diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 000000000..94c55eb5b --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "swashbuckle.aspnetcore.cli": { + "version": "6.5.0", + "commands": ["swagger"] + }, + "coverlet.console": { + "version": "3.1.2", + "commands": ["coverlet"] + }, + "dotnet-reportgenerator-globaltool": { + "version": "5.1.6", + "commands": ["reportgenerator"] + }, + "dotnet-ef": { + "version": "6.0.12", + "commands": ["dotnet-ef"] + } + } +} diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..ea060dc75 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +**/bin +**/obj +**/node_modules diff --git a/.editorconfig b/.editorconfig index 33b2aeac7..e53c670fa 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,6 +5,7 @@ root = true # Don't use tabs for indentation. [*] +end_of_line = lf indent_style = space # (Please don't specify an indent_size here; that has too many unintended consequences.) @@ -72,6 +73,15 @@ dotnet_naming_style.end_in_async.required_suffix = Async dotnet_naming_style.end_in_async.capitalization = pascal_case dotnet_naming_style.end_in_async.word_separator = +# Obsolete warnings, this should be removed or changed to warning once we address some of the obsolete items. +dotnet_diagnostic.CS0618.severity = suggestion + +# Obsolete warnings, this should be removed or changed to warning once we address some of the obsolete items. +dotnet_diagnostic.CS0612.severity = suggestion + +# Remove unnecessary using directives https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005 +dotnet_diagnostic.IDE0005.severity = warning + # CSharp code style settings: [*.cs] # Prefer "var" everywhere @@ -104,6 +114,13 @@ csharp_new_line_before_finally = true csharp_new_line_before_members_in_object_initializers = true csharp_new_line_before_members_in_anonymous_types = true +# Namespace settings +csharp_style_namespace_declarations = file_scoped:warning + +# Switch expression +dotnet_diagnostic.CS8509.severity = error # missing switch case for named enum value +dotnet_diagnostic.CS8524.severity = none # missing switch case for unnamed enum value + # All files [*] guidelines = 120 diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000..02b9803ea --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,11 @@ +# Apply .NET format https://github.com/bitwarden/server/pull/1764 +23b0a1f9df25058ab29785ecad9a233113c10889 + +# Turn on file scoped namespaces (gets reverted) https://github.com/bitwarden/server/pull/2225 +34fb4cca2aa78deb84d4cbc359992a7c6bba7ea5 + +# Revert filescoped https://github.com/bitwarden/server/pull/2227 +bae03feffecbef488cb52f5f5bc133dfdbbaa316 + +# Run formatting for file scoped namespaces https://github.com/bitwarden/server/pull/2230 +7f5f010e1eea400300c47f776604ecf46c4b4f2d diff --git a/.git-hooks/pre-commit b/.git-hooks/pre-commit new file mode 100755 index 000000000..bc661efae --- /dev/null +++ b/.git-hooks/pre-commit @@ -0,0 +1,8 @@ +#!/bin/bash + +FILES=$(git diff --cached --name-only --diff-filter=ACM "*.cs") +if [ -n "$FILES" ] +then + dotnet format ./bitwarden-server.sln --no-restore --include $FILES + echo "$FILES" | xargs git add +fi diff --git a/.gitattributes b/.gitattributes index 1d012697d..ecb84500f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ *.sh eol=lf +*.cs eol=lf .dockerignore eol=lf dockerfile eol=lf \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..a4645cd12 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# Please sort lines alphabetically, this will ensure we don't accidentally add duplicates. +# +# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners + +**/SecretsManager @bitwarden/pod-sm-dev diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 7216f51c4..a19b25052 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -1,4 +1,4 @@ -name: Bug Report +name: Server Bug Report description: File a bug report labels: [bug] body: @@ -6,7 +6,7 @@ body: attributes: value: | Thanks for taking the time to fill out this bug report! - + Please do not submit feature requests. The [Community Forums](https://community.bitwarden.com) has a section for submitting, voting for, and discussing product feature requests. - type: textarea id: reproduce @@ -71,3 +71,11 @@ body: - Operating system: [e.g. Windows 10, Mac OS Catalina] - Environment: [e.g. Docker, EKS, ECS, K8S] - Hardware: [e.g. Intel 6-core, 8GB RAM] + - type: checkboxes + id: issue-tracking-info + attributes: + label: Issue Tracking Info + description: | + Issue tracking information + options: + - label: I understand that work is tracked outside of Github. A PR will be linked to this issue should one be opened to address it, but Bitwarden doesn't use fields like "assigned", "milestone", or "project" to track progress. diff --git a/.github/ISSUE_TEMPLATE/bw-unified.yml b/.github/ISSUE_TEMPLATE/bw-unified.yml new file mode 100644 index 000000000..c1284f183 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bw-unified.yml @@ -0,0 +1,90 @@ +name: Bitwarden Unified Bug Report +name: Bitwarden Unified Deployment Bug Report +description: File a bug report +labels: [bug, bw-unified-deploy] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + + Please do not submit feature requests. The [Community Forums](https://community.bitwarden.com) has a section for submitting, voting for, and discussing product feature requests. + - type: textarea + id: reproduce + attributes: + label: Steps To Reproduce + description: How can we reproduce the behavior. + value: | + 1. Go to '...' + 2. Click on '....' + 3. Scroll down to '....' + 4. Click on '...' + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected Result + description: A clear and concise description of what you expected to happen. + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual Result + description: A clear and concise description of what is happening. + validations: + required: true + - type: textarea + id: screenshots + attributes: + label: Screenshots or Videos + description: If applicable, add screenshots and/or a short video to help explain your problem. + - type: textarea + id: additional-context + attributes: + label: Additional Context + description: Add any other context about the problem here. + - type: input + id: version + attributes: + label: Githash Version + description: Please go to https://{your-bitwarden-domain}/api/config and copy the gitHash version + validations: + required: true + - type: textarea + id: environment-details + attributes: + label: Environment Details + description: If Self-Hosted please provide some additional environment details. + placeholder: | + - Operating system: [e.g. Windows 10, Mac OS Catalina] + - Environment: [e.g. Docker, EKS, ECS, K8S] + - Hardware: [e.g. Intel 6-core, 8GB RAM] + - type: textarea + id: database-image + attributes: + label: Database Image + description: Please include the image and version of your database + placeholder: | + # MariaDB Example + mariadb:10 + # Postgres Example + postgres:14 + - type: textarea + id: epic-label + attributes: + label: Issue-Link + description: Link to our pinned issue, tracking all Bitwarden Unified + value: | + https://github.com/bitwarden/server/issues/2480 + validations: + required: true + - type: checkboxes + id: issue-tracking-info + attributes: + label: Issue Tracking Info + description: | + Issue tracking information + options: + - label: I understand that work is tracked outside of Github. A PR will be linked to this issue should one be opened to address it, but Bitwarden doesn't use fields like "assigned", "milestone", or "project" to track progress. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 590b84493..8ebc483a9 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,9 +1,14 @@ ## Type of change + + + +``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other +``` ## Objective @@ -16,13 +21,10 @@ * **file.ext:** Description of what was changed and why -## Testing requirements - - - - ## Before you submit -- [ ] If making database changes - I have also updated Entity Framework queries and/or migrations -- [ ] I have added **unit tests** where it makes sense to do so (encouraged but not required) -- [ ] This change requires a **documentation update** (notify the documentation team) -- [ ] This change has particular **deployment requirements** (notify the DevOps team) + +- Please check for formatting errors (`dotnet format --verify-no-changes`) (required) +- If making database changes - make sure you also update Entity Framework queries and/or migrations +- Please add **unit tests** where it makes sense to do so (encouraged but not required) +- If this change requires a **documentation update** - notify the documentation team +- If this change has particular **deployment requirements** - notify the DevOps team diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 000000000..61ebaed0d --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base", + "schedule:monthly", + ":maintainLockFilesMonthly", + ":preserveSemverRanges", + ":rebaseStalePrs", + ":disableMajorUpdates" + ], + "enabledManagers": [ + "nuget" + ], + "packageRules": [ + { + "matchManagers": ["nuget"], + "groupName": "Nuget updates", + "groupSlug": "nuget", + "matchUpdateTypes": [ + "minor", + "patch" + ] + } + ] +} diff --git a/.github/workflows/automatic-issue-responses.yml b/.github/workflows/automatic-issue-responses.yml new file mode 100644 index 000000000..970532ab1 --- /dev/null +++ b/.github/workflows/automatic-issue-responses.yml @@ -0,0 +1,64 @@ +--- +name: Automatic responses +on: + issues: + types: + - labeled +jobs: + close-issue: + name: 'Close issue with automatic response' + runs-on: ubuntu-20.04 + permissions: + issues: write + steps: + # Feature request + - if: github.event.label.name == 'feature-request' + name: Feature request + uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0 + with: + comment: | + We use GitHub issues as a place to track bugs and other development related issues. The [Bitwarden Community Forums](https://community.bitwarden.com/) has a [Feature Requests](https://community.bitwarden.com/c/feature-requests) section for submitting, voting for, and discussing requests like this one. + + Please [sign up on our forums](https://community.bitwarden.com/signup) and search to see if this request already exists. If so, you can vote for it and contribute to any discussions about it. If not, you can re-create the request there so that it can be properly tracked. + + This issue will now be closed. Thanks! + # Intended behavior + - if: github.event.label.name == 'intended-behavior' + name: Intended behaviour + uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0 + with: + comment: | + Your issue appears to be describing the intended behavior of the software. If you want this to be changed, it would be a feature request. + + We use GitHub issues as a place to track bugs and other development related issues. The [Bitwarden Community Forums](https://community.bitwarden.com/) has a [Feature Requests](https://community.bitwarden.com/c/feature-requests) section for submitting, voting for, and discussing requests like this one. + + Please [sign up on our forums](https://community.bitwarden.com/signup) and search to see if this request already exists. If so, you can vote for it and contribute to any discussions about it. If not, you can re-create the request there so that it can be properly tracked. + + This issue will now be closed. Thanks! + # Customer support request + - if: github.event.label.name == 'customer-support' + name: Customer Support request + uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0 + with: + comment: | + We use GitHub issues as a place to track bugs and other development related issues. Your issue appears to be a support request, or would otherwise be better handled by our dedicated Customer Success team. + + Please contact us using our [Contact page](https://bitwarden.com/contact). You can include a link to this issue in the message content. + + Alternatively, you can also search for an answer in our [help documentation](https://bitwarden.com/help/) or get help from other Bitwarden users on our [community forums](https://community.bitwarden.com/c/support/). The issue here will be closed. + # Resolved + - if: github.event.label.name == 'resolved' + name: Resolved + uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0 + with: + comment: | + We’ve closed this issue, as it appears the original problem has been resolved. If this happens again or continues to be an problem, please respond to this issue with any additional detail to assist with reproduction and root cause analysis. + # Stale + - if: github.event.label.name == 'stale' + name: Stale + uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0 + with: + comment: | + As we haven’t heard from you about this problem in some time, this issue will now be closed. + + If this happens again or continues to be an problem, please respond to this issue with any additional detail to assist with reproduction and root cause analysis. diff --git a/.github/workflows/build-self-host.yml b/.github/workflows/build-self-host.yml new file mode 100644 index 000000000..e4ccb2eb2 --- /dev/null +++ b/.github/workflows/build-self-host.yml @@ -0,0 +1,166 @@ +--- +name: Build Self-Host + +on: + push: + branches-ignore: + - "l10n_master" + - "gh-pages" + paths-ignore: + - ".github/workflows/**" + workflow_dispatch: + +jobs: + build-docker: + name: Build Docker image + runs-on: ubuntu-22.04 + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Check Branch to Publish + env: + PUBLISH_BRANCHES: "master,rc,hotfix-rc" + id: publish-branch-check + run: | + IFS="," read -a publish_branches <<< $PUBLISH_BRANCHES + + if [[ " ${publish_branches[*]} " =~ " ${GITHUB_REF:11} " ]]; then + echo "is_publish_branch=true" >> $GITHUB_ENV + else + echo "is_publish_branch=false" >> $GITHUB_ENV + fi + + ########## Set up Docker ########## + - name: Set up QEMU emulators + uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@8c0edbc76e98fa90f69d9a2c020dcb50019dc325 + + ########## Login to Docker registries ########## + - name: Login to Azure - QA Subscription + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + with: + creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }} + + - name: Login to Azure ACR + run: az acr login -n bitwardenqa + + - name: Login to Azure - Prod Subscription + if: ${{ env.is_publish_branch == 'true' }} + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + if: ${{ env.is_publish_branch == 'true' }} + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@c3b3285993151c5af47cefcb3b9134c28ab479af + with: + keyvault: "bitwarden-prod-kv" + secrets: "docker-password, + docker-username, + dct-delegate-2-repo-passphrase, + dct-delegate-2-key" + + - name: Log into Docker + if: ${{ env.is_publish_branch == 'true' }} + env: + DOCKER_USERNAME: ${{ steps.retrieve-secrets.outputs.docker-username }} + DOCKER_PASSWORD: ${{ steps.retrieve-secrets.outputs.docker-password }} + run: echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin + + - name: Setup Docker Trust + if: ${{ env.is_publish_branch == 'true' }} + env: + DCT_DELEGATION_KEY_ID: "c9bde8ec820701516491e5e03d3a6354e7bd66d05fa3df2b0062f68b116dc59c" + DCT_DELEGATE_KEY: ${{ steps.retrieve-secrets.outputs.dct-delegate-2-key }} + DCT_REPO_PASSPHRASE: ${{ steps.retrieve-secrets.outputs.dct-delegate-2-repo-passphrase }} + run: | + mkdir -p ~/.docker/trust/private + echo "$DCT_DELEGATE_KEY" > ~/.docker/trust/private/$DCT_DELEGATION_KEY_ID.key + echo "DOCKER_CONTENT_TRUST=1" >> $GITHUB_ENV + echo "DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE=$DCT_REPO_PASSPHRASE" >> $GITHUB_ENV + + ########## Generate image tag and build Docker image ########## + - name: Generate Docker image tag + id: tag + run: | + IMAGE_TAG=$(echo "${GITHUB_REF:11}" | sed "s#/#-#g") # slash safe branch name + if [[ "$IMAGE_TAG" == "master" ]]; then + IMAGE_TAG=dev + elif [[ "$IMAGE_TAG" == "rc" ]] || [[ "$IMAGE_TAG" == "hotfix-rc" ]]; then + IMAGE_TAG=beta + fi + + echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT + + - name: Generate tag list + id: tag-list + env: + IMAGE_TAG: ${{ steps.tag.outputs.image_tag }} + run: | + if [ "$IMAGE_TAG" = "dev" ] || [ "$IMAGE_TAG" = "beta" ]; then + echo "tags=bitwardenqa.azurecr.io/self-host:${IMAGE_TAG},bitwarden/self-host:${IMAGE_TAG}" >> $GITHUB_OUTPUT + else + echo "tags=bitwardenqa.azurecr.io/self-host:${IMAGE_TAG}" >> $GITHUB_OUTPUT + fi + + - name: Build Docker image + uses: docker/build-push-action@c56af957549030174b10d6867f20e78cfd7debc5 + with: + context: . + file: docker-unified/Dockerfile + platforms: | + linux/amd64, + linux/arm/v7, + linux/arm64/v8 + push: true + tags: ${{ steps.tag-list.outputs.tags }} + + - name: Log out of Docker and disable Docker Notary + if: ${{ env.is_publish_branch == 'true' }} + run: | + docker logout + echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV + + check-failures: + name: Check for failures + if: always() + runs-on: ubuntu-22.04 + needs: build-docker + steps: + - name: Check if any job failed + if: | + github.ref == 'refs/heads/master' + || github.ref == 'refs/heads/rc' + || github.ref == 'refs/heads/hotfix-rc' + env: + BUILD_DOCKER_STATUS: ${{ needs.build-docker.result }} + run: | + if [ "$BUILD_DOCKER_STATUS" = "failure" ]; then + exit 1 + fi + + - name: Login to Azure - Prod Subscription + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + if: failure() + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@c3b3285993151c5af47cefcb3b9134c28ab479af + if: failure() + with: + keyvault: "bitwarden-prod-kv" + secrets: "devops-alerts-slack-webhook-url" + + - name: Notify Slack on failure + uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33 + if: failure() + env: + SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }} + with: + status: ${{ job.status }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6b16b9aa2..aa43052df 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,18 +4,19 @@ name: Build on: push: branches-ignore: - - 'l10n_master' - - 'gh-pages' + - "l10n_master" + - "gh-pages" + paths-ignore: + - ".github/workflows/**" workflow_dispatch: - inputs: {} jobs: cloc: name: CLOC - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b - name: Install cloc run: | @@ -25,43 +26,46 @@ jobs: - name: Print lines of code run: cloc --include-lang C#,SQL,Razor,"Bourne Shell",PowerShell,HTML,CSS,Sass,JavaScript,TypeScript --vcs git + lint: + name: Lint + runs-on: ubuntu-22.04 + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Verify Format + run: dotnet format --verify-no-changes testing: name: Testing - runs-on: windows-2019 + runs-on: windows-2022 + env: + NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages steps: - - name: Set up NuGet - uses: nuget/setup-nuget@04b0c2b8d1b97922f67eca497d7cf0bf17b8ffe1 + - name: Set up dotnet + uses: actions/setup-dotnet@9211491ffb35dd6a6657ca4f45d43dfe6e97c829 with: - nuget-version: '5' - + dotnet-version: "6.0.x" - name: Set up MSBuild - uses: microsoft/setup-msbuild@c26a08ba26249b81327e26f6ef381897b6a8754d - - - name: Set up Node - uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea - with: - node-version: '14' - - - name: Update NPM - run: | - npm install -g npm@7 + uses: microsoft/setup-msbuild@ab534842b4bdf384b8aaf93765dc6f721d9f5fab - name: Print environment run: | - nuget help | grep Version - msbuild -version dotnet --info - node --version - npm --version + msbuild -version + nuget help | grep Version echo "GitHub ref: $GITHUB_REF" echo "GitHub event: $GITHUB_EVENT" - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 - name: Restore - run: msbuild /t:restore + run: dotnet restore --locked-mode + shell: pwsh + + - name: Build OSS solution + run: msbuild bitwarden-server.sln /p:Configuration=Debug /p:DefineConstants="OSS" /verbosity:minimal shell: pwsh - name: Build solution @@ -69,58 +73,69 @@ jobs: shell: pwsh - name: Test OSS solution - run: dotnet test ./test --configuration Debug --no-build + run: dotnet test ./test --configuration Debug --no-build --logger "trx;LogFileName=oss-test-results.trx" || true shell: pwsh - name: Test Bitwarden solution - run: dotnet test ./bitwarden_license/test/CmmCore.Test --configuration Debug --no-build + run: dotnet test ./bitwarden_license/test --configuration Debug --no-build --logger "trx;LogFileName=bw-test-results.trx" || true shell: pwsh + - name: Report test results + uses: dorny/test-reporter@c9b3d0e2bd2a4e96aaf424dbaa31c46b42318226 + if: always() + with: + name: Test Results + path: "**/*-test-results.trx" + reporter: dotnet-trx + fail-on-error: true build-artifacts: name: Build artifacts - runs-on: ubuntu-20.04 - needs: testing + runs-on: ubuntu-22.04 + needs: + - testing + - lint strategy: fail-fast: false matrix: include: - - service_name: Admin + - project_name: Admin base_path: ./src - gulp: true - - service_name: Api + node: true + - project_name: Api base_path: ./src - - service_name: Billing + - project_name: Billing base_path: ./src - - service_name: Events + - project_name: Events base_path: ./src - - service_name: EventsProcessor + - project_name: EventsProcessor base_path: ./src - - service_name: Icons + - project_name: Icons base_path: ./src - - service_name: Identity + - project_name: Identity base_path: ./src - - service_name: Notifications + - project_name: Notifications base_path: ./src - - service_name: Server + - project_name: Server base_path: ./util - - service_name: Setup + - project_name: Setup base_path: ./util - - service_name: Sso + - project_name: Sso base_path: ./bitwarden_license/src - gulp: true + node: true + - project_name: Scim + base_path: ./bitwarden_license/src + dotnet: true steps: - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 - name: Set up Node - uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea + uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a with: - node-version: '14' - - - name: Update NPM - run: | - npm install -g npm@7 + cache: "npm" + cache-dependency-path: "**/package-lock.json" + node-version: "16" - name: Print environment run: | @@ -128,288 +143,273 @@ jobs: dotnet --info node --version npm --version - gulp --version echo "GitHub ref: $GITHUB_REF" echo "GitHub event: $GITHUB_EVENT" - - name: Set up Gulp - if: ${{ matrix.gulp }} - working-directory: ${{ matrix.base_path }}/${{ matrix.service_name }} - run: | - npm install -g gulp - - - name: Restore/Clean service - working-directory: ${{ matrix.base_path }}/${{ matrix.service_name }} + - name: Restore/Clean project + working-directory: ${{ matrix.base_path }}/${{ matrix.project_name }} run: | echo "Restore" dotnet restore echo "Clean" dotnet clean -c "Release" -o obj/build-output/publish - - name: Execute Gulp - if: ${{ matrix.gulp }} - working-directory: ${{ matrix.base_path }}/${{ matrix.service_name }} + - name: Build node + if: ${{ matrix.node }} + working-directory: ${{ matrix.base_path }}/${{ matrix.project_name }} run: | - npm install - gulp --gulpfile gulpfile.js build + npm ci + npm run build - - name: Publish service - working-directory: ${{ matrix.base_path }}/${{ matrix.service_name }} + - name: Publish project + working-directory: ${{ matrix.base_path }}/${{ matrix.project_name }} run: | echo "Publish" dotnet publish -c "Release" -o obj/build-output/publish cd obj/build-output/publish - zip -r ${{ matrix.service_name }}.zip . - mv ${{ matrix.service_name }}.zip ../../../ + zip -r ${{ matrix.project_name }}.zip . + mv ${{ matrix.project_name }}.zip ../../../ pwd ls -atlh ../../../ - - name: Upload service artifact - uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 + - name: Upload project artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 with: - name: ${{ matrix.service_name }}.zip - path: ${{ matrix.base_path }}/${{ matrix.service_name }}/${{ matrix.service_name }}.zip + name: ${{ matrix.project_name }}.zip + path: ${{ matrix.base_path }}/${{ matrix.project_name }}/${{ matrix.project_name }}.zip if-no-files-found: error - build-docker: name: Build Docker images - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: build-artifacts strategy: fail-fast: false matrix: include: - - service_name: Admin + - project_name: Admin base_path: ./src - docker_repo: bitwarden + docker_repos: [bitwarden, bitwardenqa.azurecr.io] dotnet: true - - service_name: Api + - project_name: Api base_path: ./src - docker_repo: bitwarden + docker_repos: [bitwarden, bitwardenqa.azurecr.io] dotnet: true - - service_name: Attachments + - project_name: Attachments base_path: ./util - docker_repo: bitwarden - - service_name: Events + docker_repos: [bitwarden, bitwardenqa.azurecr.io] + - project_name: Events base_path: ./src - docker_repo: bitwarden + docker_repos: [bitwarden, bitwardenqa.azurecr.io] dotnet: true - - service_name: EventsProcessor + - project_name: EventsProcessor base_path: ./src - docker_repo: bitwardenqa.azurecr.io + docker_repos: [bitwardenqa.azurecr.io] dotnet: true - - service_name: Icons + - project_name: Icons base_path: ./src - docker_repo: bitwarden + docker_repos: [bitwarden, bitwardenqa.azurecr.io] dotnet: true - - service_name: Identity + - project_name: Identity base_path: ./src - docker_repo: bitwarden + docker_repos: [bitwarden, bitwardenqa.azurecr.io] dotnet: true - - service_name: K8S-Proxy + - project_name: MsSql base_path: ./util - docker_repo: bitwarden - - service_name: MsSql + docker_repos: [bitwarden, bitwardenqa.azurecr.io] + - project_name: Nginx base_path: ./util - docker_repo: bitwarden - - service_name: Nginx - base_path: ./util - docker_repo: bitwarden - - service_name: Notifications + docker_repos: [bitwarden, bitwardenqa.azurecr.io] + - project_name: Notifications base_path: ./src - docker_repo: bitwarden + docker_repos: [bitwarden, bitwardenqa.azurecr.io] dotnet: true - - service_name: Server + - project_name: Server base_path: ./util - docker_repo: bitwarden + docker_repos: [bitwarden, bitwardenqa.azurecr.io] dotnet: true - - service_name: Setup + - project_name: Setup base_path: ./util - docker_repo: bitwarden + docker_repos: [bitwarden, bitwardenqa.azurecr.io] dotnet: true - - service_name: Sso + - project_name: Sso base_path: ./bitwarden_license/src - docker_repo: bitwarden + docker_repos: [bitwarden, bitwardenqa.azurecr.io] + dotnet: true + - project_name: Scim + base_path: ./bitwarden_license/src + docker_repos: [bitwarden, bitwardenqa.azurecr.io] + dotnet: true + - project_name: Billing + base_path: ./src + docker_repos: [bitwardenqa.azurecr.io] dotnet: true steps: - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 - - name: Login to Azure - Prod Subscription - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a - with: - creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} - - - name: Retrieve secrets - id: retrieve-secrets - uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403 - with: - keyvault: "bitwarden-prod-kv" - secrets: "aws-ecr-access-key-id, - aws-ecr-secret-access-key, - docker-password, - docker-username, - dct-delegate-2-repo-passphrase, - dct-delegate-2-key" - - - name: Login to Azure - QA Subscription - if: ${{ matrix.service_name }} == "EventsProcessor" - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a - with: - creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }} - - - name: Log into Docker - if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix' - env: - DOCKER_USERNAME: ${{ steps.retrieve-secrets.outputs.docker-username }} - DOCKER_PASSWORD: ${{ steps.retrieve-secrets.outputs.docker-password }} - run: | - if [[ "${{ matrix.docker_repo }}" == "bitwardenqa.azurecr.io" ]]; then - az acr login -n bitwardenqa - else - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin - fi - - - name: Setup Docker Trust - if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix' - env: - DCT_DELEGATION_KEY_ID: "c9bde8ec820701516491e5e03d3a6354e7bd66d05fa3df2b0062f68b116dc59c" - DCT_DELEGATE_KEY: ${{ steps.retrieve-secrets.outputs.dct-delegate-2-key }} - run: | - mkdir -p ~/.docker/trust/private - echo "$DCT_DELEGATE_KEY" > ~/.docker/trust/private/$DCT_DELEGATION_KEY_ID.key - - - name: Setup service name + ########## Build Docker Image ########## + - name: Setup project name id: setup run: | - SERVICE_NAME=$(echo "${{ matrix.service_name }}" | awk '{print tolower($0)}') - echo "Matrix name: ${{ matrix.service_name }}" - echo "SERVICE_NAME: $SERVICE_NAME" - echo "::set-output name=service_name::$SERVICE_NAME" + PROJECT_NAME=$(echo "${{ matrix.project_name }}" | awk '{print tolower($0)}') + echo "Matrix name: ${{ matrix.project_name }}" + echo "PROJECT_NAME: $PROJECT_NAME" + echo "project_name=$PROJECT_NAME" >> $GITHUB_OUTPUT - name: Get build artifact if: ${{ matrix.dotnet }} - uses: actions/download-artifact@3be87be14a055c47b01d3bd88f8fe02320a9bb60 # v2.0.10 + uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 with: - name: ${{ matrix.service_name }}.zip + name: ${{ matrix.project_name }}.zip - name: Setup build artifact if: ${{ matrix.dotnet }} run: | - mkdir -p ${{ matrix.base_path}}/${{ matrix.service_name }}/obj/build-output/publish - unzip ${{ matrix.service_name }}.zip \ - -d ${{ matrix.base_path }}/${{ matrix.service_name }}/obj/build-output/publish + mkdir -p ${{ matrix.base_path}}/${{ matrix.project_name }}/obj/build-output/publish + unzip ${{ matrix.project_name }}.zip \ + -d ${{ matrix.base_path }}/${{ matrix.project_name }}/obj/build-output/publish - - name: Build Docker images + - name: Build Docker image + env: + PROJECT_NAME: ${{ steps.setup.outputs.project_name }} + run: docker build -t $PROJECT_NAME ${{ matrix.base_path }}/${{ matrix.project_name }} + + ########## ACR ########## + - name: Login to Azure - QA Subscription + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + with: + creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }} + + - name: Login to Azure ACR + run: az acr login -n bitwardenqa + + - name: Tag and Push image to Azure ACR QA registry + env: + PROJECT_NAME: ${{ steps.setup.outputs.project_name }} + REGISTRY: bitwardenqa.azurecr.io run: | - if [ "${{ matrix.service_name }}" = "K8S-Proxy" ]; then - docker build -f ${{ matrix.base_path }}/Nginx/Dockerfile-k8s \ - -t ${{ steps.setup.outputs.service_name }} ${{ matrix.base_path }}/Nginx - else - docker build -t ${{ steps.setup.outputs.service_name }} \ - ${{ matrix.base_path }}/${{ matrix.service_name }} + IMAGE_TAG=$(echo "${GITHUB_REF:11}" | sed "s#/#-#g") # slash safe branch name + if [[ "$IMAGE_TAG" == "master" ]]; then + IMAGE_TAG=dev fi - - name: Docker Trust setup + docker tag $PROJECT_NAME \ + $REGISTRY/$PROJECT_NAME:$IMAGE_TAG + docker push $REGISTRY/$PROJECT_NAME:$IMAGE_TAG + + - name: Log out of Docker + run: docker logout + + ########## DockerHub ########## + - name: Login to Azure - Prod Subscription if: | - matrix.docker_repo == 'bitwarden' - && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix') + contains(matrix.docker_repos, 'bitwarden') + && (github.ref == 'refs/heads/master' || + github.ref == 'refs/heads/rc' || + github.ref == 'refs/heads/hotfix-rc') + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + if: | + contains(matrix.docker_repos, 'bitwarden') + && (github.ref == 'refs/heads/master' || + github.ref == 'refs/heads/rc' || + github.ref == 'refs/heads/hotfix-rc') + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@c3b3285993151c5af47cefcb3b9134c28ab479af + with: + keyvault: "bitwarden-prod-kv" + secrets: "docker-password, + docker-username, + dct-delegate-2-repo-passphrase, + dct-delegate-2-key" + + - name: Log into Docker + if: | + contains(matrix.docker_repos, 'bitwarden') + && (github.ref == 'refs/heads/master' || + github.ref == 'refs/heads/rc' || + github.ref == 'refs/heads/hotfix-rc') env: + DOCKER_USERNAME: ${{ steps.retrieve-secrets.outputs.docker-username }} + DOCKER_PASSWORD: ${{ steps.retrieve-secrets.outputs.docker-password }} + run: echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin + + - name: Setup Docker Trust + if: | + contains(matrix.docker_repos, 'bitwarden') + && (github.ref == 'refs/heads/master' || + github.ref == 'refs/heads/rc' || + github.ref == 'refs/heads/hotfix-rc') + env: + DCT_DELEGATION_KEY_ID: "c9bde8ec820701516491e5e03d3a6354e7bd66d05fa3df2b0062f68b116dc59c" + DCT_DELEGATE_KEY: ${{ steps.retrieve-secrets.outputs.dct-delegate-2-key }} DCT_REPO_PASSPHRASE: ${{ steps.retrieve-secrets.outputs.dct-delegate-2-repo-passphrase }} run: | + mkdir -p ~/.docker/trust/private + echo "$DCT_DELEGATE_KEY" > ~/.docker/trust/private/$DCT_DELEGATION_KEY_ID.key echo "DOCKER_CONTENT_TRUST=1" >> $GITHUB_ENV - echo "DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE=$DCT_REPO_PASSPHRASE" >> $GITHUB_ENV + echo "DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE=$DCT_REPO_PASSPHRASE" >> $GITHUB_ENV - name: Tag and Push RC to Docker Hub - if: github.ref == 'refs/heads/rc' + if: | + contains(matrix.docker_repos, 'bitwarden') + && (github.ref == 'refs/heads/master' || + github.ref == 'refs/heads/rc' || + github.ref == 'refs/heads/hotfix-rc') + env: + PROJECT_NAME: ${{ steps.setup.outputs.project_name }} + REGISTRY: bitwarden run: | - docker tag ${{ steps.setup.outputs.service_name }} \ - ${{ matrix.docker_repo }}/${{ steps.setup.outputs.service_name }}:rc - docker push ${{ matrix.docker_repo }}/${{ steps.setup.outputs.service_name }}:rc + IMAGE_TAG=$(echo "${GITHUB_REF:11}" | sed "s#/#-#g") # slash safe branch name + if [[ "$IMAGE_TAG" == "master" ]]; then + IMAGE_TAG=dev + fi - - name: Tag and Push Hotfix to Docker Hub - if: github.ref == 'refs/heads/hotfix' - run: | - docker tag ${{ steps.setup.outputs.service_name }} \ - ${{ matrix.docker_repo }}/${{ steps.setup.outputs.service_name }}:hotfix - docker push ${{ matrix.docker_repo }}/${{ steps.setup.outputs.service_name }}:hotfix - - - name: Tag and Push Dev to Docker Hub - if: github.ref == 'refs/heads/master' - run: | - docker tag ${{ steps.setup.outputs.service_name }} \ - ${{ matrix.docker_repo }}/${{ steps.setup.outputs.service_name }}:dev - docker push ${{ matrix.docker_repo }}/${{ steps.setup.outputs.service_name }}:dev + docker tag $PROJECT_NAME \ + $REGISTRY/$PROJECT_NAME:$IMAGE_TAG + docker push $REGISTRY/$PROJECT_NAME:$IMAGE_TAG - name: Log out of Docker and disable Docker Notary - if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix' + if: | + contains(matrix.docker_repos, 'bitwarden') + && (github.ref == 'refs/heads/master' || + github.ref == 'refs/heads/rc' || + github.ref == 'refs/heads/hotfix-rc') run: | docker logout echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@0d9a5be0dceea74e09396820e1e522ba4a110d2f # v1 - with: - aws-access-key-id: ${{ steps.retrieve-secrets.outputs.aws-ecr-access-key-id }} - aws-secret-access-key: ${{ steps.retrieve-secrets.outputs.aws-ecr-secret-access-key }} - aws-region: us-east-1 - - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@aaf69d68aa3fb14c1d5a6be9ac61fe15b48453a2 # v1 - - - name: Tag and Push RC to AWS ECR nonprod registry - if: github.ref == 'refs/heads/rc' - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - IMAGE_TAG: ${{ github.sha }} - run: | - docker tag ${{ steps.setup.outputs.service_name }} \ - $ECR_REGISTRY/nonprod/${{ steps.setup.outputs.service_name }}:rc-${IMAGE_TAG:(-8)} - docker push $ECR_REGISTRY/nonprod/${{ steps.setup.outputs.service_name }}:rc-${IMAGE_TAG:(-8)} - - - name: Tag and Push Hotfix to AWS ECR nonprod registry - if: github.ref == 'refs/heads/hotfix' - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - IMAGE_TAG: ${{ github.sha }} - run: | - docker tag ${{ steps.setup.outputs.service_name }} \ - $ECR_REGISTRY/nonprod/${{ steps.setup.outputs.service_name }}:hotfix-${IMAGE_TAG:(-8)} - docker push $ECR_REGISTRY/nonprod/${{ steps.setup.outputs.service_name }}:hotfix-${IMAGE_TAG:(-8)} - - - name: Tag and Push Dev to AWS ECR nonprod registry - if: github.ref == 'refs/heads/master' - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - IMAGE_TAG: ${{ github.sha }} - run: | - docker tag ${{ steps.setup.outputs.service_name }} \ - $ECR_REGISTRY/nonprod/${{ steps.setup.outputs.service_name }}:dev-${IMAGE_TAG:(-8)} - docker push $ECR_REGISTRY/nonprod/${{ steps.setup.outputs.service_name }}:dev-${IMAGE_TAG:(-8)} - - upload: name: Upload - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: build-docker steps: + - name: Set up dotnet + uses: actions/setup-dotnet@9211491ffb35dd6a6657ca4f45d43dfe6e97c829 + with: + dotnet-version: "6.0.x" + - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 - name: Restore run: dotnet tool restore - name: Make Docker stub - if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix' + if: github.ref == 'refs/heads/master' || + github.ref == 'refs/heads/rc' || + github.ref == 'refs/heads/hotfix-rc' run: | if [[ "${{ github.ref }}" == "rc" ]]; then SETUP_IMAGE="bitwarden/setup:rc" - elif [[ "${{ github.ref }}" == "hotfix" ]]; then - SETUP_IMAGE="bitwarden/setup:hotfix" + elif [[ "${{ github.ref }}" == "hotfix-rc" ]]; then + SETUP_IMAGE="bitwarden/setup:hotfix-rc" else SETUP_IMAGE="bitwarden/setup:dev" fi @@ -423,12 +423,24 @@ jobs: touch $STUB_OUTPUT/env/uid.env cd docker-stub; zip -r ../docker-stub.zip *; cd .. + - name: Make Docker stub checksum + if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc' + run: sha256sum docker-stub.zip > docker-stub-sha256.txt + - name: Upload Docker stub artifact - if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix' - uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 + if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc' + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 with: name: docker-stub.zip - path: ./docker-stub.zip + path: docker-stub.zip + if-no-files-found: error + + - name: Upload Docker stub checksum artifact + if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc' + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: docker-stub-sha256.txt + path: docker-stub-sha256.txt if-no-files-found: error - name: Build Swagger @@ -446,21 +458,24 @@ jobs: cd ../.. env: ASPNETCORE_ENVIRONMENT: Production - swaggerGen: 'True' + swaggerGen: "True" + DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX: 2 + GLOBALSETTINGS__SQLSERVER__CONNECTIONSTRING: "placeholder" - name: Upload Swagger artifact - uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 with: name: swagger.json - path: ./swagger.json + path: swagger.json if-no-files-found: error check-failures: name: Check for failures if: always() - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: - cloc + - lint - testing - build-artifacts - build-docker @@ -470,9 +485,10 @@ jobs: if: | github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc' - || github.ref == 'refs/heads/hotfix' + || github.ref == 'refs/heads/hotfix-rc' env: CLOC_STATUS: ${{ needs.cloc.result }} + LINT_STATUS: ${{ needs.lint.result }} TESTING_STATUS: ${{ needs.testing.result }} BUILD_ARTIFACTS_STATUS: ${{ needs.build-artifacts.result }} BUILD_DOCKER_STATUS: ${{ needs.build-docker.result }} @@ -480,6 +496,8 @@ jobs: run: | if [ "$CLOC_STATUS" = "failure" ]; then exit 1 + elif [ "$LINT_STATUS" = "failure" ]; then + exit 1 elif [ "$TESTING_STATUS" = "failure" ]; then exit 1 elif [ "$BUILD_ARTIFACTS_STATUS" = "failure" ]; then @@ -491,21 +509,21 @@ jobs: fi - name: Login to Azure - Prod Subscription - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf if: failure() with: creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} - name: Retrieve secrets id: retrieve-secrets - uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403 + uses: bitwarden/gh-actions/get-keyvault-secrets@c3b3285993151c5af47cefcb3b9134c28ab479af if: failure() with: keyvault: "bitwarden-prod-kv" secrets: "devops-alerts-slack-webhook-url" - name: Notify Slack on failure - uses: act10ns/slack@e4e71685b9b239384b0f676a63c32367f59c2522 # v1.2.2 + uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33 if: failure() env: SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }} diff --git a/.github/workflows/cleanup-after-pr.yml b/.github/workflows/cleanup-after-pr.yml new file mode 100644 index 000000000..696d84c8f --- /dev/null +++ b/.github/workflows/cleanup-after-pr.yml @@ -0,0 +1,66 @@ +--- +name: Clean After PR + +on: + pull_request: + types: [closed] + +jobs: + build-docker: + name: Remove feature branch docker images + runs-on: ubuntu-20.04 + steps: + - name: Checkout repo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + + ########## ACR ########## + - name: Login to Azure - QA Subscription + uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + with: + creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }} + + - name: Login to Azure ACR + run: az acr login -n bitwardenqa + + ########## Remove Docker images ########## + - name: Remove the docker image from ACR + env: + REGISTRY_NAME: bitwardenqa + SERVICES: | + services: + - Admin + - Api + - Attachments + - Events + - EventsProcessor + - Icons + - Identity + - K8S-Proxy + - MsSql + - Nginx + - Notifications + - Server + - Setup + - Sso + run: | + for SERVICE in $(echo "${{ env.SERVICES }}" | yq e ".services[]" - ) + do + SERVICE_NAME=$(echo $SERVICE | awk '{print tolower($0)}') + IMAGE_TAG=$(echo "${GITHUB_REF:11}" | sed "s#/#-#g") # slash safe branch name + + echo "[*] Checking if remote exists: $REGISTRY_NAME.azurecr.io/$SERVICE_NAME:$IMAGE_TAG" + TAG_EXISTS=$( + az acr repository show-tags --name $REGISTRY_NAME --repository $SERVICE_NAME \ + | jq --arg $TAG "$IMAGE_TAG" -e '. | any(. == "$TAG")' + ) + + if [[ "$TAG_EXISTS" == "true" ]]; then + echo "[*] Tag exists. Removing tag" + az acr repository delete --name $REGISTRY_NAME --image $SERVICE_NAME:$IMAGE_TAG --yes + else + echo "[*] Tag does not exist. No action needed" + fi + done + + - name: Log out of Docker + run: docker logout diff --git a/.github/workflows/container-registry-purge.yml b/.github/workflows/container-registry-purge.yml new file mode 100644 index 000000000..8c9db2cbb --- /dev/null +++ b/.github/workflows/container-registry-purge.yml @@ -0,0 +1,121 @@ +--- +name: Container Registry Purge + +on: + schedule: + - cron: '0 0 * * SUN' + workflow_dispatch: + inputs: {} + +jobs: + purge: + name: Purge old images + runs-on: ubuntu-20.04 + strategy: + fail-fast: false + matrix: + include: + - name: bitwardenqa + - name: bitwardenprod + steps: + - name: Login to Azure + if: matrix.name == 'bitwardenprod' + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Login to Azure + if: matrix.name == 'bitwardenqa' + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + with: + creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }} + + - name: Purge images + env: + REGISTRY: ${{ matrix.name }} + AGO_DUR_VER: "180d" + AGO_DUR: "30d" + run: | + REPO_LIST=$(az acr repository list -n $REGISTRY -o tsv) + for REPO in $REPO_LIST + do + + PURGE_LATEST="" + PURGE_VERSION="" + PURGE_ELSE="" + + TAG_LIST=$(az acr repository show-tags -n $REGISTRY --repository $REPO -o tsv) + for TAG in $TAG_LIST + do + if [ $TAG = "latest" ] || [ $TAG = "dev" ]; then + PURGE_LATEST+="--filter '$REPO:$TAG' " + elif [[ $TAG =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; then + PURGE_VERSION+="--filter '$REPO:$TAG' " + else + PURGE_ELSE+="--filter '$REPO:$TAG' " + fi + done + + if [ ! -z "$PURGE_LATEST" ] + then + PURGE_LATEST_CMD="acr purge $PURGE_LATEST --ago $AGO_DUR_VER --untagged --keep 1" + az acr run --cmd "$PURGE_LATEST_CMD" --registry $REGISTRY /dev/null & + fi + + if [ ! -z "$PURGE_VERSION" ] + then + PURGE_VERSION_CMD="acr purge $PURGE_VERSION --ago $AGO_DUR_VER --untagged" + az acr run --cmd "$PURGE_VERSION_CMD" --registry $REGISTRY /dev/null & + fi + + if [ ! -z "$PURGE_ELSE" ] + then + PURGE_ELSE_CMD="acr purge $PURGE_ELSE --ago $AGO_DUR --untagged" + az acr run --cmd "$PURGE_ELSE_CMD" --registry $REGISTRY /dev/null & + fi + + wait + + done + + + check-failures: + name: Check for failures + if: always() + runs-on: ubuntu-20.04 + needs: + - purge + steps: + - name: Check if any job failed + if: | + github.ref == 'refs/heads/master' + || github.ref == 'refs/heads/rc' + || github.ref == 'refs/heads/hotfix-rc' + env: + PURGE_STATUS: ${{ needs.purge.result }} + run: | + if [ "$PURGE_STATUS" = "failure" ]; then + exit 1 + fi + + - name: Login to Azure - Prod Subscription + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + if: failure() + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f + if: failure() + with: + keyvault: "bitwarden-prod-kv" + secrets: "devops-alerts-slack-webhook-url" + + - name: Notify Slack on failure + uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33 + if: failure() + env: + SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }} + with: + status: ${{ job.status }} diff --git a/.github/workflows/database.yml b/.github/workflows/database.yml new file mode 100644 index 000000000..0e4a0171b --- /dev/null +++ b/.github/workflows/database.yml @@ -0,0 +1,107 @@ +--- +name: Validate Database + +on: + pull_request: + branches-ignore: + - 'l10n_master' + - 'gh-pages' + paths: + - 'src/Sql/**' + - 'util/Migrator/**' + push: + branches: + - 'master' + - 'rc' + paths: + - 'src/Sql/**' + - 'util/Migrator/**' + workflow_dispatch: + inputs: {} + +jobs: + build: + name: Build DACPAC + runs-on: windows-2022 + env: + NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages + steps: + - name: Set up dotnet + uses: actions/setup-dotnet@9211491ffb35dd6a6657ca4f45d43dfe6e97c829 + with: + dotnet-version: '6.0.x' + - name: Set up MSBuild + uses: microsoft/setup-msbuild@ab534842b4bdf384b8aaf93765dc6f721d9f5fab + + - name: Print environment + run: | + dotnet --info + msbuild -version + nuget help | grep Version + echo "GitHub ref: $GITHUB_REF" + echo "GitHub event: $GITHUB_EVENT" + + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Build DACPAC + run: msbuild src/Sql/Sql.sqlproj /p:Configuration=Release /verbosity:minimal + shell: pwsh + + - name: Upload DACPAC + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: sql.dacpac + path: src/Sql/bin/Release/Sql.dacpac + + validate: + name: Validate + runs-on: ubuntu-20.04 + needs: build + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Download dacpac + uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 + with: + name: sql.dacpac + + - name: Docker Compose up + working-directory: "dev" + run: | + cp .env.example .env + docker compose --profile mssql up -d + shell: pwsh + + - name: Migrate + working-directory: "dev" + run: "pwsh ./migrate.ps1" + shell: pwsh + + - name: Diff sqlproj to migrations + run: /usr/local/sqlpackage/sqlpackage /action:DeployReport /SourceFile:"Sql.dacpac" /TargetConnectionString:"Server=localhost;Database=vault_dev;User Id=SA;Password=SET_A_PASSWORD_HERE_123;Encrypt=True;TrustServerCertificate=True;" /OutputPath:"report.xml" /p:IgnoreColumnOrder=True /p:IgnoreComments=True + shell: pwsh + + - name: Upload Report + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: report.xml + path: report.xml + + - name: Validate XML + run: | + if grep -q "" "report.xml"; then + echo + echo "Migrations are out of sync with sqlproj!" + exit 1 + else + echo "Report looks good" + fi + shell: bash + + - name: Docker compose down + if: ${{ always() }} + working-directory: "dev" + run: docker compose down + shell: pwsh diff --git a/.github/workflows/enforce-labels.yml b/.github/workflows/enforce-labels.yml new file mode 100644 index 000000000..b698bf47d --- /dev/null +++ b/.github/workflows/enforce-labels.yml @@ -0,0 +1,16 @@ +--- +name: Enforce PR labels + +on: + pull_request: + types: [labeled, unlabeled, opened, edited, synchronize] + +jobs: + enforce-label: + name: EnforceLabel + runs-on: ubuntu-20.04 + steps: + - name: Enforce Label + uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 + with: + BANNED_LABELS: "hold,DB-migrations-changed,needs-qa" diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml deleted file mode 100644 index cb7759123..000000000 --- a/.github/workflows/linter.yml +++ /dev/null @@ -1,27 +0,0 @@ ---- -name: Workflow Linter - -on: - push: - branches: add-workflow-linter -# branches-ignore: -# - 'l10n_master' -# - 'gh-pages' -# workflow_dispatch: -# inputs: {} - -jobs: - cloc: - name: CLOC - runs-on: ubuntu-20.04 - steps: - - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 - - - name: Install cloc - run: | - sudo apt-get update - sudo apt-get -y install cloc - - - name: Print lines of code - run: cloc --include-lang C#,SQL,Razor,"Bourne Shell",PowerShell,HTML,CSS,Sass,JavaScript,TypeScript --vcs git diff --git a/.github/workflows/protect-files.yml b/.github/workflows/protect-files.yml new file mode 100644 index 000000000..c9461faf7 --- /dev/null +++ b/.github/workflows/protect-files.yml @@ -0,0 +1,55 @@ +# Runs if there are changes to the paths: list. +# Starts a matrix job to check for modified files, then sets output based on the results. +# The input decides if the label job is ran, adding a label to the PR. +--- + +name: Protect Files + +on: + pull_request: + types: + - opened + - synchronize + - unlabeled + paths: + - "util/Migrator/DbScripts/**.sql" + +jobs: + changed-files: + name: Check for file changes + runs-on: ubuntu-20.04 + outputs: + changes: ${{steps.check-changes.outputs.changes_detected}} + + strategy: + fail-fast: true + matrix: + include: + - name: Database Scripts + path: util/Migrator/DbScripts + label: "DB-migrations-changed" + steps: + - name: Checkout repo + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + fetch-depth: 2 + + - name: Check for file changes + id: check-changes + run: | + MODIFIED_FILES=$(git diff --name-only --diff-filter=M HEAD~1) + + for file in $MODIFIED_FILES + do + if [[ $file == *"${{ matrix.path }}"* ]]; then + echo "changes_detected=true" >> $GITHUB_OUTPUT + break + else echo "changes_detected=false" >> $GITHUB_OUTPUT + fi + done + + - name: Add label to pull request + if: contains(steps.check-changes.outputs.changes_detected, true) + uses: andymckay/labeler@e6c4322d0397f3240f0e7e30a33b5c5df2d39e90 + with: + add-labels: ${{ matrix.label }} diff --git a/.github/workflows/qa-deploy.yml b/.github/workflows/qa-deploy.yml deleted file mode 100644 index 35ef5cbc2..000000000 --- a/.github/workflows/qa-deploy.yml +++ /dev/null @@ -1,137 +0,0 @@ ---- -name: QA Deploy - -on: - workflow_dispatch: - inputs: - migrateDb: - required: true - default: "true" - resetDb: - required: true - default: "false" - -jobs: - reset-db: - name: Reset Database - if: ${{ github.event.inputs.resetDb == 'true' }} - runs-on: ubuntu-20.04 - steps: - - name: Reset Test Data - Stub - run: | - echo "placeholder for cleaning DB" - echo "placeholder for loading test dataset" - - - update-db: - name: Update Database - if: ${{ github.event.inputs.migrateDb == 'true' }} - runs-on: ubuntu-20.04 - steps: - - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f - - - name: Login to Azure - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a - with: - creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }} - - - name: Retrieve secrets - id: retrieve-secrets - uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403 - with: - keyvault: "bitwarden-qa-kv" - secrets: "mssql-server-host, - mssql-admin-login, - mssql-admin-login-password" - - - name: Migrate database - env: - MSSQL_HOST: ${{ steps.retrieve-secrets.outputs.mssql-server-host }} - MSSQL_USER: ${{ steps.retrieve-secrets.outputs.mssql-admin-login }} - MSSQL_PASS: ${{ steps.retrieve-secrets.outputs.mssql-admin-login-password }} - working-directory: ./util/Migrator/DbScripts - run: | - echo "Running database migrations..." - for f in `ls -v ./*.sql`; do - echo "Executing file: ${f}..." - sqlcmd -S $MSSQL_HOST -d vault -U $MSSQL_USER -P $MSSQL_PASS -I -i $f - done; - - - deploy: - name: Deploy - runs-on: ubuntu-20.04 - if: always() - needs: - - reset-db - - update-db - strategy: - fail-fast: false - matrix: - include: - - name: Api - - name: Admin - - name: Billing - - name: Events - - name: Sso - - name: Identity - steps: - - name: Setup - id: setup - run: | - NAME_LOWER=$(echo "${{ matrix.name }}" | awk '{print tolower($0)}') - echo "Matrix name: ${{ matrix.name }}" - echo "NAME_LOWER: $NAME_LOWER" - echo "::set-output name=name_lower::$NAME_LOWER" - - BRANCH_NAME=$(echo "$GITHUB_REF" | sed "s#refs/heads/##g") - echo "GITHUB_REF: $GITHUB_REF" - echo "BRANCH_NAME: $BRANCH_NAME" - echo "::set-output name=branch_name::$BRANCH_NAME" - - mkdir publish - - - name: Download latest ${{ matrix.name }} asset from ${{ env.branch_name }} - uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783 - env: - branch_name: ${{ steps.setup.outputs.branch_name }} - with: - workflow: build.yml - workflow_conclusion: success - branch: ${{ env.branch_name }} - artifacts: ${{ matrix.name }}.zip - - - name: Login to Azure - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a - with: - creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }} - - - name: Retrieve secrets - id: retrieve-secrets - env: - VAULT_NAME: "bitwarden-qa-kv" - run: | - webapp_name=$( - az keyvault secret show --vault-name $VAULT_NAME \ - --name appservices-${{ steps.setup.outputs.name_lower }}-webapp-name \ - --query value --output tsv - ) - echo "::add-mask::$webapp_name" - echo "::set-output name=webapp-name::$webapp_name" - - - name: Stop App Service - env: - AZURE_RESOURCE_GROUP: "bw-qa-env" - run: az webapp stop --name ${{ steps.retrieve-secrets.outputs.webapp-name }} --resource-group $AZURE_RESOURCE_GROUP - - - name: Deploy App - uses: azure/webapps-deploy@798e43877120eda6a2a690a4f212c545e586ae31 - with: - app-name: ${{ steps.retrieve-secrets.outputs.webapp-name }} - package: ./${{ matrix.name }}.zip - - - name: Start App Service - env: - AZURE_RESOURCE_GROUP: "bw-qa-env" - run: az webapp start --name ${{ steps.retrieve-secrets.outputs.webapp-name }} --resource-group $AZURE_RESOURCE_GROUP diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c56f642c7..70f46ab4c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,56 +1,58 @@ --- name: Release +run-name: Release ${{ inputs.release_type }} on: workflow_dispatch: - inputs: {} - + inputs: + release_type: + description: "Release Options" + required: true + default: "Initial Release" + type: choice + options: + - Initial Release + - Redeploy + - Dry Run jobs: setup: name: Setup - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 outputs: - release_version: ${{ steps.version.outputs.package }} + release_version: ${{ steps.version.outputs.version }} branch-name: ${{ steps.branch.outputs.branch-name }} steps: - name: Branch check + if: ${{ github.event.inputs.release_type != 'Dry Run' }} run: | - if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix" ]]; then + if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then echo "===================================" - echo "[!] Can only release from the 'rc' or 'hotfix' branches" + echo "[!] Can only release from the 'rc' or 'hotfix-rc' branches" echo "===================================" exit 1 fi - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 - name: Check Release Version id: version - run: | - version=$( grep -o ".*" Directory.Build.props | grep -o "[0-9]*\.[0-9]*\.[0-9]*") - previous_release_tag_version=$( - curl -sL https://api.github.com/repos/$GITHUB_REPOSITORY/releases/latest | jq -r ".tag_name" - ) - - if [ "v$version" == "$previous_release_tag_version" ]; then - echo "[!] Already released v$version. Please bump version to continue" - exit 1 - fi - - echo "::set-output name=package::$version" + uses: bitwarden/gh-actions/release-version-check@4cf17a5ff15a995a2daf2b60ba371e5c9907c068 + with: + release-type: ${{ github.event.inputs.release_type }} + project-type: dotnet + file: Directory.Build.props - name: Get branch name id: branch run: | BRANCH_NAME=$(basename ${{ github.ref }}) - echo "::set-output name=branch-name::$BRANCH_NAME" - + echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT deploy: name: Deploy - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: - setup strategy: @@ -70,18 +72,39 @@ jobs: NAME_LOWER=$(echo "${{ matrix.name }}" | awk '{print tolower($0)}') echo "Matrix name: ${{ matrix.name }}" echo "NAME_LOWER: $NAME_LOWER" - echo "::set-output name=name_lower::$NAME_LOWER" + echo "name_lower=$NAME_LOWER" >> $GITHUB_OUTPUT + + - name: Create GitHub deployment for ${{ matrix.name }} + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + uses: chrnorm/deployment-action@1b599fe41a0ef1f95191e7f2eec4743f2d7dfc48 + id: deployment + with: + token: "${{ secrets.GITHUB_TOKEN }}" + initial-status: "in_progress" + environment: "Production Cloud" + task: "deploy" + description: "Deploy from ${{ needs.setup.outputs.branch-name }} branch" - name: Download latest Release ${{ matrix.name }} asset - uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783 + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + uses: bitwarden/gh-actions/download-artifacts@850faad0cf6c02a8c0dc46eddde2363fbd6c373a with: workflow: build.yml workflow_conclusion: success branch: ${{ needs.setup.outputs.branch-name }} artifacts: ${{ matrix.name }}.zip + - name: Download latest Release ${{ matrix.name }} asset + if: ${{ github.event.inputs.release_type == 'Dry Run' }} + uses: bitwarden/gh-actions/download-artifacts@850faad0cf6c02a8c0dc46eddde2363fbd6c373a + with: + workflow: build.yml + workflow_conclusion: success + branch: master + artifacts: ${{ matrix.name }}.zip + - name: Login to Azure - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf with: creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} @@ -101,22 +124,50 @@ jobs: --query value --output tsv ) echo "::add-mask::$webapp_name" - echo "::set-output name=webapp-name::$webapp_name" + echo "webapp-name=$webapp_name" >> $GITHUB_OUTPUT echo "::add-mask::$publish_profile" - echo "::set-output name=publish-profile::$publish_profile" + echo "publish-profile=$publish_profile" >> $GITHUB_OUTPUT - name: Deploy App - uses: azure/webapps-deploy@798e43877120eda6a2a690a4f212c545e586ae31 + uses: azure/webapps-deploy@0b651ed7546ecfc75024011f76944cb9b381ef1e with: app-name: ${{ steps.retrieve-secrets.outputs.webapp-name }} publish-profile: ${{ steps.retrieve-secrets.outputs.publish-profile }} package: ./${{ matrix.name }}.zip slot-name: "staging" + - name: Start staging slot + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + env: + SERVICE: ${{ matrix.name }} + WEBAPP_NAME: ${{ steps.retrieve-secrets.outputs.webapp-name }} + run: | + if [[ "$SERVICE" = "Api" ]] || [[ "$SERVICE" = "Identity" ]]; then + RESOURCE_GROUP=bitwardenappservices + else + RESOURCE_GROUP=bitwarden + fi + az webapp start -n $WEBAPP_NAME -g $RESOURCE_GROUP -s staging + + - name: Update ${{ matrix.name }} deployment status to Success + if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }} + uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86 + with: + token: "${{ secrets.GITHUB_TOKEN }}" + state: "success" + deployment-id: ${{ steps.deployment.outputs.deployment_id }} + + - name: Update ${{ matrix.name }} deployment status to Failure + if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }} + uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86 + with: + token: "${{ secrets.GITHUB_TOKEN }}" + state: "failure" + deployment-id: ${{ steps.deployment.outputs.deployment_id }} release-docker: name: Build Docker images - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: - setup env: @@ -126,94 +177,226 @@ jobs: fail-fast: false matrix: include: - - service_name: Admin - - service_name: Api - - service_name: Attachments - - service_name: Events - - service_name: Icons - - service_name: Identity - - service_name: K8S-Proxy - - service_name: MsSql - - service_name: Nginx - - service_name: Notifications - - service_name: Server - - service_name: Setup - - service_name: Sso + - project_name: Admin + origin_docker_repo: bitwarden + - project_name: Api + origin_docker_repo: bitwarden + - project_name: Attachments + origin_docker_repo: bitwarden + - project_name: Events + prod_acr: true + origin_docker_repo: bitwarden + - project_name: EventsProcessor + prod_acr: true + origin_docker_repo: bitwardenqa.azurecr.io + - project_name: Icons + origin_docker_repo: bitwarden + prod_acr: true + - project_name: Identity + origin_docker_repo: bitwarden + - project_name: MsSql + origin_docker_repo: bitwarden + - project_name: Nginx + origin_docker_repo: bitwarden + - project_name: Notifications + origin_docker_repo: bitwarden + - project_name: Server + origin_docker_repo: bitwarden + - project_name: Setup + origin_docker_repo: bitwarden + - project_name: Sso + origin_docker_repo: bitwarden + - project_name: Scim + origin_docker_repo: bitwarden + - project_name: Billing + origin_docker_repo: bitwardenqa.azurecr.io steps: - name: Print environment + env: + RELEASE_OPTION: ${{ github.event.inputs.release_type }} run: | whoami docker --version echo "GitHub ref: $GITHUB_REF" echo "GitHub event: $GITHUB_EVENT" + echo "Github Release Option: $RELEASE_OPTION" + - name: Checkout repo + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 + + - name: Setup project name + id: setup + run: | + PROJECT_NAME=$(echo "${{ matrix.project_name }}" | awk '{print tolower($0)}') + echo "Matrix name: ${{ matrix.project_name }}" + echo "PROJECT_NAME: $PROJECT_NAME" + echo "project_name=$PROJECT_NAME" >> $GITHUB_OUTPUT + + ########## DockerHub ########## - name: Setup DCT id: setup-dct + if: matrix.origin_docker_repo == 'bitwarden' uses: bitwarden/gh-actions/setup-docker-trust@a8c384a05a974c05c48374c818b004be221d43ff with: azure-creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} azure-keyvault-name: "bitwarden-prod-kv" - - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f - - - name: Setup service name - id: setup - run: | - SERVICE_NAME=$(echo "${{ matrix.service_name }}" | awk '{print tolower($0)}') - echo "Matrix name: ${{ matrix.service_name }}" - echo "SERVICE_NAME: $SERVICE_NAME" - echo "::set-output name=service_name::$SERVICE_NAME" - - - name: Pull latest selfhost image + - name: Pull latest project image + if: matrix.origin_docker_repo == 'bitwarden' env: - SERVICE_NAME: ${{ steps.setup.outputs.service_name }} - run: docker pull bitwarden/$SERVICE_NAME:$_BRANCH_NAME + PROJECT_NAME: ${{ steps.setup.outputs.project_name }} + run: | + if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then + docker pull bitwarden/$PROJECT_NAME:latest + else + docker pull bitwarden/$PROJECT_NAME:$_BRANCH_NAME + fi - name: Tag version and latest + if: matrix.origin_docker_repo == 'bitwarden' env: - SERVICE_NAME: ${{ steps.setup.outputs.service_name }} + PROJECT_NAME: ${{ steps.setup.outputs.project_name }} run: | - docker tag bitwarden/$SERVICE_NAME:$_BRANCH_NAME bitwarden/$SERVICE_NAME:$_RELEASE_VERSION - docker tag bitwarden/$SERVICE_NAME:$_BRANCH_NAME bitwarden/$SERVICE_NAME:latest - - - name: List Docker images - run: docker images + if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then + docker tag bitwarden/$PROJECT_NAME:latest bitwarden/$PROJECT_NAME:dryrun + else + docker tag bitwarden/$PROJECT_NAME:$_BRANCH_NAME bitwarden/$PROJECT_NAME:$_RELEASE_VERSION + fi - name: Push version and latest image + if: ${{ github.event.inputs.release_type != 'Dry Run' && matrix.origin_docker_repo == 'bitwarden' }} env: DOCKER_CONTENT_TRUST: 1 DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ steps.setup-dct.outputs.dct-delegate-repo-passphrase }} - SERVICE_NAME: ${{ steps.setup.outputs.service_name }} + PROJECT_NAME: ${{ steps.setup.outputs.project_name }} + run: docker push bitwarden/$PROJECT_NAME:$_RELEASE_VERSION + + - name: Log out of Docker and disable Docker Notary + if: matrix.origin_docker_repo == 'bitwarden' run: | - docker push bitwarden/$SERVICE_NAME:$_RELEASE_VERSION - docker push bitwarden/$SERVICE_NAME:latest + docker logout + echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV + + ########## ACR QA ########## + - name: Login to Azure - QA Subscription + uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + with: + creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }} + + - name: Login to Azure ACR + run: az acr login -n bitwardenqa + + - name: Pull latest project image + if: matrix.origin_docker_repo == 'bitwardenqa.azurecr.io' + env: + PROJECT_NAME: ${{ steps.setup.outputs.project_name }} + REGISTRY: bitwardenqa.azurecr.io + run: | + if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then + docker pull $REGISTRY/$PROJECT_NAME:latest + else + docker pull $REGISTRY/$PROJECT_NAME:$_BRANCH_NAME + fi + + - name: Tag version and latest + env: + PROJECT_NAME: ${{ steps.setup.outputs.project_name }} + REGISTRY: bitwardenqa.azurecr.io + ORIGIN_REGISTRY: ${{ matrix.origin_docker_repo }} + run: | + if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then + docker tag $ORIGIN_REGISTRY/$PROJECT_NAME:latest $REGISTRY/$PROJECT_NAME:dryrun + else + docker tag $ORIGIN_REGISTRY/$PROJECT_NAME:$_BRANCH_NAME $REGISTRY/$PROJECT_NAME:$_RELEASE_VERSION + docker tag $ORIGIN_REGISTRY/$PROJECT_NAME:$_BRANCH_NAME $REGISTRY/$PROJECT_NAME:latest + fi + + - name: Push version and latest image + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + env: + PROJECT_NAME: ${{ steps.setup.outputs.project_name }} + REGISTRY: bitwardenqa.azurecr.io + run: | + docker push $REGISTRY/$PROJECT_NAME:latest + docker push $REGISTRY/$PROJECT_NAME:$_RELEASE_VERSION - name: Log out of Docker run: docker logout + ########## ACR PROD ########## + - name: Login to Azure - PROD Subscription + if: matrix.prod_acr == true + uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Login to Azure ACR + if: matrix.prod_acr == true + run: az acr login -n bitwardenprod + + - name: Tag version and latest + if: matrix.prod_acr == true + env: + PROJECT_NAME: ${{ steps.setup.outputs.project_name }} + REGISTRY: bitwardenprod.azurecr.io + ORIGIN_REGISTRY: ${{ matrix.origin_docker_repo }} + run: | + if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then + docker tag $ORIGIN_REGISTRY/$PROJECT_NAME:latest $REGISTRY/$PROJECT_NAME:dryrun + else + docker tag $ORIGIN_REGISTRY/$PROJECT_NAME:$_BRANCH_NAME $REGISTRY/$PROJECT_NAME:$_RELEASE_VERSION + docker tag $ORIGIN_REGISTRY/$PROJECT_NAME:$_BRANCH_NAME $REGISTRY/$PROJECT_NAME:latest + fi + + - name: Push version and latest image + if: ${{ github.event.inputs.release_type != 'Dry Run' && matrix.prod_acr == true }} + env: + PROJECT_NAME: ${{ steps.setup.outputs.project_name }} + REGISTRY: bitwardenprod.azurecr.io + run: | + docker push $REGISTRY/$PROJECT_NAME:$_RELEASE_VERSION + docker push $REGISTRY/$PROJECT_NAME:latest + + - name: Log out of Docker + if: matrix.prod_acr == true + run: docker logout release: name: Create GitHub Release - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: - setup - deploy steps: - name: Download latest Release docker-stub - uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783 + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + uses: bitwarden/gh-actions/download-artifacts@850faad0cf6c02a8c0dc46eddde2363fbd6c373a with: workflow: build.yml workflow_conclusion: success branch: ${{ needs.setup.outputs.branch-name }} artifacts: "docker-stub.zip, - swagger.json" + docker-stub-sha256.txt, + swagger.json" + + - name: Download latest Release docker-stub + if: ${{ github.event.inputs.release_type == 'Dry Run' }} + uses: bitwarden/gh-actions/download-artifacts@850faad0cf6c02a8c0dc46eddde2363fbd6c373a + with: + workflow: build.yml + workflow_conclusion: success + branch: master + artifacts: "docker-stub.zip, + docker-stub-sha256.txt, + swagger.json" - name: Create release - uses: ncipollo/release-action@95215a3cb6e6a1908b3c44e00b4fdb15548b1e09 + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + uses: ncipollo/release-action@40bb172bd05f266cf9ba4ff965cb61e9ee5f6d01 with: - artifacts: 'docker-stub.zip, - swagger.json' + artifacts: "docker-stub.zip, + docker-stub-sha256.txt, + swagger.json" commit: ${{ github.sha }} tag: "v${{ needs.setup.outputs.release_version }}" name: "Version ${{ needs.setup.outputs.release_version }}" diff --git a/.github/workflows/stale-bot.yml b/.github/workflows/stale-bot.yml new file mode 100644 index 000000000..5cd154cf2 --- /dev/null +++ b/.github/workflows/stale-bot.yml @@ -0,0 +1,30 @@ +--- +name: 'Close stale issues and PRs' +on: + workflow_dispatch: + schedule: # Run once a day at 5.23am (arbitrary but should avoid peak loads on the hour) + - cron: '23 5 * * *' + +jobs: + stale: + name: 'Check for stale issues and PRs' + runs-on: ubuntu-20.04 + steps: + - name: 'Run stale action' + uses: actions/stale@3cc123766321e9f15a6676375c154ccffb12a358 # v5.0.0 + with: + stale-issue-label: 'needs-reply' + stale-pr-label: 'needs-changes' + days-before-stale: -1 # Do not apply the stale labels automatically, this is a manual process + days-before-issue-close: 14 # Close issue if no further activity after X days + days-before-pr-close: 21 # Close PR if no further activity after X days + close-issue-message: | + We need more information before we can help you with your problem. As we haven’t heard from you recently, this issue will be closed. + + If this happens again or continues to be an problem, please respond to this issue with the information we’ve requested and anything else relevant. + close-pr-message: | + We can’t merge your pull request until you make the changes we’ve requested. As we haven’t heard from you recently, this pull request will be closed. + + If you’re still working on this, please respond here after you’ve made the changes we’ve requested and our team will re-open it for further review. + + Please make sure to resolve any conflicts with the master branch before requesting another review. diff --git a/.github/workflows/stop-staging-slots.yml b/.github/workflows/stop-staging-slots.yml new file mode 100644 index 000000000..6fb22046c --- /dev/null +++ b/.github/workflows/stop-staging-slots.yml @@ -0,0 +1,60 @@ +--- +name: Stop Staging Slots + +on: + workflow_dispatch: + inputs: {} + + +jobs: + stop-slots: + name: Stop Slots + runs-on: ubuntu-20.04 + strategy: + fail-fast: false + matrix: + include: + - name: Api + - name: Admin + - name: Billing + - name: Events + - name: Sso + - name: Identity + steps: + - name: Setup + id: setup + run: | + NAME_LOWER=$(echo "${{ matrix.name }}" | awk '{print tolower($0)}') + echo "Matrix name: ${{ matrix.name }}" + echo "NAME_LOWER: $NAME_LOWER" + echo "name_lower=$NAME_LOWER" >> $GITHUB_OUTPUT + + - name: Login to Azure + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + env: + VAULT_NAME: "bitwarden-prod-kv" + run: | + webapp_name=$( + az keyvault secret show --vault-name $VAULT_NAME \ + --name appservices-${{ steps.setup.outputs.name_lower }}-webapp-name \ + --query value --output tsv + ) + echo "::add-mask::$webapp_name" + echo "webapp-name=$webapp_name" >> $GITHUB_OUTPUT + + - name: Stop staging slot + env: + SERVICE: ${{ matrix.name }} + WEBAPP_NAME: ${{ steps.retrieve-secrets.outputs.webapp-name }} + run: | + if [[ "$SERVICE" = "Api" ]] || [[ "$SERVICE" = "Identity" ]]; then + RESOURCE_GROUP=bitwardenappservices + else + RESOURCE_GROUP=bitwarden + fi + az webapp stop -n $WEBAPP_NAME -g $RESOURCE_GROUP -s staging diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml new file mode 100644 index 000000000..022b6073e --- /dev/null +++ b/.github/workflows/version-bump.yml @@ -0,0 +1,93 @@ +--- +name: Version Bump + +on: + workflow_dispatch: + inputs: + version_number: + description: "New Version" + required: true + +jobs: + bump_props_version: + name: "Create version_bump_${{ github.event.inputs.version_number }} branch" + runs-on: ubuntu-20.04 + steps: + - name: Checkout Branch + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 + + - name: Login to Azure - Prod Subscription + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@c3b3285993151c5af47cefcb3b9134c28ab479af + with: + keyvault: "bitwarden-prod-kv" + secrets: "github-gpg-private-key, github-gpg-private-key-passphrase" + + - name: Import GPG key + uses: crazy-max/ghaction-import-gpg@c8bb57c57e8df1be8c73ff3d59deab1dbc00e0d1 + with: + gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }} + passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }} + git_user_signingkey: true + git_commit_gpgsign: true + + - name: Create Version Branch + run: git switch -c version_bump_${{ github.event.inputs.version_number }} + + - name: Bump Version - Props + uses: bitwarden/gh-actions/version-bump@6a42772f8849107fd457cf47cd9c7e224be44e55 + with: + version: ${{ github.event.inputs.version_number }} + file_path: "Directory.Build.props" + + - name: Setup git + run: | + git config --local user.email "106330231+bitwarden-devops-bot@users.noreply.github.com" + git config --local user.name "bitwarden-devops-bot" + + - name: Check if version changed + id: version-changed + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "changes_to_commit=TRUE" >> $GITHUB_OUTPUT + else + echo "changes_to_commit=FALSE" >> $GITHUB_OUTPUT + echo "No changes to commit!"; + fi + + - name: Commit files + if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} + run: git commit -m "Bumped version to ${{ github.event.inputs.version_number }}" -a + + - name: Push changes + if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} + run: git push -u origin version_bump_${{ github.event.inputs.version_number }} + + - name: Create Version PR + if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} + env: + PR_BRANCH: "version_bump_${{ github.event.inputs.version_number }}" + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + BASE_BRANCH: master + TITLE: "Bump version to ${{ github.event.inputs.version_number }}" + run: | + gh pr create --title "$TITLE" \ + --base "$BASE" \ + --head "$PR_BRANCH" \ + --label "version update" \ + --label "automated pr" \ + --body " + ## Type of change + - [ ] Bug fix + - [ ] New feature development + - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) + - [ ] Build/deploy pipeline (DevOps) + - [X] Other + + ## Objective + Automated version bump to ${{ github.event.inputs.version_number }}" diff --git a/.github/workflows/workflow-linter.yml b/.github/workflows/workflow-linter.yml new file mode 100644 index 000000000..9fda2eee0 --- /dev/null +++ b/.github/workflows/workflow-linter.yml @@ -0,0 +1,11 @@ +--- +name: Workflow Linter + +on: + pull_request: + paths: + - .github/workflows/** + +jobs: + call-workflow: + uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@master diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..7e09ae524 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,418 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "compounds": [ + { + "name": "Min Server", + "configurations": [ + "Identity", + "API" + ], + "presentation": { + "hidden": false, + "group": "AA_compounds", + "order": 1 + }, + "stopAll": true + }, + { + "name": "Admin, API, Identity", + "configurations": [ + "Admin", + "API", + "Identity" + ], + "presentation": { + "hidden": false, + "group": "AA_compounds", + "order": 3 + }, + "stopAll": true + }, + { + "name": "Full Server", + "configurations": [ + "Admin", + "API", + "EventsProcessor", + "Identity", + "Sso", + "Icons", + "Billing", + "Notifications" + ], + "presentation": { + "hidden": false, + "group": "AA_compounds", + "order": 4 + }, + "stopAll": true + }, + { + "name": "Self Host: Bit", + "configurations": [ + "Admin-SelfHost", + "API-SelfHost", + "EventsProcessor-SelfHost", + "Identity-SelfHost", + "Sso-SelfHost", + "Notifications-SelfHost" + ], + "presentation": { + "hidden": false, + "group": "AA_compounds", + "order": 2 + }, + "stopAll": true + }, + { + "name": "Self Host: OSS", + "configurations": [ + "Admin-SelfHost", + "API-SelfHost", + "EventsProcessor-SelfHost", + "Identity-SelfHost", + ], + "presentation": { + "hidden": false, + "group": "AA_compounds", + "order": 99 + }, + "stopAll": true + } + ], + "configurations": [ + { + "name": "Identity", + "presentation": { + "hidden": false, + "group": "cloud", + "order": 10 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildIdentity", + "program": "${workspaceFolder}/src/Identity/bin/Debug/net6.0/Identity.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Identity", + "stopAtEntry": false, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": "API", + "presentation": { + "hidden": false, + "group": "cloud", + "order": 10 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildAPI", + "program": "${workspaceFolder}/src/Api/bin/Debug/net6.0/Api.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Api", + "stopAtEntry": false, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": "Billing", + "presentation": { + "hidden": false, + "group": "cloud", + "order": 10 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildBilling", + "program": "${workspaceFolder}/src/Billing/bin/Debug/net6.0/Billing.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Billing", + "stopAtEntry": false, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": "Admin", + "presentation": { + "hidden": false, + "group": "cloud", + "order": 20 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildAdmin", + "OS-COMMENT4": "If you have changed target frameworks, make sure to update the program path.", + "program": "${workspaceFolder}/src/Admin/bin/Debug/net6.0/Admin.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Admin", + "stopAtEntry": false, + "OS-COMMENT5": "Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser", + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": "Sso", + "presentation": { + "hidden": false, + "group": "cloud", + "order": 50 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildSso", + "program": "${workspaceFolder}/bitwarden_license/src/Sso/bin/Debug/net6.0/Sso.dll", + "args": [], + "cwd": "${workspaceFolder}/bitwarden_license/src/Sso", + "stopAtEntry": false, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": "EventsProcessor", + "presentation": { + "hidden": false, + "group": "cloud", + "order": 90 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildEventsProcessor", + "program": "${workspaceFolder}/src/EventsProcessor/bin/Debug/net6.0/EventsProcessor.dll", + "args": [], + "cwd": "${workspaceFolder}/src/EventsProcessor", + "stopAtEntry": false, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": "Icons", + "presentation": { + "hidden": false, + "group": "cloud", + "order": 90 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildIcons", + "program": "${workspaceFolder}/src/Icons/bin/Debug/net6.0/Icons.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Icons", + "stopAtEntry": false, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": "Notifications", + "presentation": { + "hidden": true, + "group": "cloud", + "order": 100 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildNotifications", + "program": "${workspaceFolder}/src/Notifications/bin/Debug/net6.0/Notifications.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Notifications", + "stopAtEntry": false, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": "Identity-SelfHost", + "presentation": { + "hidden": true, + "group": "self-host", + "order": 999 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildIdentity", + "program": "${workspaceFolder}/src/Identity/bin/Debug/net6.0/Identity.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Identity", + "stopAtEntry": false, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "http://localhost:33657", + "developSelfHosted": "true" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": "API-SelfHost", + "presentation": { + "hidden": true, + "group": "self-host", + "order": 999 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildAPI", + "program": "${workspaceFolder}/src/Api/bin/Debug/net6.0/Api.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Api", + "stopAtEntry": false, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "http://localhost:4001", + "developSelfHosted": "true" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": "Admin-SelfHost", + "presentation": { + "hidden": true, + "group": "self-host", + "order": 999 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildAdmin", + "OS-COMMENT4": "If you have changed target frameworks, make sure to update the program path.", + "program": "${workspaceFolder}/src/Admin/bin/Debug/net6.0/Admin.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Admin", + "stopAtEntry": false, + "OS-COMMENT5": "Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser", + "env": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "http://localhost:62912", + "developSelfHosted": "true" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": "Sso-SelfHost", + "presentation": { + "hidden": true, + "group": "self-host", + "order": 999 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildSso", + "program": "${workspaceFolder}/bitwarden_license/src/Sso/bin/Debug/net6.0/Sso.dll", + "args": [], + "cwd": "${workspaceFolder}/bitwarden_license/src/Sso", + "stopAtEntry": false, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "http://localhost:51822", + "developSelfHosted": "true" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": "Notifications-SelfHost", + "presentation": { + "hidden": true, + "group": "self-host", + "order": 999 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildNotifications", + "program": "${workspaceFolder}/src/Notifications/bin/Debug/net6.0/Notifications.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Notifications", + "stopAtEntry": false, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "http://localhost:61841", + "developSelfHosted": "true" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": "EventsProcessor-SelfHost", + "presentation": { + "hidden": true, + "group": "self-host", + "order": 999 + }, + "requireExactSource": true, + "type": "coreclr", + "request": "launch", + "preLaunchTask": "buildEventsProcessor", + "program": "${workspaceFolder}/src/EventsProcessor/bin/Debug/net6.0/EventsProcessor.dll", + "args": [], + "cwd": "${workspaceFolder}/src/EventsProcessor", + "stopAtEntry": false, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "http://localhost:46274", + "developSelfHosted": "true" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ], +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..61d1f9240 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,157 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "buildIcons", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/src/Icons/Icons.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "buildPortal", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/bitwarden_license/src/Portal/Portal.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "buildSso", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/bitwarden_license/src/Sso/Sso.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "buildEventsProcessor", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/src/EventsProcessor/EventsProcessor.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "buildAdmin", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/src/Admin/Admin.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "buildIdentity", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/src/Identity/Identity.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "buildAPI", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/src/Api/Api.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile", + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "buildNotifications", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/src/Notifications/Notifications.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile", + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "buildBilling", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/src/Billing/Billing.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile", + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "clean", + "type": "shell", + "command": "dotnet clean", + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared", + "showReuseMessage": true, + "clear": false + }, + "problemMatcher": "$msCompile" + }, + { + "label": "test", + "type": "shell", + "command": "dotnet test", + "group": { + "kind": "test", + "isDefault": true + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared", + "showReuseMessage": true, + "clear": false + }, + "problemMatcher": "$msCompile" + } + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5331e9f7b..2833057bc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,31 +1,3 @@ # How to Contribute -Contributions of all kinds are welcome! - -Please visit our [Community Forums](https://community.bitwarden.com/) for general community discussion and the development roadmap. - -Here is how you can get involved: - -* **Request a new feature:** Go to the [Feature Requests category](https://community.bitwarden.com/c/feature-requests/) of the Community Forums. Please search existing feature requests before making a new one - -* **Write code for a new feature:** Make a new post in the [Github Contributions category](https://community.bitwarden.com/c/github-contributions/) of the Community Forums. Include a description of your proposed contribution, screeshots, and links to any relevant feature requests. This helps get feedback from the community and Bitwarden team members before you start writing code - -* **Report a bug or submit a bugfix:** Use Github issues and pull requests - -* **Write documentation:** Submit a pull request to the [Bitwarden help repository](https://github.com/bitwarden/help) - -* **Help other users:** Go to the [User-to-User Support category](https://community.bitwarden.com/c/support/) on the Community Forums - -## Contributor Agreement - -Please sign the [Contributor Agreement](https://cla-assistant.io/bitwarden/server) if you intend on contributing to any Github repository. Pull requests cannot be accepted and merged unless the author has signed the Contributor Agreement. - -## Pull Request Guidelines - -* commit any pull requests against the `master` branch -* include a link to your Community Forums post -* please do **not** submit version number updates/bumps - -# Setup guide - -Please read the [Setup guide](https://github.com/bitwarden/server/blob/master/SETUP.md) for a step-by-step guide to set up your own local development server. +Our [Contributing Guidelines](https://contributing.bitwarden.com/contributing/) are located in our [Contributing Documentation](https://contributing.bitwarden.com/). The documentation also includes recommended tooling, code style tips, and lots of other great information to get you started. diff --git a/Directory.Build.props b/Directory.Build.props index ffeffe4ff..ce11b46f5 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,9 +1,71 @@ - + - - net5.0 - 1.44.1 - Bit.$(MSBuildProjectName) - + + net6.0 + + 2023.1.0 + Bit.$(MSBuildProjectName) + true + enable + false + - + + + + 17.1.0 + + 2.4.1 + + 2.4.3 + + 3.1.2 + + 6.0.3 + + 4.3.0 + + 4.17.0 + + 4.17.0 + + + + + + + + + + + + <_Parameter1>GitHash + <_Parameter2>$(SourceRevisionId) + + + + + \ No newline at end of file diff --git a/LICENSE_FAQ.md b/LICENSE_FAQ.md index b84a2f700..84a46fe93 100644 --- a/LICENSE_FAQ.md +++ b/LICENSE_FAQ.md @@ -16,12 +16,12 @@ Our current software products have the following licenses: *Bitwarden server:* The main Bitwarden server code is licensed under the AGPL 3.0 license. -*CommCore and SSO integration:* Code for certain new modules that are designed and developed for use by larger +*Commercial.Core and SSO integration:* Code for certain new modules that are designed and developed for use by larger organizations and enterprise environments is released under the Bitwarden License, a "source available" license. The Bitwarden License provides users access to product source code for non-production purposes such as development and testing, but requires a paid subscription for production use of the product, and environments supporting production. -Additionally the Api module by default includes CommCore which is under the Bitwarden License, however this can be -disabled by using `/p:DefineConstants="OSS"` as an argument to `dotnet` while building the module. +Additionally the Api module by default includes Commercial.Core which is under the Bitwarden License, however this can +be disabled by using `/p:DefineConstants="OSS"` as an argument to `dotnet` while building the module. # Frequently Asked Questions diff --git a/README.md b/README.md index c5be6e88f..e6c0dcd85 100644 --- a/README.md +++ b/README.md @@ -13,51 +13,15 @@

-------------------- +--- The Bitwarden Server project contains the APIs, database, and other core infrastructure items needed for the "backend" of all bitwarden client applications. The server project is written in C# using .NET Core with ASP.NET Core. The database is written in T-SQL/SQL Server. The codebase can be developed, built, run, and deployed cross-platform on Windows, macOS, and Linux distributions. -## Build/Run +## Developer Documentation -Please read the [Setup guide](https://github.com/bitwarden/server/blob/master/SETUP.md) for a step-by-step guide to set up your own local development server. - -### Requirements - -- [.NET 5.0 SDK](https://dotnet.microsoft.com/download) -- [SQL Server 2017](https://docs.microsoft.com/en-us/sql/index) - -*These dependencies are free to use.* - -### Recommended Development Tooling - -- [Visual Studio](https://www.visualstudio.com/vs/) (Windows and macOS) -- [Visual Studio Code](https://code.visualstudio.com/) (other) - -*These tools are free to use.* - -### API - -``` -cd src/Api -dotnet restore -dotnet build -dotnet run -``` - -visit http://localhost:4000/alive - -### Identity - -``` -cd src/Identity -dotnet restore -dotnet build -dotnet run -``` - -visit http://localhost:33657/.well-known/openid-configuration +Please refer to the [Server Setup Guide](https://contributing.bitwarden.com/getting-started/server/guide) in the [Contributing Documentation](https://contributing.bitwarden.com/) for build instructions, recommended tooling, code style tips, and lots of other great information to get you started. ## Deploy @@ -76,13 +40,13 @@ Full documentation for deploying Bitwarden with Docker can be found in our help - [Docker](https://www.docker.com/community-edition#/download) - [Docker Compose](https://docs.docker.com/compose/install/) (already included with some Docker installations) -*These dependencies are free to use.* +_These dependencies are free to use._ ### Linux & macOS ``` -curl -s -o bitwarden.sh \ - https://raw.githubusercontent.com/bitwarden/server/master/scripts/bitwarden.sh \ +curl -s -L -o bitwarden.sh \ + "https://func.bitwarden.com/api/dl/?app=self-host&platform=linux" \ && chmod +x bitwarden.sh ./bitwarden.sh install ./bitwarden.sh start @@ -92,15 +56,40 @@ curl -s -o bitwarden.sh \ ``` Invoke-RestMethod -OutFile bitwarden.ps1 ` - -Uri https://raw.githubusercontent.com/bitwarden/server/master/scripts/bitwarden.ps1 + -Uri "https://func.bitwarden.com/api/dl/?app=self-host&platform=windows" .\bitwarden.ps1 -install .\bitwarden.ps1 -start ``` +## We're Hiring! + +Interested in contributing in a big way? Consider joining our team! We're hiring for many positions. Please take a look at our [Careers page](https://bitwarden.com/careers/) to see what opportunities are currently open as well as what it's like to work at Bitwarden. + ## Contribute -Code contributions are welcome! Visual Studio or VS Code is highly recommended if you are working on this project. Please commit any pull requests against the `master` branch. Please see [`CONTRIBUTING.md`](CONTRIBUTING.md) for more info (and feel free to contribute to that guide as well). +Code contributions are welcome! Please commit any pull requests against the `master` branch. Learn more about how to contribute by reading the [Contributing Guidelines](https://contributing.bitwarden.com/contributing/). Check out the [Contributing Documentation](https://contributing.bitwarden.com/) for how to get started with your first contribution. Security audits and feedback are welcome. Please open an issue or email us privately if the report is sensitive in nature. You can read our security policy in the [`SECURITY.md`](SECURITY.md) file. We also run a program on [HackerOne](https://hackerone.com/bitwarden). No grant of any rights in the trademarks, service marks, or logos of Bitwarden is made (except as may be necessary to comply with the notice requirements as applicable), and use of any Bitwarden trademarks must comply with [Bitwarden Trademark Guidelines](https://github.com/bitwarden/server/blob/master/TRADEMARK_GUIDELINES.md). + +### Dotnet-format + +Consider installing our git pre-commit hook for automatic formatting. + +```bash +git config --local core.hooksPath .git-hooks +``` + +### File Scoped Namespaces + +We recently migrated to using file scoped namespaces to save some horizontal space. All previous branches will need to update to avoid large merge conflicts using the following steps: + +1. Check out your local Branch +2. Run `git merge 9b7aef0763ad14e229b337c3b5b27cb411009792` +3. Resolve any merge conflicts, commit. +4. Run `dotnet format` +5. Commit +6. Run `git merge -Xours 7f5f010e1eea400300c47f776604ecf46c4b4f2d` +7. Fix Merge conflicts +8. Push diff --git a/SECURITY.md b/SECURITY.md index ef94f0b49..e6edb96da 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,39 +1,11 @@ -Bitwarden believes that working with security researchers across the globe is crucial to keeping our -users safe. If you believe you've found a security issue in our product or service, we encourage you to -notify us. We welcome working with you to resolve the issue promptly. Thanks in advance! +Bitwarden believes that working with security researchers across the globe is crucial to keeping our users safe. If you believe you've found a security issue in our product or service, we encourage you to please submit a report through our [HackerOne Program](https://hackerone.com/bitwarden/). We welcome working with you to resolve the issue promptly. Thanks in advance! # Disclosure Policy -- Let us know as soon as possible upon discovery of a potential security issue, and we'll make every - effort to quickly resolve the issue. -- Provide us a reasonable amount of time to resolve the issue before any disclosure to the public or a - third-party. We may publicly disclose the issue before resolving it, if appropriate. -- Make a good faith effort to avoid privacy violations, destruction of data, and interruption or - degradation of our service. Only interact with accounts you own or with explicit permission of the - account holder. -- If you would like to encrypt your report, please use the PGP key with long ID - `0xDE6887086F892325FEC04CC0D847525B6931381F` (available in the public keyserver pool). - -# In-scope - -- Security issues in any current release of Bitwarden. This includes the web vault, browser extension, - and mobile apps (iOS and Android). Product downloads are available at https://bitwarden.com. Source - code is available at https://github.com/bitwarden. - -# Exclusions - -The following bug classes are out-of scope: - -- Bugs that are already reported on any of Bitwarden's issue trackers (https://github.com/bitwarden), - or that we already know of. Note that some of our issue tracking is private. -- Issues in an upstream software dependency (ex: Xamarin, ASP.NET) which are already reported to the - upstream maintainer. -- Attacks requiring physical access to a user's device. -- Self-XSS -- Issues related to software or protocols not under Bitwarden's control -- Vulnerabilities in outdated versions of Bitwarden -- Missing security best practices that do not directly lead to a vulnerability -- Issues that do not have any impact on the general public +- Let us know as soon as possible upon discovery of a potential security issue, and we'll make every effort to quickly resolve the issue. +- Provide us a reasonable amount of time to resolve the issue before any disclosure to the public or a third-party. We may publicly disclose the issue before resolving it, if appropriate. +- Make a good faith effort to avoid privacy violations, destruction of data, and interruption or degradation of our service. Only interact with accounts you own or with explicit permission of the account holder. +- If you would like to encrypt your report, please use the PGP key with long ID `0xDE6887086F892325FEC04CC0D847525B6931381F` (available in the public keyserver pool). While researching, we'd like to ask you to refrain from: @@ -42,4 +14,8 @@ While researching, we'd like to ask you to refrain from: - Social engineering (including phishing) of Bitwarden staff or contractors - Any physical attempts against Bitwarden property or data centers +# We want to help you! + +If you have something that you feel is close to exploitation, or if you'd like some information regarding the internal API, or generally have any questions regarding the app that would help in your efforts, please email us at https://bitwarden.com/contact and ask for that information. As stated above, Bitwarden wants to help you find issues, and is more than willing to help. + Thank you for helping keep Bitwarden and our users safe! diff --git a/SETUP.md b/SETUP.md deleted file mode 100644 index 3f0cd199b..000000000 --- a/SETUP.md +++ /dev/null @@ -1,197 +0,0 @@ -# Server Architecture - -The Server is divided into a number of services. Each service is a Visual Studio project in the Server solution. These are: - -* Admin -* Api -* Icons -* Identity -* Notifications -* SQL - -Each service is built and run separately. The Bitwarden clients can use different servers for different services. - -This means that you don't need to run all services locally for a development environment. You can run only those services that you intend to modify, and use Bitwarden.com or a self-hosted instance for all other services required. - -By default some of the services depends on the Bitwarden licensed `CommCore`, however it can easily be disabled by including the `/p:DefineConstants="OSS"` as an argument to `dotnet`. - -# Local Development Environment Setup - -This guide will show you how to set up the Api, Identity and SQL projects for development. These are the minimum projects for any development work. You may need to set up additional projects depending on the changes you want to make. - -We recommend using [Visual Studio](https://visualstudio.microsoft.com/vs/), and [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.1) which is used for the helper scripts. - -## Docker containers - -To simplify the setup process we provide a [Docker Compose](https://docs.docker.com/compose/) application model. This is split up into multiple service profiles to facilitate easily customization. - -Some settings can be customized by modifying the `dev/.env` file, such as the `MSSQL_PASSWORD` which should be modified before starting the project. - -```bash -# Copy the example environment file -cp ./.env.example ./.env - -# We recommend running the following command when developing for self-hosted -docker compose --profile mssql --profile mail up - -# We also provide a storage profile which uses Azurite to emulate some services used by the cloud instance -# Usually only needed by internal Bitwarden developers -docker compose --profile cloud --profile mail up -``` - -### SQL Server - -We recommend changing the `MSSQL_PASSWORD` variable in `dev/.env` to avoid exposing the sqlserver with a default password. **Note**: changing this after first running docker compose may require a re-creation of the storage volume. To do this, stop the running containers and run `docker volume rm bitwardenserver_mssql_dev_data`. (**Warning:** this will delete your development database.) - -We provide a helper script which will create the development database `vault_dev` and also run all migrations. This command should be run after starting docker the first time, as well as after syncing against upstream and after creating a new migration. - -```powershell -.\dev\migrate.ps1 - -# You can also re-run the last migration using -.\dev\migrate.ps1 -r -``` - -**Note:** If all or many migrations are skipped even though this is a new database, make sure that there is not a `last_migration` file located in `dev/.data/mssql`. If there is, remove it and run the helper script again. This can happen if you create the database, run migrations, then delete it. - -### Azurite - -[Azurite](https://github.com/Azure/Azurite) is a emulator for Azure Storage API and supports Blob, Queues and Table storage. We use it to avoid a hard dependency on online services for cloud development. - -To bootstrap the local Azurite instance please run the following command: -```powershell -# This script requires the Az module, which can be installed using -Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force - -.\dev\setup_azurite.ps1 -``` - -### Mailcatcher - -Since the server uses emails for many user interactions a working SMTP server is a requirement, we provide a pre-setup instance of [MailCatcher](https://mailcatcher.me/) which exposes a web interface at http://localhost:1080. - -## Certificates -In order to run Bitwarden, we require two certificates which for local development can be resolved by using self signed certificates. - -### Windows - -We provide a helper script which will generate and add the certificates to the users Certificate Store. After running the script it will output the thumbprints needed for the next step. The certificates can later be accessed using `certml.msc` under `Personal/Certificates`. - -```powershell -.\create_certificates_windows.ps1 - - PSParentPath: Microsoft.PowerShell.Security\Certificate::CurrentUser\My -Thumbprint Subject ----------- ------- -0BE8A0072214AB37C6928968752F698EEC3A68B5 CN=Bitwarden Identity Server Dev -C3A6CECAD3DB580F91A52FC9C767FE780300D8AB CN=Bitwarden Data Protection Dev -``` - -### MacOS - -We provide a helper script which will generate the certificates and add them to the keychain. - -**Note:** You should update the Trust options for each certificate to `always trust` using *Keychain Access*. - -```bash -./create_certificates_mac.sh - -Certificate fingerprints: -Identity Server Dev: 0BE8A0072214AB37C6928968752F698EEC3A68B5 -Data Protection Dev: C3A6CECAD3DB580F91A52FC9C767FE780300D8AB -``` - -## User Secrets -User secrets are a method for managing application settings on a per-developer basis. They are stored outside of the local git repository so that they are not pushed to remote. - -User secrets override the settings in `appsettings.json` of each project. Your user secrets file should match the structure of the `appsettings.json` file for the settings you intend to override. - -For more information, see: [Safe storage of app secrets in development in ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0). - -### Automated Helper script - -We provide a helper scripts which simplifies setting user secrets for all projects in the repository. - -Start by copying the `secret.json.example` file to `secrets.json` and modify the existing settings and add any other required setting. Afterwards run the following command which will add the settings to each project in the bitwarden repository. - -```powershell -.\setup_secrets.ps1 - -# The script also supports an optional flag which removes all existing settings before re-applying them -.\setup_secrets.ps1 -clear 1 -``` - -### Manually creating and modifying - -It is also possible to manually create and modify the user secrets using either the `dotnet` CLI or `Visual Studio` on Windows. For more details see [Appendix A](#user-secrets). - -### Required User Secrets - -**selfhosted**: It is highly recommended that you use the `selfHosted: true` setting when running a local development environment. This tells the system not to use cloud services, assuming that you are running your own local SQL instance. - -**sqlServer__connectionString**: this provides the information required for the Server to connect to the SQL instance. See the example connection string in `secrets.json.example`. You may need to change the default password in the connection string. - -**licenseDirectory**: this must be set to avoid errors, but it can be set to an arbitrary empty folder. - -**installation__key** and **installation__id**: request your own private Installation Id and Installation Key for self-hosting: https://bitwarden.com/host/. - -## Running and Debugging -After you have completed the above steps, you should be ready to launch your development environment for the Api and Identity projects. - -### Visual Studio - -To debug: -* On Windows, right-click on each project > click **Debug** > click **Start New Instance** -* On MacOS, right-click each project > click **Start Debugging Project** - -To run without debugging, open a terminal and navigate to the location of the .csproj file for that project (usually in `src/ProjectName`). Start the project with: - -```bash -dotnet run -``` - -NOTE: check the output of the running project to find the port it is listening on. If this is different to the default in `appsettings.json`, you may need to update your user secrets to override this (typically the Api user secrets for the Identity URL). - -### Rider -From within Rider, launch both the Api project and the Identity project by clicking the "play" button for each project separately. - -### Testing your deployment -* To test the deployment of each project, navigate to the following pages in your browser. You should see server output and no errors: - * Test the Api deployment: http://localhost:4000/alive - * Test the Identity deployment: http://localhost:33656/.well-known/openid-configuration -* If your test was successful, you can connect a GUI client to the dev environment by following the instructions here: [Change your client application's environment](https://bitwarden.com/help/article/change-client-environment/). If you are following this guide, you should only set the API Server URL and Identity Server URL to localhost:port and leave all other fields blank. -* If you are using the CLI client, you will also need to set the Node environment variables for your self-signed certificates by following the instructions here: [The Bitwarden command-line tool (CLI) > Self-signed certificates](https://bitwarden.com/help/article/cli/#self-signed-certificates). - -### Troubleshooting -* If you get a 404 error, the projects may be listening on a non-default port. Check the output of your running projects to check the port they are listening on. - - -# Appendix A (User Secrets) - -### Editing user secrets - Visual Studio on Windows -Right-click on the project in the Solution Explorer and click **Manage User Secrets**. - -### Editing user secrets - Visual Studio on macOS -Open a terminal and navigate to the project directory. Once there, initiate and create the blank user secrets file by running: - -```bash -dotnet user-secrets init -``` - -Add a user secret by running: - -```bash -dotnet user-secrets set "" "" -``` - -View currently set secrets by running: - -```bash -dotnet user-secrets list -``` - -By default, user secret files are located in `~/.microsoft/usersecrets//secrets.json`. After the file has been created, you can edit this directly with VSCode, which is much easier than using the command line tool. - -### Editing user secrets - Rider -* Navigate to **Preferences -> Plugins** and Install .NET Core User Secrets -* Right click on the a project and click **Tools** > **Open project user secrets** diff --git a/bitwarden-server.sln b/bitwarden-server.sln index 410afae94..a8c3e2255 100644 --- a/bitwarden-server.sln +++ b/bitwarden-server.sln @@ -61,18 +61,56 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sso", "bitwarden_license\sr EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Icons.Test", "test\Icons.Test\Icons.Test.csproj", "{C7BA2255-C1B1-4789-8BB9-C27540DA6FB8}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommCore", "bitwarden_license\src\CommCore\CommCore.csproj", "{EDC0D688-D58C-4CE1-AA07-3606AC6874B8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Commercial.Core", "bitwarden_license\src\Commercial.Core\Commercial.Core.csproj", "{EDC0D688-D58C-4CE1-AA07-3606AC6874B8}" ProjectSection(ProjectDependencies) = postProject {3973D21B-A692-4B60-9B70-3631C057423A} = {3973D21B-A692-4B60-9B70-3631C057423A} EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommCore.Test", "bitwarden_license\test\CmmCore.Test\CommCore.Test.csproj", "{0E99A21B-684B-4C59-9831-90F775CAB6F7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Commercial.Core.Test", "bitwarden_license\test\Commercial.Core.Test\Commercial.Core.Test.csproj", "{0E99A21B-684B-4C59-9831-90F775CAB6F7}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test - Bitwarden License", "test - Bitwarden License", "{287CFF34-BBDB-4BC4-AF88-1E19A5A4679B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MySqlMigrations", "util\MySqlMigrations\MySqlMigrations.csproj", "{BDC1D592-5947-47ED-9903-7CDBB12A50C8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MySqlMigrations", "util\MySqlMigrations\MySqlMigrations.csproj", "{BDC1D592-5947-47ED-9903-7CDBB12A50C8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostgresMigrations", "util\PostgresMigrations\PostgresMigrations.csproj", "{F72E0229-2EF7-49B3-9004-FF4C0043816E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PostgresMigrations", "util\PostgresMigrations\PostgresMigrations.csproj", "{F72E0229-2EF7-49B3-9004-FF4C0043816E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common", "test\Common\Common.csproj", "{17DA09D7-0212-4009-879E-6B9CFDE5FA60}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure.Dapper", "src\Infrastructure.Dapper\Infrastructure.Dapper.csproj", "{AD933445-27CE-4D30-A6ED-9065309464AD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharedWeb", "src\SharedWeb\SharedWeb.csproj", "{713D44C0-1BC1-4024-96A3-A98A49F33908}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure.EntityFramework", "src\Infrastructure.EntityFramework\Infrastructure.EntityFramework.csproj", "{ED880735-0250-43C7-9662-FDC7C7416E7F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Billing.Test", "test\Billing.Test\Billing.Test.csproj", "{B8639B10-2157-44BC-8CE1-D9EB4B50971F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity.Test", "test\Identity.Test\Identity.Test.csproj", "{310A1D8E-2D3F-4FA0-84D4-FFE31FCE193E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity.IntegrationTest", "test\Identity.IntegrationTest\Identity.IntegrationTest.csproj", "{0D3B2BD2-53F3-421D-AD8F-C19B954C796B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationTestCommon", "test\IntegrationTestCommon\IntegrationTestCommon.csproj", "{0923DE59-5FB1-44F2-9302-A09D2236B470}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scim", "bitwarden_license\src\Scim\Scim.csproj", "{BC3B3F8C-621A-4CB8-9563-6EC0A2C8C747}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SqlServerEFScaffold", "util\SqlServerEFScaffold\SqlServerEFScaffold.csproj", "{2F2E8BB0-6838-48DA-B581-71B9F13DE364}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commercial.Infrastructure.EntityFramework", "bitwarden_license\src\Commercial.Infrastructure.EntityFramework\Commercial.Infrastructure.EntityFramework.csproj", "{5AB3BBFB-9D98-4EF8-BFCD-462D50A16EB1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure.EFIntegration.Test", "test\Infrastructure.EFIntegration.Test\Infrastructure.EFIntegration.Test.csproj", "{7EFB1124-F40A-40EB-9EDA-94FD540AA8FD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Api.IntegrationTest", "test\Api.IntegrationTest\Api.IntegrationTest.csproj", "{CBE96C6D-A4D6-46E1-94C5-42D6CAD8531C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Scim.IntegrationTest", "bitwarden_license\test\Scim.IntegrationTest\Scim.IntegrationTest.csproj", "{FE998849-5FC8-41A2-B7C9-9227901471A0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "perf", "perf", "{EC2D422A-6060-48E2-AAD2-37220D759F03}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MicroBenchmarks", "perf\MicroBenchmarks\MicroBenchmarks.csproj", "{9C8F8255-5F74-4085-AB9C-9075CF6DDC61}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Scim.Test", "bitwarden_license\test\Scim.Test\Scim.Test.csproj", "{B1595DA3-4C60-41AA-8BF0-499A5F75A885}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure.IntegrationTest", "test\Infrastructure.IntegrationTest\Infrastructure.IntegrationTest.csproj", "{7E9A7DD5-EB78-4AC5-BFD5-64573FD2533B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SqliteMigrations", "util\SqliteMigrations\SqliteMigrations.csproj", "{07143DFA-F242-47A4-A15E-39C9314D4140}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -150,15 +188,6 @@ Global {C7BA2255-C1B1-4789-8BB9-C27540DA6FB8}.Debug|Any CPU.Build.0 = Debug|Any CPU {C7BA2255-C1B1-4789-8BB9-C27540DA6FB8}.Release|Any CPU.ActiveCfg = Release|Any CPU {C7BA2255-C1B1-4789-8BB9-C27540DA6FB8}.Release|Any CPU.Build.0 = Release|Any CPU - {BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Release|Any CPU.Build.0 = Release|Any CPU - {F72E0229-2EF7-49B3-9004-FF4C0043816E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F72E0229-2EF7-49B3-9004-FF4C0043816E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F72E0229-2EF7-49B3-9004-FF4C0043816E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F72E0229-2EF7-49B3-9004-FF4C0043816E}.Release|Any CPU.Build.0 = Release|Any CPU - {EDC0D688-D58C-4CE1-AA07-3606AC6874B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EDC0D688-D58C-4CE1-AA07-3606AC6874B8}.Debug|Any CPU.Build.0 = Debug|Any CPU {EDC0D688-D58C-4CE1-AA07-3606AC6874B8}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -167,6 +196,86 @@ Global {0E99A21B-684B-4C59-9831-90F775CAB6F7}.Debug|Any CPU.Build.0 = Debug|Any CPU {0E99A21B-684B-4C59-9831-90F775CAB6F7}.Release|Any CPU.ActiveCfg = Release|Any CPU {0E99A21B-684B-4C59-9831-90F775CAB6F7}.Release|Any CPU.Build.0 = Release|Any CPU + {BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Release|Any CPU.Build.0 = Release|Any CPU + {F72E0229-2EF7-49B3-9004-FF4C0043816E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F72E0229-2EF7-49B3-9004-FF4C0043816E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F72E0229-2EF7-49B3-9004-FF4C0043816E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F72E0229-2EF7-49B3-9004-FF4C0043816E}.Release|Any CPU.Build.0 = Release|Any CPU + {17DA09D7-0212-4009-879E-6B9CFDE5FA60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {17DA09D7-0212-4009-879E-6B9CFDE5FA60}.Debug|Any CPU.Build.0 = Debug|Any CPU + {17DA09D7-0212-4009-879E-6B9CFDE5FA60}.Release|Any CPU.ActiveCfg = Release|Any CPU + {17DA09D7-0212-4009-879E-6B9CFDE5FA60}.Release|Any CPU.Build.0 = Release|Any CPU + {AD933445-27CE-4D30-A6ED-9065309464AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AD933445-27CE-4D30-A6ED-9065309464AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AD933445-27CE-4D30-A6ED-9065309464AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AD933445-27CE-4D30-A6ED-9065309464AD}.Release|Any CPU.Build.0 = Release|Any CPU + {713D44C0-1BC1-4024-96A3-A98A49F33908}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {713D44C0-1BC1-4024-96A3-A98A49F33908}.Debug|Any CPU.Build.0 = Debug|Any CPU + {713D44C0-1BC1-4024-96A3-A98A49F33908}.Release|Any CPU.ActiveCfg = Release|Any CPU + {713D44C0-1BC1-4024-96A3-A98A49F33908}.Release|Any CPU.Build.0 = Release|Any CPU + {ED880735-0250-43C7-9662-FDC7C7416E7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED880735-0250-43C7-9662-FDC7C7416E7F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED880735-0250-43C7-9662-FDC7C7416E7F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED880735-0250-43C7-9662-FDC7C7416E7F}.Release|Any CPU.Build.0 = Release|Any CPU + {B8639B10-2157-44BC-8CE1-D9EB4B50971F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B8639B10-2157-44BC-8CE1-D9EB4B50971F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B8639B10-2157-44BC-8CE1-D9EB4B50971F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B8639B10-2157-44BC-8CE1-D9EB4B50971F}.Release|Any CPU.Build.0 = Release|Any CPU + {310A1D8E-2D3F-4FA0-84D4-FFE31FCE193E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {310A1D8E-2D3F-4FA0-84D4-FFE31FCE193E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {310A1D8E-2D3F-4FA0-84D4-FFE31FCE193E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {310A1D8E-2D3F-4FA0-84D4-FFE31FCE193E}.Release|Any CPU.Build.0 = Release|Any CPU + {0D3B2BD2-53F3-421D-AD8F-C19B954C796B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0D3B2BD2-53F3-421D-AD8F-C19B954C796B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0D3B2BD2-53F3-421D-AD8F-C19B954C796B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0D3B2BD2-53F3-421D-AD8F-C19B954C796B}.Release|Any CPU.Build.0 = Release|Any CPU + {0923DE59-5FB1-44F2-9302-A09D2236B470}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0923DE59-5FB1-44F2-9302-A09D2236B470}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0923DE59-5FB1-44F2-9302-A09D2236B470}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0923DE59-5FB1-44F2-9302-A09D2236B470}.Release|Any CPU.Build.0 = Release|Any CPU + {BC3B3F8C-621A-4CB8-9563-6EC0A2C8C747}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC3B3F8C-621A-4CB8-9563-6EC0A2C8C747}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC3B3F8C-621A-4CB8-9563-6EC0A2C8C747}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC3B3F8C-621A-4CB8-9563-6EC0A2C8C747}.Release|Any CPU.Build.0 = Release|Any CPU + {2F2E8BB0-6838-48DA-B581-71B9F13DE364}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F2E8BB0-6838-48DA-B581-71B9F13DE364}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F2E8BB0-6838-48DA-B581-71B9F13DE364}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F2E8BB0-6838-48DA-B581-71B9F13DE364}.Release|Any CPU.Build.0 = Release|Any CPU + {5AB3BBFB-9D98-4EF8-BFCD-462D50A16EB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5AB3BBFB-9D98-4EF8-BFCD-462D50A16EB1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5AB3BBFB-9D98-4EF8-BFCD-462D50A16EB1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5AB3BBFB-9D98-4EF8-BFCD-462D50A16EB1}.Release|Any CPU.Build.0 = Release|Any CPU + {7EFB1124-F40A-40EB-9EDA-94FD540AA8FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7EFB1124-F40A-40EB-9EDA-94FD540AA8FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7EFB1124-F40A-40EB-9EDA-94FD540AA8FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7EFB1124-F40A-40EB-9EDA-94FD540AA8FD}.Release|Any CPU.Build.0 = Release|Any CPU + {CBE96C6D-A4D6-46E1-94C5-42D6CAD8531C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CBE96C6D-A4D6-46E1-94C5-42D6CAD8531C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CBE96C6D-A4D6-46E1-94C5-42D6CAD8531C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CBE96C6D-A4D6-46E1-94C5-42D6CAD8531C}.Release|Any CPU.Build.0 = Release|Any CPU + {FE998849-5FC8-41A2-B7C9-9227901471A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FE998849-5FC8-41A2-B7C9-9227901471A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FE998849-5FC8-41A2-B7C9-9227901471A0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FE998849-5FC8-41A2-B7C9-9227901471A0}.Release|Any CPU.Build.0 = Release|Any CPU + {9C8F8255-5F74-4085-AB9C-9075CF6DDC61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C8F8255-5F74-4085-AB9C-9075CF6DDC61}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C8F8255-5F74-4085-AB9C-9075CF6DDC61}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C8F8255-5F74-4085-AB9C-9075CF6DDC61}.Release|Any CPU.Build.0 = Release|Any CPU + {B1595DA3-4C60-41AA-8BF0-499A5F75A885}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B1595DA3-4C60-41AA-8BF0-499A5F75A885}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B1595DA3-4C60-41AA-8BF0-499A5F75A885}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B1595DA3-4C60-41AA-8BF0-499A5F75A885}.Release|Any CPU.Build.0 = Release|Any CPU + {7E9A7DD5-EB78-4AC5-BFD5-64573FD2533B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7E9A7DD5-EB78-4AC5-BFD5-64573FD2533B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E9A7DD5-EB78-4AC5-BFD5-64573FD2533B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7E9A7DD5-EB78-4AC5-BFD5-64573FD2533B}.Release|Any CPU.Build.0 = Release|Any CPU + {07143DFA-F242-47A4-A15E-39C9314D4140}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07143DFA-F242-47A4-A15E-39C9314D4140}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07143DFA-F242-47A4-A15E-39C9314D4140}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07143DFA-F242-47A4-A15E-39C9314D4140}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -189,10 +298,28 @@ Global {860DE301-0B3E-4717-9C21-A9B4C3C2B121} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} {4866AF64-6640-4C65-A662-A31E02FF9064} = {4FDB6543-F68B-4202-9EA6-7FEA984D2D0A} {C7BA2255-C1B1-4789-8BB9-C27540DA6FB8} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} - {BDC1D592-5947-47ED-9903-7CDBB12A50C8} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E} - {F72E0229-2EF7-49B3-9004-FF4C0043816E} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E} {EDC0D688-D58C-4CE1-AA07-3606AC6874B8} = {4FDB6543-F68B-4202-9EA6-7FEA984D2D0A} {0E99A21B-684B-4C59-9831-90F775CAB6F7} = {287CFF34-BBDB-4BC4-AF88-1E19A5A4679B} + {BDC1D592-5947-47ED-9903-7CDBB12A50C8} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E} + {F72E0229-2EF7-49B3-9004-FF4C0043816E} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E} + {17DA09D7-0212-4009-879E-6B9CFDE5FA60} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} + {AD933445-27CE-4D30-A6ED-9065309464AD} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D} + {713D44C0-1BC1-4024-96A3-A98A49F33908} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D} + {ED880735-0250-43C7-9662-FDC7C7416E7F} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D} + {B8639B10-2157-44BC-8CE1-D9EB4B50971F} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} + {310A1D8E-2D3F-4FA0-84D4-FFE31FCE193E} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} + {0D3B2BD2-53F3-421D-AD8F-C19B954C796B} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} + {0923DE59-5FB1-44F2-9302-A09D2236B470} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} + {BC3B3F8C-621A-4CB8-9563-6EC0A2C8C747} = {4FDB6543-F68B-4202-9EA6-7FEA984D2D0A} + {2F2E8BB0-6838-48DA-B581-71B9F13DE364} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E} + {5AB3BBFB-9D98-4EF8-BFCD-462D50A16EB1} = {4FDB6543-F68B-4202-9EA6-7FEA984D2D0A} + {7EFB1124-F40A-40EB-9EDA-94FD540AA8FD} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} + {CBE96C6D-A4D6-46E1-94C5-42D6CAD8531C} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} + {FE998849-5FC8-41A2-B7C9-9227901471A0} = {287CFF34-BBDB-4BC4-AF88-1E19A5A4679B} + {9C8F8255-5F74-4085-AB9C-9075CF6DDC61} = {EC2D422A-6060-48E2-AAD2-37220D759F03} + {B1595DA3-4C60-41AA-8BF0-499A5F75A885} = {287CFF34-BBDB-4BC4-AF88-1E19A5A4679B} + {7E9A7DD5-EB78-4AC5-BFD5-64573FD2533B} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} + {07143DFA-F242-47A4-A15E-39C9314D4140} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E01CBF68-2E20-425F-9EDB-E0A6510CA92F} diff --git a/bitwarden_license/src/CommCore/Services/ProviderService.cs b/bitwarden_license/src/CommCore/Services/ProviderService.cs deleted file mode 100644 index 9bc513ece..000000000 --- a/bitwarden_license/src/CommCore/Services/ProviderService.cs +++ /dev/null @@ -1,513 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Bit.Core.Context; -using Bit.Core.Enums; -using Bit.Core.Enums.Provider; -using Bit.Core.Exceptions; -using Bit.Core.Models.Business; -using Bit.Core.Models.Business.Provider; -using Bit.Core.Models.Data; -using Bit.Core.Models.Table; -using Bit.Core.Models.Table.Provider; -using Bit.Core.Repositories; -using Bit.Core.Services; -using Bit.Core.Settings; -using Bit.Core.Utilities; -using Microsoft.AspNetCore.DataProtection; - -namespace Bit.CommCore.Services -{ - public class ProviderService : IProviderService - { - public static PlanType[] ProviderDisllowedOrganizationTypes = new[] { PlanType.Free, PlanType.FamiliesAnnually, PlanType.FamiliesAnnually2019 }; - - private readonly IDataProtector _dataProtector; - private readonly IMailService _mailService; - private readonly IEventService _eventService; - private readonly GlobalSettings _globalSettings; - private readonly IProviderRepository _providerRepository; - private readonly IProviderUserRepository _providerUserRepository; - private readonly IProviderOrganizationRepository _providerOrganizationRepository; - private readonly IOrganizationRepository _organizationRepository; - private readonly IUserRepository _userRepository; - private readonly IUserService _userService; - private readonly IOrganizationService _organizationService; - private readonly ICurrentContext _currentContext; - - public ProviderService(IProviderRepository providerRepository, IProviderUserRepository providerUserRepository, - IProviderOrganizationRepository providerOrganizationRepository, IUserRepository userRepository, - IUserService userService, IOrganizationService organizationService, IMailService mailService, - IDataProtectionProvider dataProtectionProvider, IEventService eventService, - IOrganizationRepository organizationRepository, GlobalSettings globalSettings, - ICurrentContext currentContext) - { - _providerRepository = providerRepository; - _providerUserRepository = providerUserRepository; - _providerOrganizationRepository = providerOrganizationRepository; - _organizationRepository = organizationRepository; - _userRepository = userRepository; - _userService = userService; - _organizationService = organizationService; - _mailService = mailService; - _eventService = eventService; - _globalSettings = globalSettings; - _dataProtector = dataProtectionProvider.CreateProtector("ProviderServiceDataProtector"); - _currentContext = currentContext; - } - - public async Task CreateAsync(string ownerEmail) - { - var owner = await _userRepository.GetByEmailAsync(ownerEmail); - if (owner == null) - { - throw new BadRequestException("Invalid owner. Owner must be an existing Bitwarden user."); - } - - var provider = new Provider - { - Status = ProviderStatusType.Pending, - Enabled = true, - UseEvents = true, - }; - await _providerRepository.CreateAsync(provider); - - var providerUser = new ProviderUser - { - ProviderId = provider.Id, - UserId = owner.Id, - Type = ProviderUserType.ProviderAdmin, - Status = ProviderUserStatusType.Confirmed, - }; - await _providerUserRepository.CreateAsync(providerUser); - await SendProviderSetupInviteEmailAsync(provider, owner.Email); - } - - public async Task CompleteSetupAsync(Provider provider, Guid ownerUserId, string token, string key) - { - var owner = await _userService.GetUserByIdAsync(ownerUserId); - if (owner == null) - { - throw new BadRequestException("Invalid owner."); - } - - if (provider.Status != ProviderStatusType.Pending) - { - throw new BadRequestException("Provider is already setup."); - } - - if (!CoreHelpers.TokenIsValid("ProviderSetupInvite", _dataProtector, token, owner.Email, provider.Id, - _globalSettings.OrganizationInviteExpirationHours)) - { - throw new BadRequestException("Invalid token."); - } - - var providerUser = await _providerUserRepository.GetByProviderUserAsync(provider.Id, ownerUserId); - if (!(providerUser is { Type: ProviderUserType.ProviderAdmin })) - { - throw new BadRequestException("Invalid owner."); - } - - provider.Status = ProviderStatusType.Created; - await _providerRepository.UpsertAsync(provider); - - providerUser.Key = key; - await _providerUserRepository.ReplaceAsync(providerUser); - - return provider; - } - - public async Task UpdateAsync(Provider provider, bool updateBilling = false) - { - if (provider.Id == default) - { - throw new ArgumentException("Cannot create provider this way."); - } - - await _providerRepository.ReplaceAsync(provider); - } - - public async Task> InviteUserAsync(ProviderUserInvite invite) - { - if (!_currentContext.ProviderManageUsers(invite.ProviderId)) - { - throw new InvalidOperationException("Invalid permissions."); - } - - var emails = invite?.UserIdentifiers; - var invitingUser = await _providerUserRepository.GetByProviderUserAsync(invite.ProviderId, invite.InvitingUserId); - - var provider = await _providerRepository.GetByIdAsync(invite.ProviderId); - if (provider == null || emails == null || !emails.Any()) - { - throw new NotFoundException(); - } - - var providerUsers = new List(); - foreach (var email in emails) - { - // Make sure user is not already invited - var existingProviderUserCount = - await _providerUserRepository.GetCountByProviderAsync(invite.ProviderId, email, false); - if (existingProviderUserCount > 0) - { - continue; - } - - var providerUser = new ProviderUser - { - ProviderId = invite.ProviderId, - UserId = null, - Email = email.ToLowerInvariant(), - Key = null, - Type = invite.Type, - Status = ProviderUserStatusType.Invited, - CreationDate = DateTime.UtcNow, - RevisionDate = DateTime.UtcNow, - }; - - await _providerUserRepository.CreateAsync(providerUser); - - await SendInviteAsync(providerUser, provider); - providerUsers.Add(providerUser); - } - - await _eventService.LogProviderUsersEventAsync(providerUsers.Select(pu => (pu, EventType.ProviderUser_Invited, null as DateTime?))); - - return providerUsers; - } - - public async Task>> ResendInvitesAsync(ProviderUserInvite invite) - { - if (!_currentContext.ProviderManageUsers(invite.ProviderId)) - { - throw new BadRequestException("Invalid permissions."); - } - - var providerUsers = await _providerUserRepository.GetManyAsync(invite.UserIdentifiers); - var provider = await _providerRepository.GetByIdAsync(invite.ProviderId); - - var result = new List>(); - foreach (var providerUser in providerUsers) - { - if (providerUser.Status != ProviderUserStatusType.Invited || providerUser.ProviderId != invite.ProviderId) - { - result.Add(Tuple.Create(providerUser, "User invalid.")); - continue; - } - - await SendInviteAsync(providerUser, provider); - result.Add(Tuple.Create(providerUser, "")); - } - - return result; - } - - public async Task AcceptUserAsync(Guid providerUserId, User user, string token) - { - var providerUser = await _providerUserRepository.GetByIdAsync(providerUserId); - if (providerUser == null) - { - throw new BadRequestException("User invalid."); - } - - if (providerUser.Status != ProviderUserStatusType.Invited) - { - throw new BadRequestException("Already accepted."); - } - - if (!CoreHelpers.TokenIsValid("ProviderUserInvite", _dataProtector, token, user.Email, providerUser.Id, - _globalSettings.OrganizationInviteExpirationHours)) - { - throw new BadRequestException("Invalid token."); - } - - if (string.IsNullOrWhiteSpace(providerUser.Email) || - !providerUser.Email.Equals(user.Email, StringComparison.InvariantCultureIgnoreCase)) - { - throw new BadRequestException("User email does not match invite."); - } - - providerUser.Status = ProviderUserStatusType.Accepted; - providerUser.UserId = user.Id; - providerUser.Email = null; - - await _providerUserRepository.ReplaceAsync(providerUser); - - return providerUser; - } - - public async Task>> ConfirmUsersAsync(Guid providerId, Dictionary keys, - Guid confirmingUserId) - { - var providerUsers = await _providerUserRepository.GetManyAsync(keys.Keys); - var validProviderUsers = providerUsers - .Where(u => u.UserId != null) - .ToList(); - - if (!validProviderUsers.Any()) - { - return new List>(); - } - - var validOrganizationUserIds = validProviderUsers.Select(u => u.UserId.Value).ToList(); - - var provider = await _providerRepository.GetByIdAsync(providerId); - var users = await _userRepository.GetManyAsync(validOrganizationUserIds); - - var keyedFilteredUsers = validProviderUsers.ToDictionary(u => u.UserId.Value, u => u); - - var result = new List>(); - var events = new List<(ProviderUser, EventType, DateTime?)>(); - - foreach (var user in users) - { - if (!keyedFilteredUsers.ContainsKey(user.Id)) - { - continue; - } - var providerUser = keyedFilteredUsers[user.Id]; - try - { - if (providerUser.Status != ProviderUserStatusType.Accepted || providerUser.ProviderId != providerId) - { - throw new BadRequestException("Invalid user."); - } - - providerUser.Status = ProviderUserStatusType.Confirmed; - providerUser.Key = keys[providerUser.Id]; - providerUser.Email = null; - - await _providerUserRepository.ReplaceAsync(providerUser); - events.Add((providerUser, EventType.ProviderUser_Confirmed, null)); - await _mailService.SendProviderConfirmedEmailAsync(provider.Name, user.Email); - result.Add(Tuple.Create(providerUser, "")); - } - catch (BadRequestException e) - { - result.Add(Tuple.Create(providerUser, e.Message)); - } - } - - await _eventService.LogProviderUsersEventAsync(events); - - return result; - } - - public async Task SaveUserAsync(ProviderUser user, Guid savingUserId) - { - if (user.Id.Equals(default)) - { - throw new BadRequestException("Invite the user first."); - } - - if (user.Type != ProviderUserType.ProviderAdmin && - !await HasConfirmedProviderAdminExceptAsync(user.ProviderId, new[] { user.Id })) - { - throw new BadRequestException("Provider must have at least one confirmed ProviderAdmin."); - } - - await _providerUserRepository.ReplaceAsync(user); - await _eventService.LogProviderUserEventAsync(user, EventType.ProviderUser_Updated); - } - - public async Task>> DeleteUsersAsync(Guid providerId, - IEnumerable providerUserIds, Guid deletingUserId) - { - var provider = await _providerRepository.GetByIdAsync(providerId); - - if (provider == null) - { - throw new NotFoundException(); - } - - var providerUsers = await _providerUserRepository.GetManyAsync(providerUserIds); - var users = await _userRepository.GetManyAsync(providerUsers.Where(pu => pu.UserId.HasValue) - .Select(pu => pu.UserId.Value)); - var keyedUsers = users.ToDictionary(u => u.Id); - - if (!await HasConfirmedProviderAdminExceptAsync(providerId, providerUserIds)) - { - throw new BadRequestException("Provider must have at least one confirmed ProviderAdmin."); - } - - var result = new List>(); - var deletedUserIds = new List(); - var events = new List<(ProviderUser, EventType, DateTime?)>(); - - foreach (var providerUser in providerUsers) - { - try - { - if (providerUser.ProviderId != providerId) - { - throw new BadRequestException("Invalid user."); - } - if (providerUser.UserId == deletingUserId) - { - throw new BadRequestException("You cannot remove yourself."); - } - - events.Add((providerUser, EventType.ProviderUser_Removed, null)); - - var user = keyedUsers.GetValueOrDefault(providerUser.UserId.GetValueOrDefault()); - var email = user == null ? providerUser.Email : user.Email; - if (!string.IsNullOrWhiteSpace(email)) - { - await _mailService.SendProviderUserRemoved(provider.Name, email); - } - - result.Add(Tuple.Create(providerUser, "")); - deletedUserIds.Add(providerUser.Id); - } - catch (BadRequestException e) - { - result.Add(Tuple.Create(providerUser, e.Message)); - } - - await _providerUserRepository.DeleteManyAsync(deletedUserIds); - } - - await _eventService.LogProviderUsersEventAsync(events); - - return result; - } - - public async Task AddOrganization(Guid providerId, Guid organizationId, Guid addingUserId, string key) - { - var po = await _providerOrganizationRepository.GetByOrganizationId(organizationId); - if (po != null) - { - throw new BadRequestException("Organization already belongs to a provider."); - } - - var organization = await _organizationRepository.GetByIdAsync(organizationId); - ThrowOnInvalidPlanType(organization.PlanType); - - var providerOrganization = new ProviderOrganization - { - ProviderId = providerId, - OrganizationId = organizationId, - Key = key, - }; - - await _providerOrganizationRepository.CreateAsync(providerOrganization); - await _eventService.LogProviderOrganizationEventAsync(providerOrganization, EventType.ProviderOrganization_Added); - } - - public async Task CreateOrganizationAsync(Guid providerId, - OrganizationSignup organizationSignup, string clientOwnerEmail, User user) - { - ThrowOnInvalidPlanType(organizationSignup.Plan); - - var (organization, _) = await _organizationService.SignUpAsync(organizationSignup, true); - - var providerOrganization = new ProviderOrganization - { - ProviderId = providerId, - OrganizationId = organization.Id, - Key = organizationSignup.OwnerKey, - }; - - await _providerOrganizationRepository.CreateAsync(providerOrganization); - await _eventService.LogProviderOrganizationEventAsync(providerOrganization, EventType.ProviderOrganization_Created); - - await _organizationService.InviteUsersAsync(organization.Id, user.Id, - new (OrganizationUserInvite, string)[] - { - ( - new OrganizationUserInvite - { - Emails = new[] { clientOwnerEmail }, - AccessAll = true, - Type = OrganizationUserType.Owner, - Permissions = null, - Collections = Array.Empty(), - }, - null - ) - }); - - return providerOrganization; - } - - public async Task RemoveOrganizationAsync(Guid providerId, Guid providerOrganizationId, Guid removingUserId) - { - var providerOrganization = await _providerOrganizationRepository.GetByIdAsync(providerOrganizationId); - if (providerOrganization == null || providerOrganization.ProviderId != providerId) - { - throw new BadRequestException("Invalid organization."); - } - - if (!await _organizationService.HasConfirmedOwnersExceptAsync(providerOrganization.OrganizationId, new Guid[] { }, includeProvider: false)) - { - throw new BadRequestException("Organization needs to have at least one confirmed owner."); - } - - await _providerOrganizationRepository.DeleteAsync(providerOrganization); - await _eventService.LogProviderOrganizationEventAsync(providerOrganization, EventType.ProviderOrganization_Removed); - } - - public async Task ResendProviderSetupInviteEmailAsync(Guid providerId, Guid ownerId) - { - var provider = await _providerRepository.GetByIdAsync(providerId); - var owner = await _userRepository.GetByIdAsync(ownerId); - if (owner == null) - { - throw new BadRequestException("Invalid owner."); - } - await SendProviderSetupInviteEmailAsync(provider, owner.Email); - } - - private async Task SendProviderSetupInviteEmailAsync(Provider provider, string ownerEmail) - { - var token = _dataProtector.Protect($"ProviderSetupInvite {provider.Id} {ownerEmail} {CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow)}"); - await _mailService.SendProviderSetupInviteEmailAsync(provider, token, ownerEmail); - } - - public async Task LogProviderAccessToOrganizationAsync(Guid organizationId) - { - if (organizationId == default) - { - return; - } - - var providerOrganization = await _providerOrganizationRepository.GetByOrganizationId(organizationId); - var organization = await _organizationRepository.GetByIdAsync(organizationId); - if (providerOrganization != null) - { - await _eventService.LogProviderOrganizationEventAsync(providerOrganization, EventType.ProviderOrganization_VaultAccessed); - } - if (organization != null) - { - await _eventService.LogOrganizationEventAsync(organization, EventType.Organization_VaultAccessed); - } - } - - private async Task SendInviteAsync(ProviderUser providerUser, Provider provider) - { - var nowMillis = CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow); - var token = _dataProtector.Protect( - $"ProviderUserInvite {providerUser.Id} {providerUser.Email} {nowMillis}"); - await _mailService.SendProviderInviteEmailAsync(provider.Name, providerUser, token, providerUser.Email); - } - - private async Task HasConfirmedProviderAdminExceptAsync(Guid providerId, IEnumerable providerUserIds) - { - var providerAdmins = await _providerUserRepository.GetManyByProviderAsync(providerId, - ProviderUserType.ProviderAdmin); - var confirmedOwners = providerAdmins.Where(o => o.Status == ProviderUserStatusType.Confirmed); - var confirmedOwnersIds = confirmedOwners.Select(u => u.Id); - return confirmedOwnersIds.Except(providerUserIds).Any(); - } - - private void ThrowOnInvalidPlanType(PlanType requestedType) - { - if (ProviderDisllowedOrganizationTypes.Contains(requestedType)) - { - throw new BadRequestException($"Providers cannot manage organizations with the requested plan type ({requestedType}). Only Teams and Enterprise accounts are allowed."); - } - } - } -} diff --git a/bitwarden_license/src/CommCore/Utilities/ServiceCollectionExtensions.cs b/bitwarden_license/src/CommCore/Utilities/ServiceCollectionExtensions.cs deleted file mode 100644 index bd8447120..000000000 --- a/bitwarden_license/src/CommCore/Utilities/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Bit.CommCore.Services; -using Bit.Core.Services; -using Microsoft.Extensions.DependencyInjection; - -namespace Bit.CommCore.Utilities -{ - public static class ServiceCollectionExtensions - { - public static void AddCommCoreServices(this IServiceCollection services) - { - services.AddScoped(); - } - } -} diff --git a/bitwarden_license/src/CommCore/CommCore.csproj b/bitwarden_license/src/Commercial.Core/Commercial.Core.csproj similarity index 62% rename from bitwarden_license/src/CommCore/CommCore.csproj rename to bitwarden_license/src/Commercial.Core/Commercial.Core.csproj index a562ebbe9..dfc63666d 100644 --- a/bitwarden_license/src/CommCore/CommCore.csproj +++ b/bitwarden_license/src/Commercial.Core/Commercial.Core.csproj @@ -1,9 +1,5 @@ - - net5.0 - - diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/CreateAccessPoliciesCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/CreateAccessPoliciesCommand.cs new file mode 100644 index 000000000..05af497e6 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/CreateAccessPoliciesCommand.cs @@ -0,0 +1,45 @@ +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; + +namespace Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies; + +public class CreateAccessPoliciesCommand : ICreateAccessPoliciesCommand +{ + private readonly IAccessPolicyRepository _accessPolicyRepository; + + public CreateAccessPoliciesCommand(IAccessPolicyRepository accessPolicyRepository) + { + _accessPolicyRepository = accessPolicyRepository; + } + + public async Task> CreateAsync(List accessPolicies) + { + var distinctAccessPolicies = accessPolicies.DistinctBy(baseAccessPolicy => + { + return baseAccessPolicy switch + { + UserProjectAccessPolicy ap => new Tuple(ap.OrganizationUserId, ap.GrantedProjectId), + GroupProjectAccessPolicy ap => new Tuple(ap.GroupId, ap.GrantedProjectId), + ServiceAccountProjectAccessPolicy ap => new Tuple(ap.ServiceAccountId, ap.GrantedProjectId), + _ => throw new ArgumentException("Unsupported access policy type provided.", nameof(baseAccessPolicy)) + }; + }).ToList(); + + if (accessPolicies.Count != distinctAccessPolicies.Count) + { + throw new BadRequestException("Resources must be unique"); + } + + foreach (var accessPolicy in accessPolicies) + { + if (await _accessPolicyRepository.AccessPolicyExists(accessPolicy)) + { + throw new BadRequestException("Resource already exists"); + } + } + + return await _accessPolicyRepository.CreateManyAsync(accessPolicies); + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/DeleteAccessPolicyCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/DeleteAccessPolicyCommand.cs new file mode 100644 index 000000000..0795d6290 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/DeleteAccessPolicyCommand.cs @@ -0,0 +1,27 @@ +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces; +using Bit.Core.SecretsManager.Repositories; + +namespace Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies; + +public class DeleteAccessPolicyCommand : IDeleteAccessPolicyCommand +{ + private readonly IAccessPolicyRepository _accessPolicyRepository; + + public DeleteAccessPolicyCommand(IAccessPolicyRepository accessPolicyRepository) + { + _accessPolicyRepository = accessPolicyRepository; + } + + + public async Task DeleteAsync(Guid id) + { + var accessPolicy = await _accessPolicyRepository.GetByIdAsync(id); + if (accessPolicy == null) + { + throw new NotFoundException(); + } + + await _accessPolicyRepository.DeleteAsync(id); + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/UpdateAccessPolicyCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/UpdateAccessPolicyCommand.cs new file mode 100644 index 000000000..b7ebd1706 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessPolicies/UpdateAccessPolicyCommand.cs @@ -0,0 +1,32 @@ +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; + +namespace Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies; + +public class UpdateAccessPolicyCommand : IUpdateAccessPolicyCommand +{ + private readonly IAccessPolicyRepository _accessPolicyRepository; + + public UpdateAccessPolicyCommand(IAccessPolicyRepository accessPolicyRepository) + { + _accessPolicyRepository = accessPolicyRepository; + } + + public async Task UpdateAsync(Guid id, bool read, bool write) + { + var accessPolicy = await _accessPolicyRepository.GetByIdAsync(id); + if (accessPolicy == null) + { + throw new NotFoundException(); + } + + accessPolicy.Read = read; + accessPolicy.Write = write; + accessPolicy.RevisionDate = DateTime.UtcNow; + + await _accessPolicyRepository.ReplaceAsync(accessPolicy); + return accessPolicy; + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessTokens/CreateAccessTokenCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessTokens/CreateAccessTokenCommand.cs new file mode 100644 index 000000000..e8d179e79 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessTokens/CreateAccessTokenCommand.cs @@ -0,0 +1,55 @@ +using Bit.Core.Context; +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Commands.AccessTokens.Interfaces; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; +using Bit.Core.Utilities; + +namespace Bit.Commercial.Core.SecretsManager.Commands.AccessTokens; + +public class CreateAccessTokenCommand : ICreateAccessTokenCommand +{ + private readonly IApiKeyRepository _apiKeyRepository; + private readonly int _clientSecretMaxLength = 30; + private readonly ICurrentContext _currentContext; + private readonly IServiceAccountRepository _serviceAccountRepository; + + public CreateAccessTokenCommand( + IApiKeyRepository apiKeyRepository, + ICurrentContext currentContext, + IServiceAccountRepository serviceAccountRepository) + { + _apiKeyRepository = apiKeyRepository; + _currentContext = currentContext; + _serviceAccountRepository = serviceAccountRepository; + } + + public async Task CreateAsync(ApiKey apiKey, Guid userId) + { + if (apiKey.ServiceAccountId == null) + { + throw new BadRequestException(); + } + + var serviceAccount = await _serviceAccountRepository.GetByIdAsync(apiKey.ServiceAccountId.Value); + var orgAdmin = await _currentContext.OrganizationAdmin(serviceAccount.OrganizationId); + var accessClient = AccessClientHelper.ToAccessClient(_currentContext.ClientType, orgAdmin); + + var hasAccess = accessClient switch + { + AccessClientType.NoAccessCheck => true, + AccessClientType.User => await _serviceAccountRepository.UserHasWriteAccessToServiceAccount( + apiKey.ServiceAccountId.Value, userId), + _ => false, + }; + + if (!hasAccess) + { + throw new UnauthorizedAccessException(); + } + + apiKey.ClientSecret = CoreHelpers.SecureRandomString(_clientSecretMaxLength); + return await _apiKeyRepository.CreateAsync(apiKey); + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/CreateProjectCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/CreateProjectCommand.cs new file mode 100644 index 000000000..6e86088dc --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/CreateProjectCommand.cs @@ -0,0 +1,20 @@ +using Bit.Core.SecretsManager.Commands.Projects.Interfaces; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; + +namespace Bit.Commercial.Core.SecretsManager.Commands.Projects; + +public class CreateProjectCommand : ICreateProjectCommand +{ + private readonly IProjectRepository _projectRepository; + + public CreateProjectCommand(IProjectRepository projectRepository) + { + _projectRepository = projectRepository; + } + + public async Task CreateAsync(Project project) + { + return await _projectRepository.CreateAsync(project); + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/DeleteProjectCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/DeleteProjectCommand.cs new file mode 100644 index 000000000..8451f1d40 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/DeleteProjectCommand.cs @@ -0,0 +1,75 @@ +using Bit.Core.Context; +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Commands.Projects.Interfaces; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; + +namespace Bit.Commercial.Core.SecretsManager.Commands.Projects; + +public class DeleteProjectCommand : IDeleteProjectCommand +{ + private readonly IProjectRepository _projectRepository; + private readonly ICurrentContext _currentContext; + + public DeleteProjectCommand(IProjectRepository projectRepository, ICurrentContext currentContext) + { + _projectRepository = projectRepository; + _currentContext = currentContext; + } + + public async Task>> DeleteProjects(List ids, Guid userId) + { + if (ids.Any() != true || userId == new Guid()) + { + throw new ArgumentNullException(); + } + + var projects = (await _projectRepository.GetManyByIds(ids))?.ToList(); + + if (projects?.Any() != true || projects.Count != ids.Count) + { + throw new NotFoundException(); + } + + // Ensure all projects belongs to the same organization + var organizationId = projects.First().OrganizationId; + if (projects.Any(p => p.OrganizationId != organizationId)) + { + throw new UnauthorizedAccessException(); + } + + var orgAdmin = await _currentContext.OrganizationAdmin(organizationId); + var accessClient = AccessClientHelper.ToAccessClient(_currentContext.ClientType, orgAdmin); + + var results = new List>(projects.Count); + var deleteIds = new List(); + + foreach (var project in projects) + { + var hasAccess = accessClient switch + { + AccessClientType.NoAccessCheck => true, + AccessClientType.User => await _projectRepository.UserHasWriteAccessToProject(project.Id, userId), + _ => false, + }; + + if (!hasAccess) + { + results.Add(new Tuple(project, "access denied")); + } + else + { + results.Add(new Tuple(project, "")); + deleteIds.Add(project.Id); + } + } + + if (deleteIds.Count > 0) + { + await _projectRepository.DeleteManyByIdAsync(deleteIds); + } + return results; + } +} + diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/UpdateProjectCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/UpdateProjectCommand.cs new file mode 100644 index 000000000..74799547a --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Projects/UpdateProjectCommand.cs @@ -0,0 +1,50 @@ +using Bit.Core.Context; +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Commands.Projects.Interfaces; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; + +namespace Bit.Commercial.Core.SecretsManager.Commands.Projects; + +public class UpdateProjectCommand : IUpdateProjectCommand +{ + private readonly IProjectRepository _projectRepository; + private readonly ICurrentContext _currentContext; + + public UpdateProjectCommand(IProjectRepository projectRepository, ICurrentContext currentContext) + { + _projectRepository = projectRepository; + _currentContext = currentContext; + } + + public async Task UpdateAsync(Project updatedProject, Guid userId) + { + var project = await _projectRepository.GetByIdAsync(updatedProject.Id); + if (project == null) + { + throw new NotFoundException(); + } + + var orgAdmin = await _currentContext.OrganizationAdmin(project.OrganizationId); + var accessClient = AccessClientHelper.ToAccessClient(_currentContext.ClientType, orgAdmin); + + var hasAccess = accessClient switch + { + AccessClientType.NoAccessCheck => true, + AccessClientType.User => await _projectRepository.UserHasWriteAccessToProject(updatedProject.Id, userId), + _ => false, + }; + + if (!hasAccess) + { + throw new UnauthorizedAccessException(); + } + + project.Name = updatedProject.Name; + project.RevisionDate = DateTime.UtcNow; + + await _projectRepository.ReplaceAsync(project); + return project; + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/CreateSecretCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/CreateSecretCommand.cs new file mode 100644 index 000000000..d224247c1 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/CreateSecretCommand.cs @@ -0,0 +1,20 @@ +using Bit.Core.SecretsManager.Commands.Secrets.Interfaces; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; + +namespace Bit.Commercial.Core.SecretsManager.Commands.Secrets; + +public class CreateSecretCommand : ICreateSecretCommand +{ + private readonly ISecretRepository _secretRepository; + + public CreateSecretCommand(ISecretRepository secretRepository) + { + _secretRepository = secretRepository; + } + + public async Task CreateAsync(Secret secret) + { + return await _secretRepository.CreateAsync(secret); + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/DeleteSecretCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/DeleteSecretCommand.cs new file mode 100644 index 000000000..b04a8f911 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/DeleteSecretCommand.cs @@ -0,0 +1,44 @@ +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Commands.Secrets.Interfaces; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; + +namespace Bit.Commercial.Core.SecretsManager.Commands.Secrets; + +public class DeleteSecretCommand : IDeleteSecretCommand +{ + private readonly ISecretRepository _secretRepository; + + public DeleteSecretCommand(ISecretRepository secretRepository) + { + _secretRepository = secretRepository; + } + + public async Task>> DeleteSecrets(List ids) + { + var secrets = await _secretRepository.GetManyByIds(ids); + + if (secrets?.Any() != true) + { + throw new NotFoundException(); + } + + var results = ids.Select(id => + { + var secret = secrets.FirstOrDefault(secret => secret.Id == id); + if (secret == null) + { + throw new NotFoundException(); + } + // TODO Once permissions are implemented add check for each secret here. + else + { + return new Tuple(secret, ""); + } + }).ToList(); + + await _secretRepository.SoftDeleteManyByIdAsync(ids); + return results; + } +} + diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/UpdateSecretCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/UpdateSecretCommand.cs new file mode 100644 index 000000000..4bd0cf4f3 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/Secrets/UpdateSecretCommand.cs @@ -0,0 +1,33 @@ +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Commands.Secrets.Interfaces; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; + +namespace Bit.Commercial.Core.SecretsManager.Commands.Secrets; + +public class UpdateSecretCommand : IUpdateSecretCommand +{ + private readonly ISecretRepository _secretRepository; + + public UpdateSecretCommand(ISecretRepository secretRepository) + { + _secretRepository = secretRepository; + } + + public async Task UpdateAsync(Secret secret) + { + var existingSecret = await _secretRepository.GetByIdAsync(secret.Id); + if (existingSecret == null) + { + throw new NotFoundException(); + } + + secret.OrganizationId = existingSecret.OrganizationId; + secret.CreationDate = existingSecret.CreationDate; + secret.DeletedDate = existingSecret.DeletedDate; + secret.RevisionDate = DateTime.UtcNow; + + await _secretRepository.UpdateAsync(secret); + return secret; + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/ServiceAccounts/CreateServiceAccountCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/ServiceAccounts/CreateServiceAccountCommand.cs new file mode 100644 index 000000000..f3d379947 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/ServiceAccounts/CreateServiceAccountCommand.cs @@ -0,0 +1,20 @@ +using Bit.Core.SecretsManager.Commands.ServiceAccounts.Interfaces; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; + +namespace Bit.Commercial.Core.SecretsManager.Commands.ServiceAccounts; + +public class CreateServiceAccountCommand : ICreateServiceAccountCommand +{ + private readonly IServiceAccountRepository _serviceAccountRepository; + + public CreateServiceAccountCommand(IServiceAccountRepository serviceAccountRepository) + { + _serviceAccountRepository = serviceAccountRepository; + } + + public async Task CreateAsync(ServiceAccount serviceAccount) + { + return await _serviceAccountRepository.CreateAsync(serviceAccount); + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/ServiceAccounts/UpdateServiceAccountCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/ServiceAccounts/UpdateServiceAccountCommand.cs new file mode 100644 index 000000000..efc77fc04 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/ServiceAccounts/UpdateServiceAccountCommand.cs @@ -0,0 +1,50 @@ +using Bit.Core.Context; +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Commands.ServiceAccounts.Interfaces; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; + +namespace Bit.Commercial.Core.SecretsManager.Commands.ServiceAccounts; + +public class UpdateServiceAccountCommand : IUpdateServiceAccountCommand +{ + private readonly IServiceAccountRepository _serviceAccountRepository; + private readonly ICurrentContext _currentContext; + + public UpdateServiceAccountCommand(IServiceAccountRepository serviceAccountRepository, ICurrentContext currentContext) + { + _serviceAccountRepository = serviceAccountRepository; + _currentContext = currentContext; + } + + public async Task UpdateAsync(ServiceAccount updatedServiceAccount, Guid userId) + { + var serviceAccount = await _serviceAccountRepository.GetByIdAsync(updatedServiceAccount.Id); + if (serviceAccount == null) + { + throw new NotFoundException(); + } + + var orgAdmin = await _currentContext.OrganizationAdmin(serviceAccount.OrganizationId); + var accessClient = AccessClientHelper.ToAccessClient(_currentContext.ClientType, orgAdmin); + + var hasAccess = accessClient switch + { + AccessClientType.NoAccessCheck => true, + AccessClientType.User => await _serviceAccountRepository.UserHasWriteAccessToServiceAccount(updatedServiceAccount.Id, userId), + _ => false, + }; + + if (!hasAccess) + { + throw new UnauthorizedAccessException(); + } + + serviceAccount.Name = updatedServiceAccount.Name; + serviceAccount.RevisionDate = DateTime.UtcNow; + + await _serviceAccountRepository.ReplaceAsync(serviceAccount); + return serviceAccount; + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/SecretsManagerCollectionExtensions.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/SecretsManagerCollectionExtensions.cs new file mode 100644 index 000000000..dc645d1a1 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/SecretsManagerCollectionExtensions.cs @@ -0,0 +1,32 @@ +using Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies; +using Bit.Commercial.Core.SecretsManager.Commands.AccessTokens; +using Bit.Commercial.Core.SecretsManager.Commands.Projects; +using Bit.Commercial.Core.SecretsManager.Commands.Secrets; +using Bit.Commercial.Core.SecretsManager.Commands.ServiceAccounts; +using Bit.Core.SecretsManager.Commands.AccessPolicies.Interfaces; +using Bit.Core.SecretsManager.Commands.AccessTokens.Interfaces; +using Bit.Core.SecretsManager.Commands.Projects.Interfaces; +using Bit.Core.SecretsManager.Commands.Secrets.Interfaces; +using Bit.Core.SecretsManager.Commands.ServiceAccounts.Interfaces; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Commercial.Core.SecretsManager; + +public static class SecretsManagerCollectionExtensions +{ + public static void AddSecretsManagerServices(this IServiceCollection services) + { + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/SecretsManagerServiceCollectionExtensions.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/SecretsManagerServiceCollectionExtensions.cs new file mode 100644 index 000000000..e6c733164 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/SecretsManagerServiceCollectionExtensions.cs @@ -0,0 +1,11 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Commercial.Core.SecretsManager; + +public static class SecretsManagerServiceCollectionExtensions +{ + public static void AddCommercialSecretsManagerServices(this IServiceCollection services) + { + services.AddSecretsManagerServices(); + } +} diff --git a/bitwarden_license/src/Commercial.Core/Services/ProviderService.cs b/bitwarden_license/src/Commercial.Core/Services/ProviderService.cs new file mode 100644 index 000000000..cf3b68efa --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/Services/ProviderService.cs @@ -0,0 +1,508 @@ +using Bit.Core.Context; +using Bit.Core.Entities; +using Bit.Core.Entities.Provider; +using Bit.Core.Enums; +using Bit.Core.Enums.Provider; +using Bit.Core.Exceptions; +using Bit.Core.Models.Business; +using Bit.Core.Models.Business.Provider; +using Bit.Core.Models.Data; +using Bit.Core.Repositories; +using Bit.Core.Services; +using Bit.Core.Settings; +using Bit.Core.Utilities; +using Microsoft.AspNetCore.DataProtection; + +namespace Bit.Commercial.Core.Services; + +public class ProviderService : IProviderService +{ + public static PlanType[] ProviderDisllowedOrganizationTypes = new[] { PlanType.Free, PlanType.FamiliesAnnually, PlanType.FamiliesAnnually2019 }; + + private readonly IDataProtector _dataProtector; + private readonly IMailService _mailService; + private readonly IEventService _eventService; + private readonly GlobalSettings _globalSettings; + private readonly IProviderRepository _providerRepository; + private readonly IProviderUserRepository _providerUserRepository; + private readonly IProviderOrganizationRepository _providerOrganizationRepository; + private readonly IOrganizationRepository _organizationRepository; + private readonly IUserRepository _userRepository; + private readonly IUserService _userService; + private readonly IOrganizationService _organizationService; + private readonly ICurrentContext _currentContext; + + public ProviderService(IProviderRepository providerRepository, IProviderUserRepository providerUserRepository, + IProviderOrganizationRepository providerOrganizationRepository, IUserRepository userRepository, + IUserService userService, IOrganizationService organizationService, IMailService mailService, + IDataProtectionProvider dataProtectionProvider, IEventService eventService, + IOrganizationRepository organizationRepository, GlobalSettings globalSettings, + ICurrentContext currentContext) + { + _providerRepository = providerRepository; + _providerUserRepository = providerUserRepository; + _providerOrganizationRepository = providerOrganizationRepository; + _organizationRepository = organizationRepository; + _userRepository = userRepository; + _userService = userService; + _organizationService = organizationService; + _mailService = mailService; + _eventService = eventService; + _globalSettings = globalSettings; + _dataProtector = dataProtectionProvider.CreateProtector("ProviderServiceDataProtector"); + _currentContext = currentContext; + } + + public async Task CreateAsync(string ownerEmail) + { + var owner = await _userRepository.GetByEmailAsync(ownerEmail); + if (owner == null) + { + throw new BadRequestException("Invalid owner. Owner must be an existing Bitwarden user."); + } + + var provider = new Provider + { + Status = ProviderStatusType.Pending, + Enabled = true, + UseEvents = true, + }; + await _providerRepository.CreateAsync(provider); + + var providerUser = new ProviderUser + { + ProviderId = provider.Id, + UserId = owner.Id, + Type = ProviderUserType.ProviderAdmin, + Status = ProviderUserStatusType.Confirmed, + }; + await _providerUserRepository.CreateAsync(providerUser); + await SendProviderSetupInviteEmailAsync(provider, owner.Email); + } + + public async Task CompleteSetupAsync(Provider provider, Guid ownerUserId, string token, string key) + { + var owner = await _userService.GetUserByIdAsync(ownerUserId); + if (owner == null) + { + throw new BadRequestException("Invalid owner."); + } + + if (provider.Status != ProviderStatusType.Pending) + { + throw new BadRequestException("Provider is already setup."); + } + + if (!CoreHelpers.TokenIsValid("ProviderSetupInvite", _dataProtector, token, owner.Email, provider.Id, + _globalSettings.OrganizationInviteExpirationHours)) + { + throw new BadRequestException("Invalid token."); + } + + var providerUser = await _providerUserRepository.GetByProviderUserAsync(provider.Id, ownerUserId); + if (!(providerUser is { Type: ProviderUserType.ProviderAdmin })) + { + throw new BadRequestException("Invalid owner."); + } + + provider.Status = ProviderStatusType.Created; + await _providerRepository.UpsertAsync(provider); + + providerUser.Key = key; + await _providerUserRepository.ReplaceAsync(providerUser); + + return provider; + } + + public async Task UpdateAsync(Provider provider, bool updateBilling = false) + { + if (provider.Id == default) + { + throw new ArgumentException("Cannot create provider this way."); + } + + await _providerRepository.ReplaceAsync(provider); + } + + public async Task> InviteUserAsync(ProviderUserInvite invite) + { + if (!_currentContext.ProviderManageUsers(invite.ProviderId)) + { + throw new InvalidOperationException("Invalid permissions."); + } + + var emails = invite?.UserIdentifiers; + var invitingUser = await _providerUserRepository.GetByProviderUserAsync(invite.ProviderId, invite.InvitingUserId); + + var provider = await _providerRepository.GetByIdAsync(invite.ProviderId); + if (provider == null || emails == null || !emails.Any()) + { + throw new NotFoundException(); + } + + var providerUsers = new List(); + foreach (var email in emails) + { + // Make sure user is not already invited + var existingProviderUserCount = + await _providerUserRepository.GetCountByProviderAsync(invite.ProviderId, email, false); + if (existingProviderUserCount > 0) + { + continue; + } + + var providerUser = new ProviderUser + { + ProviderId = invite.ProviderId, + UserId = null, + Email = email.ToLowerInvariant(), + Key = null, + Type = invite.Type, + Status = ProviderUserStatusType.Invited, + CreationDate = DateTime.UtcNow, + RevisionDate = DateTime.UtcNow, + }; + + await _providerUserRepository.CreateAsync(providerUser); + + await SendInviteAsync(providerUser, provider); + providerUsers.Add(providerUser); + } + + await _eventService.LogProviderUsersEventAsync(providerUsers.Select(pu => (pu, EventType.ProviderUser_Invited, null as DateTime?))); + + return providerUsers; + } + + public async Task>> ResendInvitesAsync(ProviderUserInvite invite) + { + if (!_currentContext.ProviderManageUsers(invite.ProviderId)) + { + throw new BadRequestException("Invalid permissions."); + } + + var providerUsers = await _providerUserRepository.GetManyAsync(invite.UserIdentifiers); + var provider = await _providerRepository.GetByIdAsync(invite.ProviderId); + + var result = new List>(); + foreach (var providerUser in providerUsers) + { + if (providerUser.Status != ProviderUserStatusType.Invited || providerUser.ProviderId != invite.ProviderId) + { + result.Add(Tuple.Create(providerUser, "User invalid.")); + continue; + } + + await SendInviteAsync(providerUser, provider); + result.Add(Tuple.Create(providerUser, "")); + } + + return result; + } + + public async Task AcceptUserAsync(Guid providerUserId, User user, string token) + { + var providerUser = await _providerUserRepository.GetByIdAsync(providerUserId); + if (providerUser == null) + { + throw new BadRequestException("User invalid."); + } + + if (providerUser.Status != ProviderUserStatusType.Invited) + { + throw new BadRequestException("Already accepted."); + } + + if (!CoreHelpers.TokenIsValid("ProviderUserInvite", _dataProtector, token, user.Email, providerUser.Id, + _globalSettings.OrganizationInviteExpirationHours)) + { + throw new BadRequestException("Invalid token."); + } + + if (string.IsNullOrWhiteSpace(providerUser.Email) || + !providerUser.Email.Equals(user.Email, StringComparison.InvariantCultureIgnoreCase)) + { + throw new BadRequestException("User email does not match invite."); + } + + providerUser.Status = ProviderUserStatusType.Accepted; + providerUser.UserId = user.Id; + providerUser.Email = null; + + await _providerUserRepository.ReplaceAsync(providerUser); + + return providerUser; + } + + public async Task>> ConfirmUsersAsync(Guid providerId, Dictionary keys, + Guid confirmingUserId) + { + var providerUsers = await _providerUserRepository.GetManyAsync(keys.Keys); + var validProviderUsers = providerUsers + .Where(u => u.UserId != null) + .ToList(); + + if (!validProviderUsers.Any()) + { + return new List>(); + } + + var validOrganizationUserIds = validProviderUsers.Select(u => u.UserId.Value).ToList(); + + var provider = await _providerRepository.GetByIdAsync(providerId); + var users = await _userRepository.GetManyAsync(validOrganizationUserIds); + + var keyedFilteredUsers = validProviderUsers.ToDictionary(u => u.UserId.Value, u => u); + + var result = new List>(); + var events = new List<(ProviderUser, EventType, DateTime?)>(); + + foreach (var user in users) + { + if (!keyedFilteredUsers.ContainsKey(user.Id)) + { + continue; + } + var providerUser = keyedFilteredUsers[user.Id]; + try + { + if (providerUser.Status != ProviderUserStatusType.Accepted || providerUser.ProviderId != providerId) + { + throw new BadRequestException("Invalid user."); + } + + providerUser.Status = ProviderUserStatusType.Confirmed; + providerUser.Key = keys[providerUser.Id]; + providerUser.Email = null; + + await _providerUserRepository.ReplaceAsync(providerUser); + events.Add((providerUser, EventType.ProviderUser_Confirmed, null)); + await _mailService.SendProviderConfirmedEmailAsync(provider.Name, user.Email); + result.Add(Tuple.Create(providerUser, "")); + } + catch (BadRequestException e) + { + result.Add(Tuple.Create(providerUser, e.Message)); + } + } + + await _eventService.LogProviderUsersEventAsync(events); + + return result; + } + + public async Task SaveUserAsync(ProviderUser user, Guid savingUserId) + { + if (user.Id.Equals(default)) + { + throw new BadRequestException("Invite the user first."); + } + + if (user.Type != ProviderUserType.ProviderAdmin && + !await HasConfirmedProviderAdminExceptAsync(user.ProviderId, new[] { user.Id })) + { + throw new BadRequestException("Provider must have at least one confirmed ProviderAdmin."); + } + + await _providerUserRepository.ReplaceAsync(user); + await _eventService.LogProviderUserEventAsync(user, EventType.ProviderUser_Updated); + } + + public async Task>> DeleteUsersAsync(Guid providerId, + IEnumerable providerUserIds, Guid deletingUserId) + { + var provider = await _providerRepository.GetByIdAsync(providerId); + + if (provider == null) + { + throw new NotFoundException(); + } + + var providerUsers = await _providerUserRepository.GetManyAsync(providerUserIds); + var users = await _userRepository.GetManyAsync(providerUsers.Where(pu => pu.UserId.HasValue) + .Select(pu => pu.UserId.Value)); + var keyedUsers = users.ToDictionary(u => u.Id); + + if (!await HasConfirmedProviderAdminExceptAsync(providerId, providerUserIds)) + { + throw new BadRequestException("Provider must have at least one confirmed ProviderAdmin."); + } + + var result = new List>(); + var deletedUserIds = new List(); + var events = new List<(ProviderUser, EventType, DateTime?)>(); + + foreach (var providerUser in providerUsers) + { + try + { + if (providerUser.ProviderId != providerId) + { + throw new BadRequestException("Invalid user."); + } + if (providerUser.UserId == deletingUserId) + { + throw new BadRequestException("You cannot remove yourself."); + } + + events.Add((providerUser, EventType.ProviderUser_Removed, null)); + + var user = keyedUsers.GetValueOrDefault(providerUser.UserId.GetValueOrDefault()); + var email = user == null ? providerUser.Email : user.Email; + if (!string.IsNullOrWhiteSpace(email)) + { + await _mailService.SendProviderUserRemoved(provider.Name, email); + } + + result.Add(Tuple.Create(providerUser, "")); + deletedUserIds.Add(providerUser.Id); + } + catch (BadRequestException e) + { + result.Add(Tuple.Create(providerUser, e.Message)); + } + + await _providerUserRepository.DeleteManyAsync(deletedUserIds); + } + + await _eventService.LogProviderUsersEventAsync(events); + + return result; + } + + public async Task AddOrganization(Guid providerId, Guid organizationId, Guid addingUserId, string key) + { + var po = await _providerOrganizationRepository.GetByOrganizationId(organizationId); + if (po != null) + { + throw new BadRequestException("Organization already belongs to a provider."); + } + + var organization = await _organizationRepository.GetByIdAsync(organizationId); + ThrowOnInvalidPlanType(organization.PlanType); + + var providerOrganization = new ProviderOrganization + { + ProviderId = providerId, + OrganizationId = organizationId, + Key = key, + }; + + await _providerOrganizationRepository.CreateAsync(providerOrganization); + await _eventService.LogProviderOrganizationEventAsync(providerOrganization, EventType.ProviderOrganization_Added); + } + + public async Task CreateOrganizationAsync(Guid providerId, + OrganizationSignup organizationSignup, string clientOwnerEmail, User user) + { + ThrowOnInvalidPlanType(organizationSignup.Plan); + + var (organization, _) = await _organizationService.SignUpAsync(organizationSignup, true); + + var providerOrganization = new ProviderOrganization + { + ProviderId = providerId, + OrganizationId = organization.Id, + Key = organizationSignup.OwnerKey, + }; + + await _providerOrganizationRepository.CreateAsync(providerOrganization); + await _eventService.LogProviderOrganizationEventAsync(providerOrganization, EventType.ProviderOrganization_Created); + + await _organizationService.InviteUsersAsync(organization.Id, user.Id, + new (OrganizationUserInvite, string)[] + { + ( + new OrganizationUserInvite + { + Emails = new[] { clientOwnerEmail }, + AccessAll = true, + Type = OrganizationUserType.Owner, + Permissions = null, + Collections = Array.Empty(), + }, + null + ) + }); + + return providerOrganization; + } + + public async Task RemoveOrganizationAsync(Guid providerId, Guid providerOrganizationId, Guid removingUserId) + { + var providerOrganization = await _providerOrganizationRepository.GetByIdAsync(providerOrganizationId); + if (providerOrganization == null || providerOrganization.ProviderId != providerId) + { + throw new BadRequestException("Invalid organization."); + } + + if (!await _organizationService.HasConfirmedOwnersExceptAsync(providerOrganization.OrganizationId, new Guid[] { }, includeProvider: false)) + { + throw new BadRequestException("Organization needs to have at least one confirmed owner."); + } + + await _providerOrganizationRepository.DeleteAsync(providerOrganization); + await _eventService.LogProviderOrganizationEventAsync(providerOrganization, EventType.ProviderOrganization_Removed); + } + + public async Task ResendProviderSetupInviteEmailAsync(Guid providerId, Guid ownerId) + { + var provider = await _providerRepository.GetByIdAsync(providerId); + var owner = await _userRepository.GetByIdAsync(ownerId); + if (owner == null) + { + throw new BadRequestException("Invalid owner."); + } + await SendProviderSetupInviteEmailAsync(provider, owner.Email); + } + + private async Task SendProviderSetupInviteEmailAsync(Provider provider, string ownerEmail) + { + var token = _dataProtector.Protect($"ProviderSetupInvite {provider.Id} {ownerEmail} {CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow)}"); + await _mailService.SendProviderSetupInviteEmailAsync(provider, token, ownerEmail); + } + + public async Task LogProviderAccessToOrganizationAsync(Guid organizationId) + { + if (organizationId == default) + { + return; + } + + var providerOrganization = await _providerOrganizationRepository.GetByOrganizationId(organizationId); + var organization = await _organizationRepository.GetByIdAsync(organizationId); + if (providerOrganization != null) + { + await _eventService.LogProviderOrganizationEventAsync(providerOrganization, EventType.ProviderOrganization_VaultAccessed); + } + if (organization != null) + { + await _eventService.LogOrganizationEventAsync(organization, EventType.Organization_VaultAccessed); + } + } + + private async Task SendInviteAsync(ProviderUser providerUser, Provider provider) + { + var nowMillis = CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow); + var token = _dataProtector.Protect( + $"ProviderUserInvite {providerUser.Id} {providerUser.Email} {nowMillis}"); + await _mailService.SendProviderInviteEmailAsync(provider.Name, providerUser, token, providerUser.Email); + } + + private async Task HasConfirmedProviderAdminExceptAsync(Guid providerId, IEnumerable providerUserIds) + { + var providerAdmins = await _providerUserRepository.GetManyByProviderAsync(providerId, + ProviderUserType.ProviderAdmin); + var confirmedOwners = providerAdmins.Where(o => o.Status == ProviderUserStatusType.Confirmed); + var confirmedOwnersIds = confirmedOwners.Select(u => u.Id); + return confirmedOwnersIds.Except(providerUserIds).Any(); + } + + private void ThrowOnInvalidPlanType(PlanType requestedType) + { + if (ProviderDisllowedOrganizationTypes.Contains(requestedType)) + { + throw new BadRequestException($"Providers cannot manage organizations with the requested plan type ({requestedType}). Only Teams and Enterprise accounts are allowed."); + } + } +} diff --git a/bitwarden_license/src/Commercial.Core/Utilities/ServiceCollectionExtensions.cs b/bitwarden_license/src/Commercial.Core/Utilities/ServiceCollectionExtensions.cs new file mode 100644 index 000000000..6440f27ab --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/Utilities/ServiceCollectionExtensions.cs @@ -0,0 +1,13 @@ +using Bit.Commercial.Core.Services; +using Bit.Core.Services; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Commercial.Core.Utilities; + +public static class ServiceCollectionExtensions +{ + public static void AddCommercialCoreServices(this IServiceCollection services) + { + services.AddScoped(); + } +} diff --git a/bitwarden_license/src/Commercial.Core/packages.lock.json b/bitwarden_license/src/Commercial.Core/packages.lock.json new file mode 100644 index 000000000..730790bc8 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/packages.lock.json @@ -0,0 +1,2586 @@ +{ + "version": 1, + "dependencies": { + "net6.0": { + "AspNetCoreRateLimit": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "FzXAJFgaRjKfnKAVwjEEC7OAGQM5v/I3sQw2tpzmR0yHTCGhUAxZzDuwZiXTk8XLrI6vovzkqKkfKmiDl3nYMg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.1", + "Microsoft.Extensions.Options": "6.0.0", + "Newtonsoft.Json": "13.0.1" + } + }, + "AspNetCoreRateLimit.Redis": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "CsSGy/7SXt6iBOKg0xCvsRjb/ZHshbtr2Of1MHc912L2sLnZqadUrTboyXZC+ZlgEBeJ14GyjPTu8ZyfEhGUnw==", + "dependencies": { + "AspNetCoreRateLimit": "4.0.2", + "StackExchange.Redis": "2.5.43" + } + }, + "AWSSDK.Core": { + "type": "Transitive", + "resolved": "3.7.10.11", + "contentHash": "B+M7ggPC0FogATRPQxDXL0eTusCQtXulW4zCuX39yiHV8+u9MEXRytcAw0ZA3zFBYYx6ovl9lklho6OQo1DRRQ==" + }, + "AWSSDK.SimpleEmail": { + "type": "Transitive", + "resolved": "3.7.0.150", + "contentHash": "rc/4ZnISfbgTfqz5/BWqMHBAzk4R09qfe1xkdJf2jXo44Zn2X72W8IiLLweBtmNhL7d8Tcf6UCtOHYkFwxHvug==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "AWSSDK.SQS": { + "type": "Transitive", + "resolved": "3.7.2.47", + "contentHash": "RPTVBsY333n+aIEqw148Envx9OQkE1/jhjlioNXDP6BrA3fAPN9A+2HoA02c0KSp/sazXYWg8w/kDL8FchH8Dw==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.24.0", + "contentHash": "+/qI1j2oU1S4/nvxb2k/wDsol00iGf1AyJX5g3epV7eOpQEP/2xcgh/cxgKMeFgn3U2fmgSiBnQZdkV+l5y0Uw==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Numerics.Vectors": "4.5.0", + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Extensions.AspNetCore.DataProtection.Blobs": { + "type": "Transitive", + "resolved": "1.2.1", + "contentHash": "wxvkC6DeWThBtaPbsWdicp5Ltya4J8JuhxmZJDQkhnXG7oihfu8RqBV6w/X1nMieuIOq1qQaGTvjx7nEHHfxSQ==", + "dependencies": { + "Azure.Core": "1.14.0", + "Azure.Storage.Blobs": "12.8.0", + "Microsoft.AspNetCore.DataProtection": "2.1.0" + } + }, + "Azure.Identity": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "EycyMsb6rD2PK9P0SyibFfEhvWWttdrYhyPF4f41uzdB/44yQlV+2Wehxyg489Rj6gbPvSPgbKq0xsHJBhipZA==", + "dependencies": { + "Azure.Core": "1.24.0", + "Microsoft.Identity.Client": "4.39.0", + "Microsoft.Identity.Client.Extensions.Msal": "2.19.3", + "System.Memory": "4.5.4", + "System.Security.Cryptography.ProtectedData": "4.7.0", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Storage.Blobs": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "50eRjIhY7Q1JN7kT2MSawDKCcwSb7uRZUkz00P/BLjSg47gm2hxUYsnJPyvzCHntYMbOWzrvaVQTwYwXabaR5Q==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Text.Json": "4.7.2" + } + }, + "Azure.Storage.Common": { + "type": "Transitive", + "resolved": "12.10.0", + "contentHash": "vYkHGzUkdZTace/cDPZLG+Mh/EoPqQuGxDIBOau9D+XWoDPmuUFGk325aXplkFE4JFGpSwoytNYzk/qBCaiHqg==", + "dependencies": { + "Azure.Core": "1.22.0", + "System.IO.Hashing": "6.0.0" + } + }, + "Azure.Storage.Queues": { + "type": "Transitive", + "resolved": "12.9.0", + "contentHash": "jDiyHtsCUCrWNvZW7SjJnJb46UhpdgQrWCbL8aWpapDHlq9LvbvxYpfLh4dfKAz09QiTznLMIU3i+md9+7GzqQ==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, + "BitPay.Light": { + "type": "Transitive", + "resolved": "1.0.1907", + "contentHash": "QTTIgXakHrRNQPxNyH7bZ7frm0bI8N6gRDtiqVyKG/QYQ+KfjN70xt0zQ0kO0zf8UBaKuwcV5B7vvpXtzR9ijg==", + "dependencies": { + "Newtonsoft.Json": "12.0.2" + } + }, + "Braintree": { + "type": "Transitive", + "resolved": "5.12.0", + "contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "System.Xml.XPath.XmlDocument": "4.3.0" + } + }, + "Fido2": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "S0Bz1vfcKlO4Jase3AWp5XnQ746psf4oGx5kL+D2A10j1SsjoAOAIIpanSwfi0cEepDHgk1bClcOKY5TjOzGdA==", + "dependencies": { + "Fido2.Models": "3.0.1", + "Microsoft.Extensions.Http": "6.0.0", + "NSec.Cryptography": "22.4.0", + "System.Formats.Cbor": "6.0.0", + "System.IdentityModel.Tokens.Jwt": "6.17.0" + } + }, + "Fido2.AspNet": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "5n5shEXD7RFUyTesjUHGDjkpgES7j4KotQo1GwUcS08k+fx+1tl/zCFHJ9RFDuUwO+S681ZILT2PyA67IPYpaA==", + "dependencies": { + "Fido2": "3.0.1", + "Fido2.Models": "3.0.1" + } + }, + "Fido2.Models": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "mgjcuGETuYSCUEaZG+jQeeuuEMkDLc4GDJHBvKDdOz6oSOWp5adPdWP4btZx7Pi+9fu4szN3JIjJmby67MaILw==" + }, + "Handlebars.Net": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "p60QyeBYpZmcZdIXRMqs9XySIBaxJ0lj3+QD0EJVr4ybTigOTCumXMMin5dPwjo9At1UwkDZ3gGwa1lmGjG6DA==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "IdentityModel": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "System.Text.Encodings.Web": "4.7.0" + } + }, + "IdentityModel.AspNetCore.OAuth2Introspection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==", + "dependencies": { + "IdentityModel": "4.0.0" + } + }, + "IdentityServer4": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==", + "dependencies": { + "IdentityModel": "4.4.0", + "IdentityServer4.Storage": "4.1.2", + "Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0", + "Newtonsoft.Json": "12.0.2" + } + }, + "IdentityServer4.AccessTokenValidation": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==", + "dependencies": { + "IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1", + "Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0" + } + }, + "IdentityServer4.Storage": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==", + "dependencies": { + "IdentityModel": "4.4.0" + } + }, + "libsodium": { + "type": "Transitive", + "resolved": "1.0.18.2", + "contentHash": "flArHoVdscSzyV8ZdPV+bqqY2TTFlaN+xZf/vIqsmHI51KVcD/mOdUPaK3n/k/wGKz8dppiktXUqSmf3AXFgig==" + }, + "MailKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "5MTpTqmjqT7HPvYbP3HozRZMth5vSaT0ReN0iM3rAM4CgLI/R1qqtLDDNWGnFFIlcNzeJkZQRJJMkv8cgzWBbA==", + "dependencies": { + "MimeKit": "3.2.0" + } + }, + "Microsoft.AspNetCore.Authentication.JwtBearer": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "joDS3+lD1i9qcdFLWP4D316t3bHpezmTNOzbMIf9ZcRPX4QTuiUutZcQn/kZplf3BiLHqwUChZXxPjCAMKaKAQ==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0" + } + }, + "Microsoft.AspNetCore.Authentication.OpenIdConnect": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0" + } + }, + "Microsoft.AspNetCore.Cryptography.Internal": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "/0FX1OqckMmXAAlsHgBFNymTZuq4nuAOMhiwm6e8CEMi2aOjnMYwiMc7mtvpGTAO0O4C0zwx+iaChxDgvqit2A==" + }, + "Microsoft.AspNetCore.Cryptography.KeyDerivation": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "1Lbwrxg/HRY/nbrkcrB3EUXUYQN8Tkw7Ktgb6/2on2P7ybT5aM59H05gk+OBC8ZTBxwdle9e1tyT3wxEYKw5xw==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "6.0.4" + } + }, + "Microsoft.AspNetCore.DataProtection": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "G+UoMHL0xiyFh30wkL7Bv/XL6eugTAKYhLPS53k1/Me1bYRwOOw+8VL/q0ppq3/yMzpHX+MkExaCTDlYl48FgA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "2.1.0", + "Microsoft.AspNetCore.DataProtection.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.1.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0", + "Microsoft.Extensions.Logging.Abstractions": "2.1.0", + "Microsoft.Extensions.Options": "2.1.0", + "Microsoft.Win32.Registry": "4.5.0", + "System.Security.Cryptography.Xml": "4.5.0", + "System.Security.Principal.Windows": "4.5.0" + } + }, + "Microsoft.AspNetCore.DataProtection.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "2+HVDhUqrnV9+EJNEewSy+Gk4hOVPzLPMpFDZI7kuH7NWxtbNkI6A6gT5lO2/kEPMyM8/iLWtohbOwjpC9rHVw==" + }, + "Microsoft.AspNetCore.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "1TQgBfd/NPZLR2o/h6l5Cml2ZCF5hsyV4h9WEwWwAIavrbdTnaNozGGcTOd4AOgQvogMM9UM1ajflm9Cwd0jLQ==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Http.Abstractions": "2.1.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "YTKMi2vHX6P+WHEVpW/DS+eFHnwivCSMklkyamcK1ETtc/4j8H3VR0kgW8XIBqukNxhD8k5wYt22P7PhrWSXjQ==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "Microsoft.Extensions.Configuration.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Http.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "vbFDyKsSYBnxl3+RABtN79b0vsTcG66fDY8vD6Nqvu9uLtSej70Q5NcbGlnN6bJpZci5orSdgFTHMhBywivDPg==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Features": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "UmkUePxRjsQW0j5euFFscBwjvTu25b8+qIK/2fI3GvcqQ+mkwgbWNAT8b/Gkoei1m2bTWC07lSdutuRDPPLcJA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.0" + } + }, + "Microsoft.Azure.Amqp": { + "type": "Transitive", + "resolved": "2.4.11", + "contentHash": "7x5fu2f6TLQDDJS0sY5qW8/daFwJaY9O75YvU8RcUfRzbug+9YGjXUBxoRrprgyi0jxdBAMQL05p1s783SOSFQ==", + "dependencies": { + "System.Net.WebSockets.Client": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.Azure.Cosmos": { + "type": "Transitive", + "resolved": "3.24.0", + "contentHash": "QpUe5ho6OzlXwgcJVgAmOR7t3XLC9RI4t8T96RZY61pSOIllPOJdp30L0LwA16tKcqi5r2KayEgWO/MS9fh/6A==", + "dependencies": { + "Azure.Core": "1.3.0", + "Microsoft.Bcl.AsyncInterfaces": "1.0.0", + "Microsoft.Bcl.HashCode": "1.1.0", + "Newtonsoft.Json": "10.0.2", + "System.Buffers": "4.5.1", + "System.Collections.Immutable": "1.7.0", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Memory": "4.5.4", + "System.Numerics.Vectors": "4.5.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3", + "System.Threading.Tasks.Extensions": "4.5.4", + "System.ValueTuple": "4.5.0" + } + }, + "Microsoft.Azure.Cosmos.Table": { + "type": "Transitive", + "resolved": "1.0.8", + "contentHash": "ToeEd1yijM7nQfLYvdFLG//RjKPmfqm45eOm86UAKrxtyGI/CXqP8iL74mzBp6mZ9A/K/ZYA2fVdpH0xHR5Keg==", + "dependencies": { + "Microsoft.Azure.DocumentDB.Core": "2.11.2", + "Microsoft.OData.Core": "7.6.4", + "Newtonsoft.Json": "10.0.2" + } + }, + "Microsoft.Azure.DocumentDB.Core": { + "type": "Transitive", + "resolved": "2.11.2", + "contentHash": "cA8eWrTFbYrkHrz095x4CUGb7wqQgA1slzFZCYexhNwz6Zcn3v+S1yvWMGwGRmRjT0MKU9tYdFWgLfT0OjSycw==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "Newtonsoft.Json": "9.0.1", + "System.Collections.Immutable": "1.3.0", + "System.Collections.NonGeneric": "4.0.1", + "System.Collections.Specialized": "4.0.1", + "System.Diagnostics.TraceSource": "4.0.0", + "System.Dynamic.Runtime": "4.0.11", + "System.Linq.Queryable": "4.0.1", + "System.Net.Http": "4.3.4", + "System.Net.NameResolution": "4.0.0", + "System.Net.NetworkInformation": "4.1.0", + "System.Net.Requests": "4.0.11", + "System.Net.Security": "4.3.2", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Security.SecureString": "4.0.0" + } + }, + "Microsoft.Azure.NotificationHubs": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "C2SssjX3e6/HIo1OCImQDDVOn64d1+gkgEmgxJryzkwixyivJHWH2YIgxZs33pyzVQcZWx5PR2tqLkQ7riSq8Q==", + "dependencies": { + "Microsoft.Extensions.Caching.Memory": "3.1.8", + "Newtonsoft.Json": "12.0.3" + } + }, + "Microsoft.Azure.ServiceBus": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "wyZNJggyFNtKxd+HgvcTiuRYuTjDGi+pgE4RcBvFbfvNiarKr5AOlE4Ne7on1eUJZuMuEa19wN5dj694HlP60A==", + "dependencies": { + "Microsoft.Azure.Amqp": "2.4.11", + "Microsoft.Azure.Services.AppAuthentication": "[1.0.3, 2.0.0)", + "Newtonsoft.Json": "10.0.3", + "System.Diagnostics.DiagnosticSource": "4.5.1", + "System.IdentityModel.Tokens.Jwt": "5.4.0" + } + }, + "Microsoft.Azure.Services.AppAuthentication": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "ywpQaK1klu1IoX4VUf+TBmU4kR71aWNI6O5rEIJU8z28L2xhJhnIm7k2Nf1Zu/PygeuOtt5g0QPCk5+lLltbeQ==", + "dependencies": { + "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.14.2", + "NETStandard.Library": "1.6.1", + "System.Diagnostics.Process": "4.3.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "yuvf07qFWFqtK3P/MRkEKLhn5r2UbSpVueRziSqj0yJQIKFwG1pq9mOayK3zE5qZCTs0CbrwL9M6R8VwqyGy2w==" + }, + "Microsoft.Bcl.HashCode": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "J2G1k+u5unBV+aYcwxo94ip16Rkp65pgWFb0R6zwJipzWNMgvqlWeuI7/+R+e8bob66LnSG+llLJ+z8wI94cHg==" + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, + "Microsoft.Data.SqlClient": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "uu8dfrsx081cSbEevWuZAvqdmANDGJkbLBL2G3j0LAZxX1Oy8RCVAaC4Lcuak6jNicWP6CWvHqBTIEmQNSxQlw==", + "dependencies": { + "Azure.Identity": "1.6.0", + "Microsoft.Data.SqlClient.SNI.runtime": "5.0.1", + "Microsoft.Identity.Client": "4.45.0", + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.21.0", + "Microsoft.SqlServer.Server": "1.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Buffers": "4.5.1", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Diagnostics.DiagnosticSource": "5.0.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime.Caching": "5.0.0", + "System.Security.Cryptography.Cng": "5.0.0", + "System.Security.Principal.Windows": "5.0.0", + "System.Text.Encoding.CodePages": "5.0.0", + "System.Text.Encodings.Web": "4.7.2" + } + }, + "Microsoft.Data.SqlClient.SNI.runtime": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "y0X5MxiNdbITJYoafJ2ruaX6hqO0twpCGR/ipiDOe85JKLU8WL4TuAQfDe5qtt3bND5Je26HnrarLSAMMnVTNg==" + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bcz5sSFJbganH0+YrfvIjJDIcKNW7TL07C4d1eTmXy/wOt52iz4LVogJb6pazs7W0+74j0YpXFErvp++Aq5Bsw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.Memory": { + "type": "Transitive", + "resolved": "3.1.8", + "contentHash": "u04q7+tgc8l6pQ5HOcr6scgapkQQHnrhpGoCaaAZd24R36/NxGsGxuhSmhHOrQx9CsBLe2CVBN/4CkLlxtnnXw==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "3.1.8", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8", + "Microsoft.Extensions.Options": "3.1.8" + } + }, + "Microsoft.Extensions.Caching.StackExchangeRedis": { + "type": "Transitive", + "resolved": "6.0.6", + "contentHash": "bdVQpYm1hcHf0pyAypMjtDw3HjWQJ89UzloyyF1OBs56QlgA1naM498tP2Vjlho5vVRALMGPYzdRKCen8koubw==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "StackExchange.Redis": "2.2.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "tq2wXyh3fL17EMF2bXgRhU7JrbO3on93MRKYxzz4JzzvuGSA1l0W3GI9/tl8EO89TH+KWEymP7bcFway6z9fXg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "IznHHzGUtrdpuQqIUdmzF6TYPcsYHONhHh3o9dGp39sX/9Zfmt476UnhvU0UhXgJnXXAikt/MpN6AuSLCCMdEQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.0.0" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "pnyXV1LFOsYjGveuC07xp0YHIyGq7jRq5Ncb5zrrIieMLWVwgMyYxcOH0jTnBedDT4Gh1QinSqsjqzcieHk1og==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "V4Dth2cYMZpw3HhGw9XUDIijpI6gN+22LDt0AhufIgOppCUfpWX4483OmN+dFXRJkJLc8Tv0Q8QK+1ingT2+KQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GJGery6QytCzS/BxJ96klgG9in3uH26KcUBbiVG/coNDXCRq6LGVVlUT4vXq34KPuM+R2av+LeYdX9h4IZOCUg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "Fy8yr4V6obi7ZxvKYI1i85jqtwMq8tqyxQVZpRSkgeA8enqy/KvBIMdcuNdznlxQMZa72mvbHqb7vbg4Pyx95w==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "k6PWQMuoBDGGHOQTtyois2u4AwyVcIwL2LaSLlTZQm2CYcJ1pxbt6jfAnpWmzENA/wfrYRI/X9DTLoUkE4AsLw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.DependencyModel": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "Iaectmzg9Dc4ZbKX/FurrRjgO/I8rTumL5UU+Uube6vZuGetcnXoIgTA94RthFWePhdMVm8MMhVFJZdbzMsdyQ==", + "dependencies": { + "System.Text.Json": "4.6.0" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "3.1.8", + "contentHash": "7ZJUKwPipkDvuv2KJPZ3r01wp2AWNMiYH+61i0dL89F7QICknjKpWgLKLpTSUYFgl77S3b4264I6i4HzDdrb2A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.8", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.FileProviders.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "15+pa2G0bAMHbHewaQIdr/y6ag2H3yh4rd9hTXavtWDzQBkvpe2RMqFg8BxDpcQWssmjmBApGPcw93QRz6YcMg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Core": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "8vBsyGkA8ZI3lZvm1nf+9ynRC/TzPD+UtbdgTlKk+cz+AW5I41LrK8f/adGej5uXgprOA2DMjZw33vZG6vyXxA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Stores": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "linRCnWBfnqg8qjrd9u/KMISy8O4a6X/GRhpHXU0ar654YQw9LJ/Ht+psx8QLqSX5EsCBbBCZzuamatH2FWIyQ==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Identity.Core": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y/lGICwO27fCkQRK3tZseVzFjZaxfGmui990E67sB4MuiPzdJHnJDS/BeYWrHShSSBgCl4KyKRx4ux686fftPg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.0.0", + "Microsoft.Extensions.Options": "2.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Identity.Client": { + "type": "Transitive", + "resolved": "4.45.0", + "contentHash": "ircobISCLWbtE5eEoLKU+ldfZ8O41vg4lcy38KRj/znH17jvBiAl8oxcyNp89CsuqE3onxIpn21Ca7riyDDrRw==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.18.0" + } + }, + "Microsoft.Identity.Client.Extensions.Msal": { + "type": "Transitive", + "resolved": "2.19.3", + "contentHash": "zVVZjn8aW7W79rC1crioDgdOwaFTQorsSO6RgVlDDjc7MvbEGz071wSNrjVhzR0CdQn6Sefx7Abf1o7vasmrLg==", + "dependencies": { + "Microsoft.Identity.Client": "4.38.0", + "System.Security.Cryptography.ProtectedData": "4.5.0" + } + }, + "Microsoft.IdentityModel.Abstractions": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "XeE6LQtD719Qs2IG7HDi1TSw9LIkDbJ33xFiOBoHbApVw/8GpIBCbW+t7RwOjErUDyXZvjhZliwRkkLb8Z1uzg==" + }, + "Microsoft.IdentityModel.Clients.ActiveDirectory": { + "type": "Transitive", + "resolved": "3.14.2", + "contentHash": "TNsJJMiRnkeby1ovThVoV9yFsPWjAdluwOA+Nf0LtSsBVVrKQv8Qp4kYOgyNwMVj+pDwbhXISySk+4HyHVWNZQ==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "System.Runtime.Serialization.Json": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.IdentityModel.JsonWebTokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "d3h1/BaMeylKTkdP6XwRCxuOoDJZ44V9xaXr6gl5QxmpnZGdoK3bySo3OQN8ehRLJHShb94ElLUvoXyglQtgAw==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "tuEhHIQwvBEhMf8I50hy8FHmRSUkffDFP5EdLsSDV4qRcl2wvOPkQxYqEzWkh+ytW6sbdJGEXElGhmhDfAxAKg==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "0FqY5cTLQKtHrClzHEI+QxJl8OBT2vUiEQQB7UKk832JDiJJmetzYZ3AdSrPjN/3l3nkhByeWzXnhrX0JbifKg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "vtSKL7n6EnAsLyxmiviusm6LKrblT2ndnNqN6rvVq6iIHAnPCK9E2DkDx6h1Jrpy1cvbp40r0cnTg23nhEAGTA==", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "6.21.0", + "System.IdentityModel.Tokens.Jwt": "6.21.0" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "AAEHZvZyb597a+QJSmtxH3n2P1nIJGpZ4Q89GTenknRx6T6zyfzf592yW/jA5e8EHN4tNMjjXHQaYWEq5+L05w==", + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "Microsoft.IdentityModel.Logging": "6.21.0", + "System.Security.Cryptography.Cng": "4.5.0" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.OData.Core": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "/EjnJezMBjXf8OjcShhGzPY7pOO0CopgoZGhS6xsP3t2uhC+O72IBHgtQ7F3v1rRXWVtJwLGhzE1GfJUlx3c4Q==", + "dependencies": { + "Microsoft.OData.Edm": "[7.6.4]", + "Microsoft.Spatial": "[7.6.4]" + } + }, + "Microsoft.OData.Edm": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "MSSmA6kIfpgFTtNpOnnayoSj/6KSzHC1U9KOjF7cTA1PG4tZ7rIMi1pvjFc8CmYEvP4cxGl/+vrCn+HpK26HTQ==" + }, + "Microsoft.Spatial": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "3mB+Frn4LU4yb5ie9R752QiRn0Hvp9PITkSRofV/Lzm9EyLM87Fy9ziqgz75O/c712dh6GxuypMSBUGmNFwMeA==" + }, + "Microsoft.SqlServer.Server": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug==" + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "Microsoft.Win32.Registry": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "Microsoft.Win32.SystemEvents": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==" + }, + "MimeKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "l9YHMBhBUwY7qQHUp8fw0EvjcbmhN4Iggz6MdjqIShBf42+0nJTa5gu0kuupCOPuiARc9ZaS9c9f0gKz4OnxKw==", + "dependencies": { + "Portable.BouncyCastle": "1.9.0", + "System.Security.Cryptography.Pkcs": "6.0.0" + } + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "NSec.Cryptography": { + "type": "Transitive", + "resolved": "22.4.0", + "contentHash": "lEntcPYd7h3aZ8xxi/y/4TML7o8w0GEGqd+w4L1omqFLbdCBmhxJAeO2YBmv/fXbJKgKCQLm7+TD4bR605PEUQ==", + "dependencies": { + "libsodium": "[1.0.18.2, 1.0.19)" + } + }, + "Otp.NET": { + "type": "Transitive", + "resolved": "1.2.2", + "contentHash": "2hrZfkbzeWJ3tNXXt/1beg4IY+nS4F3gIfh4NVFvW0f6Pj51hGpiJ4prBz7Dmrr4ZYrA96rTERVGieZ4xYm7jA==" + }, + "Pipelines.Sockets.Unofficial": { + "type": "Transitive", + "resolved": "2.2.2", + "contentHash": "Bhk0FWxH1paI+18zr1g5cTL+ebeuDcBCR+rRFO+fKEhretgjs7MF2Mc1P64FGLecWp4zKCUOPzngBNrqVyY7Zg==", + "dependencies": { + "System.IO.Pipelines": "5.0.1" + } + }, + "Portable.BouncyCastle": { + "type": "Transitive", + "resolved": "1.9.0", + "contentHash": "eZZBCABzVOek+id9Xy04HhmgykF0wZg9wpByzrWN7q8qEI0Qen9b7tfd7w8VA3dOeesumMG7C5ZPy0jk7PSRHw==" + }, + "Quartz": { + "type": "Transitive", + "resolved": "3.4.0", + "contentHash": "N8350OAlQhd8zKg0ARFikGjh3bfAW/CF/KVxu2fTIlAALB/oC1eg54n/QAPYR5ryHuYyDr5G8/Qa4k+D/7OFRQ==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" + }, + "SendGrid": { + "type": "Transitive", + "resolved": "9.27.0", + "contentHash": "kMyXRQ8hmN2bG3tYZ7T31Ufl1kXkpuP5+WBh1BJ32WY31DTnBTCVGURoIqfbTo/tRuQfAYLxra6C8cQGN6kk+A==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "starkbank-ecdsa": "[1.3.3, 2.0.0)" + } + }, + "Sentry": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "Pkw4+51EDUQ0X02jdCZIpaM2Q4UO06VKGDE+dYYNxgvOirRXGKTKxRk4NPKJTLSTNl+2JyT9HoE7C6BTlYhLOw==" + }, + "Sentry.Serilog": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "GFTVfQdOFqZ9Vmo8EEZTx1EQMDRJjka/4v2CwxnAUh+sqHDICga4eOm4AyGzDBbE4s9iAHMgMUCceIqo+7z84w==", + "dependencies": { + "Sentry": "3.16.0", + "Serilog": "2.10.0" + } + }, + "Serilog": { + "type": "Transitive", + "resolved": "2.10.0", + "contentHash": "+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA==" + }, + "Serilog.AspNetCore": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "/JO/txIxRR61x1UXQAgUzG2Sx05o1QHCkokVBWrKzmAoDu+p5EtCAj7L/TVVg7Ezhh3GPiZ0JI9OJCmRO9tSRw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.Extensions.Logging": "5.0.0", + "Serilog": "2.10.0", + "Serilog.Extensions.Hosting": "4.2.0", + "Serilog.Formatting.Compact": "1.1.0", + "Serilog.Settings.Configuration": "3.3.0", + "Serilog.Sinks.Console": "4.0.1", + "Serilog.Sinks.Debug": "2.0.0", + "Serilog.Sinks.File": "5.0.0" + } + }, + "Serilog.Extensions.Hosting": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "gT2keceCmPQR9EX0VpXQZvUgELdfE7yqJ7MOxBhm3WLCblcvRgswEOOTgok/DHObbM15A3V/DtF3VdVDQPIZzQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.Hosting.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8", + "Serilog": "2.10.0", + "Serilog.Extensions.Logging": "3.1.0" + } + }, + "Serilog.Extensions.Logging": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "IWfem7wfrFbB3iw1OikqPFNPEzfayvDuN4WP7Ue1AVFskalMByeWk3QbtUXQR34SBkv1EbZ3AySHda/ErDgpcg==", + "dependencies": { + "Microsoft.Extensions.Logging": "2.0.0", + "Serilog": "2.9.0" + } + }, + "Serilog.Extensions.Logging.File": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "usO0qr4v9VCMBWiTJ1nQmAbPNCt40FrkDol6CpfCXbsxGZS/hH+YCueF7vvPQ32ATI0GWcMWiKRdjXEE7/HxTQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Serilog": "2.5.0", + "Serilog.Extensions.Logging": "2.0.2", + "Serilog.Formatting.Compact": "1.0.0", + "Serilog.Sinks.Async": "1.1.0", + "Serilog.Sinks.RollingFile": "3.3.0" + } + }, + "Serilog.Formatting.Compact": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "pNroKVjo+rDqlxNG5PXkRLpfSCuDOBY0ri6jp9PLe505ljqwhwZz8ospy2vWhQlFu5GkIesh3FcDs4n7sWZODA==", + "dependencies": { + "Serilog": "2.8.0" + } + }, + "Serilog.Settings.Configuration": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "7GNudISZwqaT902hqEL2OFGTZeUFWfnrNLupJkOqeF41AR3GjcxX+Hwb30xb8gG2/CDXsCMVfF8o0+8KY0fJNg==", + "dependencies": { + "Microsoft.Extensions.DependencyModel": "3.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "2.0.0", + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Async": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "xll0Kanz2BkCxuv+F3p1WXr47jdsVM0GU1n1LZvK+18QiRZ/WGFNxSNw9EMKFV5ED5gr7MUpAe6PCMNL1HGUMA==", + "dependencies": { + "Serilog": "2.1.0", + "System.Collections.Concurrent": "4.0.12" + } + }, + "Serilog.Sinks.AzureCosmosDB": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Im2/ZqjXQIpsd727qEo5Pq+br0MiNVuTvI40Yk7736tgjCpEx+omPHv4+c4fEAxnOP2kL9Ge6UoDFoDw3cjF2A==", + "dependencies": { + "Microsoft.Azure.Cosmos": "3.24.0", + "Microsoft.CSharp": "4.7.0", + "Newtonsoft.Json": "13.0.1", + "Serilog": "2.10.0", + "Serilog.Sinks.PeriodicBatching": "2.3.1" + } + }, + "Serilog.Sinks.Console": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Debug": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y6g3OBJ4JzTyyw16fDqtFcQ41qQAydnEvEqmXjhwhgjsnG/FaJ8GUqF5ldsC/bVkK8KYmqrPhDO+tm4dF6xx4A==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.File": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.PeriodicBatching": { + "type": "Transitive", + "resolved": "2.3.1", + "contentHash": "LVYvqpqjSTD8dhfxRnzpxTs8/ys3V2q01MvaY3r0eKsDgpKK1U1y/5N6gFHgiesbxG0V+O5IWdz4+c1DzoNyOQ==", + "dependencies": { + "Serilog": "2.0.0" + } + }, + "Serilog.Sinks.RollingFile": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "2lT5X1r3GH4P0bRWJfhA7etGl8Q2Ipw9AACvtAHWRUSpYZ42NGVyHoVs2ALBZ/cAkkS+tA4jl80Zie144eLQPg==", + "dependencies": { + "Serilog.Sinks.File": "3.2.0", + "System.IO": "4.1.0", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Serilog.Sinks.SyslogMessages": { + "type": "Transitive", + "resolved": "2.0.6", + "contentHash": "V2Yq2GEbk7taEPbpBLFzLXhrHrUzKf4sQu/zLrANU8XIoUn/Mr08M2E8PrcrWVXCj0R4xLMWYe0Z1sxOrMF3IA==", + "dependencies": { + "Serilog": "2.5.0", + "Serilog.Sinks.PeriodicBatching": "2.3.0" + } + }, + "StackExchange.Redis": { + "type": "Transitive", + "resolved": "2.5.43", + "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "dependencies": { + "Pipelines.Sockets.Unofficial": "2.2.2", + "System.Diagnostics.PerformanceCounter": "5.0.0" + } + }, + "starkbank-ecdsa": { + "type": "Transitive", + "resolved": "1.3.3", + "contentHash": "OblOaKb1enXn+dSp7tsx9yjwV+/BEKM9jFhshIkZTwCk7LuTFTp+wSon6rFzuPiIiTGtvVWQNUw2slHjGktJog==" + }, + "Stripe.net": { + "type": "Transitive", + "resolved": "40.0.0", + "contentHash": "SD1bGiF+sVQG3p2LXNTZ5rEG2aCnXIHokcxYS9yyW3dR01J0ryf+iNFOwid148yePZ0gCBcRxj3wiW1mTmP7UQ==", + "dependencies": { + "Newtonsoft.Json": "12.0.3", + "System.Configuration.ConfigurationManager": "6.0.0" + } + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "1.7.0", + "contentHash": "RVSM6wZUo6L2y6P3vN6gjUtyJ2IF2RVtrepF3J7nrDKfFQd5u/SnSUFclchYQis8/k5scHy9E+fVeKVQLnnkzw==" + }, + "System.Collections.NonGeneric": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "hMxFT2RhhlffyCdKLDXjx8WEC5JfCvNozAZxCablAuFRH74SCV4AgzE8yJCh/73bFnEoZgJ9MJmkjQ0dJmnKqA==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Collections.Specialized": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "/HKQyVP0yH1I0YtK7KJL/28snxHNH/bi+0lgk/+MbURF6ULhAE31MDI+NZDerNWu264YbxklXCCygISgm+HMug==", + "dependencies": { + "System.Collections.NonGeneric": "4.0.1", + "System.Globalization": "4.0.11", + "System.Globalization.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "6.0.0", + "System.Security.Permissions": "6.0.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Diagnostics.PerformanceCounter": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "kcQWWtGVC3MWMNXdMDWfrmIlFZZ2OdoeT6pSNVRtk9+Sa7jwdPiMlNwb0ZQcS7NRlT92pCfmjRtkSWUW3RAKwg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.Diagnostics.Process": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "J0wOX07+QASQblsfxmIMFc9Iq7KTXYL3zs2G/Xc704Ylv3NpuVdo6gij6V3PGiptTxqsK0K7CdXenRvKUnkA2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "Microsoft.Win32.Registry": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.TraceSource": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "6WVCczFZKXwpWpzd/iJkYnsmWTSFFiU24Xx/YdHXBcu+nFI/ehTgeqdJQFbtRPzbrO3KtRNjvkhtj4t5/WwWsA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Drawing.Common": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + } + }, + "System.Dynamic.Runtime": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "db34f6LHYM0U0JpE+sOmjar27BnqTVkbLJhgfwMpTdgTigG/Hna3m2MYVwnFzGGKnEJk2UXFuoVTr8WUbU91/A==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Formats.Asn1": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==" + }, + "System.Formats.Cbor": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "mGaLOoiw7KurJagOOcIsWUoCT5ACIiGxKlCcbYQASefBGXjnCcKTq5Hdjb94eEAKg38zXKlHw4c6EjzgBl9dIw==" + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IdentityModel.Tokens.Jwt": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "JRD8AuypBE+2zYxT3dMJomQVsPYsCqlyZhWel3J1d5nzQokSRyTueF+Q4ID3Jcu6zSZKuzOdJ1MLTkbQsDqcvQ==", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Rfm2jYCaUeGysFEZjDe7j1R4x6Z6BzumS/vUT5a1AA/AWJuGX71PoGB0RmpyX3VmrGqVnAwtfMn39OHR8Y/5+g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "qEePWsaq9LoEEIqhbGe6D5J8c9IqQOUuTzzV6wn1POlfdLkJliZY3OlB0j0f17uMWlqZYjH7txj+2YbyrIA8Yg==" + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Linq.Queryable": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "Yn/WfYe9RoRfmSLvUt2JerP0BTGGykCZkQPgojaxgzF2N0oPo+/AhB8TXOpdCcNlrG3VRtsamtK2uzsp3cqRVw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==", + "dependencies": { + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.6.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.4", + "contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.1", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.NameResolution": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "JdqRdM1Qym3YehqdKIi5LHrpypP4JMfxKQSNCJ2z4WawkG0il+N3XfNeJOxll2XrTnG7WgYYPoeiu/KOwg0DQw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.NetworkInformation": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "Q0rfeiW6QsiZuicGjrFA7cRr2+kXex0JIljTTxzI09GIftB8k+aNL31VsQD1sI2g31cw7UGDTgozA/FgeNSzsQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Linq": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.Sockets": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Overlapped": "4.0.1", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Requests": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "vxGt7C0cZixN+VqoSW4Yakc1Y9WknmxauDqzxgpw/FnBdz4kQNN51l4wxdXX5VY1xjqy//+G+4CvJWp1+f+y6Q==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Net.Http": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Claims": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Security.Principal": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Security": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Net.WebHeaderCollection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "XX2TIAN+wBSAIV51BU2FvvXMdstUa8b0FBSZmDWjZdwUMmggQSifpTOZ5fNH20z9ZCg2fkV1L5SsZnpO2RQDRQ==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0" + } + }, + "System.Net.WebSockets": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", + "dependencies": { + "Microsoft.Win32.Primitives": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.WebSockets.Client": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "NUCcDroX4lCQXgOrzlwIZ1u9YJ0krfyF0wk0ONnyLUmcQoEiYV2/OfUPRqUwQBbpH1BlGApkLgoQUwMqb5+c1g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.2", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Net.WebSockets": "4.0.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.X509Certificates": "4.1.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Numerics.Vectors": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Private.DataContractSerialization": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "lcqFBUaCZxPiUkA4dlSOoPZGtZsAuuElH2XHgLwGLxd7ZozWetV5yiz0qGAV2AUYOqw97MtZBjbLMN16Xz4vXA==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Collections.Concurrent": "4.0.12", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Emit.Lightweight": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1", + "System.Xml.XmlSerializer": "4.0.11" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Caching": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "30D6MkO8WF9jVGWZIP0hmCN8l9BTY4LCsAzLIe4xFSXzs+AjDotR7DpSmj27pFskDURzUvqYYY0ikModgBTxWw==", + "dependencies": { + "System.Configuration.ConfigurationManager": "5.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Runtime.Serialization.Json": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "+7DIJhnKYgCzUgcLbVTtRQb2l1M0FP549XFlFkQM5lmNiUBl44AfNbx4bz61xA8PzLtlYwfmif4JJJW7MPPnjg==", + "dependencies": { + "System.IO": "4.1.0", + "System.Private.DataContractSerialization": "4.1.1", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" + }, + "System.Security.Claims": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Security.Principal": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==", + "dependencies": { + "System.Formats.Asn1": "5.0.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Pkcs": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "elM3x+xSRhzQysiqo85SbidJJ2YbZlnvmh+53TuSZHsD7dNuuEWser+9EFtY+rYupBwkq2avc6ZCO3/6qACgmg==", + "dependencies": { + "System.Formats.Asn1": "6.0.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ==" + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Xml": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "i2Jn6rGXR63J0zIklImGRkDIJL4b1NfPSEbIVHBlqoIb12lfXIigCbDRpDmIEzwSo/v1U5y/rYJdzZYSyCWxvg==", + "dependencies": { + "System.Security.Cryptography.Pkcs": "4.5.0", + "System.Security.Permissions": "4.5.0" + } + }, + "System.Security.Permissions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==", + "dependencies": { + "System.Security.AccessControl": "6.0.0", + "System.Windows.Extensions": "6.0.0" + } + }, + "System.Security.Principal": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, + "System.Security.SecureString": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "sqzq9GD6/b0yqPuMpgIKBuoLf4VKAj8oAfh4kXSzPaN6eoKY3hRi9C5L27uip25qlU+BGPfb0xh2Rmbwc4jFVA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "NyscU59xX6Uo91qvhOs2Ccho3AR2TnZPomo1Z0K6YpyztBPM/A5VbkzOO19sy3A3i1TtEnTxA7bCe3Us+r5MWg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "zaJsHfESQvJ11vbXnNlkrR46IaMULk/gHxYsJphzSF+07kTjPHv+Oc14w6QEOfo3Q4hqLJgStUaYB9DBl0TmWg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Overlapped": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "f7aLuLkBoCQM2kng7zqLFBXz9Gk48gDK8lk1ih9rH/1arJJzZK9gJwNvPDhL6Ps/l6rwOr8jw+4FCHL0KKWiEg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Threading.Thread": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OHmbT+Zz065NKII/ZHcH9XO1dEuLGI1L2k7uYss+9C1jLxTC9kTZZuzUOyXHayRk+dft9CiDf3I/QZ0t8JKyBQ==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading.ThreadPool": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.ValueTuple": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" + }, + "System.Windows.Extensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==", + "dependencies": { + "System.Drawing.Common": "6.0.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "lJ8AxvkX7GQxpC6GFCeBj8ThYVyQczx2+f/cWHJU8tjS7YfI6Cv6bon70jVEgs2CiFbmmM8b9j1oZVx0dSI2Ww==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlSerializer": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "FrazwwqfIXTfq23mfv4zH+BjqkSFNaNFBtjzu3I9NRmG8EELYyrv/fJnttCIwRMFRR/YKXF1hmsMmMEnl55HGw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1" + } + }, + "System.Xml.XPath": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "v1JQ5SETnQusqmS3RwStF7vwQ3L02imIzl++sewmt23VGygix04pEH+FCj1yWb+z4GDzKiljr1W7Wfvrx0YwgA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XPath.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "A/uxsWi/Ifzkmd4ArTLISMbfFs6XpRPsXZonrIqyTY70xi8t+mDtvSM5Os0RqyRDobjMBwIDHDL4NOIbkDwf7A==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XPath": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "YubicoDotNetClient": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "uP5F3Ko1gqZi3lwS2R/jAAwhBxXs/6PKDpS6FdQjsBA5qmF0hQmbtfxM6QHTXOMoWbUtfetG7+LtgmG8T5zDIg==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "core": { + "type": "Project", + "dependencies": { + "AWSSDK.SQS": "[3.7.2.47, )", + "AWSSDK.SimpleEmail": "[3.7.0.150, )", + "AspNetCoreRateLimit": "[4.0.2, )", + "AspNetCoreRateLimit.Redis": "[1.0.1, )", + "Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.2.1, )", + "Azure.Storage.Blobs": "[12.11.0, )", + "Azure.Storage.Queues": "[12.9.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "Fido2.AspNet": "[3.0.1, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "MailKit": "[3.2.0, )", + "Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )", + "Microsoft.Azure.Cosmos.Table": "[1.0.8, )", + "Microsoft.Azure.NotificationHubs": "[4.1.0, )", + "Microsoft.Azure.ServiceBus": "[5.2.0, )", + "Microsoft.Data.SqlClient": "[5.0.1, )", + "Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )", + "Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )", + "Microsoft.Extensions.Identity.Stores": "[6.0.4, )", + "Newtonsoft.Json": "[13.0.1, )", + "Otp.NET": "[1.2.2, )", + "Quartz": "[3.4.0, )", + "SendGrid": "[9.27.0, )", + "Sentry.Serilog": "[3.16.0, )", + "Serilog.AspNetCore": "[5.0.0, )", + "Serilog.Extensions.Logging": "[3.1.0, )", + "Serilog.Extensions.Logging.File": "[2.0.0, )", + "Serilog.Sinks.AzureCosmosDB": "[2.0.0, )", + "Serilog.Sinks.SyslogMessages": "[2.0.6, )", + "Stripe.net": "[40.0.0, )", + "YubicoDotNetClient": "[1.2.0, )" + } + } + } + } +} \ No newline at end of file diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Commercial.Infrastructure.EntityFramework.csproj b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Commercial.Infrastructure.EntityFramework.csproj new file mode 100644 index 000000000..7e94399c0 --- /dev/null +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Commercial.Infrastructure.EntityFramework.csproj @@ -0,0 +1,13 @@ + + + + enable + + + + + + + + + diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/AccessPolicyRepository.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/AccessPolicyRepository.cs new file mode 100644 index 000000000..dd56e08fc --- /dev/null +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/AccessPolicyRepository.cs @@ -0,0 +1,184 @@ +using AutoMapper; +using Bit.Core.SecretsManager.Repositories; +using Bit.Infrastructure.EntityFramework.Repositories; +using Bit.Infrastructure.EntityFramework.SecretsManager.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Commercial.Infrastructure.EntityFramework.SecretsManager.Repositories; + +public class AccessPolicyRepository : BaseEntityFrameworkRepository, IAccessPolicyRepository +{ + public AccessPolicyRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) : base(serviceScopeFactory, + mapper) + { + } + + public async Task> CreateManyAsync(List baseAccessPolicies) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + foreach (var baseAccessPolicy in baseAccessPolicies) + { + baseAccessPolicy.SetNewId(); + switch (baseAccessPolicy) + { + case Core.SecretsManager.Entities.UserProjectAccessPolicy accessPolicy: + { + var entity = + Mapper.Map(accessPolicy); + await dbContext.AddAsync(entity); + break; + } + case Core.SecretsManager.Entities.UserServiceAccountAccessPolicy accessPolicy: + { + var entity = + Mapper.Map(accessPolicy); + await dbContext.AddAsync(entity); + break; + } + case Core.SecretsManager.Entities.GroupProjectAccessPolicy accessPolicy: + { + var entity = Mapper.Map(accessPolicy); + await dbContext.AddAsync(entity); + break; + } + case Core.SecretsManager.Entities.GroupServiceAccountAccessPolicy accessPolicy: + { + var entity = Mapper.Map(accessPolicy); + await dbContext.AddAsync(entity); + break; + } + case Core.SecretsManager.Entities.ServiceAccountProjectAccessPolicy accessPolicy: + { + var entity = Mapper.Map(accessPolicy); + await dbContext.AddAsync(entity); + break; + } + } + } + + await dbContext.SaveChangesAsync(); + return baseAccessPolicies; + } + } + + public async Task AccessPolicyExists(Core.SecretsManager.Entities.BaseAccessPolicy baseAccessPolicy) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + switch (baseAccessPolicy) + { + case Core.SecretsManager.Entities.UserProjectAccessPolicy accessPolicy: + { + var policy = await dbContext.UserProjectAccessPolicy + .Where(c => c.OrganizationUserId == accessPolicy.OrganizationUserId && + c.GrantedProjectId == accessPolicy.GrantedProjectId) + .FirstOrDefaultAsync(); + return policy != null; + } + case Core.SecretsManager.Entities.GroupProjectAccessPolicy accessPolicy: + { + var policy = await dbContext.GroupProjectAccessPolicy + .Where(c => c.GroupId == accessPolicy.GroupId && + c.GrantedProjectId == accessPolicy.GrantedProjectId) + .FirstOrDefaultAsync(); + return policy != null; + } + case Core.SecretsManager.Entities.ServiceAccountProjectAccessPolicy accessPolicy: + { + var policy = await dbContext.ServiceAccountProjectAccessPolicy + .Where(c => c.ServiceAccountId == accessPolicy.ServiceAccountId && + c.GrantedProjectId == accessPolicy.GrantedProjectId) + .FirstOrDefaultAsync(); + return policy != null; + } + default: + throw new ArgumentException("Unsupported access policy type provided.", nameof(baseAccessPolicy)); + } + } + } + + public async Task GetByIdAsync(Guid id) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var entity = await dbContext.AccessPolicies.Where(ap => ap.Id == id) + .Include(ap => ((UserProjectAccessPolicy)ap).OrganizationUser.User) + .Include(ap => ((GroupProjectAccessPolicy)ap).Group) + .Include(ap => ((ServiceAccountProjectAccessPolicy)ap).ServiceAccount) + .FirstOrDefaultAsync(); + + if (entity == null) + { + return null; + } + + return MapToCore(entity); + } + } + + public async Task ReplaceAsync(Core.SecretsManager.Entities.BaseAccessPolicy baseAccessPolicy) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var entity = await dbContext.AccessPolicies.FindAsync(baseAccessPolicy.Id); + if (entity != null) + { + dbContext.AccessPolicies.Attach(entity); + entity.Write = baseAccessPolicy.Write; + entity.Read = baseAccessPolicy.Read; + entity.RevisionDate = baseAccessPolicy.RevisionDate; + await dbContext.SaveChangesAsync(); + } + } + } + + public async Task?> GetManyByProjectId(Guid id) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + + var entities = await dbContext.AccessPolicies.Where(ap => + ((UserProjectAccessPolicy)ap).GrantedProjectId == id || + ((GroupProjectAccessPolicy)ap).GrantedProjectId == id || + ((ServiceAccountProjectAccessPolicy)ap).GrantedProjectId == id) + .Include(ap => ((UserProjectAccessPolicy)ap).OrganizationUser.User) + .Include(ap => ((GroupProjectAccessPolicy)ap).Group) + .Include(ap => ((ServiceAccountProjectAccessPolicy)ap).ServiceAccount) + .ToListAsync(); + + return !entities.Any() ? null : entities.Select(MapToCore); + } + } + + public async Task DeleteAsync(Guid id) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var entity = await dbContext.AccessPolicies.FindAsync(id); + if (entity != null) + { + dbContext.Remove(entity); + await dbContext.SaveChangesAsync(); + } + } + } + + private Core.SecretsManager.Entities.BaseAccessPolicy MapToCore(BaseAccessPolicy baseAccessPolicyEntity) + { + return baseAccessPolicyEntity switch + { + UserProjectAccessPolicy ap => Mapper.Map(ap), + GroupProjectAccessPolicy ap => Mapper.Map(ap), + ServiceAccountProjectAccessPolicy ap => Mapper.Map(ap), + _ => throw new ArgumentException("Unsupported access policy type") + }; + } +} diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ProjectRepository.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ProjectRepository.cs new file mode 100644 index 000000000..bf35a47dc --- /dev/null +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ProjectRepository.cs @@ -0,0 +1,106 @@ +using System.Linq.Expressions; +using AutoMapper; +using Bit.Core.Enums; +using Bit.Core.SecretsManager.Repositories; +using Bit.Infrastructure.EntityFramework.Repositories; +using Bit.Infrastructure.EntityFramework.SecretsManager.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Commercial.Infrastructure.EntityFramework.SecretsManager.Repositories; + +public class ProjectRepository : Repository, IProjectRepository +{ + public ProjectRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) + : base(serviceScopeFactory, mapper, db => db.Project) + { } + + public override async Task GetByIdAsync(Guid id) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var project = await dbContext.Project + .Where(c => c.Id == id && c.DeletedDate == null) + .FirstOrDefaultAsync(); + return Mapper.Map(project); + } + } + + public async Task> GetManyByOrganizationIdAsync(Guid organizationId, Guid userId, AccessClientType accessType) + { + using var scope = ServiceScopeFactory.CreateScope(); + var dbContext = GetDatabaseContext(scope); + var query = dbContext.Project.Where(p => p.OrganizationId == organizationId && p.DeletedDate == null); + + query = accessType switch + { + AccessClientType.NoAccessCheck => query, + AccessClientType.User => query.Where(UserHasReadAccessToProject(userId)), + AccessClientType.ServiceAccount => query.Where(ServiceAccountHasReadAccessToProject(userId)), + _ => throw new ArgumentOutOfRangeException(nameof(accessType), accessType, null), + }; + + var projects = await query.OrderBy(p => p.RevisionDate).ToListAsync(); + return Mapper.Map>(projects); + } + + private static Expression> UserHasReadAccessToProject(Guid userId) => p => + p.UserAccessPolicies.Any(ap => ap.OrganizationUser.User.Id == userId && ap.Read) || + p.GroupAccessPolicies.Any(ap => ap.Group.GroupUsers.Any(gu => gu.OrganizationUser.User.Id == userId && ap.Read)); + + private static Expression> UserHasWriteAccessToProject(Guid userId) => p => + p.UserAccessPolicies.Any(ap => ap.OrganizationUser.User.Id == userId && ap.Write) || + p.GroupAccessPolicies.Any(ap => ap.Group.GroupUsers.Any(gu => gu.OrganizationUser.User.Id == userId && ap.Write)); + + private static Expression> ServiceAccountHasReadAccessToProject(Guid serviceAccountId) => p => + p.ServiceAccountAccessPolicies.Any(ap => ap.ServiceAccount.Id == serviceAccountId && ap.Read); + + public async Task DeleteManyByIdAsync(IEnumerable ids) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var projects = dbContext.Project.Where(c => ids.Contains(c.Id)); + await projects.ForEachAsync(project => + { + dbContext.Remove(project); + }); + await dbContext.SaveChangesAsync(); + } + } + + public async Task> GetManyByIds(IEnumerable ids) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var projects = await dbContext.Project + .Where(c => ids.Contains(c.Id) && c.DeletedDate == null) + .ToListAsync(); + return Mapper.Map>(projects); + } + } + + public async Task UserHasReadAccessToProject(Guid id, Guid userId) + { + using var scope = ServiceScopeFactory.CreateScope(); + var dbContext = GetDatabaseContext(scope); + var query = dbContext.Project + .Where(p => p.Id == id) + .Where(UserHasReadAccessToProject(userId)); + + return await query.AnyAsync(); + } + + public async Task UserHasWriteAccessToProject(Guid id, Guid userId) + { + using var scope = ServiceScopeFactory.CreateScope(); + var dbContext = GetDatabaseContext(scope); + var query = dbContext.Project + .Where(p => p.Id == id) + .Where(UserHasWriteAccessToProject(userId)); + + return await query.AnyAsync(); + } +} diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/SecretRepository.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/SecretRepository.cs new file mode 100644 index 000000000..a17af71e6 --- /dev/null +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/SecretRepository.cs @@ -0,0 +1,139 @@ +using AutoMapper; +using Bit.Core.SecretsManager.Repositories; +using Bit.Infrastructure.EntityFramework; +using Bit.Infrastructure.EntityFramework.Repositories; +using Bit.Infrastructure.EntityFramework.SecretsManager.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Commercial.Infrastructure.EntityFramework.SecretsManager.Repositories; + +public class SecretRepository : Repository, ISecretRepository +{ + public SecretRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) + : base(serviceScopeFactory, mapper, db => db.Secret) + { } + + public override async Task GetByIdAsync(Guid id) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var secret = await dbContext.Secret + .Include("Projects") + .Where(c => c.Id == id && c.DeletedDate == null) + .FirstOrDefaultAsync(); + return Mapper.Map(secret); + } + } + + public async Task> GetManyByIds(IEnumerable ids) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var secrets = await dbContext.Secret + .Where(c => ids.Contains(c.Id) && c.DeletedDate == null) + .ToListAsync(); + return Mapper.Map>(secrets); + } + } + + public async Task> GetManyByOrganizationIdAsync(Guid organizationId) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var secrets = await dbContext.Secret + .Where(c => c.OrganizationId == organizationId && c.DeletedDate == null) + .Include("Projects") + .OrderBy(c => c.RevisionDate) + .ToListAsync(); + + return Mapper.Map>(secrets); + } + } + + public async Task> GetManyByProjectIdAsync(Guid projectId) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var secrets = await dbContext.Secret + .Where(s => s.Projects.Any(p => p.Id == projectId) && s.DeletedDate == null).Include("Projects") + .OrderBy(s => s.RevisionDate).ToListAsync(); + + return Mapper.Map>(secrets); + } + } + + public override async Task CreateAsync(Core.SecretsManager.Entities.Secret secret) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + secret.SetNewId(); + var entity = Mapper.Map(secret); + + if (secret.Projects?.Count > 0) + { + foreach (var p in entity.Projects) + { + dbContext.Attach(p); + } + } + + await dbContext.AddAsync(entity); + await dbContext.SaveChangesAsync(); + secret.Id = entity.Id; + return secret; + } + } + + public async Task UpdateAsync(Core.SecretsManager.Entities.Secret secret) + { + + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var mappedEntity = Mapper.Map(secret); + var entity = await dbContext.Secret + .Include("Projects") + .FirstAsync(s => s.Id == secret.Id); + + foreach (var p in entity.Projects?.Where(p => mappedEntity.Projects.All(mp => mp.Id != p.Id))) + { + entity.Projects.Remove(p); + } + + // Add new relationships + foreach (var project in mappedEntity.Projects?.Where(p => entity.Projects.All(ep => ep.Id != p.Id))) + { + var p = dbContext.AttachToOrGet(_ => _.Id == project.Id, () => project); + entity.Projects.Add(p); + } + + dbContext.Entry(entity).CurrentValues.SetValues(mappedEntity); + await dbContext.SaveChangesAsync(); + } + + return secret; + } + + public async Task SoftDeleteManyByIdAsync(IEnumerable ids) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var utcNow = DateTime.UtcNow; + var secrets = dbContext.Secret.Where(c => ids.Contains(c.Id)); + await secrets.ForEachAsync(secret => + { + dbContext.Attach(secret); + secret.DeletedDate = utcNow; + secret.RevisionDate = utcNow; + }); + await dbContext.SaveChangesAsync(); + } + } +} diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ServiceAccountRepository.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ServiceAccountRepository.cs new file mode 100644 index 000000000..4632abc8f --- /dev/null +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/ServiceAccountRepository.cs @@ -0,0 +1,64 @@ +using System.Linq.Expressions; +using AutoMapper; +using Bit.Core.Enums; +using Bit.Core.SecretsManager.Repositories; +using Bit.Infrastructure.EntityFramework.Repositories; +using Bit.Infrastructure.EntityFramework.SecretsManager.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Commercial.Infrastructure.EntityFramework.SecretsManager.Repositories; + +public class ServiceAccountRepository : Repository, IServiceAccountRepository +{ + public ServiceAccountRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) + : base(serviceScopeFactory, mapper, db => db.ServiceAccount) + { } + + public async Task> GetManyByOrganizationIdAsync(Guid organizationId, Guid userId, AccessClientType accessType) + { + using var scope = ServiceScopeFactory.CreateScope(); + var dbContext = GetDatabaseContext(scope); + var query = dbContext.ServiceAccount.Where(c => c.OrganizationId == organizationId); + + query = accessType switch + { + AccessClientType.NoAccessCheck => query, + AccessClientType.User => query.Where(UserHasReadAccessToServiceAccount(userId)), + _ => throw new ArgumentOutOfRangeException(nameof(accessType), accessType, null), + }; + + var serviceAccounts = await query.OrderBy(c => c.RevisionDate).ToListAsync(); + return Mapper.Map>(serviceAccounts); + } + + public async Task UserHasReadAccessToServiceAccount(Guid id, Guid userId) + { + using var scope = ServiceScopeFactory.CreateScope(); + var dbContext = GetDatabaseContext(scope); + var query = dbContext.ServiceAccount + .Where(sa => sa.Id == id) + .Where(UserHasReadAccessToServiceAccount(userId)); + + return await query.AnyAsync(); + } + + public async Task UserHasWriteAccessToServiceAccount(Guid id, Guid userId) + { + using var scope = ServiceScopeFactory.CreateScope(); + var dbContext = GetDatabaseContext(scope); + var query = dbContext.ServiceAccount + .Where(sa => sa.Id == id) + .Where(UserHasWriteAccessToServiceAccount(userId)); + + return await query.AnyAsync(); + } + + private static Expression> UserHasReadAccessToServiceAccount(Guid userId) => sa => + sa.UserAccessPolicies.Any(ap => ap.OrganizationUser.User.Id == userId && ap.Read) || + sa.GroupAccessPolicies.Any(ap => ap.Group.GroupUsers.Any(gu => gu.OrganizationUser.User.Id == userId && ap.Read)); + + private static Expression> UserHasWriteAccessToServiceAccount(Guid userId) => sa => + sa.UserAccessPolicies.Any(ap => ap.OrganizationUser.User.Id == userId && ap.Write) || + sa.GroupAccessPolicies.Any(ap => ap.Group.GroupUsers.Any(gu => gu.OrganizationUser.User.Id == userId && ap.Write)); +} diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/SecretsManagerEFServiceCollectionExtensions.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/SecretsManagerEFServiceCollectionExtensions.cs new file mode 100644 index 000000000..d6c884807 --- /dev/null +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/SecretsManagerEFServiceCollectionExtensions.cs @@ -0,0 +1,16 @@ +using Bit.Commercial.Infrastructure.EntityFramework.SecretsManager.Repositories; +using Bit.Core.SecretsManager.Repositories; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Commercial.Infrastructure.EntityFramework.SecretsManager; + +public static class SecretsManagerEfServiceCollectionExtensions +{ + public static void AddSecretsManagerEfRepositories(this IServiceCollection services) + { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + } +} diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/packages.lock.json b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/packages.lock.json new file mode 100644 index 000000000..f2b6cb0b2 --- /dev/null +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/packages.lock.json @@ -0,0 +1,2772 @@ +{ + "version": 1, + "dependencies": { + "net6.0": { + "AutoMapper.Extensions.Microsoft.DependencyInjection": { + "type": "Direct", + "requested": "[11.0.0, )", + "resolved": "11.0.0", + "contentHash": "0asw5WxdCFh2OTi9Gv+oKyH9SzxwYQSnO8TV5Dd0GggovILzJW4UimP26JAcxc3yB5NnC5urooZ1BBs8ElpiBw==", + "dependencies": { + "AutoMapper": "11.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "AspNetCoreRateLimit": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "FzXAJFgaRjKfnKAVwjEEC7OAGQM5v/I3sQw2tpzmR0yHTCGhUAxZzDuwZiXTk8XLrI6vovzkqKkfKmiDl3nYMg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.1", + "Microsoft.Extensions.Options": "6.0.0", + "Newtonsoft.Json": "13.0.1" + } + }, + "AspNetCoreRateLimit.Redis": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "CsSGy/7SXt6iBOKg0xCvsRjb/ZHshbtr2Of1MHc912L2sLnZqadUrTboyXZC+ZlgEBeJ14GyjPTu8ZyfEhGUnw==", + "dependencies": { + "AspNetCoreRateLimit": "4.0.2", + "StackExchange.Redis": "2.5.43" + } + }, + "AutoMapper": { + "type": "Transitive", + "resolved": "11.0.0", + "contentHash": "+596AnKykYCk9RxXCEF4GYuapSebQtFVvIA1oVG1rrRkCLAC7AkWehJ0brCfYUbdDW3v1H/p0W3hob7JoXGjMw==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "AWSSDK.Core": { + "type": "Transitive", + "resolved": "3.7.10.11", + "contentHash": "B+M7ggPC0FogATRPQxDXL0eTusCQtXulW4zCuX39yiHV8+u9MEXRytcAw0ZA3zFBYYx6ovl9lklho6OQo1DRRQ==" + }, + "AWSSDK.SimpleEmail": { + "type": "Transitive", + "resolved": "3.7.0.150", + "contentHash": "rc/4ZnISfbgTfqz5/BWqMHBAzk4R09qfe1xkdJf2jXo44Zn2X72W8IiLLweBtmNhL7d8Tcf6UCtOHYkFwxHvug==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "AWSSDK.SQS": { + "type": "Transitive", + "resolved": "3.7.2.47", + "contentHash": "RPTVBsY333n+aIEqw148Envx9OQkE1/jhjlioNXDP6BrA3fAPN9A+2HoA02c0KSp/sazXYWg8w/kDL8FchH8Dw==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.24.0", + "contentHash": "+/qI1j2oU1S4/nvxb2k/wDsol00iGf1AyJX5g3epV7eOpQEP/2xcgh/cxgKMeFgn3U2fmgSiBnQZdkV+l5y0Uw==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Numerics.Vectors": "4.5.0", + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Extensions.AspNetCore.DataProtection.Blobs": { + "type": "Transitive", + "resolved": "1.2.1", + "contentHash": "wxvkC6DeWThBtaPbsWdicp5Ltya4J8JuhxmZJDQkhnXG7oihfu8RqBV6w/X1nMieuIOq1qQaGTvjx7nEHHfxSQ==", + "dependencies": { + "Azure.Core": "1.14.0", + "Azure.Storage.Blobs": "12.8.0", + "Microsoft.AspNetCore.DataProtection": "2.1.0" + } + }, + "Azure.Identity": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "EycyMsb6rD2PK9P0SyibFfEhvWWttdrYhyPF4f41uzdB/44yQlV+2Wehxyg489Rj6gbPvSPgbKq0xsHJBhipZA==", + "dependencies": { + "Azure.Core": "1.24.0", + "Microsoft.Identity.Client": "4.39.0", + "Microsoft.Identity.Client.Extensions.Msal": "2.19.3", + "System.Memory": "4.5.4", + "System.Security.Cryptography.ProtectedData": "4.7.0", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Storage.Blobs": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "50eRjIhY7Q1JN7kT2MSawDKCcwSb7uRZUkz00P/BLjSg47gm2hxUYsnJPyvzCHntYMbOWzrvaVQTwYwXabaR5Q==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Text.Json": "4.7.2" + } + }, + "Azure.Storage.Common": { + "type": "Transitive", + "resolved": "12.10.0", + "contentHash": "vYkHGzUkdZTace/cDPZLG+Mh/EoPqQuGxDIBOau9D+XWoDPmuUFGk325aXplkFE4JFGpSwoytNYzk/qBCaiHqg==", + "dependencies": { + "Azure.Core": "1.22.0", + "System.IO.Hashing": "6.0.0" + } + }, + "Azure.Storage.Queues": { + "type": "Transitive", + "resolved": "12.9.0", + "contentHash": "jDiyHtsCUCrWNvZW7SjJnJb46UhpdgQrWCbL8aWpapDHlq9LvbvxYpfLh4dfKAz09QiTznLMIU3i+md9+7GzqQ==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, + "BitPay.Light": { + "type": "Transitive", + "resolved": "1.0.1907", + "contentHash": "QTTIgXakHrRNQPxNyH7bZ7frm0bI8N6gRDtiqVyKG/QYQ+KfjN70xt0zQ0kO0zf8UBaKuwcV5B7vvpXtzR9ijg==", + "dependencies": { + "Newtonsoft.Json": "12.0.2" + } + }, + "Braintree": { + "type": "Transitive", + "resolved": "5.12.0", + "contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "System.Xml.XPath.XmlDocument": "4.3.0" + } + }, + "Fido2": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "S0Bz1vfcKlO4Jase3AWp5XnQ746psf4oGx5kL+D2A10j1SsjoAOAIIpanSwfi0cEepDHgk1bClcOKY5TjOzGdA==", + "dependencies": { + "Fido2.Models": "3.0.1", + "Microsoft.Extensions.Http": "6.0.0", + "NSec.Cryptography": "22.4.0", + "System.Formats.Cbor": "6.0.0", + "System.IdentityModel.Tokens.Jwt": "6.17.0" + } + }, + "Fido2.AspNet": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "5n5shEXD7RFUyTesjUHGDjkpgES7j4KotQo1GwUcS08k+fx+1tl/zCFHJ9RFDuUwO+S681ZILT2PyA67IPYpaA==", + "dependencies": { + "Fido2": "3.0.1", + "Fido2.Models": "3.0.1" + } + }, + "Fido2.Models": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "mgjcuGETuYSCUEaZG+jQeeuuEMkDLc4GDJHBvKDdOz6oSOWp5adPdWP4btZx7Pi+9fu4szN3JIjJmby67MaILw==" + }, + "Handlebars.Net": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "p60QyeBYpZmcZdIXRMqs9XySIBaxJ0lj3+QD0EJVr4ybTigOTCumXMMin5dPwjo9At1UwkDZ3gGwa1lmGjG6DA==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "IdentityModel": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "System.Text.Encodings.Web": "4.7.0" + } + }, + "IdentityModel.AspNetCore.OAuth2Introspection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==", + "dependencies": { + "IdentityModel": "4.0.0" + } + }, + "IdentityServer4": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==", + "dependencies": { + "IdentityModel": "4.4.0", + "IdentityServer4.Storage": "4.1.2", + "Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0", + "Newtonsoft.Json": "12.0.2" + } + }, + "IdentityServer4.AccessTokenValidation": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==", + "dependencies": { + "IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1", + "Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0" + } + }, + "IdentityServer4.Storage": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==", + "dependencies": { + "IdentityModel": "4.4.0" + } + }, + "libsodium": { + "type": "Transitive", + "resolved": "1.0.18.2", + "contentHash": "flArHoVdscSzyV8ZdPV+bqqY2TTFlaN+xZf/vIqsmHI51KVcD/mOdUPaK3n/k/wGKz8dppiktXUqSmf3AXFgig==" + }, + "linq2db": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "6/u1EzQlV25bhN0Ej/I5dLV5Hgxun+ww/TX2VnMBnSVytED2VzQGeFIO/14I624GkfPOtB79x1ooL3F18dAbdw==" + }, + "linq2db.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.11.0", + "contentHash": "mS+L6HyVHP3oJaTuFVZswNmPpTfYleGjDTo2IWBJmYXZpSQ5EPw1DpHzmyLAiQd+93ofy0Ala+9HWzv6/k73ZQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "6.0.5", + "linq2db": "4.4.0" + } + }, + "MailKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "5MTpTqmjqT7HPvYbP3HozRZMth5vSaT0ReN0iM3rAM4CgLI/R1qqtLDDNWGnFFIlcNzeJkZQRJJMkv8cgzWBbA==", + "dependencies": { + "MimeKit": "3.2.0" + } + }, + "Microsoft.AspNetCore.Authentication.JwtBearer": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "joDS3+lD1i9qcdFLWP4D316t3bHpezmTNOzbMIf9ZcRPX4QTuiUutZcQn/kZplf3BiLHqwUChZXxPjCAMKaKAQ==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0" + } + }, + "Microsoft.AspNetCore.Authentication.OpenIdConnect": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0" + } + }, + "Microsoft.AspNetCore.Cryptography.Internal": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "/0FX1OqckMmXAAlsHgBFNymTZuq4nuAOMhiwm6e8CEMi2aOjnMYwiMc7mtvpGTAO0O4C0zwx+iaChxDgvqit2A==" + }, + "Microsoft.AspNetCore.Cryptography.KeyDerivation": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "1Lbwrxg/HRY/nbrkcrB3EUXUYQN8Tkw7Ktgb6/2on2P7ybT5aM59H05gk+OBC8ZTBxwdle9e1tyT3wxEYKw5xw==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "6.0.4" + } + }, + "Microsoft.AspNetCore.DataProtection": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "G+UoMHL0xiyFh30wkL7Bv/XL6eugTAKYhLPS53k1/Me1bYRwOOw+8VL/q0ppq3/yMzpHX+MkExaCTDlYl48FgA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "2.1.0", + "Microsoft.AspNetCore.DataProtection.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.1.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0", + "Microsoft.Extensions.Logging.Abstractions": "2.1.0", + "Microsoft.Extensions.Options": "2.1.0", + "Microsoft.Win32.Registry": "4.5.0", + "System.Security.Cryptography.Xml": "4.5.0", + "System.Security.Principal.Windows": "4.5.0" + } + }, + "Microsoft.AspNetCore.DataProtection.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "2+HVDhUqrnV9+EJNEewSy+Gk4hOVPzLPMpFDZI7kuH7NWxtbNkI6A6gT5lO2/kEPMyM8/iLWtohbOwjpC9rHVw==" + }, + "Microsoft.AspNetCore.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "1TQgBfd/NPZLR2o/h6l5Cml2ZCF5hsyV4h9WEwWwAIavrbdTnaNozGGcTOd4AOgQvogMM9UM1ajflm9Cwd0jLQ==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Http.Abstractions": "2.1.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "YTKMi2vHX6P+WHEVpW/DS+eFHnwivCSMklkyamcK1ETtc/4j8H3VR0kgW8XIBqukNxhD8k5wYt22P7PhrWSXjQ==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "Microsoft.Extensions.Configuration.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Http.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "vbFDyKsSYBnxl3+RABtN79b0vsTcG66fDY8vD6Nqvu9uLtSej70Q5NcbGlnN6bJpZci5orSdgFTHMhBywivDPg==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Features": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "UmkUePxRjsQW0j5euFFscBwjvTu25b8+qIK/2fI3GvcqQ+mkwgbWNAT8b/Gkoei1m2bTWC07lSdutuRDPPLcJA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.0" + } + }, + "Microsoft.Azure.Amqp": { + "type": "Transitive", + "resolved": "2.4.11", + "contentHash": "7x5fu2f6TLQDDJS0sY5qW8/daFwJaY9O75YvU8RcUfRzbug+9YGjXUBxoRrprgyi0jxdBAMQL05p1s783SOSFQ==", + "dependencies": { + "System.Net.WebSockets.Client": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.Azure.Cosmos": { + "type": "Transitive", + "resolved": "3.24.0", + "contentHash": "QpUe5ho6OzlXwgcJVgAmOR7t3XLC9RI4t8T96RZY61pSOIllPOJdp30L0LwA16tKcqi5r2KayEgWO/MS9fh/6A==", + "dependencies": { + "Azure.Core": "1.3.0", + "Microsoft.Bcl.AsyncInterfaces": "1.0.0", + "Microsoft.Bcl.HashCode": "1.1.0", + "Newtonsoft.Json": "10.0.2", + "System.Buffers": "4.5.1", + "System.Collections.Immutable": "1.7.0", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Memory": "4.5.4", + "System.Numerics.Vectors": "4.5.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3", + "System.Threading.Tasks.Extensions": "4.5.4", + "System.ValueTuple": "4.5.0" + } + }, + "Microsoft.Azure.Cosmos.Table": { + "type": "Transitive", + "resolved": "1.0.8", + "contentHash": "ToeEd1yijM7nQfLYvdFLG//RjKPmfqm45eOm86UAKrxtyGI/CXqP8iL74mzBp6mZ9A/K/ZYA2fVdpH0xHR5Keg==", + "dependencies": { + "Microsoft.Azure.DocumentDB.Core": "2.11.2", + "Microsoft.OData.Core": "7.6.4", + "Newtonsoft.Json": "10.0.2" + } + }, + "Microsoft.Azure.DocumentDB.Core": { + "type": "Transitive", + "resolved": "2.11.2", + "contentHash": "cA8eWrTFbYrkHrz095x4CUGb7wqQgA1slzFZCYexhNwz6Zcn3v+S1yvWMGwGRmRjT0MKU9tYdFWgLfT0OjSycw==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "Newtonsoft.Json": "9.0.1", + "System.Collections.Immutable": "1.3.0", + "System.Collections.NonGeneric": "4.0.1", + "System.Collections.Specialized": "4.0.1", + "System.Diagnostics.TraceSource": "4.0.0", + "System.Dynamic.Runtime": "4.0.11", + "System.Linq.Queryable": "4.0.1", + "System.Net.Http": "4.3.4", + "System.Net.NameResolution": "4.0.0", + "System.Net.NetworkInformation": "4.1.0", + "System.Net.Requests": "4.0.11", + "System.Net.Security": "4.3.2", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Security.SecureString": "4.0.0" + } + }, + "Microsoft.Azure.NotificationHubs": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "C2SssjX3e6/HIo1OCImQDDVOn64d1+gkgEmgxJryzkwixyivJHWH2YIgxZs33pyzVQcZWx5PR2tqLkQ7riSq8Q==", + "dependencies": { + "Microsoft.Extensions.Caching.Memory": "3.1.8", + "Newtonsoft.Json": "12.0.3" + } + }, + "Microsoft.Azure.ServiceBus": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "wyZNJggyFNtKxd+HgvcTiuRYuTjDGi+pgE4RcBvFbfvNiarKr5AOlE4Ne7on1eUJZuMuEa19wN5dj694HlP60A==", + "dependencies": { + "Microsoft.Azure.Amqp": "2.4.11", + "Microsoft.Azure.Services.AppAuthentication": "[1.0.3, 2.0.0)", + "Newtonsoft.Json": "10.0.3", + "System.Diagnostics.DiagnosticSource": "4.5.1", + "System.IdentityModel.Tokens.Jwt": "5.4.0" + } + }, + "Microsoft.Azure.Services.AppAuthentication": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "ywpQaK1klu1IoX4VUf+TBmU4kR71aWNI6O5rEIJU8z28L2xhJhnIm7k2Nf1Zu/PygeuOtt5g0QPCk5+lLltbeQ==", + "dependencies": { + "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.14.2", + "NETStandard.Library": "1.6.1", + "System.Diagnostics.Process": "4.3.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "yuvf07qFWFqtK3P/MRkEKLhn5r2UbSpVueRziSqj0yJQIKFwG1pq9mOayK3zE5qZCTs0CbrwL9M6R8VwqyGy2w==" + }, + "Microsoft.Bcl.HashCode": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "J2G1k+u5unBV+aYcwxo94ip16Rkp65pgWFb0R6zwJipzWNMgvqlWeuI7/+R+e8bob66LnSG+llLJ+z8wI94cHg==" + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, + "Microsoft.Data.SqlClient": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "uu8dfrsx081cSbEevWuZAvqdmANDGJkbLBL2G3j0LAZxX1Oy8RCVAaC4Lcuak6jNicWP6CWvHqBTIEmQNSxQlw==", + "dependencies": { + "Azure.Identity": "1.6.0", + "Microsoft.Data.SqlClient.SNI.runtime": "5.0.1", + "Microsoft.Identity.Client": "4.45.0", + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.21.0", + "Microsoft.SqlServer.Server": "1.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Buffers": "4.5.1", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Diagnostics.DiagnosticSource": "5.0.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime.Caching": "5.0.0", + "System.Security.Cryptography.Cng": "5.0.0", + "System.Security.Principal.Windows": "5.0.0", + "System.Text.Encoding.CodePages": "5.0.0", + "System.Text.Encodings.Web": "4.7.2" + } + }, + "Microsoft.Data.SqlClient.SNI.runtime": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "y0X5MxiNdbITJYoafJ2ruaX6hqO0twpCGR/ipiDOe85JKLU8WL4TuAQfDe5qtt3bND5Je26HnrarLSAMMnVTNg==" + }, + "Microsoft.Data.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bui5wPPqq9OwTL5A+YJPcVStTPrOFcLwg/kAVWyqdjrTief4kTK/3bNv0MqUDVNgAUG8pcFbtdc674CIh1F3gw==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "xb10XFoPf/gWu8ik5v7xnVyUY7W21LBOLtT7PidzwYVdnE3aKuQ/bIZLcQuY7rdDNT89/wse2q5FRjm207cIMQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Analyzers": "6.0.12", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.DependencyInjection": "6.0.1", + "Microsoft.Extensions.Logging": "6.0.0", + "System.Collections.Immutable": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Abstractions": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "hvRytAcLhrb35HmtMjYWsNZZLt39ryuN7j04lDchRa9VToreyqgo5gMniTdQ6MfCflxtGnDes65V/Y2pjbEyWg==" + }, + "Microsoft.EntityFrameworkCore.Analyzers": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "ZDUY+KlsIyKdfvIJeNdqRiPExFQ5GRZVdx/Cp52vhpCJRImYv34O0Xfmw2eiLu4qe1jmM2pTzAAFKELaKwtj/w==" + }, + "Microsoft.EntityFrameworkCore.Relational": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "HBtRGHtF0Vf+BIQTkRGiopmE5rLYhj59xPpd17S1tLgYpiHDVbepCuHwh5H63fzjO99Z4tW5wmmEGF7KnD91WQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "2Hutlqt07bnWZFtYqT1lj0otX8ygMyBikysGnfQNF2TK3i5GqSTeJ8tqNi/URiI9II7Cyl15A0rflXmFoySuIw==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Sqlite.Core": "6.0.12", + "SQLitePCLRaw.bundle_e_sqlite3": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "07vKE7+t9Z2BfGmHuJwNZNv8m1GWt7ZpYYHFh1tQg1oC6FJ78bSaFzLawsf2NK6CLhbB8DBsjE0rRhxMJ4rXsA==", + "dependencies": { + "Microsoft.Data.Sqlite.Core": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Microsoft.Extensions.DependencyModel": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bcz5sSFJbganH0+YrfvIjJDIcKNW7TL07C4d1eTmXy/wOt52iz4LVogJb6pazs7W0+74j0YpXFErvp++Aq5Bsw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.Memory": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "B4y+Cev05eMcjf1na0v9gza6GUtahXbtY1JCypIgx3B4Ea/KAgsWyXEmW4q6zMbmTMtKzmPVk09rvFJirvMwTg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.StackExchangeRedis": { + "type": "Transitive", + "resolved": "6.0.6", + "contentHash": "bdVQpYm1hcHf0pyAypMjtDw3HjWQJ89UzloyyF1OBs56QlgA1naM498tP2Vjlho5vVRALMGPYzdRKCen8koubw==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "StackExchange.Redis": "2.2.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "tq2wXyh3fL17EMF2bXgRhU7JrbO3on93MRKYxzz4JzzvuGSA1l0W3GI9/tl8EO89TH+KWEymP7bcFway6z9fXg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "IznHHzGUtrdpuQqIUdmzF6TYPcsYHONhHh3o9dGp39sX/9Zfmt476UnhvU0UhXgJnXXAikt/MpN6AuSLCCMdEQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.0.0" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "pnyXV1LFOsYjGveuC07xp0YHIyGq7jRq5Ncb5zrrIieMLWVwgMyYxcOH0jTnBedDT4Gh1QinSqsjqzcieHk1og==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "V4Dth2cYMZpw3HhGw9XUDIijpI6gN+22LDt0AhufIgOppCUfpWX4483OmN+dFXRJkJLc8Tv0Q8QK+1ingT2+KQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GJGery6QytCzS/BxJ96klgG9in3uH26KcUBbiVG/coNDXCRq6LGVVlUT4vXq34KPuM+R2av+LeYdX9h4IZOCUg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "Fy8yr4V6obi7ZxvKYI1i85jqtwMq8tqyxQVZpRSkgeA8enqy/KvBIMdcuNdznlxQMZa72mvbHqb7vbg4Pyx95w==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "vWXPg3HJQIpZkENn1KWq8SfbqVujVD7S7vIAyFXXqK5xkf1Vho+vG0bLBCHxU36lD1cLLtmGpfYf0B3MYFi9tQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.DependencyModel": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "TD5QHg98m3+QhgEV1YVoNMl5KtBw/4rjfxLHO0e/YV9bPUBDKntApP4xdrVtGgCeQZHVfC2EXIGsdpRNrr87Pg==", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "3.1.8", + "contentHash": "7ZJUKwPipkDvuv2KJPZ3r01wp2AWNMiYH+61i0dL89F7QICknjKpWgLKLpTSUYFgl77S3b4264I6i4HzDdrb2A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.8", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.FileProviders.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "15+pa2G0bAMHbHewaQIdr/y6ag2H3yh4rd9hTXavtWDzQBkvpe2RMqFg8BxDpcQWssmjmBApGPcw93QRz6YcMg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Core": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "8vBsyGkA8ZI3lZvm1nf+9ynRC/TzPD+UtbdgTlKk+cz+AW5I41LrK8f/adGej5uXgprOA2DMjZw33vZG6vyXxA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Stores": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "linRCnWBfnqg8qjrd9u/KMISy8O4a6X/GRhpHXU0ar654YQw9LJ/Ht+psx8QLqSX5EsCBbBCZzuamatH2FWIyQ==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Identity.Core": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y/lGICwO27fCkQRK3tZseVzFjZaxfGmui990E67sB4MuiPzdJHnJDS/BeYWrHShSSBgCl4KyKRx4ux686fftPg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.0.0", + "Microsoft.Extensions.Options": "2.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Identity.Client": { + "type": "Transitive", + "resolved": "4.45.0", + "contentHash": "ircobISCLWbtE5eEoLKU+ldfZ8O41vg4lcy38KRj/znH17jvBiAl8oxcyNp89CsuqE3onxIpn21Ca7riyDDrRw==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.18.0" + } + }, + "Microsoft.Identity.Client.Extensions.Msal": { + "type": "Transitive", + "resolved": "2.19.3", + "contentHash": "zVVZjn8aW7W79rC1crioDgdOwaFTQorsSO6RgVlDDjc7MvbEGz071wSNrjVhzR0CdQn6Sefx7Abf1o7vasmrLg==", + "dependencies": { + "Microsoft.Identity.Client": "4.38.0", + "System.Security.Cryptography.ProtectedData": "4.5.0" + } + }, + "Microsoft.IdentityModel.Abstractions": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "XeE6LQtD719Qs2IG7HDi1TSw9LIkDbJ33xFiOBoHbApVw/8GpIBCbW+t7RwOjErUDyXZvjhZliwRkkLb8Z1uzg==" + }, + "Microsoft.IdentityModel.Clients.ActiveDirectory": { + "type": "Transitive", + "resolved": "3.14.2", + "contentHash": "TNsJJMiRnkeby1ovThVoV9yFsPWjAdluwOA+Nf0LtSsBVVrKQv8Qp4kYOgyNwMVj+pDwbhXISySk+4HyHVWNZQ==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "System.Runtime.Serialization.Json": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.IdentityModel.JsonWebTokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "d3h1/BaMeylKTkdP6XwRCxuOoDJZ44V9xaXr6gl5QxmpnZGdoK3bySo3OQN8ehRLJHShb94ElLUvoXyglQtgAw==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "tuEhHIQwvBEhMf8I50hy8FHmRSUkffDFP5EdLsSDV4qRcl2wvOPkQxYqEzWkh+ytW6sbdJGEXElGhmhDfAxAKg==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "0FqY5cTLQKtHrClzHEI+QxJl8OBT2vUiEQQB7UKk832JDiJJmetzYZ3AdSrPjN/3l3nkhByeWzXnhrX0JbifKg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "vtSKL7n6EnAsLyxmiviusm6LKrblT2ndnNqN6rvVq6iIHAnPCK9E2DkDx6h1Jrpy1cvbp40r0cnTg23nhEAGTA==", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "6.21.0", + "System.IdentityModel.Tokens.Jwt": "6.21.0" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "AAEHZvZyb597a+QJSmtxH3n2P1nIJGpZ4Q89GTenknRx6T6zyfzf592yW/jA5e8EHN4tNMjjXHQaYWEq5+L05w==", + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "Microsoft.IdentityModel.Logging": "6.21.0", + "System.Security.Cryptography.Cng": "4.5.0" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.OData.Core": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "/EjnJezMBjXf8OjcShhGzPY7pOO0CopgoZGhS6xsP3t2uhC+O72IBHgtQ7F3v1rRXWVtJwLGhzE1GfJUlx3c4Q==", + "dependencies": { + "Microsoft.OData.Edm": "[7.6.4]", + "Microsoft.Spatial": "[7.6.4]" + } + }, + "Microsoft.OData.Edm": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "MSSmA6kIfpgFTtNpOnnayoSj/6KSzHC1U9KOjF7cTA1PG4tZ7rIMi1pvjFc8CmYEvP4cxGl/+vrCn+HpK26HTQ==" + }, + "Microsoft.Spatial": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "3mB+Frn4LU4yb5ie9R752QiRn0Hvp9PITkSRofV/Lzm9EyLM87Fy9ziqgz75O/c712dh6GxuypMSBUGmNFwMeA==" + }, + "Microsoft.SqlServer.Server": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug==" + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "Microsoft.Win32.Registry": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "Microsoft.Win32.SystemEvents": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==" + }, + "MimeKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "l9YHMBhBUwY7qQHUp8fw0EvjcbmhN4Iggz6MdjqIShBf42+0nJTa5gu0kuupCOPuiARc9ZaS9c9f0gKz4OnxKw==", + "dependencies": { + "Portable.BouncyCastle": "1.9.0", + "System.Security.Cryptography.Pkcs": "6.0.0" + } + }, + "MySqlConnector": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "JVokQTUNN3WHAu9Vw8ieeq1dXTFokJiig5P0VJ4f439UxRrsPo6SaVWC8Zdm6mkPeQFhZ0/9afdWa02EY/1j/w==" + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "Npgsql": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "wKa8MJEJaj0xQXUQZGv7q/KfPID23jSSvFFtljMworrv7dNajr0GN8PCU1SpywqHjMWdYEfK29DY1aYbiISbQg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Npgsql.EntityFrameworkCore.PostgreSQL": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "YJRpO+3wXQyWuwRUCVJj/Rsn46sY0bZ6uCGOEFApiRe0ZYJ6N6TxZUWKbTNJYjesickcLGzynOerpSbDJX1AYg==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Npgsql": "6.0.8" + } + }, + "NSec.Cryptography": { + "type": "Transitive", + "resolved": "22.4.0", + "contentHash": "lEntcPYd7h3aZ8xxi/y/4TML7o8w0GEGqd+w4L1omqFLbdCBmhxJAeO2YBmv/fXbJKgKCQLm7+TD4bR605PEUQ==", + "dependencies": { + "libsodium": "[1.0.18.2, 1.0.19)" + } + }, + "Otp.NET": { + "type": "Transitive", + "resolved": "1.2.2", + "contentHash": "2hrZfkbzeWJ3tNXXt/1beg4IY+nS4F3gIfh4NVFvW0f6Pj51hGpiJ4prBz7Dmrr4ZYrA96rTERVGieZ4xYm7jA==" + }, + "Pipelines.Sockets.Unofficial": { + "type": "Transitive", + "resolved": "2.2.2", + "contentHash": "Bhk0FWxH1paI+18zr1g5cTL+ebeuDcBCR+rRFO+fKEhretgjs7MF2Mc1P64FGLecWp4zKCUOPzngBNrqVyY7Zg==", + "dependencies": { + "System.IO.Pipelines": "5.0.1" + } + }, + "Pomelo.EntityFrameworkCore.MySql": { + "type": "Transitive", + "resolved": "6.0.2", + "contentHash": "KvlZ800CnEuEGnxj5OT1fCKGjQXxW5kpPlCP91JqBYG+2Z3927eqXmlX6LLKUt4swqE8ZsEQ+Zkpab8bqstf4g==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "[6.0.7, 7.0.0)", + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "MySqlConnector": "2.1.2" + } + }, + "Portable.BouncyCastle": { + "type": "Transitive", + "resolved": "1.9.0", + "contentHash": "eZZBCABzVOek+id9Xy04HhmgykF0wZg9wpByzrWN7q8qEI0Qen9b7tfd7w8VA3dOeesumMG7C5ZPy0jk7PSRHw==" + }, + "Quartz": { + "type": "Transitive", + "resolved": "3.4.0", + "contentHash": "N8350OAlQhd8zKg0ARFikGjh3bfAW/CF/KVxu2fTIlAALB/oC1eg54n/QAPYR5ryHuYyDr5G8/Qa4k+D/7OFRQ==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" + }, + "SendGrid": { + "type": "Transitive", + "resolved": "9.27.0", + "contentHash": "kMyXRQ8hmN2bG3tYZ7T31Ufl1kXkpuP5+WBh1BJ32WY31DTnBTCVGURoIqfbTo/tRuQfAYLxra6C8cQGN6kk+A==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "starkbank-ecdsa": "[1.3.3, 2.0.0)" + } + }, + "Sentry": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "Pkw4+51EDUQ0X02jdCZIpaM2Q4UO06VKGDE+dYYNxgvOirRXGKTKxRk4NPKJTLSTNl+2JyT9HoE7C6BTlYhLOw==" + }, + "Sentry.Serilog": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "GFTVfQdOFqZ9Vmo8EEZTx1EQMDRJjka/4v2CwxnAUh+sqHDICga4eOm4AyGzDBbE4s9iAHMgMUCceIqo+7z84w==", + "dependencies": { + "Sentry": "3.16.0", + "Serilog": "2.10.0" + } + }, + "Serilog": { + "type": "Transitive", + "resolved": "2.10.0", + "contentHash": "+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA==" + }, + "Serilog.AspNetCore": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "/JO/txIxRR61x1UXQAgUzG2Sx05o1QHCkokVBWrKzmAoDu+p5EtCAj7L/TVVg7Ezhh3GPiZ0JI9OJCmRO9tSRw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.Extensions.Logging": "5.0.0", + "Serilog": "2.10.0", + "Serilog.Extensions.Hosting": "4.2.0", + "Serilog.Formatting.Compact": "1.1.0", + "Serilog.Settings.Configuration": "3.3.0", + "Serilog.Sinks.Console": "4.0.1", + "Serilog.Sinks.Debug": "2.0.0", + "Serilog.Sinks.File": "5.0.0" + } + }, + "Serilog.Extensions.Hosting": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "gT2keceCmPQR9EX0VpXQZvUgELdfE7yqJ7MOxBhm3WLCblcvRgswEOOTgok/DHObbM15A3V/DtF3VdVDQPIZzQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.Hosting.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8", + "Serilog": "2.10.0", + "Serilog.Extensions.Logging": "3.1.0" + } + }, + "Serilog.Extensions.Logging": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "IWfem7wfrFbB3iw1OikqPFNPEzfayvDuN4WP7Ue1AVFskalMByeWk3QbtUXQR34SBkv1EbZ3AySHda/ErDgpcg==", + "dependencies": { + "Microsoft.Extensions.Logging": "2.0.0", + "Serilog": "2.9.0" + } + }, + "Serilog.Extensions.Logging.File": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "usO0qr4v9VCMBWiTJ1nQmAbPNCt40FrkDol6CpfCXbsxGZS/hH+YCueF7vvPQ32ATI0GWcMWiKRdjXEE7/HxTQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Serilog": "2.5.0", + "Serilog.Extensions.Logging": "2.0.2", + "Serilog.Formatting.Compact": "1.0.0", + "Serilog.Sinks.Async": "1.1.0", + "Serilog.Sinks.RollingFile": "3.3.0" + } + }, + "Serilog.Formatting.Compact": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "pNroKVjo+rDqlxNG5PXkRLpfSCuDOBY0ri6jp9PLe505ljqwhwZz8ospy2vWhQlFu5GkIesh3FcDs4n7sWZODA==", + "dependencies": { + "Serilog": "2.8.0" + } + }, + "Serilog.Settings.Configuration": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "7GNudISZwqaT902hqEL2OFGTZeUFWfnrNLupJkOqeF41AR3GjcxX+Hwb30xb8gG2/CDXsCMVfF8o0+8KY0fJNg==", + "dependencies": { + "Microsoft.Extensions.DependencyModel": "3.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "2.0.0", + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Async": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "xll0Kanz2BkCxuv+F3p1WXr47jdsVM0GU1n1LZvK+18QiRZ/WGFNxSNw9EMKFV5ED5gr7MUpAe6PCMNL1HGUMA==", + "dependencies": { + "Serilog": "2.1.0", + "System.Collections.Concurrent": "4.0.12" + } + }, + "Serilog.Sinks.AzureCosmosDB": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Im2/ZqjXQIpsd727qEo5Pq+br0MiNVuTvI40Yk7736tgjCpEx+omPHv4+c4fEAxnOP2kL9Ge6UoDFoDw3cjF2A==", + "dependencies": { + "Microsoft.Azure.Cosmos": "3.24.0", + "Microsoft.CSharp": "4.7.0", + "Newtonsoft.Json": "13.0.1", + "Serilog": "2.10.0", + "Serilog.Sinks.PeriodicBatching": "2.3.1" + } + }, + "Serilog.Sinks.Console": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Debug": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y6g3OBJ4JzTyyw16fDqtFcQ41qQAydnEvEqmXjhwhgjsnG/FaJ8GUqF5ldsC/bVkK8KYmqrPhDO+tm4dF6xx4A==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.File": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.PeriodicBatching": { + "type": "Transitive", + "resolved": "2.3.1", + "contentHash": "LVYvqpqjSTD8dhfxRnzpxTs8/ys3V2q01MvaY3r0eKsDgpKK1U1y/5N6gFHgiesbxG0V+O5IWdz4+c1DzoNyOQ==", + "dependencies": { + "Serilog": "2.0.0" + } + }, + "Serilog.Sinks.RollingFile": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "2lT5X1r3GH4P0bRWJfhA7etGl8Q2Ipw9AACvtAHWRUSpYZ42NGVyHoVs2ALBZ/cAkkS+tA4jl80Zie144eLQPg==", + "dependencies": { + "Serilog.Sinks.File": "3.2.0", + "System.IO": "4.1.0", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Serilog.Sinks.SyslogMessages": { + "type": "Transitive", + "resolved": "2.0.6", + "contentHash": "V2Yq2GEbk7taEPbpBLFzLXhrHrUzKf4sQu/zLrANU8XIoUn/Mr08M2E8PrcrWVXCj0R4xLMWYe0Z1sxOrMF3IA==", + "dependencies": { + "Serilog": "2.5.0", + "Serilog.Sinks.PeriodicBatching": "2.3.0" + } + }, + "SQLitePCLRaw.bundle_e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "ilkvNhrTersLmIVAcDwwPqfhUFCg19Z1GVMvCSi3xk6Akq94f4qadLORQCq/T8+9JgMiPs+F/NECw5uauviaNw==", + "dependencies": { + "SQLitePCLRaw.lib.e_sqlite3": "2.1.2", + "SQLitePCLRaw.provider.e_sqlite3": "2.1.2" + } + }, + "SQLitePCLRaw.core": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "A8EBepVqY2lnAp3a8jnhbgzF2tlj2S3HcJQGANTYg/TbYbKa8Z5cM1h74An/vy0svhfzT7tVY0sFmUglLgv+2g==", + "dependencies": { + "System.Memory": "4.5.3" + } + }, + "SQLitePCLRaw.lib.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "zibGtku8M4Eea1R3ZCAxc86QbNvyEN17mAcQkvWKBuHvRpMiK2g5anG4R5Be7cWKSd1i6baYz8y4dMMAKcXKPg==" + }, + "SQLitePCLRaw.provider.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "lxCZarZdvAsMl2zw9bXHrXK6RxVhB4b23iTFhCOdHFhxfbsxLxWf+ocvswJwR/9Wh/E//ddMi+wJGqUKV7VwoA==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "StackExchange.Redis": { + "type": "Transitive", + "resolved": "2.5.43", + "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "dependencies": { + "Pipelines.Sockets.Unofficial": "2.2.2", + "System.Diagnostics.PerformanceCounter": "5.0.0" + } + }, + "starkbank-ecdsa": { + "type": "Transitive", + "resolved": "1.3.3", + "contentHash": "OblOaKb1enXn+dSp7tsx9yjwV+/BEKM9jFhshIkZTwCk7LuTFTp+wSon6rFzuPiIiTGtvVWQNUw2slHjGktJog==" + }, + "Stripe.net": { + "type": "Transitive", + "resolved": "40.0.0", + "contentHash": "SD1bGiF+sVQG3p2LXNTZ5rEG2aCnXIHokcxYS9yyW3dR01J0ryf+iNFOwid148yePZ0gCBcRxj3wiW1mTmP7UQ==", + "dependencies": { + "Newtonsoft.Json": "12.0.3", + "System.Configuration.ConfigurationManager": "6.0.0" + } + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Collections.NonGeneric": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "hMxFT2RhhlffyCdKLDXjx8WEC5JfCvNozAZxCablAuFRH74SCV4AgzE8yJCh/73bFnEoZgJ9MJmkjQ0dJmnKqA==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Collections.Specialized": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "/HKQyVP0yH1I0YtK7KJL/28snxHNH/bi+0lgk/+MbURF6ULhAE31MDI+NZDerNWu264YbxklXCCygISgm+HMug==", + "dependencies": { + "System.Collections.NonGeneric": "4.0.1", + "System.Globalization": "4.0.11", + "System.Globalization.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "6.0.0", + "System.Security.Permissions": "6.0.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Diagnostics.PerformanceCounter": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "kcQWWtGVC3MWMNXdMDWfrmIlFZZ2OdoeT6pSNVRtk9+Sa7jwdPiMlNwb0ZQcS7NRlT92pCfmjRtkSWUW3RAKwg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.Diagnostics.Process": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "J0wOX07+QASQblsfxmIMFc9Iq7KTXYL3zs2G/Xc704Ylv3NpuVdo6gij6V3PGiptTxqsK0K7CdXenRvKUnkA2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "Microsoft.Win32.Registry": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.TraceSource": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "6WVCczFZKXwpWpzd/iJkYnsmWTSFFiU24Xx/YdHXBcu+nFI/ehTgeqdJQFbtRPzbrO3KtRNjvkhtj4t5/WwWsA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Drawing.Common": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + } + }, + "System.Dynamic.Runtime": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "db34f6LHYM0U0JpE+sOmjar27BnqTVkbLJhgfwMpTdgTigG/Hna3m2MYVwnFzGGKnEJk2UXFuoVTr8WUbU91/A==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Formats.Asn1": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==" + }, + "System.Formats.Cbor": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "mGaLOoiw7KurJagOOcIsWUoCT5ACIiGxKlCcbYQASefBGXjnCcKTq5Hdjb94eEAKg38zXKlHw4c6EjzgBl9dIw==" + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IdentityModel.Tokens.Jwt": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "JRD8AuypBE+2zYxT3dMJomQVsPYsCqlyZhWel3J1d5nzQokSRyTueF+Q4ID3Jcu6zSZKuzOdJ1MLTkbQsDqcvQ==", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Rfm2jYCaUeGysFEZjDe7j1R4x6Z6BzumS/vUT5a1AA/AWJuGX71PoGB0RmpyX3VmrGqVnAwtfMn39OHR8Y/5+g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "qEePWsaq9LoEEIqhbGe6D5J8c9IqQOUuTzzV6wn1POlfdLkJliZY3OlB0j0f17uMWlqZYjH7txj+2YbyrIA8Yg==" + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Linq.Queryable": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "Yn/WfYe9RoRfmSLvUt2JerP0BTGGykCZkQPgojaxgzF2N0oPo+/AhB8TXOpdCcNlrG3VRtsamtK2uzsp3cqRVw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==", + "dependencies": { + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.6.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.4", + "contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.1", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.NameResolution": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "JdqRdM1Qym3YehqdKIi5LHrpypP4JMfxKQSNCJ2z4WawkG0il+N3XfNeJOxll2XrTnG7WgYYPoeiu/KOwg0DQw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.NetworkInformation": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "Q0rfeiW6QsiZuicGjrFA7cRr2+kXex0JIljTTxzI09GIftB8k+aNL31VsQD1sI2g31cw7UGDTgozA/FgeNSzsQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Linq": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.Sockets": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Overlapped": "4.0.1", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Requests": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "vxGt7C0cZixN+VqoSW4Yakc1Y9WknmxauDqzxgpw/FnBdz4kQNN51l4wxdXX5VY1xjqy//+G+4CvJWp1+f+y6Q==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Net.Http": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Claims": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Security.Principal": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Security": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Net.WebHeaderCollection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "XX2TIAN+wBSAIV51BU2FvvXMdstUa8b0FBSZmDWjZdwUMmggQSifpTOZ5fNH20z9ZCg2fkV1L5SsZnpO2RQDRQ==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0" + } + }, + "System.Net.WebSockets": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", + "dependencies": { + "Microsoft.Win32.Primitives": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.WebSockets.Client": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "NUCcDroX4lCQXgOrzlwIZ1u9YJ0krfyF0wk0ONnyLUmcQoEiYV2/OfUPRqUwQBbpH1BlGApkLgoQUwMqb5+c1g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.2", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Net.WebSockets": "4.0.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.X509Certificates": "4.1.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Numerics.Vectors": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Private.DataContractSerialization": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "lcqFBUaCZxPiUkA4dlSOoPZGtZsAuuElH2XHgLwGLxd7ZozWetV5yiz0qGAV2AUYOqw97MtZBjbLMN16Xz4vXA==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Collections.Concurrent": "4.0.12", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Emit.Lightweight": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1", + "System.Xml.XmlSerializer": "4.0.11" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Caching": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "30D6MkO8WF9jVGWZIP0hmCN8l9BTY4LCsAzLIe4xFSXzs+AjDotR7DpSmj27pFskDURzUvqYYY0ikModgBTxWw==", + "dependencies": { + "System.Configuration.ConfigurationManager": "5.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Runtime.Serialization.Json": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "+7DIJhnKYgCzUgcLbVTtRQb2l1M0FP549XFlFkQM5lmNiUBl44AfNbx4bz61xA8PzLtlYwfmif4JJJW7MPPnjg==", + "dependencies": { + "System.IO": "4.1.0", + "System.Private.DataContractSerialization": "4.1.1", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" + }, + "System.Security.Claims": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Security.Principal": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==", + "dependencies": { + "System.Formats.Asn1": "5.0.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Pkcs": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "elM3x+xSRhzQysiqo85SbidJJ2YbZlnvmh+53TuSZHsD7dNuuEWser+9EFtY+rYupBwkq2avc6ZCO3/6qACgmg==", + "dependencies": { + "System.Formats.Asn1": "6.0.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ==" + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Xml": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "i2Jn6rGXR63J0zIklImGRkDIJL4b1NfPSEbIVHBlqoIb12lfXIigCbDRpDmIEzwSo/v1U5y/rYJdzZYSyCWxvg==", + "dependencies": { + "System.Security.Cryptography.Pkcs": "4.5.0", + "System.Security.Permissions": "4.5.0" + } + }, + "System.Security.Permissions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==", + "dependencies": { + "System.Security.AccessControl": "6.0.0", + "System.Windows.Extensions": "6.0.0" + } + }, + "System.Security.Principal": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, + "System.Security.SecureString": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "sqzq9GD6/b0yqPuMpgIKBuoLf4VKAj8oAfh4kXSzPaN6eoKY3hRi9C5L27uip25qlU+BGPfb0xh2Rmbwc4jFVA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "NyscU59xX6Uo91qvhOs2Ccho3AR2TnZPomo1Z0K6YpyztBPM/A5VbkzOO19sy3A3i1TtEnTxA7bCe3Us+r5MWg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "zaJsHfESQvJ11vbXnNlkrR46IaMULk/gHxYsJphzSF+07kTjPHv+Oc14w6QEOfo3Q4hqLJgStUaYB9DBl0TmWg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Overlapped": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "f7aLuLkBoCQM2kng7zqLFBXz9Gk48gDK8lk1ih9rH/1arJJzZK9gJwNvPDhL6Ps/l6rwOr8jw+4FCHL0KKWiEg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Threading.Thread": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OHmbT+Zz065NKII/ZHcH9XO1dEuLGI1L2k7uYss+9C1jLxTC9kTZZuzUOyXHayRk+dft9CiDf3I/QZ0t8JKyBQ==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading.ThreadPool": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.ValueTuple": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" + }, + "System.Windows.Extensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==", + "dependencies": { + "System.Drawing.Common": "6.0.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "lJ8AxvkX7GQxpC6GFCeBj8ThYVyQczx2+f/cWHJU8tjS7YfI6Cv6bon70jVEgs2CiFbmmM8b9j1oZVx0dSI2Ww==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlSerializer": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "FrazwwqfIXTfq23mfv4zH+BjqkSFNaNFBtjzu3I9NRmG8EELYyrv/fJnttCIwRMFRR/YKXF1hmsMmMEnl55HGw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1" + } + }, + "System.Xml.XPath": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "v1JQ5SETnQusqmS3RwStF7vwQ3L02imIzl++sewmt23VGygix04pEH+FCj1yWb+z4GDzKiljr1W7Wfvrx0YwgA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XPath.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "A/uxsWi/Ifzkmd4ArTLISMbfFs6XpRPsXZonrIqyTY70xi8t+mDtvSM5Os0RqyRDobjMBwIDHDL4NOIbkDwf7A==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XPath": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "YubicoDotNetClient": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "uP5F3Ko1gqZi3lwS2R/jAAwhBxXs/6PKDpS6FdQjsBA5qmF0hQmbtfxM6QHTXOMoWbUtfetG7+LtgmG8T5zDIg==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "core": { + "type": "Project", + "dependencies": { + "AWSSDK.SQS": "[3.7.2.47, )", + "AWSSDK.SimpleEmail": "[3.7.0.150, )", + "AspNetCoreRateLimit": "[4.0.2, )", + "AspNetCoreRateLimit.Redis": "[1.0.1, )", + "Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.2.1, )", + "Azure.Storage.Blobs": "[12.11.0, )", + "Azure.Storage.Queues": "[12.9.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "Fido2.AspNet": "[3.0.1, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "MailKit": "[3.2.0, )", + "Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )", + "Microsoft.Azure.Cosmos.Table": "[1.0.8, )", + "Microsoft.Azure.NotificationHubs": "[4.1.0, )", + "Microsoft.Azure.ServiceBus": "[5.2.0, )", + "Microsoft.Data.SqlClient": "[5.0.1, )", + "Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )", + "Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )", + "Microsoft.Extensions.Identity.Stores": "[6.0.4, )", + "Newtonsoft.Json": "[13.0.1, )", + "Otp.NET": "[1.2.2, )", + "Quartz": "[3.4.0, )", + "SendGrid": "[9.27.0, )", + "Sentry.Serilog": "[3.16.0, )", + "Serilog.AspNetCore": "[5.0.0, )", + "Serilog.Extensions.Logging": "[3.1.0, )", + "Serilog.Extensions.Logging.File": "[2.0.0, )", + "Serilog.Sinks.AzureCosmosDB": "[2.0.0, )", + "Serilog.Sinks.SyslogMessages": "[2.0.6, )", + "Stripe.net": "[40.0.0, )", + "YubicoDotNetClient": "[1.2.0, )" + } + }, + "infrastructure.entityframework": { + "type": "Project", + "dependencies": { + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", + "Core": "[2023.1.0, )", + "Microsoft.EntityFrameworkCore.Relational": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.SqlServer": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.Sqlite": "[6.0.12, )", + "Npgsql.EntityFrameworkCore.PostgreSQL": "[6.0.8, )", + "Pomelo.EntityFrameworkCore.MySql": "[6.0.2, )", + "linq2db.EntityFrameworkCore": "[6.11.0, )" + } + } + } + } +} \ No newline at end of file diff --git a/bitwarden_license/src/Scim/.dockerignore b/bitwarden_license/src/Scim/.dockerignore new file mode 100644 index 000000000..fc12f2514 --- /dev/null +++ b/bitwarden_license/src/Scim/.dockerignore @@ -0,0 +1,4 @@ +* +!obj/build-output/publish/* +!obj/Docker/empty/ +!entrypoint.sh diff --git a/bitwarden_license/src/Scim/Context/IScimContext.cs b/bitwarden_license/src/Scim/Context/IScimContext.cs new file mode 100644 index 000000000..1e7010bd2 --- /dev/null +++ b/bitwarden_license/src/Scim/Context/IScimContext.cs @@ -0,0 +1,20 @@ +using Bit.Core.Entities; +using Bit.Core.Enums; +using Bit.Core.Models.OrganizationConnectionConfigs; +using Bit.Core.Repositories; +using Bit.Core.Settings; + +namespace Bit.Scim.Context; + +public interface IScimContext +{ + ScimProviderType RequestScimProvider { get; set; } + ScimConfig ScimConfiguration { get; set; } + Guid? OrganizationId { get; set; } + Organization Organization { get; set; } + Task BuildAsync( + HttpContext httpContext, + GlobalSettings globalSettings, + IOrganizationRepository organizationRepository, + IOrganizationConnectionRepository organizationConnectionRepository); +} diff --git a/bitwarden_license/src/Scim/Context/ScimContext.cs b/bitwarden_license/src/Scim/Context/ScimContext.cs new file mode 100644 index 000000000..ae8d30807 --- /dev/null +++ b/bitwarden_license/src/Scim/Context/ScimContext.cs @@ -0,0 +1,63 @@ +using Bit.Core.Entities; +using Bit.Core.Enums; +using Bit.Core.Models.OrganizationConnectionConfigs; +using Bit.Core.Repositories; +using Bit.Core.Settings; + +namespace Bit.Scim.Context; + +public class ScimContext : IScimContext +{ + private bool _builtHttpContext; + + public ScimProviderType RequestScimProvider { get; set; } = ScimProviderType.Default; + public ScimConfig ScimConfiguration { get; set; } + public Guid? OrganizationId { get; set; } + public Organization Organization { get; set; } + + public async virtual Task BuildAsync( + HttpContext httpContext, + GlobalSettings globalSettings, + IOrganizationRepository organizationRepository, + IOrganizationConnectionRepository organizationConnectionRepository) + { + if (_builtHttpContext) + { + return; + } + + _builtHttpContext = true; + + string orgIdString = null; + if (httpContext.Request.RouteValues.TryGetValue("organizationId", out var orgIdObject)) + { + orgIdString = orgIdObject?.ToString(); + } + + if (Guid.TryParse(orgIdString, out var orgId)) + { + OrganizationId = orgId; + Organization = await organizationRepository.GetByIdAsync(orgId); + if (Organization != null) + { + var scimConnections = await organizationConnectionRepository.GetByOrganizationIdTypeAsync(Organization.Id, + OrganizationConnectionType.Scim); + ScimConfiguration = scimConnections?.FirstOrDefault()?.GetConfig(); + } + } + + if (RequestScimProvider == ScimProviderType.Default && + httpContext.Request.Headers.TryGetValue("User-Agent", out var userAgent)) + { + if (userAgent.ToString().StartsWith("Okta")) + { + RequestScimProvider = ScimProviderType.Okta; + } + } + if (RequestScimProvider == ScimProviderType.Default && + httpContext.Request.Headers.ContainsKey("Adscimversion")) + { + RequestScimProvider = ScimProviderType.AzureAd; + } + } +} diff --git a/bitwarden_license/src/Scim/Controllers/InfoController.cs b/bitwarden_license/src/Scim/Controllers/InfoController.cs new file mode 100644 index 000000000..9959bfb0a --- /dev/null +++ b/bitwarden_license/src/Scim/Controllers/InfoController.cs @@ -0,0 +1,22 @@ +using Bit.Core.Utilities; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Bit.Scim.Controllers; + +[AllowAnonymous] +public class InfoController : Controller +{ + [HttpGet("~/alive")] + [HttpGet("~/now")] + public DateTime GetAlive() + { + return DateTime.UtcNow; + } + + [HttpGet("~/version")] + public JsonResult GetVersion() + { + return Json(AssemblyHelpers.GetVersion()); + } +} diff --git a/bitwarden_license/src/Scim/Controllers/v2/GroupsController.cs b/bitwarden_license/src/Scim/Controllers/v2/GroupsController.cs new file mode 100644 index 000000000..8a3c02f5e --- /dev/null +++ b/bitwarden_license/src/Scim/Controllers/v2/GroupsController.cs @@ -0,0 +1,109 @@ +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.OrganizationFeatures.Groups.Interfaces; +using Bit.Core.Repositories; +using Bit.Scim.Groups.Interfaces; +using Bit.Scim.Models; +using Bit.Scim.Utilities; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Bit.Scim.Controllers.v2; + +[Authorize("Scim")] +[Route("v2/{organizationId}/groups")] +[ExceptionHandlerFilter] +public class GroupsController : Controller +{ + private readonly IGroupRepository _groupRepository; + private readonly IOrganizationRepository _organizationRepository; + private readonly IGetGroupsListQuery _getGroupsListQuery; + private readonly IDeleteGroupCommand _deleteGroupCommand; + private readonly IPatchGroupCommand _patchGroupCommand; + private readonly IPostGroupCommand _postGroupCommand; + private readonly IPutGroupCommand _putGroupCommand; + private readonly ILogger _logger; + + public GroupsController( + IGroupRepository groupRepository, + IOrganizationRepository organizationRepository, + IGetGroupsListQuery getGroupsListQuery, + IDeleteGroupCommand deleteGroupCommand, + IPatchGroupCommand patchGroupCommand, + IPostGroupCommand postGroupCommand, + IPutGroupCommand putGroupCommand, + ILogger logger) + { + _groupRepository = groupRepository; + _organizationRepository = organizationRepository; + _getGroupsListQuery = getGroupsListQuery; + _deleteGroupCommand = deleteGroupCommand; + _patchGroupCommand = patchGroupCommand; + _postGroupCommand = postGroupCommand; + _putGroupCommand = putGroupCommand; + _logger = logger; + } + + [HttpGet("{id}")] + public async Task Get(Guid organizationId, Guid id) + { + var group = await _groupRepository.GetByIdAsync(id); + if (group == null || group.OrganizationId != organizationId) + { + throw new NotFoundException("Group not found."); + } + return Ok(new ScimGroupResponseModel(group)); + } + + [HttpGet("")] + public async Task Get( + Guid organizationId, + [FromQuery] string filter, + [FromQuery] int? count, + [FromQuery] int? startIndex) + { + var groupsListQueryResult = await _getGroupsListQuery.GetGroupsListAsync(organizationId, filter, count, startIndex); + var scimListResponseModel = new ScimListResponseModel + { + Resources = groupsListQueryResult.groupList.Select(g => new ScimGroupResponseModel(g)).ToList(), + ItemsPerPage = count.GetValueOrDefault(groupsListQueryResult.groupList.Count()), + TotalResults = groupsListQueryResult.totalResults, + StartIndex = startIndex.GetValueOrDefault(1), + }; + return Ok(scimListResponseModel); + } + + [HttpPost("")] + public async Task Post(Guid organizationId, [FromBody] ScimGroupRequestModel model) + { + var organization = await _organizationRepository.GetByIdAsync(organizationId); + var group = await _postGroupCommand.PostGroupAsync(organization, model); + var scimGroupResponseModel = new ScimGroupResponseModel(group); + return new CreatedResult(Url.Action(nameof(Get), new { group.OrganizationId, group.Id }), scimGroupResponseModel); + } + + [HttpPut("{id}")] + public async Task Put(Guid organizationId, Guid id, [FromBody] ScimGroupRequestModel model) + { + var organization = await _organizationRepository.GetByIdAsync(organizationId); + var group = await _putGroupCommand.PutGroupAsync(organization, id, model); + var response = new ScimGroupResponseModel(group); + + return Ok(response); + } + + [HttpPatch("{id}")] + public async Task Patch(Guid organizationId, Guid id, [FromBody] ScimPatchModel model) + { + var organization = await _organizationRepository.GetByIdAsync(organizationId); + await _patchGroupCommand.PatchGroupAsync(organization, id, model); + return new NoContentResult(); + } + + [HttpDelete("{id}")] + public async Task Delete(Guid organizationId, Guid id) + { + await _deleteGroupCommand.DeleteGroupAsync(organizationId, id, EventSystemUser.SCIM); + return new NoContentResult(); + } +} diff --git a/bitwarden_license/src/Scim/Controllers/v2/UsersController.cs b/bitwarden_license/src/Scim/Controllers/v2/UsersController.cs new file mode 100644 index 000000000..ea58a90af --- /dev/null +++ b/bitwarden_license/src/Scim/Controllers/v2/UsersController.cs @@ -0,0 +1,125 @@ +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.OrganizationFeatures.OrganizationUsers.Interfaces; +using Bit.Core.Repositories; +using Bit.Core.Services; +using Bit.Scim.Models; +using Bit.Scim.Users.Interfaces; +using Bit.Scim.Utilities; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Bit.Scim.Controllers.v2; + +[Authorize("Scim")] +[Route("v2/{organizationId}/users")] +[ExceptionHandlerFilter] +public class UsersController : Controller +{ + private readonly IUserService _userService; + private readonly IOrganizationUserRepository _organizationUserRepository; + private readonly IOrganizationService _organizationService; + private readonly IGetUsersListQuery _getUsersListQuery; + private readonly IDeleteOrganizationUserCommand _deleteOrganizationUserCommand; + private readonly IPatchUserCommand _patchUserCommand; + private readonly IPostUserCommand _postUserCommand; + private readonly ILogger _logger; + + public UsersController( + IUserService userService, + IOrganizationUserRepository organizationUserRepository, + IOrganizationService organizationService, + IGetUsersListQuery getUsersListQuery, + IDeleteOrganizationUserCommand deleteOrganizationUserCommand, + IPatchUserCommand patchUserCommand, + IPostUserCommand postUserCommand, + ILogger logger) + { + _userService = userService; + _organizationUserRepository = organizationUserRepository; + _organizationService = organizationService; + _getUsersListQuery = getUsersListQuery; + _deleteOrganizationUserCommand = deleteOrganizationUserCommand; + _patchUserCommand = patchUserCommand; + _postUserCommand = postUserCommand; + _logger = logger; + } + + [HttpGet("{id}")] + public async Task Get(Guid organizationId, Guid id) + { + var orgUser = await _organizationUserRepository.GetDetailsByIdAsync(id); + if (orgUser == null || orgUser.OrganizationId != organizationId) + { + throw new NotFoundException("User not found."); + } + return Ok(new ScimUserResponseModel(orgUser)); + } + + [HttpGet("")] + public async Task Get( + Guid organizationId, + [FromQuery] string filter, + [FromQuery] int? count, + [FromQuery] int? startIndex) + { + var usersListQueryResult = await _getUsersListQuery.GetUsersListAsync(organizationId, filter, count, startIndex); + var scimListResponseModel = new ScimListResponseModel + { + Resources = usersListQueryResult.userList.Select(u => new ScimUserResponseModel(u)).ToList(), + ItemsPerPage = count.GetValueOrDefault(usersListQueryResult.userList.Count()), + TotalResults = usersListQueryResult.totalResults, + StartIndex = startIndex.GetValueOrDefault(1), + }; + return Ok(scimListResponseModel); + } + + [HttpPost("")] + public async Task Post(Guid organizationId, [FromBody] ScimUserRequestModel model) + { + var orgUser = await _postUserCommand.PostUserAsync(organizationId, model); + var scimUserResponseModel = new ScimUserResponseModel(orgUser); + return new CreatedResult(Url.Action(nameof(Get), new { orgUser.OrganizationId, orgUser.Id }), scimUserResponseModel); + } + + [HttpPut("{id}")] + public async Task Put(Guid organizationId, Guid id, [FromBody] ScimUserRequestModel model) + { + var orgUser = await _organizationUserRepository.GetByIdAsync(id); + if (orgUser == null || orgUser.OrganizationId != organizationId) + { + return new NotFoundObjectResult(new ScimErrorResponseModel + { + Status = 404, + Detail = "User not found." + }); + } + + if (model.Active && orgUser.Status == OrganizationUserStatusType.Revoked) + { + await _organizationService.RestoreUserAsync(orgUser, null, _userService); + } + else if (!model.Active && orgUser.Status != OrganizationUserStatusType.Revoked) + { + await _organizationService.RevokeUserAsync(orgUser, null); + } + + // Have to get full details object for response model + var orgUserDetails = await _organizationUserRepository.GetDetailsByIdAsync(id); + return new ObjectResult(new ScimUserResponseModel(orgUserDetails)); + } + + [HttpPatch("{id}")] + public async Task Patch(Guid organizationId, Guid id, [FromBody] ScimPatchModel model) + { + await _patchUserCommand.PatchUserAsync(organizationId, id, model); + return new NoContentResult(); + } + + [HttpDelete("{id}")] + public async Task Delete(Guid organizationId, Guid id) + { + await _deleteOrganizationUserCommand.DeleteUserAsync(organizationId, id, EventSystemUser.SCIM); + return new NoContentResult(); + } +} diff --git a/bitwarden_license/src/Scim/Dockerfile b/bitwarden_license/src/Scim/Dockerfile new file mode 100644 index 000000000..f63cb82ce --- /dev/null +++ b/bitwarden_license/src/Scim/Dockerfile @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/dotnet/aspnet:6.0 + +LABEL com.bitwarden.product="bitwarden" + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + gosu \ + curl \ + && rm -rf /var/lib/apt/lists/* + +ENV ASPNETCORE_URLS http://+:5000 +WORKDIR /app +EXPOSE 5000 +COPY obj/build-output/publish . +COPY entrypoint.sh / +RUN chmod +x /entrypoint.sh + +HEALTHCHECK CMD curl -f http://localhost:5000/alive || exit 1 + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/bitwarden_license/src/Scim/Groups/GetGroupsListQuery.cs b/bitwarden_license/src/Scim/Groups/GetGroupsListQuery.cs new file mode 100644 index 000000000..1afab3a0f --- /dev/null +++ b/bitwarden_license/src/Scim/Groups/GetGroupsListQuery.cs @@ -0,0 +1,64 @@ +using Bit.Core.Entities; +using Bit.Core.Repositories; +using Bit.Scim.Groups.Interfaces; + +namespace Bit.Scim.Groups; + +public class GetGroupsListQuery : IGetGroupsListQuery +{ + private readonly IGroupRepository _groupRepository; + + public GetGroupsListQuery(IGroupRepository groupRepository) + { + _groupRepository = groupRepository; + } + + public async Task<(IEnumerable groupList, int totalResults)> GetGroupsListAsync(Guid organizationId, string filter, int? count, int? startIndex) + { + string nameFilter = null; + string externalIdFilter = null; + if (!string.IsNullOrWhiteSpace(filter)) + { + if (filter.StartsWith("displayName eq ")) + { + nameFilter = filter.Substring(15).Trim('"'); + } + else if (filter.StartsWith("externalId eq ")) + { + externalIdFilter = filter.Substring(14).Trim('"'); + } + } + + var groupList = new List(); + var groups = await _groupRepository.GetManyByOrganizationIdAsync(organizationId); + var totalResults = 0; + if (!string.IsNullOrWhiteSpace(nameFilter)) + { + var group = groups.FirstOrDefault(g => g.Name == nameFilter); + if (group != null) + { + groupList.Add(group); + } + totalResults = groupList.Count; + } + else if (!string.IsNullOrWhiteSpace(externalIdFilter)) + { + var group = groups.FirstOrDefault(ou => ou.ExternalId == externalIdFilter); + if (group != null) + { + groupList.Add(group); + } + totalResults = groupList.Count; + } + else if (string.IsNullOrWhiteSpace(filter) && startIndex.HasValue && count.HasValue) + { + groupList = groups.OrderBy(g => g.Name) + .Skip(startIndex.Value - 1) + .Take(count.Value) + .ToList(); + totalResults = groups.Count; + } + + return (groupList, totalResults); + } +} diff --git a/bitwarden_license/src/Scim/Groups/Interfaces/IGetGroupsListQuery.cs b/bitwarden_license/src/Scim/Groups/Interfaces/IGetGroupsListQuery.cs new file mode 100644 index 000000000..d2cf5ef0a --- /dev/null +++ b/bitwarden_license/src/Scim/Groups/Interfaces/IGetGroupsListQuery.cs @@ -0,0 +1,8 @@ +using Bit.Core.Entities; + +namespace Bit.Scim.Groups.Interfaces; + +public interface IGetGroupsListQuery +{ + Task<(IEnumerable groupList, int totalResults)> GetGroupsListAsync(Guid organizationId, string filter, int? count, int? startIndex); +} diff --git a/bitwarden_license/src/Scim/Groups/Interfaces/IPatchGroupCommand.cs b/bitwarden_license/src/Scim/Groups/Interfaces/IPatchGroupCommand.cs new file mode 100644 index 000000000..181f0c70a --- /dev/null +++ b/bitwarden_license/src/Scim/Groups/Interfaces/IPatchGroupCommand.cs @@ -0,0 +1,9 @@ +using Bit.Core.Entities; +using Bit.Scim.Models; + +namespace Bit.Scim.Groups.Interfaces; + +public interface IPatchGroupCommand +{ + Task PatchGroupAsync(Organization organization, Guid id, ScimPatchModel model); +} diff --git a/bitwarden_license/src/Scim/Groups/Interfaces/IPostGroupCommand.cs b/bitwarden_license/src/Scim/Groups/Interfaces/IPostGroupCommand.cs new file mode 100644 index 000000000..76e80f08d --- /dev/null +++ b/bitwarden_license/src/Scim/Groups/Interfaces/IPostGroupCommand.cs @@ -0,0 +1,9 @@ +using Bit.Core.Entities; +using Bit.Scim.Models; + +namespace Bit.Scim.Groups.Interfaces; + +public interface IPostGroupCommand +{ + Task PostGroupAsync(Organization organization, ScimGroupRequestModel model); +} diff --git a/bitwarden_license/src/Scim/Groups/Interfaces/IPutGroupCommand.cs b/bitwarden_license/src/Scim/Groups/Interfaces/IPutGroupCommand.cs new file mode 100644 index 000000000..052a4e554 --- /dev/null +++ b/bitwarden_license/src/Scim/Groups/Interfaces/IPutGroupCommand.cs @@ -0,0 +1,9 @@ +using Bit.Core.Entities; +using Bit.Scim.Models; + +namespace Bit.Scim.Groups.Interfaces; + +public interface IPutGroupCommand +{ + Task PutGroupAsync(Organization organization, Guid id, ScimGroupRequestModel model); +} diff --git a/bitwarden_license/src/Scim/Groups/PatchGroupCommand.cs b/bitwarden_license/src/Scim/Groups/PatchGroupCommand.cs new file mode 100644 index 000000000..750dcec46 --- /dev/null +++ b/bitwarden_license/src/Scim/Groups/PatchGroupCommand.cs @@ -0,0 +1,153 @@ +using System.Text.Json; +using Bit.Core.Entities; +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.OrganizationFeatures.Groups.Interfaces; +using Bit.Core.Repositories; +using Bit.Core.Services; +using Bit.Scim.Groups.Interfaces; +using Bit.Scim.Models; + +namespace Bit.Scim.Groups; + +public class PatchGroupCommand : IPatchGroupCommand +{ + private readonly IGroupRepository _groupRepository; + private readonly IGroupService _groupService; + private readonly IUpdateGroupCommand _updateGroupCommand; + private readonly ILogger _logger; + + public PatchGroupCommand( + IGroupRepository groupRepository, + IGroupService groupService, + IUpdateGroupCommand updateGroupCommand, + ILogger logger) + { + _groupRepository = groupRepository; + _groupService = groupService; + _updateGroupCommand = updateGroupCommand; + _logger = logger; + } + + public async Task PatchGroupAsync(Organization organization, Guid id, ScimPatchModel model) + { + var group = await _groupRepository.GetByIdAsync(id); + if (group == null || group.OrganizationId != organization.Id) + { + throw new NotFoundException("Group not found."); + } + + var operationHandled = false; + foreach (var operation in model.Operations) + { + // Replace operations + if (operation.Op?.ToLowerInvariant() == "replace") + { + // Replace a list of members + if (operation.Path?.ToLowerInvariant() == "members") + { + var ids = GetOperationValueIds(operation.Value); + await _groupRepository.UpdateUsersAsync(group.Id, ids); + operationHandled = true; + } + // Replace group name from path + else if (operation.Path?.ToLowerInvariant() == "displayname") + { + group.Name = operation.Value.GetString(); + await _updateGroupCommand.UpdateGroupAsync(group, organization, EventSystemUser.SCIM); + operationHandled = true; + } + // Replace group name from value object + else if (string.IsNullOrWhiteSpace(operation.Path) && + operation.Value.TryGetProperty("displayName", out var displayNameProperty)) + { + group.Name = displayNameProperty.GetString(); + await _updateGroupCommand.UpdateGroupAsync(group, organization, EventSystemUser.SCIM); + operationHandled = true; + } + } + // Add a single member + else if (operation.Op?.ToLowerInvariant() == "add" && + !string.IsNullOrWhiteSpace(operation.Path) && + operation.Path.ToLowerInvariant().StartsWith("members[value eq ")) + { + var addId = GetOperationPathId(operation.Path); + if (addId.HasValue) + { + var orgUserIds = (await _groupRepository.GetManyUserIdsByIdAsync(group.Id)).ToHashSet(); + orgUserIds.Add(addId.Value); + await _groupRepository.UpdateUsersAsync(group.Id, orgUserIds); + operationHandled = true; + } + } + // Add a list of members + else if (operation.Op?.ToLowerInvariant() == "add" && + operation.Path?.ToLowerInvariant() == "members") + { + var orgUserIds = (await _groupRepository.GetManyUserIdsByIdAsync(group.Id)).ToHashSet(); + foreach (var v in GetOperationValueIds(operation.Value)) + { + orgUserIds.Add(v); + } + await _groupRepository.UpdateUsersAsync(group.Id, orgUserIds); + operationHandled = true; + } + // Remove a single member + else if (operation.Op?.ToLowerInvariant() == "remove" && + !string.IsNullOrWhiteSpace(operation.Path) && + operation.Path.ToLowerInvariant().StartsWith("members[value eq ")) + { + var removeId = GetOperationPathId(operation.Path); + if (removeId.HasValue) + { + await _groupService.DeleteUserAsync(group, removeId.Value, EventSystemUser.SCIM); + operationHandled = true; + } + } + // Remove a list of members + else if (operation.Op?.ToLowerInvariant() == "remove" && + operation.Path?.ToLowerInvariant() == "members") + { + var orgUserIds = (await _groupRepository.GetManyUserIdsByIdAsync(group.Id)).ToHashSet(); + foreach (var v in GetOperationValueIds(operation.Value)) + { + orgUserIds.Remove(v); + } + await _groupRepository.UpdateUsersAsync(group.Id, orgUserIds); + operationHandled = true; + } + } + + if (!operationHandled) + { + _logger.LogWarning("Group patch operation not handled: {0} : ", + string.Join(", ", model.Operations.Select(o => $"{o.Op}:{o.Path}"))); + } + } + + private List GetOperationValueIds(JsonElement objArray) + { + var ids = new List(); + foreach (var obj in objArray.EnumerateArray()) + { + if (obj.TryGetProperty("value", out var valueProperty)) + { + if (valueProperty.TryGetGuid(out var guid)) + { + ids.Add(guid); + } + } + } + return ids; + } + + private Guid? GetOperationPathId(string path) + { + // Parse Guid from string like: members[value eq "{GUID}"}] + if (Guid.TryParse(path.Substring(18).Replace("\"]", string.Empty), out var id)) + { + return id; + } + return null; + } +} diff --git a/bitwarden_license/src/Scim/Groups/PostGroupCommand.cs b/bitwarden_license/src/Scim/Groups/PostGroupCommand.cs new file mode 100644 index 000000000..4da336fb7 --- /dev/null +++ b/bitwarden_license/src/Scim/Groups/PostGroupCommand.cs @@ -0,0 +1,77 @@ +using Bit.Core.Entities; +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.OrganizationFeatures.Groups.Interfaces; +using Bit.Core.Repositories; +using Bit.Scim.Context; +using Bit.Scim.Groups.Interfaces; +using Bit.Scim.Models; + +namespace Bit.Scim.Groups; + +public class PostGroupCommand : IPostGroupCommand +{ + private readonly IGroupRepository _groupRepository; + private readonly IScimContext _scimContext; + private readonly ICreateGroupCommand _createGroupCommand; + + public PostGroupCommand( + IGroupRepository groupRepository, + IOrganizationRepository organizationRepository, + IScimContext scimContext, + ICreateGroupCommand createGroupCommand) + { + _groupRepository = groupRepository; + _scimContext = scimContext; + _createGroupCommand = createGroupCommand; + } + + public async Task PostGroupAsync(Organization organization, ScimGroupRequestModel model) + { + if (string.IsNullOrWhiteSpace(model.DisplayName)) + { + throw new BadRequestException(); + } + + var groups = await _groupRepository.GetManyByOrganizationIdAsync(organization.Id); + if (!string.IsNullOrWhiteSpace(model.ExternalId) && groups.Any(g => g.ExternalId == model.ExternalId)) + { + throw new ConflictException(); + } + + var group = model.ToGroup(organization.Id); + await _createGroupCommand.CreateGroupAsync(group, organization, EventSystemUser.SCIM, collections: null); + await UpdateGroupMembersAsync(group, model); + + return group; + } + + private async Task UpdateGroupMembersAsync(Group group, ScimGroupRequestModel model) + { + if (_scimContext.RequestScimProvider != Core.Enums.ScimProviderType.Okta) + { + return; + } + + if (model.Members == null) + { + return; + } + + var memberIds = new List(); + foreach (var id in model.Members.Select(i => i.Value)) + { + if (Guid.TryParse(id, out var guidId)) + { + memberIds.Add(guidId); + } + } + + if (!memberIds.Any()) + { + return; + } + + await _groupRepository.UpdateUsersAsync(group.Id, memberIds); + } +} diff --git a/bitwarden_license/src/Scim/Groups/PutGroupCommand.cs b/bitwarden_license/src/Scim/Groups/PutGroupCommand.cs new file mode 100644 index 000000000..ec2cd170d --- /dev/null +++ b/bitwarden_license/src/Scim/Groups/PutGroupCommand.cs @@ -0,0 +1,66 @@ +using Bit.Core.Entities; +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.OrganizationFeatures.Groups.Interfaces; +using Bit.Core.Repositories; +using Bit.Scim.Context; +using Bit.Scim.Groups.Interfaces; +using Bit.Scim.Models; + +namespace Bit.Scim.Groups; + +public class PutGroupCommand : IPutGroupCommand +{ + private readonly IGroupRepository _groupRepository; + private readonly IScimContext _scimContext; + private readonly IUpdateGroupCommand _updateGroupCommand; + + public PutGroupCommand( + IGroupRepository groupRepository, + IScimContext scimContext, + IUpdateGroupCommand updateGroupCommand) + { + _groupRepository = groupRepository; + _scimContext = scimContext; + _updateGroupCommand = updateGroupCommand; + } + + public async Task PutGroupAsync(Organization organization, Guid id, ScimGroupRequestModel model) + { + var group = await _groupRepository.GetByIdAsync(id); + if (group == null || group.OrganizationId != organization.Id) + { + throw new NotFoundException("Group not found."); + } + + group.Name = model.DisplayName; + await _updateGroupCommand.UpdateGroupAsync(group, organization, EventSystemUser.SCIM); + await UpdateGroupMembersAsync(group, model); + + return group; + } + + private async Task UpdateGroupMembersAsync(Group group, ScimGroupRequestModel model) + { + if (_scimContext.RequestScimProvider != Core.Enums.ScimProviderType.Okta) + { + return; + } + + if (model.Members == null) + { + return; + } + + var memberIds = new List(); + foreach (var id in model.Members.Select(i => i.Value)) + { + if (Guid.TryParse(id, out var guidId)) + { + memberIds.Add(guidId); + } + } + + await _groupRepository.UpdateUsersAsync(group.Id, memberIds); + } +} diff --git a/bitwarden_license/src/Scim/Models/BaseScimGroupModel.cs b/bitwarden_license/src/Scim/Models/BaseScimGroupModel.cs new file mode 100644 index 000000000..150885fb5 --- /dev/null +++ b/bitwarden_license/src/Scim/Models/BaseScimGroupModel.cs @@ -0,0 +1,17 @@ +using Bit.Scim.Utilities; + +namespace Bit.Scim.Models; + +public abstract class BaseScimGroupModel : BaseScimModel +{ + public BaseScimGroupModel(bool initSchema = false) + { + if (initSchema) + { + Schemas = new List { ScimConstants.Scim2SchemaGroup }; + } + } + + public string DisplayName { get; set; } + public string ExternalId { get; set; } +} diff --git a/bitwarden_license/src/Scim/Models/BaseScimModel.cs b/bitwarden_license/src/Scim/Models/BaseScimModel.cs new file mode 100644 index 000000000..8f3adfbe4 --- /dev/null +++ b/bitwarden_license/src/Scim/Models/BaseScimModel.cs @@ -0,0 +1,14 @@ +namespace Bit.Scim.Models; + +public abstract class BaseScimModel +{ + public BaseScimModel() + { } + + public BaseScimModel(string schema) + { + Schemas = new List { schema }; + } + + public List Schemas { get; set; } +} diff --git a/bitwarden_license/src/Scim/Models/BaseScimUserModel.cs b/bitwarden_license/src/Scim/Models/BaseScimUserModel.cs new file mode 100644 index 000000000..d3c69d574 --- /dev/null +++ b/bitwarden_license/src/Scim/Models/BaseScimUserModel.cs @@ -0,0 +1,55 @@ +using Bit.Scim.Utilities; + +namespace Bit.Scim.Models; + +public abstract class BaseScimUserModel : BaseScimModel +{ + public BaseScimUserModel(bool initSchema = false) + { + if (initSchema) + { + Schemas = new List { ScimConstants.Scim2SchemaUser }; + } + } + + public string UserName { get; set; } + public NameModel Name { get; set; } + public List Emails { get; set; } + public string PrimaryEmail => Emails?.FirstOrDefault(e => e.Primary)?.Value; + public string WorkEmail => Emails?.FirstOrDefault(e => e.Type == "work")?.Value; + public string DisplayName { get; set; } + public bool Active { get; set; } + public List Groups { get; set; } + public string ExternalId { get; set; } + + public class NameModel + { + public NameModel() { } + + public NameModel(string name) + { + Formatted = name; + } + + public string Formatted { get; set; } + public string GivenName { get; set; } + public string MiddleName { get; set; } + public string FamilyName { get; set; } + } + + public class EmailModel + { + public EmailModel() { } + + public EmailModel(string email) + { + Primary = true; + Value = email; + Type = "work"; + } + + public bool Primary { get; set; } + public string Value { get; set; } + public string Type { get; set; } + } +} diff --git a/bitwarden_license/src/Scim/Models/ScimErrorResponseModel.cs b/bitwarden_license/src/Scim/Models/ScimErrorResponseModel.cs new file mode 100644 index 000000000..d1dce35ef --- /dev/null +++ b/bitwarden_license/src/Scim/Models/ScimErrorResponseModel.cs @@ -0,0 +1,13 @@ +using Bit.Scim.Utilities; + +namespace Bit.Scim.Models; + +public class ScimErrorResponseModel : BaseScimModel +{ + public ScimErrorResponseModel() + : base(ScimConstants.Scim2SchemaError) + { } + + public string Detail { get; set; } + public int Status { get; set; } +} diff --git a/bitwarden_license/src/Scim/Models/ScimGroupRequestModel.cs b/bitwarden_license/src/Scim/Models/ScimGroupRequestModel.cs new file mode 100644 index 000000000..ac99eca2e --- /dev/null +++ b/bitwarden_license/src/Scim/Models/ScimGroupRequestModel.cs @@ -0,0 +1,30 @@ +using Bit.Core.Entities; +using Bit.Core.Utilities; + +namespace Bit.Scim.Models; + +public class ScimGroupRequestModel : BaseScimGroupModel +{ + public ScimGroupRequestModel() + : base(false) + { } + + public Group ToGroup(Guid organizationId) + { + var externalId = string.IsNullOrWhiteSpace(ExternalId) ? CoreHelpers.RandomString(15) : ExternalId; + return new Group + { + Name = DisplayName, + ExternalId = externalId, + OrganizationId = organizationId + }; + } + + public List Members { get; set; } + + public class GroupMembersModel + { + public string Value { get; set; } + public string Display { get; set; } + } +} diff --git a/bitwarden_license/src/Scim/Models/ScimGroupResponseModel.cs b/bitwarden_license/src/Scim/Models/ScimGroupResponseModel.cs new file mode 100644 index 000000000..d5bd64a32 --- /dev/null +++ b/bitwarden_license/src/Scim/Models/ScimGroupResponseModel.cs @@ -0,0 +1,25 @@ +using Bit.Core.Entities; + +namespace Bit.Scim.Models; + +public class ScimGroupResponseModel : BaseScimGroupModel +{ + public ScimGroupResponseModel() + : base(true) + { + Meta = new ScimMetaModel("Group"); + } + + public ScimGroupResponseModel(Group group) + : this() + { + Id = group.Id.ToString(); + DisplayName = group.Name; + ExternalId = group.ExternalId; + Meta.Created = group.CreationDate; + Meta.LastModified = group.RevisionDate; + } + + public string Id { get; set; } + public ScimMetaModel Meta { get; private set; } +} diff --git a/bitwarden_license/src/Scim/Models/ScimListResponseModel.cs b/bitwarden_license/src/Scim/Models/ScimListResponseModel.cs new file mode 100644 index 000000000..77ab52356 --- /dev/null +++ b/bitwarden_license/src/Scim/Models/ScimListResponseModel.cs @@ -0,0 +1,15 @@ +using Bit.Scim.Utilities; + +namespace Bit.Scim.Models; + +public class ScimListResponseModel : BaseScimModel +{ + public ScimListResponseModel() + : base(ScimConstants.Scim2SchemaListResponse) + { } + + public int TotalResults { get; set; } + public int StartIndex { get; set; } + public int ItemsPerPage { get; set; } + public List Resources { get; set; } +} diff --git a/bitwarden_license/src/Scim/Models/ScimMetaModel.cs b/bitwarden_license/src/Scim/Models/ScimMetaModel.cs new file mode 100644 index 000000000..862c054b7 --- /dev/null +++ b/bitwarden_license/src/Scim/Models/ScimMetaModel.cs @@ -0,0 +1,13 @@ +namespace Bit.Scim.Models; + +public class ScimMetaModel +{ + public ScimMetaModel(string resourceType) + { + ResourceType = resourceType; + } + + public string ResourceType { get; set; } + public DateTime? Created { get; set; } + public DateTime? LastModified { get; set; } +} diff --git a/bitwarden_license/src/Scim/Models/ScimPatchModel.cs b/bitwarden_license/src/Scim/Models/ScimPatchModel.cs new file mode 100644 index 000000000..6707ced85 --- /dev/null +++ b/bitwarden_license/src/Scim/Models/ScimPatchModel.cs @@ -0,0 +1,18 @@ +using System.Text.Json; + +namespace Bit.Scim.Models; + +public class ScimPatchModel : BaseScimModel +{ + public ScimPatchModel() + : base() { } + + public List Operations { get; set; } + + public class OperationModel + { + public string Op { get; set; } + public string Path { get; set; } + public JsonElement Value { get; set; } + } +} diff --git a/bitwarden_license/src/Scim/Models/ScimUserRequestModel.cs b/bitwarden_license/src/Scim/Models/ScimUserRequestModel.cs new file mode 100644 index 000000000..a489e03ad --- /dev/null +++ b/bitwarden_license/src/Scim/Models/ScimUserRequestModel.cs @@ -0,0 +1,8 @@ +namespace Bit.Scim.Models; + +public class ScimUserRequestModel : BaseScimUserModel +{ + public ScimUserRequestModel() + : base(false) + { } +} diff --git a/bitwarden_license/src/Scim/Models/ScimUserResponseModel.cs b/bitwarden_license/src/Scim/Models/ScimUserResponseModel.cs new file mode 100644 index 000000000..95d5184da --- /dev/null +++ b/bitwarden_license/src/Scim/Models/ScimUserResponseModel.cs @@ -0,0 +1,28 @@ +using Bit.Core.Models.Data.Organizations.OrganizationUsers; + +namespace Bit.Scim.Models; + +public class ScimUserResponseModel : BaseScimUserModel +{ + public ScimUserResponseModel() + : base(true) + { + Meta = new ScimMetaModel("User"); + Groups = new List(); + } + + public ScimUserResponseModel(OrganizationUserUserDetails orgUser) + : this() + { + Id = orgUser.Id.ToString(); + ExternalId = orgUser.ExternalId; + UserName = orgUser.Email; + DisplayName = orgUser.Name; + Emails = new List { new EmailModel(orgUser.Email) }; + Name = new NameModel(orgUser.Name); + Active = orgUser.Status != Core.Enums.OrganizationUserStatusType.Revoked; + } + + public string Id { get; set; } + public ScimMetaModel Meta { get; private set; } +} diff --git a/bitwarden_license/src/Scim/Program.cs b/bitwarden_license/src/Scim/Program.cs new file mode 100644 index 000000000..5d7d505aa --- /dev/null +++ b/bitwarden_license/src/Scim/Program.cs @@ -0,0 +1,32 @@ +using Bit.Core.Utilities; + +namespace Bit.Scim; + +public class Program +{ + public static void Main(string[] args) + { + Host + .CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + webBuilder.ConfigureLogging((hostingContext, logging) => + logging.AddSerilog(hostingContext, (e, globalSettings) => + { + var context = e.Properties["SourceContext"].ToString(); + + if (e.Properties.ContainsKey("RequestPath") && + !string.IsNullOrWhiteSpace(e.Properties["RequestPath"]?.ToString()) && + (context.Contains(".Server.Kestrel") || context.Contains(".Core.IISHttpServer"))) + { + return false; + } + + return e.Level >= globalSettings.MinLogLevel.ScimSettings.Default; + })); + }) + .Build() + .Run(); + } +} diff --git a/bitwarden_license/src/Scim/Properties/launchSettings.json b/bitwarden_license/src/Scim/Properties/launchSettings.json new file mode 100644 index 000000000..a391acb2b --- /dev/null +++ b/bitwarden_license/src/Scim/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:44558/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": false, + "launchUrl": "http://localhost:44558", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Scim": { + "commandName": "Project", + "launchBrowser": false, + "launchUrl": "http://localhost:44558", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:44559" + } + } +} diff --git a/bitwarden_license/src/Scim/Scim.csproj b/bitwarden_license/src/Scim/Scim.csproj new file mode 100644 index 000000000..3387d74e0 --- /dev/null +++ b/bitwarden_license/src/Scim/Scim.csproj @@ -0,0 +1,17 @@ + + + + bitwarden-Scim + false + + + + + + + + + + + + diff --git a/bitwarden_license/src/Scim/ScimSettings.cs b/bitwarden_license/src/Scim/ScimSettings.cs new file mode 100644 index 000000000..ef4ebfb50 --- /dev/null +++ b/bitwarden_license/src/Scim/ScimSettings.cs @@ -0,0 +1,5 @@ +namespace Bit.Scim; + +public class ScimSettings +{ +} diff --git a/bitwarden_license/src/Scim/Startup.cs b/bitwarden_license/src/Scim/Startup.cs new file mode 100644 index 000000000..4aaccd9ed --- /dev/null +++ b/bitwarden_license/src/Scim/Startup.cs @@ -0,0 +1,120 @@ +using System.Globalization; +using Bit.Core.Context; +using Bit.Core.Settings; +using Bit.Core.Utilities; +using Bit.Scim.Context; +using Bit.Scim.Utilities; +using Bit.SharedWeb.Utilities; +using IdentityModel; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Stripe; + +namespace Bit.Scim; + +public class Startup +{ + public Startup(IWebHostEnvironment env, IConfiguration configuration) + { + CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); + Configuration = configuration; + Environment = env; + } + + public IConfiguration Configuration { get; } + public IWebHostEnvironment Environment { get; set; } + + public void ConfigureServices(IServiceCollection services) + { + // Options + services.AddOptions(); + + // Settings + var globalSettings = services.AddGlobalSettingsServices(Configuration, Environment); + services.Configure(Configuration.GetSection("ScimSettings")); + + // Data Protection + services.AddCustomDataProtectionServices(Environment, globalSettings); + + // Stripe Billing + StripeConfiguration.ApiKey = globalSettings.Stripe.ApiKey; + StripeConfiguration.MaxNetworkRetries = globalSettings.Stripe.MaxNetworkRetries; + + // Repositories + services.AddDatabaseRepositories(globalSettings); + + // Context + services.AddScoped(); + services.AddScoped(); + + // Authentication + services.AddAuthentication(ApiKeyAuthenticationOptions.DefaultScheme) + .AddScheme( + ApiKeyAuthenticationOptions.DefaultScheme, null); + + services.AddAuthorization(config => + { + config.AddPolicy("Scim", policy => + { + policy.RequireAuthenticatedUser(); + policy.RequireClaim(JwtClaimTypes.Scope, "api.scim"); + }); + }); + + // Identity + services.AddCustomIdentityServices(globalSettings); + + // Services + services.AddBaseServices(globalSettings); + services.AddDefaultServices(globalSettings); + + services.TryAddSingleton(); + + // Mvc + services.AddMvc(config => + { + config.Filters.Add(new LoggingExceptionHandlerFilterAttribute()); + }); + services.Configure(options => options.LowercaseUrls = true); + + services.AddScimGroupCommands(); + services.AddScimGroupQueries(); + services.AddScimUserQueries(); + services.AddScimUserCommands(); + } + + public void Configure( + IApplicationBuilder app, + IWebHostEnvironment env, + IHostApplicationLifetime appLifetime, + GlobalSettings globalSettings) + { + app.UseSerilog(env, appLifetime, globalSettings); + + // Add general security headers + app.UseMiddleware(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + // Default Middleware + app.UseDefaultMiddleware(env, globalSettings); + + // Add routing + app.UseRouting(); + + // Add Scim context + app.UseMiddleware(); + + // Add authentication and authorization to the request pipeline. + app.UseAuthentication(); + app.UseAuthorization(); + + // Add current context + app.UseMiddleware(); + + // Add MVC to the request pipeline. + app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute()); + } +} diff --git a/bitwarden_license/src/Scim/Users/GetUsersListQuery.cs b/bitwarden_license/src/Scim/Users/GetUsersListQuery.cs new file mode 100644 index 000000000..51250250f --- /dev/null +++ b/bitwarden_license/src/Scim/Users/GetUsersListQuery.cs @@ -0,0 +1,69 @@ +using Bit.Core.Models.Data.Organizations.OrganizationUsers; +using Bit.Core.Repositories; +using Bit.Scim.Users.Interfaces; + +namespace Bit.Scim.Users; + +public class GetUsersListQuery : IGetUsersListQuery +{ + private readonly IOrganizationUserRepository _organizationUserRepository; + + public GetUsersListQuery(IOrganizationUserRepository organizationUserRepository) + { + _organizationUserRepository = organizationUserRepository; + } + + public async Task<(IEnumerable userList, int totalResults)> GetUsersListAsync(Guid organizationId, string filter, int? count, int? startIndex) + { + string emailFilter = null; + string usernameFilter = null; + string externalIdFilter = null; + if (!string.IsNullOrWhiteSpace(filter)) + { + if (filter.StartsWith("userName eq ")) + { + usernameFilter = filter.Substring(12).Trim('"').ToLowerInvariant(); + if (usernameFilter.Contains("@")) + { + emailFilter = usernameFilter; + } + } + else if (filter.StartsWith("externalId eq ")) + { + externalIdFilter = filter.Substring(14).Trim('"'); + } + } + + var userList = new List(); + var orgUsers = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(organizationId); + var totalResults = 0; + if (!string.IsNullOrWhiteSpace(emailFilter)) + { + var orgUser = orgUsers.FirstOrDefault(ou => ou.Email.ToLowerInvariant() == emailFilter); + if (orgUser != null) + { + userList.Add(orgUser); + } + totalResults = userList.Count; + } + else if (!string.IsNullOrWhiteSpace(externalIdFilter)) + { + var orgUser = orgUsers.FirstOrDefault(ou => ou.ExternalId == externalIdFilter); + if (orgUser != null) + { + userList.Add(orgUser); + } + totalResults = userList.Count; + } + else if (string.IsNullOrWhiteSpace(filter) && startIndex.HasValue && count.HasValue) + { + userList = orgUsers.OrderBy(ou => ou.Email) + .Skip(startIndex.Value - 1) + .Take(count.Value) + .ToList(); + totalResults = orgUsers.Count; + } + + return (userList, totalResults); + } +} diff --git a/bitwarden_license/src/Scim/Users/Interfaces/IGetUsersListQuery.cs b/bitwarden_license/src/Scim/Users/Interfaces/IGetUsersListQuery.cs new file mode 100644 index 000000000..265c6a8e7 --- /dev/null +++ b/bitwarden_license/src/Scim/Users/Interfaces/IGetUsersListQuery.cs @@ -0,0 +1,8 @@ +using Bit.Core.Models.Data.Organizations.OrganizationUsers; + +namespace Bit.Scim.Users.Interfaces; + +public interface IGetUsersListQuery +{ + Task<(IEnumerable userList, int totalResults)> GetUsersListAsync(Guid organizationId, string filter, int? count, int? startIndex); +} diff --git a/bitwarden_license/src/Scim/Users/Interfaces/IPatchUserCommand.cs b/bitwarden_license/src/Scim/Users/Interfaces/IPatchUserCommand.cs new file mode 100644 index 000000000..dcc349a0c --- /dev/null +++ b/bitwarden_license/src/Scim/Users/Interfaces/IPatchUserCommand.cs @@ -0,0 +1,8 @@ +using Bit.Scim.Models; + +namespace Bit.Scim.Users.Interfaces; + +public interface IPatchUserCommand +{ + Task PatchUserAsync(Guid organizationId, Guid id, ScimPatchModel model); +} diff --git a/bitwarden_license/src/Scim/Users/Interfaces/IPostUserCommand.cs b/bitwarden_license/src/Scim/Users/Interfaces/IPostUserCommand.cs new file mode 100644 index 000000000..05dd05510 --- /dev/null +++ b/bitwarden_license/src/Scim/Users/Interfaces/IPostUserCommand.cs @@ -0,0 +1,9 @@ +using Bit.Core.Models.Data.Organizations.OrganizationUsers; +using Bit.Scim.Models; + +namespace Bit.Scim.Users.Interfaces; + +public interface IPostUserCommand +{ + Task PostUserAsync(Guid organizationId, ScimUserRequestModel model); +} diff --git a/bitwarden_license/src/Scim/Users/PatchUserCommand.cs b/bitwarden_license/src/Scim/Users/PatchUserCommand.cs new file mode 100644 index 000000000..075807a58 --- /dev/null +++ b/bitwarden_license/src/Scim/Users/PatchUserCommand.cs @@ -0,0 +1,87 @@ +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Core.Services; +using Bit.Scim.Models; +using Bit.Scim.Users.Interfaces; + +namespace Bit.Scim.Users; + +public class PatchUserCommand : IPatchUserCommand +{ + private readonly IUserService _userService; + private readonly IOrganizationUserRepository _organizationUserRepository; + private readonly IOrganizationService _organizationService; + private readonly ILogger _logger; + + public PatchUserCommand( + IUserService userService, + IOrganizationUserRepository organizationUserRepository, + IOrganizationService organizationService, + ILogger logger) + { + _userService = userService; + _organizationUserRepository = organizationUserRepository; + _organizationService = organizationService; + _logger = logger; + } + + public async Task PatchUserAsync(Guid organizationId, Guid id, ScimPatchModel model) + { + var orgUser = await _organizationUserRepository.GetByIdAsync(id); + if (orgUser == null || orgUser.OrganizationId != organizationId) + { + throw new NotFoundException("User not found."); + } + + var operationHandled = false; + foreach (var operation in model.Operations) + { + // Replace operations + if (operation.Op?.ToLowerInvariant() == "replace") + { + // Active from path + if (operation.Path?.ToLowerInvariant() == "active") + { + var active = operation.Value.ToString()?.ToLowerInvariant(); + var handled = await HandleActiveOperationAsync(orgUser, active == "true"); + if (!operationHandled) + { + operationHandled = handled; + } + } + // Active from value object + else if (string.IsNullOrWhiteSpace(operation.Path) && + operation.Value.TryGetProperty("active", out var activeProperty)) + { + var handled = await HandleActiveOperationAsync(orgUser, activeProperty.GetBoolean()); + if (!operationHandled) + { + operationHandled = handled; + } + } + } + } + + if (!operationHandled) + { + _logger.LogWarning("User patch operation not handled: {operation} : ", + string.Join(", ", model.Operations.Select(o => $"{o.Op}:{o.Path}"))); + } + } + + private async Task HandleActiveOperationAsync(Core.Entities.OrganizationUser orgUser, bool active) + { + if (active && orgUser.Status == OrganizationUserStatusType.Revoked) + { + await _organizationService.RestoreUserAsync(orgUser, EventSystemUser.SCIM, _userService); + return true; + } + else if (!active && orgUser.Status != OrganizationUserStatusType.Revoked) + { + await _organizationService.RevokeUserAsync(orgUser, EventSystemUser.SCIM); + return true; + } + return false; + } +} diff --git a/bitwarden_license/src/Scim/Users/PostUserCommand.cs b/bitwarden_license/src/Scim/Users/PostUserCommand.cs new file mode 100644 index 000000000..3526cf5ab --- /dev/null +++ b/bitwarden_license/src/Scim/Users/PostUserCommand.cs @@ -0,0 +1,88 @@ +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.Models.Data; +using Bit.Core.Models.Data.Organizations.OrganizationUsers; +using Bit.Core.Repositories; +using Bit.Core.Services; +using Bit.Core.Utilities; +using Bit.Scim.Context; +using Bit.Scim.Models; +using Bit.Scim.Users.Interfaces; + +namespace Bit.Scim.Users; + +public class PostUserCommand : IPostUserCommand +{ + private readonly IOrganizationUserRepository _organizationUserRepository; + private readonly IOrganizationService _organizationService; + private readonly IScimContext _scimContext; + + public PostUserCommand( + IOrganizationUserRepository organizationUserRepository, + IOrganizationService organizationService, + IScimContext scimContext) + { + _organizationUserRepository = organizationUserRepository; + _organizationService = organizationService; + _scimContext = scimContext; + } + + public async Task PostUserAsync(Guid organizationId, ScimUserRequestModel model) + { + var email = model.PrimaryEmail?.ToLowerInvariant(); + if (string.IsNullOrWhiteSpace(email)) + { + switch (_scimContext.RequestScimProvider) + { + case ScimProviderType.AzureAd: + email = model.UserName?.ToLowerInvariant(); + break; + default: + email = model.WorkEmail?.ToLowerInvariant(); + if (string.IsNullOrWhiteSpace(email)) + { + email = model.Emails?.FirstOrDefault()?.Value?.ToLowerInvariant(); + } + break; + } + } + + if (string.IsNullOrWhiteSpace(email) || !model.Active) + { + throw new BadRequestException(); + } + + var orgUsers = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(organizationId); + var orgUserByEmail = orgUsers.FirstOrDefault(ou => ou.Email?.ToLowerInvariant() == email); + if (orgUserByEmail != null) + { + throw new ConflictException(); + } + + string externalId = null; + if (!string.IsNullOrWhiteSpace(model.ExternalId)) + { + externalId = model.ExternalId; + } + else if (!string.IsNullOrWhiteSpace(model.UserName)) + { + externalId = model.UserName; + } + else + { + externalId = CoreHelpers.RandomString(15); + } + + var orgUserByExternalId = orgUsers.FirstOrDefault(ou => ou.ExternalId == externalId); + if (orgUserByExternalId != null) + { + throw new ConflictException(); + } + + var invitedOrgUser = await _organizationService.InviteUserAsync(organizationId, EventSystemUser.SCIM, email, + OrganizationUserType.User, false, externalId, new List(), new List()); + var orgUser = await _organizationUserRepository.GetDetailsByIdAsync(invitedOrgUser.Id); + + return orgUser; + } +} diff --git a/bitwarden_license/src/Scim/Utilities/ApiKeyAuthenticationHandler.cs b/bitwarden_license/src/Scim/Utilities/ApiKeyAuthenticationHandler.cs new file mode 100644 index 000000000..4e7e7ceb7 --- /dev/null +++ b/bitwarden_license/src/Scim/Utilities/ApiKeyAuthenticationHandler.cs @@ -0,0 +1,89 @@ +using System.Security.Claims; +using System.Text.Encodings.Web; +using Bit.Core.Enums; +using Bit.Core.Repositories; +using Bit.Scim.Context; +using IdentityModel; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Options; + +namespace Bit.Scim.Utilities; + +public class ApiKeyAuthenticationHandler : AuthenticationHandler +{ + private readonly IOrganizationRepository _organizationRepository; + private readonly IOrganizationApiKeyRepository _organizationApiKeyRepository; + private readonly IScimContext _scimContext; + + public ApiKeyAuthenticationHandler( + IOptionsMonitor options, + ILoggerFactory logger, + UrlEncoder encoder, + ISystemClock clock, + IOrganizationRepository organizationRepository, + IOrganizationApiKeyRepository organizationApiKeyRepository, + IScimContext scimContext) : + base(options, logger, encoder, clock) + { + _organizationRepository = organizationRepository; + _organizationApiKeyRepository = organizationApiKeyRepository; + _scimContext = scimContext; + } + + protected override async Task HandleAuthenticateAsync() + { + var endpoint = Context.GetEndpoint(); + if (endpoint?.Metadata?.GetMetadata() != null) + { + return AuthenticateResult.NoResult(); + } + + if (!_scimContext.OrganizationId.HasValue || _scimContext.Organization == null) + { + Logger.LogWarning("No organization."); + return AuthenticateResult.Fail("Invalid parameters"); + } + + if (!Request.Headers.TryGetValue("Authorization", out var authHeader) || authHeader.Count != 1) + { + Logger.LogWarning("An API request was received without the Authorization header"); + return AuthenticateResult.Fail("Invalid parameters"); + } + var apiKey = authHeader.ToString(); + if (apiKey.StartsWith("Bearer ")) + { + apiKey = apiKey.Substring(7); + } + + if (!_scimContext.Organization.Enabled || !_scimContext.Organization.UseScim || + _scimContext.ScimConfiguration == null || !_scimContext.ScimConfiguration.Enabled) + { + Logger.LogInformation("Org {organizationId} not able to use Scim.", _scimContext.OrganizationId); + return AuthenticateResult.Fail("Invalid parameters"); + } + + var orgApiKey = (await _organizationApiKeyRepository + .GetManyByOrganizationIdTypeAsync(_scimContext.Organization.Id, OrganizationApiKeyType.Scim)) + .FirstOrDefault(); + if (orgApiKey?.ApiKey != apiKey) + { + Logger.LogWarning("An API request was received with an invalid API key: {apiKey}", apiKey); + return AuthenticateResult.Fail("Invalid parameters"); + } + + Logger.LogInformation("Org {organizationId} authenticated", _scimContext.OrganizationId); + + var claims = new[] + { + new Claim(JwtClaimTypes.ClientId, $"organization.{_scimContext.OrganizationId.Value}"), + new Claim("client_sub", _scimContext.OrganizationId.Value.ToString()), + new Claim(JwtClaimTypes.Scope, "api.scim"), + }; + var identity = new ClaimsIdentity(claims, nameof(ApiKeyAuthenticationHandler)); + var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), + ApiKeyAuthenticationOptions.DefaultScheme); + + return AuthenticateResult.Success(ticket); + } +} diff --git a/bitwarden_license/src/Scim/Utilities/ApiKeyAuthenticationOptions.cs b/bitwarden_license/src/Scim/Utilities/ApiKeyAuthenticationOptions.cs new file mode 100644 index 000000000..f0015226b --- /dev/null +++ b/bitwarden_license/src/Scim/Utilities/ApiKeyAuthenticationOptions.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNetCore.Authentication; + +namespace Bit.Scim.Utilities; + +public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions +{ + public const string DefaultScheme = "ScimApiKey"; +} diff --git a/bitwarden_license/src/Scim/Utilities/ExceptionHandlerFilterAttribute.cs b/bitwarden_license/src/Scim/Utilities/ExceptionHandlerFilterAttribute.cs new file mode 100644 index 000000000..004a8b844 --- /dev/null +++ b/bitwarden_license/src/Scim/Utilities/ExceptionHandlerFilterAttribute.cs @@ -0,0 +1,43 @@ +using Bit.Core.Exceptions; +using Bit.Scim.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace Bit.Scim.Utilities; + +public class ExceptionHandlerFilterAttribute : ExceptionFilterAttribute +{ + public override void OnException(ExceptionContext context) + { + var exception = context.Exception; + if (exception == null) + { + // Should never happen. + return; + } + + int statusCode = StatusCodes.Status500InternalServerError; + var scimErrorResponseModel = new ScimErrorResponseModel + { + Detail = exception.Message + }; + + if (exception is NotFoundException) + { + statusCode = StatusCodes.Status404NotFound; + } + else if (exception is BadRequestException) + { + statusCode = StatusCodes.Status400BadRequest; + } + else if (exception is ConflictException) + { + statusCode = StatusCodes.Status409Conflict; + } + + scimErrorResponseModel.Status = statusCode; + + context.HttpContext.Response.StatusCode = statusCode; + context.Result = new ObjectResult(scimErrorResponseModel); + } +} diff --git a/bitwarden_license/src/Scim/Utilities/ScimConstants.cs b/bitwarden_license/src/Scim/Utilities/ScimConstants.cs new file mode 100644 index 000000000..219be6534 --- /dev/null +++ b/bitwarden_license/src/Scim/Utilities/ScimConstants.cs @@ -0,0 +1,9 @@ +namespace Bit.Scim.Utilities; + +public static class ScimConstants +{ + public const string Scim2SchemaListResponse = "urn:ietf:params:scim:api:messages:2.0:ListResponse"; + public const string Scim2SchemaError = "urn:ietf:params:scim:api:messages:2.0:Error"; + public const string Scim2SchemaUser = "urn:ietf:params:scim:schemas:core:2.0:User"; + public const string Scim2SchemaGroup = "urn:ietf:params:scim:schemas:core:2.0:Group"; +} diff --git a/bitwarden_license/src/Scim/Utilities/ScimContextMiddleware.cs b/bitwarden_license/src/Scim/Utilities/ScimContextMiddleware.cs new file mode 100644 index 000000000..6d5f3e1bf --- /dev/null +++ b/bitwarden_license/src/Scim/Utilities/ScimContextMiddleware.cs @@ -0,0 +1,22 @@ +using Bit.Core.Repositories; +using Bit.Core.Settings; +using Bit.Scim.Context; + +namespace Bit.Scim.Utilities; + +public class ScimContextMiddleware +{ + private readonly RequestDelegate _next; + + public ScimContextMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task Invoke(HttpContext httpContext, IScimContext scimContext, GlobalSettings globalSettings, + IOrganizationRepository organizationRepository, IOrganizationConnectionRepository organizationConnectionRepository) + { + await scimContext.BuildAsync(httpContext, globalSettings, organizationRepository, organizationConnectionRepository); + await _next.Invoke(httpContext); + } +} diff --git a/bitwarden_license/src/Scim/Utilities/ScimServiceCollectionExtensions.cs b/bitwarden_license/src/Scim/Utilities/ScimServiceCollectionExtensions.cs new file mode 100644 index 000000000..fff70760d --- /dev/null +++ b/bitwarden_license/src/Scim/Utilities/ScimServiceCollectionExtensions.cs @@ -0,0 +1,35 @@ +using Bit.Core.OrganizationFeatures.OrganizationUsers; +using Bit.Core.OrganizationFeatures.OrganizationUsers.Interfaces; +using Bit.Scim.Groups; +using Bit.Scim.Groups.Interfaces; +using Bit.Scim.Users; +using Bit.Scim.Users.Interfaces; + +namespace Bit.Scim.Utilities; + +public static class ScimServiceCollectionExtensions +{ + public static void AddScimGroupCommands(this IServiceCollection services) + { + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + } + + public static void AddScimGroupQueries(this IServiceCollection services) + { + services.AddScoped(); + } + + public static void AddScimUserCommands(this IServiceCollection services) + { + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + } + + public static void AddScimUserQueries(this IServiceCollection services) + { + services.AddScoped(); + } +} diff --git a/bitwarden_license/src/Scim/appsettings.Development.json b/bitwarden_license/src/Scim/appsettings.Development.json new file mode 100644 index 000000000..32253a93c --- /dev/null +++ b/bitwarden_license/src/Scim/appsettings.Development.json @@ -0,0 +1,35 @@ +{ + "globalSettings": { + "baseServiceUri": { + "vault": "https://localhost:8080", + "api": "http://localhost:4000", + "identity": "http://localhost:33656", + "admin": "http://localhost:62911", + "notifications": "http://localhost:61840", + "sso": "http://localhost:51822", + "internalNotifications": "http://localhost:61840", + "internalAdmin": "http://localhost:62911", + "internalIdentity": "http://localhost:33656", + "internalApi": "http://localhost:4000", + "internalVault": "https://localhost:8080", + "internalSso": "http://localhost:51822", + "internalScim": "http://localhost:44559" + }, + "mail": { + "smtp": { + "host": "localhost", + "port": 10250 + } + }, + "attachment": { + "connectionString": "UseDevelopmentStorage=true", + "baseUrl": "http://localhost:4000/attachments/" + }, + "events": { + "connectionString": "UseDevelopmentStorage=true" + }, + "storage": { + "connectionString": "UseDevelopmentStorage=true" + } + } +} diff --git a/bitwarden_license/src/Scim/appsettings.Production.json b/bitwarden_license/src/Scim/appsettings.Production.json new file mode 100644 index 000000000..d9efbcda1 --- /dev/null +++ b/bitwarden_license/src/Scim/appsettings.Production.json @@ -0,0 +1,42 @@ +{ + "globalSettings": { + "baseServiceUri": { + "vault": "https://vault.bitwarden.com", + "api": "https://api.bitwarden.com", + "identity": "https://identity.bitwarden.com", + "admin": "https://admin.bitwarden.com", + "notifications": "https://notifications.bitwarden.com", + "sso": "https://sso.bitwarden.com", + "internalNotifications": "https://notifications.bitwarden.com", + "internalAdmin": "https://admin.bitwarden.com", + "internalIdentity": "https://identity.bitwarden.com", + "internalApi": "https://api.bitwarden.com", + "internalVault": "https://vault.bitwarden.com", + "internalSso": "https://sso.bitwarden.com", + "internalScim": "https://scim.bitwarden.com" + }, + "braintree": { + "production": true + }, + "bitPay": { + "production": true + } + }, + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + }, + "Console": { + "IncludeScopes": true, + "LogLevel": { + "Default": "Warning", + "System": "Warning", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } + } +} diff --git a/bitwarden_license/src/Scim/appsettings.QA.json b/bitwarden_license/src/Scim/appsettings.QA.json new file mode 100644 index 000000000..f4491a055 --- /dev/null +++ b/bitwarden_license/src/Scim/appsettings.QA.json @@ -0,0 +1,42 @@ +{ + "globalSettings": { + "baseServiceUri": { + "vault": "https://vault.qa.bitwarden.pw", + "api": "https://api.qa.bitwarden.pw", + "identity": "https://identity.qa.bitwarden.pw", + "admin": "https://admin.qa.bitwarden.pw", + "notifications": "https://notifications.qa.bitwarden.pw", + "sso": "https://sso.qa.bitwarden.pw", + "internalNotifications": "https://notifications.qa.bitwarden.pw", + "internalAdmin": "https://admin.qa.bitwarden.pw", + "internalIdentity": "https://identity.qa.bitwarden.pw", + "internalApi": "https://api.qa.bitwarden.pw", + "internalVault": "https://vault.qa.bitwarden.pw", + "internalSso": "https://sso.qa.bitwarden.pw", + "internalScim": "https://scim.qa.bitwarden.pw" + }, + "braintree": { + "production": false + }, + "bitPay": { + "production": false + } + }, + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + }, + "Console": { + "IncludeScopes": true, + "LogLevel": { + "Default": "Debug", + "System": "Debug", + "Microsoft": "Debug", + "Microsoft.Hosting.Lifetime": "Information" + } + } + } +} diff --git a/bitwarden_license/src/Scim/appsettings.json b/bitwarden_license/src/Scim/appsettings.json new file mode 100644 index 000000000..630896a65 --- /dev/null +++ b/bitwarden_license/src/Scim/appsettings.json @@ -0,0 +1,63 @@ +{ + "globalSettings": { + "selfHosted": false, + "siteName": "Bitwarden", + "projectName": "Scim", + "stripe": { + "apiKey": "SECRET" + }, + "sqlServer": { + "connectionString": "SECRET" + }, + "mail": { + "sendGridApiKey": "SECRET", + "amazonConfigSetName": "Email", + "replyToEmail": "no-reply@bitwarden.com" + }, + "identityServer": { + "certificateThumbprint": "SECRET" + }, + "dataProtection": { + "certificateThumbprint": "SECRET" + }, + "storage": { + "connectionString": "SECRET" + }, + "events": { + "connectionString": "SECRET" + }, + "serviceBus": { + "connectionString": "SECRET", + "applicationCacheTopicName": "SECRET" + }, + "documentDb": { + "uri": "SECRET", + "key": "SECRET" + }, + "sentry": { + "dsn": "SECRET" + }, + "notificationHub": { + "connectionString": "SECRET", + "hubName": "SECRET" + }, + "braintree": { + "production": false, + "merchantId": "SECRET", + "publicKey": "SECRET", + "privateKey": "SECRET" + }, + "bitPay": { + "production": false, + "token": "SECRET", + "notificationUrl": "https://bitwarden.com/SECRET" + }, + "amazon": { + "accessKeyId": "SECRET", + "accessKeySecret": "SECRET", + "region": "SECRET" + } + }, + "scimSettings": { + } +} diff --git a/bitwarden_license/src/Scim/build.ps1 b/bitwarden_license/src/Scim/build.ps1 new file mode 100644 index 000000000..21ed14161 --- /dev/null +++ b/bitwarden_license/src/Scim/build.ps1 @@ -0,0 +1,12 @@ +$dir = Split-Path -Parent $MyInvocation.MyCommand.Path + +echo "`n## Building Scim" + +echo "`nBuilding app" +echo ".NET Core version $(dotnet --version)" +echo "Restore" +dotnet restore $dir\Scim.csproj +echo "Clean" +dotnet clean $dir\Scim.csproj -c "Release" -o $dir\obj\Azure\publish +echo "Publish" +dotnet publish $dir\Scim.csproj -c "Release" -o $dir\obj\Azure\publish diff --git a/bitwarden_license/src/Scim/build.sh b/bitwarden_license/src/Scim/build.sh new file mode 100644 index 000000000..b6deb89b4 --- /dev/null +++ b/bitwarden_license/src/Scim/build.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -e + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && "pwd" )" + +echo -e "\n## Building SCIM" + +echo -e "\nBuilding app" +echo ".NET Core version $(dotnet --version)" +echo "Restore" +dotnet restore "$DIR/Scim.csproj" +echo "Clean" +dotnet clean "$DIR/Scim.csproj" -c "Release" -o "$DIR/obj/build-output/publish" +echo "Publish" +dotnet publish "$DIR/Scim.csproj" -c "Release" -o "$DIR/obj/build-output/publish" diff --git a/bitwarden_license/src/Scim/entrypoint.sh b/bitwarden_license/src/Scim/entrypoint.sh new file mode 100644 index 000000000..0d54517bb --- /dev/null +++ b/bitwarden_license/src/Scim/entrypoint.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# Setup + +GROUPNAME="bitwarden" +USERNAME="bitwarden" + +LUID=${LOCAL_UID:-0} +LGID=${LOCAL_GID:-0} + +# Step down from host root to well-known nobody/nogroup user + +if [ $LUID -eq 0 ] +then + LUID=65534 +fi +if [ $LGID -eq 0 ] +then + LGID=65534 +fi + +# Create user and group + +groupadd -o -g $LGID $GROUPNAME >/dev/null 2>&1 || +groupmod -o -g $LGID $GROUPNAME >/dev/null 2>&1 +useradd -o -u $LUID -g $GROUPNAME -s /bin/false $USERNAME >/dev/null 2>&1 || +usermod -o -u $LUID -g $GROUPNAME -s /bin/false $USERNAME >/dev/null 2>&1 +mkhomedir_helper $USERNAME + +# The rest... + +chown -R $USERNAME:$GROUPNAME /app +mkdir -p /etc/bitwarden/core +mkdir -p /etc/bitwarden/logs +mkdir -p /etc/bitwarden/ca-certificates +chown -R $USERNAME:$GROUPNAME /etc/bitwarden + +cp /etc/bitwarden/ca-certificates/*.crt /usr/local/share/ca-certificates/ >/dev/null 2>&1 \ + && update-ca-certificates + +exec gosu $USERNAME:$GROUPNAME dotnet /app/Scim.dll diff --git a/bitwarden_license/src/Scim/packages.lock.json b/bitwarden_license/src/Scim/packages.lock.json new file mode 100644 index 000000000..e0ee3394c --- /dev/null +++ b/bitwarden_license/src/Scim/packages.lock.json @@ -0,0 +1,3063 @@ +{ + "version": 1, + "dependencies": { + "net6.0": { + "Microsoft.VisualStudio.Web.CodeGeneration.Design": { + "type": "Direct", + "requested": "[5.0.2, )", + "resolved": "5.0.2", + "contentHash": "9eTZV7W+S2iO2AJD03xXyXJZ+Nf71Y25gMXhqyXb8bB63jPfn+VQhV8I1lb6J+NR3jW98m5EB9QBftBSrjgiYQ==", + "dependencies": { + "Microsoft.VisualStudio.Web.CodeGenerators.Mvc": "5.0.2" + } + }, + "AspNetCoreRateLimit": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "FzXAJFgaRjKfnKAVwjEEC7OAGQM5v/I3sQw2tpzmR0yHTCGhUAxZzDuwZiXTk8XLrI6vovzkqKkfKmiDl3nYMg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.1", + "Microsoft.Extensions.Options": "6.0.0", + "Newtonsoft.Json": "13.0.1" + } + }, + "AspNetCoreRateLimit.Redis": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "CsSGy/7SXt6iBOKg0xCvsRjb/ZHshbtr2Of1MHc912L2sLnZqadUrTboyXZC+ZlgEBeJ14GyjPTu8ZyfEhGUnw==", + "dependencies": { + "AspNetCoreRateLimit": "4.0.2", + "StackExchange.Redis": "2.5.43" + } + }, + "AutoMapper": { + "type": "Transitive", + "resolved": "11.0.0", + "contentHash": "+596AnKykYCk9RxXCEF4GYuapSebQtFVvIA1oVG1rrRkCLAC7AkWehJ0brCfYUbdDW3v1H/p0W3hob7JoXGjMw==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "AutoMapper.Extensions.Microsoft.DependencyInjection": { + "type": "Transitive", + "resolved": "11.0.0", + "contentHash": "0asw5WxdCFh2OTi9Gv+oKyH9SzxwYQSnO8TV5Dd0GggovILzJW4UimP26JAcxc3yB5NnC5urooZ1BBs8ElpiBw==", + "dependencies": { + "AutoMapper": "11.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "AWSSDK.Core": { + "type": "Transitive", + "resolved": "3.7.10.11", + "contentHash": "B+M7ggPC0FogATRPQxDXL0eTusCQtXulW4zCuX39yiHV8+u9MEXRytcAw0ZA3zFBYYx6ovl9lklho6OQo1DRRQ==" + }, + "AWSSDK.SimpleEmail": { + "type": "Transitive", + "resolved": "3.7.0.150", + "contentHash": "rc/4ZnISfbgTfqz5/BWqMHBAzk4R09qfe1xkdJf2jXo44Zn2X72W8IiLLweBtmNhL7d8Tcf6UCtOHYkFwxHvug==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "AWSSDK.SQS": { + "type": "Transitive", + "resolved": "3.7.2.47", + "contentHash": "RPTVBsY333n+aIEqw148Envx9OQkE1/jhjlioNXDP6BrA3fAPN9A+2HoA02c0KSp/sazXYWg8w/kDL8FchH8Dw==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.24.0", + "contentHash": "+/qI1j2oU1S4/nvxb2k/wDsol00iGf1AyJX5g3epV7eOpQEP/2xcgh/cxgKMeFgn3U2fmgSiBnQZdkV+l5y0Uw==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Numerics.Vectors": "4.5.0", + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Extensions.AspNetCore.DataProtection.Blobs": { + "type": "Transitive", + "resolved": "1.2.1", + "contentHash": "wxvkC6DeWThBtaPbsWdicp5Ltya4J8JuhxmZJDQkhnXG7oihfu8RqBV6w/X1nMieuIOq1qQaGTvjx7nEHHfxSQ==", + "dependencies": { + "Azure.Core": "1.14.0", + "Azure.Storage.Blobs": "12.8.0", + "Microsoft.AspNetCore.DataProtection": "2.1.0" + } + }, + "Azure.Identity": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "EycyMsb6rD2PK9P0SyibFfEhvWWttdrYhyPF4f41uzdB/44yQlV+2Wehxyg489Rj6gbPvSPgbKq0xsHJBhipZA==", + "dependencies": { + "Azure.Core": "1.24.0", + "Microsoft.Identity.Client": "4.39.0", + "Microsoft.Identity.Client.Extensions.Msal": "2.19.3", + "System.Memory": "4.5.4", + "System.Security.Cryptography.ProtectedData": "4.7.0", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Storage.Blobs": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "50eRjIhY7Q1JN7kT2MSawDKCcwSb7uRZUkz00P/BLjSg47gm2hxUYsnJPyvzCHntYMbOWzrvaVQTwYwXabaR5Q==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Text.Json": "4.7.2" + } + }, + "Azure.Storage.Common": { + "type": "Transitive", + "resolved": "12.10.0", + "contentHash": "vYkHGzUkdZTace/cDPZLG+Mh/EoPqQuGxDIBOau9D+XWoDPmuUFGk325aXplkFE4JFGpSwoytNYzk/qBCaiHqg==", + "dependencies": { + "Azure.Core": "1.22.0", + "System.IO.Hashing": "6.0.0" + } + }, + "Azure.Storage.Queues": { + "type": "Transitive", + "resolved": "12.9.0", + "contentHash": "jDiyHtsCUCrWNvZW7SjJnJb46UhpdgQrWCbL8aWpapDHlq9LvbvxYpfLh4dfKAz09QiTznLMIU3i+md9+7GzqQ==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, + "BitPay.Light": { + "type": "Transitive", + "resolved": "1.0.1907", + "contentHash": "QTTIgXakHrRNQPxNyH7bZ7frm0bI8N6gRDtiqVyKG/QYQ+KfjN70xt0zQ0kO0zf8UBaKuwcV5B7vvpXtzR9ijg==", + "dependencies": { + "Newtonsoft.Json": "12.0.2" + } + }, + "Braintree": { + "type": "Transitive", + "resolved": "5.12.0", + "contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "System.Xml.XPath.XmlDocument": "4.3.0" + } + }, + "Dapper": { + "type": "Transitive", + "resolved": "2.0.123", + "contentHash": "RDFF4rBLLmbpi6pwkY7q/M6UXHRJEOerplDGE5jwEkP/JGJnBauAClYavNKJPW1yOTWRPIyfj4is3EaJxQXILQ==" + }, + "Fido2": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "S0Bz1vfcKlO4Jase3AWp5XnQ746psf4oGx5kL+D2A10j1SsjoAOAIIpanSwfi0cEepDHgk1bClcOKY5TjOzGdA==", + "dependencies": { + "Fido2.Models": "3.0.1", + "Microsoft.Extensions.Http": "6.0.0", + "NSec.Cryptography": "22.4.0", + "System.Formats.Cbor": "6.0.0", + "System.IdentityModel.Tokens.Jwt": "6.17.0" + } + }, + "Fido2.AspNet": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "5n5shEXD7RFUyTesjUHGDjkpgES7j4KotQo1GwUcS08k+fx+1tl/zCFHJ9RFDuUwO+S681ZILT2PyA67IPYpaA==", + "dependencies": { + "Fido2": "3.0.1", + "Fido2.Models": "3.0.1" + } + }, + "Fido2.Models": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "mgjcuGETuYSCUEaZG+jQeeuuEMkDLc4GDJHBvKDdOz6oSOWp5adPdWP4btZx7Pi+9fu4szN3JIjJmby67MaILw==" + }, + "Handlebars.Net": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "p60QyeBYpZmcZdIXRMqs9XySIBaxJ0lj3+QD0EJVr4ybTigOTCumXMMin5dPwjo9At1UwkDZ3gGwa1lmGjG6DA==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "Humanizer.Core": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "rsYXB7+iUPP8AHgQ8JP2UZI2xK2KhjcdGr9E6zX3CsZaTLCaw8M35vaAJRo1rfxeaZEVMuXeaquLVCkZ7JcZ5Q==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "IdentityModel": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "System.Text.Encodings.Web": "4.7.0" + } + }, + "IdentityModel.AspNetCore.OAuth2Introspection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==", + "dependencies": { + "IdentityModel": "4.0.0" + } + }, + "IdentityServer4": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==", + "dependencies": { + "IdentityModel": "4.4.0", + "IdentityServer4.Storage": "4.1.2", + "Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0", + "Newtonsoft.Json": "12.0.2" + } + }, + "IdentityServer4.AccessTokenValidation": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==", + "dependencies": { + "IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1", + "Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0" + } + }, + "IdentityServer4.Storage": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==", + "dependencies": { + "IdentityModel": "4.4.0" + } + }, + "libsodium": { + "type": "Transitive", + "resolved": "1.0.18.2", + "contentHash": "flArHoVdscSzyV8ZdPV+bqqY2TTFlaN+xZf/vIqsmHI51KVcD/mOdUPaK3n/k/wGKz8dppiktXUqSmf3AXFgig==" + }, + "linq2db": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "6/u1EzQlV25bhN0Ej/I5dLV5Hgxun+ww/TX2VnMBnSVytED2VzQGeFIO/14I624GkfPOtB79x1ooL3F18dAbdw==" + }, + "linq2db.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.11.0", + "contentHash": "mS+L6HyVHP3oJaTuFVZswNmPpTfYleGjDTo2IWBJmYXZpSQ5EPw1DpHzmyLAiQd+93ofy0Ala+9HWzv6/k73ZQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "6.0.5", + "linq2db": "4.4.0" + } + }, + "MailKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "5MTpTqmjqT7HPvYbP3HozRZMth5vSaT0ReN0iM3rAM4CgLI/R1qqtLDDNWGnFFIlcNzeJkZQRJJMkv8cgzWBbA==", + "dependencies": { + "MimeKit": "3.2.0" + } + }, + "Microsoft.AspNetCore.Authentication.JwtBearer": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "joDS3+lD1i9qcdFLWP4D316t3bHpezmTNOzbMIf9ZcRPX4QTuiUutZcQn/kZplf3BiLHqwUChZXxPjCAMKaKAQ==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0" + } + }, + "Microsoft.AspNetCore.Authentication.OpenIdConnect": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0" + } + }, + "Microsoft.AspNetCore.Cryptography.Internal": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "/0FX1OqckMmXAAlsHgBFNymTZuq4nuAOMhiwm6e8CEMi2aOjnMYwiMc7mtvpGTAO0O4C0zwx+iaChxDgvqit2A==" + }, + "Microsoft.AspNetCore.Cryptography.KeyDerivation": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "1Lbwrxg/HRY/nbrkcrB3EUXUYQN8Tkw7Ktgb6/2on2P7ybT5aM59H05gk+OBC8ZTBxwdle9e1tyT3wxEYKw5xw==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "6.0.4" + } + }, + "Microsoft.AspNetCore.DataProtection": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "G+UoMHL0xiyFh30wkL7Bv/XL6eugTAKYhLPS53k1/Me1bYRwOOw+8VL/q0ppq3/yMzpHX+MkExaCTDlYl48FgA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "2.1.0", + "Microsoft.AspNetCore.DataProtection.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.1.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0", + "Microsoft.Extensions.Logging.Abstractions": "2.1.0", + "Microsoft.Extensions.Options": "2.1.0", + "Microsoft.Win32.Registry": "4.5.0", + "System.Security.Cryptography.Xml": "4.5.0", + "System.Security.Principal.Windows": "4.5.0" + } + }, + "Microsoft.AspNetCore.DataProtection.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "2+HVDhUqrnV9+EJNEewSy+Gk4hOVPzLPMpFDZI7kuH7NWxtbNkI6A6gT5lO2/kEPMyM8/iLWtohbOwjpC9rHVw==" + }, + "Microsoft.AspNetCore.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "1TQgBfd/NPZLR2o/h6l5Cml2ZCF5hsyV4h9WEwWwAIavrbdTnaNozGGcTOd4AOgQvogMM9UM1ajflm9Cwd0jLQ==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Http.Abstractions": "2.1.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "YTKMi2vHX6P+WHEVpW/DS+eFHnwivCSMklkyamcK1ETtc/4j8H3VR0kgW8XIBqukNxhD8k5wYt22P7PhrWSXjQ==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "Microsoft.Extensions.Configuration.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Html.Abstractions": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "Y4rs5aMEXY8G7wJo5S3EEt6ltqyOTr/qOeZzfn+hw/fuQj5GppGckMY5psGLETo1U9hcT5MmAhaT5xtusM1b5g==", + "dependencies": { + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "vbFDyKsSYBnxl3+RABtN79b0vsTcG66fDY8vD6Nqvu9uLtSej70Q5NcbGlnN6bJpZci5orSdgFTHMhBywivDPg==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Features": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "UmkUePxRjsQW0j5euFFscBwjvTu25b8+qIK/2fI3GvcqQ+mkwgbWNAT8b/Gkoei1m2bTWC07lSdutuRDPPLcJA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.0" + } + }, + "Microsoft.AspNetCore.Razor": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "V54PIyDCFl8COnTp9gezNHpUNHk7F9UnerGeZy3UfbnwYvfzbo+ipqQmSgeoESH8e0JvKhRTyQyZquW2EPtCmg==", + "dependencies": { + "Microsoft.AspNetCore.Html.Abstractions": "2.2.0" + } + }, + "Microsoft.AspNetCore.Razor.Language": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "6yOBBASGfXMx1fY6hyjvG+oM3eR8vovIehDdEZW7jAV4gKlY4xuAvTm7Iw1fEq7KPunh2VrJwo7oRK1XxUn1OQ==" + }, + "Microsoft.AspNetCore.Razor.Runtime": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "7YqK+H61lN6yj9RiQUko7oaOhKtRR9Q/kBcoWNRemhJdTIWOh1OmdvJKzZrMWOlff3BAjejkPQm+0V0qXk+B1w==", + "dependencies": { + "Microsoft.AspNetCore.Html.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Razor": "2.2.0" + } + }, + "Microsoft.Azure.Amqp": { + "type": "Transitive", + "resolved": "2.4.11", + "contentHash": "7x5fu2f6TLQDDJS0sY5qW8/daFwJaY9O75YvU8RcUfRzbug+9YGjXUBxoRrprgyi0jxdBAMQL05p1s783SOSFQ==", + "dependencies": { + "System.Net.WebSockets.Client": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.Azure.Cosmos": { + "type": "Transitive", + "resolved": "3.24.0", + "contentHash": "QpUe5ho6OzlXwgcJVgAmOR7t3XLC9RI4t8T96RZY61pSOIllPOJdp30L0LwA16tKcqi5r2KayEgWO/MS9fh/6A==", + "dependencies": { + "Azure.Core": "1.3.0", + "Microsoft.Bcl.AsyncInterfaces": "1.0.0", + "Microsoft.Bcl.HashCode": "1.1.0", + "Newtonsoft.Json": "10.0.2", + "System.Buffers": "4.5.1", + "System.Collections.Immutable": "1.7.0", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Memory": "4.5.4", + "System.Numerics.Vectors": "4.5.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3", + "System.Threading.Tasks.Extensions": "4.5.4", + "System.ValueTuple": "4.5.0" + } + }, + "Microsoft.Azure.Cosmos.Table": { + "type": "Transitive", + "resolved": "1.0.8", + "contentHash": "ToeEd1yijM7nQfLYvdFLG//RjKPmfqm45eOm86UAKrxtyGI/CXqP8iL74mzBp6mZ9A/K/ZYA2fVdpH0xHR5Keg==", + "dependencies": { + "Microsoft.Azure.DocumentDB.Core": "2.11.2", + "Microsoft.OData.Core": "7.6.4", + "Newtonsoft.Json": "10.0.2" + } + }, + "Microsoft.Azure.DocumentDB.Core": { + "type": "Transitive", + "resolved": "2.11.2", + "contentHash": "cA8eWrTFbYrkHrz095x4CUGb7wqQgA1slzFZCYexhNwz6Zcn3v+S1yvWMGwGRmRjT0MKU9tYdFWgLfT0OjSycw==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "Newtonsoft.Json": "9.0.1", + "System.Collections.Immutable": "1.3.0", + "System.Collections.NonGeneric": "4.0.1", + "System.Collections.Specialized": "4.0.1", + "System.Diagnostics.TraceSource": "4.0.0", + "System.Dynamic.Runtime": "4.0.11", + "System.Linq.Queryable": "4.0.1", + "System.Net.Http": "4.3.4", + "System.Net.NameResolution": "4.0.0", + "System.Net.NetworkInformation": "4.1.0", + "System.Net.Requests": "4.0.11", + "System.Net.Security": "4.3.2", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Security.SecureString": "4.0.0" + } + }, + "Microsoft.Azure.NotificationHubs": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "C2SssjX3e6/HIo1OCImQDDVOn64d1+gkgEmgxJryzkwixyivJHWH2YIgxZs33pyzVQcZWx5PR2tqLkQ7riSq8Q==", + "dependencies": { + "Microsoft.Extensions.Caching.Memory": "3.1.8", + "Newtonsoft.Json": "12.0.3" + } + }, + "Microsoft.Azure.ServiceBus": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "wyZNJggyFNtKxd+HgvcTiuRYuTjDGi+pgE4RcBvFbfvNiarKr5AOlE4Ne7on1eUJZuMuEa19wN5dj694HlP60A==", + "dependencies": { + "Microsoft.Azure.Amqp": "2.4.11", + "Microsoft.Azure.Services.AppAuthentication": "[1.0.3, 2.0.0)", + "Newtonsoft.Json": "10.0.3", + "System.Diagnostics.DiagnosticSource": "4.5.1", + "System.IdentityModel.Tokens.Jwt": "5.4.0" + } + }, + "Microsoft.Azure.Services.AppAuthentication": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "ywpQaK1klu1IoX4VUf+TBmU4kR71aWNI6O5rEIJU8z28L2xhJhnIm7k2Nf1Zu/PygeuOtt5g0QPCk5+lLltbeQ==", + "dependencies": { + "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.14.2", + "NETStandard.Library": "1.6.1", + "System.Diagnostics.Process": "4.3.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "yuvf07qFWFqtK3P/MRkEKLhn5r2UbSpVueRziSqj0yJQIKFwG1pq9mOayK3zE5qZCTs0CbrwL9M6R8VwqyGy2w==" + }, + "Microsoft.Bcl.HashCode": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "J2G1k+u5unBV+aYcwxo94ip16Rkp65pgWFb0R6zwJipzWNMgvqlWeuI7/+R+e8bob66LnSG+llLJ+z8wI94cHg==" + }, + "Microsoft.CodeAnalysis.Analyzers": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "ojG5pGAhTPmjxRGTNvuszO3H8XPZqksDwr9xLd4Ae/JBjZZdl6GuoLk7uLMf+o7yl5wO0TAqoWcEKkEWqrZE5g==" + }, + "Microsoft.CodeAnalysis.Common": { + "type": "Transitive", + "resolved": "3.8.0", + "contentHash": "8YTZ7GpsbTdC08DITx7/kwV0k4SC6cbBAFqc13cOm5vKJZcEIAh51tNSyGSkWisMgYCr96B2wb5Zri1bsla3+g==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.0.0", + "System.Collections.Immutable": "5.0.0", + "System.Memory": "4.5.4", + "System.Reflection.Metadata": "5.0.0", + "System.Runtime.CompilerServices.Unsafe": "4.7.1", + "System.Text.Encoding.CodePages": "4.5.1", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Microsoft.CodeAnalysis.CSharp": { + "type": "Transitive", + "resolved": "3.8.0", + "contentHash": "hKqFCUSk9TIMBDjiYMF8/ZfK9p9mzpU+slM73CaCHu4ctfkoqJGHLQhyT8wvrYsIg+ufrUWBF8hcJYmyr5rc5Q==", + "dependencies": { + "Microsoft.CodeAnalysis.Common": "[3.8.0]" + } + }, + "Microsoft.CodeAnalysis.CSharp.Workspaces": { + "type": "Transitive", + "resolved": "3.8.0", + "contentHash": "rdEBvPWqe/IIscsnp7OkZ4tQin8khxBcSLyV9tU+sHdw9uW9U0GKL+Dv2rD4voC1bZBaO18Hp+m4Vkyfmaz0OA==", + "dependencies": { + "Humanizer.Core": "2.2.0", + "Microsoft.CodeAnalysis.CSharp": "[3.8.0]", + "Microsoft.CodeAnalysis.Common": "[3.8.0]", + "Microsoft.CodeAnalysis.Workspaces.Common": "[3.8.0]" + } + }, + "Microsoft.CodeAnalysis.Razor": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "s4u/6z/MQ35y/egrXf4WgJlUZf5GGvuba9mZ700dH4XxLBrA9Fw9kFZ8uymoATry7hwz5owvFhBVo+2VnoiGRg==", + "dependencies": { + "Microsoft.AspNetCore.Razor.Language": "5.0.0", + "Microsoft.CodeAnalysis.CSharp": "3.7.0", + "Microsoft.CodeAnalysis.Common": "3.7.0" + } + }, + "Microsoft.CodeAnalysis.Workspaces.Common": { + "type": "Transitive", + "resolved": "3.8.0", + "contentHash": "GPYVydsmOmScOWDJA1LFky7/MkoXpx1JI3lZJShxC+bvVUvL9zVKE8WDZMLsYJ5MAbry2xkZftdfeMpZ+kvLDQ==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "Microsoft.CodeAnalysis.Common": "[3.8.0]", + "System.Composition": "1.0.31" + } + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, + "Microsoft.Data.SqlClient": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "uu8dfrsx081cSbEevWuZAvqdmANDGJkbLBL2G3j0LAZxX1Oy8RCVAaC4Lcuak6jNicWP6CWvHqBTIEmQNSxQlw==", + "dependencies": { + "Azure.Identity": "1.6.0", + "Microsoft.Data.SqlClient.SNI.runtime": "5.0.1", + "Microsoft.Identity.Client": "4.45.0", + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.21.0", + "Microsoft.SqlServer.Server": "1.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Buffers": "4.5.1", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Diagnostics.DiagnosticSource": "5.0.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime.Caching": "5.0.0", + "System.Security.Cryptography.Cng": "5.0.0", + "System.Security.Principal.Windows": "5.0.0", + "System.Text.Encoding.CodePages": "5.0.0", + "System.Text.Encodings.Web": "4.7.2" + } + }, + "Microsoft.Data.SqlClient.SNI.runtime": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "y0X5MxiNdbITJYoafJ2ruaX6hqO0twpCGR/ipiDOe85JKLU8WL4TuAQfDe5qtt3bND5Je26HnrarLSAMMnVTNg==" + }, + "Microsoft.Data.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bui5wPPqq9OwTL5A+YJPcVStTPrOFcLwg/kAVWyqdjrTief4kTK/3bNv0MqUDVNgAUG8pcFbtdc674CIh1F3gw==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "xb10XFoPf/gWu8ik5v7xnVyUY7W21LBOLtT7PidzwYVdnE3aKuQ/bIZLcQuY7rdDNT89/wse2q5FRjm207cIMQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Analyzers": "6.0.12", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.DependencyInjection": "6.0.1", + "Microsoft.Extensions.Logging": "6.0.0", + "System.Collections.Immutable": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Abstractions": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "hvRytAcLhrb35HmtMjYWsNZZLt39ryuN7j04lDchRa9VToreyqgo5gMniTdQ6MfCflxtGnDes65V/Y2pjbEyWg==" + }, + "Microsoft.EntityFrameworkCore.Analyzers": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "ZDUY+KlsIyKdfvIJeNdqRiPExFQ5GRZVdx/Cp52vhpCJRImYv34O0Xfmw2eiLu4qe1jmM2pTzAAFKELaKwtj/w==" + }, + "Microsoft.EntityFrameworkCore.Relational": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "HBtRGHtF0Vf+BIQTkRGiopmE5rLYhj59xPpd17S1tLgYpiHDVbepCuHwh5H63fzjO99Z4tW5wmmEGF7KnD91WQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "2Hutlqt07bnWZFtYqT1lj0otX8ygMyBikysGnfQNF2TK3i5GqSTeJ8tqNi/URiI9II7Cyl15A0rflXmFoySuIw==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Sqlite.Core": "6.0.12", + "SQLitePCLRaw.bundle_e_sqlite3": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "07vKE7+t9Z2BfGmHuJwNZNv8m1GWt7ZpYYHFh1tQg1oC6FJ78bSaFzLawsf2NK6CLhbB8DBsjE0rRhxMJ4rXsA==", + "dependencies": { + "Microsoft.Data.Sqlite.Core": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Microsoft.Extensions.DependencyModel": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bcz5sSFJbganH0+YrfvIjJDIcKNW7TL07C4d1eTmXy/wOt52iz4LVogJb6pazs7W0+74j0YpXFErvp++Aq5Bsw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.Memory": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "B4y+Cev05eMcjf1na0v9gza6GUtahXbtY1JCypIgx3B4Ea/KAgsWyXEmW4q6zMbmTMtKzmPVk09rvFJirvMwTg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.StackExchangeRedis": { + "type": "Transitive", + "resolved": "6.0.6", + "contentHash": "bdVQpYm1hcHf0pyAypMjtDw3HjWQJ89UzloyyF1OBs56QlgA1naM498tP2Vjlho5vVRALMGPYzdRKCen8koubw==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "StackExchange.Redis": "2.2.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "tq2wXyh3fL17EMF2bXgRhU7JrbO3on93MRKYxzz4JzzvuGSA1l0W3GI9/tl8EO89TH+KWEymP7bcFway6z9fXg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "IznHHzGUtrdpuQqIUdmzF6TYPcsYHONhHh3o9dGp39sX/9Zfmt476UnhvU0UhXgJnXXAikt/MpN6AuSLCCMdEQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.0.0" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "pnyXV1LFOsYjGveuC07xp0YHIyGq7jRq5Ncb5zrrIieMLWVwgMyYxcOH0jTnBedDT4Gh1QinSqsjqzcieHk1og==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "V4Dth2cYMZpw3HhGw9XUDIijpI6gN+22LDt0AhufIgOppCUfpWX4483OmN+dFXRJkJLc8Tv0Q8QK+1ingT2+KQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GJGery6QytCzS/BxJ96klgG9in3uH26KcUBbiVG/coNDXCRq6LGVVlUT4vXq34KPuM+R2av+LeYdX9h4IZOCUg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "Fy8yr4V6obi7ZxvKYI1i85jqtwMq8tqyxQVZpRSkgeA8enqy/KvBIMdcuNdznlxQMZa72mvbHqb7vbg4Pyx95w==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "vWXPg3HJQIpZkENn1KWq8SfbqVujVD7S7vIAyFXXqK5xkf1Vho+vG0bLBCHxU36lD1cLLtmGpfYf0B3MYFi9tQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.DependencyModel": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "TD5QHg98m3+QhgEV1YVoNMl5KtBw/4rjfxLHO0e/YV9bPUBDKntApP4xdrVtGgCeQZHVfC2EXIGsdpRNrr87Pg==", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "3.1.8", + "contentHash": "7ZJUKwPipkDvuv2KJPZ3r01wp2AWNMiYH+61i0dL89F7QICknjKpWgLKLpTSUYFgl77S3b4264I6i4HzDdrb2A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.8", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.FileProviders.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "15+pa2G0bAMHbHewaQIdr/y6ag2H3yh4rd9hTXavtWDzQBkvpe2RMqFg8BxDpcQWssmjmBApGPcw93QRz6YcMg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Core": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "8vBsyGkA8ZI3lZvm1nf+9ynRC/TzPD+UtbdgTlKk+cz+AW5I41LrK8f/adGej5uXgprOA2DMjZw33vZG6vyXxA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Stores": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "linRCnWBfnqg8qjrd9u/KMISy8O4a6X/GRhpHXU0ar654YQw9LJ/Ht+psx8QLqSX5EsCBbBCZzuamatH2FWIyQ==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Identity.Core": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y/lGICwO27fCkQRK3tZseVzFjZaxfGmui990E67sB4MuiPzdJHnJDS/BeYWrHShSSBgCl4KyKRx4ux686fftPg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.0.0", + "Microsoft.Extensions.Options": "2.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Identity.Client": { + "type": "Transitive", + "resolved": "4.45.0", + "contentHash": "ircobISCLWbtE5eEoLKU+ldfZ8O41vg4lcy38KRj/znH17jvBiAl8oxcyNp89CsuqE3onxIpn21Ca7riyDDrRw==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.18.0" + } + }, + "Microsoft.Identity.Client.Extensions.Msal": { + "type": "Transitive", + "resolved": "2.19.3", + "contentHash": "zVVZjn8aW7W79rC1crioDgdOwaFTQorsSO6RgVlDDjc7MvbEGz071wSNrjVhzR0CdQn6Sefx7Abf1o7vasmrLg==", + "dependencies": { + "Microsoft.Identity.Client": "4.38.0", + "System.Security.Cryptography.ProtectedData": "4.5.0" + } + }, + "Microsoft.IdentityModel.Abstractions": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "XeE6LQtD719Qs2IG7HDi1TSw9LIkDbJ33xFiOBoHbApVw/8GpIBCbW+t7RwOjErUDyXZvjhZliwRkkLb8Z1uzg==" + }, + "Microsoft.IdentityModel.Clients.ActiveDirectory": { + "type": "Transitive", + "resolved": "3.14.2", + "contentHash": "TNsJJMiRnkeby1ovThVoV9yFsPWjAdluwOA+Nf0LtSsBVVrKQv8Qp4kYOgyNwMVj+pDwbhXISySk+4HyHVWNZQ==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "System.Runtime.Serialization.Json": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.IdentityModel.JsonWebTokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "d3h1/BaMeylKTkdP6XwRCxuOoDJZ44V9xaXr6gl5QxmpnZGdoK3bySo3OQN8ehRLJHShb94ElLUvoXyglQtgAw==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "tuEhHIQwvBEhMf8I50hy8FHmRSUkffDFP5EdLsSDV4qRcl2wvOPkQxYqEzWkh+ytW6sbdJGEXElGhmhDfAxAKg==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "0FqY5cTLQKtHrClzHEI+QxJl8OBT2vUiEQQB7UKk832JDiJJmetzYZ3AdSrPjN/3l3nkhByeWzXnhrX0JbifKg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "vtSKL7n6EnAsLyxmiviusm6LKrblT2ndnNqN6rvVq6iIHAnPCK9E2DkDx6h1Jrpy1cvbp40r0cnTg23nhEAGTA==", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "6.21.0", + "System.IdentityModel.Tokens.Jwt": "6.21.0" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "AAEHZvZyb597a+QJSmtxH3n2P1nIJGpZ4Q89GTenknRx6T6zyfzf592yW/jA5e8EHN4tNMjjXHQaYWEq5+L05w==", + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "Microsoft.IdentityModel.Logging": "6.21.0", + "System.Security.Cryptography.Cng": "4.5.0" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.OData.Core": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "/EjnJezMBjXf8OjcShhGzPY7pOO0CopgoZGhS6xsP3t2uhC+O72IBHgtQ7F3v1rRXWVtJwLGhzE1GfJUlx3c4Q==", + "dependencies": { + "Microsoft.OData.Edm": "[7.6.4]", + "Microsoft.Spatial": "[7.6.4]" + } + }, + "Microsoft.OData.Edm": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "MSSmA6kIfpgFTtNpOnnayoSj/6KSzHC1U9KOjF7cTA1PG4tZ7rIMi1pvjFc8CmYEvP4cxGl/+vrCn+HpK26HTQ==" + }, + "Microsoft.Spatial": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "3mB+Frn4LU4yb5ie9R752QiRn0Hvp9PITkSRofV/Lzm9EyLM87Fy9ziqgz75O/c712dh6GxuypMSBUGmNFwMeA==" + }, + "Microsoft.SqlServer.Server": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug==" + }, + "Microsoft.VisualStudio.Web.CodeGeneration": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "YUah81QG5q/ViVbr1BZcTbDLNJ5/k84fr+xx3/IoDVJR8KEUm89HmPAGM+FMMyWOjit+CIVpyOq7yEmRBBWXxQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore": "5.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Contracts": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "34v6AkkRJykgFq7rHwNbzXBsLFquevLuegM9XDQl2j+wyOfj+ql1++jUR1WdZoPkv04WoM09mD47S3lMzJmHrQ==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "System.Collections.Immutable": "1.7.0" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Core": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "R7mrxvTtv/MiEH42OtHYi/3L0A/vaAH8mwg+3yAyQtVuy6v9CeeVyL30lfTQ7EYV4ezUmuQKFwfjcU6PP0/KSQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.VisualStudio.Web.CodeGeneration.Templating": "5.0.2", + "Newtonsoft.Json": "11.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "f9XeBRS9ICosrCpbO9jnAVMd/ISLhaZgx388XNBjigiyBJuq577J6tQgQWZA8PQTiPj6MKe9HVIW2GnKXDiUrQ==", + "dependencies": { + "Microsoft.VisualStudio.Web.CodeGeneration.Core": "5.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Templating": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "P3z/JZTGP5DhSc8ik4xrimWuCZ2ZaEZ6q7WGgfgmSVibfXxwh2Oo+dtdkiXwq8MNlkrcP0AZAo3+1wowYUzluA==", + "dependencies": { + "Microsoft.AspNetCore.Razor.Language": "5.0.0", + "Microsoft.AspNetCore.Razor.Runtime": "2.2.0", + "Microsoft.CodeAnalysis.CSharp": "3.8.0", + "Microsoft.CodeAnalysis.Razor": "5.0.0", + "Microsoft.VisualStudio.Web.CodeGeneration.Utils": "5.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Utils": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "4zViWGIFeKsGxDmc5xpn2G8kWs2FSHiLOolw85ZPHihDXc2jiFKp7qjA3SRt8U23kR3zeb0vZiFlETxgTHwAUA==", + "dependencies": { + "Microsoft.CodeAnalysis.CSharp.Workspaces": "3.8.0", + "Microsoft.VisualStudio.Web.CodeGeneration.Contracts": "5.0.2", + "Newtonsoft.Json": "11.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGenerators.Mvc": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "W4Uk2y0oja+4E+XP5d5OFu+ViTEtlqm3a6nYuuC3tjA+lTK6dLaMf0G6WnO4BO18i0kM0l49XjTwwXd5XpjnAQ==", + "dependencies": { + "Microsoft.VisualStudio.Web.CodeGeneration": "5.0.2" + } + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "Microsoft.Win32.Registry": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "Microsoft.Win32.SystemEvents": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==" + }, + "MimeKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "l9YHMBhBUwY7qQHUp8fw0EvjcbmhN4Iggz6MdjqIShBf42+0nJTa5gu0kuupCOPuiARc9ZaS9c9f0gKz4OnxKw==", + "dependencies": { + "Portable.BouncyCastle": "1.9.0", + "System.Security.Cryptography.Pkcs": "6.0.0" + } + }, + "MySqlConnector": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "JVokQTUNN3WHAu9Vw8ieeq1dXTFokJiig5P0VJ4f439UxRrsPo6SaVWC8Zdm6mkPeQFhZ0/9afdWa02EY/1j/w==" + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "Npgsql": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "wKa8MJEJaj0xQXUQZGv7q/KfPID23jSSvFFtljMworrv7dNajr0GN8PCU1SpywqHjMWdYEfK29DY1aYbiISbQg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Npgsql.EntityFrameworkCore.PostgreSQL": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "YJRpO+3wXQyWuwRUCVJj/Rsn46sY0bZ6uCGOEFApiRe0ZYJ6N6TxZUWKbTNJYjesickcLGzynOerpSbDJX1AYg==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Npgsql": "6.0.8" + } + }, + "NSec.Cryptography": { + "type": "Transitive", + "resolved": "22.4.0", + "contentHash": "lEntcPYd7h3aZ8xxi/y/4TML7o8w0GEGqd+w4L1omqFLbdCBmhxJAeO2YBmv/fXbJKgKCQLm7+TD4bR605PEUQ==", + "dependencies": { + "libsodium": "[1.0.18.2, 1.0.19)" + } + }, + "Otp.NET": { + "type": "Transitive", + "resolved": "1.2.2", + "contentHash": "2hrZfkbzeWJ3tNXXt/1beg4IY+nS4F3gIfh4NVFvW0f6Pj51hGpiJ4prBz7Dmrr4ZYrA96rTERVGieZ4xYm7jA==" + }, + "Pipelines.Sockets.Unofficial": { + "type": "Transitive", + "resolved": "2.2.2", + "contentHash": "Bhk0FWxH1paI+18zr1g5cTL+ebeuDcBCR+rRFO+fKEhretgjs7MF2Mc1P64FGLecWp4zKCUOPzngBNrqVyY7Zg==", + "dependencies": { + "System.IO.Pipelines": "5.0.1" + } + }, + "Pomelo.EntityFrameworkCore.MySql": { + "type": "Transitive", + "resolved": "6.0.2", + "contentHash": "KvlZ800CnEuEGnxj5OT1fCKGjQXxW5kpPlCP91JqBYG+2Z3927eqXmlX6LLKUt4swqE8ZsEQ+Zkpab8bqstf4g==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "[6.0.7, 7.0.0)", + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "MySqlConnector": "2.1.2" + } + }, + "Portable.BouncyCastle": { + "type": "Transitive", + "resolved": "1.9.0", + "contentHash": "eZZBCABzVOek+id9Xy04HhmgykF0wZg9wpByzrWN7q8qEI0Qen9b7tfd7w8VA3dOeesumMG7C5ZPy0jk7PSRHw==" + }, + "Quartz": { + "type": "Transitive", + "resolved": "3.4.0", + "contentHash": "N8350OAlQhd8zKg0ARFikGjh3bfAW/CF/KVxu2fTIlAALB/oC1eg54n/QAPYR5ryHuYyDr5G8/Qa4k+D/7OFRQ==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" + }, + "SendGrid": { + "type": "Transitive", + "resolved": "9.27.0", + "contentHash": "kMyXRQ8hmN2bG3tYZ7T31Ufl1kXkpuP5+WBh1BJ32WY31DTnBTCVGURoIqfbTo/tRuQfAYLxra6C8cQGN6kk+A==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "starkbank-ecdsa": "[1.3.3, 2.0.0)" + } + }, + "Sentry": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "Pkw4+51EDUQ0X02jdCZIpaM2Q4UO06VKGDE+dYYNxgvOirRXGKTKxRk4NPKJTLSTNl+2JyT9HoE7C6BTlYhLOw==" + }, + "Sentry.Serilog": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "GFTVfQdOFqZ9Vmo8EEZTx1EQMDRJjka/4v2CwxnAUh+sqHDICga4eOm4AyGzDBbE4s9iAHMgMUCceIqo+7z84w==", + "dependencies": { + "Sentry": "3.16.0", + "Serilog": "2.10.0" + } + }, + "Serilog": { + "type": "Transitive", + "resolved": "2.10.0", + "contentHash": "+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA==" + }, + "Serilog.AspNetCore": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "/JO/txIxRR61x1UXQAgUzG2Sx05o1QHCkokVBWrKzmAoDu+p5EtCAj7L/TVVg7Ezhh3GPiZ0JI9OJCmRO9tSRw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.Extensions.Logging": "5.0.0", + "Serilog": "2.10.0", + "Serilog.Extensions.Hosting": "4.2.0", + "Serilog.Formatting.Compact": "1.1.0", + "Serilog.Settings.Configuration": "3.3.0", + "Serilog.Sinks.Console": "4.0.1", + "Serilog.Sinks.Debug": "2.0.0", + "Serilog.Sinks.File": "5.0.0" + } + }, + "Serilog.Extensions.Hosting": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "gT2keceCmPQR9EX0VpXQZvUgELdfE7yqJ7MOxBhm3WLCblcvRgswEOOTgok/DHObbM15A3V/DtF3VdVDQPIZzQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.Hosting.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8", + "Serilog": "2.10.0", + "Serilog.Extensions.Logging": "3.1.0" + } + }, + "Serilog.Extensions.Logging": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "IWfem7wfrFbB3iw1OikqPFNPEzfayvDuN4WP7Ue1AVFskalMByeWk3QbtUXQR34SBkv1EbZ3AySHda/ErDgpcg==", + "dependencies": { + "Microsoft.Extensions.Logging": "2.0.0", + "Serilog": "2.9.0" + } + }, + "Serilog.Extensions.Logging.File": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "usO0qr4v9VCMBWiTJ1nQmAbPNCt40FrkDol6CpfCXbsxGZS/hH+YCueF7vvPQ32ATI0GWcMWiKRdjXEE7/HxTQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Serilog": "2.5.0", + "Serilog.Extensions.Logging": "2.0.2", + "Serilog.Formatting.Compact": "1.0.0", + "Serilog.Sinks.Async": "1.1.0", + "Serilog.Sinks.RollingFile": "3.3.0" + } + }, + "Serilog.Formatting.Compact": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "pNroKVjo+rDqlxNG5PXkRLpfSCuDOBY0ri6jp9PLe505ljqwhwZz8ospy2vWhQlFu5GkIesh3FcDs4n7sWZODA==", + "dependencies": { + "Serilog": "2.8.0" + } + }, + "Serilog.Settings.Configuration": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "7GNudISZwqaT902hqEL2OFGTZeUFWfnrNLupJkOqeF41AR3GjcxX+Hwb30xb8gG2/CDXsCMVfF8o0+8KY0fJNg==", + "dependencies": { + "Microsoft.Extensions.DependencyModel": "3.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "2.0.0", + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Async": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "xll0Kanz2BkCxuv+F3p1WXr47jdsVM0GU1n1LZvK+18QiRZ/WGFNxSNw9EMKFV5ED5gr7MUpAe6PCMNL1HGUMA==", + "dependencies": { + "Serilog": "2.1.0", + "System.Collections.Concurrent": "4.0.12" + } + }, + "Serilog.Sinks.AzureCosmosDB": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Im2/ZqjXQIpsd727qEo5Pq+br0MiNVuTvI40Yk7736tgjCpEx+omPHv4+c4fEAxnOP2kL9Ge6UoDFoDw3cjF2A==", + "dependencies": { + "Microsoft.Azure.Cosmos": "3.24.0", + "Microsoft.CSharp": "4.7.0", + "Newtonsoft.Json": "13.0.1", + "Serilog": "2.10.0", + "Serilog.Sinks.PeriodicBatching": "2.3.1" + } + }, + "Serilog.Sinks.Console": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Debug": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y6g3OBJ4JzTyyw16fDqtFcQ41qQAydnEvEqmXjhwhgjsnG/FaJ8GUqF5ldsC/bVkK8KYmqrPhDO+tm4dF6xx4A==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.File": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.PeriodicBatching": { + "type": "Transitive", + "resolved": "2.3.1", + "contentHash": "LVYvqpqjSTD8dhfxRnzpxTs8/ys3V2q01MvaY3r0eKsDgpKK1U1y/5N6gFHgiesbxG0V+O5IWdz4+c1DzoNyOQ==", + "dependencies": { + "Serilog": "2.0.0" + } + }, + "Serilog.Sinks.RollingFile": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "2lT5X1r3GH4P0bRWJfhA7etGl8Q2Ipw9AACvtAHWRUSpYZ42NGVyHoVs2ALBZ/cAkkS+tA4jl80Zie144eLQPg==", + "dependencies": { + "Serilog.Sinks.File": "3.2.0", + "System.IO": "4.1.0", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Serilog.Sinks.SyslogMessages": { + "type": "Transitive", + "resolved": "2.0.6", + "contentHash": "V2Yq2GEbk7taEPbpBLFzLXhrHrUzKf4sQu/zLrANU8XIoUn/Mr08M2E8PrcrWVXCj0R4xLMWYe0Z1sxOrMF3IA==", + "dependencies": { + "Serilog": "2.5.0", + "Serilog.Sinks.PeriodicBatching": "2.3.0" + } + }, + "SQLitePCLRaw.bundle_e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "ilkvNhrTersLmIVAcDwwPqfhUFCg19Z1GVMvCSi3xk6Akq94f4qadLORQCq/T8+9JgMiPs+F/NECw5uauviaNw==", + "dependencies": { + "SQLitePCLRaw.lib.e_sqlite3": "2.1.2", + "SQLitePCLRaw.provider.e_sqlite3": "2.1.2" + } + }, + "SQLitePCLRaw.core": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "A8EBepVqY2lnAp3a8jnhbgzF2tlj2S3HcJQGANTYg/TbYbKa8Z5cM1h74An/vy0svhfzT7tVY0sFmUglLgv+2g==", + "dependencies": { + "System.Memory": "4.5.3" + } + }, + "SQLitePCLRaw.lib.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "zibGtku8M4Eea1R3ZCAxc86QbNvyEN17mAcQkvWKBuHvRpMiK2g5anG4R5Be7cWKSd1i6baYz8y4dMMAKcXKPg==" + }, + "SQLitePCLRaw.provider.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "lxCZarZdvAsMl2zw9bXHrXK6RxVhB4b23iTFhCOdHFhxfbsxLxWf+ocvswJwR/9Wh/E//ddMi+wJGqUKV7VwoA==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "StackExchange.Redis": { + "type": "Transitive", + "resolved": "2.5.43", + "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "dependencies": { + "Pipelines.Sockets.Unofficial": "2.2.2", + "System.Diagnostics.PerformanceCounter": "5.0.0" + } + }, + "starkbank-ecdsa": { + "type": "Transitive", + "resolved": "1.3.3", + "contentHash": "OblOaKb1enXn+dSp7tsx9yjwV+/BEKM9jFhshIkZTwCk7LuTFTp+wSon6rFzuPiIiTGtvVWQNUw2slHjGktJog==" + }, + "Stripe.net": { + "type": "Transitive", + "resolved": "40.0.0", + "contentHash": "SD1bGiF+sVQG3p2LXNTZ5rEG2aCnXIHokcxYS9yyW3dR01J0ryf+iNFOwid148yePZ0gCBcRxj3wiW1mTmP7UQ==", + "dependencies": { + "Newtonsoft.Json": "12.0.3", + "System.Configuration.ConfigurationManager": "6.0.0" + } + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Collections.NonGeneric": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "hMxFT2RhhlffyCdKLDXjx8WEC5JfCvNozAZxCablAuFRH74SCV4AgzE8yJCh/73bFnEoZgJ9MJmkjQ0dJmnKqA==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Collections.Specialized": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "/HKQyVP0yH1I0YtK7KJL/28snxHNH/bi+0lgk/+MbURF6ULhAE31MDI+NZDerNWu264YbxklXCCygISgm+HMug==", + "dependencies": { + "System.Collections.NonGeneric": "4.0.1", + "System.Globalization": "4.0.11", + "System.Globalization.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Composition": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "I+D26qpYdoklyAVUdqwUBrEIckMNjAYnuPJy/h9dsQItpQwVREkDFs4b4tkBza0kT2Yk48Lcfsv2QQ9hWsh9Iw==", + "dependencies": { + "System.Composition.AttributedModel": "1.0.31", + "System.Composition.Convention": "1.0.31", + "System.Composition.Hosting": "1.0.31", + "System.Composition.Runtime": "1.0.31", + "System.Composition.TypedParts": "1.0.31" + } + }, + "System.Composition.AttributedModel": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "NHWhkM3ZkspmA0XJEsKdtTt1ViDYuojgSND3yHhTzwxepiwqZf+BCWuvCbjUt4fe0NxxQhUDGJ5km6sLjo9qnQ==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Composition.Convention": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "GLjh2Ju71k6C0qxMMtl4efHa68NmWeIUYh4fkUI8xbjQrEBvFmRwMDFcylT8/PR9SQbeeL48IkFxU/+gd0nYEQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Composition.AttributedModel": "1.0.31", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Composition.Hosting": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "fN1bT4RX4vUqjbgoyuJFVUizAl2mYF5VAb+bVIxIYZSSc0BdnX+yGAxcavxJuDDCQ1K+/mdpgyEFc8e9ikjvrg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Composition.Runtime": "1.0.31", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Composition.Runtime": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "0LEJN+2NVM89CE4SekDrrk5tHV5LeATltkp+9WNYrR+Huiyt0vaCqHbbHtVAjPyeLWIc8dOz/3kthRBj32wGQg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Composition.TypedParts": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "0Zae/FtzeFgDBBuILeIbC/T9HMYbW4olAmi8XqqAGosSOWvXfiQLfARZEhiGd0LVXaYgXr0NhxiU1LldRP1fpQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Composition.AttributedModel": "1.0.31", + "System.Composition.Hosting": "1.0.31", + "System.Composition.Runtime": "1.0.31", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "6.0.0", + "System.Security.Permissions": "6.0.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Diagnostics.PerformanceCounter": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "kcQWWtGVC3MWMNXdMDWfrmIlFZZ2OdoeT6pSNVRtk9+Sa7jwdPiMlNwb0ZQcS7NRlT92pCfmjRtkSWUW3RAKwg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.Diagnostics.Process": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "J0wOX07+QASQblsfxmIMFc9Iq7KTXYL3zs2G/Xc704Ylv3NpuVdo6gij6V3PGiptTxqsK0K7CdXenRvKUnkA2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "Microsoft.Win32.Registry": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.TraceSource": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "6WVCczFZKXwpWpzd/iJkYnsmWTSFFiU24Xx/YdHXBcu+nFI/ehTgeqdJQFbtRPzbrO3KtRNjvkhtj4t5/WwWsA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Drawing.Common": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + } + }, + "System.Dynamic.Runtime": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "db34f6LHYM0U0JpE+sOmjar27BnqTVkbLJhgfwMpTdgTigG/Hna3m2MYVwnFzGGKnEJk2UXFuoVTr8WUbU91/A==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Formats.Asn1": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==" + }, + "System.Formats.Cbor": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "mGaLOoiw7KurJagOOcIsWUoCT5ACIiGxKlCcbYQASefBGXjnCcKTq5Hdjb94eEAKg38zXKlHw4c6EjzgBl9dIw==" + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IdentityModel.Tokens.Jwt": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "JRD8AuypBE+2zYxT3dMJomQVsPYsCqlyZhWel3J1d5nzQokSRyTueF+Q4ID3Jcu6zSZKuzOdJ1MLTkbQsDqcvQ==", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Rfm2jYCaUeGysFEZjDe7j1R4x6Z6BzumS/vUT5a1AA/AWJuGX71PoGB0RmpyX3VmrGqVnAwtfMn39OHR8Y/5+g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "qEePWsaq9LoEEIqhbGe6D5J8c9IqQOUuTzzV6wn1POlfdLkJliZY3OlB0j0f17uMWlqZYjH7txj+2YbyrIA8Yg==" + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Linq.Queryable": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "Yn/WfYe9RoRfmSLvUt2JerP0BTGGykCZkQPgojaxgzF2N0oPo+/AhB8TXOpdCcNlrG3VRtsamtK2uzsp3cqRVw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==", + "dependencies": { + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.6.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.4", + "contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.1", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.NameResolution": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "JdqRdM1Qym3YehqdKIi5LHrpypP4JMfxKQSNCJ2z4WawkG0il+N3XfNeJOxll2XrTnG7WgYYPoeiu/KOwg0DQw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.NetworkInformation": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "Q0rfeiW6QsiZuicGjrFA7cRr2+kXex0JIljTTxzI09GIftB8k+aNL31VsQD1sI2g31cw7UGDTgozA/FgeNSzsQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Linq": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.Sockets": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Overlapped": "4.0.1", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Requests": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "vxGt7C0cZixN+VqoSW4Yakc1Y9WknmxauDqzxgpw/FnBdz4kQNN51l4wxdXX5VY1xjqy//+G+4CvJWp1+f+y6Q==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Net.Http": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Claims": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Security.Principal": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Security": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Net.WebHeaderCollection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "XX2TIAN+wBSAIV51BU2FvvXMdstUa8b0FBSZmDWjZdwUMmggQSifpTOZ5fNH20z9ZCg2fkV1L5SsZnpO2RQDRQ==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0" + } + }, + "System.Net.WebSockets": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", + "dependencies": { + "Microsoft.Win32.Primitives": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.WebSockets.Client": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "NUCcDroX4lCQXgOrzlwIZ1u9YJ0krfyF0wk0ONnyLUmcQoEiYV2/OfUPRqUwQBbpH1BlGApkLgoQUwMqb5+c1g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.2", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Net.WebSockets": "4.0.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.X509Certificates": "4.1.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Numerics.Vectors": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Private.DataContractSerialization": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "lcqFBUaCZxPiUkA4dlSOoPZGtZsAuuElH2XHgLwGLxd7ZozWetV5yiz0qGAV2AUYOqw97MtZBjbLMN16Xz4vXA==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Collections.Concurrent": "4.0.12", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Emit.Lightweight": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1", + "System.Xml.XmlSerializer": "4.0.11" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Caching": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "30D6MkO8WF9jVGWZIP0hmCN8l9BTY4LCsAzLIe4xFSXzs+AjDotR7DpSmj27pFskDURzUvqYYY0ikModgBTxWw==", + "dependencies": { + "System.Configuration.ConfigurationManager": "5.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Runtime.Serialization.Json": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "+7DIJhnKYgCzUgcLbVTtRQb2l1M0FP549XFlFkQM5lmNiUBl44AfNbx4bz61xA8PzLtlYwfmif4JJJW7MPPnjg==", + "dependencies": { + "System.IO": "4.1.0", + "System.Private.DataContractSerialization": "4.1.1", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" + }, + "System.Security.Claims": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Security.Principal": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==", + "dependencies": { + "System.Formats.Asn1": "5.0.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Pkcs": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "elM3x+xSRhzQysiqo85SbidJJ2YbZlnvmh+53TuSZHsD7dNuuEWser+9EFtY+rYupBwkq2avc6ZCO3/6qACgmg==", + "dependencies": { + "System.Formats.Asn1": "6.0.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ==" + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Xml": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "i2Jn6rGXR63J0zIklImGRkDIJL4b1NfPSEbIVHBlqoIb12lfXIigCbDRpDmIEzwSo/v1U5y/rYJdzZYSyCWxvg==", + "dependencies": { + "System.Security.Cryptography.Pkcs": "4.5.0", + "System.Security.Permissions": "4.5.0" + } + }, + "System.Security.Permissions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==", + "dependencies": { + "System.Security.AccessControl": "6.0.0", + "System.Windows.Extensions": "6.0.0" + } + }, + "System.Security.Principal": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, + "System.Security.SecureString": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "sqzq9GD6/b0yqPuMpgIKBuoLf4VKAj8oAfh4kXSzPaN6eoKY3hRi9C5L27uip25qlU+BGPfb0xh2Rmbwc4jFVA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "NyscU59xX6Uo91qvhOs2Ccho3AR2TnZPomo1Z0K6YpyztBPM/A5VbkzOO19sy3A3i1TtEnTxA7bCe3Us+r5MWg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "zaJsHfESQvJ11vbXnNlkrR46IaMULk/gHxYsJphzSF+07kTjPHv+Oc14w6QEOfo3Q4hqLJgStUaYB9DBl0TmWg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Overlapped": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "f7aLuLkBoCQM2kng7zqLFBXz9Gk48gDK8lk1ih9rH/1arJJzZK9gJwNvPDhL6Ps/l6rwOr8jw+4FCHL0KKWiEg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Threading.Thread": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OHmbT+Zz065NKII/ZHcH9XO1dEuLGI1L2k7uYss+9C1jLxTC9kTZZuzUOyXHayRk+dft9CiDf3I/QZ0t8JKyBQ==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading.ThreadPool": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.ValueTuple": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" + }, + "System.Windows.Extensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==", + "dependencies": { + "System.Drawing.Common": "6.0.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "lJ8AxvkX7GQxpC6GFCeBj8ThYVyQczx2+f/cWHJU8tjS7YfI6Cv6bon70jVEgs2CiFbmmM8b9j1oZVx0dSI2Ww==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlSerializer": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "FrazwwqfIXTfq23mfv4zH+BjqkSFNaNFBtjzu3I9NRmG8EELYyrv/fJnttCIwRMFRR/YKXF1hmsMmMEnl55HGw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1" + } + }, + "System.Xml.XPath": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "v1JQ5SETnQusqmS3RwStF7vwQ3L02imIzl++sewmt23VGygix04pEH+FCj1yWb+z4GDzKiljr1W7Wfvrx0YwgA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XPath.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "A/uxsWi/Ifzkmd4ArTLISMbfFs6XpRPsXZonrIqyTY70xi8t+mDtvSM5Os0RqyRDobjMBwIDHDL4NOIbkDwf7A==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XPath": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "YubicoDotNetClient": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "uP5F3Ko1gqZi3lwS2R/jAAwhBxXs/6PKDpS6FdQjsBA5qmF0hQmbtfxM6QHTXOMoWbUtfetG7+LtgmG8T5zDIg==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "core": { + "type": "Project", + "dependencies": { + "AWSSDK.SQS": "[3.7.2.47, )", + "AWSSDK.SimpleEmail": "[3.7.0.150, )", + "AspNetCoreRateLimit": "[4.0.2, )", + "AspNetCoreRateLimit.Redis": "[1.0.1, )", + "Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.2.1, )", + "Azure.Storage.Blobs": "[12.11.0, )", + "Azure.Storage.Queues": "[12.9.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "Fido2.AspNet": "[3.0.1, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "MailKit": "[3.2.0, )", + "Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )", + "Microsoft.Azure.Cosmos.Table": "[1.0.8, )", + "Microsoft.Azure.NotificationHubs": "[4.1.0, )", + "Microsoft.Azure.ServiceBus": "[5.2.0, )", + "Microsoft.Data.SqlClient": "[5.0.1, )", + "Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )", + "Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )", + "Microsoft.Extensions.Identity.Stores": "[6.0.4, )", + "Newtonsoft.Json": "[13.0.1, )", + "Otp.NET": "[1.2.2, )", + "Quartz": "[3.4.0, )", + "SendGrid": "[9.27.0, )", + "Sentry.Serilog": "[3.16.0, )", + "Serilog.AspNetCore": "[5.0.0, )", + "Serilog.Extensions.Logging": "[3.1.0, )", + "Serilog.Extensions.Logging.File": "[2.0.0, )", + "Serilog.Sinks.AzureCosmosDB": "[2.0.0, )", + "Serilog.Sinks.SyslogMessages": "[2.0.6, )", + "Stripe.net": "[40.0.0, )", + "YubicoDotNetClient": "[1.2.0, )" + } + }, + "infrastructure.dapper": { + "type": "Project", + "dependencies": { + "Core": "[2023.1.0, )", + "Dapper": "[2.0.123, )" + } + }, + "infrastructure.entityframework": { + "type": "Project", + "dependencies": { + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", + "Core": "[2023.1.0, )", + "Microsoft.EntityFrameworkCore.Relational": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.SqlServer": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.Sqlite": "[6.0.12, )", + "Npgsql.EntityFrameworkCore.PostgreSQL": "[6.0.8, )", + "Pomelo.EntityFrameworkCore.MySql": "[6.0.2, )", + "linq2db.EntityFrameworkCore": "[6.11.0, )" + } + }, + "sharedweb": { + "type": "Project", + "dependencies": { + "Core": "[2023.1.0, )", + "Infrastructure.Dapper": "[2023.1.0, )", + "Infrastructure.EntityFramework": "[2023.1.0, )" + } + } + } + } +} \ No newline at end of file diff --git a/bitwarden_license/src/Sso/Controllers/AccountController.cs b/bitwarden_license/src/Sso/Controllers/AccountController.cs index 3ef99f0fa..fdbcf0f0d 100644 --- a/bitwarden_license/src/Sso/Controllers/AccountController.cs +++ b/bitwarden_license/src/Sso/Controllers/AccountController.cs @@ -1,8 +1,16 @@ -using Bit.Core; +using System.Security.Claims; +using Bit.Core; +using Bit.Core.Entities; using Bit.Core.Enums; -using Bit.Core.Models.Table; +using Bit.Core.Models; +using Bit.Core.Models.Api; +using Bit.Core.Models.Business.Tokenables; +using Bit.Core.Models.Data; using Bit.Core.Repositories; using Bit.Core.Services; +using Bit.Core.Settings; +using Bit.Core.Tokens; +using Bit.Core.Utilities; using Bit.Sso.Models; using Bit.Sso.Utilities; using IdentityModel; @@ -12,675 +20,690 @@ using IdentityServer4.Services; using IdentityServer4.Stores; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.Logging; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; -using Bit.Core.Models; -using Bit.Core.Models.Api; -using Bit.Core.Utilities; -using System.Text.Json; -using Bit.Core.Models.Data; -using Bit.Core.Settings; -namespace Bit.Sso.Controllers +namespace Bit.Sso.Controllers; + +public class AccountController : Controller { - public class AccountController : Controller + private readonly IAuthenticationSchemeProvider _schemeProvider; + private readonly IClientStore _clientStore; + + private readonly IIdentityServerInteractionService _interaction; + private readonly ILogger _logger; + private readonly IOrganizationRepository _organizationRepository; + private readonly IOrganizationUserRepository _organizationUserRepository; + private readonly IOrganizationService _organizationService; + private readonly ISsoConfigRepository _ssoConfigRepository; + private readonly ISsoUserRepository _ssoUserRepository; + private readonly IUserRepository _userRepository; + private readonly IPolicyRepository _policyRepository; + private readonly IUserService _userService; + private readonly II18nService _i18nService; + private readonly UserManager _userManager; + private readonly IGlobalSettings _globalSettings; + private readonly Core.Services.IEventService _eventService; + private readonly IDataProtectorTokenFactory _dataProtector; + + public AccountController( + IAuthenticationSchemeProvider schemeProvider, + IClientStore clientStore, + IIdentityServerInteractionService interaction, + ILogger logger, + IOrganizationRepository organizationRepository, + IOrganizationUserRepository organizationUserRepository, + IOrganizationService organizationService, + ISsoConfigRepository ssoConfigRepository, + ISsoUserRepository ssoUserRepository, + IUserRepository userRepository, + IPolicyRepository policyRepository, + IUserService userService, + II18nService i18nService, + UserManager userManager, + IGlobalSettings globalSettings, + Core.Services.IEventService eventService, + IDataProtectorTokenFactory dataProtector) { - private readonly IAuthenticationSchemeProvider _schemeProvider; - private readonly IClientStore _clientStore; + _schemeProvider = schemeProvider; + _clientStore = clientStore; + _interaction = interaction; + _logger = logger; + _organizationRepository = organizationRepository; + _organizationUserRepository = organizationUserRepository; + _organizationService = organizationService; + _userRepository = userRepository; + _ssoConfigRepository = ssoConfigRepository; + _ssoUserRepository = ssoUserRepository; + _policyRepository = policyRepository; + _userService = userService; + _i18nService = i18nService; + _userManager = userManager; + _eventService = eventService; + _globalSettings = globalSettings; + _dataProtector = dataProtector; + } - private readonly IIdentityServerInteractionService _interaction; - private readonly ILogger _logger; - private readonly IOrganizationRepository _organizationRepository; - private readonly IOrganizationUserRepository _organizationUserRepository; - private readonly IOrganizationService _organizationService; - private readonly ISsoConfigRepository _ssoConfigRepository; - private readonly ISsoUserRepository _ssoUserRepository; - private readonly IUserRepository _userRepository; - private readonly IPolicyRepository _policyRepository; - private readonly IUserService _userService; - private readonly II18nService _i18nService; - private readonly UserManager _userManager; - private readonly IGlobalSettings _globalSettings; - private readonly Core.Services.IEventService _eventService; - - public AccountController( - IAuthenticationSchemeProvider schemeProvider, - IClientStore clientStore, - IIdentityServerInteractionService interaction, - ILogger logger, - IOrganizationRepository organizationRepository, - IOrganizationUserRepository organizationUserRepository, - IOrganizationService organizationService, - ISsoConfigRepository ssoConfigRepository, - ISsoUserRepository ssoUserRepository, - IUserRepository userRepository, - IPolicyRepository policyRepository, - IUserService userService, - II18nService i18nService, - UserManager userManager, - IGlobalSettings globalSettings, - Core.Services.IEventService eventService) + [HttpGet] + public async Task PreValidate(string domainHint) + { + try { - _schemeProvider = schemeProvider; - _clientStore = clientStore; - _interaction = interaction; - _logger = logger; - _organizationRepository = organizationRepository; - _organizationUserRepository = organizationUserRepository; - _organizationService = organizationService; - _userRepository = userRepository; - _ssoConfigRepository = ssoConfigRepository; - _ssoUserRepository = ssoUserRepository; - _policyRepository = policyRepository; - _userService = userService; - _i18nService = i18nService; - _userManager = userManager; - _eventService = eventService; - _globalSettings = globalSettings; - } - - [HttpGet] - public async Task PreValidate(string domainHint) - { - IActionResult invalidJson(string errorMessageKey, Exception ex = null) + // Validate domain_hint provided + if (string.IsNullOrWhiteSpace(domainHint)) { - Response.StatusCode = ex == null ? 400 : 500; - return Json(new ErrorResponseModel(_i18nService.T(errorMessageKey)) - { - ExceptionMessage = ex?.Message, - ExceptionStackTrace = ex?.StackTrace, - InnerExceptionMessage = ex?.InnerException?.Message, - }); + return InvalidJson("NoOrganizationIdentifierProvidedError"); } + // Validate organization exists from domain_hint + var organization = await _organizationRepository.GetByIdentifierAsync(domainHint); + if (organization == null) + { + return InvalidJson("OrganizationNotFoundByIdentifierError"); + } + if (!organization.UseSso) + { + return InvalidJson("SsoNotAllowedForOrganizationError"); + } + + // Validate SsoConfig exists and is Enabled + var ssoConfig = await _ssoConfigRepository.GetByIdentifierAsync(domainHint); + if (ssoConfig == null) + { + return InvalidJson("SsoConfigurationNotFoundForOrganizationError"); + } + if (!ssoConfig.Enabled) + { + return InvalidJson("SsoNotEnabledForOrganizationError"); + } + + // Validate Authentication Scheme exists and is loaded (cache) + var scheme = await _schemeProvider.GetSchemeAsync(organization.Id.ToString()); + if (scheme == null || !(scheme is IDynamicAuthenticationScheme dynamicScheme)) + { + return InvalidJson("NoSchemeOrHandlerForSsoConfigurationFoundError"); + } + + // Run scheme validation try { - // Validate domain_hint provided - if (string.IsNullOrWhiteSpace(domainHint)) - { - return invalidJson("NoOrganizationIdentifierProvidedError"); - } - - // Validate organization exists from domain_hint - var organization = await _organizationRepository.GetByIdentifierAsync(domainHint); - if (organization == null) - { - return invalidJson("OrganizationNotFoundByIdentifierError"); - } - if (!organization.UseSso) - { - return invalidJson("SsoNotAllowedForOrganizationError"); - } - - // Validate SsoConfig exists and is Enabled - var ssoConfig = await _ssoConfigRepository.GetByIdentifierAsync(domainHint); - if (ssoConfig == null) - { - return invalidJson("SsoConfigurationNotFoundForOrganizationError"); - } - if (!ssoConfig.Enabled) - { - return invalidJson("SsoNotEnabledForOrganizationError"); - } - - // Validate Authentication Scheme exists and is loaded (cache) - var scheme = await _schemeProvider.GetSchemeAsync(organization.Id.ToString()); - if (scheme == null || !(scheme is IDynamicAuthenticationScheme dynamicScheme)) - { - return invalidJson("NoSchemeOrHandlerForSsoConfigurationFoundError"); - } - - // Run scheme validation - try - { - await dynamicScheme.Validate(); - } - catch (Exception ex) - { - var translatedException = _i18nService.GetLocalizedHtmlString(ex.Message); - var errorKey = "InvalidSchemeConfigurationError"; - if (!translatedException.ResourceNotFound) - { - errorKey = ex.Message; - } - return invalidJson(errorKey, translatedException.ResourceNotFound ? ex : null); - } + await dynamicScheme.Validate(); } catch (Exception ex) { - return invalidJson("PreValidationError", ex); - } - - // Everything is good! - return new EmptyResult(); - } - - [HttpGet] - public async Task Login(string returnUrl) - { - var context = await _interaction.GetAuthorizationContextAsync(returnUrl); - if (context.Parameters.AllKeys.Contains("domain_hint") && - !string.IsNullOrWhiteSpace(context.Parameters["domain_hint"])) - { - return RedirectToAction(nameof(ExternalChallenge), new + var translatedException = _i18nService.GetLocalizedHtmlString(ex.Message); + var errorKey = "InvalidSchemeConfigurationError"; + if (!translatedException.ResourceNotFound) { - scheme = context.Parameters["domain_hint"], - returnUrl, - state = context.Parameters["state"], - userIdentifier = context.Parameters["session_state"] - }); - } - else - { - throw new Exception(_i18nService.T("NoDomainHintProvided")); - } - } - - [HttpGet] - public IActionResult ExternalChallenge(string scheme, string returnUrl, string state, string userIdentifier) - { - if (string.IsNullOrEmpty(returnUrl)) - { - returnUrl = "~/"; - } - - if (!Url.IsLocalUrl(returnUrl) && !_interaction.IsValidReturnUrl(returnUrl)) - { - throw new Exception(_i18nService.T("InvalidReturnUrl")); - } - - var props = new AuthenticationProperties - { - RedirectUri = Url.Action(nameof(ExternalCallback)), - Items = - { - // scheme will get serialized into `State` and returned back - { "scheme", scheme }, - { "return_url", returnUrl }, - { "state", state }, - { "user_identifier", userIdentifier }, + errorKey = ex.Message; } - }; + return InvalidJson(errorKey, translatedException.ResourceNotFound ? ex : null); + } - return Challenge(props, scheme); + var tokenable = new SsoTokenable(organization, _globalSettings.Sso.SsoTokenLifetimeInSeconds); + var token = _dataProtector.Protect(tokenable); + + return new SsoPreValidateResponseModel(token); } - - [HttpGet] - public async Task ExternalCallback() + catch (Exception ex) { - // Read external identity from the temporary cookie - var result = await HttpContext.AuthenticateAsync( - AuthenticationSchemes.BitwardenExternalCookieAuthenticationScheme); - if (result?.Succeeded != true) - { - throw new Exception(_i18nService.T("ExternalAuthenticationError")); - } - - // Debugging - var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}"); - _logger.LogDebug("External claims: {@claims}", externalClaims); - - // Lookup our user and external provider info - var (user, provider, providerUserId, claims, ssoConfigData) = await FindUserFromExternalProviderAsync(result); - if (user == null) - { - // This might be where you might initiate a custom workflow for user registration - // in this sample we don't show how that would be done, as our sample implementation - // simply auto-provisions new external user - var userIdentifier = result.Properties.Items.Keys.Contains("user_identifier") ? - result.Properties.Items["user_identifier"] : null; - user = await AutoProvisionUserAsync(provider, providerUserId, claims, userIdentifier, ssoConfigData); - } - - if (user != null) - { - // This allows us to collect any additional claims or properties - // for the specific protocols used and store them in the local auth cookie. - // this is typically used to store data needed for signout from those protocols. - var additionalLocalClaims = new List(); - var localSignInProps = new AuthenticationProperties - { - IsPersistent = true, - ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(1) - }; - ProcessLoginCallback(result, additionalLocalClaims, localSignInProps); - - // Issue authentication cookie for user - await HttpContext.SignInAsync(new IdentityServerUser(user.Id.ToString()) - { - DisplayName = user.Email, - IdentityProvider = provider, - AdditionalClaims = additionalLocalClaims.ToArray() - }, localSignInProps); - } - - // Delete temporary cookie used during external authentication - await HttpContext.SignOutAsync(AuthenticationSchemes.BitwardenExternalCookieAuthenticationScheme); - - // Retrieve return URL - var returnUrl = result.Properties.Items["return_url"] ?? "~/"; - - // Check if external login is in the context of an OIDC request - var context = await _interaction.GetAuthorizationContextAsync(returnUrl); - if (context != null) - { - if (IsNativeClient(context)) - { - // The client is native, so this change in how to - // return the response is for better UX for the end user. - HttpContext.Response.StatusCode = 200; - HttpContext.Response.Headers["Location"] = string.Empty; - return View("Redirect", new RedirectViewModel { RedirectUrl = returnUrl }); - } - } - - return Redirect(returnUrl); - } - - [HttpGet] - public async Task Logout(string logoutId) - { - // Build a model so the logged out page knows what to display - var (updatedLogoutId, redirectUri, externalAuthenticationScheme) = await GetLoggedOutDataAsync(logoutId); - - if (User?.Identity.IsAuthenticated == true) - { - // Delete local authentication cookie - await HttpContext.SignOutAsync(); - } - - // HACK: Temporary workaroud for the time being that doesn't try to sign out of OneLogin schemes, - // which doesnt support SLO - if (externalAuthenticationScheme != null && !externalAuthenticationScheme.Contains("onelogin")) - { - // Build a return URL so the upstream provider will redirect back - // to us after the user has logged out. this allows us to then - // complete our single sign-out processing. - var url = Url.Action("Logout", new { logoutId = updatedLogoutId }); - - // This triggers a redirect to the external provider for sign-out - return SignOut(new AuthenticationProperties { RedirectUri = url }, externalAuthenticationScheme); - } - if (redirectUri != null) - { - return View("Redirect", new RedirectViewModel { RedirectUrl = redirectUri }); - } - else - { - return Redirect("~/"); - } - } - - private async Task<(User user, string provider, string providerUserId, IEnumerable claims, SsoConfigurationData config)> - FindUserFromExternalProviderAsync(AuthenticateResult result) - { - var provider = result.Properties.Items["scheme"]; - var orgId = new Guid(provider); - var ssoConfig = await _ssoConfigRepository.GetByOrganizationIdAsync(orgId); - if (ssoConfig == null || !ssoConfig.Enabled) - { - throw new Exception(_i18nService.T("OrganizationOrSsoConfigNotFound")); - } - - var ssoConfigData = ssoConfig.GetData(); - var externalUser = result.Principal; - - // Validate acr claim against expectation before going further - if (!string.IsNullOrWhiteSpace(ssoConfigData.ExpectedReturnAcrValue)) - { - var acrClaim = externalUser.FindFirst(JwtClaimTypes.AuthenticationContextClassReference); - if (acrClaim?.Value != ssoConfigData.ExpectedReturnAcrValue) - { - throw new Exception(_i18nService.T("AcrMissingOrInvalid")); - } - } - - // Ensure the NameIdentifier used is not a transient name ID, if so, we need a different attribute - // for the user identifier. - static bool nameIdIsNotTransient(Claim c) => c.Type == ClaimTypes.NameIdentifier - && (c.Properties == null - || !c.Properties.ContainsKey(SamlPropertyKeys.ClaimFormat) - || c.Properties[SamlPropertyKeys.ClaimFormat] != SamlNameIdFormats.Transient); - - // Try to determine the unique id of the external user (issued by the provider) - // the most common claim type for that are the sub claim and the NameIdentifier - // depending on the external provider, some other claim type might be used - var customUserIdClaimTypes = ssoConfigData.GetAdditionalUserIdClaimTypes(); - var userIdClaim = externalUser.FindFirst(c => customUserIdClaimTypes.Contains(c.Type)) ?? - externalUser.FindFirst(JwtClaimTypes.Subject) ?? - externalUser.FindFirst(nameIdIsNotTransient) ?? - // Some SAML providers may use the `uid` attribute for this - // where a transient NameID has been sent in the subject - externalUser.FindFirst("uid") ?? - externalUser.FindFirst("upn") ?? - externalUser.FindFirst("eppn") ?? - throw new Exception(_i18nService.T("UnknownUserId")); - - // Remove the user id claim so we don't include it as an extra claim if/when we provision the user - var claims = externalUser.Claims.ToList(); - claims.Remove(userIdClaim); - - // find external user - var providerUserId = userIdClaim.Value; - - var user = await _userRepository.GetBySsoUserAsync(providerUserId, orgId); - - return (user, provider, providerUserId, claims, ssoConfigData); - } - - private async Task AutoProvisionUserAsync(string provider, string providerUserId, - IEnumerable claims, string userIdentifier, SsoConfigurationData config) - { - var name = GetName(claims, config.GetAdditionalNameClaimTypes()); - var email = GetEmailAddress(claims, config.GetAdditionalEmailClaimTypes()); - if (string.IsNullOrWhiteSpace(email) && providerUserId.Contains("@")) - { - email = providerUserId; - } - - if (!Guid.TryParse(provider, out var orgId)) - { - // TODO: support non-org (server-wide) SSO in the future? - throw new Exception(_i18nService.T("SSOProviderIsNotAnOrgId", provider)); - } - - User existingUser = null; - if (string.IsNullOrWhiteSpace(userIdentifier)) - { - if (string.IsNullOrWhiteSpace(email)) - { - throw new Exception(_i18nService.T("CannotFindEmailClaim")); - } - existingUser = await _userRepository.GetByEmailAsync(email); - } - else - { - var split = userIdentifier.Split(","); - if (split.Length < 2) - { - throw new Exception(_i18nService.T("InvalidUserIdentifier")); - } - var userId = split[0]; - var token = split[1]; - - var tokenOptions = new TokenOptions(); - - var claimedUser = await _userService.GetUserByIdAsync(userId); - if (claimedUser != null) - { - var tokenIsValid = await _userManager.VerifyUserTokenAsync( - claimedUser, tokenOptions.PasswordResetTokenProvider, TokenPurposes.LinkSso, token); - if (tokenIsValid) - { - existingUser = claimedUser; - } - else - { - throw new Exception(_i18nService.T("UserIdAndTokenMismatch")); - } - } - } - - OrganizationUser orgUser = null; - var organization = await _organizationRepository.GetByIdAsync(orgId); - if (organization == null) - { - throw new Exception(_i18nService.T("CouldNotFindOrganization", orgId)); - } - - // Try to find OrgUser via existing User Id (accepted/confirmed user) - if (existingUser != null) - { - var orgUsersByUserId = await _organizationUserRepository.GetManyByUserAsync(existingUser.Id); - orgUser = orgUsersByUserId.SingleOrDefault(u => u.OrganizationId == orgId); - } - - // If no Org User found by Existing User Id - search all organization users via email - orgUser ??= await _organizationUserRepository.GetByOrganizationEmailAsync(orgId, email); - - // All Existing User flows handled below - if (existingUser != null) - { - if (orgUser == null) - { - // Org User is not created - no invite has been sent - throw new Exception(_i18nService.T("UserAlreadyExistsInviteProcess")); - } - - if (orgUser.Status == OrganizationUserStatusType.Invited) - { - // Org User is invited - they must manually accept the invite via email and authenticate with MP - throw new Exception(_i18nService.T("UserAlreadyInvited", email, organization.Name)); - } - - // Delete existing SsoUser (if any) - avoids error if providerId has changed and the sso link is stale - await DeleteExistingSsoUserRecord(existingUser.Id, orgId, orgUser); - - // Accepted or Confirmed - create SSO link and return; - await CreateSsoUserRecord(providerUserId, existingUser.Id, orgId); - return existingUser; - } - - // Before any user creation - if Org User doesn't exist at this point - make sure there are enough seats to add one - if (orgUser == null && organization.Seats.HasValue) - { - var userCount = await _organizationUserRepository.GetCountByOrganizationIdAsync(orgId); - var initialSeatCount = organization.Seats.Value; - var availableSeats = initialSeatCount - userCount; - var prorationDate = DateTime.UtcNow; - if (availableSeats < 1) - { - try - { - if (_globalSettings.SelfHosted) - { - throw new Exception("Cannot autoscale on self-hosted instance."); - } - - await _organizationService.AutoAddSeatsAsync(organization, 1, prorationDate); - } - catch (Exception e) - { - if (organization.Seats.Value != initialSeatCount) - { - await _organizationService.AdjustSeatsAsync(orgId, initialSeatCount - organization.Seats.Value, prorationDate); - } - _logger.LogInformation(e, "SSO auto provisioning failed"); - throw new Exception(_i18nService.T("NoSeatsAvailable", organization.Name)); - } - } - } - - // Create user record - all existing user flows are handled above - var user = new User - { - Name = name, - Email = email, - ApiKey = CoreHelpers.SecureRandomString(30) - }; - await _userService.RegisterUserAsync(user); - - // If the organization has 2fa policy enabled, make sure to default jit user 2fa to email - var twoFactorPolicy = - await _policyRepository.GetByOrganizationIdTypeAsync(orgId, PolicyType.TwoFactorAuthentication); - if (twoFactorPolicy != null && twoFactorPolicy.Enabled) - { - user.SetTwoFactorProviders(new Dictionary - { - [TwoFactorProviderType.Email] = new TwoFactorProvider - { - MetaData = new Dictionary { ["Email"] = user.Email.ToLowerInvariant() }, - Enabled = true - } - }); - await _userService.UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.Email); - } - - // Create Org User if null or else update existing Org User - if (orgUser == null) - { - orgUser = new OrganizationUser - { - OrganizationId = orgId, - UserId = user.Id, - Type = OrganizationUserType.User, - Status = OrganizationUserStatusType.Invited - }; - await _organizationUserRepository.CreateAsync(orgUser); - } - else - { - orgUser.UserId = user.Id; - await _organizationUserRepository.ReplaceAsync(orgUser); - } - - // Delete any stale user record to be safe - await DeleteExistingSsoUserRecord(user.Id, orgId, orgUser); - - // Create sso user record - await CreateSsoUserRecord(providerUserId, user.Id, orgId); - - return user; - } - - private string GetEmailAddress(IEnumerable claims, IEnumerable additionalClaimTypes) - { - var filteredClaims = claims.Where(c => !string.IsNullOrWhiteSpace(c.Value) && c.Value.Contains("@")); - - var email = filteredClaims.GetFirstMatch(additionalClaimTypes.ToArray()) ?? - filteredClaims.GetFirstMatch(JwtClaimTypes.Email, ClaimTypes.Email, - SamlClaimTypes.Email, "mail", "emailaddress"); - if (!string.IsNullOrWhiteSpace(email)) - { - return email; - } - - var username = filteredClaims.GetFirstMatch(JwtClaimTypes.PreferredUserName, - SamlClaimTypes.UserId, "uid"); - if (!string.IsNullOrWhiteSpace(username)) - { - return username; - } - - return null; - } - - private string GetName(IEnumerable claims, IEnumerable additionalClaimTypes) - { - var filteredClaims = claims.Where(c => !string.IsNullOrWhiteSpace(c.Value)); - - var name = filteredClaims.GetFirstMatch(additionalClaimTypes.ToArray()) ?? - filteredClaims.GetFirstMatch(JwtClaimTypes.Name, ClaimTypes.Name, - SamlClaimTypes.DisplayName, SamlClaimTypes.CommonName, "displayname", "cn"); - if (!string.IsNullOrWhiteSpace(name)) - { - return name; - } - - var givenName = filteredClaims.GetFirstMatch(SamlClaimTypes.GivenName, "givenname", "firstname", - "fn", "fname", "nickname"); - var surname = filteredClaims.GetFirstMatch(SamlClaimTypes.Surname, "sn", "surname", "lastname"); - var nameParts = new[] { givenName, surname }.Where(p => !string.IsNullOrWhiteSpace(p)); - if (nameParts.Any()) - { - return string.Join(' ', nameParts); - } - - return null; - } - - private async Task DeleteExistingSsoUserRecord(Guid userId, Guid orgId, OrganizationUser orgUser) - { - var existingSsoUser = await _ssoUserRepository.GetByUserIdOrganizationIdAsync(orgId, userId); - if (existingSsoUser != null) - { - await _ssoUserRepository.DeleteAsync(userId, orgId); - await _eventService.LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_ResetSsoLink); - } - } - - private async Task CreateSsoUserRecord(string providerUserId, Guid userId, Guid orgId) - { - var ssoUser = new SsoUser - { - ExternalId = providerUserId, - UserId = userId, - OrganizationId = orgId, - }; - await _ssoUserRepository.CreateAsync(ssoUser); - } - - private void ProcessLoginCallback(AuthenticateResult externalResult, - List localClaims, AuthenticationProperties localSignInProps) - { - // If the external system sent a session id claim, copy it over - // so we can use it for single sign-out - var sid = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId); - if (sid != null) - { - localClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value)); - } - - // If the external provider issued an idToken, we'll keep it for signout - var idToken = externalResult.Properties.GetTokenValue("id_token"); - if (idToken != null) - { - localSignInProps.StoreTokens( - new[] { new AuthenticationToken { Name = "id_token", Value = idToken } }); - } - } - - private async Task GetProviderAsync(string returnUrl) - { - var context = await _interaction.GetAuthorizationContextAsync(returnUrl); - if (context?.IdP != null && await _schemeProvider.GetSchemeAsync(context.IdP) != null) - { - return context.IdP; - } - var schemes = await _schemeProvider.GetAllSchemesAsync(); - var providers = schemes.Select(x => x.Name).ToList(); - return providers.FirstOrDefault(); - } - - private async Task<(string, string, string)> GetLoggedOutDataAsync(string logoutId) - { - // Get context information (client name, post logout redirect URI and iframe for federated signout) - var logout = await _interaction.GetLogoutContextAsync(logoutId); - string externalAuthenticationScheme = null; - if (User?.Identity.IsAuthenticated == true) - { - var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value; - if (idp != null && idp != IdentityServerConstants.LocalIdentityProvider) - { - var providerSupportsSignout = await HttpContext.GetSchemeSupportsSignOutAsync(idp); - if (providerSupportsSignout) - { - if (logoutId == null) - { - // If there's no current logout context, we need to create one - // this captures necessary info from the current logged in user - // before we signout and redirect away to the external IdP for signout - logoutId = await _interaction.CreateLogoutContextAsync(); - } - - externalAuthenticationScheme = idp; - } - } - } - - return (logoutId, logout?.PostLogoutRedirectUri, externalAuthenticationScheme); - } - - public bool IsNativeClient(IdentityServer4.Models.AuthorizationRequest context) - { - return !context.RedirectUri.StartsWith("https", StringComparison.Ordinal) - && !context.RedirectUri.StartsWith("http", StringComparison.Ordinal); + return InvalidJson("PreValidationError", ex); } } + + [HttpGet] + public async Task Login(string returnUrl) + { + var context = await _interaction.GetAuthorizationContextAsync(returnUrl); + + if (!context.Parameters.AllKeys.Contains("domain_hint") || + string.IsNullOrWhiteSpace(context.Parameters["domain_hint"])) + { + throw new Exception(_i18nService.T("NoDomainHintProvided")); + } + + var ssoToken = context.Parameters[SsoTokenable.TokenIdentifier]; + + if (string.IsNullOrWhiteSpace(ssoToken)) + { + return Unauthorized("A valid SSO token is required to continue with SSO login"); + } + + var domainHint = context.Parameters["domain_hint"]; + var organization = await _organizationRepository.GetByIdentifierAsync(domainHint); + + if (organization == null) + { + return InvalidJson("OrganizationNotFoundByIdentifierError"); + } + + var tokenable = _dataProtector.Unprotect(ssoToken); + + if (!tokenable.TokenIsValid(organization)) + { + return Unauthorized("The SSO token associated with your request is expired. A valid SSO token is required to continue."); + } + + return RedirectToAction(nameof(ExternalChallenge), new + { + scheme = organization.Id.ToString(), + returnUrl, + state = context.Parameters["state"], + userIdentifier = context.Parameters["session_state"], + }); + } + + [HttpGet] + public IActionResult ExternalChallenge(string scheme, string returnUrl, string state, string userIdentifier) + { + if (string.IsNullOrEmpty(returnUrl)) + { + returnUrl = "~/"; + } + + if (!Url.IsLocalUrl(returnUrl) && !_interaction.IsValidReturnUrl(returnUrl)) + { + throw new Exception(_i18nService.T("InvalidReturnUrl")); + } + + var props = new AuthenticationProperties + { + RedirectUri = Url.Action(nameof(ExternalCallback)), + Items = + { + // scheme will get serialized into `State` and returned back + { "scheme", scheme }, + { "return_url", returnUrl }, + { "state", state }, + { "user_identifier", userIdentifier }, + } + }; + + return Challenge(props, scheme); + } + + [HttpGet] + public async Task ExternalCallback() + { + // Read external identity from the temporary cookie + var result = await HttpContext.AuthenticateAsync( + AuthenticationSchemes.BitwardenExternalCookieAuthenticationScheme); + if (result?.Succeeded != true) + { + throw new Exception(_i18nService.T("ExternalAuthenticationError")); + } + + // Debugging + var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}"); + _logger.LogDebug("External claims: {@claims}", externalClaims); + + // Lookup our user and external provider info + var (user, provider, providerUserId, claims, ssoConfigData) = await FindUserFromExternalProviderAsync(result); + if (user == null) + { + // This might be where you might initiate a custom workflow for user registration + // in this sample we don't show how that would be done, as our sample implementation + // simply auto-provisions new external user + var userIdentifier = result.Properties.Items.Keys.Contains("user_identifier") ? + result.Properties.Items["user_identifier"] : null; + user = await AutoProvisionUserAsync(provider, providerUserId, claims, userIdentifier, ssoConfigData); + } + + if (user != null) + { + // This allows us to collect any additional claims or properties + // for the specific protocols used and store them in the local auth cookie. + // this is typically used to store data needed for signout from those protocols. + var additionalLocalClaims = new List(); + var localSignInProps = new AuthenticationProperties + { + IsPersistent = true, + ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(1) + }; + ProcessLoginCallback(result, additionalLocalClaims, localSignInProps); + + // Issue authentication cookie for user + await HttpContext.SignInAsync(new IdentityServerUser(user.Id.ToString()) + { + DisplayName = user.Email, + IdentityProvider = provider, + AdditionalClaims = additionalLocalClaims.ToArray() + }, localSignInProps); + } + + // Delete temporary cookie used during external authentication + await HttpContext.SignOutAsync(AuthenticationSchemes.BitwardenExternalCookieAuthenticationScheme); + + // Retrieve return URL + var returnUrl = result.Properties.Items["return_url"] ?? "~/"; + + // Check if external login is in the context of an OIDC request + var context = await _interaction.GetAuthorizationContextAsync(returnUrl); + if (context != null) + { + if (IsNativeClient(context)) + { + // The client is native, so this change in how to + // return the response is for better UX for the end user. + HttpContext.Response.StatusCode = 200; + HttpContext.Response.Headers["Location"] = string.Empty; + return View("Redirect", new RedirectViewModel { RedirectUrl = returnUrl }); + } + } + + return Redirect(returnUrl); + } + + [HttpGet] + public async Task Logout(string logoutId) + { + // Build a model so the logged out page knows what to display + var (updatedLogoutId, redirectUri, externalAuthenticationScheme) = await GetLoggedOutDataAsync(logoutId); + + if (User?.Identity.IsAuthenticated == true) + { + // Delete local authentication cookie + await HttpContext.SignOutAsync(); + } + + // HACK: Temporary workaroud for the time being that doesn't try to sign out of OneLogin schemes, + // which doesnt support SLO + if (externalAuthenticationScheme != null && !externalAuthenticationScheme.Contains("onelogin")) + { + // Build a return URL so the upstream provider will redirect back + // to us after the user has logged out. this allows us to then + // complete our single sign-out processing. + var url = Url.Action("Logout", new { logoutId = updatedLogoutId }); + + // This triggers a redirect to the external provider for sign-out + return SignOut(new AuthenticationProperties { RedirectUri = url }, externalAuthenticationScheme); + } + if (redirectUri != null) + { + return View("Redirect", new RedirectViewModel { RedirectUrl = redirectUri }); + } + else + { + return Redirect("~/"); + } + } + + private async Task<(User user, string provider, string providerUserId, IEnumerable claims, SsoConfigurationData config)> + FindUserFromExternalProviderAsync(AuthenticateResult result) + { + var provider = result.Properties.Items["scheme"]; + var orgId = new Guid(provider); + var ssoConfig = await _ssoConfigRepository.GetByOrganizationIdAsync(orgId); + if (ssoConfig == null || !ssoConfig.Enabled) + { + throw new Exception(_i18nService.T("OrganizationOrSsoConfigNotFound")); + } + + var ssoConfigData = ssoConfig.GetData(); + var externalUser = result.Principal; + + // Validate acr claim against expectation before going further + if (!string.IsNullOrWhiteSpace(ssoConfigData.ExpectedReturnAcrValue)) + { + var acrClaim = externalUser.FindFirst(JwtClaimTypes.AuthenticationContextClassReference); + if (acrClaim?.Value != ssoConfigData.ExpectedReturnAcrValue) + { + throw new Exception(_i18nService.T("AcrMissingOrInvalid")); + } + } + + // Ensure the NameIdentifier used is not a transient name ID, if so, we need a different attribute + // for the user identifier. + static bool nameIdIsNotTransient(Claim c) => c.Type == ClaimTypes.NameIdentifier + && (c.Properties == null + || !c.Properties.ContainsKey(SamlPropertyKeys.ClaimFormat) + || c.Properties[SamlPropertyKeys.ClaimFormat] != SamlNameIdFormats.Transient); + + // Try to determine the unique id of the external user (issued by the provider) + // the most common claim type for that are the sub claim and the NameIdentifier + // depending on the external provider, some other claim type might be used + var customUserIdClaimTypes = ssoConfigData.GetAdditionalUserIdClaimTypes(); + var userIdClaim = externalUser.FindFirst(c => customUserIdClaimTypes.Contains(c.Type)) ?? + externalUser.FindFirst(JwtClaimTypes.Subject) ?? + externalUser.FindFirst(nameIdIsNotTransient) ?? + // Some SAML providers may use the `uid` attribute for this + // where a transient NameID has been sent in the subject + externalUser.FindFirst("uid") ?? + externalUser.FindFirst("upn") ?? + externalUser.FindFirst("eppn") ?? + throw new Exception(_i18nService.T("UnknownUserId")); + + // Remove the user id claim so we don't include it as an extra claim if/when we provision the user + var claims = externalUser.Claims.ToList(); + claims.Remove(userIdClaim); + + // find external user + var providerUserId = userIdClaim.Value; + + var user = await _userRepository.GetBySsoUserAsync(providerUserId, orgId); + + return (user, provider, providerUserId, claims, ssoConfigData); + } + + private async Task AutoProvisionUserAsync(string provider, string providerUserId, + IEnumerable claims, string userIdentifier, SsoConfigurationData config) + { + var name = GetName(claims, config.GetAdditionalNameClaimTypes()); + var email = GetEmailAddress(claims, config.GetAdditionalEmailClaimTypes()); + if (string.IsNullOrWhiteSpace(email) && providerUserId.Contains("@")) + { + email = providerUserId; + } + + if (!Guid.TryParse(provider, out var orgId)) + { + // TODO: support non-org (server-wide) SSO in the future? + throw new Exception(_i18nService.T("SSOProviderIsNotAnOrgId", provider)); + } + + User existingUser = null; + if (string.IsNullOrWhiteSpace(userIdentifier)) + { + if (string.IsNullOrWhiteSpace(email)) + { + throw new Exception(_i18nService.T("CannotFindEmailClaim")); + } + existingUser = await _userRepository.GetByEmailAsync(email); + } + else + { + var split = userIdentifier.Split(","); + if (split.Length < 2) + { + throw new Exception(_i18nService.T("InvalidUserIdentifier")); + } + var userId = split[0]; + var token = split[1]; + + var tokenOptions = new TokenOptions(); + + var claimedUser = await _userService.GetUserByIdAsync(userId); + if (claimedUser != null) + { + var tokenIsValid = await _userManager.VerifyUserTokenAsync( + claimedUser, tokenOptions.PasswordResetTokenProvider, TokenPurposes.LinkSso, token); + if (tokenIsValid) + { + existingUser = claimedUser; + } + else + { + throw new Exception(_i18nService.T("UserIdAndTokenMismatch")); + } + } + } + + OrganizationUser orgUser = null; + var organization = await _organizationRepository.GetByIdAsync(orgId); + if (organization == null) + { + throw new Exception(_i18nService.T("CouldNotFindOrganization", orgId)); + } + + // Try to find OrgUser via existing User Id (accepted/confirmed user) + if (existingUser != null) + { + var orgUsersByUserId = await _organizationUserRepository.GetManyByUserAsync(existingUser.Id); + orgUser = orgUsersByUserId.SingleOrDefault(u => u.OrganizationId == orgId); + } + + // If no Org User found by Existing User Id - search all organization users via email + orgUser ??= await _organizationUserRepository.GetByOrganizationEmailAsync(orgId, email); + + // All Existing User flows handled below + if (existingUser != null) + { + if (existingUser.UsesKeyConnector && + (orgUser == null || orgUser.Status == OrganizationUserStatusType.Invited)) + { + throw new Exception(_i18nService.T("UserAlreadyExistsKeyConnector")); + } + + if (orgUser == null) + { + // Org User is not created - no invite has been sent + throw new Exception(_i18nService.T("UserAlreadyExistsInviteProcess")); + } + + if (orgUser.Status == OrganizationUserStatusType.Invited) + { + // Org User is invited - they must manually accept the invite via email and authenticate with MP + throw new Exception(_i18nService.T("UserAlreadyInvited", email, organization.Name)); + } + + // Accepted or Confirmed - create SSO link and return; + await CreateSsoUserRecord(providerUserId, existingUser.Id, orgId, orgUser); + return existingUser; + } + + // Before any user creation - if Org User doesn't exist at this point - make sure there are enough seats to add one + if (orgUser == null && organization.Seats.HasValue) + { + var occupiedSeats = await _organizationService.GetOccupiedSeatCount(organization); + var initialSeatCount = organization.Seats.Value; + var availableSeats = initialSeatCount - occupiedSeats; + var prorationDate = DateTime.UtcNow; + if (availableSeats < 1) + { + try + { + if (_globalSettings.SelfHosted) + { + throw new Exception("Cannot autoscale on self-hosted instance."); + } + + await _organizationService.AutoAddSeatsAsync(organization, 1, prorationDate); + } + catch (Exception e) + { + if (organization.Seats.Value != initialSeatCount) + { + await _organizationService.AdjustSeatsAsync(orgId, initialSeatCount - organization.Seats.Value, prorationDate); + } + _logger.LogInformation(e, "SSO auto provisioning failed"); + throw new Exception(_i18nService.T("NoSeatsAvailable", organization.Name)); + } + } + } + + // Create user record - all existing user flows are handled above + var user = new User + { + Name = name, + Email = email, + ApiKey = CoreHelpers.SecureRandomString(30) + }; + await _userService.RegisterUserAsync(user); + + // If the organization has 2fa policy enabled, make sure to default jit user 2fa to email + var twoFactorPolicy = + await _policyRepository.GetByOrganizationIdTypeAsync(orgId, PolicyType.TwoFactorAuthentication); + if (twoFactorPolicy != null && twoFactorPolicy.Enabled) + { + user.SetTwoFactorProviders(new Dictionary + { + [TwoFactorProviderType.Email] = new TwoFactorProvider + { + MetaData = new Dictionary { ["Email"] = user.Email.ToLowerInvariant() }, + Enabled = true + } + }); + await _userService.UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.Email); + } + + // Create Org User if null or else update existing Org User + if (orgUser == null) + { + orgUser = new OrganizationUser + { + OrganizationId = orgId, + UserId = user.Id, + Type = OrganizationUserType.User, + Status = OrganizationUserStatusType.Invited + }; + await _organizationUserRepository.CreateAsync(orgUser); + } + else + { + orgUser.UserId = user.Id; + await _organizationUserRepository.ReplaceAsync(orgUser); + } + + // Create sso user record + await CreateSsoUserRecord(providerUserId, user.Id, orgId, orgUser); + + return user; + } + + private IActionResult InvalidJson(string errorMessageKey, Exception ex = null) + { + Response.StatusCode = ex == null ? 400 : 500; + return Json(new ErrorResponseModel(_i18nService.T(errorMessageKey)) + { + ExceptionMessage = ex?.Message, + ExceptionStackTrace = ex?.StackTrace, + InnerExceptionMessage = ex?.InnerException?.Message, + }); + } + + private string GetEmailAddress(IEnumerable claims, IEnumerable additionalClaimTypes) + { + var filteredClaims = claims.Where(c => !string.IsNullOrWhiteSpace(c.Value) && c.Value.Contains("@")); + + var email = filteredClaims.GetFirstMatch(additionalClaimTypes.ToArray()) ?? + filteredClaims.GetFirstMatch(JwtClaimTypes.Email, ClaimTypes.Email, + SamlClaimTypes.Email, "mail", "emailaddress"); + if (!string.IsNullOrWhiteSpace(email)) + { + return email; + } + + var username = filteredClaims.GetFirstMatch(JwtClaimTypes.PreferredUserName, + SamlClaimTypes.UserId, "uid"); + if (!string.IsNullOrWhiteSpace(username)) + { + return username; + } + + return null; + } + + private string GetName(IEnumerable claims, IEnumerable additionalClaimTypes) + { + var filteredClaims = claims.Where(c => !string.IsNullOrWhiteSpace(c.Value)); + + var name = filteredClaims.GetFirstMatch(additionalClaimTypes.ToArray()) ?? + filteredClaims.GetFirstMatch(JwtClaimTypes.Name, ClaimTypes.Name, + SamlClaimTypes.DisplayName, SamlClaimTypes.CommonName, "displayname", "cn"); + if (!string.IsNullOrWhiteSpace(name)) + { + return name; + } + + var givenName = filteredClaims.GetFirstMatch(SamlClaimTypes.GivenName, "givenname", "firstname", + "fn", "fname", "nickname"); + var surname = filteredClaims.GetFirstMatch(SamlClaimTypes.Surname, "sn", "surname", "lastname"); + var nameParts = new[] { givenName, surname }.Where(p => !string.IsNullOrWhiteSpace(p)); + if (nameParts.Any()) + { + return string.Join(' ', nameParts); + } + + return null; + } + + private async Task CreateSsoUserRecord(string providerUserId, Guid userId, Guid orgId, OrganizationUser orgUser) + { + // Delete existing SsoUser (if any) - avoids error if providerId has changed and the sso link is stale + var existingSsoUser = await _ssoUserRepository.GetByUserIdOrganizationIdAsync(orgId, userId); + if (existingSsoUser != null) + { + await _ssoUserRepository.DeleteAsync(userId, orgId); + await _eventService.LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_ResetSsoLink); + } + else + { + // If no stale user, this is the user's first Sso login ever + await _eventService.LogOrganizationUserEventAsync(orgUser, EventType.OrganizationUser_FirstSsoLogin); + } + + var ssoUser = new SsoUser + { + ExternalId = providerUserId, + UserId = userId, + OrganizationId = orgId, + }; + await _ssoUserRepository.CreateAsync(ssoUser); + } + + private void ProcessLoginCallback(AuthenticateResult externalResult, + List localClaims, AuthenticationProperties localSignInProps) + { + // If the external system sent a session id claim, copy it over + // so we can use it for single sign-out + var sid = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId); + if (sid != null) + { + localClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value)); + } + + // If the external provider issued an idToken, we'll keep it for signout + var idToken = externalResult.Properties.GetTokenValue("id_token"); + if (idToken != null) + { + localSignInProps.StoreTokens( + new[] { new AuthenticationToken { Name = "id_token", Value = idToken } }); + } + } + + private async Task GetProviderAsync(string returnUrl) + { + var context = await _interaction.GetAuthorizationContextAsync(returnUrl); + if (context?.IdP != null && await _schemeProvider.GetSchemeAsync(context.IdP) != null) + { + return context.IdP; + } + var schemes = await _schemeProvider.GetAllSchemesAsync(); + var providers = schemes.Select(x => x.Name).ToList(); + return providers.FirstOrDefault(); + } + + private async Task<(string, string, string)> GetLoggedOutDataAsync(string logoutId) + { + // Get context information (client name, post logout redirect URI and iframe for federated signout) + var logout = await _interaction.GetLogoutContextAsync(logoutId); + string externalAuthenticationScheme = null; + if (User?.Identity.IsAuthenticated == true) + { + var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value; + if (idp != null && idp != IdentityServerConstants.LocalIdentityProvider) + { + var providerSupportsSignout = await HttpContext.GetSchemeSupportsSignOutAsync(idp); + if (providerSupportsSignout) + { + if (logoutId == null) + { + // If there's no current logout context, we need to create one + // this captures necessary info from the current logged in user + // before we signout and redirect away to the external IdP for signout + logoutId = await _interaction.CreateLogoutContextAsync(); + } + + externalAuthenticationScheme = idp; + } + } + } + + return (logoutId, logout?.PostLogoutRedirectUri, externalAuthenticationScheme); + } + + public bool IsNativeClient(IdentityServer4.Models.AuthorizationRequest context) + { + return !context.RedirectUri.StartsWith("https", StringComparison.Ordinal) + && !context.RedirectUri.StartsWith("http", StringComparison.Ordinal); + } } diff --git a/bitwarden_license/src/Sso/Controllers/HomeController.cs b/bitwarden_license/src/Sso/Controllers/HomeController.cs index 7536a1ca4..ee15fefc9 100644 --- a/bitwarden_license/src/Sso/Controllers/HomeController.cs +++ b/bitwarden_license/src/Sso/Controllers/HomeController.cs @@ -1,65 +1,54 @@ -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Authorization; -using IdentityServer4.Services; -using System.Threading.Tasks; +using System.Diagnostics; using Bit.Sso.Models; -using System.Diagnostics; +using IdentityServer4.Services; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Mvc; -namespace Bit.Sso.Controllers +namespace Bit.Sso.Controllers; + +public class HomeController : Controller { - public class HomeController : Controller + private readonly IIdentityServerInteractionService _interaction; + + public HomeController(IIdentityServerInteractionService interaction) { - private readonly IIdentityServerInteractionService _interaction; + _interaction = interaction; + } - public HomeController(IIdentityServerInteractionService interaction) + [Route("~/Error")] + [Route("~/Home/Error")] + [AllowAnonymous] + public async Task Error(string errorId) + { + var vm = new ErrorViewModel(); + + // retrieve error details from identityserver + var message = string.IsNullOrWhiteSpace(errorId) ? null : + await _interaction.GetErrorContextAsync(errorId); + if (message != null) { - _interaction = interaction; + vm.Error = message; } - - [HttpGet("~/alive")] - [HttpGet("~/now")] - [AllowAnonymous] - public DateTime GetAlive() + else { - return DateTime.UtcNow; - } - - [Route("~/Error")] - [Route("~/Home/Error")] - [AllowAnonymous] - public async Task Error(string errorId) - { - var vm = new ErrorViewModel(); - - // retrieve error details from identityserver - var message = string.IsNullOrWhiteSpace(errorId) ? null : - await _interaction.GetErrorContextAsync(errorId); - if (message != null) + vm.RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; + var exceptionHandlerPathFeature = HttpContext.Features.Get(); + var exception = exceptionHandlerPathFeature?.Error; + if (exception is InvalidOperationException opEx && opEx.Message.Contains("schemes are: ")) { - vm.Error = message; + // Messages coming from aspnetcore with a message + // similar to "The registered sign-in schemes are: {schemes}." + // will expose other Org IDs and sign-in schemes enabled on + // the server. These errors should be truncated to just the + // scheme impacted (always the first sentence) + var cleanupPoint = opEx.Message.IndexOf(". ") + 1; + var exMessage = opEx.Message.Substring(0, cleanupPoint); + exception = new InvalidOperationException(exMessage, opEx); } - else - { - vm.RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; - var exceptionHandlerPathFeature = HttpContext.Features.Get(); - var exception = exceptionHandlerPathFeature?.Error; - if (exception is InvalidOperationException opEx && opEx.Message.Contains("schemes are: ")) - { - // Messages coming from aspnetcore with a message - // similar to "The registered sign-in schemes are: {schemes}." - // will expose other Org IDs and sign-in schemes enabled on - // the server. These errors should be truncated to just the - // scheme impacted (always the first sentence) - var cleanupPoint = opEx.Message.IndexOf(". ") + 1; - var exMessage = opEx.Message.Substring(0, cleanupPoint); - exception = new InvalidOperationException(exMessage, opEx); - } - vm.Exception = exception; - } - - return View("Error", vm); + vm.Exception = exception; } + + return View("Error", vm); } } diff --git a/bitwarden_license/src/Sso/Controllers/InfoController.cs b/bitwarden_license/src/Sso/Controllers/InfoController.cs new file mode 100644 index 000000000..67794de75 --- /dev/null +++ b/bitwarden_license/src/Sso/Controllers/InfoController.cs @@ -0,0 +1,20 @@ +using Bit.Core.Utilities; +using Microsoft.AspNetCore.Mvc; + +namespace Bit.Sso.Controllers; + +public class InfoController : Controller +{ + [HttpGet("~/alive")] + [HttpGet("~/now")] + public DateTime GetAlive() + { + return DateTime.UtcNow; + } + + [HttpGet("~/version")] + public JsonResult GetVersion() + { + return Json(AssemblyHelpers.GetVersion()); + } +} diff --git a/bitwarden_license/src/Sso/Controllers/MetadataController.cs b/bitwarden_license/src/Sso/Controllers/MetadataController.cs index a114f8e82..54f4f8cd4 100644 --- a/bitwarden_license/src/Sso/Controllers/MetadataController.cs +++ b/bitwarden_license/src/Sso/Controllers/MetadataController.cs @@ -1,72 +1,69 @@ -using System; -using System.Threading.Tasks; -using Bit.Core.Enums; +using Bit.Core.Enums; using Bit.Sso.Utilities; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Mvc; using Sustainsys.Saml2.AspNetCore2; using Sustainsys.Saml2.WebSso; -namespace Bit.Sso.Controllers +namespace Bit.Sso.Controllers; + +public class MetadataController : Controller { - public class MetadataController : Controller + private readonly IAuthenticationSchemeProvider _schemeProvider; + + public MetadataController( + IAuthenticationSchemeProvider schemeProvider) { - private readonly IAuthenticationSchemeProvider _schemeProvider; + _schemeProvider = schemeProvider; + } - public MetadataController( - IAuthenticationSchemeProvider schemeProvider) + [HttpGet("saml2/{scheme}")] + public async Task ViewAsync(string scheme) + { + if (string.IsNullOrWhiteSpace(scheme)) { - _schemeProvider = schemeProvider; + return NotFound(); } - [HttpGet("saml2/{scheme}")] - public async Task ViewAsync(string scheme) + var authScheme = await _schemeProvider.GetSchemeAsync(scheme); + if (authScheme == null || + !(authScheme is DynamicAuthenticationScheme dynamicAuthScheme) || + dynamicAuthScheme?.SsoType != SsoType.Saml2) { - if (string.IsNullOrWhiteSpace(scheme)) - { - return NotFound(); - } - - var authScheme = await _schemeProvider.GetSchemeAsync(scheme); - if (authScheme == null || - !(authScheme is DynamicAuthenticationScheme dynamicAuthScheme) || - dynamicAuthScheme?.SsoType != SsoType.Saml2) - { - return NotFound(); - } - - if (!(dynamicAuthScheme.Options is Saml2Options options)) - { - return NotFound(); - } - - var uri = new Uri( - Request.Scheme - + "://" - + Request.Host - + Request.Path - + Request.QueryString); - - var pathBase = Request.PathBase.Value; - pathBase = string.IsNullOrEmpty(pathBase) ? "/" : pathBase; - - var requestdata = new HttpRequestData( - Request.Method, - uri, - pathBase, - null, - Request.Cookies, - (data) => data); - - var metadataResult = CommandFactory - .GetCommand(CommandFactory.MetadataCommand) - .Run(requestdata, options); - //Response.Headers.Add("Content-Disposition", $"filename= bitwarden-saml2-meta-{scheme}.xml"); - return new ContentResult - { - Content = metadataResult.Content, - ContentType = "text/xml", - }; + return NotFound(); } + + if (!(dynamicAuthScheme.Options is Saml2Options options)) + { + return NotFound(); + } + + var uri = new Uri( + Request.Scheme + + "://" + + Request.Host + + Request.Path + + Request.QueryString); + + var pathBase = Request.PathBase.Value; + pathBase = string.IsNullOrEmpty(pathBase) ? "/" : pathBase; + + var requestdata = new HttpRequestData( + Request.Method, + uri, + pathBase, + null, + Request.Cookies, + (data) => data); + + var metadataResult = CommandFactory + .GetCommand(CommandFactory.MetadataCommand) + .Run(requestdata, options); + //Response.Headers.Add("Content-Disposition", $"filename= bitwarden-saml2-meta-{scheme}.xml"); + return new ContentResult + { + Content = metadataResult.Content, + ContentType = "text/xml", + }; } } diff --git a/bitwarden_license/src/Sso/Dockerfile b/bitwarden_license/src/Sso/Dockerfile index 8668004ff..f63cb82ce 100644 --- a/bitwarden_license/src/Sso/Dockerfile +++ b/bitwarden_license/src/Sso/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 +FROM mcr.microsoft.com/dotnet/aspnet:6.0 LABEL com.bitwarden.product="bitwarden" diff --git a/bitwarden_license/src/Sso/IdentityServer/OidcIdentityClient.cs b/bitwarden_license/src/Sso/IdentityServer/OidcIdentityClient.cs new file mode 100644 index 000000000..8629da07e --- /dev/null +++ b/bitwarden_license/src/Sso/IdentityServer/OidcIdentityClient.cs @@ -0,0 +1,25 @@ +using Bit.Core.Settings; +using IdentityServer4; +using IdentityServer4.Models; + +namespace Bit.Sso.IdentityServer; + +public class OidcIdentityClient : Client +{ + public OidcIdentityClient(GlobalSettings globalSettings) + { + ClientId = "oidc-identity"; + RequireClientSecret = true; + RequirePkce = true; + ClientSecrets = new List { new(globalSettings.OidcIdentityClientKey.Sha256()) }; + AllowedScopes = new[] + { + IdentityServerConstants.StandardScopes.OpenId, + IdentityServerConstants.StandardScopes.Profile + }; + AllowedGrantTypes = GrantTypes.Code; + Enabled = true; + RedirectUris = new List { $"{globalSettings.BaseServiceUri.Identity}/signin-oidc" }; + RequireConsent = false; + } +} diff --git a/bitwarden_license/src/Sso/Models/ErrorViewModel.cs b/bitwarden_license/src/Sso/Models/ErrorViewModel.cs index b1420e2c3..46ae8edd9 100644 --- a/bitwarden_license/src/Sso/Models/ErrorViewModel.cs +++ b/bitwarden_license/src/Sso/Models/ErrorViewModel.cs @@ -1,28 +1,26 @@ -using System; -using IdentityServer4.Models; +using IdentityServer4.Models; -namespace Bit.Sso.Models +namespace Bit.Sso.Models; + +public class ErrorViewModel { - public class ErrorViewModel + private string _requestId; + + public ErrorMessage Error { get; set; } + public Exception Exception { get; set; } + + public string Message => Error?.Error; + public string Description => Error?.ErrorDescription ?? Exception?.Message; + public string RedirectUri => Error?.RedirectUri; + public string RequestId { - private string _requestId; - - public ErrorMessage Error { get; set; } - public Exception Exception { get; set; } - - public string Message => Error?.Error; - public string Description => Error?.ErrorDescription ?? Exception?.Message; - public string RedirectUri => Error?.RedirectUri; - public string RequestId + get { - get - { - return Error?.RequestId ?? _requestId; - } - set - { - _requestId = value; - } + return Error?.RequestId ?? _requestId; + } + set + { + _requestId = value; } } } diff --git a/bitwarden_license/src/Sso/Models/RedirectViewModel.cs b/bitwarden_license/src/Sso/Models/RedirectViewModel.cs index 54b5b4715..9bc294d96 100644 --- a/bitwarden_license/src/Sso/Models/RedirectViewModel.cs +++ b/bitwarden_license/src/Sso/Models/RedirectViewModel.cs @@ -1,7 +1,6 @@ -namespace Bit.Sso.Models +namespace Bit.Sso.Models; + +public class RedirectViewModel { - public class RedirectViewModel - { - public string RedirectUrl { get; set; } - } + public string RedirectUrl { get; set; } } diff --git a/bitwarden_license/src/Sso/Models/SamlEnvironment.cs b/bitwarden_license/src/Sso/Models/SamlEnvironment.cs index f1890840f..6de718029 100644 --- a/bitwarden_license/src/Sso/Models/SamlEnvironment.cs +++ b/bitwarden_license/src/Sso/Models/SamlEnvironment.cs @@ -1,9 +1,8 @@ using System.Security.Cryptography.X509Certificates; -namespace Bit.Sso.Models +namespace Bit.Sso.Models; + +public class SamlEnvironment { - public class SamlEnvironment - { - public X509Certificate2 SpSigningCertificate { get; set; } - } + public X509Certificate2 SpSigningCertificate { get; set; } } diff --git a/bitwarden_license/src/Sso/Models/SsoPreValidateResponseModel.cs b/bitwarden_license/src/Sso/Models/SsoPreValidateResponseModel.cs new file mode 100644 index 000000000..f96b38775 --- /dev/null +++ b/bitwarden_license/src/Sso/Models/SsoPreValidateResponseModel.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Bit.Sso.Models; + +public class SsoPreValidateResponseModel : JsonResult +{ + public SsoPreValidateResponseModel(string token) : base(new + { + token + }) + { } +} diff --git a/bitwarden_license/src/Sso/Program.cs b/bitwarden_license/src/Sso/Program.cs index 6b6a83d05..051caca9c 100644 --- a/bitwarden_license/src/Sso/Program.cs +++ b/bitwarden_license/src/Sso/Program.cs @@ -1,36 +1,32 @@ using Bit.Core.Utilities; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Hosting; using Serilog; -using Serilog.Events; -namespace Bit.Sso +namespace Bit.Sso; + +public class Program { - public class Program + public static void Main(string[] args) { - public static void Main(string[] args) - { - Host - .CreateDefaultBuilder(args) - .ConfigureCustomAppConfiguration(args) - .ConfigureWebHostDefaults(webBuilder => + Host + .CreateDefaultBuilder(args) + .ConfigureCustomAppConfiguration(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + webBuilder.ConfigureLogging((hostingContext, logging) => + logging.AddSerilog(hostingContext, (e, globalSettings) => { - webBuilder.UseStartup(); - webBuilder.ConfigureLogging((hostingContext, logging) => - logging.AddSerilog(hostingContext, e => + var context = e.Properties["SourceContext"].ToString(); + if (e.Properties.ContainsKey("RequestPath") && + !string.IsNullOrWhiteSpace(e.Properties["RequestPath"]?.ToString()) && + (context.Contains(".Server.Kestrel") || context.Contains(".Core.IISHttpServer"))) { - var context = e.Properties["SourceContext"].ToString(); - if (e.Properties.ContainsKey("RequestPath") && - !string.IsNullOrWhiteSpace(e.Properties["RequestPath"]?.ToString()) && - (context.Contains(".Server.Kestrel") || context.Contains(".Core.IISHttpServer"))) - { - return false; - } - return e.Level >= LogEventLevel.Error; - })); - }) - .Build() - .Run(); - } + return false; + } + return e.Level >= globalSettings.MinLogLevel.SsoSettings.Default; + })); + }) + .Build() + .Run(); } } diff --git a/bitwarden_license/src/Sso/Properties/launchSettings.json b/bitwarden_license/src/Sso/Properties/launchSettings.json index 8367fbeb7..e9c6e1dd1 100644 --- a/bitwarden_license/src/Sso/Properties/launchSettings.json +++ b/bitwarden_license/src/Sso/Properties/launchSettings.json @@ -22,6 +22,15 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } + }, + "Sso-SelfHost": { + "commandName": "Project", + "launchBrowser": false, + "applicationUrl": "http://localhost:51823", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "developSelfHosted": "true" + } } } } diff --git a/bitwarden_license/src/Sso/Sso.csproj b/bitwarden_license/src/Sso/Sso.csproj index cb9e81ef8..29843dac3 100644 --- a/bitwarden_license/src/Sso/Sso.csproj +++ b/bitwarden_license/src/Sso/Sso.csproj @@ -4,14 +4,13 @@ bitwarden-Sso - - - + + diff --git a/bitwarden_license/src/Sso/Startup.cs b/bitwarden_license/src/Sso/Startup.cs index 0abfeaf85..aeeaa7e6f 100644 --- a/bitwarden_license/src/Sso/Startup.cs +++ b/bitwarden_license/src/Sso/Startup.cs @@ -1,156 +1,154 @@ -using System; -using Bit.Core; +using Bit.Core; using Bit.Core.Context; using Bit.Core.Settings; using Bit.Core.Utilities; +using Bit.SharedWeb.Utilities; using Bit.Sso.Utilities; using IdentityServer4.Extensions; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Logging; using Stripe; -namespace Bit.Sso +namespace Bit.Sso; + +public class Startup { - public class Startup + public Startup(IWebHostEnvironment env, IConfiguration configuration) { - public Startup(IWebHostEnvironment env, IConfiguration configuration) + Configuration = configuration; + Environment = env; + } + + public IConfiguration Configuration { get; } + public IWebHostEnvironment Environment { get; set; } + + public void ConfigureServices(IServiceCollection services) + { + // Options + services.AddOptions(); + + // Settings + var globalSettings = services.AddGlobalSettingsServices(Configuration, Environment); + + // Stripe Billing + StripeConfiguration.ApiKey = globalSettings.Stripe.ApiKey; + StripeConfiguration.MaxNetworkRetries = globalSettings.Stripe.MaxNetworkRetries; + + // Data Protection + services.AddCustomDataProtectionServices(Environment, globalSettings); + + // Repositories + services.AddDatabaseRepositories(globalSettings); + + // Context + services.AddScoped(); + + // Caching + services.AddMemoryCache(); + services.AddDistributedCache(globalSettings); + + // Mvc + services.AddControllersWithViews(); + + // Cookies + if (Environment.IsDevelopment()) { - Configuration = configuration; - Environment = env; - } - - public IConfiguration Configuration { get; } - public IWebHostEnvironment Environment { get; set; } - - public void ConfigureServices(IServiceCollection services) - { - // Options - services.AddOptions(); - - // Settings - var globalSettings = services.AddGlobalSettingsServices(Configuration); - - // Stripe Billing - StripeConfiguration.ApiKey = globalSettings.StripeApiKey; - - // Data Protection - services.AddCustomDataProtectionServices(Environment, globalSettings); - - // Repositories - services.AddSqlServerRepositories(globalSettings); - - // Context - services.AddScoped(); - - // Mvc - services.AddControllersWithViews(); - - // Cookies - if (Environment.IsDevelopment()) + services.Configure(options => { - services.Configure(options => + options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.Unspecified; + options.OnAppendCookie = ctx => { - options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.Unspecified; - options.OnAppendCookie = ctx => - { - ctx.CookieOptions.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Unspecified; - }; - }); - } - - // Authentication - services.AddDistributedIdentityServices(globalSettings); - services.AddAuthentication() - .AddCookie(AuthenticationSchemes.BitwardenExternalCookieAuthenticationScheme); - services.AddSsoServices(globalSettings); - - // IdentityServer - services.AddSsoIdentityServerServices(Environment, globalSettings); - - // Identity - services.AddCustomIdentityServices(globalSettings); - - // Services - services.AddBaseServices(); - services.AddDefaultServices(globalSettings); - services.AddCoreLocalizationServices(); - } - - public void Configure( - IApplicationBuilder app, - IWebHostEnvironment env, - IHostApplicationLifetime appLifetime, - GlobalSettings globalSettings, - ILogger logger) - { - if (env.IsDevelopment() || globalSettings.SelfHosted) - { - IdentityModelEventSource.ShowPII = true; - } - - app.UseSerilog(env, appLifetime, globalSettings); - - // Add general security headers - app.UseMiddleware(); - - if (!env.IsDevelopment()) - { - var uri = new Uri(globalSettings.BaseServiceUri.Sso); - app.Use(async (ctx, next) => - { - ctx.SetIdentityServerOrigin($"{uri.Scheme}://{uri.Host}"); - await next(); - }); - } - - if (globalSettings.SelfHosted) - { - app.UsePathBase("/sso"); - app.UseForwardedHeaders(globalSettings); - } - - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - app.UseCookiePolicy(); - } - else - { - app.UseExceptionHandler("/Error"); - } - - app.UseCoreLocalization(); - - // Add static files to the request pipeline. - app.UseStaticFiles(); - - // Add routing - app.UseRouting(); - - // Add Cors - app.UseCors(policy => policy.SetIsOriginAllowed(o => CoreHelpers.IsCorsOriginAllowed(o, globalSettings)) - .AllowAnyMethod().AllowAnyHeader().AllowCredentials()); - - // Add current context - app.UseMiddleware(); - - // Add IdentityServer to the request pipeline. - app.UseIdentityServer(new IdentityServerMiddlewareOptions - { - AuthenticationMiddleware = app => app.UseMiddleware() + ctx.CookieOptions.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Unspecified; + }; }); - - // Add Mvc stuff - app.UseAuthorization(); - app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute()); - - // Log startup - logger.LogInformation(Constants.BypassFiltersEventId, globalSettings.ProjectName + " started."); } + + // Authentication + services.AddDistributedIdentityServices(globalSettings); + services.AddAuthentication() + .AddCookie(AuthenticationSchemes.BitwardenExternalCookieAuthenticationScheme); + services.AddSsoServices(globalSettings); + + // IdentityServer + services.AddSsoIdentityServerServices(Environment, globalSettings); + + // Identity + services.AddCustomIdentityServices(globalSettings); + + // Services + services.AddBaseServices(globalSettings); + services.AddDefaultServices(globalSettings); + services.AddCoreLocalizationServices(); + } + + public void Configure( + IApplicationBuilder app, + IWebHostEnvironment env, + IHostApplicationLifetime appLifetime, + GlobalSettings globalSettings, + ILogger logger) + { + if (env.IsDevelopment() || globalSettings.SelfHosted) + { + IdentityModelEventSource.ShowPII = true; + } + + app.UseSerilog(env, appLifetime, globalSettings); + + // Add general security headers + app.UseMiddleware(); + + if (!env.IsDevelopment()) + { + var uri = new Uri(globalSettings.BaseServiceUri.Sso); + app.Use(async (ctx, next) => + { + ctx.SetIdentityServerOrigin($"{uri.Scheme}://{uri.Host}"); + await next(); + }); + } + + if (globalSettings.SelfHosted) + { + app.UsePathBase("/sso"); + app.UseForwardedHeaders(globalSettings); + } + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + app.UseCookiePolicy(); + } + else + { + app.UseExceptionHandler("/Error"); + } + + app.UseCoreLocalization(); + + // Add static files to the request pipeline. + app.UseStaticFiles(); + + // Add routing + app.UseRouting(); + + // Add Cors + app.UseCors(policy => policy.SetIsOriginAllowed(o => CoreHelpers.IsCorsOriginAllowed(o, globalSettings)) + .AllowAnyMethod().AllowAnyHeader().AllowCredentials()); + + // Add current context + app.UseMiddleware(); + + // Add IdentityServer to the request pipeline. + app.UseIdentityServer(new IdentityServerMiddlewareOptions + { + AuthenticationMiddleware = app => app.UseMiddleware() + }); + + // Add Mvc stuff + app.UseAuthorization(); + app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute()); + + // Log startup + logger.LogInformation(Constants.BypassFiltersEventId, globalSettings.ProjectName + " started."); } } diff --git a/bitwarden_license/src/Sso/Utilities/ClaimsExtensions.cs b/bitwarden_license/src/Sso/Utilities/ClaimsExtensions.cs index 886842720..735c7bc0a 100644 --- a/bitwarden_license/src/Sso/Utilities/ClaimsExtensions.cs +++ b/bitwarden_license/src/Sso/Utilities/ClaimsExtensions.cs @@ -1,49 +1,45 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; +using System.Security.Claims; using System.Text.RegularExpressions; -namespace Bit.Sso.Utilities +namespace Bit.Sso.Utilities; + +public static class ClaimsExtensions { - public static class ClaimsExtensions + private static readonly Regex _normalizeTextRegEx = + new Regex(@"[^a-zA-Z]", RegexOptions.CultureInvariant | RegexOptions.Singleline); + + public static string GetFirstMatch(this IEnumerable claims, params string[] possibleNames) { - private static readonly Regex _normalizeTextRegEx = - new Regex(@"[^a-zA-Z]", RegexOptions.CultureInvariant | RegexOptions.Singleline); + var normalizedClaims = claims.Select(c => (Normalize(c.Type), c.Value)).ToList(); - public static string GetFirstMatch(this IEnumerable claims, params string[] possibleNames) + // Order of prescendence is by passed in names + foreach (var name in possibleNames.Select(Normalize)) { - var normalizedClaims = claims.Select(c => (Normalize(c.Type), c.Value)).ToList(); - - // Order of prescendence is by passed in names - foreach (var name in possibleNames.Select(Normalize)) + // Second by order of claims (find claim by name) + foreach (var claim in normalizedClaims) { - // Second by order of claims (find claim by name) - foreach (var claim in normalizedClaims) + if (Equals(claim.Item1, name)) { - if (Equals(claim.Item1, name)) - { - return claim.Value; - } + return claim.Value; } } - return null; } + return null; + } - private static bool Equals(string text, string compare) - { - return text == compare || - (string.IsNullOrWhiteSpace(text) && string.IsNullOrWhiteSpace(compare)) || - string.Equals(Normalize(text), compare, StringComparison.InvariantCultureIgnoreCase); - } + private static bool Equals(string text, string compare) + { + return text == compare || + (string.IsNullOrWhiteSpace(text) && string.IsNullOrWhiteSpace(compare)) || + string.Equals(Normalize(text), compare, StringComparison.InvariantCultureIgnoreCase); + } - private static string Normalize(string text) + private static string Normalize(string text) + { + if (string.IsNullOrWhiteSpace(text)) { - if (string.IsNullOrWhiteSpace(text)) - { - return text; - } - return _normalizeTextRegEx.Replace(text, string.Empty); + return text; } + return _normalizeTextRegEx.Replace(text, string.Empty); } } diff --git a/bitwarden_license/src/Sso/Utilities/DiscoveryResponseGenerator.cs b/bitwarden_license/src/Sso/Utilities/DiscoveryResponseGenerator.cs index 2aecd6f13..7a7f56963 100644 --- a/bitwarden_license/src/Sso/Utilities/DiscoveryResponseGenerator.cs +++ b/bitwarden_license/src/Sso/Utilities/DiscoveryResponseGenerator.cs @@ -1,39 +1,35 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Bit.Core.Settings; +using Bit.Core.Settings; using Bit.Core.Utilities; using IdentityServer4.Configuration; using IdentityServer4.Services; using IdentityServer4.Stores; using IdentityServer4.Validation; -using Microsoft.Extensions.Logging; -namespace Bit.Sso.Utilities +namespace Bit.Sso.Utilities; + +public class DiscoveryResponseGenerator : IdentityServer4.ResponseHandling.DiscoveryResponseGenerator { - public class DiscoveryResponseGenerator : IdentityServer4.ResponseHandling.DiscoveryResponseGenerator + private readonly GlobalSettings _globalSettings; + + public DiscoveryResponseGenerator( + IdentityServerOptions options, + IResourceStore resourceStore, + IKeyMaterialService keys, + ExtensionGrantValidator extensionGrants, + ISecretsListParser secretParsers, + IResourceOwnerPasswordValidator resourceOwnerValidator, + ILogger logger, + GlobalSettings globalSettings) + : base(options, resourceStore, keys, extensionGrants, secretParsers, resourceOwnerValidator, logger) { - private readonly GlobalSettings _globalSettings; + _globalSettings = globalSettings; + } - public DiscoveryResponseGenerator( - IdentityServerOptions options, - IResourceStore resourceStore, - IKeyMaterialService keys, - ExtensionGrantValidator extensionGrants, - ISecretsListParser secretParsers, - IResourceOwnerPasswordValidator resourceOwnerValidator, - ILogger logger, - GlobalSettings globalSettings) - : base(options, resourceStore, keys, extensionGrants, secretParsers, resourceOwnerValidator, logger) - { - _globalSettings = globalSettings; - } - - public override async Task> CreateDiscoveryDocumentAsync( - string baseUrl, string issuerUri) - { - var dict = await base.CreateDiscoveryDocumentAsync(baseUrl, issuerUri); - return CoreHelpers.AdjustIdentityServerConfig(dict, _globalSettings.BaseServiceUri.Sso, - _globalSettings.BaseServiceUri.InternalSso); - } + public override async Task> CreateDiscoveryDocumentAsync( + string baseUrl, string issuerUri) + { + var dict = await base.CreateDiscoveryDocumentAsync(baseUrl, issuerUri); + return CoreHelpers.AdjustIdentityServerConfig(dict, _globalSettings.BaseServiceUri.Sso, + _globalSettings.BaseServiceUri.InternalSso); } } diff --git a/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationScheme.cs b/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationScheme.cs index 5dd4669b9..96a316bc6 100644 --- a/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationScheme.cs +++ b/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationScheme.cs @@ -1,93 +1,89 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Bit.Core.Enums; +using Bit.Core.Enums; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Sustainsys.Saml2.AspNetCore2; -namespace Bit.Sso.Utilities +namespace Bit.Sso.Utilities; + +public class DynamicAuthenticationScheme : AuthenticationScheme, IDynamicAuthenticationScheme { - public class DynamicAuthenticationScheme : AuthenticationScheme, IDynamicAuthenticationScheme + public DynamicAuthenticationScheme(string name, string displayName, Type handlerType, + AuthenticationSchemeOptions options) + : base(name, displayName, handlerType) { - public DynamicAuthenticationScheme(string name, string displayName, Type handlerType, - AuthenticationSchemeOptions options) - : base(name, displayName, handlerType) - { - Options = options; - } - public DynamicAuthenticationScheme(string name, string displayName, Type handlerType, - AuthenticationSchemeOptions options, SsoType ssoType) - : this(name, displayName, handlerType, options) - { - SsoType = ssoType; - } + Options = options; + } + public DynamicAuthenticationScheme(string name, string displayName, Type handlerType, + AuthenticationSchemeOptions options, SsoType ssoType) + : this(name, displayName, handlerType, options) + { + SsoType = ssoType; + } - public AuthenticationSchemeOptions Options { get; set; } - public SsoType SsoType { get; set; } + public AuthenticationSchemeOptions Options { get; set; } + public SsoType SsoType { get; set; } - public async Task Validate() + public async Task Validate() + { + switch (SsoType) { - switch (SsoType) - { - case SsoType.OpenIdConnect: - await ValidateOpenIdConnectAsync(); - break; - case SsoType.Saml2: - ValidateSaml(); - break; - default: - break; - } + case SsoType.OpenIdConnect: + await ValidateOpenIdConnectAsync(); + break; + case SsoType.Saml2: + ValidateSaml(); + break; + default: + break; } + } - private void ValidateSaml() + private void ValidateSaml() + { + if (SsoType != SsoType.Saml2) { - if (SsoType != SsoType.Saml2) - { - return; - } - if (!(Options is Saml2Options samlOptions)) - { - throw new Exception("InvalidAuthenticationOptionsForSaml2SchemeError"); - } - samlOptions.Validate(Name); + return; } - - private async Task ValidateOpenIdConnectAsync() + if (!(Options is Saml2Options samlOptions)) { - if (SsoType != SsoType.OpenIdConnect) + throw new Exception("InvalidAuthenticationOptionsForSaml2SchemeError"); + } + samlOptions.Validate(Name); + } + + private async Task ValidateOpenIdConnectAsync() + { + if (SsoType != SsoType.OpenIdConnect) + { + return; + } + if (!(Options is OpenIdConnectOptions oidcOptions)) + { + throw new Exception("InvalidAuthenticationOptionsForOidcSchemeError"); + } + oidcOptions.Validate(); + if (oidcOptions.Configuration == null) + { + if (oidcOptions.ConfigurationManager == null) { - return; - } - if (!(Options is OpenIdConnectOptions oidcOptions)) - { - throw new Exception("InvalidAuthenticationOptionsForOidcSchemeError"); - } - oidcOptions.Validate(); - if (oidcOptions.Configuration == null) - { - if (oidcOptions.ConfigurationManager == null) - { - throw new Exception("PostConfigurationNotExecutedError"); - } - if (oidcOptions.Configuration == null) - { - try - { - oidcOptions.Configuration = await oidcOptions.ConfigurationManager - .GetConfigurationAsync(CancellationToken.None); - } - catch (Exception ex) - { - throw new Exception("ReadingOpenIdConnectMetadataFailedError", ex); - } - } + throw new Exception("PostConfigurationNotExecutedError"); } if (oidcOptions.Configuration == null) { - throw new Exception("NoOpenIdConnectMetadataError"); + try + { + oidcOptions.Configuration = await oidcOptions.ConfigurationManager + .GetConfigurationAsync(CancellationToken.None); + } + catch (Exception ex) + { + throw new Exception("ReadingOpenIdConnectMetadataFailedError", ex); + } } } + if (oidcOptions.Configuration == null) + { + throw new Exception("NoOpenIdConnectMetadataError"); + } } } diff --git a/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationSchemeProvider.cs b/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationSchemeProvider.cs index 7220e12a9..b02e83ded 100644 --- a/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationSchemeProvider.cs +++ b/bitwarden_license/src/Sso/Utilities/DynamicAuthenticationSchemeProvider.cs @@ -1,16 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography.X509Certificates; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; +using System.Security.Cryptography.X509Certificates; +using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Models.Data; -using Bit.Core.Models.Table; using Bit.Core.Repositories; -using Bit.Core.Utilities; using Bit.Core.Settings; +using Bit.Core.Utilities; using Bit.Sso.Models; using Bit.Sso.Utilities; using IdentityModel; @@ -18,454 +12,446 @@ using IdentityServer4; using IdentityServer4.Infrastructure; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using Sustainsys.Saml2.AspNetCore2; using Sustainsys.Saml2.Configuration; using Sustainsys.Saml2.Saml2P; -using U2F.Core.Utils; -namespace Bit.Core.Business.Sso +namespace Bit.Core.Business.Sso; + +public class DynamicAuthenticationSchemeProvider : AuthenticationSchemeProvider { - public class DynamicAuthenticationSchemeProvider : AuthenticationSchemeProvider + private readonly IPostConfigureOptions _oidcPostConfigureOptions; + private readonly IExtendedOptionsMonitorCache _extendedOidcOptionsMonitorCache; + private readonly IPostConfigureOptions _saml2PostConfigureOptions; + private readonly IExtendedOptionsMonitorCache _extendedSaml2OptionsMonitorCache; + private readonly ISsoConfigRepository _ssoConfigRepository; + private readonly ILogger _logger; + private readonly GlobalSettings _globalSettings; + private readonly SamlEnvironment _samlEnvironment; + private readonly TimeSpan _schemeCacheLifetime; + private readonly Dictionary _cachedSchemes; + private readonly Dictionary _cachedHandlerSchemes; + private readonly SemaphoreSlim _semaphore; + private readonly IHttpContextAccessor _httpContextAccessor; + + private DateTime? _lastSchemeLoad; + private IEnumerable _schemesCopy = Array.Empty(); + private IEnumerable _handlerSchemesCopy = Array.Empty(); + + public DynamicAuthenticationSchemeProvider( + IOptions options, + IPostConfigureOptions oidcPostConfigureOptions, + IOptionsMonitorCache oidcOptionsMonitorCache, + IPostConfigureOptions saml2PostConfigureOptions, + IOptionsMonitorCache saml2OptionsMonitorCache, + ISsoConfigRepository ssoConfigRepository, + ILogger logger, + GlobalSettings globalSettings, + SamlEnvironment samlEnvironment, + IHttpContextAccessor httpContextAccessor) + : base(options) { - private readonly IPostConfigureOptions _oidcPostConfigureOptions; - private readonly IExtendedOptionsMonitorCache _extendedOidcOptionsMonitorCache; - private readonly IPostConfigureOptions _saml2PostConfigureOptions; - private readonly IExtendedOptionsMonitorCache _extendedSaml2OptionsMonitorCache; - private readonly ISsoConfigRepository _ssoConfigRepository; - private readonly ILogger _logger; - private readonly GlobalSettings _globalSettings; - private readonly SamlEnvironment _samlEnvironment; - private readonly TimeSpan _schemeCacheLifetime; - private readonly Dictionary _cachedSchemes; - private readonly Dictionary _cachedHandlerSchemes; - private readonly SemaphoreSlim _semaphore; - private readonly IHttpContextAccessor _httpContextAccessor; - - private DateTime? _lastSchemeLoad; - private IEnumerable _schemesCopy = Array.Empty(); - private IEnumerable _handlerSchemesCopy = Array.Empty(); - - public DynamicAuthenticationSchemeProvider( - IOptions options, - IPostConfigureOptions oidcPostConfigureOptions, - IOptionsMonitorCache oidcOptionsMonitorCache, - IPostConfigureOptions saml2PostConfigureOptions, - IOptionsMonitorCache saml2OptionsMonitorCache, - ISsoConfigRepository ssoConfigRepository, - ILogger logger, - GlobalSettings globalSettings, - SamlEnvironment samlEnvironment, - IHttpContextAccessor httpContextAccessor) - : base(options) + _oidcPostConfigureOptions = oidcPostConfigureOptions; + _extendedOidcOptionsMonitorCache = oidcOptionsMonitorCache as + IExtendedOptionsMonitorCache; + if (_extendedOidcOptionsMonitorCache == null) { - _oidcPostConfigureOptions = oidcPostConfigureOptions; - _extendedOidcOptionsMonitorCache = oidcOptionsMonitorCache as - IExtendedOptionsMonitorCache; - if (_extendedOidcOptionsMonitorCache == null) - { - throw new ArgumentNullException("_extendedOidcOptionsMonitorCache could not be resolved."); - } - - _saml2PostConfigureOptions = saml2PostConfigureOptions; - _extendedSaml2OptionsMonitorCache = saml2OptionsMonitorCache as - IExtendedOptionsMonitorCache; - if (_extendedSaml2OptionsMonitorCache == null) - { - throw new ArgumentNullException("_extendedSaml2OptionsMonitorCache could not be resolved."); - } - - _ssoConfigRepository = ssoConfigRepository; - _logger = logger; - _globalSettings = globalSettings; - _schemeCacheLifetime = TimeSpan.FromSeconds(_globalSettings.Sso?.CacheLifetimeInSeconds ?? 30); - _samlEnvironment = samlEnvironment; - _cachedSchemes = new Dictionary(); - _cachedHandlerSchemes = new Dictionary(); - _semaphore = new SemaphoreSlim(1); - _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); + throw new ArgumentNullException("_extendedOidcOptionsMonitorCache could not be resolved."); } - private bool CacheIsValid + _saml2PostConfigureOptions = saml2PostConfigureOptions; + _extendedSaml2OptionsMonitorCache = saml2OptionsMonitorCache as + IExtendedOptionsMonitorCache; + if (_extendedSaml2OptionsMonitorCache == null) { - get => _lastSchemeLoad.HasValue - && _lastSchemeLoad.Value.Add(_schemeCacheLifetime) >= DateTime.UtcNow; + throw new ArgumentNullException("_extendedSaml2OptionsMonitorCache could not be resolved."); } - public override async Task GetSchemeAsync(string name) + _ssoConfigRepository = ssoConfigRepository; + _logger = logger; + _globalSettings = globalSettings; + _schemeCacheLifetime = TimeSpan.FromSeconds(_globalSettings.Sso?.CacheLifetimeInSeconds ?? 30); + _samlEnvironment = samlEnvironment; + _cachedSchemes = new Dictionary(); + _cachedHandlerSchemes = new Dictionary(); + _semaphore = new SemaphoreSlim(1); + _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); + } + + private bool CacheIsValid + { + get => _lastSchemeLoad.HasValue + && _lastSchemeLoad.Value.Add(_schemeCacheLifetime) >= DateTime.UtcNow; + } + + public override async Task GetSchemeAsync(string name) + { + var scheme = await base.GetSchemeAsync(name); + if (scheme != null) { - var scheme = await base.GetSchemeAsync(name); - if (scheme != null) - { - return scheme; - } - - try - { - var dynamicScheme = await GetDynamicSchemeAsync(name); - return dynamicScheme; - } - catch (Exception ex) - { - _logger.LogError(ex, "Unable to load a dynamic authentication scheme for '{0}'", name); - } - - return null; - } - - public override async Task> GetAllSchemesAsync() - { - var existingSchemes = await base.GetAllSchemesAsync(); - var schemes = new List(); - schemes.AddRange(existingSchemes); - - await LoadAllDynamicSchemesIntoCacheAsync(); - schemes.AddRange(_schemesCopy); - - return schemes.ToArray(); - } - - public override async Task> GetRequestHandlerSchemesAsync() - { - var existingSchemes = await base.GetRequestHandlerSchemesAsync(); - var schemes = new List(); - schemes.AddRange(existingSchemes); - - await LoadAllDynamicSchemesIntoCacheAsync(); - schemes.AddRange(_handlerSchemesCopy); - - return schemes.ToArray(); - } - - private async Task LoadAllDynamicSchemesIntoCacheAsync() - { - if (CacheIsValid) - { - // Our cache hasn't expired or been invalidated, ignore request - return; - } - await _semaphore.WaitAsync(); - try - { - if (CacheIsValid) - { - // Just in case (double-checked locking pattern) - return; - } - - // Save time just in case the following operation takes longer - var now = DateTime.UtcNow; - var newSchemes = await _ssoConfigRepository.GetManyByRevisionNotBeforeDate(_lastSchemeLoad); - - foreach (var config in newSchemes) - { - DynamicAuthenticationScheme scheme; - try - { - scheme = GetSchemeFromSsoConfig(config); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error converting configuration to scheme for '{0}'", config.Id); - continue; - } - if (scheme == null) - { - continue; - } - SetSchemeInCache(scheme); - } - - if (newSchemes.Any()) - { - // Maintain "safe" copy for use in enumeration routines - _schemesCopy = _cachedSchemes.Values.ToArray(); - _handlerSchemesCopy = _cachedHandlerSchemes.Values.ToArray(); - } - _lastSchemeLoad = now; - } - finally - { - _semaphore.Release(); - } - } - - private DynamicAuthenticationScheme SetSchemeInCache(DynamicAuthenticationScheme scheme) - { - if (!PostConfigureDynamicScheme(scheme)) - { - return null; - } - _cachedSchemes[scheme.Name] = scheme; - if (typeof(IAuthenticationRequestHandler).IsAssignableFrom(scheme.HandlerType)) - { - _cachedHandlerSchemes[scheme.Name] = scheme; - } return scheme; } - private async Task GetDynamicSchemeAsync(string name) + try { - if (_cachedSchemes.TryGetValue(name, out var cachedScheme)) + var dynamicScheme = await GetDynamicSchemeAsync(name); + return dynamicScheme; + } + catch (Exception ex) + { + _logger.LogError(ex, "Unable to load a dynamic authentication scheme for '{0}'", name); + } + + return null; + } + + public override async Task> GetAllSchemesAsync() + { + var existingSchemes = await base.GetAllSchemesAsync(); + var schemes = new List(); + schemes.AddRange(existingSchemes); + + await LoadAllDynamicSchemesIntoCacheAsync(); + schemes.AddRange(_schemesCopy); + + return schemes.ToArray(); + } + + public override async Task> GetRequestHandlerSchemesAsync() + { + var existingSchemes = await base.GetRequestHandlerSchemesAsync(); + var schemes = new List(); + schemes.AddRange(existingSchemes); + + await LoadAllDynamicSchemesIntoCacheAsync(); + schemes.AddRange(_handlerSchemesCopy); + + return schemes.ToArray(); + } + + private async Task LoadAllDynamicSchemesIntoCacheAsync() + { + if (CacheIsValid) + { + // Our cache hasn't expired or been invalidated, ignore request + return; + } + await _semaphore.WaitAsync(); + try + { + if (CacheIsValid) { - return cachedScheme; + // Just in case (double-checked locking pattern) + return; } - var scheme = await GetSchemeFromSsoConfigAsync(name); + // Save time just in case the following operation takes longer + var now = DateTime.UtcNow; + var newSchemes = await _ssoConfigRepository.GetManyByRevisionNotBeforeDate(_lastSchemeLoad); + + foreach (var config in newSchemes) + { + DynamicAuthenticationScheme scheme; + try + { + scheme = GetSchemeFromSsoConfig(config); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error converting configuration to scheme for '{0}'", config.Id); + continue; + } + if (scheme == null) + { + continue; + } + SetSchemeInCache(scheme); + } + + if (newSchemes.Any()) + { + // Maintain "safe" copy for use in enumeration routines + _schemesCopy = _cachedSchemes.Values.ToArray(); + _handlerSchemesCopy = _cachedHandlerSchemes.Values.ToArray(); + } + _lastSchemeLoad = now; + } + finally + { + _semaphore.Release(); + } + } + + private DynamicAuthenticationScheme SetSchemeInCache(DynamicAuthenticationScheme scheme) + { + if (!PostConfigureDynamicScheme(scheme)) + { + return null; + } + _cachedSchemes[scheme.Name] = scheme; + if (typeof(IAuthenticationRequestHandler).IsAssignableFrom(scheme.HandlerType)) + { + _cachedHandlerSchemes[scheme.Name] = scheme; + } + return scheme; + } + + private async Task GetDynamicSchemeAsync(string name) + { + if (_cachedSchemes.TryGetValue(name, out var cachedScheme)) + { + return cachedScheme; + } + + var scheme = await GetSchemeFromSsoConfigAsync(name); + if (scheme == null) + { + return null; + } + + await _semaphore.WaitAsync(); + try + { + scheme = SetSchemeInCache(scheme); if (scheme == null) { return null; } - await _semaphore.WaitAsync(); - try + if (typeof(IAuthenticationRequestHandler).IsAssignableFrom(scheme.HandlerType)) { - scheme = SetSchemeInCache(scheme); - if (scheme == null) - { - return null; - } + _handlerSchemesCopy = _cachedHandlerSchemes.Values.ToArray(); + } + _schemesCopy = _cachedSchemes.Values.ToArray(); + } + finally + { + // Note: _lastSchemeLoad is not set here, this is a one-off + // and should not impact loading further cache updates + _semaphore.Release(); + } + return scheme; + } - if (typeof(IAuthenticationRequestHandler).IsAssignableFrom(scheme.HandlerType)) - { - _handlerSchemesCopy = _cachedHandlerSchemes.Values.ToArray(); - } - _schemesCopy = _cachedSchemes.Values.ToArray(); - } - finally + private bool PostConfigureDynamicScheme(DynamicAuthenticationScheme scheme) + { + try + { + if (scheme.SsoType == SsoType.OpenIdConnect && scheme.Options is OpenIdConnectOptions oidcOptions) { - // Note: _lastSchemeLoad is not set here, this is a one-off - // and should not impact loading further cache updates - _semaphore.Release(); + _oidcPostConfigureOptions.PostConfigure(scheme.Name, oidcOptions); + _extendedOidcOptionsMonitorCache.AddOrUpdate(scheme.Name, oidcOptions); } - return scheme; + else if (scheme.SsoType == SsoType.Saml2 && scheme.Options is Saml2Options saml2Options) + { + _saml2PostConfigureOptions.PostConfigure(scheme.Name, saml2Options); + _extendedSaml2OptionsMonitorCache.AddOrUpdate(scheme.Name, saml2Options); + } + return true; + } + catch (Exception ex) + { + _logger.LogError(ex, "Error performing post configuration for '{0}' ({1})", + scheme.Name, scheme.DisplayName); + } + return false; + } + + private DynamicAuthenticationScheme GetSchemeFromSsoConfig(SsoConfig config) + { + var data = config.GetData(); + return data.ConfigType switch + { + SsoType.OpenIdConnect => GetOidcAuthenticationScheme(config.OrganizationId.ToString(), data), + SsoType.Saml2 => GetSaml2AuthenticationScheme(config.OrganizationId.ToString(), data), + _ => throw new Exception($"SSO Config Type, '{data.ConfigType}', not supported"), + }; + } + + private async Task GetSchemeFromSsoConfigAsync(string name) + { + if (!Guid.TryParse(name, out var organizationId)) + { + _logger.LogWarning("Could not determine organization id from name, '{0}'", name); + return null; + } + var ssoConfig = await _ssoConfigRepository.GetByOrganizationIdAsync(organizationId); + if (ssoConfig == null || !ssoConfig.Enabled) + { + _logger.LogWarning("Could not find SSO config or config was not enabled for '{0}'", name); + return null; } - private bool PostConfigureDynamicScheme(DynamicAuthenticationScheme scheme) + return GetSchemeFromSsoConfig(ssoConfig); + } + + private DynamicAuthenticationScheme GetOidcAuthenticationScheme(string name, SsoConfigurationData config) + { + var oidcOptions = new OpenIdConnectOptions { - try + Authority = config.Authority, + ClientId = config.ClientId, + ClientSecret = config.ClientSecret, + ResponseType = "code", + ResponseMode = "form_post", + SignInScheme = AuthenticationSchemes.BitwardenExternalCookieAuthenticationScheme, + SignOutScheme = IdentityServerConstants.SignoutScheme, + SaveTokens = false, // reduce overall request size + TokenValidationParameters = new TokenValidationParameters { - if (scheme.SsoType == SsoType.OpenIdConnect && scheme.Options is OpenIdConnectOptions oidcOptions) - { - _oidcPostConfigureOptions.PostConfigure(scheme.Name, oidcOptions); - _extendedOidcOptionsMonitorCache.AddOrUpdate(scheme.Name, oidcOptions); - } - else if (scheme.SsoType == SsoType.Saml2 && scheme.Options is Saml2Options saml2Options) - { - _saml2PostConfigureOptions.PostConfigure(scheme.Name, saml2Options); - _extendedSaml2OptionsMonitorCache.AddOrUpdate(scheme.Name, saml2Options); - } - return true; - } - catch (Exception ex) - { - _logger.LogError(ex, "Error performing post configuration for '{0}' ({1})", - scheme.Name, scheme.DisplayName); - } - return false; + NameClaimType = JwtClaimTypes.Name, + RoleClaimType = JwtClaimTypes.Role, + }, + CallbackPath = SsoConfigurationData.BuildCallbackPath(), + SignedOutCallbackPath = SsoConfigurationData.BuildSignedOutCallbackPath(), + MetadataAddress = config.MetadataAddress, + // Prevents URLs that go beyond 1024 characters which may break for some servers + AuthenticationMethod = config.RedirectBehavior, + GetClaimsFromUserInfoEndpoint = config.GetClaimsFromUserInfoEndpoint, + }; + oidcOptions.Scope + .AddIfNotExists(OpenIdConnectScopes.OpenId) + .AddIfNotExists(OpenIdConnectScopes.Email) + .AddIfNotExists(OpenIdConnectScopes.Profile); + foreach (var scope in config.GetAdditionalScopes()) + { + oidcOptions.Scope.AddIfNotExists(scope); + } + if (!string.IsNullOrWhiteSpace(config.ExpectedReturnAcrValue)) + { + oidcOptions.Scope.AddIfNotExists(OpenIdConnectScopes.Acr); } - private DynamicAuthenticationScheme GetSchemeFromSsoConfig(SsoConfig config) + oidcOptions.StateDataFormat = new DistributedCacheStateDataFormatter(_httpContextAccessor, name); + + // see: https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest (acr_values) + if (!string.IsNullOrWhiteSpace(config.AcrValues)) { - var data = config.GetData(); - return data.ConfigType switch + oidcOptions.Events ??= new OpenIdConnectEvents(); + oidcOptions.Events.OnRedirectToIdentityProvider = ctx => { - SsoType.OpenIdConnect => GetOidcAuthenticationScheme(config.OrganizationId.ToString(), data), - SsoType.Saml2 => GetSaml2AuthenticationScheme(config.OrganizationId.ToString(), data), - _ => throw new Exception($"SSO Config Type, '{data.ConfigType}', not supported"), + ctx.ProtocolMessage.AcrValues = config.AcrValues; + return Task.CompletedTask; }; } - private async Task GetSchemeFromSsoConfigAsync(string name) - { - if (!Guid.TryParse(name, out var organizationId)) - { - _logger.LogWarning("Could not determine organization id from name, '{0}'", name); - return null; - } - var ssoConfig = await _ssoConfigRepository.GetByOrganizationIdAsync(organizationId); - if (ssoConfig == null || !ssoConfig.Enabled) - { - _logger.LogWarning("Could not find SSO config or config was not enabled for '{0}'", name); - return null; - } + return new DynamicAuthenticationScheme(name, name, typeof(OpenIdConnectHandler), + oidcOptions, SsoType.OpenIdConnect); + } - return GetSchemeFromSsoConfig(ssoConfig); + private DynamicAuthenticationScheme GetSaml2AuthenticationScheme(string name, SsoConfigurationData config) + { + if (_samlEnvironment == null) + { + throw new Exception($"SSO SAML2 Service Provider profile is missing for {name}"); } - private DynamicAuthenticationScheme GetOidcAuthenticationScheme(string name, SsoConfigurationData config) + var spEntityId = new Sustainsys.Saml2.Metadata.EntityId( + SsoConfigurationData.BuildSaml2ModulePath(_globalSettings.BaseServiceUri.Sso)); + bool? allowCreate = null; + if (config.SpNameIdFormat != Saml2NameIdFormat.Transient) { - var oidcOptions = new OpenIdConnectOptions - { - Authority = config.Authority, - ClientId = config.ClientId, - ClientSecret = config.ClientSecret, - ResponseType = "code", - ResponseMode = "form_post", - SignInScheme = AuthenticationSchemes.BitwardenExternalCookieAuthenticationScheme, - SignOutScheme = IdentityServerConstants.SignoutScheme, - SaveTokens = false, // reduce overall request size - TokenValidationParameters = new TokenValidationParameters - { - NameClaimType = JwtClaimTypes.Name, - RoleClaimType = JwtClaimTypes.Role, - }, - CallbackPath = config.BuildCallbackPath(), - SignedOutCallbackPath = config.BuildSignedOutCallbackPath(), - MetadataAddress = config.MetadataAddress, - // Prevents URLs that go beyond 1024 characters which may break for some servers - AuthenticationMethod = config.RedirectBehavior, - GetClaimsFromUserInfoEndpoint = config.GetClaimsFromUserInfoEndpoint, - }; - oidcOptions.Scope - .AddIfNotExists(OpenIdConnectScopes.OpenId) - .AddIfNotExists(OpenIdConnectScopes.Email) - .AddIfNotExists(OpenIdConnectScopes.Profile); - foreach (var scope in config.GetAdditionalScopes()) - { - oidcOptions.Scope.AddIfNotExists(scope); - } - if (!string.IsNullOrWhiteSpace(config.ExpectedReturnAcrValue)) - { - oidcOptions.Scope.AddIfNotExists(OpenIdConnectScopes.Acr); - } - - oidcOptions.StateDataFormat = new DistributedCacheStateDataFormatter(_httpContextAccessor, name); - - // see: https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest (acr_values) - if (!string.IsNullOrWhiteSpace(config.AcrValues)) - { - oidcOptions.Events ??= new OpenIdConnectEvents(); - oidcOptions.Events.OnRedirectToIdentityProvider = ctx => - { - ctx.ProtocolMessage.AcrValues = config.AcrValues; - return Task.CompletedTask; - }; - } - - return new DynamicAuthenticationScheme(name, name, typeof(OpenIdConnectHandler), - oidcOptions, SsoType.OpenIdConnect); + allowCreate = true; + } + var spOptions = new SPOptions + { + EntityId = spEntityId, + ModulePath = SsoConfigurationData.BuildSaml2ModulePath(null, name), + NameIdPolicy = new Saml2NameIdPolicy(allowCreate, GetNameIdFormat(config.SpNameIdFormat)), + WantAssertionsSigned = config.SpWantAssertionsSigned, + AuthenticateRequestSigningBehavior = GetSigningBehavior(config.SpSigningBehavior), + ValidateCertificates = config.SpValidateCertificates, + }; + if (!string.IsNullOrWhiteSpace(config.SpMinIncomingSigningAlgorithm)) + { + spOptions.MinIncomingSigningAlgorithm = config.SpMinIncomingSigningAlgorithm; + } + if (!string.IsNullOrWhiteSpace(config.SpOutboundSigningAlgorithm)) + { + spOptions.OutboundSigningAlgorithm = config.SpOutboundSigningAlgorithm; + } + if (_samlEnvironment.SpSigningCertificate != null) + { + spOptions.ServiceCertificates.Add(_samlEnvironment.SpSigningCertificate); } - private DynamicAuthenticationScheme GetSaml2AuthenticationScheme(string name, SsoConfigurationData config) + var idpEntityId = new Sustainsys.Saml2.Metadata.EntityId(config.IdpEntityId); + var idp = new Sustainsys.Saml2.IdentityProvider(idpEntityId, spOptions) { - if (_samlEnvironment == null) - { - throw new Exception($"SSO SAML2 Service Provider profile is missing for {name}"); - } - - var spEntityId = new Sustainsys.Saml2.Metadata.EntityId( - config.BuildSaml2ModulePath(_globalSettings.BaseServiceUri.Sso)); - bool? allowCreate = null; - if (config.SpNameIdFormat != Saml2NameIdFormat.Transient) - { - allowCreate = true; - } - var spOptions = new SPOptions - { - EntityId = spEntityId, - ModulePath = config.BuildSaml2ModulePath(null, name), - NameIdPolicy = new Saml2NameIdPolicy(allowCreate, GetNameIdFormat(config.SpNameIdFormat)), - WantAssertionsSigned = config.SpWantAssertionsSigned, - AuthenticateRequestSigningBehavior = GetSigningBehavior(config.SpSigningBehavior), - ValidateCertificates = config.SpValidateCertificates, - }; - if (!string.IsNullOrWhiteSpace(config.SpMinIncomingSigningAlgorithm)) - { - spOptions.MinIncomingSigningAlgorithm = config.SpMinIncomingSigningAlgorithm; - } - if (!string.IsNullOrWhiteSpace(config.SpOutboundSigningAlgorithm)) - { - spOptions.OutboundSigningAlgorithm = config.SpOutboundSigningAlgorithm; - } - if (_samlEnvironment.SpSigningCertificate != null) - { - spOptions.ServiceCertificates.Add(_samlEnvironment.SpSigningCertificate); - } - - var idpEntityId = new Sustainsys.Saml2.Metadata.EntityId(config.IdpEntityId); - var idp = new Sustainsys.Saml2.IdentityProvider(idpEntityId, spOptions) - { - Binding = GetBindingType(config.IdpBindingType), - AllowUnsolicitedAuthnResponse = config.IdpAllowUnsolicitedAuthnResponse, - DisableOutboundLogoutRequests = config.IdpDisableOutboundLogoutRequests, - WantAuthnRequestsSigned = config.IdpWantAuthnRequestsSigned, - }; - if (!string.IsNullOrWhiteSpace(config.IdpSingleSignOnServiceUrl)) - { - idp.SingleSignOnServiceUrl = new Uri(config.IdpSingleSignOnServiceUrl); - } - if (!string.IsNullOrWhiteSpace(config.IdpSingleLogoutServiceUrl)) - { - idp.SingleLogoutServiceUrl = new Uri(config.IdpSingleLogoutServiceUrl); - } - if (!string.IsNullOrWhiteSpace(config.IdpArtifactResolutionServiceUrl)) - { - idp.ArtifactResolutionServiceUrls.TryAdd(0, new Uri(config.IdpArtifactResolutionServiceUrl)); - } - if (!string.IsNullOrWhiteSpace(config.IdpOutboundSigningAlgorithm)) - { - idp.OutboundSigningAlgorithm = config.IdpOutboundSigningAlgorithm; - } - if (!string.IsNullOrWhiteSpace(config.IdpX509PublicCert)) - { - var cert = config.IdpX509PublicCert.Base64StringToByteArray(); - idp.SigningKeys.AddConfiguredKey(new X509Certificate2(cert)); - } - // This must happen last since it calls Validate() internally. - idp.LoadMetadata = false; - - var options = new Saml2Options - { - SPOptions = spOptions, - SignInScheme = AuthenticationSchemes.BitwardenExternalCookieAuthenticationScheme, - SignOutScheme = IdentityServerConstants.DefaultCookieAuthenticationScheme, - CookieManager = new IdentityServer.DistributedCacheCookieManager(), - }; - options.IdentityProviders.Add(idp); - - return new DynamicAuthenticationScheme(name, name, typeof(Saml2Handler), options, SsoType.Saml2); - } - - private NameIdFormat GetNameIdFormat(Saml2NameIdFormat format) + Binding = GetBindingType(config.IdpBindingType), + AllowUnsolicitedAuthnResponse = config.IdpAllowUnsolicitedAuthnResponse, + DisableOutboundLogoutRequests = config.IdpDisableOutboundLogoutRequests, + WantAuthnRequestsSigned = config.IdpWantAuthnRequestsSigned, + }; + if (!string.IsNullOrWhiteSpace(config.IdpSingleSignOnServiceUrl)) { - return format switch - { - Saml2NameIdFormat.Unspecified => NameIdFormat.Unspecified, - Saml2NameIdFormat.EmailAddress => NameIdFormat.EmailAddress, - Saml2NameIdFormat.X509SubjectName => NameIdFormat.X509SubjectName, - Saml2NameIdFormat.WindowsDomainQualifiedName => NameIdFormat.WindowsDomainQualifiedName, - Saml2NameIdFormat.KerberosPrincipalName => NameIdFormat.KerberosPrincipalName, - Saml2NameIdFormat.EntityIdentifier => NameIdFormat.EntityIdentifier, - Saml2NameIdFormat.Persistent => NameIdFormat.Persistent, - Saml2NameIdFormat.Transient => NameIdFormat.Transient, - _ => NameIdFormat.NotConfigured, - }; + idp.SingleSignOnServiceUrl = new Uri(config.IdpSingleSignOnServiceUrl); } - - private SigningBehavior GetSigningBehavior(Saml2SigningBehavior behavior) + if (!string.IsNullOrWhiteSpace(config.IdpSingleLogoutServiceUrl)) { - return behavior switch - { - Saml2SigningBehavior.IfIdpWantAuthnRequestsSigned => SigningBehavior.IfIdpWantAuthnRequestsSigned, - Saml2SigningBehavior.Always => SigningBehavior.Always, - Saml2SigningBehavior.Never => SigningBehavior.Never, - _ => SigningBehavior.IfIdpWantAuthnRequestsSigned, - }; + idp.SingleLogoutServiceUrl = new Uri(config.IdpSingleLogoutServiceUrl); } - - private Sustainsys.Saml2.WebSso.Saml2BindingType GetBindingType(Saml2BindingType bindingType) + if (!string.IsNullOrWhiteSpace(config.IdpOutboundSigningAlgorithm)) { - return bindingType switch - { - Saml2BindingType.HttpRedirect => Sustainsys.Saml2.WebSso.Saml2BindingType.HttpRedirect, - Saml2BindingType.HttpPost => Sustainsys.Saml2.WebSso.Saml2BindingType.HttpPost, - Saml2BindingType.Artifact => Sustainsys.Saml2.WebSso.Saml2BindingType.Artifact, - _ => Sustainsys.Saml2.WebSso.Saml2BindingType.HttpPost, - }; + idp.OutboundSigningAlgorithm = config.IdpOutboundSigningAlgorithm; } + if (!string.IsNullOrWhiteSpace(config.IdpX509PublicCert)) + { + var cert = CoreHelpers.Base64UrlDecode(config.IdpX509PublicCert); + idp.SigningKeys.AddConfiguredKey(new X509Certificate2(cert)); + } + idp.ArtifactResolutionServiceUrls.Clear(); + // This must happen last since it calls Validate() internally. + idp.LoadMetadata = false; + + var options = new Saml2Options + { + SPOptions = spOptions, + SignInScheme = AuthenticationSchemes.BitwardenExternalCookieAuthenticationScheme, + SignOutScheme = IdentityServerConstants.DefaultCookieAuthenticationScheme, + CookieManager = new IdentityServer.DistributedCacheCookieManager(), + }; + options.IdentityProviders.Add(idp); + + return new DynamicAuthenticationScheme(name, name, typeof(Saml2Handler), options, SsoType.Saml2); + } + + private NameIdFormat GetNameIdFormat(Saml2NameIdFormat format) + { + return format switch + { + Saml2NameIdFormat.Unspecified => NameIdFormat.Unspecified, + Saml2NameIdFormat.EmailAddress => NameIdFormat.EmailAddress, + Saml2NameIdFormat.X509SubjectName => NameIdFormat.X509SubjectName, + Saml2NameIdFormat.WindowsDomainQualifiedName => NameIdFormat.WindowsDomainQualifiedName, + Saml2NameIdFormat.KerberosPrincipalName => NameIdFormat.KerberosPrincipalName, + Saml2NameIdFormat.EntityIdentifier => NameIdFormat.EntityIdentifier, + Saml2NameIdFormat.Persistent => NameIdFormat.Persistent, + Saml2NameIdFormat.Transient => NameIdFormat.Transient, + _ => NameIdFormat.NotConfigured, + }; + } + + private SigningBehavior GetSigningBehavior(Saml2SigningBehavior behavior) + { + return behavior switch + { + Saml2SigningBehavior.IfIdpWantAuthnRequestsSigned => SigningBehavior.IfIdpWantAuthnRequestsSigned, + Saml2SigningBehavior.Always => SigningBehavior.Always, + Saml2SigningBehavior.Never => SigningBehavior.Never, + _ => SigningBehavior.IfIdpWantAuthnRequestsSigned, + }; + } + + private Sustainsys.Saml2.WebSso.Saml2BindingType GetBindingType(Saml2BindingType bindingType) + { + return bindingType switch + { + Saml2BindingType.HttpRedirect => Sustainsys.Saml2.WebSso.Saml2BindingType.HttpRedirect, + Saml2BindingType.HttpPost => Sustainsys.Saml2.WebSso.Saml2BindingType.HttpPost, + _ => Sustainsys.Saml2.WebSso.Saml2BindingType.HttpPost, + }; } } diff --git a/bitwarden_license/src/Sso/Utilities/ExtendedOptionsMonitorCache.cs b/bitwarden_license/src/Sso/Utilities/ExtendedOptionsMonitorCache.cs index 6d657625d..083417f25 100644 --- a/bitwarden_license/src/Sso/Utilities/ExtendedOptionsMonitorCache.cs +++ b/bitwarden_license/src/Sso/Utilities/ExtendedOptionsMonitorCache.cs @@ -1,38 +1,36 @@ -using Microsoft.Extensions.Options; -using System; -using System.Collections.Concurrent; +using System.Collections.Concurrent; +using Microsoft.Extensions.Options; -namespace Bit.Sso.Utilities +namespace Bit.Sso.Utilities; + +public class ExtendedOptionsMonitorCache : IExtendedOptionsMonitorCache where TOptions : class { - public class ExtendedOptionsMonitorCache : IExtendedOptionsMonitorCache where TOptions : class + private readonly ConcurrentDictionary> _cache = + new ConcurrentDictionary>(StringComparer.Ordinal); + + public void AddOrUpdate(string name, TOptions options) { - private readonly ConcurrentDictionary> _cache = - new ConcurrentDictionary>(StringComparer.Ordinal); - - public void AddOrUpdate(string name, TOptions options) - { - _cache.AddOrUpdate(name ?? Options.DefaultName, new Lazy(() => options), - (string s, Lazy lazy) => new Lazy(() => options)); - } - - public void Clear() - { - _cache.Clear(); - } - - public TOptions GetOrAdd(string name, Func createOptions) - { - return _cache.GetOrAdd(name ?? Options.DefaultName, new Lazy(createOptions)).Value; - } - - public bool TryAdd(string name, TOptions options) - { - return _cache.TryAdd(name ?? Options.DefaultName, new Lazy(() => options)); - } - - public bool TryRemove(string name) - { - return _cache.TryRemove(name ?? Options.DefaultName, out _); - } + _cache.AddOrUpdate(name ?? Options.DefaultName, new Lazy(() => options), + (string s, Lazy lazy) => new Lazy(() => options)); } -} \ No newline at end of file + + public void Clear() + { + _cache.Clear(); + } + + public TOptions GetOrAdd(string name, Func createOptions) + { + return _cache.GetOrAdd(name ?? Options.DefaultName, new Lazy(createOptions)).Value; + } + + public bool TryAdd(string name, TOptions options) + { + return _cache.TryAdd(name ?? Options.DefaultName, new Lazy(() => options)); + } + + public bool TryRemove(string name) + { + return _cache.TryRemove(name ?? Options.DefaultName, out _); + } +} diff --git a/bitwarden_license/src/Sso/Utilities/IDynamicAuthenticationScheme.cs b/bitwarden_license/src/Sso/Utilities/IDynamicAuthenticationScheme.cs index ff3b257db..9ebd0f9cf 100644 --- a/bitwarden_license/src/Sso/Utilities/IDynamicAuthenticationScheme.cs +++ b/bitwarden_license/src/Sso/Utilities/IDynamicAuthenticationScheme.cs @@ -1,14 +1,12 @@ -using System.Threading.Tasks; -using Bit.Core.Enums; +using Bit.Core.Enums; using Microsoft.AspNetCore.Authentication; -namespace Bit.Sso.Utilities -{ - public interface IDynamicAuthenticationScheme - { - AuthenticationSchemeOptions Options { get; set; } - SsoType SsoType { get; set; } +namespace Bit.Sso.Utilities; - Task Validate(); - } +public interface IDynamicAuthenticationScheme +{ + AuthenticationSchemeOptions Options { get; set; } + SsoType SsoType { get; set; } + + Task Validate(); } diff --git a/bitwarden_license/src/Sso/Utilities/IExtendedOptionsMonitorCache.cs b/bitwarden_license/src/Sso/Utilities/IExtendedOptionsMonitorCache.cs index 6b039f559..0f6284318 100644 --- a/bitwarden_license/src/Sso/Utilities/IExtendedOptionsMonitorCache.cs +++ b/bitwarden_license/src/Sso/Utilities/IExtendedOptionsMonitorCache.cs @@ -1,9 +1,8 @@ using Microsoft.Extensions.Options; -namespace Bit.Sso.Utilities +namespace Bit.Sso.Utilities; + +public interface IExtendedOptionsMonitorCache : IOptionsMonitorCache where TOptions : class { - public interface IExtendedOptionsMonitorCache : IOptionsMonitorCache where TOptions : class - { - void AddOrUpdate(string name, TOptions options); - } -} \ No newline at end of file + void AddOrUpdate(string name, TOptions options); +} diff --git a/bitwarden_license/src/Sso/Utilities/OpenIdConnectOptionsExtensions.cs b/bitwarden_license/src/Sso/Utilities/OpenIdConnectOptionsExtensions.cs index 758629e75..9221877a0 100644 --- a/bitwarden_license/src/Sso/Utilities/OpenIdConnectOptionsExtensions.cs +++ b/bitwarden_license/src/Sso/Utilities/OpenIdConnectOptionsExtensions.cs @@ -1,68 +1,62 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.IdentityModel.Protocols.OpenIdConnect; -namespace Bit.Sso.Utilities +namespace Bit.Sso.Utilities; + +public static class OpenIdConnectOptionsExtensions { - public static class OpenIdConnectOptionsExtensions + public static async Task CouldHandleAsync(this OpenIdConnectOptions options, string scheme, HttpContext context) { - public static async Task CouldHandleAsync(this OpenIdConnectOptions options, string scheme, HttpContext context) + // Determine this is a valid request for our handler + if (options.CallbackPath != context.Request.Path && + options.RemoteSignOutPath != context.Request.Path && + options.SignedOutCallbackPath != context.Request.Path) { - // Determine this is a valid request for our handler - if (options.CallbackPath != context.Request.Path && - options.RemoteSignOutPath != context.Request.Path && - options.SignedOutCallbackPath != context.Request.Path) - { - return false; - } - - if (context.Request.Query["scheme"].FirstOrDefault() == scheme) - { - return true; - } - - try - { - // Parse out the message - OpenIdConnectMessage message = null; - if (string.Equals(context.Request.Method, "GET", StringComparison.OrdinalIgnoreCase)) - { - message = new OpenIdConnectMessage(context.Request.Query.Select(pair => new KeyValuePair(pair.Key, pair.Value))); - } - else if (string.Equals(context.Request.Method, "POST", StringComparison.OrdinalIgnoreCase) && - !string.IsNullOrEmpty(context.Request.ContentType) && - context.Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) && - context.Request.Body.CanRead) - { - var form = await context.Request.ReadFormAsync(); - message = new OpenIdConnectMessage(form.Select(pair => new KeyValuePair(pair.Key, pair.Value))); - } - - var state = message?.State; - if (string.IsNullOrWhiteSpace(state)) - { - // State is required, it will fail later on for this reason. - return false; - } - - // Handle State if we've gotten that back - var decodedState = options.StateDataFormat.Unprotect(state); - if (decodedState != null && decodedState.Items.ContainsKey("scheme")) - { - return decodedState.Items["scheme"] == scheme; - } - } - catch - { - return false; - } - - // This is likely not an appropriate handler return false; } + + if (context.Request.Query["scheme"].FirstOrDefault() == scheme) + { + return true; + } + + try + { + // Parse out the message + OpenIdConnectMessage message = null; + if (string.Equals(context.Request.Method, "GET", StringComparison.OrdinalIgnoreCase)) + { + message = new OpenIdConnectMessage(context.Request.Query.Select(pair => new KeyValuePair(pair.Key, pair.Value))); + } + else if (string.Equals(context.Request.Method, "POST", StringComparison.OrdinalIgnoreCase) && + !string.IsNullOrEmpty(context.Request.ContentType) && + context.Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) && + context.Request.Body.CanRead) + { + var form = await context.Request.ReadFormAsync(); + message = new OpenIdConnectMessage(form.Select(pair => new KeyValuePair(pair.Key, pair.Value))); + } + + var state = message?.State; + if (string.IsNullOrWhiteSpace(state)) + { + // State is required, it will fail later on for this reason. + return false; + } + + // Handle State if we've gotten that back + var decodedState = options.StateDataFormat.Unprotect(state); + if (decodedState != null && decodedState.Items.ContainsKey("scheme")) + { + return decodedState.Items["scheme"] == scheme; + } + } + catch + { + return false; + } + + // This is likely not an appropriate handler + return false; } } diff --git a/bitwarden_license/src/Sso/Utilities/OpenIdConnectScopes.cs b/bitwarden_license/src/Sso/Utilities/OpenIdConnectScopes.cs index 983ce8b33..3fae7ce4e 100644 --- a/bitwarden_license/src/Sso/Utilities/OpenIdConnectScopes.cs +++ b/bitwarden_license/src/Sso/Utilities/OpenIdConnectScopes.cs @@ -1,64 +1,63 @@ -namespace Bit.Sso.Utilities +namespace Bit.Sso.Utilities; + +/// +/// OpenID Connect Clients use scope values as defined in 3.3 of OAuth 2.0 +/// [RFC6749]. These values represent the standard scope values supported +/// by OAuth 2.0 and therefore OIDC. +/// +/// +/// See: https://openid.net/specs/openid-connect-basic-1_0.html#Scopes +/// +public static class OpenIdConnectScopes { /// - /// OpenID Connect Clients use scope values as defined in 3.3 of OAuth 2.0 - /// [RFC6749]. These values represent the standard scope values supported - /// by OAuth 2.0 and therefore OIDC. + /// REQUIRED. Informs the Authorization Server that the Client is making + /// an OpenID Connect request. If the openid scope value is not present, + /// the behavior is entirely unspecified. + /// + public const string OpenId = "openid"; + + /// + /// OPTIONAL. This scope value requests access to the End-User's default + /// profile Claims, which are: name, family_name, given_name, + /// middle_name, nickname, preferred_username, profile, picture, + /// website, gender, birthdate, zoneinfo, locale, and updated_at. + /// + public const string Profile = "profile"; + + /// + /// OPTIONAL. This scope value requests access to the email and + /// email_verified Claims. + /// + public const string Email = "email"; + + /// + /// OPTIONAL. This scope value requests access to the address Claim. + /// + public const string Address = "address"; + + /// + /// OPTIONAL. This scope value requests access to the phone_number and + /// phone_number_verified Claims. + /// + public const string Phone = "phone"; + + /// + /// OPTIONAL. This scope value requests that an OAuth 2.0 Refresh Token + /// be issued that can be used to obtain an Access Token that grants + /// access to the End-User's UserInfo Endpoint even when the End-User is + /// not present (not logged in). + /// + public const string OfflineAccess = "offline_access"; + + /// + /// OPTIONAL. Authentication Context Class Reference. String specifying + /// an Authentication Context Class Reference value that identifies the + /// Authentication Context Class that the authentication performed + /// satisfied. /// /// - /// See: https://openid.net/specs/openid-connect-basic-1_0.html#Scopes + /// See: https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.2 /// - public static class OpenIdConnectScopes - { - /// - /// REQUIRED. Informs the Authorization Server that the Client is making - /// an OpenID Connect request. If the openid scope value is not present, - /// the behavior is entirely unspecified. - /// - public const string OpenId = "openid"; - - /// - /// OPTIONAL. This scope value requests access to the End-User's default - /// profile Claims, which are: name, family_name, given_name, - /// middle_name, nickname, preferred_username, profile, picture, - /// website, gender, birthdate, zoneinfo, locale, and updated_at. - /// - public const string Profile = "profile"; - - /// - /// OPTIONAL. This scope value requests access to the email and - /// email_verified Claims. - /// - public const string Email = "email"; - - /// - /// OPTIONAL. This scope value requests access to the address Claim. - /// - public const string Address = "address"; - - /// - /// OPTIONAL. This scope value requests access to the phone_number and - /// phone_number_verified Claims. - /// - public const string Phone = "phone"; - - /// - /// OPTIONAL. This scope value requests that an OAuth 2.0 Refresh Token - /// be issued that can be used to obtain an Access Token that grants - /// access to the End-User's UserInfo Endpoint even when the End-User is - /// not present (not logged in). - /// - public const string OfflineAccess = "offline_access"; - - /// - /// OPTIONAL. Authentication Context Class Reference. String specifying - /// an Authentication Context Class Reference value that identifies the - /// Authentication Context Class that the authentication performed - /// satisfied. - /// - /// - /// See: https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.2 - /// - public const string Acr = "acr"; - } + public const string Acr = "acr"; } diff --git a/bitwarden_license/src/Sso/Utilities/Saml2OptionsExtensions.cs b/bitwarden_license/src/Sso/Utilities/Saml2OptionsExtensions.cs index d13efd70b..46a75ca5c 100644 --- a/bitwarden_license/src/Sso/Utilities/Saml2OptionsExtensions.cs +++ b/bitwarden_license/src/Sso/Utilities/Saml2OptionsExtensions.cs @@ -1,110 +1,104 @@ -using System; -using System.IO; -using System.IO.Compression; -using System.Linq; +using System.IO.Compression; using System.Text; -using System.Threading.Tasks; using System.Xml; -using Microsoft.AspNetCore.Http; using Sustainsys.Saml2; using Sustainsys.Saml2.AspNetCore2; -namespace Bit.Sso.Utilities +namespace Bit.Sso.Utilities; + +public static class Saml2OptionsExtensions { - public static class Saml2OptionsExtensions + public static async Task CouldHandleAsync(this Saml2Options options, string scheme, HttpContext context) { - public static async Task CouldHandleAsync(this Saml2Options options, string scheme, HttpContext context) + // Determine this is a valid request for our handler + if (!context.Request.Path.StartsWithSegments(options.SPOptions.ModulePath, StringComparison.Ordinal)) { - // Determine this is a valid request for our handler - if (!context.Request.Path.StartsWithSegments(options.SPOptions.ModulePath, StringComparison.Ordinal)) - { - return false; - } + return false; + } - var idp = options.IdentityProviders.IsEmpty ? null : options.IdentityProviders.Default; - if (idp == null) - { - return false; - } - - if (context.Request.Query["scheme"].FirstOrDefault() == scheme) - { - return true; - } - - // We need to pull out and parse the response or request SAML envelope - XmlElement envelope = null; - try - { - if (string.Equals(context.Request.Method, "POST", StringComparison.OrdinalIgnoreCase) && - context.Request.HasFormContentType) - { - string encodedMessage; - if (context.Request.Form.TryGetValue("SAMLResponse", out var response)) - { - encodedMessage = response.FirstOrDefault(); - } - else - { - encodedMessage = context.Request.Form["SAMLRequest"]; - } - if (string.IsNullOrWhiteSpace(encodedMessage)) - { - return false; - } - envelope = XmlHelpers.XmlDocumentFromString( - Encoding.UTF8.GetString(Convert.FromBase64String(encodedMessage)))?.DocumentElement; - } - else if (string.Equals(context.Request.Method, "GET", StringComparison.OrdinalIgnoreCase)) - { - var encodedPayload = context.Request.Query["SAMLRequest"].FirstOrDefault() ?? - context.Request.Query["SAMLResponse"].FirstOrDefault(); - try - { - var payload = Convert.FromBase64String(encodedPayload); - using var compressed = new MemoryStream(payload); - using var decompressedStream = new DeflateStream(compressed, CompressionMode.Decompress, true); - using var deCompressed = new MemoryStream(); - await decompressedStream.CopyToAsync(deCompressed); - - envelope = XmlHelpers.XmlDocumentFromString( - Encoding.UTF8.GetString(deCompressed.GetBuffer(), 0, (int)deCompressed.Length))?.DocumentElement; - } - catch (FormatException ex) - { - throw new FormatException($"\'{encodedPayload}\' is not a valid Base64 encoded string: {ex.Message}", ex); - } - } - } - catch - { - return false; - } - - if (envelope == null) - { - return false; - } - - // Double check the entity Ids - var entityId = envelope["Issuer", Saml2Namespaces.Saml2Name]?.InnerText.Trim(); - if (!string.Equals(entityId, idp.EntityId.Id, StringComparison.InvariantCultureIgnoreCase)) - { - return false; - } - - if (options.SPOptions.WantAssertionsSigned) - { - var assertion = envelope["Assertion", Saml2Namespaces.Saml2Name]; - var isAssertionSigned = assertion != null && XmlHelpers.IsSignedByAny(assertion, idp.SigningKeys, - options.SPOptions.ValidateCertificates, options.SPOptions.MinIncomingSigningAlgorithm); - if (!isAssertionSigned) - { - throw new Exception("Cannot verify SAML assertion signature."); - } - } + var idp = options.IdentityProviders.IsEmpty ? null : options.IdentityProviders.Default; + if (idp == null) + { + return false; + } + if (context.Request.Query["scheme"].FirstOrDefault() == scheme) + { return true; } + + // We need to pull out and parse the response or request SAML envelope + XmlElement envelope = null; + try + { + if (string.Equals(context.Request.Method, "POST", StringComparison.OrdinalIgnoreCase) && + context.Request.HasFormContentType) + { + string encodedMessage; + if (context.Request.Form.TryGetValue("SAMLResponse", out var response)) + { + encodedMessage = response.FirstOrDefault(); + } + else + { + encodedMessage = context.Request.Form["SAMLRequest"]; + } + if (string.IsNullOrWhiteSpace(encodedMessage)) + { + return false; + } + envelope = XmlHelpers.XmlDocumentFromString( + Encoding.UTF8.GetString(Convert.FromBase64String(encodedMessage)))?.DocumentElement; + } + else if (string.Equals(context.Request.Method, "GET", StringComparison.OrdinalIgnoreCase)) + { + var encodedPayload = context.Request.Query["SAMLRequest"].FirstOrDefault() ?? + context.Request.Query["SAMLResponse"].FirstOrDefault(); + try + { + var payload = Convert.FromBase64String(encodedPayload); + using var compressed = new MemoryStream(payload); + using var decompressedStream = new DeflateStream(compressed, CompressionMode.Decompress, true); + using var deCompressed = new MemoryStream(); + await decompressedStream.CopyToAsync(deCompressed); + + envelope = XmlHelpers.XmlDocumentFromString( + Encoding.UTF8.GetString(deCompressed.GetBuffer(), 0, (int)deCompressed.Length))?.DocumentElement; + } + catch (FormatException ex) + { + throw new FormatException($"\'{encodedPayload}\' is not a valid Base64 encoded string: {ex.Message}", ex); + } + } + } + catch + { + return false; + } + + if (envelope == null) + { + return false; + } + + // Double check the entity Ids + var entityId = envelope["Issuer", Saml2Namespaces.Saml2Name]?.InnerText.Trim(); + if (!string.Equals(entityId, idp.EntityId.Id, StringComparison.InvariantCultureIgnoreCase)) + { + return false; + } + + if (options.SPOptions.WantAssertionsSigned) + { + var assertion = envelope["Assertion", Saml2Namespaces.Saml2Name]; + var isAssertionSigned = assertion != null && XmlHelpers.IsSignedByAny(assertion, idp.SigningKeys, + options.SPOptions.ValidateCertificates, options.SPOptions.MinIncomingSigningAlgorithm); + if (!isAssertionSigned) + { + throw new Exception("Cannot verify SAML assertion signature."); + } + } + + return true; } } diff --git a/bitwarden_license/src/Sso/Utilities/SamlClaimTypes.cs b/bitwarden_license/src/Sso/Utilities/SamlClaimTypes.cs index f62f5b04b..2f314c7ef 100644 --- a/bitwarden_license/src/Sso/Utilities/SamlClaimTypes.cs +++ b/bitwarden_license/src/Sso/Utilities/SamlClaimTypes.cs @@ -1,12 +1,11 @@ -namespace Bit.Sso.Utilities +namespace Bit.Sso.Utilities; + +public static class SamlClaimTypes { - public static class SamlClaimTypes - { - public const string Email = "urn:oid:0.9.2342.19200300.100.1.3"; - public const string GivenName = "urn:oid:2.5.4.42"; - public const string Surname = "urn:oid:2.5.4.4"; - public const string DisplayName = "urn:oid:2.16.840.1.113730.3.1.241"; - public const string CommonName = "urn:oid:2.5.4.3"; - public const string UserId = "urn:oid:0.9.2342.19200300.100.1.1"; - } + public const string Email = "urn:oid:0.9.2342.19200300.100.1.3"; + public const string GivenName = "urn:oid:2.5.4.42"; + public const string Surname = "urn:oid:2.5.4.4"; + public const string DisplayName = "urn:oid:2.16.840.1.113730.3.1.241"; + public const string CommonName = "urn:oid:2.5.4.3"; + public const string UserId = "urn:oid:0.9.2342.19200300.100.1.1"; } diff --git a/bitwarden_license/src/Sso/Utilities/SamlNameIdFormats.cs b/bitwarden_license/src/Sso/Utilities/SamlNameIdFormats.cs index 18ccc140f..94c03bd64 100644 --- a/bitwarden_license/src/Sso/Utilities/SamlNameIdFormats.cs +++ b/bitwarden_license/src/Sso/Utilities/SamlNameIdFormats.cs @@ -1,18 +1,17 @@ -namespace Bit.Sso.Utilities +namespace Bit.Sso.Utilities; + +public static class SamlNameIdFormats { - public static class SamlNameIdFormats - { - // Common - public const string Unspecified = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"; - public const string Email = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"; - public const string Persistent = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"; - public const string Transient = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"; - // Not-so-common - public const string Upn = "http://schemas.xmlsoap.org/claims/UPN"; - public const string CommonName = "http://schemas.xmlsoap.org/claims/CommonName"; - public const string X509SubjectName = "urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName"; - public const string WindowsQualifiedDomainName = "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName"; - public const string KerberosPrincipalName = "urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos"; - public const string EntityIdentifier = "urn:oasis:names:tc:SAML:2.0:nameid-format:entity"; - } + // Common + public const string Unspecified = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"; + public const string Email = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"; + public const string Persistent = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"; + public const string Transient = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"; + // Not-so-common + public const string Upn = "http://schemas.xmlsoap.org/claims/UPN"; + public const string CommonName = "http://schemas.xmlsoap.org/claims/CommonName"; + public const string X509SubjectName = "urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName"; + public const string WindowsQualifiedDomainName = "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName"; + public const string KerberosPrincipalName = "urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos"; + public const string EntityIdentifier = "urn:oasis:names:tc:SAML:2.0:nameid-format:entity"; } diff --git a/bitwarden_license/src/Sso/Utilities/SamlPropertyKeys.cs b/bitwarden_license/src/Sso/Utilities/SamlPropertyKeys.cs index 21d599b7f..7be7fb4f6 100644 --- a/bitwarden_license/src/Sso/Utilities/SamlPropertyKeys.cs +++ b/bitwarden_license/src/Sso/Utilities/SamlPropertyKeys.cs @@ -1,7 +1,6 @@ -namespace Bit.Sso.Utilities +namespace Bit.Sso.Utilities; + +public static class SamlPropertyKeys { - public static class SamlPropertyKeys - { - public const string ClaimFormat = "http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"; - } + public const string ClaimFormat = "http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"; } diff --git a/bitwarden_license/src/Sso/Utilities/ServiceCollectionExtensions.cs b/bitwarden_license/src/Sso/Utilities/ServiceCollectionExtensions.cs index 89a545c53..cd4aa707d 100644 --- a/bitwarden_license/src/Sso/Utilities/ServiceCollectionExtensions.cs +++ b/bitwarden_license/src/Sso/Utilities/ServiceCollectionExtensions.cs @@ -1,82 +1,77 @@ -using System; -using System.Collections.Generic; -using Bit.Core.Business.Sso; -using Bit.Core.IdentityServer; -using Bit.Core.Utilities; +using Bit.Core.Business.Sso; using Bit.Core.Settings; +using Bit.Core.Utilities; +using Bit.SharedWeb.Utilities; +using Bit.Sso.IdentityServer; using Bit.Sso.Models; using IdentityServer4.Models; using IdentityServer4.ResponseHandling; using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Sustainsys.Saml2.AspNetCore2; -namespace Bit.Sso.Utilities +namespace Bit.Sso.Utilities; + +public static class ServiceCollectionExtensions { - public static class ServiceCollectionExtensions + public static IServiceCollection AddSsoServices(this IServiceCollection services, + GlobalSettings globalSettings) { - public static IServiceCollection AddSsoServices(this IServiceCollection services, - GlobalSettings globalSettings) + // SAML SP Configuration + var samlEnvironment = new SamlEnvironment { - // SAML SP Configuration - var samlEnvironment = new SamlEnvironment + SpSigningCertificate = CoreHelpers.GetIdentityServerCertificate(globalSettings), + }; + services.AddSingleton(s => samlEnvironment); + + services.AddSingleton(); + // Oidc + services.AddSingleton, + OpenIdConnectPostConfigureOptions>(); + services.AddSingleton, + ExtendedOptionsMonitorCache>(); + // Saml2 + services.AddSingleton, + PostConfigureSaml2Options>(); + services.AddSingleton, + ExtendedOptionsMonitorCache>(); + + return services; + } + + public static IIdentityServerBuilder AddSsoIdentityServerServices(this IServiceCollection services, + IWebHostEnvironment env, GlobalSettings globalSettings) + { + services.AddTransient(); + + var issuerUri = new Uri(globalSettings.BaseServiceUri.InternalSso); + var identityServerBuilder = services + .AddIdentityServer(options => { - SpSigningCertificate = CoreHelpers.GetIdentityServerCertificate(globalSettings), - }; - services.AddSingleton(s => samlEnvironment); - - services.AddSingleton(); - // Oidc - services.AddSingleton, - OpenIdConnectPostConfigureOptions>(); - services.AddSingleton, - ExtendedOptionsMonitorCache>(); - // Saml2 - services.AddSingleton, - PostConfigureSaml2Options>(); - services.AddSingleton, - ExtendedOptionsMonitorCache>(); - - return services; - } - - public static IIdentityServerBuilder AddSsoIdentityServerServices(this IServiceCollection services, - IWebHostEnvironment env, GlobalSettings globalSettings) - { - services.AddTransient(); - - var issuerUri = new Uri(globalSettings.BaseServiceUri.InternalSso); - var identityServerBuilder = services - .AddIdentityServer(options => + options.IssuerUri = $"{issuerUri.Scheme}://{issuerUri.Host}"; + if (env.IsDevelopment()) { - options.IssuerUri = $"{issuerUri.Scheme}://{issuerUri.Host}"; - if (env.IsDevelopment()) - { - options.Authentication.CookieSameSiteMode = Microsoft.AspNetCore.Http.SameSiteMode.Unspecified; - } - else - { - options.UserInteraction.ErrorUrl = "/Error"; - options.UserInteraction.ErrorIdParameter = "errorId"; - } - options.InputLengthRestrictions.UserName = 256; - }) - .AddInMemoryCaching() - .AddInMemoryClients(new List + options.Authentication.CookieSameSiteMode = Microsoft.AspNetCore.Http.SameSiteMode.Unspecified; + } + else { - new OidcIdentityClient(globalSettings) - }) - .AddInMemoryIdentityResources(new List - { - new IdentityResources.OpenId(), - new IdentityResources.Profile() - }) - .AddIdentityServerCertificate(env, globalSettings); + options.UserInteraction.ErrorUrl = "/Error"; + options.UserInteraction.ErrorIdParameter = "errorId"; + } + options.InputLengthRestrictions.UserName = 256; + }) + .AddInMemoryCaching() + .AddInMemoryClients(new List + { + new OidcIdentityClient(globalSettings) + }) + .AddInMemoryIdentityResources(new List + { + new IdentityResources.OpenId(), + new IdentityResources.Profile() + }) + .AddIdentityServerCertificate(env, globalSettings); - return identityServerBuilder; - } + return identityServerBuilder; } } diff --git a/bitwarden_license/src/Sso/Utilities/SsoAuthenticationMiddleware.cs b/bitwarden_license/src/Sso/Utilities/SsoAuthenticationMiddleware.cs index 04b636cb6..9dca7a690 100644 --- a/bitwarden_license/src/Sso/Utilities/SsoAuthenticationMiddleware.cs +++ b/bitwarden_license/src/Sso/Utilities/SsoAuthenticationMiddleware.cs @@ -1,83 +1,84 @@ -using System; -using System.Threading.Tasks; -using Bit.Core.Enums; +using Bit.Core.Enums; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; using Sustainsys.Saml2.AspNetCore2; -namespace Bit.Sso.Utilities +namespace Bit.Sso.Utilities; + +public class SsoAuthenticationMiddleware { - public class SsoAuthenticationMiddleware + private readonly RequestDelegate _next; + + public SsoAuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemes) { - private readonly RequestDelegate _next; - - public SsoAuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemes) + _next = next ?? throw new ArgumentNullException(nameof(next)); + Schemes = schemes ?? throw new ArgumentNullException(nameof(schemes)); + } + + public IAuthenticationSchemeProvider Schemes { get; set; } + + public async Task Invoke(HttpContext context) + { + if ((context.Request.Method == "GET" && context.Request.Query.ContainsKey("SAMLart")) + || (context.Request.Method == "POST" && context.Request.Form.ContainsKey("SAMLart"))) { - _next = next ?? throw new ArgumentNullException(nameof(next)); - Schemes = schemes ?? throw new ArgumentNullException(nameof(schemes)); + throw new Exception("SAMLart parameter detected. SAML Artifact binding is not allowed."); } - public IAuthenticationSchemeProvider Schemes { get; set; } - - public async Task Invoke(HttpContext context) + context.Features.Set(new AuthenticationFeature { - context.Features.Set(new AuthenticationFeature - { - OriginalPath = context.Request.Path, - OriginalPathBase = context.Request.PathBase - }); + OriginalPath = context.Request.Path, + OriginalPathBase = context.Request.PathBase + }); - // Give any IAuthenticationRequestHandler schemes a chance to handle the request - var handlers = context.RequestServices.GetRequiredService(); - foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) + // Give any IAuthenticationRequestHandler schemes a chance to handle the request + var handlers = context.RequestServices.GetRequiredService(); + foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) + { + // Determine if scheme is appropriate for the current context FIRST + if (scheme is IDynamicAuthenticationScheme dynamicScheme) { - // Determine if scheme is appropriate for the current context FIRST - if (scheme is IDynamicAuthenticationScheme dynamicScheme) + switch (dynamicScheme.SsoType) { - switch (dynamicScheme.SsoType) - { - case SsoType.OpenIdConnect: - default: - if (dynamicScheme.Options is OpenIdConnectOptions oidcOptions && - !await oidcOptions.CouldHandleAsync(scheme.Name, context)) - { - // It's OIDC and Dynamic, but not a good fit - continue; - } - break; - case SsoType.Saml2: - if (dynamicScheme.Options is Saml2Options samlOptions && - !await samlOptions.CouldHandleAsync(scheme.Name, context)) - { - // It's SAML and Dynamic, but not a good fit - continue; - } - break; - } - } - - // This far it's not dynamic OR it is but "could" be handled - if (await handlers.GetHandlerAsync(context, scheme.Name) is IAuthenticationRequestHandler handler && - await handler.HandleRequestAsync()) - { - return; + case SsoType.OpenIdConnect: + default: + if (dynamicScheme.Options is OpenIdConnectOptions oidcOptions && + !await oidcOptions.CouldHandleAsync(scheme.Name, context)) + { + // It's OIDC and Dynamic, but not a good fit + continue; + } + break; + case SsoType.Saml2: + if (dynamicScheme.Options is Saml2Options samlOptions && + !await samlOptions.CouldHandleAsync(scheme.Name, context)) + { + // It's SAML and Dynamic, but not a good fit + continue; + } + break; } } - // Fallback to the default scheme from the provider - var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync(); - if (defaultAuthenticate != null) + // This far it's not dynamic OR it is but "could" be handled + if (await handlers.GetHandlerAsync(context, scheme.Name) is IAuthenticationRequestHandler handler && + await handler.HandleRequestAsync()) { - var result = await context.AuthenticateAsync(defaultAuthenticate.Name); - if (result?.Principal != null) - { - context.User = result.Principal; - } + return; } - - await _next(context); } + + // Fallback to the default scheme from the provider + var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync(); + if (defaultAuthenticate != null) + { + var result = await context.AuthenticateAsync(defaultAuthenticate.Name); + if (result?.Principal != null) + { + context.User = result.Principal; + } + } + + await _next(context); } } diff --git a/bitwarden_license/src/Sso/Views/Shared/Error.cshtml b/bitwarden_license/src/Sso/Views/Shared/Error.cshtml index 6bd879fe3..cdce82948 100644 --- a/bitwarden_license/src/Sso/Views/Shared/Error.cshtml +++ b/bitwarden_license/src/Sso/Views/Shared/Error.cshtml @@ -7,11 +7,15 @@

@i18nService.T("Error")@(string.IsNullOrWhiteSpace(Model?.Message) ? null : $": {Model.Message}")

@if (!string.IsNullOrWhiteSpace(Model?.RedirectUri)) { -

@Html.Raw(i18nService.T("SsoErrorWithRedirect", Model?.RedirectUri)) @Model?.Description

+

@Html.Raw(i18nService.T("SsoErrorWithRedirect", Model?.RedirectUri))

} else { -

@i18nService.T("SsoError") @Model?.Description

+

@i18nService.T("SsoError")

+} +@if (!string.IsNullOrWhiteSpace(Model?.Description)) +{ +

@Model?.Description

} @if (!string.IsNullOrWhiteSpace(Model?.RequestId)) { diff --git a/bitwarden_license/src/Sso/Views/Shared/_Layout.cshtml b/bitwarden_license/src/Sso/Views/Shared/_Layout.cshtml index 4467f08f2..ae7511942 100644 --- a/bitwarden_license/src/Sso/Views/Shared/_Layout.cshtml +++ b/bitwarden_license/src/Sso/Views/Shared/_Layout.cshtml @@ -1,4 +1,4 @@ -@using static Bit.Core.Utilities.CoreHelpers; +@using static Bit.Core.Utilities.AssemblyHelpers; diff --git a/bitwarden_license/src/Sso/appsettings.Development.json b/bitwarden_license/src/Sso/appsettings.Development.json index efe36471f..d45377822 100644 --- a/bitwarden_license/src/Sso/appsettings.Development.json +++ b/bitwarden_license/src/Sso/appsettings.Development.json @@ -11,8 +11,9 @@ "internalAdmin": "http://localhost:62911", "internalIdentity": "http://localhost:33656", "internalApi": "http://localhost:4000", - "internalVault": "http://localhost:4001", - "internalSso": "http://localhost:51822" + "internalVault": "https://localhost:8080", + "internalSso": "http://localhost:51822", + "internalScim": "http://localhost:44559" }, "events": { "connectionString": "UseDevelopmentStorage=true" diff --git a/bitwarden_license/src/Sso/appsettings.Production.json b/bitwarden_license/src/Sso/appsettings.Production.json index 54786119f..d2009cb3b 100644 --- a/bitwarden_license/src/Sso/appsettings.Production.json +++ b/bitwarden_license/src/Sso/appsettings.Production.json @@ -12,7 +12,8 @@ "internalIdentity": "https://identity.bitwarden.com", "internalApi": "https://api.bitwarden.com", "internalVault": "https://vault.bitwarden.com", - "internalSso": "https://sso.bitwarden.com" + "internalSso": "https://sso.bitwarden.com", + "internalScim": "https://scim.bitwarden.com" }, "braintree": { "production": true diff --git a/bitwarden_license/src/Sso/appsettings.QA.json b/bitwarden_license/src/Sso/appsettings.QA.json index e2a020c07..b1d71196c 100644 --- a/bitwarden_license/src/Sso/appsettings.QA.json +++ b/bitwarden_license/src/Sso/appsettings.QA.json @@ -12,7 +12,8 @@ "internalIdentity": "https://identity.qa.bitwarden.pw", "internalApi": "https://api.qa.bitwarden.pw", "internalVault": "https://vault.qa.bitwarden.pw", - "internalSso": "https://sso.qa.bitwarden.pw" + "internalSso": "https://sso.qa.bitwarden.pw", + "internalScim": "https://scim.qa.bitwarden.pw" }, "braintree": { "production": false diff --git a/bitwarden_license/src/Sso/appsettings.SelfHosted.json b/bitwarden_license/src/Sso/appsettings.SelfHosted.json index 0fab07f9f..37faf24b5 100644 --- a/bitwarden_license/src/Sso/appsettings.SelfHosted.json +++ b/bitwarden_license/src/Sso/appsettings.SelfHosted.json @@ -12,7 +12,8 @@ "internalIdentity": null, "internalApi": null, "internalVault": null, - "internalSso": null + "internalSso": null, + "internalScim": null } } } diff --git a/bitwarden_license/src/Sso/appsettings.json b/bitwarden_license/src/Sso/appsettings.json index 7e1d1be5e..3bf02cd86 100644 --- a/bitwarden_license/src/Sso/appsettings.json +++ b/bitwarden_license/src/Sso/appsettings.json @@ -3,7 +3,9 @@ "selfHosted": false, "siteName": "Bitwarden", "projectName": "SSO", - "stripeApiKey": "SECRET", + "stripe": { + "apiKey": "SECRET" + }, "oidcIdentityClientKey": "SECRET", "sqlServer": { "connectionString": "SECRET" diff --git a/bitwarden_license/src/Sso/build.ps1 b/bitwarden_license/src/Sso/build.ps1 index fec3977fc..c60942d72 100644 --- a/bitwarden_license/src/Sso/build.ps1 +++ b/bitwarden_license/src/Sso/build.ps1 @@ -11,8 +11,8 @@ echo "Clean" dotnet clean $dir\Sso.csproj -c "Release" -o $dir\obj\Azure\publish echo "Node Build" cd $dir -npm install +npm ci +npm run build cd $curDir -gulp --gulpfile $dir\gulpfile.js build echo "Publish" dotnet publish $dir\Sso.csproj -c "Release" -o $dir\obj\Azure\publish diff --git a/bitwarden_license/src/Sso/build.sh b/bitwarden_license/src/Sso/build.sh index bff940261..4796de010 100755 --- a/bitwarden_license/src/Sso/build.sh +++ b/bitwarden_license/src/Sso/build.sh @@ -14,8 +14,8 @@ echo "Clean" dotnet clean "$DIR/Sso.csproj" -c "Release" -o "$DIR/obj/build-output/publish" echo "Node Build" cd "$DIR" -npm install +npm ci +npm run build cd "$CUR_DIR" -gulp --gulpfile "$DIR/gulpfile.js" build echo "Publish" dotnet publish "$DIR/Sso.csproj" -c "Release" -o "$DIR/obj/build-output/publish" diff --git a/bitwarden_license/src/Sso/gulpfile.js b/bitwarden_license/src/Sso/gulpfile.js index 4d24f475d..fd1f74346 100644 --- a/bitwarden_license/src/Sso/gulpfile.js +++ b/bitwarden_license/src/Sso/gulpfile.js @@ -2,7 +2,7 @@ const gulp = require('gulp'); const merge = require('merge-stream'); -const sass = require('gulp-sass'); +const sass = require('gulp-sass')(require("sass")); const del = require('del'); const paths = {}; diff --git a/bitwarden_license/src/Sso/newrelic.config b/bitwarden_license/src/Sso/newrelic.config deleted file mode 100644 index 7ed805d30..000000000 --- a/bitwarden_license/src/Sso/newrelic.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/bitwarden_license/src/Sso/package-lock.json b/bitwarden_license/src/Sso/package-lock.json index dd76dc134..3df2f9237 100644 --- a/bitwarden_license/src/Sso/package-lock.json +++ b/bitwarden_license/src/Sso/package-lock.json @@ -1,63 +1,5107 @@ { "name": "bitwarden-sso", "version": "0.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "bitwarden-sso", + "version": "0.0.0", + "license": "-", + "devDependencies": { + "bootstrap": "4.5.0", + "del": "6.0.0", + "font-awesome": "4.7.0", + "gulp": "4.0.2", + "gulp-sass": "5.1.0", + "jquery": "3.5.1", + "merge-stream": "2.0.0", + "popper.js": "1.16.1", + "sass": "^1.49.7" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "dependencies": { + "ansi-wrap": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "dependencies": { + "ansi-wrap": "0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/anymatch/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/anymatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch/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/anymatch/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/anymatch/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/anymatch/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/anymatch/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/anymatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch/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/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "dependencies": { + "buffer-equal": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "dev": true, + "dependencies": { + "make-iterator": "^1.0.0" + }, + "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-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "dependencies": { + "make-iterator": "^1.0.0" + }, + "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": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "dependencies": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-initial/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "dependencies": { + "is-number": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-last/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "dependencies": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "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": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/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/base/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/base/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/base/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bootstrap": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.5.0.tgz", + "integrity": "sha512-Z93QoXvodoVslA+PWNdk23Hze4RBYIkpb5h8I2HY2Tu2h7A0LpAgLcyrhrSUyo2/Oxm2l1fRZPs1e5hnxnliXA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + }, + "peerDependencies": { + "jquery": "1.9.1 - 3", + "popper.js": "^1.16.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "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" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "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/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/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/chokidar/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "node_modules/cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "dependencies": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "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/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.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==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-props": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", + "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", + "dev": true, + "dependencies": { + "each-props": "^1.3.2", + "is-plain-object": "^5.0.0" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "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/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "dependencies": { + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "dev": true, + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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/each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, + "node_modules/each-props/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/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "dependencies": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "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-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "dev": true, + "dependencies": { + "type": "^2.5.0" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "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": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/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/extglob/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/extglob/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/extglob/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "dependencies": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", + "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==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "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/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/findup-sync/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/findup-sync/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/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/findup-sync/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/findup-sync/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/findup-sync/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/findup-sync/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/findup-sync/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/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/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fined/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/flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/font-awesome": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", + "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=", + "dev": true, + "engines": { + "node": ">=0.10.3" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "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/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/glob-stream/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/glob-stream/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "dependencies": { + "sparkles": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "dev": true + }, + "node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "dev": true, + "dependencies": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-sass": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-5.1.0.tgz", + "integrity": "sha512-7VT0uaF+VZCmkNBglfe1b34bxn/AfcssquLKVDYnCDJ3xNBaW7cUuI3p3BQmoKcoKFrs9jdzUxyb+u+NGfL4OQ==", + "dev": true, + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "picocolors": "^1.0.0", + "plugin-error": "^1.0.1", + "replace-ext": "^2.0.0", + "strip-ansi": "^6.0.1", + "vinyl-sourcemaps-apply": "^0.2.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "dependencies": { + "glogg": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "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-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "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": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", + "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", + "dev": true + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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/is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "node_modules/is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jquery": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz", + "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/just-debounce": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", + "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", + "dev": true + }, + "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/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/liftoff/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/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "node_modules/make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/make-iterator/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "dependencies": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/matchdep/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/matchdep/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/node_modules/findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/matchdep/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/matchdep/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/matchdep/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/matchdep/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/matchdep/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/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/matchdep/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/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/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/micromatch/node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/micromatch/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/micromatch/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "dev": true, + "optional": true + }, + "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/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/nanomatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/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/nanomatch/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/nanomatch/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/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/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true, + "engines": { + "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": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "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/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "dependencies": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.1" + } + }, + "node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "dependencies": { + "path-root-regex": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "dependencies": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/plugin-error/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/plugin-error/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/plugin-error/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/popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "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": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "dev": true + }, + "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/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/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg/node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "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/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/readdirp/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/readdirp/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp/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/readdirp/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/readdirp/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/readdirp/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/readdirp/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/readdirp/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp/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/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "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": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "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/remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "dependencies": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "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": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + }, + "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", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "dev": true + }, + "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", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "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/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/sass": { + "version": "1.49.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.7.tgz", + "integrity": "sha512-13dml55EMIR2rS4d/RDHHP0sXMY3+30e1TKsyXaSz3iLWVoDWEoboY8WzJd5JMnxrRHffKO3wq2mpJ0jxRJiEQ==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/sass/node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/sass/node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sass/node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sass/node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/sass/node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sass/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/sass/node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sass/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/sass/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/sass/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "dependencies": { + "sver-compat": "^1.5.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "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/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "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": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/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/snapdragon-node/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/snapdragon-node/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/snapdragon-node/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "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/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "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", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "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-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/sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, + "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": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "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/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "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/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/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "dependencies": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "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/through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "dependencies": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "node_modules/time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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" + } + }, + "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": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/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/to-regex/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "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-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/to-regex/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/to-regex/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/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/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "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-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "dependencies": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "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": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "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": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "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": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "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/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "dependencies": { + "source-map": "^0.5.1" + } + }, + "node_modules/vinyl/node_modules/replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, + "node_modules/yargs": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", + "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", + "dev": true, + "dependencies": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.1" + } + }, + "node_modules/yargs-parser": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", + "dev": true, + "dependencies": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + } + }, "dependencies": { "@nodelib/fs.scandir": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", - "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "requires": { - "@nodelib/fs.stat": "2.0.3", + "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true }, "@nodelib/fs.walk": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", - "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "requires": { - "@nodelib/fs.scandir": "2.1.3", + "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/node": { - "version": "14.6.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.2.tgz", - "integrity": "sha512-onlIwbaeqvZyniGPfdw/TEhKIh79pz66L1q06WUQqJLnAb6wbjvOtepLYTGHTqzdXgBYIE3ZdmqHDGsRsbBz7A==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, "aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -68,24 +5112,6 @@ "indent-string": "^4.0.0" } }, - "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, "ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", @@ -105,20 +5131,11 @@ } }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, "ansi-wrap": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", @@ -135,78 +5152,79 @@ "normalize-path": "^2.1.1" }, "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "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": { - "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" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "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": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "kind-of": "^6.0.0" } }, + "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-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-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" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -236,16 +5254,6 @@ "requires": { "remove-trailing-separator": "^1.0.1" } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } } } }, @@ -258,28 +5266,12 @@ "buffer-equal": "^1.0.0" } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -322,12 +5314,6 @@ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, "array-initial": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", @@ -378,14 +5364,6 @@ "default-compare": "^1.0.0", "get-value": "^2.0.6", "kind-of": "^5.0.2" - }, - "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 - } } }, "array-union": { @@ -400,21 +5378,6 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -439,12 +5402,6 @@ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "dev": true }, - "async-foreach": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", - "dev": true - }, "async-settle": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", @@ -454,30 +5411,12 @@ "async-done": "^1.2.2" } }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "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==", "dev": true }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", - "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", - "dev": true - }, "bach": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", @@ -496,9 +5435,9 @@ } }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "base": { @@ -553,18 +5492,15 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true } } }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, "binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", @@ -581,20 +5517,12 @@ "file-uri-to-path": "1.0.0" } }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "~2.0.0" - } - }, "bootstrap": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.5.0.tgz", "integrity": "sha512-Z93QoXvodoVslA+PWNdk23Hze4RBYIkpb5h8I2HY2Tu2h7A0LpAgLcyrhrSUyo2/Oxm2l1fRZPs1e5hnxnliXA==", - "dev": true + "dev": true, + "requires": {} }, "brace-expansion": { "version": "1.1.11", @@ -607,12 +5535,21 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "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" } }, "buffer-equal": { @@ -622,9 +5559,9 @@ "dev": true }, "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "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 }, "cache-base": { @@ -644,47 +5581,22 @@ "unset-value": "^1.0.0" } }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - } - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, "chokidar": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", @@ -705,45 +5617,6 @@ "upath": "^1.1.1" }, "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "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" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } - }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -764,34 +5637,6 @@ } } } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } } } }, @@ -805,17 +5650,6 @@ "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": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } } }, "clean-stack": { @@ -833,6 +5667,23 @@ "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } } }, "clone": { @@ -891,36 +5742,12 @@ "object-visit": "^1.0.0" } }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -945,16 +5772,10 @@ "typedarray": "^0.0.6" } }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "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==", "dev": true, "requires": { "safe-buffer": "~5.1.1" @@ -967,40 +5788,21 @@ "dev": true }, "copy-props": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", - "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", + "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", "dev": true, "requires": { - "each-props": "^1.3.0", - "is-plain-object": "^2.0.1" + "each-props": "^1.3.2", + "is-plain-object": "^5.0.0" } }, "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, - "cross-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", - "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -1011,15 +5813,6 @@ "type": "^1.0.1" } }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1048,14 +5841,6 @@ "dev": true, "requires": { "kind-of": "^5.0.2" - }, - "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 - } } }, "default-resolution": { @@ -1074,74 +5859,30 @@ } }, "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "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-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-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-descriptor": "^0.1.0" } }, "del": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/del/-/del-5.1.0.tgz", - "integrity": "sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", "dev": true, "requires": { - "globby": "^10.0.1", - "graceful-fs": "^4.2.2", + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", "is-glob": "^4.0.1", "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.1", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", "slash": "^3.0.0" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, "detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", @@ -1177,24 +5918,19 @@ "requires": { "is-plain-object": "^2.0.1", "object.defaults": "^1.1.0" + }, + "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" + } + } } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -1257,12 +5993,6 @@ "es6-symbol": "^3.1.1" } }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -1276,26 +6006,6 @@ "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": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } } }, "expand-tilde": { @@ -1308,18 +6018,18 @@ } }, "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", "dev": true, "requires": { - "type": "^2.0.0" + "type": "^2.5.0" }, "dependencies": { "type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==", "dev": true } } @@ -1331,24 +6041,12 @@ "dev": true }, "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "assign-symbols": "^1.0.0", - "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-extendable": "^0.1.0" } }, "extglob": { @@ -1376,15 +6074,6 @@ "is-descriptor": "^1.0.0" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", @@ -1413,15 +6102,15 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true } } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, "fancy-log": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", @@ -1434,32 +6123,19 @@ "time-stamp": "^1.0.0" } }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, "fast-glob": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", - "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", + "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" + "micromatch": "^4.0.4" } }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, "fast-levenshtein": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", @@ -1467,9 +6143,9 @@ "dev": true }, "fastq": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", - "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -1483,12 +6159,15 @@ "optional": true }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "to-regex-range": "^5.0.1" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" } }, "find-up": { @@ -1513,78 +6192,79 @@ "resolve-dir": "^1.0.1" }, "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "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": { - "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" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "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": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "kind-of": "^6.0.0" } }, + "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-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-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" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -1605,16 +6285,6 @@ "snapdragon": "^0.8.1", "to-regex": "^3.0.2" } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } } } }, @@ -1629,6 +6299,17 @@ "object.defaults": "^1.1.0", "object.pick": "^1.2.0", "parse-filepath": "^1.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" + } + } } }, "flagged-respawn": { @@ -1668,23 +6349,6 @@ "for-in": "^1.0.1" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -1721,71 +6385,28 @@ "nan": "^2.12.1" } }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "dependencies": { - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "requires": { - "globule": "^1.0.0" - } - }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } }, "get-value": { "version": "2.0.6", @@ -1793,19 +6414,10 @@ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -1817,9 +6429,9 @@ } }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" @@ -1904,32 +6516,19 @@ } }, "globby": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", - "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "requires": { - "@types/glob": "^7.1.1", "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", "slash": "^3.0.0" } }, - "globule": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", - "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", - "dev": true, - "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - } - }, "glogg": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", @@ -1940,9 +6539,9 @@ } }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", "dev": true }, "gulp": { @@ -1955,67 +6554,46 @@ "gulp-cli": "^2.2.0", "undertaker": "^1.2.1", "vinyl-fs": "^3.0.0" - }, - "dependencies": { - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - } - } + } + }, + "gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" } }, "gulp-sass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-4.0.1.tgz", - "integrity": "sha512-OMQEgWNggpog8Tc5v1MuI6eo+5iiPkVeLL76iBhDoEEScLUPfZlpvzmgTnLkpcqdrNodZxpz5qcv6mS2rulk3g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-5.1.0.tgz", + "integrity": "sha512-7VT0uaF+VZCmkNBglfe1b34bxn/AfcssquLKVDYnCDJ3xNBaW7cUuI3p3BQmoKcoKFrs9jdzUxyb+u+NGfL4OQ==", "dev": true, "requires": { - "chalk": "^2.3.0", - "lodash.clonedeep": "^4.3.2", - "node-sass": "^4.8.3", + "lodash.clonedeep": "^4.5.0", + "picocolors": "^1.0.0", "plugin-error": "^1.0.1", - "replace-ext": "^1.0.0", - "strip-ansi": "^4.0.0", - "through2": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } + "replace-ext": "^2.0.0", + "strip-ansi": "^6.0.1", + "vinyl-sourcemaps-apply": "^0.2.1" } }, "gulplog": { @@ -2027,47 +6605,19 @@ "glogg": "^1.0.0" } }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" + "function-bind": "^1.1.1" } }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true }, "has-value": { @@ -2091,26 +6641,6 @@ "kind-of": "^4.0.0" }, "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "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": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "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", @@ -2132,32 +6662,21 @@ } }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true }, - "in-publish": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz", - "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==", + "immutable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", + "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", "dev": true }, "indent-string": { @@ -2183,9 +6702,9 @@ "dev": true }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, "interpret": { @@ -2251,6 +6770,15 @@ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, + "is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -2280,14 +6808,6 @@ "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 - } } }, "is-extendable": { @@ -2302,12 +6822,6 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true - }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -2318,9 +6832,9 @@ } }, "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "requires": { "is-extglob": "^2.1.1" @@ -2333,10 +6847,24 @@ "dev": true }, "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "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": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } }, "is-path-cwd": { "version": "2.2.0", @@ -2345,19 +6873,16 @@ "dev": true }, "is-path-inside": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", - "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, "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" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true }, "is-relative": { "version": "1.0.0", @@ -2368,12 +6893,6 @@ "is-unc-path": "^1.0.0" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -2419,76 +6938,28 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, "jquery": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz", "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==", "dev": true }, - "js-base64": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", - "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", - "dev": true - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", + "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", "dev": true }, "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "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 }, "last-run": { @@ -2502,9 +6973,9 @@ } }, "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "dev": true, "requires": { "readable-stream": "^2.0.5" @@ -2542,6 +7013,17 @@ "object.map": "^1.0.0", "rechoir": "^0.6.2", "resolve": "^1.1.7" + }, + "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" + } + } } }, "load-json-file": { @@ -2557,56 +7039,12 @@ "strip-bom": "^2.0.0" } }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -2614,6 +7052,14 @@ "dev": true, "requires": { "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } } }, "map-cache": { @@ -2622,12 +7068,6 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -2649,56 +7089,24 @@ "stack-trace": "0.0.10" }, "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "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": { - "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" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" } }, "findup-sync": { @@ -2713,6 +7121,44 @@ "resolve-dir": "^1.0.1" } }, + "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-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-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-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-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", @@ -2722,26 +7168,21 @@ "is-extglob": "^2.1.0" } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "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": { - "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": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "isobject": "^3.0.1" } }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -2762,45 +7203,14 @@ "snapdragon": "^0.8.1", "to-regex": "^3.0.2" } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } } } }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - } - }, "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true }, "merge2": { "version": "1.4.1", @@ -2809,45 +7219,59 @@ "dev": true }, "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "requires": { "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "dev": true - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dev": true, - "requires": { - "mime-db": "1.44.0" + "picomatch": "^2.2.3" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } } }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", @@ -2866,18 +7290,18 @@ "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" + } } } }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -2891,10 +7315,11 @@ "dev": true }, "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "dev": true, + "optional": true }, "nanomatch": { "version": "1.2.13", @@ -2913,6 +7338,81 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" + }, + "dependencies": { + "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" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "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-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-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-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" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } } }, "next-tick": { @@ -2921,104 +7421,6 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, - "node-gyp": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", - "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", - "dev": true, - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - } - } - }, - "node-sass": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz", - "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==", - "dev": true, - "requires": { - "async-foreach": "^0.1.3", - "chalk": "^1.1.1", - "cross-spawn": "^3.0.0", - "gaze": "^1.0.0", - "get-stdin": "^4.0.1", - "glob": "^7.0.3", - "in-publish": "^2.0.0", - "lodash": "^4.17.15", - "meow": "^3.7.0", - "mkdirp": "^0.5.1", - "nan": "^2.13.2", - "node-gyp": "^3.8.0", - "npmlog": "^4.0.0", - "request": "^2.88.0", - "sass-graph": "2.2.5", - "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -3046,36 +7448,12 @@ "once": "^1.3.2" } }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, "object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", @@ -3087,15 +7465,6 @@ "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": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -3123,15 +7492,15 @@ } }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" } }, "object.defaults": { @@ -3193,12 +7562,6 @@ "readable-stream": "^2.0.1" } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", @@ -3208,55 +7571,15 @@ "lcid": "^1.0.0" } }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, "p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "requires": { "aggregate-error": "^3.0.0" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, "parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", @@ -3317,9 +7640,9 @@ "dev": true }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "path-root": { @@ -3343,16 +7666,16 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, "pify": { @@ -3386,6 +7709,36 @@ "arr-diff": "^4.0.0", "arr-union": "^3.1.0", "extend-shallow": "^3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "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" + } + } } }, "popper.js": { @@ -3412,18 +7765,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, "pump": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", @@ -3445,16 +7786,10 @@ "pump": "^2.0.0" } }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, "read-pkg": { @@ -3517,78 +7852,79 @@ "readable-stream": "^2.0.2" }, "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "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": { - "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" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "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": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "kind-of": "^6.0.0" } }, + "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-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-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" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -3609,16 +7945,6 @@ "snapdragon": "^0.8.1", "to-regex": "^3.0.2" } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } } } }, @@ -3631,27 +7957,6 @@ "resolve": "^1.1.6" } }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - }, - "dependencies": { - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - } - } - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -3660,6 +7965,36 @@ "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": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "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" + } + } } }, "remove-bom-buffer": { @@ -3690,9 +8025,9 @@ "dev": true }, "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "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": { @@ -3701,19 +8036,10 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", "dev": true }, "replace-homedir": { @@ -3727,34 +8053,6 @@ "remove-trailing-separator": "^1.1.0" } }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3768,12 +8066,14 @@ "dev": true }, "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dev": true, "requires": { - "path-parse": "^1.0.6" + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" } }, "resolve-dir": { @@ -3823,10 +8123,13 @@ } }, "run-parallel": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } }, "safe-buffer": { "version": "5.1.2", @@ -3843,164 +8146,105 @@ "ret": "~0.1.10" } }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "sass-graph": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", - "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", + "sass": { + "version": "1.49.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.7.tgz", + "integrity": "sha512-13dml55EMIR2rS4d/RDHHP0sXMY3+30e1TKsyXaSz3iLWVoDWEoboY8WzJd5JMnxrRHffKO3wq2mpJ0jxRJiEQ==", "dev": true, "requires": { - "glob": "^7.0.0", - "lodash": "^4.0.0", - "scss-tokenizer": "^0.2.3", - "yargs": "^13.3.2" + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "picomatch": "^2.2.1" } }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "scss-tokenizer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", - "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", - "dev": true, - "requires": { - "js-base64": "^2.1.8", - "source-map": "^0.4.2" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" + "is-number": "^7.0.0" } } } @@ -4038,23 +8282,17 @@ "split-string": "^3.0.1" }, "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "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": { - "is-extendable": "^0.1.0" + "isobject": "^3.0.1" } } } }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -4075,26 +8313,6 @@ "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": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } } }, "snapdragon-node": { @@ -4145,6 +8363,12 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true } } }, @@ -4174,6 +8398,12 @@ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, "source-map-resolve": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", @@ -4188,9 +8418,9 @@ } }, "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", "dev": true }, "sparkles": { @@ -4226,9 +8456,9 @@ } }, "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", "dev": true }, "split-string": { @@ -4238,23 +8468,36 @@ "dev": true, "requires": { "extend-shallow": "^3.0.0" - } - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "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" + } + } } }, "stack-trace": { @@ -4271,26 +8514,6 @@ "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": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stdout-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", - "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" } }, "stream-exhaust": { @@ -4305,17 +8528,6 @@ "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -4325,13 +8537,41 @@ "safe-buffer": "~5.1.0" } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" } }, "strip-bom": { @@ -4343,23 +8583,11 @@ "is-utf8": "^0.2.0" } }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true }, "sver-compat": { "version": "1.5.0", @@ -4371,17 +8599,6 @@ "es6-symbol": "^3.1.1" } }, - "tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "dev": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -4448,15 +8665,91 @@ "extend-shallow": "^3.0.2", "regex-not": "^1.0.2", "safe-regex": "^1.1.0" + }, + "dependencies": { + "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" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "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-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-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-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" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } } }, "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "^7.0.0" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" } }, "to-through": { @@ -4468,46 +8761,6 @@ "through2": "^2.0.3" } }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", - "dev": true, - "requires": { - "glob": "^7.1.2" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", @@ -4618,15 +8871,6 @@ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true }, - "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -4645,12 +8889,6 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, "v8flags": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", @@ -4676,21 +8914,10 @@ "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", "dev": true }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", "dev": true, "requires": { "clone": "^2.1.1", @@ -4699,6 +8926,14 @@ "cloneable-readable": "^1.0.0", "remove-trailing-separator": "^1.0.1", "replace-ext": "^1.0.0" + }, + "dependencies": { + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + } } }, "vinyl-fs": { @@ -4776,15 +9011,6 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", @@ -4793,6 +9019,23 @@ "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } } }, "wrappy": { @@ -4808,21 +9051,15 @@ "dev": true }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", "dev": true }, "yargs": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", - "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", + "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", "dev": true, "requires": { "camelcase": "^3.0.0", @@ -4837,13 +9074,13 @@ "string-width": "^1.0.2", "which-module": "^1.0.0", "y18n": "^3.2.1", - "yargs-parser": "5.0.0-security.0" + "yargs-parser": "^5.0.1" } }, "yargs-parser": { - "version": "5.0.0-security.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", - "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", "dev": true, "requires": { "camelcase": "^3.0.0", diff --git a/bitwarden_license/src/Sso/package.json b/bitwarden_license/src/Sso/package.json index 175e9bcd6..585fa3d9b 100644 --- a/bitwarden_license/src/Sso/package.json +++ b/bitwarden_license/src/Sso/package.json @@ -4,14 +4,18 @@ "description": "Bitwarden SSO", "repository": "https://github.com/bitwarden/enterprise", "license": "-", + "scripts": { + "build": "gulp build" + }, "devDependencies": { "bootstrap": "4.5.0", - "del": "5.1.0", + "del": "6.0.0", "font-awesome": "4.7.0", "gulp": "4.0.2", - "gulp-sass": "4.0.1", + "gulp-sass": "5.1.0", "jquery": "3.5.1", - "merge-stream": "1.0.1", - "popper.js": "1.16.1" + "merge-stream": "2.0.0", + "popper.js": "1.16.1", + "sass": "^1.49.7" } } diff --git a/bitwarden_license/src/Sso/packages.lock.json b/bitwarden_license/src/Sso/packages.lock.json new file mode 100644 index 000000000..a55e1aa2b --- /dev/null +++ b/bitwarden_license/src/Sso/packages.lock.json @@ -0,0 +1,2933 @@ +{ + "version": 1, + "dependencies": { + "net6.0": { + "Sustainsys.Saml2.AspNetCore2": { + "type": "Direct", + "requested": "[2.9.0, )", + "resolved": "2.9.0", + "contentHash": "R1E9du8rYeswB94vn6Tj8S1Y9+ZG7D+S02f7+lRt6CeiWV7AQxVKYR8pUlCc7Io1U+t+aTg7+L7JvmKhnDDdzA==", + "dependencies": { + "Microsoft.AspNetCore.Authentication": "2.1.2", + "Microsoft.AspNetCore.Authentication.Cookies": "2.1.2", + "Microsoft.AspNetCore.Http": "2.1.1", + "Sustainsys.Saml2": "2.9.0" + } + }, + "AspNetCoreRateLimit": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "FzXAJFgaRjKfnKAVwjEEC7OAGQM5v/I3sQw2tpzmR0yHTCGhUAxZzDuwZiXTk8XLrI6vovzkqKkfKmiDl3nYMg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.1", + "Microsoft.Extensions.Options": "6.0.0", + "Newtonsoft.Json": "13.0.1" + } + }, + "AspNetCoreRateLimit.Redis": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "CsSGy/7SXt6iBOKg0xCvsRjb/ZHshbtr2Of1MHc912L2sLnZqadUrTboyXZC+ZlgEBeJ14GyjPTu8ZyfEhGUnw==", + "dependencies": { + "AspNetCoreRateLimit": "4.0.2", + "StackExchange.Redis": "2.5.43" + } + }, + "AutoMapper": { + "type": "Transitive", + "resolved": "11.0.0", + "contentHash": "+596AnKykYCk9RxXCEF4GYuapSebQtFVvIA1oVG1rrRkCLAC7AkWehJ0brCfYUbdDW3v1H/p0W3hob7JoXGjMw==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "AutoMapper.Extensions.Microsoft.DependencyInjection": { + "type": "Transitive", + "resolved": "11.0.0", + "contentHash": "0asw5WxdCFh2OTi9Gv+oKyH9SzxwYQSnO8TV5Dd0GggovILzJW4UimP26JAcxc3yB5NnC5urooZ1BBs8ElpiBw==", + "dependencies": { + "AutoMapper": "11.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "AWSSDK.Core": { + "type": "Transitive", + "resolved": "3.7.10.11", + "contentHash": "B+M7ggPC0FogATRPQxDXL0eTusCQtXulW4zCuX39yiHV8+u9MEXRytcAw0ZA3zFBYYx6ovl9lklho6OQo1DRRQ==" + }, + "AWSSDK.SimpleEmail": { + "type": "Transitive", + "resolved": "3.7.0.150", + "contentHash": "rc/4ZnISfbgTfqz5/BWqMHBAzk4R09qfe1xkdJf2jXo44Zn2X72W8IiLLweBtmNhL7d8Tcf6UCtOHYkFwxHvug==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "AWSSDK.SQS": { + "type": "Transitive", + "resolved": "3.7.2.47", + "contentHash": "RPTVBsY333n+aIEqw148Envx9OQkE1/jhjlioNXDP6BrA3fAPN9A+2HoA02c0KSp/sazXYWg8w/kDL8FchH8Dw==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.24.0", + "contentHash": "+/qI1j2oU1S4/nvxb2k/wDsol00iGf1AyJX5g3epV7eOpQEP/2xcgh/cxgKMeFgn3U2fmgSiBnQZdkV+l5y0Uw==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Numerics.Vectors": "4.5.0", + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Extensions.AspNetCore.DataProtection.Blobs": { + "type": "Transitive", + "resolved": "1.2.1", + "contentHash": "wxvkC6DeWThBtaPbsWdicp5Ltya4J8JuhxmZJDQkhnXG7oihfu8RqBV6w/X1nMieuIOq1qQaGTvjx7nEHHfxSQ==", + "dependencies": { + "Azure.Core": "1.14.0", + "Azure.Storage.Blobs": "12.8.0", + "Microsoft.AspNetCore.DataProtection": "2.1.0" + } + }, + "Azure.Identity": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "EycyMsb6rD2PK9P0SyibFfEhvWWttdrYhyPF4f41uzdB/44yQlV+2Wehxyg489Rj6gbPvSPgbKq0xsHJBhipZA==", + "dependencies": { + "Azure.Core": "1.24.0", + "Microsoft.Identity.Client": "4.39.0", + "Microsoft.Identity.Client.Extensions.Msal": "2.19.3", + "System.Memory": "4.5.4", + "System.Security.Cryptography.ProtectedData": "4.7.0", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Storage.Blobs": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "50eRjIhY7Q1JN7kT2MSawDKCcwSb7uRZUkz00P/BLjSg47gm2hxUYsnJPyvzCHntYMbOWzrvaVQTwYwXabaR5Q==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Text.Json": "4.7.2" + } + }, + "Azure.Storage.Common": { + "type": "Transitive", + "resolved": "12.10.0", + "contentHash": "vYkHGzUkdZTace/cDPZLG+Mh/EoPqQuGxDIBOau9D+XWoDPmuUFGk325aXplkFE4JFGpSwoytNYzk/qBCaiHqg==", + "dependencies": { + "Azure.Core": "1.22.0", + "System.IO.Hashing": "6.0.0" + } + }, + "Azure.Storage.Queues": { + "type": "Transitive", + "resolved": "12.9.0", + "contentHash": "jDiyHtsCUCrWNvZW7SjJnJb46UhpdgQrWCbL8aWpapDHlq9LvbvxYpfLh4dfKAz09QiTznLMIU3i+md9+7GzqQ==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, + "BitPay.Light": { + "type": "Transitive", + "resolved": "1.0.1907", + "contentHash": "QTTIgXakHrRNQPxNyH7bZ7frm0bI8N6gRDtiqVyKG/QYQ+KfjN70xt0zQ0kO0zf8UBaKuwcV5B7vvpXtzR9ijg==", + "dependencies": { + "Newtonsoft.Json": "12.0.2" + } + }, + "Braintree": { + "type": "Transitive", + "resolved": "5.12.0", + "contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "System.Xml.XPath.XmlDocument": "4.3.0" + } + }, + "Dapper": { + "type": "Transitive", + "resolved": "2.0.123", + "contentHash": "RDFF4rBLLmbpi6pwkY7q/M6UXHRJEOerplDGE5jwEkP/JGJnBauAClYavNKJPW1yOTWRPIyfj4is3EaJxQXILQ==" + }, + "Fido2": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "S0Bz1vfcKlO4Jase3AWp5XnQ746psf4oGx5kL+D2A10j1SsjoAOAIIpanSwfi0cEepDHgk1bClcOKY5TjOzGdA==", + "dependencies": { + "Fido2.Models": "3.0.1", + "Microsoft.Extensions.Http": "6.0.0", + "NSec.Cryptography": "22.4.0", + "System.Formats.Cbor": "6.0.0", + "System.IdentityModel.Tokens.Jwt": "6.17.0" + } + }, + "Fido2.AspNet": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "5n5shEXD7RFUyTesjUHGDjkpgES7j4KotQo1GwUcS08k+fx+1tl/zCFHJ9RFDuUwO+S681ZILT2PyA67IPYpaA==", + "dependencies": { + "Fido2": "3.0.1", + "Fido2.Models": "3.0.1" + } + }, + "Fido2.Models": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "mgjcuGETuYSCUEaZG+jQeeuuEMkDLc4GDJHBvKDdOz6oSOWp5adPdWP4btZx7Pi+9fu4szN3JIjJmby67MaILw==" + }, + "Handlebars.Net": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "p60QyeBYpZmcZdIXRMqs9XySIBaxJ0lj3+QD0EJVr4ybTigOTCumXMMin5dPwjo9At1UwkDZ3gGwa1lmGjG6DA==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "IdentityModel": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "System.Text.Encodings.Web": "4.7.0" + } + }, + "IdentityModel.AspNetCore.OAuth2Introspection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==", + "dependencies": { + "IdentityModel": "4.0.0" + } + }, + "IdentityServer4": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==", + "dependencies": { + "IdentityModel": "4.4.0", + "IdentityServer4.Storage": "4.1.2", + "Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0", + "Newtonsoft.Json": "12.0.2" + } + }, + "IdentityServer4.AccessTokenValidation": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==", + "dependencies": { + "IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1", + "Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0" + } + }, + "IdentityServer4.Storage": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==", + "dependencies": { + "IdentityModel": "4.4.0" + } + }, + "libsodium": { + "type": "Transitive", + "resolved": "1.0.18.2", + "contentHash": "flArHoVdscSzyV8ZdPV+bqqY2TTFlaN+xZf/vIqsmHI51KVcD/mOdUPaK3n/k/wGKz8dppiktXUqSmf3AXFgig==" + }, + "linq2db": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "6/u1EzQlV25bhN0Ej/I5dLV5Hgxun+ww/TX2VnMBnSVytED2VzQGeFIO/14I624GkfPOtB79x1ooL3F18dAbdw==" + }, + "linq2db.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.11.0", + "contentHash": "mS+L6HyVHP3oJaTuFVZswNmPpTfYleGjDTo2IWBJmYXZpSQ5EPw1DpHzmyLAiQd+93ofy0Ala+9HWzv6/k73ZQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "6.0.5", + "linq2db": "4.4.0" + } + }, + "MailKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "5MTpTqmjqT7HPvYbP3HozRZMth5vSaT0ReN0iM3rAM4CgLI/R1qqtLDDNWGnFFIlcNzeJkZQRJJMkv8cgzWBbA==", + "dependencies": { + "MimeKit": "3.2.0" + } + }, + "Microsoft.AspNetCore.Authentication": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "RYM3HHMm/MNwsbUh1xnrhosAGNeZV2Q/FmNQrblgytIK1HIZ6UqNMorFI+kz2MW7gNKHKn6TBLTUXPRmqC6iRQ==", + "dependencies": { + "Microsoft.AspNetCore.Authentication.Core": "2.1.1", + "Microsoft.AspNetCore.DataProtection": "2.1.1", + "Microsoft.AspNetCore.Http": "2.1.1", + "Microsoft.AspNetCore.Http.Extensions": "2.1.1", + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "Microsoft.Extensions.Options": "2.1.1", + "Microsoft.Extensions.WebEncoders": "2.1.1" + } + }, + "Microsoft.AspNetCore.Authentication.Abstractions": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "Smj5TGeE9629+hGHPk/DZUfCMYGvQwCajAsU/OVExRb8JXfeua4uXZFzT9Kh3pJY2MThPSt1lbDnkL2KaDyw/A==", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "2.1.1", + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "Microsoft.Extensions.Options": "2.1.1" + } + }, + "Microsoft.AspNetCore.Authentication.Cookies": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "XwE4/p9QHJOkoSWYdgx3u3Jhx6+NQZuRWGJT7jsdlpfDJeS3gJWEqIM9pBmrdt803sX2WZDpgm8hxGIAtiJcQQ==", + "dependencies": { + "Microsoft.AspNetCore.Authentication": "2.1.2" + } + }, + "Microsoft.AspNetCore.Authentication.Core": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "Zo6SLzqxrW0PFg1AB0xSb+Rta4hCuX8hgOY425ldhFq4kKcmw45oJQ2zOIeeW/6EuBtEy+hwDB96baxTmXtfeA==", + "dependencies": { + "Microsoft.AspNetCore.Authentication.Abstractions": "2.1.1", + "Microsoft.AspNetCore.Http": "2.1.1", + "Microsoft.AspNetCore.Http.Extensions": "2.1.1" + } + }, + "Microsoft.AspNetCore.Authentication.JwtBearer": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "joDS3+lD1i9qcdFLWP4D316t3bHpezmTNOzbMIf9ZcRPX4QTuiUutZcQn/kZplf3BiLHqwUChZXxPjCAMKaKAQ==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0" + } + }, + "Microsoft.AspNetCore.Authentication.OpenIdConnect": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0" + } + }, + "Microsoft.AspNetCore.Cryptography.Internal": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "/0FX1OqckMmXAAlsHgBFNymTZuq4nuAOMhiwm6e8CEMi2aOjnMYwiMc7mtvpGTAO0O4C0zwx+iaChxDgvqit2A==" + }, + "Microsoft.AspNetCore.Cryptography.KeyDerivation": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "1Lbwrxg/HRY/nbrkcrB3EUXUYQN8Tkw7Ktgb6/2on2P7ybT5aM59H05gk+OBC8ZTBxwdle9e1tyT3wxEYKw5xw==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "6.0.4" + } + }, + "Microsoft.AspNetCore.DataProtection": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "OPZDPAAL3OwOCrz870F9goq//NJOmPl4Lv3dz+v0cRQe8EpsbCe0c6IRI8vdlFwM13Qy57D5rLQlysb+tLpENA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "2.1.1", + "Microsoft.AspNetCore.DataProtection.Abstractions": "2.1.1", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.1.1", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "Microsoft.Extensions.Options": "2.1.1", + "Microsoft.Win32.Registry": "4.5.0", + "System.Security.Cryptography.Xml": "4.5.0", + "System.Security.Principal.Windows": "4.5.0" + } + }, + "Microsoft.AspNetCore.DataProtection.Abstractions": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "dcH52SMIIUOwBeDZ2QQEY3hWXJz50Dk2YzC/B2hxDLB78Il75BHGOhClIw6/0H+dKZCwItUytxoMNYtCSmG+aQ==" + }, + "Microsoft.AspNetCore.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "76cKcp2pWhvdV2TXTqMg/DyW7N6cDzTEhtL8vVWFShQN+Ylwv3eO/vUQr2BS3Hz4IZHEpL+FOo2T+MtymHDqDQ==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "2.1.1", + "Microsoft.AspNetCore.Http.Abstractions": "2.1.1", + "Microsoft.Extensions.Hosting.Abstractions": "2.1.1" + } + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "+vD7HJYzAXNq17t+NgRkpS38cxuAyOBu8ixruOiA3nWsybozolUdALWiZ5QFtGRzajSLPFA2YsbO3NPcqoUwcw==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.1", + "Microsoft.Extensions.Configuration.Abstractions": "2.1.1" + } + }, + "Microsoft.AspNetCore.Http": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "pPDcCW8spnyibK3krpxrOpaFHf5fjV6k1Hsl6gfh77N/8gRYlLU7MOQDUnjpEwdlHmtxwJKQJNxZqVQOmJGRUw==", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "2.1.1", + "Microsoft.AspNetCore.WebUtilities": "2.1.1", + "Microsoft.Extensions.ObjectPool": "2.1.1", + "Microsoft.Extensions.Options": "2.1.1", + "Microsoft.Net.Http.Headers": "2.1.1" + } + }, + "Microsoft.AspNetCore.Http.Abstractions": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "kQUEVOU4loc8CPSb2WoHFTESqwIa8Ik7ysCBfTwzHAd0moWovc9JQLmhDIHlYLjHbyexqZAlkq/FPRUZqokebw==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.1", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Extensions": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "ncAgV+cqsWSqjLXFUTyObGh4Tr7ShYYs3uW8Q/YpRwZn7eLV7dux5Z6GLY+rsdzmIHiia3Q2NWbLULQi7aziHw==", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "2.1.1", + "Microsoft.Extensions.FileProviders.Abstractions": "2.1.1", + "Microsoft.Net.Http.Headers": "2.1.1", + "System.Buffers": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Features": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "VklZ7hWgSvHBcDtwYYkdMdI/adlf7ebxTZ9kdzAhX+gUs5jSHE9mZlTamdgf9miSsxc1QjNazHXTDJdVPZKKTw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.1" + } + }, + "Microsoft.AspNetCore.WebUtilities": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "PGKIZt4+412Z/XPoSjvYu/QIbTxcAQuEFNoA1Pw8a9mgmO0ZhNBmfaNyhgXFf7Rq62kP0tT/2WXpxdcQhkFUPA==", + "dependencies": { + "Microsoft.Net.Http.Headers": "2.1.1", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.Azure.Amqp": { + "type": "Transitive", + "resolved": "2.4.11", + "contentHash": "7x5fu2f6TLQDDJS0sY5qW8/daFwJaY9O75YvU8RcUfRzbug+9YGjXUBxoRrprgyi0jxdBAMQL05p1s783SOSFQ==", + "dependencies": { + "System.Net.WebSockets.Client": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.Azure.Cosmos": { + "type": "Transitive", + "resolved": "3.24.0", + "contentHash": "QpUe5ho6OzlXwgcJVgAmOR7t3XLC9RI4t8T96RZY61pSOIllPOJdp30L0LwA16tKcqi5r2KayEgWO/MS9fh/6A==", + "dependencies": { + "Azure.Core": "1.3.0", + "Microsoft.Bcl.AsyncInterfaces": "1.0.0", + "Microsoft.Bcl.HashCode": "1.1.0", + "Newtonsoft.Json": "10.0.2", + "System.Buffers": "4.5.1", + "System.Collections.Immutable": "1.7.0", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Memory": "4.5.4", + "System.Numerics.Vectors": "4.5.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3", + "System.Threading.Tasks.Extensions": "4.5.4", + "System.ValueTuple": "4.5.0" + } + }, + "Microsoft.Azure.Cosmos.Table": { + "type": "Transitive", + "resolved": "1.0.8", + "contentHash": "ToeEd1yijM7nQfLYvdFLG//RjKPmfqm45eOm86UAKrxtyGI/CXqP8iL74mzBp6mZ9A/K/ZYA2fVdpH0xHR5Keg==", + "dependencies": { + "Microsoft.Azure.DocumentDB.Core": "2.11.2", + "Microsoft.OData.Core": "7.6.4", + "Newtonsoft.Json": "10.0.2" + } + }, + "Microsoft.Azure.DocumentDB.Core": { + "type": "Transitive", + "resolved": "2.11.2", + "contentHash": "cA8eWrTFbYrkHrz095x4CUGb7wqQgA1slzFZCYexhNwz6Zcn3v+S1yvWMGwGRmRjT0MKU9tYdFWgLfT0OjSycw==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "Newtonsoft.Json": "9.0.1", + "System.Collections.Immutable": "1.3.0", + "System.Collections.NonGeneric": "4.0.1", + "System.Collections.Specialized": "4.0.1", + "System.Diagnostics.TraceSource": "4.0.0", + "System.Dynamic.Runtime": "4.0.11", + "System.Linq.Queryable": "4.0.1", + "System.Net.Http": "4.3.4", + "System.Net.NameResolution": "4.0.0", + "System.Net.NetworkInformation": "4.1.0", + "System.Net.Requests": "4.0.11", + "System.Net.Security": "4.3.2", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Security.SecureString": "4.0.0" + } + }, + "Microsoft.Azure.NotificationHubs": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "C2SssjX3e6/HIo1OCImQDDVOn64d1+gkgEmgxJryzkwixyivJHWH2YIgxZs33pyzVQcZWx5PR2tqLkQ7riSq8Q==", + "dependencies": { + "Microsoft.Extensions.Caching.Memory": "3.1.8", + "Newtonsoft.Json": "12.0.3" + } + }, + "Microsoft.Azure.ServiceBus": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "wyZNJggyFNtKxd+HgvcTiuRYuTjDGi+pgE4RcBvFbfvNiarKr5AOlE4Ne7on1eUJZuMuEa19wN5dj694HlP60A==", + "dependencies": { + "Microsoft.Azure.Amqp": "2.4.11", + "Microsoft.Azure.Services.AppAuthentication": "[1.0.3, 2.0.0)", + "Newtonsoft.Json": "10.0.3", + "System.Diagnostics.DiagnosticSource": "4.5.1", + "System.IdentityModel.Tokens.Jwt": "5.4.0" + } + }, + "Microsoft.Azure.Services.AppAuthentication": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "ywpQaK1klu1IoX4VUf+TBmU4kR71aWNI6O5rEIJU8z28L2xhJhnIm7k2Nf1Zu/PygeuOtt5g0QPCk5+lLltbeQ==", + "dependencies": { + "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.14.2", + "NETStandard.Library": "1.6.1", + "System.Diagnostics.Process": "4.3.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "yuvf07qFWFqtK3P/MRkEKLhn5r2UbSpVueRziSqj0yJQIKFwG1pq9mOayK3zE5qZCTs0CbrwL9M6R8VwqyGy2w==" + }, + "Microsoft.Bcl.HashCode": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "J2G1k+u5unBV+aYcwxo94ip16Rkp65pgWFb0R6zwJipzWNMgvqlWeuI7/+R+e8bob66LnSG+llLJ+z8wI94cHg==" + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, + "Microsoft.Data.SqlClient": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "uu8dfrsx081cSbEevWuZAvqdmANDGJkbLBL2G3j0LAZxX1Oy8RCVAaC4Lcuak6jNicWP6CWvHqBTIEmQNSxQlw==", + "dependencies": { + "Azure.Identity": "1.6.0", + "Microsoft.Data.SqlClient.SNI.runtime": "5.0.1", + "Microsoft.Identity.Client": "4.45.0", + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.21.0", + "Microsoft.SqlServer.Server": "1.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Buffers": "4.5.1", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Diagnostics.DiagnosticSource": "5.0.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime.Caching": "5.0.0", + "System.Security.Cryptography.Cng": "5.0.0", + "System.Security.Principal.Windows": "5.0.0", + "System.Text.Encoding.CodePages": "5.0.0", + "System.Text.Encodings.Web": "4.7.2" + } + }, + "Microsoft.Data.SqlClient.SNI.runtime": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "y0X5MxiNdbITJYoafJ2ruaX6hqO0twpCGR/ipiDOe85JKLU8WL4TuAQfDe5qtt3bND5Je26HnrarLSAMMnVTNg==" + }, + "Microsoft.Data.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bui5wPPqq9OwTL5A+YJPcVStTPrOFcLwg/kAVWyqdjrTief4kTK/3bNv0MqUDVNgAUG8pcFbtdc674CIh1F3gw==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "xb10XFoPf/gWu8ik5v7xnVyUY7W21LBOLtT7PidzwYVdnE3aKuQ/bIZLcQuY7rdDNT89/wse2q5FRjm207cIMQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Analyzers": "6.0.12", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.DependencyInjection": "6.0.1", + "Microsoft.Extensions.Logging": "6.0.0", + "System.Collections.Immutable": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Abstractions": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "hvRytAcLhrb35HmtMjYWsNZZLt39ryuN7j04lDchRa9VToreyqgo5gMniTdQ6MfCflxtGnDes65V/Y2pjbEyWg==" + }, + "Microsoft.EntityFrameworkCore.Analyzers": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "ZDUY+KlsIyKdfvIJeNdqRiPExFQ5GRZVdx/Cp52vhpCJRImYv34O0Xfmw2eiLu4qe1jmM2pTzAAFKELaKwtj/w==" + }, + "Microsoft.EntityFrameworkCore.Relational": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "HBtRGHtF0Vf+BIQTkRGiopmE5rLYhj59xPpd17S1tLgYpiHDVbepCuHwh5H63fzjO99Z4tW5wmmEGF7KnD91WQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "2Hutlqt07bnWZFtYqT1lj0otX8ygMyBikysGnfQNF2TK3i5GqSTeJ8tqNi/URiI9II7Cyl15A0rflXmFoySuIw==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Sqlite.Core": "6.0.12", + "SQLitePCLRaw.bundle_e_sqlite3": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "07vKE7+t9Z2BfGmHuJwNZNv8m1GWt7ZpYYHFh1tQg1oC6FJ78bSaFzLawsf2NK6CLhbB8DBsjE0rRhxMJ4rXsA==", + "dependencies": { + "Microsoft.Data.Sqlite.Core": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Microsoft.Extensions.DependencyModel": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bcz5sSFJbganH0+YrfvIjJDIcKNW7TL07C4d1eTmXy/wOt52iz4LVogJb6pazs7W0+74j0YpXFErvp++Aq5Bsw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.Memory": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "B4y+Cev05eMcjf1na0v9gza6GUtahXbtY1JCypIgx3B4Ea/KAgsWyXEmW4q6zMbmTMtKzmPVk09rvFJirvMwTg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.StackExchangeRedis": { + "type": "Transitive", + "resolved": "6.0.6", + "contentHash": "bdVQpYm1hcHf0pyAypMjtDw3HjWQJ89UzloyyF1OBs56QlgA1naM498tP2Vjlho5vVRALMGPYzdRKCen8koubw==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "StackExchange.Redis": "2.2.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "tq2wXyh3fL17EMF2bXgRhU7JrbO3on93MRKYxzz4JzzvuGSA1l0W3GI9/tl8EO89TH+KWEymP7bcFway6z9fXg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "IznHHzGUtrdpuQqIUdmzF6TYPcsYHONhHh3o9dGp39sX/9Zfmt476UnhvU0UhXgJnXXAikt/MpN6AuSLCCMdEQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.0.0" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "pnyXV1LFOsYjGveuC07xp0YHIyGq7jRq5Ncb5zrrIieMLWVwgMyYxcOH0jTnBedDT4Gh1QinSqsjqzcieHk1og==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "V4Dth2cYMZpw3HhGw9XUDIijpI6gN+22LDt0AhufIgOppCUfpWX4483OmN+dFXRJkJLc8Tv0Q8QK+1ingT2+KQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GJGery6QytCzS/BxJ96klgG9in3uH26KcUBbiVG/coNDXCRq6LGVVlUT4vXq34KPuM+R2av+LeYdX9h4IZOCUg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "Fy8yr4V6obi7ZxvKYI1i85jqtwMq8tqyxQVZpRSkgeA8enqy/KvBIMdcuNdznlxQMZa72mvbHqb7vbg4Pyx95w==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "vWXPg3HJQIpZkENn1KWq8SfbqVujVD7S7vIAyFXXqK5xkf1Vho+vG0bLBCHxU36lD1cLLtmGpfYf0B3MYFi9tQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.DependencyModel": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "TD5QHg98m3+QhgEV1YVoNMl5KtBw/4rjfxLHO0e/YV9bPUBDKntApP4xdrVtGgCeQZHVfC2EXIGsdpRNrr87Pg==", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "3.1.8", + "contentHash": "7ZJUKwPipkDvuv2KJPZ3r01wp2AWNMiYH+61i0dL89F7QICknjKpWgLKLpTSUYFgl77S3b4264I6i4HzDdrb2A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.8", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.FileProviders.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "15+pa2G0bAMHbHewaQIdr/y6ag2H3yh4rd9hTXavtWDzQBkvpe2RMqFg8BxDpcQWssmjmBApGPcw93QRz6YcMg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Core": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "8vBsyGkA8ZI3lZvm1nf+9ynRC/TzPD+UtbdgTlKk+cz+AW5I41LrK8f/adGej5uXgprOA2DMjZw33vZG6vyXxA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Stores": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "linRCnWBfnqg8qjrd9u/KMISy8O4a6X/GRhpHXU0ar654YQw9LJ/Ht+psx8QLqSX5EsCBbBCZzuamatH2FWIyQ==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Identity.Core": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + }, + "Microsoft.Extensions.ObjectPool": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "SErON45qh4ogDp6lr6UvVmFYW0FERihW+IQ+2JyFv1PUyWktcJytFaWH5zarufJvZwhci7Rf1IyGXr9pVEadTw==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y/lGICwO27fCkQRK3tZseVzFjZaxfGmui990E67sB4MuiPzdJHnJDS/BeYWrHShSSBgCl4KyKRx4ux686fftPg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.0.0", + "Microsoft.Extensions.Options": "2.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.WebEncoders": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "XIuJXPNUAX/ZV/onarixNoq3kO7Q9/RXXOY8hhYydsDwHI9PqPeJH6WE3LmPJJDmB+7y3+MT6ZmW78gZZDApBA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", + "Microsoft.Extensions.Options": "2.1.1", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.Identity.Client": { + "type": "Transitive", + "resolved": "4.45.0", + "contentHash": "ircobISCLWbtE5eEoLKU+ldfZ8O41vg4lcy38KRj/znH17jvBiAl8oxcyNp89CsuqE3onxIpn21Ca7riyDDrRw==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.18.0" + } + }, + "Microsoft.Identity.Client.Extensions.Msal": { + "type": "Transitive", + "resolved": "2.19.3", + "contentHash": "zVVZjn8aW7W79rC1crioDgdOwaFTQorsSO6RgVlDDjc7MvbEGz071wSNrjVhzR0CdQn6Sefx7Abf1o7vasmrLg==", + "dependencies": { + "Microsoft.Identity.Client": "4.38.0", + "System.Security.Cryptography.ProtectedData": "4.5.0" + } + }, + "Microsoft.IdentityModel.Abstractions": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "XeE6LQtD719Qs2IG7HDi1TSw9LIkDbJ33xFiOBoHbApVw/8GpIBCbW+t7RwOjErUDyXZvjhZliwRkkLb8Z1uzg==" + }, + "Microsoft.IdentityModel.Clients.ActiveDirectory": { + "type": "Transitive", + "resolved": "3.14.2", + "contentHash": "TNsJJMiRnkeby1ovThVoV9yFsPWjAdluwOA+Nf0LtSsBVVrKQv8Qp4kYOgyNwMVj+pDwbhXISySk+4HyHVWNZQ==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "System.Runtime.Serialization.Json": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.IdentityModel.JsonWebTokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "d3h1/BaMeylKTkdP6XwRCxuOoDJZ44V9xaXr6gl5QxmpnZGdoK3bySo3OQN8ehRLJHShb94ElLUvoXyglQtgAw==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "tuEhHIQwvBEhMf8I50hy8FHmRSUkffDFP5EdLsSDV4qRcl2wvOPkQxYqEzWkh+ytW6sbdJGEXElGhmhDfAxAKg==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "0FqY5cTLQKtHrClzHEI+QxJl8OBT2vUiEQQB7UKk832JDiJJmetzYZ3AdSrPjN/3l3nkhByeWzXnhrX0JbifKg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "vtSKL7n6EnAsLyxmiviusm6LKrblT2ndnNqN6rvVq6iIHAnPCK9E2DkDx6h1Jrpy1cvbp40r0cnTg23nhEAGTA==", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "6.21.0", + "System.IdentityModel.Tokens.Jwt": "6.21.0" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "AAEHZvZyb597a+QJSmtxH3n2P1nIJGpZ4Q89GTenknRx6T6zyfzf592yW/jA5e8EHN4tNMjjXHQaYWEq5+L05w==", + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "Microsoft.IdentityModel.Logging": "6.21.0", + "System.Security.Cryptography.Cng": "4.5.0" + } + }, + "Microsoft.IdentityModel.Tokens.Saml": { + "type": "Transitive", + "resolved": "5.2.4", + "contentHash": "00JslaTaHAUtMqiv/C/jQBqqrHkYmTe2n08qqrsHW57xVKTu+vOoi75HqDZbK3SAnRuadevDtvGCHf7V5GOQDQ==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "5.2.4", + "Microsoft.IdentityModel.Xml": "5.2.4", + "NETStandard.Library": "1.6.1" + } + }, + "Microsoft.IdentityModel.Xml": { + "type": "Transitive", + "resolved": "5.2.4", + "contentHash": "v0UUzcpzz+mcR+Fzp8wFrcBt0Br0nJH5vuAdmlUmFqoc/DuDt/u5fcXVFRP3D77l22CQ/Rs3FTXUeXrTvi4gPg==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "5.2.4", + "NETStandard.Library": "1.6.1" + } + }, + "Microsoft.Net.Http.Headers": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "lPNIphl8b2EuhOE9dMH6EZDmu7pS882O+HMi5BJNsigxHaWlBrYxZHFZgE18cyaPp6SSZcTkKkuzfjV/RRQKlA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.1", + "System.Buffers": "4.5.0" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.OData.Core": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "/EjnJezMBjXf8OjcShhGzPY7pOO0CopgoZGhS6xsP3t2uhC+O72IBHgtQ7F3v1rRXWVtJwLGhzE1GfJUlx3c4Q==", + "dependencies": { + "Microsoft.OData.Edm": "[7.6.4]", + "Microsoft.Spatial": "[7.6.4]" + } + }, + "Microsoft.OData.Edm": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "MSSmA6kIfpgFTtNpOnnayoSj/6KSzHC1U9KOjF7cTA1PG4tZ7rIMi1pvjFc8CmYEvP4cxGl/+vrCn+HpK26HTQ==" + }, + "Microsoft.Spatial": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "3mB+Frn4LU4yb5ie9R752QiRn0Hvp9PITkSRofV/Lzm9EyLM87Fy9ziqgz75O/c712dh6GxuypMSBUGmNFwMeA==" + }, + "Microsoft.SqlServer.Server": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug==" + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "Microsoft.Win32.Registry": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "Microsoft.Win32.SystemEvents": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==" + }, + "MimeKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "l9YHMBhBUwY7qQHUp8fw0EvjcbmhN4Iggz6MdjqIShBf42+0nJTa5gu0kuupCOPuiARc9ZaS9c9f0gKz4OnxKw==", + "dependencies": { + "Portable.BouncyCastle": "1.9.0", + "System.Security.Cryptography.Pkcs": "6.0.0" + } + }, + "MySqlConnector": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "JVokQTUNN3WHAu9Vw8ieeq1dXTFokJiig5P0VJ4f439UxRrsPo6SaVWC8Zdm6mkPeQFhZ0/9afdWa02EY/1j/w==" + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "Npgsql": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "wKa8MJEJaj0xQXUQZGv7q/KfPID23jSSvFFtljMworrv7dNajr0GN8PCU1SpywqHjMWdYEfK29DY1aYbiISbQg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Npgsql.EntityFrameworkCore.PostgreSQL": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "YJRpO+3wXQyWuwRUCVJj/Rsn46sY0bZ6uCGOEFApiRe0ZYJ6N6TxZUWKbTNJYjesickcLGzynOerpSbDJX1AYg==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Npgsql": "6.0.8" + } + }, + "NSec.Cryptography": { + "type": "Transitive", + "resolved": "22.4.0", + "contentHash": "lEntcPYd7h3aZ8xxi/y/4TML7o8w0GEGqd+w4L1omqFLbdCBmhxJAeO2YBmv/fXbJKgKCQLm7+TD4bR605PEUQ==", + "dependencies": { + "libsodium": "[1.0.18.2, 1.0.19)" + } + }, + "Otp.NET": { + "type": "Transitive", + "resolved": "1.2.2", + "contentHash": "2hrZfkbzeWJ3tNXXt/1beg4IY+nS4F3gIfh4NVFvW0f6Pj51hGpiJ4prBz7Dmrr4ZYrA96rTERVGieZ4xYm7jA==" + }, + "Pipelines.Sockets.Unofficial": { + "type": "Transitive", + "resolved": "2.2.2", + "contentHash": "Bhk0FWxH1paI+18zr1g5cTL+ebeuDcBCR+rRFO+fKEhretgjs7MF2Mc1P64FGLecWp4zKCUOPzngBNrqVyY7Zg==", + "dependencies": { + "System.IO.Pipelines": "5.0.1" + } + }, + "Pomelo.EntityFrameworkCore.MySql": { + "type": "Transitive", + "resolved": "6.0.2", + "contentHash": "KvlZ800CnEuEGnxj5OT1fCKGjQXxW5kpPlCP91JqBYG+2Z3927eqXmlX6LLKUt4swqE8ZsEQ+Zkpab8bqstf4g==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "[6.0.7, 7.0.0)", + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "MySqlConnector": "2.1.2" + } + }, + "Portable.BouncyCastle": { + "type": "Transitive", + "resolved": "1.9.0", + "contentHash": "eZZBCABzVOek+id9Xy04HhmgykF0wZg9wpByzrWN7q8qEI0Qen9b7tfd7w8VA3dOeesumMG7C5ZPy0jk7PSRHw==" + }, + "Quartz": { + "type": "Transitive", + "resolved": "3.4.0", + "contentHash": "N8350OAlQhd8zKg0ARFikGjh3bfAW/CF/KVxu2fTIlAALB/oC1eg54n/QAPYR5ryHuYyDr5G8/Qa4k+D/7OFRQ==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" + }, + "SendGrid": { + "type": "Transitive", + "resolved": "9.27.0", + "contentHash": "kMyXRQ8hmN2bG3tYZ7T31Ufl1kXkpuP5+WBh1BJ32WY31DTnBTCVGURoIqfbTo/tRuQfAYLxra6C8cQGN6kk+A==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "starkbank-ecdsa": "[1.3.3, 2.0.0)" + } + }, + "Sentry": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "Pkw4+51EDUQ0X02jdCZIpaM2Q4UO06VKGDE+dYYNxgvOirRXGKTKxRk4NPKJTLSTNl+2JyT9HoE7C6BTlYhLOw==" + }, + "Sentry.Serilog": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "GFTVfQdOFqZ9Vmo8EEZTx1EQMDRJjka/4v2CwxnAUh+sqHDICga4eOm4AyGzDBbE4s9iAHMgMUCceIqo+7z84w==", + "dependencies": { + "Sentry": "3.16.0", + "Serilog": "2.10.0" + } + }, + "Serilog": { + "type": "Transitive", + "resolved": "2.10.0", + "contentHash": "+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA==" + }, + "Serilog.AspNetCore": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "/JO/txIxRR61x1UXQAgUzG2Sx05o1QHCkokVBWrKzmAoDu+p5EtCAj7L/TVVg7Ezhh3GPiZ0JI9OJCmRO9tSRw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.Extensions.Logging": "5.0.0", + "Serilog": "2.10.0", + "Serilog.Extensions.Hosting": "4.2.0", + "Serilog.Formatting.Compact": "1.1.0", + "Serilog.Settings.Configuration": "3.3.0", + "Serilog.Sinks.Console": "4.0.1", + "Serilog.Sinks.Debug": "2.0.0", + "Serilog.Sinks.File": "5.0.0" + } + }, + "Serilog.Extensions.Hosting": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "gT2keceCmPQR9EX0VpXQZvUgELdfE7yqJ7MOxBhm3WLCblcvRgswEOOTgok/DHObbM15A3V/DtF3VdVDQPIZzQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.Hosting.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8", + "Serilog": "2.10.0", + "Serilog.Extensions.Logging": "3.1.0" + } + }, + "Serilog.Extensions.Logging": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "IWfem7wfrFbB3iw1OikqPFNPEzfayvDuN4WP7Ue1AVFskalMByeWk3QbtUXQR34SBkv1EbZ3AySHda/ErDgpcg==", + "dependencies": { + "Microsoft.Extensions.Logging": "2.0.0", + "Serilog": "2.9.0" + } + }, + "Serilog.Extensions.Logging.File": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "usO0qr4v9VCMBWiTJ1nQmAbPNCt40FrkDol6CpfCXbsxGZS/hH+YCueF7vvPQ32ATI0GWcMWiKRdjXEE7/HxTQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Serilog": "2.5.0", + "Serilog.Extensions.Logging": "2.0.2", + "Serilog.Formatting.Compact": "1.0.0", + "Serilog.Sinks.Async": "1.1.0", + "Serilog.Sinks.RollingFile": "3.3.0" + } + }, + "Serilog.Formatting.Compact": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "pNroKVjo+rDqlxNG5PXkRLpfSCuDOBY0ri6jp9PLe505ljqwhwZz8ospy2vWhQlFu5GkIesh3FcDs4n7sWZODA==", + "dependencies": { + "Serilog": "2.8.0" + } + }, + "Serilog.Settings.Configuration": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "7GNudISZwqaT902hqEL2OFGTZeUFWfnrNLupJkOqeF41AR3GjcxX+Hwb30xb8gG2/CDXsCMVfF8o0+8KY0fJNg==", + "dependencies": { + "Microsoft.Extensions.DependencyModel": "3.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "2.0.0", + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Async": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "xll0Kanz2BkCxuv+F3p1WXr47jdsVM0GU1n1LZvK+18QiRZ/WGFNxSNw9EMKFV5ED5gr7MUpAe6PCMNL1HGUMA==", + "dependencies": { + "Serilog": "2.1.0", + "System.Collections.Concurrent": "4.0.12" + } + }, + "Serilog.Sinks.AzureCosmosDB": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Im2/ZqjXQIpsd727qEo5Pq+br0MiNVuTvI40Yk7736tgjCpEx+omPHv4+c4fEAxnOP2kL9Ge6UoDFoDw3cjF2A==", + "dependencies": { + "Microsoft.Azure.Cosmos": "3.24.0", + "Microsoft.CSharp": "4.7.0", + "Newtonsoft.Json": "13.0.1", + "Serilog": "2.10.0", + "Serilog.Sinks.PeriodicBatching": "2.3.1" + } + }, + "Serilog.Sinks.Console": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Debug": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y6g3OBJ4JzTyyw16fDqtFcQ41qQAydnEvEqmXjhwhgjsnG/FaJ8GUqF5ldsC/bVkK8KYmqrPhDO+tm4dF6xx4A==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.File": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.PeriodicBatching": { + "type": "Transitive", + "resolved": "2.3.1", + "contentHash": "LVYvqpqjSTD8dhfxRnzpxTs8/ys3V2q01MvaY3r0eKsDgpKK1U1y/5N6gFHgiesbxG0V+O5IWdz4+c1DzoNyOQ==", + "dependencies": { + "Serilog": "2.0.0" + } + }, + "Serilog.Sinks.RollingFile": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "2lT5X1r3GH4P0bRWJfhA7etGl8Q2Ipw9AACvtAHWRUSpYZ42NGVyHoVs2ALBZ/cAkkS+tA4jl80Zie144eLQPg==", + "dependencies": { + "Serilog.Sinks.File": "3.2.0", + "System.IO": "4.1.0", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Serilog.Sinks.SyslogMessages": { + "type": "Transitive", + "resolved": "2.0.6", + "contentHash": "V2Yq2GEbk7taEPbpBLFzLXhrHrUzKf4sQu/zLrANU8XIoUn/Mr08M2E8PrcrWVXCj0R4xLMWYe0Z1sxOrMF3IA==", + "dependencies": { + "Serilog": "2.5.0", + "Serilog.Sinks.PeriodicBatching": "2.3.0" + } + }, + "SQLitePCLRaw.bundle_e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "ilkvNhrTersLmIVAcDwwPqfhUFCg19Z1GVMvCSi3xk6Akq94f4qadLORQCq/T8+9JgMiPs+F/NECw5uauviaNw==", + "dependencies": { + "SQLitePCLRaw.lib.e_sqlite3": "2.1.2", + "SQLitePCLRaw.provider.e_sqlite3": "2.1.2" + } + }, + "SQLitePCLRaw.core": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "A8EBepVqY2lnAp3a8jnhbgzF2tlj2S3HcJQGANTYg/TbYbKa8Z5cM1h74An/vy0svhfzT7tVY0sFmUglLgv+2g==", + "dependencies": { + "System.Memory": "4.5.3" + } + }, + "SQLitePCLRaw.lib.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "zibGtku8M4Eea1R3ZCAxc86QbNvyEN17mAcQkvWKBuHvRpMiK2g5anG4R5Be7cWKSd1i6baYz8y4dMMAKcXKPg==" + }, + "SQLitePCLRaw.provider.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "lxCZarZdvAsMl2zw9bXHrXK6RxVhB4b23iTFhCOdHFhxfbsxLxWf+ocvswJwR/9Wh/E//ddMi+wJGqUKV7VwoA==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "StackExchange.Redis": { + "type": "Transitive", + "resolved": "2.5.43", + "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "dependencies": { + "Pipelines.Sockets.Unofficial": "2.2.2", + "System.Diagnostics.PerformanceCounter": "5.0.0" + } + }, + "starkbank-ecdsa": { + "type": "Transitive", + "resolved": "1.3.3", + "contentHash": "OblOaKb1enXn+dSp7tsx9yjwV+/BEKM9jFhshIkZTwCk7LuTFTp+wSon6rFzuPiIiTGtvVWQNUw2slHjGktJog==" + }, + "Stripe.net": { + "type": "Transitive", + "resolved": "40.0.0", + "contentHash": "SD1bGiF+sVQG3p2LXNTZ5rEG2aCnXIHokcxYS9yyW3dR01J0ryf+iNFOwid148yePZ0gCBcRxj3wiW1mTmP7UQ==", + "dependencies": { + "Newtonsoft.Json": "12.0.3", + "System.Configuration.ConfigurationManager": "6.0.0" + } + }, + "Sustainsys.Saml2": { + "type": "Transitive", + "resolved": "2.9.0", + "contentHash": "dcAGeL36EkIfxuC794TzM3xYGEJiFmeBiwkDUTaHVGyu9/A3WuV5AbqZ0eWmwLco+tZJI9cbLaxeOd2oyhAARg==", + "dependencies": { + "Microsoft.Extensions.Caching.Memory": "2.1.2", + "Microsoft.IdentityModel.Protocols": "5.2.4", + "Microsoft.IdentityModel.Tokens": "5.2.4", + "Microsoft.IdentityModel.Tokens.Saml": "5.2.4", + "System.Configuration.ConfigurationManager": "4.4.1", + "System.Security.Cryptography.Xml": "4.5.0" + } + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Collections.NonGeneric": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "hMxFT2RhhlffyCdKLDXjx8WEC5JfCvNozAZxCablAuFRH74SCV4AgzE8yJCh/73bFnEoZgJ9MJmkjQ0dJmnKqA==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Collections.Specialized": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "/HKQyVP0yH1I0YtK7KJL/28snxHNH/bi+0lgk/+MbURF6ULhAE31MDI+NZDerNWu264YbxklXCCygISgm+HMug==", + "dependencies": { + "System.Collections.NonGeneric": "4.0.1", + "System.Globalization": "4.0.11", + "System.Globalization.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "6.0.0", + "System.Security.Permissions": "6.0.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Diagnostics.PerformanceCounter": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "kcQWWtGVC3MWMNXdMDWfrmIlFZZ2OdoeT6pSNVRtk9+Sa7jwdPiMlNwb0ZQcS7NRlT92pCfmjRtkSWUW3RAKwg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.Diagnostics.Process": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "J0wOX07+QASQblsfxmIMFc9Iq7KTXYL3zs2G/Xc704Ylv3NpuVdo6gij6V3PGiptTxqsK0K7CdXenRvKUnkA2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "Microsoft.Win32.Registry": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.TraceSource": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "6WVCczFZKXwpWpzd/iJkYnsmWTSFFiU24Xx/YdHXBcu+nFI/ehTgeqdJQFbtRPzbrO3KtRNjvkhtj4t5/WwWsA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Drawing.Common": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + } + }, + "System.Dynamic.Runtime": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "db34f6LHYM0U0JpE+sOmjar27BnqTVkbLJhgfwMpTdgTigG/Hna3m2MYVwnFzGGKnEJk2UXFuoVTr8WUbU91/A==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Formats.Asn1": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==" + }, + "System.Formats.Cbor": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "mGaLOoiw7KurJagOOcIsWUoCT5ACIiGxKlCcbYQASefBGXjnCcKTq5Hdjb94eEAKg38zXKlHw4c6EjzgBl9dIw==" + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IdentityModel.Tokens.Jwt": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "JRD8AuypBE+2zYxT3dMJomQVsPYsCqlyZhWel3J1d5nzQokSRyTueF+Q4ID3Jcu6zSZKuzOdJ1MLTkbQsDqcvQ==", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Rfm2jYCaUeGysFEZjDe7j1R4x6Z6BzumS/vUT5a1AA/AWJuGX71PoGB0RmpyX3VmrGqVnAwtfMn39OHR8Y/5+g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "qEePWsaq9LoEEIqhbGe6D5J8c9IqQOUuTzzV6wn1POlfdLkJliZY3OlB0j0f17uMWlqZYjH7txj+2YbyrIA8Yg==" + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Linq.Queryable": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "Yn/WfYe9RoRfmSLvUt2JerP0BTGGykCZkQPgojaxgzF2N0oPo+/AhB8TXOpdCcNlrG3VRtsamtK2uzsp3cqRVw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==", + "dependencies": { + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.6.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.4", + "contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.1", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.NameResolution": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "JdqRdM1Qym3YehqdKIi5LHrpypP4JMfxKQSNCJ2z4WawkG0il+N3XfNeJOxll2XrTnG7WgYYPoeiu/KOwg0DQw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.NetworkInformation": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "Q0rfeiW6QsiZuicGjrFA7cRr2+kXex0JIljTTxzI09GIftB8k+aNL31VsQD1sI2g31cw7UGDTgozA/FgeNSzsQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Linq": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.Sockets": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Overlapped": "4.0.1", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Requests": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "vxGt7C0cZixN+VqoSW4Yakc1Y9WknmxauDqzxgpw/FnBdz4kQNN51l4wxdXX5VY1xjqy//+G+4CvJWp1+f+y6Q==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Net.Http": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Claims": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Security.Principal": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Security": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Net.WebHeaderCollection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "XX2TIAN+wBSAIV51BU2FvvXMdstUa8b0FBSZmDWjZdwUMmggQSifpTOZ5fNH20z9ZCg2fkV1L5SsZnpO2RQDRQ==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0" + } + }, + "System.Net.WebSockets": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", + "dependencies": { + "Microsoft.Win32.Primitives": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.WebSockets.Client": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "NUCcDroX4lCQXgOrzlwIZ1u9YJ0krfyF0wk0ONnyLUmcQoEiYV2/OfUPRqUwQBbpH1BlGApkLgoQUwMqb5+c1g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.2", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Net.WebSockets": "4.0.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.X509Certificates": "4.1.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Numerics.Vectors": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Private.DataContractSerialization": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "lcqFBUaCZxPiUkA4dlSOoPZGtZsAuuElH2XHgLwGLxd7ZozWetV5yiz0qGAV2AUYOqw97MtZBjbLMN16Xz4vXA==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Collections.Concurrent": "4.0.12", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Emit.Lightweight": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1", + "System.Xml.XmlSerializer": "4.0.11" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Caching": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "30D6MkO8WF9jVGWZIP0hmCN8l9BTY4LCsAzLIe4xFSXzs+AjDotR7DpSmj27pFskDURzUvqYYY0ikModgBTxWw==", + "dependencies": { + "System.Configuration.ConfigurationManager": "5.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Runtime.Serialization.Json": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "+7DIJhnKYgCzUgcLbVTtRQb2l1M0FP549XFlFkQM5lmNiUBl44AfNbx4bz61xA8PzLtlYwfmif4JJJW7MPPnjg==", + "dependencies": { + "System.IO": "4.1.0", + "System.Private.DataContractSerialization": "4.1.1", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" + }, + "System.Security.Claims": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Security.Principal": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==", + "dependencies": { + "System.Formats.Asn1": "5.0.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Pkcs": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "elM3x+xSRhzQysiqo85SbidJJ2YbZlnvmh+53TuSZHsD7dNuuEWser+9EFtY+rYupBwkq2avc6ZCO3/6qACgmg==", + "dependencies": { + "System.Formats.Asn1": "6.0.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ==" + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Xml": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "i2Jn6rGXR63J0zIklImGRkDIJL4b1NfPSEbIVHBlqoIb12lfXIigCbDRpDmIEzwSo/v1U5y/rYJdzZYSyCWxvg==", + "dependencies": { + "System.Security.Cryptography.Pkcs": "4.5.0", + "System.Security.Permissions": "4.5.0" + } + }, + "System.Security.Permissions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==", + "dependencies": { + "System.Security.AccessControl": "6.0.0", + "System.Windows.Extensions": "6.0.0" + } + }, + "System.Security.Principal": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, + "System.Security.SecureString": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "sqzq9GD6/b0yqPuMpgIKBuoLf4VKAj8oAfh4kXSzPaN6eoKY3hRi9C5L27uip25qlU+BGPfb0xh2Rmbwc4jFVA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "NyscU59xX6Uo91qvhOs2Ccho3AR2TnZPomo1Z0K6YpyztBPM/A5VbkzOO19sy3A3i1TtEnTxA7bCe3Us+r5MWg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "zaJsHfESQvJ11vbXnNlkrR46IaMULk/gHxYsJphzSF+07kTjPHv+Oc14w6QEOfo3Q4hqLJgStUaYB9DBl0TmWg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Overlapped": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "f7aLuLkBoCQM2kng7zqLFBXz9Gk48gDK8lk1ih9rH/1arJJzZK9gJwNvPDhL6Ps/l6rwOr8jw+4FCHL0KKWiEg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Threading.Thread": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OHmbT+Zz065NKII/ZHcH9XO1dEuLGI1L2k7uYss+9C1jLxTC9kTZZuzUOyXHayRk+dft9CiDf3I/QZ0t8JKyBQ==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading.ThreadPool": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.ValueTuple": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" + }, + "System.Windows.Extensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==", + "dependencies": { + "System.Drawing.Common": "6.0.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "lJ8AxvkX7GQxpC6GFCeBj8ThYVyQczx2+f/cWHJU8tjS7YfI6Cv6bon70jVEgs2CiFbmmM8b9j1oZVx0dSI2Ww==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlSerializer": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "FrazwwqfIXTfq23mfv4zH+BjqkSFNaNFBtjzu3I9NRmG8EELYyrv/fJnttCIwRMFRR/YKXF1hmsMmMEnl55HGw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1" + } + }, + "System.Xml.XPath": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "v1JQ5SETnQusqmS3RwStF7vwQ3L02imIzl++sewmt23VGygix04pEH+FCj1yWb+z4GDzKiljr1W7Wfvrx0YwgA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XPath.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "A/uxsWi/Ifzkmd4ArTLISMbfFs6XpRPsXZonrIqyTY70xi8t+mDtvSM5Os0RqyRDobjMBwIDHDL4NOIbkDwf7A==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XPath": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "YubicoDotNetClient": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "uP5F3Ko1gqZi3lwS2R/jAAwhBxXs/6PKDpS6FdQjsBA5qmF0hQmbtfxM6QHTXOMoWbUtfetG7+LtgmG8T5zDIg==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "core": { + "type": "Project", + "dependencies": { + "AWSSDK.SQS": "[3.7.2.47, )", + "AWSSDK.SimpleEmail": "[3.7.0.150, )", + "AspNetCoreRateLimit": "[4.0.2, )", + "AspNetCoreRateLimit.Redis": "[1.0.1, )", + "Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.2.1, )", + "Azure.Storage.Blobs": "[12.11.0, )", + "Azure.Storage.Queues": "[12.9.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "Fido2.AspNet": "[3.0.1, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "MailKit": "[3.2.0, )", + "Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )", + "Microsoft.Azure.Cosmos.Table": "[1.0.8, )", + "Microsoft.Azure.NotificationHubs": "[4.1.0, )", + "Microsoft.Azure.ServiceBus": "[5.2.0, )", + "Microsoft.Data.SqlClient": "[5.0.1, )", + "Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )", + "Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )", + "Microsoft.Extensions.Identity.Stores": "[6.0.4, )", + "Newtonsoft.Json": "[13.0.1, )", + "Otp.NET": "[1.2.2, )", + "Quartz": "[3.4.0, )", + "SendGrid": "[9.27.0, )", + "Sentry.Serilog": "[3.16.0, )", + "Serilog.AspNetCore": "[5.0.0, )", + "Serilog.Extensions.Logging": "[3.1.0, )", + "Serilog.Extensions.Logging.File": "[2.0.0, )", + "Serilog.Sinks.AzureCosmosDB": "[2.0.0, )", + "Serilog.Sinks.SyslogMessages": "[2.0.6, )", + "Stripe.net": "[40.0.0, )", + "YubicoDotNetClient": "[1.2.0, )" + } + }, + "infrastructure.dapper": { + "type": "Project", + "dependencies": { + "Core": "[2023.1.0, )", + "Dapper": "[2.0.123, )" + } + }, + "infrastructure.entityframework": { + "type": "Project", + "dependencies": { + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", + "Core": "[2023.1.0, )", + "Microsoft.EntityFrameworkCore.Relational": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.SqlServer": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.Sqlite": "[6.0.12, )", + "Npgsql.EntityFrameworkCore.PostgreSQL": "[6.0.8, )", + "Pomelo.EntityFrameworkCore.MySql": "[6.0.2, )", + "linq2db.EntityFrameworkCore": "[6.11.0, )" + } + }, + "sharedweb": { + "type": "Project", + "dependencies": { + "Core": "[2023.1.0, )", + "Infrastructure.Dapper": "[2023.1.0, )", + "Infrastructure.EntityFramework": "[2023.1.0, )" + } + } + } + } +} \ No newline at end of file diff --git a/bitwarden_license/test/CmmCore.Test/AutoFixture/ProviderUserFixtures.cs b/bitwarden_license/test/CmmCore.Test/AutoFixture/ProviderUserFixtures.cs deleted file mode 100644 index 8dd7a94c6..000000000 --- a/bitwarden_license/test/CmmCore.Test/AutoFixture/ProviderUserFixtures.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Reflection; -using AutoFixture; -using AutoFixture.Xunit2; -using Bit.Core.Enums.Provider; - -namespace Bit.CommCore.Test.AutoFixture.ProviderUserFixtures -{ - internal class ProviderUser : ICustomization - { - public ProviderUserStatusType Status { get; set; } - public ProviderUserType Type { get; set; } - - public ProviderUser(ProviderUserStatusType status, ProviderUserType type) - { - Status = status; - Type = type; - } - - public void Customize(IFixture fixture) - { - fixture.Customize(composer => composer - .With(o => o.Type, Type) - .With(o => o.Status, Status)); - } - } - - public class ProviderUserAttribute : CustomizeAttribute - { - private readonly ProviderUserStatusType _status; - private readonly ProviderUserType _type; - - public ProviderUserAttribute( - ProviderUserStatusType status = ProviderUserStatusType.Confirmed, - ProviderUserType type = ProviderUserType.ProviderAdmin) - { - _status = status; - _type = type; - } - - public override ICustomization GetCustomization(ParameterInfo parameter) - { - return new ProviderUser(_status, _type); - } - } -} diff --git a/bitwarden_license/test/CmmCore.Test/Services/ProviderServiceTests.cs b/bitwarden_license/test/CmmCore.Test/Services/ProviderServiceTests.cs deleted file mode 100644 index a46d85443..000000000 --- a/bitwarden_license/test/CmmCore.Test/Services/ProviderServiceTests.cs +++ /dev/null @@ -1,555 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Bit.CommCore.Test.AutoFixture.ProviderUserFixtures; -using Bit.CommCore.Services; -using Bit.Core.Enums; -using Bit.Core.Enums.Provider; -using Bit.Core.Exceptions; -using Bit.Core.Models.Business; -using Bit.Core.Models.Business.Provider; -using Bit.Core.Models.Table; -using Bit.Core.Models.Table.Provider; -using Bit.Core.Repositories; -using Bit.Core.Services; -using Bit.Core.Test.AutoFixture; -using Bit.Core.Test.AutoFixture.Attributes; -using Bit.Core.Utilities; -using Microsoft.AspNetCore.DataProtection; -using NSubstitute; -using NSubstitute.ReturnsExtensions; -using Xunit; -using ProviderUser = Bit.Core.Models.Table.Provider.ProviderUser; -using Bit.Core.Context; - -namespace Bit.CommCore.Test.Services -{ - public class ProviderServiceTests - { - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task CreateAsync_UserIdIsInvalid_Throws(SutProvider sutProvider) - { - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.CreateAsync(default)); - Assert.Contains("Invalid owner.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task CreateAsync_Success(User user, SutProvider sutProvider) - { - var userRepository = sutProvider.GetDependency(); - userRepository.GetByEmailAsync(user.Email).Returns(user); - - await sutProvider.Sut.CreateAsync(user.Email); - - await sutProvider.GetDependency().ReceivedWithAnyArgs().CreateAsync(default); - await sutProvider.GetDependency().ReceivedWithAnyArgs().SendProviderSetupInviteEmailAsync(default, default, default); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task CompleteSetupAsync_UserIdIsInvalid_Throws(SutProvider sutProvider) - { - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.CompleteSetupAsync(default, default, default, default)); - Assert.Contains("Invalid owner.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task CompleteSetupAsync_TokenIsInvalid_Throws(User user, Provider provider, - SutProvider sutProvider) - { - var userService = sutProvider.GetDependency(); - userService.GetUserByIdAsync(user.Id).Returns(user); - - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.CompleteSetupAsync(provider, user.Id, default, default)); - Assert.Contains("Invalid token.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task CompleteSetupAsync_Success(User user, Provider provider, string key, - [ProviderUser(ProviderUserStatusType.Confirmed, ProviderUserType.ProviderAdmin)]ProviderUser providerUser, - SutProvider sutProvider) - { - providerUser.ProviderId = provider.Id; - providerUser.UserId = user.Id; - var userService = sutProvider.GetDependency(); - userService.GetUserByIdAsync(user.Id).Returns(user); - - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetByProviderUserAsync(provider.Id, user.Id).Returns(providerUser); - - var dataProtectionProvider = DataProtectionProvider.Create("ApplicationName"); - var protector = dataProtectionProvider.CreateProtector("ProviderServiceDataProtector"); - sutProvider.GetDependency().CreateProtector("ProviderServiceDataProtector") - .Returns(protector); - sutProvider.Create(); - - var token = protector.Protect($"ProviderSetupInvite {provider.Id} {user.Email} {CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow)}"); - - await sutProvider.Sut.CompleteSetupAsync(provider, user.Id, token, key); - - await sutProvider.GetDependency().Received().UpsertAsync(provider); - await sutProvider.GetDependency().Received() - .ReplaceAsync(Arg.Is(pu => pu.UserId == user.Id && pu.ProviderId == provider.Id && pu.Key == key)); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task UpdateAsync_ProviderIdIsInvalid_Throws(Provider provider, SutProvider sutProvider) - { - provider.Id = default; - - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.UpdateAsync(provider)); - Assert.Contains("Cannot create provider this way.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task UpdateAsync_Success(Provider provider, SutProvider sutProvider) - { - await sutProvider.Sut.UpdateAsync(provider); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task InviteUserAsync_ProviderIdIsInvalid_Throws(ProviderUserInvite invite, SutProvider sutProvider) - { - sutProvider.GetDependency().ProviderManageUsers(invite.ProviderId).Returns(true); - - await Assert.ThrowsAsync(() => sutProvider.Sut.InviteUserAsync(invite)); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task InviteUserAsync_InvalidPermissions_Throws(ProviderUserInvite invite, SutProvider sutProvider) - { - sutProvider.GetDependency().ProviderManageUsers(invite.ProviderId).Returns(false); - await Assert.ThrowsAsync(() => sutProvider.Sut.InviteUserAsync(invite)); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task InviteUserAsync_EmailsInvalid_Throws(Provider provider, ProviderUserInvite providerUserInvite, - SutProvider sutProvider) - { - var providerRepository = sutProvider.GetDependency(); - providerRepository.GetByIdAsync(providerUserInvite.ProviderId).Returns(provider); - sutProvider.GetDependency().ProviderManageUsers(providerUserInvite.ProviderId).Returns(true); - - providerUserInvite.UserIdentifiers = null; - - await Assert.ThrowsAsync(() => sutProvider.Sut.InviteUserAsync(providerUserInvite)); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task InviteUserAsync_AlreadyInvited(Provider provider, ProviderUserInvite providerUserInvite, - SutProvider sutProvider) - { - var providerRepository = sutProvider.GetDependency(); - providerRepository.GetByIdAsync(providerUserInvite.ProviderId).Returns(provider); - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetCountByProviderAsync(default, default, default).ReturnsForAnyArgs(1); - sutProvider.GetDependency().ProviderManageUsers(providerUserInvite.ProviderId).Returns(true); - - var result = await sutProvider.Sut.InviteUserAsync(providerUserInvite); - Assert.Empty(result); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task InviteUserAsync_Success(Provider provider, ProviderUserInvite providerUserInvite, - SutProvider sutProvider) - { - var providerRepository = sutProvider.GetDependency(); - providerRepository.GetByIdAsync(providerUserInvite.ProviderId).Returns(provider); - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetCountByProviderAsync(default, default, default).ReturnsForAnyArgs(0); - sutProvider.GetDependency().ProviderManageUsers(providerUserInvite.ProviderId).Returns(true); - - var result = await sutProvider.Sut.InviteUserAsync(providerUserInvite); - Assert.Equal(providerUserInvite.UserIdentifiers.Count(), result.Count); - Assert.True(result.TrueForAll(pu => pu.Status == ProviderUserStatusType.Invited), "Status must be invited"); - Assert.True(result.TrueForAll(pu => pu.ProviderId == providerUserInvite.ProviderId), "Provider Id must be correct"); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task ResendInviteUserAsync_InvalidPermissions_Throws(ProviderUserInvite invite, SutProvider sutProvider) - { - sutProvider.GetDependency().ProviderManageUsers(invite.ProviderId).Returns(false); - await Assert.ThrowsAsync(() => sutProvider.Sut.ResendInvitesAsync(invite)); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task ResendInvitesAsync_Errors(Provider provider, - [ProviderUser(ProviderUserStatusType.Invited)]ProviderUser pu1, - [ProviderUser(ProviderUserStatusType.Accepted)]ProviderUser pu2, - [ProviderUser(ProviderUserStatusType.Confirmed)]ProviderUser pu3, - [ProviderUser(ProviderUserStatusType.Invited)]ProviderUser pu4, - SutProvider sutProvider) - { - var providerUsers = new[] {pu1, pu2, pu3, pu4}; - pu1.ProviderId = pu2.ProviderId = pu3.ProviderId = provider.Id; - - var invite = new ProviderUserInvite - { - UserIdentifiers = providerUsers.Select(pu => pu.Id), - ProviderId = provider.Id - }; - - var providerRepository = sutProvider.GetDependency(); - providerRepository.GetByIdAsync(provider.Id).Returns(provider); - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers.ToList()); - sutProvider.GetDependency().ProviderManageUsers(invite.ProviderId).Returns(true); - - var result = await sutProvider.Sut.ResendInvitesAsync(invite); - Assert.Equal("", result[0].Item2); - Assert.Equal("User invalid.", result[1].Item2); - Assert.Equal("User invalid.", result[2].Item2); - Assert.Equal("User invalid.", result[3].Item2); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task ResendInvitesAsync_Success(Provider provider, IEnumerable providerUsers, - SutProvider sutProvider) - { - foreach (var providerUser in providerUsers) - { - providerUser.ProviderId = provider.Id; - providerUser.Status = ProviderUserStatusType.Invited; - } - - var invite = new ProviderUserInvite - { - UserIdentifiers = providerUsers.Select(pu => pu.Id), - ProviderId = provider.Id - }; - - var providerRepository = sutProvider.GetDependency(); - providerRepository.GetByIdAsync(provider.Id).Returns(provider); - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers.ToList()); - sutProvider.GetDependency().ProviderManageUsers(invite.ProviderId).Returns(true); - - var result = await sutProvider.Sut.ResendInvitesAsync(invite); - Assert.True(result.All(r => r.Item2 == "")); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task AcceptUserAsync_UserIsInvalid_Throws(ProviderUser providerUser, User user, - SutProvider sutProvider) - { - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.AcceptUserAsync(default, default, default)); - Assert.Equal("User invalid.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task AcceptUserAsync_AlreadyAccepted_Throws( - [ProviderUser(ProviderUserStatusType.Accepted)]ProviderUser providerUser, User user, - SutProvider sutProvider) - { - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetByIdAsync(providerUser.Id).Returns(providerUser); - - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.AcceptUserAsync(providerUser.Id, user, default)); - Assert.Equal("Already accepted.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task AcceptUserAsync_TokenIsInvalid_Throws( - [ProviderUser(ProviderUserStatusType.Invited)]ProviderUser providerUser, User user, - SutProvider sutProvider) - { - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetByIdAsync(providerUser.Id).Returns(providerUser); - - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.AcceptUserAsync(providerUser.Id, user, default)); - Assert.Equal("Invalid token.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task AcceptUserAsync_WrongEmail_Throws( - [ProviderUser(ProviderUserStatusType.Invited)]ProviderUser providerUser, User user, - SutProvider sutProvider) - { - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetByIdAsync(providerUser.Id).Returns(providerUser); - - var dataProtectionProvider = DataProtectionProvider.Create("ApplicationName"); - var protector = dataProtectionProvider.CreateProtector("ProviderServiceDataProtector"); - sutProvider.GetDependency().CreateProtector("ProviderServiceDataProtector") - .Returns(protector); - sutProvider.Create(); - - var token = protector.Protect($"ProviderUserInvite {providerUser.Id} {user.Email} {CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow)}"); - - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.AcceptUserAsync(providerUser.Id, user, token)); - Assert.Equal("User email does not match invite.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task AcceptUserAsync_Success( - [ProviderUser(ProviderUserStatusType.Invited)]ProviderUser providerUser, User user, - SutProvider sutProvider) - { - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetByIdAsync(providerUser.Id).Returns(providerUser); - - var dataProtectionProvider = DataProtectionProvider.Create("ApplicationName"); - var protector = dataProtectionProvider.CreateProtector("ProviderServiceDataProtector"); - sutProvider.GetDependency().CreateProtector("ProviderServiceDataProtector") - .Returns(protector); - sutProvider.Create(); - - providerUser.Email = user.Email; - var token = protector.Protect($"ProviderUserInvite {providerUser.Id} {user.Email} {CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow)}"); - - var pu = await sutProvider.Sut.AcceptUserAsync(providerUser.Id, user, token); - Assert.Null(pu.Email); - Assert.Equal(ProviderUserStatusType.Accepted, pu.Status); - Assert.Equal(user.Id, pu.UserId); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task ConfirmUsersAsync_NoValid( - [ProviderUser(ProviderUserStatusType.Invited)]ProviderUser pu1, - [ProviderUser(ProviderUserStatusType.Accepted)]ProviderUser pu2, - [ProviderUser(ProviderUserStatusType.Confirmed)]ProviderUser pu3, - SutProvider sutProvider) - { - pu1.ProviderId = pu3.ProviderId; - var providerUsers = new[] {pu1, pu2, pu3}; - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers); - - var dict = providerUsers.ToDictionary(pu => pu.Id, _ => "key"); - var result = await sutProvider.Sut.ConfirmUsersAsync(pu1.ProviderId, dict, default); - - Assert.Empty(result); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task ConfirmUsersAsync_Success( - [ProviderUser(ProviderUserStatusType.Invited)]ProviderUser pu1, User u1, - [ProviderUser(ProviderUserStatusType.Accepted)]ProviderUser pu2, User u2, - [ProviderUser(ProviderUserStatusType.Confirmed)]ProviderUser pu3, User u3, - Provider provider, User user, SutProvider sutProvider) - { - pu1.ProviderId = pu2.ProviderId = pu3.ProviderId = provider.Id; - pu1.UserId = u1.Id; - pu2.UserId = u2.Id; - pu3.UserId = u3.Id; - var providerUsers = new[] {pu1, pu2, pu3}; - - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers); - var providerRepository = sutProvider.GetDependency(); - providerRepository.GetByIdAsync(provider.Id).Returns(provider); - var userRepository = sutProvider.GetDependency(); - userRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] {u1, u2, u3}); - - var dict = providerUsers.ToDictionary(pu => pu.Id, _ => "key"); - var result = await sutProvider.Sut.ConfirmUsersAsync(pu1.ProviderId, dict, user.Id); - - Assert.Equal("Invalid user.", result[0].Item2); - Assert.Equal("", result[1].Item2); - Assert.Equal("Invalid user.", result[2].Item2); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task SaveUserAsync_UserIdIsInvalid_Throws(ProviderUser providerUser, - SutProvider sutProvider) - { - providerUser.Id = default; - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.SaveUserAsync(providerUser, default)); - Assert.Equal("Invite the user first.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task SaveUserAsync_Success( - [ProviderUser(type: ProviderUserType.ProviderAdmin)]ProviderUser providerUser, User savingUser, - SutProvider sutProvider) - { - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetByIdAsync(providerUser.Id).Returns(providerUser); - - await sutProvider.Sut.SaveUserAsync(providerUser, savingUser.Id); - await providerUserRepository.Received().ReplaceAsync(providerUser); - await sutProvider.GetDependency().Received() - .LogProviderUserEventAsync(providerUser, EventType.ProviderUser_Updated, null); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task DeleteUsersAsync_NoRemainingOwner_Throws(Provider provider, User deletingUser, - ICollection providerUsers, SutProvider sutProvider) - { - var userIds = providerUsers.Select(pu => pu.Id); - - providerUsers.First().UserId = deletingUser.Id; - foreach (var providerUser in providerUsers) - { - providerUser.ProviderId = provider.Id; - } - providerUsers.Last().ProviderId = default; - - sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers); - providerUserRepository.GetManyByProviderAsync(default, default).ReturnsForAnyArgs(new ProviderUser[] {}); - - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.DeleteUsersAsync(provider.Id, userIds, deletingUser.Id)); - Assert.Equal("Provider must have at least one confirmed ProviderAdmin.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task DeleteUsersAsync_Success(Provider provider, User deletingUser, ICollection providerUsers, - [ProviderUser(ProviderUserStatusType.Confirmed, ProviderUserType.ProviderAdmin)]ProviderUser remainingOwner, - SutProvider sutProvider) - { - var userIds = providerUsers.Select(pu => pu.Id); - - providerUsers.First().UserId = deletingUser.Id; - foreach (var providerUser in providerUsers) - { - providerUser.ProviderId = provider.Id; - } - providerUsers.Last().ProviderId = default; - - sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); - var providerUserRepository = sutProvider.GetDependency(); - providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers); - providerUserRepository.GetManyByProviderAsync(default, default).ReturnsForAnyArgs(new[] {remainingOwner}); - - var result = await sutProvider.Sut.DeleteUsersAsync(provider.Id, userIds, deletingUser.Id); - - Assert.NotEmpty(result); - Assert.Equal("You cannot remove yourself.", result[0].Item2); - Assert.Equal("", result[1].Item2); - Assert.Equal("Invalid user.", result[2].Item2); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task AddOrganization_OrganizationAlreadyBelongsToAProvider_Throws(Provider provider, - Organization organization, ProviderOrganization po, User user, string key, - SutProvider sutProvider) - { - po.OrganizationId = organization.Id; - sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); - sutProvider.GetDependency().GetByOrganizationId(organization.Id) - .Returns(po); - - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.AddOrganization(provider.Id, organization.Id, user.Id, key)); - Assert.Equal("Organization already belongs to a provider.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task AddOrganization_Success(Provider provider, Organization organization, User user, string key, - SutProvider sutProvider) - { - organization.PlanType = PlanType.EnterpriseAnnually; - - sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); - var providerOrganizationRepository = sutProvider.GetDependency(); - providerOrganizationRepository.GetByOrganizationId(organization.Id).ReturnsNull(); - sutProvider.GetDependency().GetByIdAsync(organization.Id).Returns(organization); - - await sutProvider.Sut.AddOrganization(provider.Id, organization.Id, user.Id, key); - - await providerOrganizationRepository.ReceivedWithAnyArgs().CreateAsync(default); - await sutProvider.GetDependency() - .Received().LogProviderOrganizationEventAsync(Arg.Any(), - EventType.ProviderOrganization_Added); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task CreateOrganizationAsync_Success(Provider provider, OrganizationSignup organizationSignup, - Organization organization, string clientOwnerEmail, User user, SutProvider sutProvider) - { - organizationSignup.Plan = PlanType.EnterpriseAnnually; - - sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); - var providerOrganizationRepository = sutProvider.GetDependency(); - sutProvider.GetDependency().SignUpAsync(organizationSignup, true) - .Returns(Tuple.Create(organization, null as OrganizationUser)); - - var providerOrganization = - await sutProvider.Sut.CreateOrganizationAsync(provider.Id, organizationSignup, clientOwnerEmail, user); - - await providerOrganizationRepository.ReceivedWithAnyArgs().CreateAsync(default); - await sutProvider.GetDependency() - .Received().LogProviderOrganizationEventAsync(providerOrganization, - EventType.ProviderOrganization_Created); - await sutProvider.GetDependency() - .Received().InviteUsersAsync(organization.Id, user.Id, Arg.Is>( - t => t.Count() == 1 && - t.First().Item1.Emails.Count() == 1 && - t.First().Item1.Emails.First() == clientOwnerEmail && - t.First().Item1.Type == OrganizationUserType.Owner && - t.First().Item1.AccessAll && - t.First().Item2 == null)); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task RemoveOrganization_ProviderOrganizationIsInvalid_Throws(Provider provider, - ProviderOrganization providerOrganization, User user, SutProvider sutProvider) - { - sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); - sutProvider.GetDependency().GetByIdAsync(providerOrganization.Id) - .ReturnsNull(); - - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.RemoveOrganizationAsync(provider.Id, providerOrganization.Id, user.Id)); - Assert.Equal("Invalid organization.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task RemoveOrganization_ProviderOrganizationBelongsToWrongProvider_Throws(Provider provider, - ProviderOrganization providerOrganization, User user, SutProvider sutProvider) - { - sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); - sutProvider.GetDependency().GetByIdAsync(providerOrganization.Id) - .Returns(providerOrganization); - - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.RemoveOrganizationAsync(provider.Id, providerOrganization.Id, user.Id)); - Assert.Equal("Invalid organization.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task RemoveOrganization_HasNoOwners_Throws(Provider provider, - ProviderOrganization providerOrganization, User user, SutProvider sutProvider) - { - providerOrganization.ProviderId = provider.Id; - sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); - sutProvider.GetDependency().GetByIdAsync(providerOrganization.Id) - .Returns(providerOrganization); - sutProvider.GetDependency().HasConfirmedOwnersExceptAsync(default, default, default) - .ReturnsForAnyArgs(false); - - var exception = await Assert.ThrowsAsync( - () => sutProvider.Sut.RemoveOrganizationAsync(provider.Id, providerOrganization.Id, user.Id)); - Assert.Equal("Organization needs to have at least one confirmed owner.", exception.Message); - } - - [Theory, CustomAutoData(typeof(SutProviderCustomization))] - public async Task RemoveOrganization_Success(Provider provider, - ProviderOrganization providerOrganization, User user, SutProvider sutProvider) - { - providerOrganization.ProviderId = provider.Id; - sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); - var providerOrganizationRepository = sutProvider.GetDependency(); - providerOrganizationRepository.GetByIdAsync(providerOrganization.Id).Returns(providerOrganization); - sutProvider.GetDependency().HasConfirmedOwnersExceptAsync(default, default, default) - .ReturnsForAnyArgs(true); - - await sutProvider.Sut.RemoveOrganizationAsync(provider.Id, providerOrganization.Id, user.Id); - await providerOrganizationRepository.Received().DeleteAsync(providerOrganization); - await sutProvider.GetDependency().Received() - .LogProviderOrganizationEventAsync(providerOrganization, EventType.ProviderOrganization_Removed); - } - } -} diff --git a/bitwarden_license/test/Commercial.Core.Test/AutoFixture/ProviderUserFixtures.cs b/bitwarden_license/test/Commercial.Core.Test/AutoFixture/ProviderUserFixtures.cs new file mode 100644 index 000000000..48f70c335 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/AutoFixture/ProviderUserFixtures.cs @@ -0,0 +1,44 @@ +using System.Reflection; +using AutoFixture; +using AutoFixture.Xunit2; +using Bit.Core.Enums.Provider; + +namespace Bit.Commercial.Core.Test.AutoFixture; + +internal class ProviderUser : ICustomization +{ + public ProviderUserStatusType Status { get; set; } + public ProviderUserType Type { get; set; } + + public ProviderUser(ProviderUserStatusType status, ProviderUserType type) + { + Status = status; + Type = type; + } + + public void Customize(IFixture fixture) + { + fixture.Customize(composer => composer + .With(o => o.Type, Type) + .With(o => o.Status, Status)); + } +} + +public class ProviderUserAttribute : CustomizeAttribute +{ + private readonly ProviderUserStatusType _status; + private readonly ProviderUserType _type; + + public ProviderUserAttribute( + ProviderUserStatusType status = ProviderUserStatusType.Confirmed, + ProviderUserType type = ProviderUserType.ProviderAdmin) + { + _status = status; + _type = type; + } + + public override ICustomization GetCustomization(ParameterInfo parameter) + { + return new ProviderUser(_status, _type); + } +} diff --git a/bitwarden_license/test/CmmCore.Test/CommCore.Test.csproj b/bitwarden_license/test/Commercial.Core.Test/Commercial.Core.Test.csproj similarity index 69% rename from bitwarden_license/test/CmmCore.Test/CommCore.Test.csproj rename to bitwarden_license/test/Commercial.Core.Test/Commercial.Core.Test.csproj index 5a319e5e8..6c92db92b 100644 --- a/bitwarden_license/test/CmmCore.Test/CommCore.Test.csproj +++ b/bitwarden_license/test/Commercial.Core.Test/Commercial.Core.Test.csproj @@ -1,26 +1,24 @@ - net5.0 - false - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/CreateAccessPoliciesCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/CreateAccessPoliciesCommandTests.cs new file mode 100644 index 000000000..6005f1a9a --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/CreateAccessPoliciesCommandTests.cs @@ -0,0 +1,126 @@ +using Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies; +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretsManager.AccessPolicies; + +[SutProviderCustomize] +public class CreateAccessPoliciesCommandTests +{ + [Theory] + [BitAutoData] + public async Task CreateAsync_CallsCreate(List userProjectAccessPolicies, + List groupProjectAccessPolicies, + List serviceAccountProjectAccessPolicies, + SutProvider sutProvider) + { + var data = new List(); + data.AddRange(userProjectAccessPolicies); + data.AddRange(groupProjectAccessPolicies); + data.AddRange(serviceAccountProjectAccessPolicies); + + await sutProvider.Sut.CreateAsync(data); + + await sutProvider.GetDependency().Received(1) + .CreateManyAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data))); + } + + [Theory] + [BitAutoData] + public async Task CreateAsync_AlreadyExists_Throws_BadRequestException( + List userProjectAccessPolicies, + List groupProjectAccessPolicies, + List serviceAccountProjectAccessPolicies, + SutProvider sutProvider) + { + var data = new List(); + data.AddRange(userProjectAccessPolicies); + data.AddRange(groupProjectAccessPolicies); + data.AddRange(serviceAccountProjectAccessPolicies); + + sutProvider.GetDependency().AccessPolicyExists(Arg.Any()) + .Returns(true); + + var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.CreateAsync(data)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().CreateManyAsync(default); + } + + + [Theory] + [BitAutoData(true, false, false)] + [BitAutoData(false, true, false)] + [BitAutoData(true, true, false)] + [BitAutoData(false, false, true)] + [BitAutoData(true, false, true)] + [BitAutoData(false, true, true)] + [BitAutoData(true, true, true)] + public async Task CreateAsync_NotUnique_ThrowsException( + bool testUserPolicies, + bool testGroupPolicies, + bool testServiceAccountPolicies, + List userProjectAccessPolicies, + List groupProjectAccessPolicies, + List serviceAccountProjectAccessPolicies, + SutProvider sutProvider + ) + { + var data = new List(); + data.AddRange(userProjectAccessPolicies); + data.AddRange(groupProjectAccessPolicies); + data.AddRange(serviceAccountProjectAccessPolicies); + + if (testUserPolicies) + { + var mockUserPolicy = new UserProjectAccessPolicy + { + OrganizationUserId = Guid.NewGuid(), + GrantedProjectId = Guid.NewGuid() + }; + data.Add(mockUserPolicy); + + // Add a duplicate policy + data.Add(mockUserPolicy); + } + + if (testGroupPolicies) + { + var mockGroupPolicy = new GroupProjectAccessPolicy + { + GroupId = Guid.NewGuid(), + GrantedProjectId = Guid.NewGuid() + }; + data.Add(mockGroupPolicy); + + // Add a duplicate policy + data.Add(mockGroupPolicy); + } + + if (testServiceAccountPolicies) + { + var mockServiceAccountPolicy = new ServiceAccountProjectAccessPolicy + { + ServiceAccountId = Guid.NewGuid(), + GrantedProjectId = Guid.NewGuid() + }; + data.Add(mockServiceAccountPolicy); + + // Add a duplicate policy + data.Add(mockServiceAccountPolicy); + } + + + sutProvider.GetDependency().AccessPolicyExists(Arg.Any()) + .Returns(true); + + var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.CreateAsync(data)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().CreateManyAsync(default); + } +} diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/DeleteAccessPolicyCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/DeleteAccessPolicyCommandTests.cs new file mode 100644 index 000000000..dfb09eb44 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/DeleteAccessPolicyCommandTests.cs @@ -0,0 +1,38 @@ +using Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies; +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using NSubstitute; +using NSubstitute.ReturnsExtensions; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretsManager.AccessPolicies; + +[SutProviderCustomize] +public class DeleteAccessPolicyCommandTests +{ + [Theory] + [BitAutoData] + public async Task DeleteAccessPolicy_Throws_NotFoundException(Guid data, + SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(data).ReturnsNull(); + var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteAsync(data)); + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().DeleteAsync(default); + } + + [Theory] + [BitAutoData] + public async Task DeleteAccessPolicy_Success(Guid data, + SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(data) + .Returns(new UserProjectAccessPolicy { Id = data }); + + await sutProvider.Sut.DeleteAsync(data); + + await sutProvider.GetDependency().Received(1).DeleteAsync(Arg.Is(data)); + } +} diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/UpdateAccessPolicyCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/UpdateAccessPolicyCommandTests.cs new file mode 100644 index 000000000..482be4839 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessPolicies/UpdateAccessPolicyCommandTests.cs @@ -0,0 +1,40 @@ +using Bit.Commercial.Core.SecretsManager.Commands.AccessPolicies; +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretsManager.AccessPolicies; + +[SutProviderCustomize] +public class UpdateAccessPolicyCommandTests +{ + [Theory] + [BitAutoData] + public async Task UpdateAsync_Throws_NotFoundException(Guid data, bool read, bool write, + SutProvider sutProvider) + { + var exception = + await Assert.ThrowsAsync(() => sutProvider.Sut.UpdateAsync(data, read, write)); + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().ReplaceAsync(default); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_Calls_Replace(Guid data, bool read, bool write, + SutProvider sutProvider) + { + var existingPolicy = new UserProjectAccessPolicy { Id = data, Read = true, Write = true }; + sutProvider.GetDependency().GetByIdAsync(data).Returns(existingPolicy); + var result = await sutProvider.Sut.UpdateAsync(data, read, write); + await sutProvider.GetDependency().Received(1).ReplaceAsync(existingPolicy); + + AssertHelper.AssertRecent(result.RevisionDate); + Assert.Equal(read, result.Read); + Assert.Equal(write, result.Write); + } +} diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessTokens/CreateAccessTokenCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessTokens/CreateAccessTokenCommandTests.cs new file mode 100644 index 000000000..d9b2027c3 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AccessTokens/CreateAccessTokenCommandTests.cs @@ -0,0 +1,74 @@ +using Bit.Commercial.Core.SecretsManager.Commands.AccessTokens; +using Bit.Core.Context; +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretsManager.AccessTokens; + +[SutProviderCustomize] +public class CreateServiceAccountCommandTests +{ + [Theory] + [BitAutoData] + public async Task CreateAsync_NoServiceAccountId_ThrowsBadRequestException(ApiKey data, Guid userId, + SutProvider sutProvider) + { + data.ServiceAccountId = null; + + await Assert.ThrowsAsync(() => sutProvider.Sut.CreateAsync(data, userId)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().CreateAsync(default); + } + + [Theory] + [BitAutoData] + public async Task CreateAsync_User_NoAccess(ApiKey data, Guid userId, ServiceAccount saData, + SutProvider sutProvider) + { + data.ServiceAccountId = saData.Id; + + sutProvider.GetDependency().GetByIdAsync(saData.Id).Returns(saData); + sutProvider.GetDependency().UserHasWriteAccessToServiceAccount(saData.Id, userId).Returns(false); + + await Assert.ThrowsAsync(() => sutProvider.Sut.CreateAsync(data, userId)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().CreateAsync(default); + } + + [Theory] + [BitAutoData] + public async Task CreateAsync_User_Success(ApiKey data, Guid userId, ServiceAccount saData, + SutProvider sutProvider) + { + data.ServiceAccountId = saData.Id; + sutProvider.GetDependency().GetByIdAsync(saData.Id).Returns(saData); + sutProvider.GetDependency().UserHasWriteAccessToServiceAccount(saData.Id, userId).Returns(true); + + await sutProvider.Sut.CreateAsync(data, userId); + + await sutProvider.GetDependency().Received(1) + .CreateAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data))); + } + + [Theory] + [BitAutoData] + public async Task CreateAsync_Admin_Succeeds(ApiKey data, Guid userId, ServiceAccount saData, + SutProvider sutProvider) + { + data.ServiceAccountId = saData.Id; + + sutProvider.GetDependency().GetByIdAsync(saData.Id).Returns(saData); + sutProvider.GetDependency().OrganizationAdmin(saData.OrganizationId).Returns(true); + + await sutProvider.Sut.CreateAsync(data, userId); + + await sutProvider.GetDependency().Received(1) + .CreateAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data))); + } +} diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/DeleteProjectCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/DeleteProjectCommandTests.cs new file mode 100644 index 000000000..3d93d3979 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/DeleteProjectCommandTests.cs @@ -0,0 +1,105 @@ +using Bit.Commercial.Core.SecretsManager.Commands.Projects; +using Bit.Core.Context; +using Bit.Core.Exceptions; +using Bit.Core.Identity; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretsManager.Projects; + +[SutProviderCustomize] +public class DeleteProjectCommandTests +{ + [Theory] + [BitAutoData] + public async Task DeleteProjects_Throws_NotFoundException(List data, Guid userId, + SutProvider sutProvider) + { + sutProvider.GetDependency().GetManyByIds(data).Returns(new List()); + + await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteProjects(data, userId)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().DeleteManyByIdAsync(default); + } + + [Theory] + [BitAutoData] + public async Task DeleteSecrets_OneIdNotFound_Throws_NotFoundException(List data, Guid userId, + SutProvider sutProvider) + { + var project = new Project() + { + Id = Guid.NewGuid() + }; + sutProvider.GetDependency().GetManyByIds(data).Returns(new List() { project }); + + await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteProjects(data, userId)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().DeleteManyByIdAsync(default); + } + + [Theory] + [BitAutoData] + public async Task DeleteSecrets_User_Success(List data, Guid userId, Guid organizationId, + SutProvider sutProvider) + { + var projects = data.Select(id => new Project { Id = id, OrganizationId = organizationId }).ToList(); + + sutProvider.GetDependency().ClientType = ClientType.User; + sutProvider.GetDependency().GetManyByIds(data).Returns(projects); + sutProvider.GetDependency().UserHasWriteAccessToProject(Arg.Any(), userId).Returns(true); + + var results = await sutProvider.Sut.DeleteProjects(data, userId); + + foreach (var result in results) + { + Assert.Equal("", result.Item2); + } + + await sutProvider.GetDependency().Received(1).DeleteManyByIdAsync(Arg.Is>(d => d.SequenceEqual(data))); + } + + [Theory] + [BitAutoData] + public async Task DeleteSecrets_User_No_Permission(List data, Guid userId, Guid organizationId, + SutProvider sutProvider) + { + var projects = data.Select(id => new Project { Id = id, OrganizationId = organizationId }).ToList(); + + sutProvider.GetDependency().ClientType = ClientType.User; + sutProvider.GetDependency().GetManyByIds(data).Returns(projects); + sutProvider.GetDependency().UserHasWriteAccessToProject(userId, userId).Returns(false); + + var results = await sutProvider.Sut.DeleteProjects(data, userId); + + foreach (var result in results) + { + Assert.Equal("access denied", result.Item2); + } + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().DeleteManyByIdAsync(default); + } + + [Theory] + [BitAutoData] + public async Task DeleteSecrets_OrganizationAdmin_Success(List data, Guid userId, Guid organizationId, + SutProvider sutProvider) + { + var projects = data.Select(id => new Project { Id = id, OrganizationId = organizationId }).ToList(); + + sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(true); + sutProvider.GetDependency().GetManyByIds(data).Returns(projects); + + var results = await sutProvider.Sut.DeleteProjects(data, userId); + + await sutProvider.GetDependency().Received(1).DeleteManyByIdAsync(Arg.Is>(d => d.SequenceEqual(data))); + foreach (var result in results) + { + Assert.Equal("", result.Item2); + } + } +} diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/UpdateProjectCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/UpdateProjectCommandTests.cs new file mode 100644 index 000000000..d85a44a91 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Projects/UpdateProjectCommandTests.cs @@ -0,0 +1,75 @@ +using Bit.Commercial.Core.SecretsManager.Commands.Projects; +using Bit.Core.Context; +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; +using Bit.Core.Test.SecretsManager.AutoFixture.ProjectsFixture; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using NSubstitute.ReturnsExtensions; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretsManager.Projects; + +[SutProviderCustomize] +[ProjectCustomize] +public class UpdateProjectCommandTests +{ + [Theory] + [BitAutoData] + public async Task UpdateAsync_Throws_NotFoundException(Project project, Guid userId, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(project.Id).ReturnsNull(); + + await Assert.ThrowsAsync(() => sutProvider.Sut.UpdateAsync(project, userId)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().ReplaceAsync(default); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_Admin_Succeeds(Project project, Guid userId, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(project.Id).Returns(project); + sutProvider.GetDependency().OrganizationAdmin(project.OrganizationId).Returns(true); + + var project2 = new Project { Id = project.Id, Name = "newName" }; + var result = await sutProvider.Sut.UpdateAsync(project2, userId); + + Assert.NotNull(result); + Assert.Equal("newName", result.Name); + AssertHelper.AssertRecent(result.RevisionDate); + + await sutProvider.GetDependency().ReceivedWithAnyArgs(1).ReplaceAsync(default); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_User_NoAccess(Project project, Guid userId, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(project.Id).Returns(project); + sutProvider.GetDependency().UserHasWriteAccessToProject(project.Id, userId).Returns(false); + + await Assert.ThrowsAsync(() => sutProvider.Sut.UpdateAsync(project, userId)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().ReplaceAsync(default); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_User_Success(Project project, Guid userId, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(project.Id).Returns(project); + sutProvider.GetDependency().UserHasWriteAccessToProject(project.Id, userId).Returns(true); + + var project2 = new Project { Id = project.Id, Name = "newName" }; + var result = await sutProvider.Sut.UpdateAsync(project2, userId); + + Assert.NotNull(result); + Assert.Equal("newName", result.Name); + + await sutProvider.GetDependency().ReceivedWithAnyArgs(1).ReplaceAsync(default); + } +} diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/CreateSecretCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/CreateSecretCommandTests.cs new file mode 100644 index 000000000..9accbc53f --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/CreateSecretCommandTests.cs @@ -0,0 +1,27 @@ +using Bit.Commercial.Core.SecretsManager.Commands.Secrets; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; +using Bit.Core.Test.SecretsManager.AutoFixture.SecretsFixture; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretsManager.Secrets; + +[SutProviderCustomize] +[SecretCustomize] +public class CreateSecretCommandTests +{ + [Theory] + [BitAutoData] + public async Task CreateAsync_CallsCreate(Secret data, + SutProvider sutProvider) + { + await sutProvider.Sut.CreateAsync(data); + + await sutProvider.GetDependency().Received(1) + .CreateAsync(data); + } +} + diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/DeleteSecretCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/DeleteSecretCommandTests.cs new file mode 100644 index 000000000..d5adec882 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/DeleteSecretCommandTests.cs @@ -0,0 +1,69 @@ +using Bit.Commercial.Core.SecretsManager.Commands.Secrets; +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretsManager.Secrets; + +[SutProviderCustomize] +public class DeleteSecretCommandTests +{ + [Theory] + [BitAutoData] + public async Task DeleteSecrets_Throws_NotFoundException(List data, + SutProvider sutProvider) + { + sutProvider.GetDependency().GetManyByIds(data).Returns(new List()); + + var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteSecrets(data)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().SoftDeleteManyByIdAsync(default); + } + + [Theory] + [BitAutoData] + public async Task DeleteSecrets_OneIdNotFound_Throws_NotFoundException(List data, + SutProvider sutProvider) + { + var secret = new Secret() + { + Id = Guid.NewGuid() + }; + sutProvider.GetDependency().GetManyByIds(data).Returns(new List() { secret }); + + var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteSecrets(data)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().SoftDeleteManyByIdAsync(default); + } + + [Theory] + [BitAutoData] + public async Task DeleteSecrets_Success(List data, + SutProvider sutProvider) + { + var secrets = new List(); + foreach (Guid id in data) + { + var secret = new Secret() + { + Id = id + }; + secrets.Add(secret); + } + + sutProvider.GetDependency().GetManyByIds(data).Returns(secrets); + + var results = await sutProvider.Sut.DeleteSecrets(data); + + await sutProvider.GetDependency().Received(1).SoftDeleteManyByIdAsync(Arg.Is(data)); + foreach (var result in results) + { + Assert.Equal("", result.Item2); + } + } +} + diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/UpdateSecretCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/UpdateSecretCommandTests.cs new file mode 100644 index 000000000..683868d7e --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Secrets/UpdateSecretCommandTests.cs @@ -0,0 +1,119 @@ +using Bit.Commercial.Core.SecretsManager.Commands.Secrets; +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; +using Bit.Core.Test.SecretsManager.AutoFixture.SecretsFixture; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretsManager.Secrets; + +[SutProviderCustomize] +[SecretCustomize] +public class UpdateSecretCommandTests +{ + [Theory] + [BitAutoData] + public async Task UpdateAsync_SecretDoesNotExist_ThrowsNotFound(Secret data, SutProvider sutProvider) + { + var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.UpdateAsync(data)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().UpdateAsync(default); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_CallsReplaceAsync(Secret data, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); + await sutProvider.Sut.UpdateAsync(data); + + await sutProvider.GetDependency().Received(1) + .UpdateAsync(data); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_DoesNotModifyOrganizationId(Secret existingSecret, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingSecret.Id).Returns(existingSecret); + + var updatedOrgId = Guid.NewGuid(); + var secretUpdate = new Secret() + { + OrganizationId = updatedOrgId, + Id = existingSecret.Id, + Key = existingSecret.Key, + }; + + var result = await sutProvider.Sut.UpdateAsync(secretUpdate); + + Assert.Equal(existingSecret.OrganizationId, result.OrganizationId); + Assert.NotEqual(existingSecret.OrganizationId, updatedOrgId); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_DoesNotModifyCreationDate(Secret existingSecret, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingSecret.Id).Returns(existingSecret); + + var updatedCreationDate = DateTime.UtcNow; + var secretUpdate = new Secret() + { + CreationDate = updatedCreationDate, + Id = existingSecret.Id, + Key = existingSecret.Key, + }; + + var result = await sutProvider.Sut.UpdateAsync(secretUpdate); + + Assert.Equal(existingSecret.CreationDate, result.CreationDate); + Assert.NotEqual(existingSecret.CreationDate, updatedCreationDate); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_DoesNotModifyDeletionDate(Secret existingSecret, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingSecret.Id).Returns(existingSecret); + + var updatedDeletionDate = DateTime.UtcNow; + var secretUpdate = new Secret() + { + DeletedDate = updatedDeletionDate, + Id = existingSecret.Id, + Key = existingSecret.Key, + }; + + var result = await sutProvider.Sut.UpdateAsync(secretUpdate); + + Assert.Equal(existingSecret.DeletedDate, result.DeletedDate); + Assert.NotEqual(existingSecret.DeletedDate, updatedDeletionDate); + } + + + [Theory] + [BitAutoData] + public async Task UpdateAsync_RevisionDateIsUpdatedToUtcNow(Secret existingSecret, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingSecret.Id).Returns(existingSecret); + + var updatedRevisionDate = DateTime.UtcNow.AddDays(10); + var secretUpdate = new Secret() + { + RevisionDate = updatedRevisionDate, + Id = existingSecret.Id, + Key = existingSecret.Key, + }; + + var result = await sutProvider.Sut.UpdateAsync(secretUpdate); + + Assert.NotEqual(existingSecret.RevisionDate, result.RevisionDate); + AssertHelper.AssertRecent(result.RevisionDate); + } +} + diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/ServiceAccounts/CreateServiceAccountCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/ServiceAccounts/CreateServiceAccountCommandTests.cs new file mode 100644 index 000000000..3c3e11a6a --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/ServiceAccounts/CreateServiceAccountCommandTests.cs @@ -0,0 +1,25 @@ +using Bit.Commercial.Core.SecretsManager.Commands.ServiceAccounts; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretsManager.ServiceAccounts; + +[SutProviderCustomize] +public class CreateServiceAccountCommandTests +{ + [Theory] + [BitAutoData] + public async Task CreateAsync_CallsCreate(ServiceAccount data, + SutProvider sutProvider) + { + await sutProvider.Sut.CreateAsync(data); + + await sutProvider.GetDependency().Received(1) + .CreateAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data))); + } +} diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/ServiceAccounts/UpdateServiceAccountCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/ServiceAccounts/UpdateServiceAccountCommandTests.cs new file mode 100644 index 000000000..0b75cb2a9 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/ServiceAccounts/UpdateServiceAccountCommandTests.cs @@ -0,0 +1,127 @@ +using Bit.Commercial.Core.SecretsManager.Commands.ServiceAccounts; +using Bit.Core.Context; +using Bit.Core.Exceptions; +using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Repositories; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretsManager.ServiceAccounts; + +[SutProviderCustomize] +public class UpdateServiceAccountCommandTests +{ + [Theory] + [BitAutoData] + public async Task UpdateAsync_ServiceAccountDoesNotExist_ThrowsNotFound(ServiceAccount data, Guid userId, SutProvider sutProvider) + { + var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.UpdateAsync(data, userId)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().ReplaceAsync(default); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_User_NoAccess(ServiceAccount data, Guid userId, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); + sutProvider.GetDependency().UserHasWriteAccessToServiceAccount(data.Id, userId).Returns(false); + + await Assert.ThrowsAsync(() => sutProvider.Sut.UpdateAsync(data, userId)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().ReplaceAsync(default); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_User_Success(ServiceAccount data, Guid userId, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); + sutProvider.GetDependency().UserHasWriteAccessToServiceAccount(data.Id, userId).Returns(true); + + await sutProvider.Sut.UpdateAsync(data, userId); + + await sutProvider.GetDependency().Received(1) + .ReplaceAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data))); + } + + + [Theory] + [BitAutoData] + public async Task UpdateAsync_Admin_Success(ServiceAccount data, Guid userId, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); + sutProvider.GetDependency().OrganizationAdmin(data.OrganizationId).Returns(true); + + await sutProvider.Sut.UpdateAsync(data, userId); + + await sutProvider.GetDependency().Received(1) + .ReplaceAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data))); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_DoesNotModifyOrganizationId(ServiceAccount existingServiceAccount, Guid userId, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingServiceAccount.Id).Returns(existingServiceAccount); + sutProvider.GetDependency().UserHasWriteAccessToServiceAccount(existingServiceAccount.Id, userId).Returns(true); + + var updatedOrgId = Guid.NewGuid(); + var serviceAccountUpdate = new ServiceAccount() + { + OrganizationId = updatedOrgId, + Id = existingServiceAccount.Id, + Name = existingServiceAccount.Name, + }; + + var result = await sutProvider.Sut.UpdateAsync(serviceAccountUpdate, userId); + + Assert.Equal(existingServiceAccount.OrganizationId, result.OrganizationId); + Assert.NotEqual(existingServiceAccount.OrganizationId, updatedOrgId); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_DoesNotModifyCreationDate(ServiceAccount existingServiceAccount, Guid userId, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingServiceAccount.Id).Returns(existingServiceAccount); + sutProvider.GetDependency().UserHasWriteAccessToServiceAccount(existingServiceAccount.Id, userId).Returns(true); + + var updatedCreationDate = DateTime.UtcNow; + var serviceAccountUpdate = new ServiceAccount() + { + CreationDate = updatedCreationDate, + Id = existingServiceAccount.Id, + Name = existingServiceAccount.Name, + }; + + var result = await sutProvider.Sut.UpdateAsync(serviceAccountUpdate, userId); + + Assert.Equal(existingServiceAccount.CreationDate, result.CreationDate); + Assert.NotEqual(existingServiceAccount.CreationDate, updatedCreationDate); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_RevisionDateIsUpdatedToUtcNow(ServiceAccount existingServiceAccount, Guid userId, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingServiceAccount.Id).Returns(existingServiceAccount); + sutProvider.GetDependency().UserHasWriteAccessToServiceAccount(existingServiceAccount.Id, userId).Returns(true); + + var updatedRevisionDate = DateTime.UtcNow.AddDays(10); + var serviceAccountUpdate = new ServiceAccount() + { + RevisionDate = updatedRevisionDate, + Id = existingServiceAccount.Id, + Name = existingServiceAccount.Name, + }; + + var result = await sutProvider.Sut.UpdateAsync(serviceAccountUpdate, userId); + + Assert.NotEqual(serviceAccountUpdate.RevisionDate, result.RevisionDate); + AssertHelper.AssertRecent(result.RevisionDate); + } +} diff --git a/bitwarden_license/test/Commercial.Core.Test/Services/ProviderServiceTests.cs b/bitwarden_license/test/Commercial.Core.Test/Services/ProviderServiceTests.cs new file mode 100644 index 000000000..52da69186 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/Services/ProviderServiceTests.cs @@ -0,0 +1,550 @@ +using Bit.Commercial.Core.Services; +using Bit.Commercial.Core.Test.AutoFixture; +using Bit.Core.Context; +using Bit.Core.Entities; +using Bit.Core.Entities.Provider; +using Bit.Core.Enums; +using Bit.Core.Enums.Provider; +using Bit.Core.Exceptions; +using Bit.Core.Models.Business; +using Bit.Core.Models.Business.Provider; +using Bit.Core.Repositories; +using Bit.Core.Services; +using Bit.Core.Utilities; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Microsoft.AspNetCore.DataProtection; +using NSubstitute; +using NSubstitute.ReturnsExtensions; +using Xunit; +using ProviderUser = Bit.Core.Entities.Provider.ProviderUser; + +namespace Bit.Commercial.Core.Test.Services; + +[SutProviderCustomize] +public class ProviderServiceTests +{ + [Theory, BitAutoData] + public async Task CreateAsync_UserIdIsInvalid_Throws(SutProvider sutProvider) + { + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.CreateAsync(default)); + Assert.Contains("Invalid owner.", exception.Message); + } + + [Theory, BitAutoData] + public async Task CreateAsync_Success(User user, SutProvider sutProvider) + { + var userRepository = sutProvider.GetDependency(); + userRepository.GetByEmailAsync(user.Email).Returns(user); + + await sutProvider.Sut.CreateAsync(user.Email); + + await sutProvider.GetDependency().ReceivedWithAnyArgs().CreateAsync(default); + await sutProvider.GetDependency().ReceivedWithAnyArgs().SendProviderSetupInviteEmailAsync(default, default, default); + } + + [Theory, BitAutoData] + public async Task CompleteSetupAsync_UserIdIsInvalid_Throws(SutProvider sutProvider) + { + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.CompleteSetupAsync(default, default, default, default)); + Assert.Contains("Invalid owner.", exception.Message); + } + + [Theory, BitAutoData] + public async Task CompleteSetupAsync_TokenIsInvalid_Throws(User user, Provider provider, + SutProvider sutProvider) + { + var userService = sutProvider.GetDependency(); + userService.GetUserByIdAsync(user.Id).Returns(user); + + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.CompleteSetupAsync(provider, user.Id, default, default)); + Assert.Contains("Invalid token.", exception.Message); + } + + [Theory, BitAutoData] + public async Task CompleteSetupAsync_Success(User user, Provider provider, string key, + [ProviderUser(ProviderUserStatusType.Confirmed, ProviderUserType.ProviderAdmin)] ProviderUser providerUser, + SutProvider sutProvider) + { + providerUser.ProviderId = provider.Id; + providerUser.UserId = user.Id; + var userService = sutProvider.GetDependency(); + userService.GetUserByIdAsync(user.Id).Returns(user); + + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetByProviderUserAsync(provider.Id, user.Id).Returns(providerUser); + + var dataProtectionProvider = DataProtectionProvider.Create("ApplicationName"); + var protector = dataProtectionProvider.CreateProtector("ProviderServiceDataProtector"); + sutProvider.GetDependency().CreateProtector("ProviderServiceDataProtector") + .Returns(protector); + sutProvider.Create(); + + var token = protector.Protect($"ProviderSetupInvite {provider.Id} {user.Email} {CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow)}"); + + await sutProvider.Sut.CompleteSetupAsync(provider, user.Id, token, key); + + await sutProvider.GetDependency().Received().UpsertAsync(provider); + await sutProvider.GetDependency().Received() + .ReplaceAsync(Arg.Is(pu => pu.UserId == user.Id && pu.ProviderId == provider.Id && pu.Key == key)); + } + + [Theory, BitAutoData] + public async Task UpdateAsync_ProviderIdIsInvalid_Throws(Provider provider, SutProvider sutProvider) + { + provider.Id = default; + + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.UpdateAsync(provider)); + Assert.Contains("Cannot create provider this way.", exception.Message); + } + + [Theory, BitAutoData] + public async Task UpdateAsync_Success(Provider provider, SutProvider sutProvider) + { + await sutProvider.Sut.UpdateAsync(provider); + } + + [Theory, BitAutoData] + public async Task InviteUserAsync_ProviderIdIsInvalid_Throws(ProviderUserInvite invite, SutProvider sutProvider) + { + sutProvider.GetDependency().ProviderManageUsers(invite.ProviderId).Returns(true); + + await Assert.ThrowsAsync(() => sutProvider.Sut.InviteUserAsync(invite)); + } + + [Theory, BitAutoData] + public async Task InviteUserAsync_InvalidPermissions_Throws(ProviderUserInvite invite, SutProvider sutProvider) + { + sutProvider.GetDependency().ProviderManageUsers(invite.ProviderId).Returns(false); + await Assert.ThrowsAsync(() => sutProvider.Sut.InviteUserAsync(invite)); + } + + [Theory, BitAutoData] + public async Task InviteUserAsync_EmailsInvalid_Throws(Provider provider, ProviderUserInvite providerUserInvite, + SutProvider sutProvider) + { + var providerRepository = sutProvider.GetDependency(); + providerRepository.GetByIdAsync(providerUserInvite.ProviderId).Returns(provider); + sutProvider.GetDependency().ProviderManageUsers(providerUserInvite.ProviderId).Returns(true); + + providerUserInvite.UserIdentifiers = null; + + await Assert.ThrowsAsync(() => sutProvider.Sut.InviteUserAsync(providerUserInvite)); + } + + [Theory, BitAutoData] + public async Task InviteUserAsync_AlreadyInvited(Provider provider, ProviderUserInvite providerUserInvite, + SutProvider sutProvider) + { + var providerRepository = sutProvider.GetDependency(); + providerRepository.GetByIdAsync(providerUserInvite.ProviderId).Returns(provider); + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetCountByProviderAsync(default, default, default).ReturnsForAnyArgs(1); + sutProvider.GetDependency().ProviderManageUsers(providerUserInvite.ProviderId).Returns(true); + + var result = await sutProvider.Sut.InviteUserAsync(providerUserInvite); + Assert.Empty(result); + } + + [Theory, BitAutoData] + public async Task InviteUserAsync_Success(Provider provider, ProviderUserInvite providerUserInvite, + SutProvider sutProvider) + { + var providerRepository = sutProvider.GetDependency(); + providerRepository.GetByIdAsync(providerUserInvite.ProviderId).Returns(provider); + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetCountByProviderAsync(default, default, default).ReturnsForAnyArgs(0); + sutProvider.GetDependency().ProviderManageUsers(providerUserInvite.ProviderId).Returns(true); + + var result = await sutProvider.Sut.InviteUserAsync(providerUserInvite); + Assert.Equal(providerUserInvite.UserIdentifiers.Count(), result.Count); + Assert.True(result.TrueForAll(pu => pu.Status == ProviderUserStatusType.Invited), "Status must be invited"); + Assert.True(result.TrueForAll(pu => pu.ProviderId == providerUserInvite.ProviderId), "Provider Id must be correct"); + } + + [Theory, BitAutoData] + public async Task ResendInviteUserAsync_InvalidPermissions_Throws(ProviderUserInvite invite, SutProvider sutProvider) + { + sutProvider.GetDependency().ProviderManageUsers(invite.ProviderId).Returns(false); + await Assert.ThrowsAsync(() => sutProvider.Sut.ResendInvitesAsync(invite)); + } + + [Theory, BitAutoData] + public async Task ResendInvitesAsync_Errors(Provider provider, + [ProviderUser(ProviderUserStatusType.Invited)] ProviderUser pu1, + [ProviderUser(ProviderUserStatusType.Accepted)] ProviderUser pu2, + [ProviderUser(ProviderUserStatusType.Confirmed)] ProviderUser pu3, + [ProviderUser(ProviderUserStatusType.Invited)] ProviderUser pu4, + SutProvider sutProvider) + { + var providerUsers = new[] { pu1, pu2, pu3, pu4 }; + pu1.ProviderId = pu2.ProviderId = pu3.ProviderId = provider.Id; + + var invite = new ProviderUserInvite + { + UserIdentifiers = providerUsers.Select(pu => pu.Id), + ProviderId = provider.Id + }; + + var providerRepository = sutProvider.GetDependency(); + providerRepository.GetByIdAsync(provider.Id).Returns(provider); + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers.ToList()); + sutProvider.GetDependency().ProviderManageUsers(invite.ProviderId).Returns(true); + + var result = await sutProvider.Sut.ResendInvitesAsync(invite); + Assert.Equal("", result[0].Item2); + Assert.Equal("User invalid.", result[1].Item2); + Assert.Equal("User invalid.", result[2].Item2); + Assert.Equal("User invalid.", result[3].Item2); + } + + [Theory, BitAutoData] + public async Task ResendInvitesAsync_Success(Provider provider, IEnumerable providerUsers, + SutProvider sutProvider) + { + foreach (var providerUser in providerUsers) + { + providerUser.ProviderId = provider.Id; + providerUser.Status = ProviderUserStatusType.Invited; + } + + var invite = new ProviderUserInvite + { + UserIdentifiers = providerUsers.Select(pu => pu.Id), + ProviderId = provider.Id + }; + + var providerRepository = sutProvider.GetDependency(); + providerRepository.GetByIdAsync(provider.Id).Returns(provider); + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers.ToList()); + sutProvider.GetDependency().ProviderManageUsers(invite.ProviderId).Returns(true); + + var result = await sutProvider.Sut.ResendInvitesAsync(invite); + Assert.True(result.All(r => r.Item2 == "")); + } + + [Theory, BitAutoData] + public async Task AcceptUserAsync_UserIsInvalid_Throws(SutProvider sutProvider) + { + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.AcceptUserAsync(default, default, default)); + Assert.Equal("User invalid.", exception.Message); + } + + [Theory, BitAutoData] + public async Task AcceptUserAsync_AlreadyAccepted_Throws( + [ProviderUser(ProviderUserStatusType.Accepted)] ProviderUser providerUser, User user, + SutProvider sutProvider) + { + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetByIdAsync(providerUser.Id).Returns(providerUser); + + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.AcceptUserAsync(providerUser.Id, user, default)); + Assert.Equal("Already accepted.", exception.Message); + } + + [Theory, BitAutoData] + public async Task AcceptUserAsync_TokenIsInvalid_Throws( + [ProviderUser(ProviderUserStatusType.Invited)] ProviderUser providerUser, User user, + SutProvider sutProvider) + { + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetByIdAsync(providerUser.Id).Returns(providerUser); + + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.AcceptUserAsync(providerUser.Id, user, default)); + Assert.Equal("Invalid token.", exception.Message); + } + + [Theory, BitAutoData] + public async Task AcceptUserAsync_WrongEmail_Throws( + [ProviderUser(ProviderUserStatusType.Invited)] ProviderUser providerUser, User user, + SutProvider sutProvider) + { + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetByIdAsync(providerUser.Id).Returns(providerUser); + + var dataProtectionProvider = DataProtectionProvider.Create("ApplicationName"); + var protector = dataProtectionProvider.CreateProtector("ProviderServiceDataProtector"); + sutProvider.GetDependency().CreateProtector("ProviderServiceDataProtector") + .Returns(protector); + sutProvider.Create(); + + var token = protector.Protect($"ProviderUserInvite {providerUser.Id} {user.Email} {CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow)}"); + + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.AcceptUserAsync(providerUser.Id, user, token)); + Assert.Equal("User email does not match invite.", exception.Message); + } + + [Theory, BitAutoData] + public async Task AcceptUserAsync_Success( + [ProviderUser(ProviderUserStatusType.Invited)] ProviderUser providerUser, User user, + SutProvider sutProvider) + { + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetByIdAsync(providerUser.Id).Returns(providerUser); + + var dataProtectionProvider = DataProtectionProvider.Create("ApplicationName"); + var protector = dataProtectionProvider.CreateProtector("ProviderServiceDataProtector"); + sutProvider.GetDependency().CreateProtector("ProviderServiceDataProtector") + .Returns(protector); + sutProvider.Create(); + + providerUser.Email = user.Email; + var token = protector.Protect($"ProviderUserInvite {providerUser.Id} {user.Email} {CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow)}"); + + var pu = await sutProvider.Sut.AcceptUserAsync(providerUser.Id, user, token); + Assert.Null(pu.Email); + Assert.Equal(ProviderUserStatusType.Accepted, pu.Status); + Assert.Equal(user.Id, pu.UserId); + } + + [Theory, BitAutoData] + public async Task ConfirmUsersAsync_NoValid( + [ProviderUser(ProviderUserStatusType.Invited)] ProviderUser pu1, + [ProviderUser(ProviderUserStatusType.Accepted)] ProviderUser pu2, + [ProviderUser(ProviderUserStatusType.Confirmed)] ProviderUser pu3, + SutProvider sutProvider) + { + pu1.ProviderId = pu3.ProviderId; + var providerUsers = new[] { pu1, pu2, pu3 }; + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers); + + var dict = providerUsers.ToDictionary(pu => pu.Id, _ => "key"); + var result = await sutProvider.Sut.ConfirmUsersAsync(pu1.ProviderId, dict, default); + + Assert.Empty(result); + } + + [Theory, BitAutoData] + public async Task ConfirmUsersAsync_Success( + [ProviderUser(ProviderUserStatusType.Invited)] ProviderUser pu1, User u1, + [ProviderUser(ProviderUserStatusType.Accepted)] ProviderUser pu2, User u2, + [ProviderUser(ProviderUserStatusType.Confirmed)] ProviderUser pu3, User u3, + Provider provider, User user, SutProvider sutProvider) + { + pu1.ProviderId = pu2.ProviderId = pu3.ProviderId = provider.Id; + pu1.UserId = u1.Id; + pu2.UserId = u2.Id; + pu3.UserId = u3.Id; + var providerUsers = new[] { pu1, pu2, pu3 }; + + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers); + var providerRepository = sutProvider.GetDependency(); + providerRepository.GetByIdAsync(provider.Id).Returns(provider); + var userRepository = sutProvider.GetDependency(); + userRepository.GetManyAsync(default).ReturnsForAnyArgs(new[] { u1, u2, u3 }); + + var dict = providerUsers.ToDictionary(pu => pu.Id, _ => "key"); + var result = await sutProvider.Sut.ConfirmUsersAsync(pu1.ProviderId, dict, user.Id); + + Assert.Equal("Invalid user.", result[0].Item2); + Assert.Equal("", result[1].Item2); + Assert.Equal("Invalid user.", result[2].Item2); + } + + [Theory, BitAutoData] + public async Task SaveUserAsync_UserIdIsInvalid_Throws(ProviderUser providerUser, + SutProvider sutProvider) + { + providerUser.Id = default; + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.SaveUserAsync(providerUser, default)); + Assert.Equal("Invite the user first.", exception.Message); + } + + [Theory, BitAutoData] + public async Task SaveUserAsync_Success( + [ProviderUser(type: ProviderUserType.ProviderAdmin)] ProviderUser providerUser, User savingUser, + SutProvider sutProvider) + { + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetByIdAsync(providerUser.Id).Returns(providerUser); + + await sutProvider.Sut.SaveUserAsync(providerUser, savingUser.Id); + await providerUserRepository.Received().ReplaceAsync(providerUser); + await sutProvider.GetDependency().Received() + .LogProviderUserEventAsync(providerUser, EventType.ProviderUser_Updated, null); + } + + [Theory, BitAutoData] + public async Task DeleteUsersAsync_NoRemainingOwner_Throws(Provider provider, User deletingUser, + ICollection providerUsers, SutProvider sutProvider) + { + var userIds = providerUsers.Select(pu => pu.Id); + + providerUsers.First().UserId = deletingUser.Id; + foreach (var providerUser in providerUsers) + { + providerUser.ProviderId = provider.Id; + } + providerUsers.Last().ProviderId = default; + + sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers); + providerUserRepository.GetManyByProviderAsync(default, default).ReturnsForAnyArgs(new ProviderUser[] { }); + + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.DeleteUsersAsync(provider.Id, userIds, deletingUser.Id)); + Assert.Equal("Provider must have at least one confirmed ProviderAdmin.", exception.Message); + } + + [Theory, BitAutoData] + public async Task DeleteUsersAsync_Success(Provider provider, User deletingUser, ICollection providerUsers, + [ProviderUser(ProviderUserStatusType.Confirmed, ProviderUserType.ProviderAdmin)] ProviderUser remainingOwner, + SutProvider sutProvider) + { + var userIds = providerUsers.Select(pu => pu.Id); + + providerUsers.First().UserId = deletingUser.Id; + foreach (var providerUser in providerUsers) + { + providerUser.ProviderId = provider.Id; + } + providerUsers.Last().ProviderId = default; + + sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); + var providerUserRepository = sutProvider.GetDependency(); + providerUserRepository.GetManyAsync(default).ReturnsForAnyArgs(providerUsers); + providerUserRepository.GetManyByProviderAsync(default, default).ReturnsForAnyArgs(new[] { remainingOwner }); + + var result = await sutProvider.Sut.DeleteUsersAsync(provider.Id, userIds, deletingUser.Id); + + Assert.NotEmpty(result); + Assert.Equal("You cannot remove yourself.", result[0].Item2); + Assert.Equal("", result[1].Item2); + Assert.Equal("Invalid user.", result[2].Item2); + } + + [Theory, BitAutoData] + public async Task AddOrganization_OrganizationAlreadyBelongsToAProvider_Throws(Provider provider, + Organization organization, ProviderOrganization po, User user, string key, + SutProvider sutProvider) + { + po.OrganizationId = organization.Id; + sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); + sutProvider.GetDependency().GetByOrganizationId(organization.Id) + .Returns(po); + + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.AddOrganization(provider.Id, organization.Id, user.Id, key)); + Assert.Equal("Organization already belongs to a provider.", exception.Message); + } + + [Theory, BitAutoData] + public async Task AddOrganization_Success(Provider provider, Organization organization, User user, string key, + SutProvider sutProvider) + { + organization.PlanType = PlanType.EnterpriseAnnually; + + sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); + var providerOrganizationRepository = sutProvider.GetDependency(); + providerOrganizationRepository.GetByOrganizationId(organization.Id).ReturnsNull(); + sutProvider.GetDependency().GetByIdAsync(organization.Id).Returns(organization); + + await sutProvider.Sut.AddOrganization(provider.Id, organization.Id, user.Id, key); + + await providerOrganizationRepository.ReceivedWithAnyArgs().CreateAsync(default); + await sutProvider.GetDependency() + .Received().LogProviderOrganizationEventAsync(Arg.Any(), + EventType.ProviderOrganization_Added); + } + + [Theory, BitAutoData] + public async Task CreateOrganizationAsync_Success(Provider provider, OrganizationSignup organizationSignup, + Organization organization, string clientOwnerEmail, User user, SutProvider sutProvider) + { + organizationSignup.Plan = PlanType.EnterpriseAnnually; + + sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); + var providerOrganizationRepository = sutProvider.GetDependency(); + sutProvider.GetDependency().SignUpAsync(organizationSignup, true) + .Returns(Tuple.Create(organization, null as OrganizationUser)); + + var providerOrganization = + await sutProvider.Sut.CreateOrganizationAsync(provider.Id, organizationSignup, clientOwnerEmail, user); + + await providerOrganizationRepository.ReceivedWithAnyArgs().CreateAsync(default); + await sutProvider.GetDependency() + .Received().LogProviderOrganizationEventAsync(providerOrganization, + EventType.ProviderOrganization_Created); + await sutProvider.GetDependency() + .Received().InviteUsersAsync(organization.Id, user.Id, Arg.Is>( + t => t.Count() == 1 && + t.First().Item1.Emails.Count() == 1 && + t.First().Item1.Emails.First() == clientOwnerEmail && + t.First().Item1.Type == OrganizationUserType.Owner && + t.First().Item1.AccessAll && + t.First().Item2 == null)); + } + + [Theory, BitAutoData] + public async Task RemoveOrganization_ProviderOrganizationIsInvalid_Throws(Provider provider, + ProviderOrganization providerOrganization, User user, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); + sutProvider.GetDependency().GetByIdAsync(providerOrganization.Id) + .ReturnsNull(); + + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.RemoveOrganizationAsync(provider.Id, providerOrganization.Id, user.Id)); + Assert.Equal("Invalid organization.", exception.Message); + } + + [Theory, BitAutoData] + public async Task RemoveOrganization_ProviderOrganizationBelongsToWrongProvider_Throws(Provider provider, + ProviderOrganization providerOrganization, User user, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); + sutProvider.GetDependency().GetByIdAsync(providerOrganization.Id) + .Returns(providerOrganization); + + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.RemoveOrganizationAsync(provider.Id, providerOrganization.Id, user.Id)); + Assert.Equal("Invalid organization.", exception.Message); + } + + [Theory, BitAutoData] + public async Task RemoveOrganization_HasNoOwners_Throws(Provider provider, + ProviderOrganization providerOrganization, User user, SutProvider sutProvider) + { + providerOrganization.ProviderId = provider.Id; + sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); + sutProvider.GetDependency().GetByIdAsync(providerOrganization.Id) + .Returns(providerOrganization); + sutProvider.GetDependency().HasConfirmedOwnersExceptAsync(default, default, default) + .ReturnsForAnyArgs(false); + + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.RemoveOrganizationAsync(provider.Id, providerOrganization.Id, user.Id)); + Assert.Equal("Organization needs to have at least one confirmed owner.", exception.Message); + } + + [Theory, BitAutoData] + public async Task RemoveOrganization_Success(Provider provider, + ProviderOrganization providerOrganization, User user, SutProvider sutProvider) + { + providerOrganization.ProviderId = provider.Id; + sutProvider.GetDependency().GetByIdAsync(provider.Id).Returns(provider); + var providerOrganizationRepository = sutProvider.GetDependency(); + providerOrganizationRepository.GetByIdAsync(providerOrganization.Id).Returns(providerOrganization); + sutProvider.GetDependency().HasConfirmedOwnersExceptAsync(default, default, default) + .ReturnsForAnyArgs(true); + + await sutProvider.Sut.RemoveOrganizationAsync(provider.Id, providerOrganization.Id, user.Id); + await providerOrganizationRepository.Received().DeleteAsync(providerOrganization); + await sutProvider.GetDependency().Received() + .LogProviderOrganizationEventAsync(providerOrganization, EventType.ProviderOrganization_Removed); + } +} diff --git a/bitwarden_license/test/Commercial.Core.Test/packages.lock.json b/bitwarden_license/test/Commercial.Core.Test/packages.lock.json new file mode 100644 index 000000000..b2acfe514 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/packages.lock.json @@ -0,0 +1,2869 @@ +{ + "version": 1, + "dependencies": { + "net6.0": { + "coverlet.collector": { + "type": "Direct", + "requested": "[3.1.2, )", + "resolved": "3.1.2", + "contentHash": "wuLDIDKD5XMt0A7lE31JPenT7QQwZPFkP5rRpdJeblyXZ9MGLI8rYjvm5fvAKln+2/X+4IxxQDxBtwdrqKNLZw==" + }, + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[17.1.0, )", + "resolved": "17.1.0", + "contentHash": "MVKvOsHIfrZrvg+8aqOF5dknO/qWrR1sWZjMPQ1N42MKMlL/zQL30FQFZxPeWfmVKWUWAOmAHYsqB5OerTKziw==", + "dependencies": { + "Microsoft.CodeCoverage": "17.1.0", + "Microsoft.TestPlatform.TestHost": "17.1.0" + } + }, + "xunit": { + "type": "Direct", + "requested": "[2.4.1, )", + "resolved": "2.4.1", + "contentHash": "XNR3Yz9QTtec16O0aKcO6+baVNpXmOnPUxDkCY97J+8krUYxPvXT1szYYEUdKk4sB8GOI2YbAjRIOm8ZnXRfzQ==", + "dependencies": { + "xunit.analyzers": "0.10.0", + "xunit.assert": "[2.4.1]", + "xunit.core": "[2.4.1]" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[2.4.3, )", + "resolved": "2.4.3", + "contentHash": "kZZSmOmKA8OBlAJaquPXnJJLM9RwQ27H7BMVqfMLUcTi9xHinWGJiWksa3D4NEtz0wZ/nxd2mogObvBgJKCRhQ==" + }, + "AspNetCoreRateLimit": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "FzXAJFgaRjKfnKAVwjEEC7OAGQM5v/I3sQw2tpzmR0yHTCGhUAxZzDuwZiXTk8XLrI6vovzkqKkfKmiDl3nYMg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.1", + "Microsoft.Extensions.Options": "6.0.0", + "Newtonsoft.Json": "13.0.1" + } + }, + "AspNetCoreRateLimit.Redis": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "CsSGy/7SXt6iBOKg0xCvsRjb/ZHshbtr2Of1MHc912L2sLnZqadUrTboyXZC+ZlgEBeJ14GyjPTu8ZyfEhGUnw==", + "dependencies": { + "AspNetCoreRateLimit": "4.0.2", + "StackExchange.Redis": "2.5.43" + } + }, + "AutoFixture": { + "type": "Transitive", + "resolved": "4.17.0", + "contentHash": "efMRCG3Epc4QDELwdmQGf6/caQUleRXPRCnLAq5gLMpTuOTcOQWV12vEJ8qo678Rj97/TjjxHYu/34rGkXdVAA==", + "dependencies": { + "Fare": "[2.1.1, 3.0.0)", + "System.ComponentModel.Annotations": "4.3.0" + } + }, + "AutoFixture.AutoNSubstitute": { + "type": "Transitive", + "resolved": "4.17.0", + "contentHash": "iWsRiDQ7T8s6F4mvYbSvPTq0GDtxJD6D+E1Fu9gVbHUvJiNikC1yIDNTH+3tQF7RK864HH/3R8ETj9m2X8UXvg==", + "dependencies": { + "AutoFixture": "4.17.0", + "NSubstitute": "[2.0.3, 5.0.0)" + } + }, + "AutoFixture.Xunit2": { + "type": "Transitive", + "resolved": "4.17.0", + "contentHash": "lrURL/LhJLPkn2tSPUEW8Wscr5LoV2Mr8A+ikn5gwkofex3o7qWUsBswlLw+KCA7EOpeqwZOldp3k91zDF+48Q==", + "dependencies": { + "AutoFixture": "4.17.0", + "xunit.extensibility.core": "[2.2.0, 3.0.0)" + } + }, + "AWSSDK.Core": { + "type": "Transitive", + "resolved": "3.7.10.11", + "contentHash": "B+M7ggPC0FogATRPQxDXL0eTusCQtXulW4zCuX39yiHV8+u9MEXRytcAw0ZA3zFBYYx6ovl9lklho6OQo1DRRQ==" + }, + "AWSSDK.SimpleEmail": { + "type": "Transitive", + "resolved": "3.7.0.150", + "contentHash": "rc/4ZnISfbgTfqz5/BWqMHBAzk4R09qfe1xkdJf2jXo44Zn2X72W8IiLLweBtmNhL7d8Tcf6UCtOHYkFwxHvug==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "AWSSDK.SQS": { + "type": "Transitive", + "resolved": "3.7.2.47", + "contentHash": "RPTVBsY333n+aIEqw148Envx9OQkE1/jhjlioNXDP6BrA3fAPN9A+2HoA02c0KSp/sazXYWg8w/kDL8FchH8Dw==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.24.0", + "contentHash": "+/qI1j2oU1S4/nvxb2k/wDsol00iGf1AyJX5g3epV7eOpQEP/2xcgh/cxgKMeFgn3U2fmgSiBnQZdkV+l5y0Uw==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Numerics.Vectors": "4.5.0", + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Extensions.AspNetCore.DataProtection.Blobs": { + "type": "Transitive", + "resolved": "1.2.1", + "contentHash": "wxvkC6DeWThBtaPbsWdicp5Ltya4J8JuhxmZJDQkhnXG7oihfu8RqBV6w/X1nMieuIOq1qQaGTvjx7nEHHfxSQ==", + "dependencies": { + "Azure.Core": "1.14.0", + "Azure.Storage.Blobs": "12.8.0", + "Microsoft.AspNetCore.DataProtection": "2.1.0" + } + }, + "Azure.Identity": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "EycyMsb6rD2PK9P0SyibFfEhvWWttdrYhyPF4f41uzdB/44yQlV+2Wehxyg489Rj6gbPvSPgbKq0xsHJBhipZA==", + "dependencies": { + "Azure.Core": "1.24.0", + "Microsoft.Identity.Client": "4.39.0", + "Microsoft.Identity.Client.Extensions.Msal": "2.19.3", + "System.Memory": "4.5.4", + "System.Security.Cryptography.ProtectedData": "4.7.0", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Storage.Blobs": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "50eRjIhY7Q1JN7kT2MSawDKCcwSb7uRZUkz00P/BLjSg47gm2hxUYsnJPyvzCHntYMbOWzrvaVQTwYwXabaR5Q==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Text.Json": "4.7.2" + } + }, + "Azure.Storage.Common": { + "type": "Transitive", + "resolved": "12.10.0", + "contentHash": "vYkHGzUkdZTace/cDPZLG+Mh/EoPqQuGxDIBOau9D+XWoDPmuUFGk325aXplkFE4JFGpSwoytNYzk/qBCaiHqg==", + "dependencies": { + "Azure.Core": "1.22.0", + "System.IO.Hashing": "6.0.0" + } + }, + "Azure.Storage.Queues": { + "type": "Transitive", + "resolved": "12.9.0", + "contentHash": "jDiyHtsCUCrWNvZW7SjJnJb46UhpdgQrWCbL8aWpapDHlq9LvbvxYpfLh4dfKAz09QiTznLMIU3i+md9+7GzqQ==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, + "BitPay.Light": { + "type": "Transitive", + "resolved": "1.0.1907", + "contentHash": "QTTIgXakHrRNQPxNyH7bZ7frm0bI8N6gRDtiqVyKG/QYQ+KfjN70xt0zQ0kO0zf8UBaKuwcV5B7vvpXtzR9ijg==", + "dependencies": { + "Newtonsoft.Json": "12.0.2" + } + }, + "Braintree": { + "type": "Transitive", + "resolved": "5.12.0", + "contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "System.Xml.XPath.XmlDocument": "4.3.0" + } + }, + "Castle.Core": { + "type": "Transitive", + "resolved": "4.4.1", + "contentHash": "zanbjWC0Y05gbx4eGXkzVycOQqVOFVeCjVsDSyuao9P4mtN1w3WxxTo193NGC7j3o2u3AJRswaoC6hEbnGACnQ==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "System.Collections.Specialized": "4.3.0", + "System.ComponentModel": "4.3.0", + "System.ComponentModel.TypeConverter": "4.3.0", + "System.Diagnostics.TraceSource": "4.3.0", + "System.Dynamic.Runtime": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "Fare": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "HaI8puqA66YU7/9cK4Sgbs1taUTP1Ssa4QT2PIzqJ7GvAbN1QgkjbRsjH+FSbMh1MJdvS0CIwQNLtFT+KF6KpA==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "Fido2": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "S0Bz1vfcKlO4Jase3AWp5XnQ746psf4oGx5kL+D2A10j1SsjoAOAIIpanSwfi0cEepDHgk1bClcOKY5TjOzGdA==", + "dependencies": { + "Fido2.Models": "3.0.1", + "Microsoft.Extensions.Http": "6.0.0", + "NSec.Cryptography": "22.4.0", + "System.Formats.Cbor": "6.0.0", + "System.IdentityModel.Tokens.Jwt": "6.17.0" + } + }, + "Fido2.AspNet": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "5n5shEXD7RFUyTesjUHGDjkpgES7j4KotQo1GwUcS08k+fx+1tl/zCFHJ9RFDuUwO+S681ZILT2PyA67IPYpaA==", + "dependencies": { + "Fido2": "3.0.1", + "Fido2.Models": "3.0.1" + } + }, + "Fido2.Models": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "mgjcuGETuYSCUEaZG+jQeeuuEMkDLc4GDJHBvKDdOz6oSOWp5adPdWP4btZx7Pi+9fu4szN3JIjJmby67MaILw==" + }, + "Handlebars.Net": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "p60QyeBYpZmcZdIXRMqs9XySIBaxJ0lj3+QD0EJVr4ybTigOTCumXMMin5dPwjo9At1UwkDZ3gGwa1lmGjG6DA==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "IdentityModel": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "System.Text.Encodings.Web": "4.7.0" + } + }, + "IdentityModel.AspNetCore.OAuth2Introspection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==", + "dependencies": { + "IdentityModel": "4.0.0" + } + }, + "IdentityServer4": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==", + "dependencies": { + "IdentityModel": "4.4.0", + "IdentityServer4.Storage": "4.1.2", + "Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0", + "Newtonsoft.Json": "12.0.2" + } + }, + "IdentityServer4.AccessTokenValidation": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==", + "dependencies": { + "IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1", + "Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0" + } + }, + "IdentityServer4.Storage": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==", + "dependencies": { + "IdentityModel": "4.4.0" + } + }, + "Kralizek.AutoFixture.Extensions.MockHttp": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "6zmks7/5mVczazv910N7V2EdiU6B+rY61lwdgVO0o2iZuTI6KI3T+Hgkrjv0eGOKYucq2OMC+gnAc5Ej2ajoTQ==", + "dependencies": { + "AutoFixture": "4.11.0", + "RichardSzalay.MockHttp": "6.0.0" + } + }, + "libsodium": { + "type": "Transitive", + "resolved": "1.0.18.2", + "contentHash": "flArHoVdscSzyV8ZdPV+bqqY2TTFlaN+xZf/vIqsmHI51KVcD/mOdUPaK3n/k/wGKz8dppiktXUqSmf3AXFgig==" + }, + "MailKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "5MTpTqmjqT7HPvYbP3HozRZMth5vSaT0ReN0iM3rAM4CgLI/R1qqtLDDNWGnFFIlcNzeJkZQRJJMkv8cgzWBbA==", + "dependencies": { + "MimeKit": "3.2.0" + } + }, + "Microsoft.AspNetCore.Authentication.JwtBearer": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "joDS3+lD1i9qcdFLWP4D316t3bHpezmTNOzbMIf9ZcRPX4QTuiUutZcQn/kZplf3BiLHqwUChZXxPjCAMKaKAQ==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0" + } + }, + "Microsoft.AspNetCore.Authentication.OpenIdConnect": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0" + } + }, + "Microsoft.AspNetCore.Cryptography.Internal": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "/0FX1OqckMmXAAlsHgBFNymTZuq4nuAOMhiwm6e8CEMi2aOjnMYwiMc7mtvpGTAO0O4C0zwx+iaChxDgvqit2A==" + }, + "Microsoft.AspNetCore.Cryptography.KeyDerivation": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "1Lbwrxg/HRY/nbrkcrB3EUXUYQN8Tkw7Ktgb6/2on2P7ybT5aM59H05gk+OBC8ZTBxwdle9e1tyT3wxEYKw5xw==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "6.0.4" + } + }, + "Microsoft.AspNetCore.DataProtection": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "G+UoMHL0xiyFh30wkL7Bv/XL6eugTAKYhLPS53k1/Me1bYRwOOw+8VL/q0ppq3/yMzpHX+MkExaCTDlYl48FgA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "2.1.0", + "Microsoft.AspNetCore.DataProtection.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.1.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0", + "Microsoft.Extensions.Logging.Abstractions": "2.1.0", + "Microsoft.Extensions.Options": "2.1.0", + "Microsoft.Win32.Registry": "4.5.0", + "System.Security.Cryptography.Xml": "4.5.0", + "System.Security.Principal.Windows": "4.5.0" + } + }, + "Microsoft.AspNetCore.DataProtection.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "2+HVDhUqrnV9+EJNEewSy+Gk4hOVPzLPMpFDZI7kuH7NWxtbNkI6A6gT5lO2/kEPMyM8/iLWtohbOwjpC9rHVw==" + }, + "Microsoft.AspNetCore.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "1TQgBfd/NPZLR2o/h6l5Cml2ZCF5hsyV4h9WEwWwAIavrbdTnaNozGGcTOd4AOgQvogMM9UM1ajflm9Cwd0jLQ==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Http.Abstractions": "2.1.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "YTKMi2vHX6P+WHEVpW/DS+eFHnwivCSMklkyamcK1ETtc/4j8H3VR0kgW8XIBqukNxhD8k5wYt22P7PhrWSXjQ==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "Microsoft.Extensions.Configuration.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Http.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "vbFDyKsSYBnxl3+RABtN79b0vsTcG66fDY8vD6Nqvu9uLtSej70Q5NcbGlnN6bJpZci5orSdgFTHMhBywivDPg==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Features": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "UmkUePxRjsQW0j5euFFscBwjvTu25b8+qIK/2fI3GvcqQ+mkwgbWNAT8b/Gkoei1m2bTWC07lSdutuRDPPLcJA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.0" + } + }, + "Microsoft.Azure.Amqp": { + "type": "Transitive", + "resolved": "2.4.11", + "contentHash": "7x5fu2f6TLQDDJS0sY5qW8/daFwJaY9O75YvU8RcUfRzbug+9YGjXUBxoRrprgyi0jxdBAMQL05p1s783SOSFQ==", + "dependencies": { + "System.Net.WebSockets.Client": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.Azure.Cosmos": { + "type": "Transitive", + "resolved": "3.24.0", + "contentHash": "QpUe5ho6OzlXwgcJVgAmOR7t3XLC9RI4t8T96RZY61pSOIllPOJdp30L0LwA16tKcqi5r2KayEgWO/MS9fh/6A==", + "dependencies": { + "Azure.Core": "1.3.0", + "Microsoft.Bcl.AsyncInterfaces": "1.0.0", + "Microsoft.Bcl.HashCode": "1.1.0", + "Newtonsoft.Json": "10.0.2", + "System.Buffers": "4.5.1", + "System.Collections.Immutable": "1.7.0", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Memory": "4.5.4", + "System.Numerics.Vectors": "4.5.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3", + "System.Threading.Tasks.Extensions": "4.5.4", + "System.ValueTuple": "4.5.0" + } + }, + "Microsoft.Azure.Cosmos.Table": { + "type": "Transitive", + "resolved": "1.0.8", + "contentHash": "ToeEd1yijM7nQfLYvdFLG//RjKPmfqm45eOm86UAKrxtyGI/CXqP8iL74mzBp6mZ9A/K/ZYA2fVdpH0xHR5Keg==", + "dependencies": { + "Microsoft.Azure.DocumentDB.Core": "2.11.2", + "Microsoft.OData.Core": "7.6.4", + "Newtonsoft.Json": "10.0.2" + } + }, + "Microsoft.Azure.DocumentDB.Core": { + "type": "Transitive", + "resolved": "2.11.2", + "contentHash": "cA8eWrTFbYrkHrz095x4CUGb7wqQgA1slzFZCYexhNwz6Zcn3v+S1yvWMGwGRmRjT0MKU9tYdFWgLfT0OjSycw==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "Newtonsoft.Json": "9.0.1", + "System.Collections.Immutable": "1.3.0", + "System.Collections.NonGeneric": "4.0.1", + "System.Collections.Specialized": "4.0.1", + "System.Diagnostics.TraceSource": "4.0.0", + "System.Dynamic.Runtime": "4.0.11", + "System.Linq.Queryable": "4.0.1", + "System.Net.Http": "4.3.4", + "System.Net.NameResolution": "4.0.0", + "System.Net.NetworkInformation": "4.1.0", + "System.Net.Requests": "4.0.11", + "System.Net.Security": "4.3.2", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Security.SecureString": "4.0.0" + } + }, + "Microsoft.Azure.NotificationHubs": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "C2SssjX3e6/HIo1OCImQDDVOn64d1+gkgEmgxJryzkwixyivJHWH2YIgxZs33pyzVQcZWx5PR2tqLkQ7riSq8Q==", + "dependencies": { + "Microsoft.Extensions.Caching.Memory": "3.1.8", + "Newtonsoft.Json": "12.0.3" + } + }, + "Microsoft.Azure.ServiceBus": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "wyZNJggyFNtKxd+HgvcTiuRYuTjDGi+pgE4RcBvFbfvNiarKr5AOlE4Ne7on1eUJZuMuEa19wN5dj694HlP60A==", + "dependencies": { + "Microsoft.Azure.Amqp": "2.4.11", + "Microsoft.Azure.Services.AppAuthentication": "[1.0.3, 2.0.0)", + "Newtonsoft.Json": "10.0.3", + "System.Diagnostics.DiagnosticSource": "4.5.1", + "System.IdentityModel.Tokens.Jwt": "5.4.0" + } + }, + "Microsoft.Azure.Services.AppAuthentication": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "ywpQaK1klu1IoX4VUf+TBmU4kR71aWNI6O5rEIJU8z28L2xhJhnIm7k2Nf1Zu/PygeuOtt5g0QPCk5+lLltbeQ==", + "dependencies": { + "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.14.2", + "NETStandard.Library": "1.6.1", + "System.Diagnostics.Process": "4.3.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "yuvf07qFWFqtK3P/MRkEKLhn5r2UbSpVueRziSqj0yJQIKFwG1pq9mOayK3zE5qZCTs0CbrwL9M6R8VwqyGy2w==" + }, + "Microsoft.Bcl.HashCode": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "J2G1k+u5unBV+aYcwxo94ip16Rkp65pgWFb0R6zwJipzWNMgvqlWeuI7/+R+e8bob66LnSG+llLJ+z8wI94cHg==" + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "0N/ZJ71ncCxQWhgtkEYKOgu2oMHa8h1tsOUbhmIKXF8UwtSUCe4vHAsJ3DVcNWRwNfQzSTy263ZE+QF6MdIhhQ==" + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, + "Microsoft.Data.SqlClient": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "uu8dfrsx081cSbEevWuZAvqdmANDGJkbLBL2G3j0LAZxX1Oy8RCVAaC4Lcuak6jNicWP6CWvHqBTIEmQNSxQlw==", + "dependencies": { + "Azure.Identity": "1.6.0", + "Microsoft.Data.SqlClient.SNI.runtime": "5.0.1", + "Microsoft.Identity.Client": "4.45.0", + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.21.0", + "Microsoft.SqlServer.Server": "1.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Buffers": "4.5.1", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Diagnostics.DiagnosticSource": "5.0.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime.Caching": "5.0.0", + "System.Security.Cryptography.Cng": "5.0.0", + "System.Security.Principal.Windows": "5.0.0", + "System.Text.Encoding.CodePages": "5.0.0", + "System.Text.Encodings.Web": "4.7.2" + } + }, + "Microsoft.Data.SqlClient.SNI.runtime": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "y0X5MxiNdbITJYoafJ2ruaX6hqO0twpCGR/ipiDOe85JKLU8WL4TuAQfDe5qtt3bND5Je26HnrarLSAMMnVTNg==" + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bcz5sSFJbganH0+YrfvIjJDIcKNW7TL07C4d1eTmXy/wOt52iz4LVogJb6pazs7W0+74j0YpXFErvp++Aq5Bsw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.Memory": { + "type": "Transitive", + "resolved": "3.1.8", + "contentHash": "u04q7+tgc8l6pQ5HOcr6scgapkQQHnrhpGoCaaAZd24R36/NxGsGxuhSmhHOrQx9CsBLe2CVBN/4CkLlxtnnXw==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "3.1.8", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8", + "Microsoft.Extensions.Options": "3.1.8" + } + }, + "Microsoft.Extensions.Caching.StackExchangeRedis": { + "type": "Transitive", + "resolved": "6.0.6", + "contentHash": "bdVQpYm1hcHf0pyAypMjtDw3HjWQJ89UzloyyF1OBs56QlgA1naM498tP2Vjlho5vVRALMGPYzdRKCen8koubw==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "StackExchange.Redis": "2.2.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "tq2wXyh3fL17EMF2bXgRhU7JrbO3on93MRKYxzz4JzzvuGSA1l0W3GI9/tl8EO89TH+KWEymP7bcFway6z9fXg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "IznHHzGUtrdpuQqIUdmzF6TYPcsYHONhHh3o9dGp39sX/9Zfmt476UnhvU0UhXgJnXXAikt/MpN6AuSLCCMdEQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.0.0" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "pnyXV1LFOsYjGveuC07xp0YHIyGq7jRq5Ncb5zrrIieMLWVwgMyYxcOH0jTnBedDT4Gh1QinSqsjqzcieHk1og==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "V4Dth2cYMZpw3HhGw9XUDIijpI6gN+22LDt0AhufIgOppCUfpWX4483OmN+dFXRJkJLc8Tv0Q8QK+1ingT2+KQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GJGery6QytCzS/BxJ96klgG9in3uH26KcUBbiVG/coNDXCRq6LGVVlUT4vXq34KPuM+R2av+LeYdX9h4IZOCUg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "Fy8yr4V6obi7ZxvKYI1i85jqtwMq8tqyxQVZpRSkgeA8enqy/KvBIMdcuNdznlxQMZa72mvbHqb7vbg4Pyx95w==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "k6PWQMuoBDGGHOQTtyois2u4AwyVcIwL2LaSLlTZQm2CYcJ1pxbt6jfAnpWmzENA/wfrYRI/X9DTLoUkE4AsLw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.DependencyModel": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "Iaectmzg9Dc4ZbKX/FurrRjgO/I8rTumL5UU+Uube6vZuGetcnXoIgTA94RthFWePhdMVm8MMhVFJZdbzMsdyQ==", + "dependencies": { + "System.Text.Json": "4.6.0" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "3.1.8", + "contentHash": "7ZJUKwPipkDvuv2KJPZ3r01wp2AWNMiYH+61i0dL89F7QICknjKpWgLKLpTSUYFgl77S3b4264I6i4HzDdrb2A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.8", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.FileProviders.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "15+pa2G0bAMHbHewaQIdr/y6ag2H3yh4rd9hTXavtWDzQBkvpe2RMqFg8BxDpcQWssmjmBApGPcw93QRz6YcMg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Core": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "8vBsyGkA8ZI3lZvm1nf+9ynRC/TzPD+UtbdgTlKk+cz+AW5I41LrK8f/adGej5uXgprOA2DMjZw33vZG6vyXxA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Stores": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "linRCnWBfnqg8qjrd9u/KMISy8O4a6X/GRhpHXU0ar654YQw9LJ/Ht+psx8QLqSX5EsCBbBCZzuamatH2FWIyQ==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Identity.Core": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y/lGICwO27fCkQRK3tZseVzFjZaxfGmui990E67sB4MuiPzdJHnJDS/BeYWrHShSSBgCl4KyKRx4ux686fftPg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.0.0", + "Microsoft.Extensions.Options": "2.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Identity.Client": { + "type": "Transitive", + "resolved": "4.45.0", + "contentHash": "ircobISCLWbtE5eEoLKU+ldfZ8O41vg4lcy38KRj/znH17jvBiAl8oxcyNp89CsuqE3onxIpn21Ca7riyDDrRw==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.18.0" + } + }, + "Microsoft.Identity.Client.Extensions.Msal": { + "type": "Transitive", + "resolved": "2.19.3", + "contentHash": "zVVZjn8aW7W79rC1crioDgdOwaFTQorsSO6RgVlDDjc7MvbEGz071wSNrjVhzR0CdQn6Sefx7Abf1o7vasmrLg==", + "dependencies": { + "Microsoft.Identity.Client": "4.38.0", + "System.Security.Cryptography.ProtectedData": "4.5.0" + } + }, + "Microsoft.IdentityModel.Abstractions": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "XeE6LQtD719Qs2IG7HDi1TSw9LIkDbJ33xFiOBoHbApVw/8GpIBCbW+t7RwOjErUDyXZvjhZliwRkkLb8Z1uzg==" + }, + "Microsoft.IdentityModel.Clients.ActiveDirectory": { + "type": "Transitive", + "resolved": "3.14.2", + "contentHash": "TNsJJMiRnkeby1ovThVoV9yFsPWjAdluwOA+Nf0LtSsBVVrKQv8Qp4kYOgyNwMVj+pDwbhXISySk+4HyHVWNZQ==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "System.Runtime.Serialization.Json": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.IdentityModel.JsonWebTokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "d3h1/BaMeylKTkdP6XwRCxuOoDJZ44V9xaXr6gl5QxmpnZGdoK3bySo3OQN8ehRLJHShb94ElLUvoXyglQtgAw==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "tuEhHIQwvBEhMf8I50hy8FHmRSUkffDFP5EdLsSDV4qRcl2wvOPkQxYqEzWkh+ytW6sbdJGEXElGhmhDfAxAKg==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "0FqY5cTLQKtHrClzHEI+QxJl8OBT2vUiEQQB7UKk832JDiJJmetzYZ3AdSrPjN/3l3nkhByeWzXnhrX0JbifKg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "vtSKL7n6EnAsLyxmiviusm6LKrblT2ndnNqN6rvVq6iIHAnPCK9E2DkDx6h1Jrpy1cvbp40r0cnTg23nhEAGTA==", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "6.21.0", + "System.IdentityModel.Tokens.Jwt": "6.21.0" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "AAEHZvZyb597a+QJSmtxH3n2P1nIJGpZ4Q89GTenknRx6T6zyfzf592yW/jA5e8EHN4tNMjjXHQaYWEq5+L05w==", + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "Microsoft.IdentityModel.Logging": "6.21.0", + "System.Security.Cryptography.Cng": "4.5.0" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.OData.Core": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "/EjnJezMBjXf8OjcShhGzPY7pOO0CopgoZGhS6xsP3t2uhC+O72IBHgtQ7F3v1rRXWVtJwLGhzE1GfJUlx3c4Q==", + "dependencies": { + "Microsoft.OData.Edm": "[7.6.4]", + "Microsoft.Spatial": "[7.6.4]" + } + }, + "Microsoft.OData.Edm": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "MSSmA6kIfpgFTtNpOnnayoSj/6KSzHC1U9KOjF7cTA1PG4tZ7rIMi1pvjFc8CmYEvP4cxGl/+vrCn+HpK26HTQ==" + }, + "Microsoft.Spatial": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "3mB+Frn4LU4yb5ie9R752QiRn0Hvp9PITkSRofV/Lzm9EyLM87Fy9ziqgz75O/c712dh6GxuypMSBUGmNFwMeA==" + }, + "Microsoft.SqlServer.Server": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug==" + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "OMo/FYnKGy3lZEK0gfitskRM3ga/YBt6MyCyFPq0xNLeybGOQ6HnYNAAvzyePo5WPuMiw3LX+HiuRWNjnas1fA==", + "dependencies": { + "NuGet.Frameworks": "5.11.0", + "System.Reflection.Metadata": "1.6.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "JS0JDLniDhIzkSPLHz7N/x1CG8ywJOtwInFDYA3KQvbz+ojGoT5MT2YDVReL1b86zmNRV8339vsTSm/zh0RcMg==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.1.0", + "Newtonsoft.Json": "9.0.1" + } + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "Microsoft.Win32.Registry": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "Microsoft.Win32.SystemEvents": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==" + }, + "MimeKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "l9YHMBhBUwY7qQHUp8fw0EvjcbmhN4Iggz6MdjqIShBf42+0nJTa5gu0kuupCOPuiARc9ZaS9c9f0gKz4OnxKw==", + "dependencies": { + "Portable.BouncyCastle": "1.9.0", + "System.Security.Cryptography.Pkcs": "6.0.0" + } + }, + "Moq": { + "type": "Transitive", + "resolved": "4.17.2", + "contentHash": "HytUPJ3/uks2UgJ9hIcyXm3YxpFAR4OJzbQwTHltbKGun3lFLhEHs97hiiPj1dY8jV/kasXeihTzDxct6Zf3iQ==", + "dependencies": { + "Castle.Core": "4.4.1", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "NSec.Cryptography": { + "type": "Transitive", + "resolved": "22.4.0", + "contentHash": "lEntcPYd7h3aZ8xxi/y/4TML7o8w0GEGqd+w4L1omqFLbdCBmhxJAeO2YBmv/fXbJKgKCQLm7+TD4bR605PEUQ==", + "dependencies": { + "libsodium": "[1.0.18.2, 1.0.19)" + } + }, + "NSubstitute": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c0nY4GGSe5KidQemTk+CTuDLdv7hLvHHftH6vRbKoYb6bw07wzJ6DdgA0NWrwbW3xjmp/ByEskCsUEWAaMC20g==", + "dependencies": { + "Castle.Core": "4.4.1" + } + }, + "NuGet.Frameworks": { + "type": "Transitive", + "resolved": "5.11.0", + "contentHash": "eaiXkUjC4NPcquGWzAGMXjuxvLwc6XGKMptSyOGQeT0X70BUZObuybJFZLA0OfTdueLd3US23NBPTBb6iF3V1Q==" + }, + "Otp.NET": { + "type": "Transitive", + "resolved": "1.2.2", + "contentHash": "2hrZfkbzeWJ3tNXXt/1beg4IY+nS4F3gIfh4NVFvW0f6Pj51hGpiJ4prBz7Dmrr4ZYrA96rTERVGieZ4xYm7jA==" + }, + "Pipelines.Sockets.Unofficial": { + "type": "Transitive", + "resolved": "2.2.2", + "contentHash": "Bhk0FWxH1paI+18zr1g5cTL+ebeuDcBCR+rRFO+fKEhretgjs7MF2Mc1P64FGLecWp4zKCUOPzngBNrqVyY7Zg==", + "dependencies": { + "System.IO.Pipelines": "5.0.1" + } + }, + "Portable.BouncyCastle": { + "type": "Transitive", + "resolved": "1.9.0", + "contentHash": "eZZBCABzVOek+id9Xy04HhmgykF0wZg9wpByzrWN7q8qEI0Qen9b7tfd7w8VA3dOeesumMG7C5ZPy0jk7PSRHw==" + }, + "Quartz": { + "type": "Transitive", + "resolved": "3.4.0", + "contentHash": "N8350OAlQhd8zKg0ARFikGjh3bfAW/CF/KVxu2fTIlAALB/oC1eg54n/QAPYR5ryHuYyDr5G8/Qa4k+D/7OFRQ==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "RichardSzalay.MockHttp": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bStGNqIX/MGYtML7K3EzdsE/k5HGVAcg7XgN23TQXGXqxNC9fvYFR94fA0sGM5hAT36R+BBGet6ZDQxXL/IPxg==" + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" + }, + "SendGrid": { + "type": "Transitive", + "resolved": "9.27.0", + "contentHash": "kMyXRQ8hmN2bG3tYZ7T31Ufl1kXkpuP5+WBh1BJ32WY31DTnBTCVGURoIqfbTo/tRuQfAYLxra6C8cQGN6kk+A==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "starkbank-ecdsa": "[1.3.3, 2.0.0)" + } + }, + "Sentry": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "Pkw4+51EDUQ0X02jdCZIpaM2Q4UO06VKGDE+dYYNxgvOirRXGKTKxRk4NPKJTLSTNl+2JyT9HoE7C6BTlYhLOw==" + }, + "Sentry.Serilog": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "GFTVfQdOFqZ9Vmo8EEZTx1EQMDRJjka/4v2CwxnAUh+sqHDICga4eOm4AyGzDBbE4s9iAHMgMUCceIqo+7z84w==", + "dependencies": { + "Sentry": "3.16.0", + "Serilog": "2.10.0" + } + }, + "Serilog": { + "type": "Transitive", + "resolved": "2.10.0", + "contentHash": "+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA==" + }, + "Serilog.AspNetCore": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "/JO/txIxRR61x1UXQAgUzG2Sx05o1QHCkokVBWrKzmAoDu+p5EtCAj7L/TVVg7Ezhh3GPiZ0JI9OJCmRO9tSRw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.Extensions.Logging": "5.0.0", + "Serilog": "2.10.0", + "Serilog.Extensions.Hosting": "4.2.0", + "Serilog.Formatting.Compact": "1.1.0", + "Serilog.Settings.Configuration": "3.3.0", + "Serilog.Sinks.Console": "4.0.1", + "Serilog.Sinks.Debug": "2.0.0", + "Serilog.Sinks.File": "5.0.0" + } + }, + "Serilog.Extensions.Hosting": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "gT2keceCmPQR9EX0VpXQZvUgELdfE7yqJ7MOxBhm3WLCblcvRgswEOOTgok/DHObbM15A3V/DtF3VdVDQPIZzQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.Hosting.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8", + "Serilog": "2.10.0", + "Serilog.Extensions.Logging": "3.1.0" + } + }, + "Serilog.Extensions.Logging": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "IWfem7wfrFbB3iw1OikqPFNPEzfayvDuN4WP7Ue1AVFskalMByeWk3QbtUXQR34SBkv1EbZ3AySHda/ErDgpcg==", + "dependencies": { + "Microsoft.Extensions.Logging": "2.0.0", + "Serilog": "2.9.0" + } + }, + "Serilog.Extensions.Logging.File": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "usO0qr4v9VCMBWiTJ1nQmAbPNCt40FrkDol6CpfCXbsxGZS/hH+YCueF7vvPQ32ATI0GWcMWiKRdjXEE7/HxTQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Serilog": "2.5.0", + "Serilog.Extensions.Logging": "2.0.2", + "Serilog.Formatting.Compact": "1.0.0", + "Serilog.Sinks.Async": "1.1.0", + "Serilog.Sinks.RollingFile": "3.3.0" + } + }, + "Serilog.Formatting.Compact": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "pNroKVjo+rDqlxNG5PXkRLpfSCuDOBY0ri6jp9PLe505ljqwhwZz8ospy2vWhQlFu5GkIesh3FcDs4n7sWZODA==", + "dependencies": { + "Serilog": "2.8.0" + } + }, + "Serilog.Settings.Configuration": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "7GNudISZwqaT902hqEL2OFGTZeUFWfnrNLupJkOqeF41AR3GjcxX+Hwb30xb8gG2/CDXsCMVfF8o0+8KY0fJNg==", + "dependencies": { + "Microsoft.Extensions.DependencyModel": "3.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "2.0.0", + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Async": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "xll0Kanz2BkCxuv+F3p1WXr47jdsVM0GU1n1LZvK+18QiRZ/WGFNxSNw9EMKFV5ED5gr7MUpAe6PCMNL1HGUMA==", + "dependencies": { + "Serilog": "2.1.0", + "System.Collections.Concurrent": "4.0.12" + } + }, + "Serilog.Sinks.AzureCosmosDB": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Im2/ZqjXQIpsd727qEo5Pq+br0MiNVuTvI40Yk7736tgjCpEx+omPHv4+c4fEAxnOP2kL9Ge6UoDFoDw3cjF2A==", + "dependencies": { + "Microsoft.Azure.Cosmos": "3.24.0", + "Microsoft.CSharp": "4.7.0", + "Newtonsoft.Json": "13.0.1", + "Serilog": "2.10.0", + "Serilog.Sinks.PeriodicBatching": "2.3.1" + } + }, + "Serilog.Sinks.Console": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Debug": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y6g3OBJ4JzTyyw16fDqtFcQ41qQAydnEvEqmXjhwhgjsnG/FaJ8GUqF5ldsC/bVkK8KYmqrPhDO+tm4dF6xx4A==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.File": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.PeriodicBatching": { + "type": "Transitive", + "resolved": "2.3.1", + "contentHash": "LVYvqpqjSTD8dhfxRnzpxTs8/ys3V2q01MvaY3r0eKsDgpKK1U1y/5N6gFHgiesbxG0V+O5IWdz4+c1DzoNyOQ==", + "dependencies": { + "Serilog": "2.0.0" + } + }, + "Serilog.Sinks.RollingFile": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "2lT5X1r3GH4P0bRWJfhA7etGl8Q2Ipw9AACvtAHWRUSpYZ42NGVyHoVs2ALBZ/cAkkS+tA4jl80Zie144eLQPg==", + "dependencies": { + "Serilog.Sinks.File": "3.2.0", + "System.IO": "4.1.0", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Serilog.Sinks.SyslogMessages": { + "type": "Transitive", + "resolved": "2.0.6", + "contentHash": "V2Yq2GEbk7taEPbpBLFzLXhrHrUzKf4sQu/zLrANU8XIoUn/Mr08M2E8PrcrWVXCj0R4xLMWYe0Z1sxOrMF3IA==", + "dependencies": { + "Serilog": "2.5.0", + "Serilog.Sinks.PeriodicBatching": "2.3.0" + } + }, + "StackExchange.Redis": { + "type": "Transitive", + "resolved": "2.5.43", + "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "dependencies": { + "Pipelines.Sockets.Unofficial": "2.2.2", + "System.Diagnostics.PerformanceCounter": "5.0.0" + } + }, + "starkbank-ecdsa": { + "type": "Transitive", + "resolved": "1.3.3", + "contentHash": "OblOaKb1enXn+dSp7tsx9yjwV+/BEKM9jFhshIkZTwCk7LuTFTp+wSon6rFzuPiIiTGtvVWQNUw2slHjGktJog==" + }, + "Stripe.net": { + "type": "Transitive", + "resolved": "40.0.0", + "contentHash": "SD1bGiF+sVQG3p2LXNTZ5rEG2aCnXIHokcxYS9yyW3dR01J0ryf+iNFOwid148yePZ0gCBcRxj3wiW1mTmP7UQ==", + "dependencies": { + "Newtonsoft.Json": "12.0.3", + "System.Configuration.ConfigurationManager": "6.0.0" + } + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "1.7.0", + "contentHash": "RVSM6wZUo6L2y6P3vN6gjUtyJ2IF2RVtrepF3J7nrDKfFQd5u/SnSUFclchYQis8/k5scHy9E+fVeKVQLnnkzw==" + }, + "System.Collections.NonGeneric": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "prtjIEMhGUnQq6RnPEYLpFt8AtLbp9yq2zxOSrY7KJJZrw25Fi97IzBqY7iqssbM61Ek5b8f3MG/sG1N2sN5KA==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Collections.Specialized": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Epx8PoVZR0iuOnJJDzp7pWvdfMMOAvpUo95pC4ScH2mJuXkKA2Y4aR3cG9qt2klHgSons1WFh4kcGW7cSXvrxg==", + "dependencies": { + "System.Collections.NonGeneric": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.ComponentModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VyGn1jGRZVfxnh8EdvDCi71v3bMXrsu8aYJOwoV7SNDLVhiEqwP86pPMyRGsDsxhXAm2b3o9OIqeETfN5qfezw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.ComponentModel.Annotations": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "SY2RLItHt43rd8J9D8M8e8NM4m+9WLN2uUd9G0n1I4hj/7w+v3pzK6ZBjexlG1/2xvLKQsqir3UGVSyBTXMLWA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.ComponentModel": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.ComponentModel.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "j8GUkCpM8V4d4vhLIIoBLGey2Z5bCkMVNjEZseyAlm4n5arcsJOeI3zkUP+zvZgzsbLTYh4lYeP/ZD/gdIAPrw==", + "dependencies": { + "System.ComponentModel": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.ComponentModel.TypeConverter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "16pQ6P+EdhcXzPiEK4kbA953Fu0MNG2ovxTZU81/qsCd1zPRsKc3uif5NgvllCY598k6bI0KUyKW8fanlfaDQg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Collections.NonGeneric": "4.3.0", + "System.Collections.Specialized": "4.3.0", + "System.ComponentModel": "4.3.0", + "System.ComponentModel.Primitives": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "6.0.0", + "System.Security.Permissions": "6.0.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Diagnostics.PerformanceCounter": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "kcQWWtGVC3MWMNXdMDWfrmIlFZZ2OdoeT6pSNVRtk9+Sa7jwdPiMlNwb0ZQcS7NRlT92pCfmjRtkSWUW3RAKwg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.Diagnostics.Process": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "J0wOX07+QASQblsfxmIMFc9Iq7KTXYL3zs2G/Xc704Ylv3NpuVdo6gij6V3PGiptTxqsK0K7CdXenRvKUnkA2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "Microsoft.Win32.Registry": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.TraceSource": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VnYp1NxGx8Ww731y2LJ1vpfb/DKVNKEZ8Jsh5SgQTZREL/YpWRArgh9pI8CDLmgHspZmLL697CaLvH85qQpRiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Drawing.Common": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + } + }, + "System.Dynamic.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "SNVi1E/vfWUAs/WYKhE9+qlS6KqK0YVhnlT0HQtr8pMIA8YX3lwy3uPMownDwdYISBdmAF/2holEIldVp85Wag==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Formats.Asn1": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==" + }, + "System.Formats.Cbor": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "mGaLOoiw7KurJagOOcIsWUoCT5ACIiGxKlCcbYQASefBGXjnCcKTq5Hdjb94eEAKg38zXKlHw4c6EjzgBl9dIw==" + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IdentityModel.Tokens.Jwt": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "JRD8AuypBE+2zYxT3dMJomQVsPYsCqlyZhWel3J1d5nzQokSRyTueF+Q4ID3Jcu6zSZKuzOdJ1MLTkbQsDqcvQ==", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Rfm2jYCaUeGysFEZjDe7j1R4x6Z6BzumS/vUT5a1AA/AWJuGX71PoGB0RmpyX3VmrGqVnAwtfMn39OHR8Y/5+g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "qEePWsaq9LoEEIqhbGe6D5J8c9IqQOUuTzzV6wn1POlfdLkJliZY3OlB0j0f17uMWlqZYjH7txj+2YbyrIA8Yg==" + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Linq.Queryable": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "Yn/WfYe9RoRfmSLvUt2JerP0BTGGykCZkQPgojaxgzF2N0oPo+/AhB8TXOpdCcNlrG3VRtsamtK2uzsp3cqRVw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==", + "dependencies": { + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.6.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.4", + "contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.1", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.NameResolution": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "JdqRdM1Qym3YehqdKIi5LHrpypP4JMfxKQSNCJ2z4WawkG0il+N3XfNeJOxll2XrTnG7WgYYPoeiu/KOwg0DQw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.NetworkInformation": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "Q0rfeiW6QsiZuicGjrFA7cRr2+kXex0JIljTTxzI09GIftB8k+aNL31VsQD1sI2g31cw7UGDTgozA/FgeNSzsQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Linq": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.Sockets": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Overlapped": "4.0.1", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Requests": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "vxGt7C0cZixN+VqoSW4Yakc1Y9WknmxauDqzxgpw/FnBdz4kQNN51l4wxdXX5VY1xjqy//+G+4CvJWp1+f+y6Q==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Net.Http": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Claims": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Security.Principal": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Security": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Net.WebHeaderCollection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "XX2TIAN+wBSAIV51BU2FvvXMdstUa8b0FBSZmDWjZdwUMmggQSifpTOZ5fNH20z9ZCg2fkV1L5SsZnpO2RQDRQ==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0" + } + }, + "System.Net.WebSockets": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", + "dependencies": { + "Microsoft.Win32.Primitives": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.WebSockets.Client": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "NUCcDroX4lCQXgOrzlwIZ1u9YJ0krfyF0wk0ONnyLUmcQoEiYV2/OfUPRqUwQBbpH1BlGApkLgoQUwMqb5+c1g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.2", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Net.WebSockets": "4.0.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.X509Certificates": "4.1.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Numerics.Vectors": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Private.DataContractSerialization": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "lcqFBUaCZxPiUkA4dlSOoPZGtZsAuuElH2XHgLwGLxd7ZozWetV5yiz0qGAV2AUYOqw97MtZBjbLMN16Xz4vXA==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Collections.Concurrent": "4.0.12", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Emit.Lightweight": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1", + "System.Xml.XmlSerializer": "4.0.11" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Caching": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "30D6MkO8WF9jVGWZIP0hmCN8l9BTY4LCsAzLIe4xFSXzs+AjDotR7DpSmj27pFskDURzUvqYYY0ikModgBTxWw==", + "dependencies": { + "System.Configuration.ConfigurationManager": "5.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Runtime.Serialization.Json": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "+7DIJhnKYgCzUgcLbVTtRQb2l1M0FP549XFlFkQM5lmNiUBl44AfNbx4bz61xA8PzLtlYwfmif4JJJW7MPPnjg==", + "dependencies": { + "System.IO": "4.1.0", + "System.Private.DataContractSerialization": "4.1.1", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" + }, + "System.Security.Claims": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Security.Principal": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==", + "dependencies": { + "System.Formats.Asn1": "5.0.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Pkcs": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "elM3x+xSRhzQysiqo85SbidJJ2YbZlnvmh+53TuSZHsD7dNuuEWser+9EFtY+rYupBwkq2avc6ZCO3/6qACgmg==", + "dependencies": { + "System.Formats.Asn1": "6.0.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ==" + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Xml": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "i2Jn6rGXR63J0zIklImGRkDIJL4b1NfPSEbIVHBlqoIb12lfXIigCbDRpDmIEzwSo/v1U5y/rYJdzZYSyCWxvg==", + "dependencies": { + "System.Security.Cryptography.Pkcs": "4.5.0", + "System.Security.Permissions": "4.5.0" + } + }, + "System.Security.Permissions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==", + "dependencies": { + "System.Security.AccessControl": "6.0.0", + "System.Windows.Extensions": "6.0.0" + } + }, + "System.Security.Principal": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, + "System.Security.SecureString": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "sqzq9GD6/b0yqPuMpgIKBuoLf4VKAj8oAfh4kXSzPaN6eoKY3hRi9C5L27uip25qlU+BGPfb0xh2Rmbwc4jFVA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "NyscU59xX6Uo91qvhOs2Ccho3AR2TnZPomo1Z0K6YpyztBPM/A5VbkzOO19sy3A3i1TtEnTxA7bCe3Us+r5MWg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "zaJsHfESQvJ11vbXnNlkrR46IaMULk/gHxYsJphzSF+07kTjPHv+Oc14w6QEOfo3Q4hqLJgStUaYB9DBl0TmWg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Overlapped": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "f7aLuLkBoCQM2kng7zqLFBXz9Gk48gDK8lk1ih9rH/1arJJzZK9gJwNvPDhL6Ps/l6rwOr8jw+4FCHL0KKWiEg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Threading.Thread": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OHmbT+Zz065NKII/ZHcH9XO1dEuLGI1L2k7uYss+9C1jLxTC9kTZZuzUOyXHayRk+dft9CiDf3I/QZ0t8JKyBQ==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading.ThreadPool": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.ValueTuple": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" + }, + "System.Windows.Extensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==", + "dependencies": { + "System.Drawing.Common": "6.0.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "lJ8AxvkX7GQxpC6GFCeBj8ThYVyQczx2+f/cWHJU8tjS7YfI6Cv6bon70jVEgs2CiFbmmM8b9j1oZVx0dSI2Ww==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlSerializer": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "FrazwwqfIXTfq23mfv4zH+BjqkSFNaNFBtjzu3I9NRmG8EELYyrv/fJnttCIwRMFRR/YKXF1hmsMmMEnl55HGw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1" + } + }, + "System.Xml.XPath": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "v1JQ5SETnQusqmS3RwStF7vwQ3L02imIzl++sewmt23VGygix04pEH+FCj1yWb+z4GDzKiljr1W7Wfvrx0YwgA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XPath.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "A/uxsWi/Ifzkmd4ArTLISMbfFs6XpRPsXZonrIqyTY70xi8t+mDtvSM5Os0RqyRDobjMBwIDHDL4NOIbkDwf7A==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XPath": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "xunit.abstractions": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" + }, + "xunit.analyzers": { + "type": "Transitive", + "resolved": "0.10.0", + "contentHash": "4/IDFCJfIeg6bix9apmUtIMwvOsiwqdEexeO/R2D4GReIGPLIRODTpId/l4LRSrAJk9lEO3Zx1H0Zx6uohJDNg==" + }, + "xunit.assert": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "O/Oe0BS5RmSsM+LQOb041TzuPo5MdH2Rov+qXGS37X+KFG1Hxz7kopYklM5+1Y+tRGeXrOx5+Xne1RuqLFQoyQ==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "xunit.core": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "Zsj5OMU6JasNGERXZy8s72+pcheG6Q15atS5XpZXqAtULuyQiQ6XNnUsp1gyfC6WgqScqMvySiEHmHcOG6Eg0Q==", + "dependencies": { + "xunit.extensibility.core": "[2.4.1]", + "xunit.extensibility.execution": "[2.4.1]" + } + }, + "xunit.extensibility.core": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "yKZKm/8QNZnBnGZFD9SewkllHBiK0DThybQD/G4PiAmQjKtEZyHi6ET70QPU9KtSMJGRYS6Syk7EyR2EVDU4Kg==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.abstractions": "2.0.3" + } + }, + "xunit.extensibility.execution": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "7e/1jqBpcb7frLkB6XDrHCGXAbKN4Rtdb88epYxCSRQuZDRW8UtTfdTEVpdTl8s4T56e07hOBVd4G0OdCxIY2A==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.extensibility.core": "[2.4.1]" + } + }, + "YubicoDotNetClient": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "uP5F3Ko1gqZi3lwS2R/jAAwhBxXs/6PKDpS6FdQjsBA5qmF0hQmbtfxM6QHTXOMoWbUtfetG7+LtgmG8T5zDIg==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "commercial.core": { + "type": "Project", + "dependencies": { + "Core": "[2023.1.0, )" + } + }, + "common": { + "type": "Project", + "dependencies": { + "AutoFixture.AutoNSubstitute": "[4.17.0, )", + "AutoFixture.Xunit2": "[4.17.0, )", + "Core": "[2023.1.0, )", + "Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )", + "Microsoft.NET.Test.Sdk": "[17.1.0, )", + "NSubstitute": "[4.3.0, )", + "xunit": "[2.4.1, )" + } + }, + "core": { + "type": "Project", + "dependencies": { + "AWSSDK.SQS": "[3.7.2.47, )", + "AWSSDK.SimpleEmail": "[3.7.0.150, )", + "AspNetCoreRateLimit": "[4.0.2, )", + "AspNetCoreRateLimit.Redis": "[1.0.1, )", + "Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.2.1, )", + "Azure.Storage.Blobs": "[12.11.0, )", + "Azure.Storage.Queues": "[12.9.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "Fido2.AspNet": "[3.0.1, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "MailKit": "[3.2.0, )", + "Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )", + "Microsoft.Azure.Cosmos.Table": "[1.0.8, )", + "Microsoft.Azure.NotificationHubs": "[4.1.0, )", + "Microsoft.Azure.ServiceBus": "[5.2.0, )", + "Microsoft.Data.SqlClient": "[5.0.1, )", + "Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )", + "Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )", + "Microsoft.Extensions.Identity.Stores": "[6.0.4, )", + "Newtonsoft.Json": "[13.0.1, )", + "Otp.NET": "[1.2.2, )", + "Quartz": "[3.4.0, )", + "SendGrid": "[9.27.0, )", + "Sentry.Serilog": "[3.16.0, )", + "Serilog.AspNetCore": "[5.0.0, )", + "Serilog.Extensions.Logging": "[3.1.0, )", + "Serilog.Extensions.Logging.File": "[2.0.0, )", + "Serilog.Sinks.AzureCosmosDB": "[2.0.0, )", + "Serilog.Sinks.SyslogMessages": "[2.0.6, )", + "Stripe.net": "[40.0.0, )", + "YubicoDotNetClient": "[1.2.0, )" + } + }, + "core.test": { + "type": "Project", + "dependencies": { + "AutoFixture.AutoNSubstitute": "[4.17.0, )", + "AutoFixture.Xunit2": "[4.17.0, )", + "Common": "[2023.1.0, )", + "Core": "[2023.1.0, )", + "Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )", + "Microsoft.NET.Test.Sdk": "[17.1.0, )", + "Moq": "[4.17.2, )", + "NSubstitute": "[4.3.0, )", + "xunit": "[2.4.1, )" + } + } + } + } +} \ No newline at end of file diff --git a/bitwarden_license/test/Scim.IntegrationTest/Controllers/v2/GroupsControllerTests.cs b/bitwarden_license/test/Scim.IntegrationTest/Controllers/v2/GroupsControllerTests.cs new file mode 100644 index 000000000..2e29334cc --- /dev/null +++ b/bitwarden_license/test/Scim.IntegrationTest/Controllers/v2/GroupsControllerTests.cs @@ -0,0 +1,601 @@ +using System.Text.Json; +using Bit.Scim.IntegrationTest.Factories; +using Bit.Scim.Models; +using Bit.Scim.Utilities; +using Bit.Test.Common.Helpers; +using Xunit; + +namespace Bit.Scim.IntegrationTest.Controllers.v2; + +public class GroupsControllerTests : IClassFixture, IAsyncLifetime +{ + private const int _initialGroupCount = 3; + private const int _initialGroupUsersCount = 2; + + private readonly ScimApplicationFactory _factory; + + public GroupsControllerTests(ScimApplicationFactory factory) + { + _factory = factory; + _factory.DatabaseName = "test_database_groups"; + } + + public Task InitializeAsync() + { + var databaseContext = _factory.GetDatabaseContext(); + _factory.ReinitializeDbForTests(databaseContext); + return Task.CompletedTask; + } + + Task IAsyncLifetime.DisposeAsync() => Task.CompletedTask; + + [Fact] + public async Task Get_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var groupId = ScimApplicationFactory.TestGroupId1; + var expectedResponse = new ScimGroupResponseModel + { + Id = groupId, + DisplayName = "Test Group 1", + ExternalId = "A", + Schemas = new List { ScimConstants.Scim2SchemaGroup } + }; + + var context = await _factory.GroupsGetAsync(organizationId, groupId); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task Get_NotFound() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var groupId = Guid.NewGuid().ToString(); + var expectedResponse = new ScimErrorResponseModel + { + Status = StatusCodes.Status404NotFound, + Detail = "Group not found.", + Schemas = new List { ScimConstants.Scim2SchemaError } + }; + + var context = await _factory.GroupsGetAsync(organizationId, groupId); + + Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task GetList_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + string filter = null; + int? itemsPerPage = 2; + int? startIndex = 1; + var expectedResponse = new ScimListResponseModel + { + ItemsPerPage = itemsPerPage.Value, + TotalResults = 3, + StartIndex = startIndex.Value, + Resources = new List + { + new ScimGroupResponseModel + { + Id = ScimApplicationFactory.TestGroupId1, + DisplayName = "Test Group 1", + ExternalId = "A", + Schemas = new List { ScimConstants.Scim2SchemaGroup } + }, + new ScimGroupResponseModel + { + Id = ScimApplicationFactory.TestGroupId2, + DisplayName = "Test Group 2", + ExternalId = "B", + Schemas = new List { ScimConstants.Scim2SchemaGroup } + } + }, + Schemas = new List { ScimConstants.Scim2SchemaListResponse } + }; + + var context = await _factory.GroupsGetListAsync(organizationId, filter, itemsPerPage, startIndex); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task GetList_SearchDisplayName_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + string filter = "displayName eq Test Group 2"; + int? itemsPerPage = 10; + int? startIndex = 1; + var expectedResponse = new ScimListResponseModel + { + ItemsPerPage = itemsPerPage.Value, + TotalResults = 1, + StartIndex = startIndex.Value, + Resources = new List + { + new ScimGroupResponseModel + { + Id = ScimApplicationFactory.TestGroupId2, + DisplayName = "Test Group 2", + ExternalId = "B", + Schemas = new List { ScimConstants.Scim2SchemaGroup } + } + }, + Schemas = new List { ScimConstants.Scim2SchemaListResponse } + }; + + var context = await _factory.GroupsGetListAsync(organizationId, filter, itemsPerPage, startIndex); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task GetList_SearchExternalId_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + string filter = "externalId eq C"; + int? itemsPerPage = 10; + int? startIndex = 1; + var expectedResponse = new ScimListResponseModel + { + ItemsPerPage = itemsPerPage.Value, + TotalResults = 1, + StartIndex = startIndex.Value, + Resources = new List + { + new ScimGroupResponseModel + { + Id = ScimApplicationFactory.TestGroupId3, + DisplayName = "Test Group 3", + ExternalId = "C", + Schemas = new List { ScimConstants.Scim2SchemaGroup } + } + }, + Schemas = new List { ScimConstants.Scim2SchemaListResponse } + }; + + + var context = await _factory.GroupsGetListAsync(organizationId, filter, itemsPerPage, startIndex); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task GetList_EmptyResult_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + string filter = "externalId eq Z"; + int? itemsPerPage = 10; + int? startIndex = 1; + var expectedResponse = new ScimListResponseModel + { + ItemsPerPage = itemsPerPage.Value, + TotalResults = 0, + StartIndex = startIndex.Value, + Resources = new List(), + Schemas = new List { ScimConstants.Scim2SchemaListResponse } + }; + + + var context = await _factory.GroupsGetListAsync(organizationId, filter, itemsPerPage, startIndex); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task Post_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var displayName = "New Group"; + var externalId = Guid.NewGuid().ToString(); + var inputModel = new ScimGroupRequestModel + { + DisplayName = displayName, + ExternalId = externalId.ToString(), + Members = new List + { + new ScimGroupRequestModel.GroupMembersModel { Display = "user1@example.com", Value = ScimApplicationFactory.TestOrganizationUserId1 } + }, + Schemas = new List() { ScimConstants.Scim2SchemaGroup } + }; + var expectedResponse = new ScimGroupResponseModel + { + DisplayName = displayName, + ExternalId = externalId, + Schemas = new List { ScimConstants.Scim2SchemaGroup } + }; + + var context = await _factory.GroupsPostAsync(organizationId, inputModel); + + Assert.Equal(StatusCodes.Status201Created, context.Response.StatusCode); + + // Verifying that the response includes a header with the URL of the created Group + Assert.Contains(context.Response.Headers, h => h.Key == "Location"); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel, "Id"); + Assert.NotNull(responseModel.Id); + + var databaseContext = _factory.GetDatabaseContext(); + Assert.Equal(_initialGroupCount + 1, databaseContext.Groups.Count()); + Assert.True(databaseContext.Groups.Any(g => g.Name == displayName && g.ExternalId == externalId)); + + Assert.Equal(_initialGroupUsersCount + 1, databaseContext.GroupUsers.Count()); + Assert.True(databaseContext.GroupUsers.Any(gu => gu.GroupId.ToString() == responseModel.Id && gu.OrganizationUserId.ToString() == ScimApplicationFactory.TestOrganizationUserId1)); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public async Task Post_InvalidDisplayName_BadRequest(string displayName) + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var model = new ScimGroupRequestModel + { + DisplayName = displayName, + ExternalId = null, + Members = null, + Schemas = new List() { ScimConstants.Scim2SchemaGroup } + }; + + var context = await _factory.GroupsPostAsync(organizationId, model); + + Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode); + } + + [Fact] + public async Task Post_ExistingExternalId_Conflict() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var model = new ScimGroupRequestModel + { + DisplayName = "New Group", + ExternalId = "A", + Members = null, + Schemas = new List() { ScimConstants.Scim2SchemaGroup } + }; + + var context = await _factory.GroupsPostAsync(organizationId, model); + + Assert.Equal(StatusCodes.Status409Conflict, context.Response.StatusCode); + + var databaseContext = _factory.GetDatabaseContext(); + Assert.Equal(_initialGroupCount, databaseContext.Groups.Count()); + Assert.False(databaseContext.Groups.Any(g => g.Name == "New Group")); + } + + [Fact] + public async Task Put_ChangeNameAndMembers_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var groupId = ScimApplicationFactory.TestGroupId1; + var newGroupName = Guid.NewGuid().ToString(); + var inputModel = new ScimGroupRequestModel + { + DisplayName = newGroupName, + ExternalId = "A", + Members = new List + { + new ScimGroupRequestModel.GroupMembersModel { Display = "user2@example.com", Value = ScimApplicationFactory.TestOrganizationUserId2 }, + new ScimGroupRequestModel.GroupMembersModel { Display = "user3@example.com", Value = ScimApplicationFactory.TestOrganizationUserId3 } + }, + Schemas = new List() { ScimConstants.Scim2SchemaGroup } + }; + var expectedResponse = new ScimGroupResponseModel + { + Id = groupId, + DisplayName = newGroupName, + ExternalId = "A", + Schemas = new List() { ScimConstants.Scim2SchemaGroup } + }; + + var context = await _factory.GroupsPutAsync(organizationId, groupId, inputModel); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + + var databaseContext = _factory.GetDatabaseContext(); + var firstGroup = databaseContext.Groups.FirstOrDefault(g => g.Id.ToString() == groupId); + Assert.Equal(newGroupName, firstGroup.Name); + + Assert.Equal(2, databaseContext.GroupUsers.Count(gu => gu.GroupId.ToString() == groupId)); + Assert.NotNull(databaseContext.GroupUsers.FirstOrDefault(gu => gu.GroupId.ToString() == groupId && gu.OrganizationUserId.ToString() == ScimApplicationFactory.TestOrganizationUserId2)); + Assert.NotNull(databaseContext.GroupUsers.FirstOrDefault(gu => gu.GroupId.ToString() == groupId && gu.OrganizationUserId.ToString() == ScimApplicationFactory.TestOrganizationUserId3)); + } + + [Fact] + public async Task Put_NotFound() + { + var newGroupName = "Test Group 1 New Name"; + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var groupId = Guid.NewGuid().ToString(); + var inputModel = new ScimGroupRequestModel + { + DisplayName = newGroupName, + ExternalId = "A", + Members = new List(), + Schemas = new List() { ScimConstants.Scim2SchemaGroup } + }; + var expectedResponse = new ScimErrorResponseModel + { + Status = StatusCodes.Status404NotFound, + Detail = "Group not found.", + Schemas = new List { ScimConstants.Scim2SchemaError } + }; + + var context = await _factory.GroupsPutAsync(organizationId, groupId, inputModel); + + Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task Patch_ReplaceDisplayName_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var groupId = ScimApplicationFactory.TestGroupId1; + var newDisplayName = "Patch Display Name"; + var inputModel = new ScimPatchModel + { + Operations = new List() + { + new ScimPatchModel.OperationModel + { + Op = "replace", + Value = JsonDocument.Parse($"{{\"displayName\":\"{newDisplayName}\"}}").RootElement + } + }, + Schemas = new List() { ScimConstants.Scim2SchemaGroup } + }; + + var context = await _factory.GroupsPatchAsync(organizationId, groupId, inputModel); + + Assert.Equal(StatusCodes.Status204NoContent, context.Response.StatusCode); + + var databaseContext = _factory.GetDatabaseContext(); + var group = databaseContext.Groups.FirstOrDefault(g => g.Id.ToString() == groupId); + Assert.Equal(newDisplayName, group.Name); + + Assert.Equal(_initialGroupUsersCount, databaseContext.GroupUsers.Count()); + Assert.True(databaseContext.GroupUsers.Any(gu => gu.OrganizationUserId.ToString() == ScimApplicationFactory.TestOrganizationUserId1)); + Assert.True(databaseContext.GroupUsers.Any(gu => gu.OrganizationUserId.ToString() == ScimApplicationFactory.TestOrganizationUserId4)); + } + + [Fact] + public async Task Patch_ReplaceMembers_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var groupId = ScimApplicationFactory.TestGroupId1; + var inputModel = new ScimPatchModel + { + Operations = new List() + { + new ScimPatchModel.OperationModel + { + Op = "replace", + Path = "members", + Value = JsonDocument.Parse($"[{{\"value\":\"{ScimApplicationFactory.TestOrganizationUserId2}\"}}]").RootElement + } + }, + Schemas = new List() { ScimConstants.Scim2SchemaGroup } + }; + + var context = await _factory.GroupsPatchAsync(organizationId, groupId, inputModel); + + Assert.Equal(StatusCodes.Status204NoContent, context.Response.StatusCode); + + var databaseContext = _factory.GetDatabaseContext(); + Assert.Single(databaseContext.GroupUsers); + + Assert.Equal(_initialGroupUsersCount - 1, databaseContext.GroupUsers.Count()); + var groupUser = databaseContext.GroupUsers.FirstOrDefault(); + Assert.Equal(ScimApplicationFactory.TestOrganizationUserId2, groupUser.OrganizationUserId.ToString()); + } + + [Fact] + public async Task Patch_AddSingleMember_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var groupId = ScimApplicationFactory.TestGroupId1; + var inputModel = new ScimPatchModel + { + Operations = new List() + { + new ScimPatchModel.OperationModel + { + Op = "add", + Path = $"members[value eq \"{ScimApplicationFactory.TestOrganizationUserId2}\"]", + Value = JsonDocument.Parse("{}").RootElement + } + }, + Schemas = new List() { ScimConstants.Scim2SchemaGroup } + }; + + var context = await _factory.GroupsPatchAsync(organizationId, groupId, inputModel); + + Assert.Equal(StatusCodes.Status204NoContent, context.Response.StatusCode); + + var databaseContext = _factory.GetDatabaseContext(); + Assert.Equal(_initialGroupUsersCount + 1, databaseContext.GroupUsers.Count()); + Assert.True(databaseContext.GroupUsers.Any(gu => gu.GroupId.ToString() == groupId && gu.OrganizationUserId.ToString() == ScimApplicationFactory.TestOrganizationUserId1)); + Assert.True(databaseContext.GroupUsers.Any(gu => gu.GroupId.ToString() == groupId && gu.OrganizationUserId.ToString() == ScimApplicationFactory.TestOrganizationUserId2)); + Assert.True(databaseContext.GroupUsers.Any(gu => gu.GroupId.ToString() == groupId && gu.OrganizationUserId.ToString() == ScimApplicationFactory.TestOrganizationUserId4)); + } + + [Fact] + public async Task Patch_AddListMembers_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var groupId = ScimApplicationFactory.TestGroupId2; + var inputModel = new ScimPatchModel + { + Operations = new List() + { + new ScimPatchModel.OperationModel + { + Op = "add", + Path = "members", + Value = JsonDocument.Parse($"[{{\"value\":\"{ScimApplicationFactory.TestOrganizationUserId2}\"}},{{\"value\":\"{ScimApplicationFactory.TestOrganizationUserId3}\"}}]").RootElement + } + }, + Schemas = new List() { ScimConstants.Scim2SchemaGroup } + }; + + var context = await _factory.GroupsPatchAsync(organizationId, groupId, inputModel); + + Assert.Equal(StatusCodes.Status204NoContent, context.Response.StatusCode); + + var databaseContext = _factory.GetDatabaseContext(); + Assert.True(databaseContext.GroupUsers.Any(gu => gu.GroupId.ToString() == groupId && gu.OrganizationUserId.ToString() == ScimApplicationFactory.TestOrganizationUserId2)); + Assert.True(databaseContext.GroupUsers.Any(gu => gu.GroupId.ToString() == groupId && gu.OrganizationUserId.ToString() == ScimApplicationFactory.TestOrganizationUserId3)); + } + + [Fact] + public async Task Patch_RemoveSingleMember_ReplaceDisplayName_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var groupId = ScimApplicationFactory.TestGroupId1; + var newDisplayName = "Patch Display Name"; + var inputModel = new ScimPatchModel + { + Operations = new List() + { + new ScimPatchModel.OperationModel + { + Op = "remove", + Path = $"members[value eq \"{ScimApplicationFactory.TestOrganizationUserId1}\"]", + Value = JsonDocument.Parse("{}").RootElement + }, + new ScimPatchModel.OperationModel + { + Op = "replace", + Value = JsonDocument.Parse($"{{\"displayName\":\"{newDisplayName}\"}}").RootElement + } + }, + Schemas = new List() { ScimConstants.Scim2SchemaGroup } + }; + + var context = await _factory.GroupsPatchAsync(organizationId, groupId, inputModel); + + Assert.Equal(StatusCodes.Status204NoContent, context.Response.StatusCode); + + var databaseContext = _factory.GetDatabaseContext(); + Assert.Equal(_initialGroupUsersCount - 1, databaseContext.GroupUsers.Count()); + Assert.Equal(_initialGroupCount, databaseContext.Groups.Count()); + + var group = databaseContext.Groups.FirstOrDefault(g => g.Id.ToString() == groupId); + Assert.Equal(newDisplayName, group.Name); + } + + [Fact] + public async Task Patch_RemoveListMembers_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var groupId = ScimApplicationFactory.TestGroupId1; + var inputModel = new ScimPatchModel + { + Operations = new List() + { + new ScimPatchModel.OperationModel + { + Op = "remove", + Path = "members", + Value = JsonDocument.Parse($"[{{\"value\":\"{ScimApplicationFactory.TestOrganizationUserId1}\"}}, {{\"value\":\"{ScimApplicationFactory.TestOrganizationUserId4}\"}}]").RootElement + } + }, + Schemas = new List() { ScimConstants.Scim2SchemaGroup } + }; + + var context = await _factory.GroupsPatchAsync(organizationId, groupId, inputModel); + + Assert.Equal(StatusCodes.Status204NoContent, context.Response.StatusCode); + + var databaseContext = _factory.GetDatabaseContext(); + Assert.Empty(databaseContext.GroupUsers); + } + + [Fact] + public async Task Patch_NotFound() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var groupId = Guid.NewGuid().ToString(); + var inputModel = new Models.ScimPatchModel + { + Operations = new List(), + Schemas = new List() { ScimConstants.Scim2SchemaGroup } + }; + var expectedResponse = new ScimErrorResponseModel + { + Status = StatusCodes.Status404NotFound, + Detail = "Group not found.", + Schemas = new List { ScimConstants.Scim2SchemaError } + }; + + var context = await _factory.GroupsPatchAsync(organizationId, groupId, inputModel); + + Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task Delete_Success() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var groupId = ScimApplicationFactory.TestGroupId3; + + var context = await _factory.GroupsDeleteAsync(organizationId, groupId); + + Assert.Equal(StatusCodes.Status204NoContent, context.Response.StatusCode); + + var databaseContext = _factory.GetDatabaseContext(); + Assert.Equal(_initialGroupCount - 1, databaseContext.Groups.Count()); + Assert.True(databaseContext.Groups.FirstOrDefault(g => g.Id.ToString() == groupId) == null); + } + + [Fact] + public async Task Delete_NotFound() + { + var organizationId = ScimApplicationFactory.TestOrganizationId1; + var groupId = Guid.NewGuid().ToString(); + var expectedResponse = new ScimErrorResponseModel + { + Status = StatusCodes.Status404NotFound, + Detail = "Group not found.", + Schemas = new List { ScimConstants.Scim2SchemaError } + }; + + var context = await _factory.GroupsDeleteAsync(organizationId, groupId); + + Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } +} diff --git a/bitwarden_license/test/Scim.IntegrationTest/Controllers/v2/UsersControllerTests.cs b/bitwarden_license/test/Scim.IntegrationTest/Controllers/v2/UsersControllerTests.cs new file mode 100644 index 000000000..c4f7ade0a --- /dev/null +++ b/bitwarden_license/test/Scim.IntegrationTest/Controllers/v2/UsersControllerTests.cs @@ -0,0 +1,547 @@ +using System.Text.Json; +using Bit.Core.Enums; +using Bit.Scim.IntegrationTest.Factories; +using Bit.Scim.Models; +using Bit.Scim.Utilities; +using Bit.Test.Common.Helpers; +using Xunit; + +namespace Bit.Scim.IntegrationTest.Controllers.v2; + +public class UsersControllerTests : IClassFixture, IAsyncLifetime +{ + private const int _initialUserCount = 4; + + private readonly ScimApplicationFactory _factory; + + public UsersControllerTests(ScimApplicationFactory factory) + { + _factory = factory; + _factory.DatabaseName = "test_database_users"; + } + + public Task InitializeAsync() + { + var databaseContext = _factory.GetDatabaseContext(); + _factory.ReinitializeDbForTests(databaseContext); + return Task.CompletedTask; + } + + Task IAsyncLifetime.DisposeAsync() => Task.CompletedTask; + + [Fact] + public async Task Get_Success() + { + var organizationUserId = ScimApplicationFactory.TestOrganizationUserId1; + var expectedResponse = new ScimUserResponseModel + { + Id = ScimApplicationFactory.TestOrganizationUserId1, + DisplayName = "Test User 1", + ExternalId = "UA", + Active = true, + Emails = new List + { + new BaseScimUserModel.EmailModel { Primary = true, Type = "work", Value = "user1@example.com" } + }, + Groups = new List(), + Name = new BaseScimUserModel.NameModel("Test User 1"), + UserName = "user1@example.com", + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + var context = await _factory.UsersGetAsync(ScimApplicationFactory.TestOrganizationId1, organizationUserId); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task Get_NotFound() + { + var organizationUserId = Guid.NewGuid().ToString(); + var expectedResponse = new ScimErrorResponseModel + { + Status = StatusCodes.Status404NotFound, + Detail = "User not found.", + Schemas = new List { ScimConstants.Scim2SchemaError } + }; + + var context = await _factory.UsersGetAsync(ScimApplicationFactory.TestOrganizationId1, organizationUserId); + + Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task GetList_Success() + { + string filter = null; + int? itemsPerPage = 2; + int? startIndex = 1; + var expectedResponse = new ScimListResponseModel + { + ItemsPerPage = itemsPerPage.Value, + // Note: total matching results is larger than resources actually returned due to pagination settings. See https://www.rfc-editor.org/rfc/rfc7644#section-3.4.2 + TotalResults = 4, + StartIndex = startIndex.Value, + Resources = new List + { + new ScimUserResponseModel + { + Id = ScimApplicationFactory.TestOrganizationUserId1, + DisplayName = "Test User 1", + ExternalId = "UA", + Active = true, + Emails = new List + { + new BaseScimUserModel.EmailModel { Primary = true, Type = "work", Value = "user1@example.com" } + }, + Groups = new List(), + Name = new BaseScimUserModel.NameModel("Test User 1"), + UserName = "user1@example.com", + Schemas = new List { ScimConstants.Scim2SchemaUser } + }, + new ScimUserResponseModel + { + Id = ScimApplicationFactory.TestOrganizationUserId2, + DisplayName = "Test User 2", + ExternalId = "UB", + Active = true, + Emails = new List + { + new BaseScimUserModel.EmailModel { Primary = true, Type = "work", Value = "user2@example.com" } + }, + Groups = new List(), + Name = new BaseScimUserModel.NameModel("Test User 2"), + UserName = "user2@example.com", + Schemas = new List { ScimConstants.Scim2SchemaUser } + } + }, + Schemas = new List { ScimConstants.Scim2SchemaListResponse } + }; + + var context = await _factory.UsersGetListAsync(ScimApplicationFactory.TestOrganizationId1, filter, itemsPerPage, startIndex); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task GetList_SearchUserName_Success() + { + string filter = "userName eq user2@example.com"; + int? itemsPerPage = 10; + int? startIndex = 1; + var expectedResponse = new ScimListResponseModel + { + ItemsPerPage = itemsPerPage.Value, + TotalResults = 1, + StartIndex = startIndex.Value, + Resources = new List + { + new ScimUserResponseModel + { + Id = ScimApplicationFactory.TestOrganizationUserId2, + DisplayName = "Test User 2", + ExternalId = "UB", + Active = true, + Emails = new List + { + new BaseScimUserModel.EmailModel { Primary = true, Type = "work", Value = "user2@example.com" } + }, + Groups = new List(), + Name = new BaseScimUserModel.NameModel("Test User 2"), + UserName = "user2@example.com", + Schemas = new List { ScimConstants.Scim2SchemaUser } + } + }, + Schemas = new List { ScimConstants.Scim2SchemaListResponse } + }; + + var context = await _factory.UsersGetListAsync(ScimApplicationFactory.TestOrganizationId1, filter, itemsPerPage, startIndex); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task GetList_SearchExternalId_Success() + { + string filter = "externalId eq UC"; + int? itemsPerPage = 10; + int? startIndex = 1; + var expectedResponse = new ScimListResponseModel + { + ItemsPerPage = itemsPerPage.Value, + TotalResults = 1, + StartIndex = startIndex.Value, + Resources = new List + { + new ScimUserResponseModel + { + Id = ScimApplicationFactory.TestOrganizationUserId3, + DisplayName = "Test User 3", + ExternalId = "UC", + Active = false, + Emails = new List + { + new BaseScimUserModel.EmailModel { Primary = true, Type = "work", Value = "user3@example.com" } + }, + Groups = new List(), + Name = new BaseScimUserModel.NameModel("Test User 3"), + UserName = "user3@example.com", + Schemas = new List { ScimConstants.Scim2SchemaUser } + } + }, + Schemas = new List { ScimConstants.Scim2SchemaListResponse } + }; + + var context = await _factory.UsersGetListAsync(ScimApplicationFactory.TestOrganizationId1, filter, itemsPerPage, startIndex); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task GetList_EmptyResult_Success() + { + string filter = "externalId eq UZ"; + int? itemsPerPage = 10; + int? startIndex = 1; + var expectedResponse = new ScimListResponseModel + { + ItemsPerPage = itemsPerPage.Value, + TotalResults = 0, + StartIndex = startIndex.Value, + Resources = new List(), + Schemas = new List { ScimConstants.Scim2SchemaListResponse } + }; + + var context = await _factory.UsersGetListAsync(ScimApplicationFactory.TestOrganizationId1, filter, itemsPerPage, startIndex); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize>(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task Post_Success() + { + var email = "user5@example.com"; + var displayName = "Test User 5"; + var externalId = "UE"; + var inputModel = new ScimUserRequestModel + { + Name = new BaseScimUserModel.NameModel(displayName), + DisplayName = displayName, + Emails = new List { new BaseScimUserModel.EmailModel(email) }, + ExternalId = externalId, + Active = true, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + var expectedResponse = new ScimUserResponseModel + { + // DisplayName is not being saved + ExternalId = externalId, + Active = true, + Emails = new List + { + new BaseScimUserModel.EmailModel { Primary = true, Type = "work", Value = email } + }, + Groups = new List(), + Name = new BaseScimUserModel.NameModel(), + UserName = email, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + var context = await _factory.UsersPostAsync(ScimApplicationFactory.TestOrganizationId1, inputModel); + + Assert.Equal(StatusCodes.Status201Created, context.Response.StatusCode); + + // Verifying that the response includes a header with the URL of the created Group + Assert.Contains(context.Response.Headers, h => h.Key == "Location"); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel, "Id"); + Assert.NotNull(responseModel.Id); + + var databaseContext = _factory.GetDatabaseContext(); + Assert.Equal(_initialUserCount + 1, databaseContext.OrganizationUsers.Count()); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public async Task Post_InvalidEmail_BadRequest(string email) + { + var displayName = "Test User 5"; + var externalId = "UE"; + var inputModel = new ScimUserRequestModel + { + Name = new BaseScimUserModel.NameModel(displayName), + DisplayName = displayName, + Emails = new List { new BaseScimUserModel.EmailModel(email) }, + ExternalId = externalId, + Active = true, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + var context = await _factory.UsersPostAsync(ScimApplicationFactory.TestOrganizationId1, inputModel); + + Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode); + } + + [Fact] + public async Task Post_Inactive_BadRequest() + { + var displayName = "Test User 5"; + var inputModel = new ScimUserRequestModel + { + DisplayName = displayName, + ExternalId = null, + Active = false, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + var context = await _factory.UsersPostAsync(ScimApplicationFactory.TestOrganizationId1, inputModel); + + Assert.Equal(StatusCodes.Status400BadRequest, context.Response.StatusCode); + } + + [Theory] + [InlineData("user1@example.com", "UZ")] + [InlineData("userZ@example.com", "UA")] + public async Task Post_ExistingData_Conflict(string email, string externalId) + { + var inputModel = new ScimUserRequestModel + { + DisplayName = "New User", + Emails = new List { new BaseScimUserModel.EmailModel(email) }, + ExternalId = externalId, + Schemas = null, + Active = true + }; + + var context = await _factory.UsersPostAsync(ScimApplicationFactory.TestOrganizationId1, inputModel); + + Assert.Equal(StatusCodes.Status409Conflict, context.Response.StatusCode); + + var databaseContext = _factory.GetDatabaseContext(); + Assert.Equal(_initialUserCount, databaseContext.OrganizationUsers.Count()); + } + + [Fact] + public async Task Put_RevokeUser_Success() + { + var organizationUserId = ScimApplicationFactory.TestOrganizationUserId2; + var inputModel = new ScimUserRequestModel + { + Active = false + }; + var expectedResponse = new ScimUserResponseModel + { + Id = ScimApplicationFactory.TestOrganizationUserId2, + DisplayName = "Test User 2", + ExternalId = "UB", + Active = false, + Emails = new List + { + new BaseScimUserModel.EmailModel { Primary = true, Type = "work", Value = "user2@example.com" } + }, + Groups = new List(), + Name = new BaseScimUserModel.NameModel("Test User 2"), + UserName = "user2@example.com", + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + var context = await _factory.UsersPutAsync(ScimApplicationFactory.TestOrganizationId1, organizationUserId, inputModel); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + + var databaseContext = _factory.GetDatabaseContext(); + var revokedUser = databaseContext.OrganizationUsers.FirstOrDefault(g => g.Id.ToString() == organizationUserId); + Assert.Equal(OrganizationUserStatusType.Revoked, revokedUser.Status); + } + + [Fact] + public async Task Put_RestoreUser_Success() + { + var organizationUserId = ScimApplicationFactory.TestOrganizationUserId3; + var inputModel = new ScimUserRequestModel + { + Active = true + }; + var expectedResponse = new ScimUserResponseModel + { + Id = ScimApplicationFactory.TestOrganizationUserId3, + DisplayName = "Test User 3", + ExternalId = "UC", + Active = true, + Emails = new List + { + new BaseScimUserModel.EmailModel { Primary = true, Type = "work", Value = "user3@example.com" } + }, + Groups = new List(), + Name = new BaseScimUserModel.NameModel("Test User 3"), + UserName = "user3@example.com", + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + var context = await _factory.UsersPutAsync(ScimApplicationFactory.TestOrganizationId1, organizationUserId, inputModel); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + + var databaseContext = _factory.GetDatabaseContext(); + var revokedUser = databaseContext.OrganizationUsers.FirstOrDefault(g => g.Id.ToString() == organizationUserId); + Assert.NotEqual(OrganizationUserStatusType.Revoked, revokedUser.Status); + } + + [Fact] + public async Task Put_NotFound() + { + var organizationUserId = Guid.NewGuid(); + var inputModel = new ScimUserRequestModel + { + DisplayName = "Test Group 1", + ExternalId = "AA", + Schemas = new List() + }; + var expectedResponse = new ScimErrorResponseModel + { + Status = StatusCodes.Status404NotFound, + Detail = "User not found.", + Schemas = new List { ScimConstants.Scim2SchemaError } + }; + + var context = await _factory.UsersPutAsync(ScimApplicationFactory.TestOrganizationId1, organizationUserId.ToString(), inputModel); + + Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task Patch_ReplaceRevoke_Success() + { + var organizationUserId = ScimApplicationFactory.TestOrganizationUserId2; + var inputModel = new ScimPatchModel + { + Operations = new List() + { + new ScimPatchModel.OperationModel { Op = "replace", Value = JsonDocument.Parse("{\"active\":false}").RootElement }, + }, + Schemas = new List() + }; + + var context = await _factory.UsersPatchAsync(ScimApplicationFactory.TestOrganizationId1, organizationUserId, inputModel); + + Assert.Equal(StatusCodes.Status204NoContent, context.Response.StatusCode); + + var databaseContext = _factory.GetDatabaseContext(); + + var organizationUser = databaseContext.OrganizationUsers.FirstOrDefault(g => g.Id.ToString() == organizationUserId); + Assert.Equal(OrganizationUserStatusType.Revoked, organizationUser.Status); + } + + [Fact] + public async Task Patch_ReplaceRestore_Success() + { + var organizationUserId = ScimApplicationFactory.TestOrganizationUserId3; + var inputModel = new ScimPatchModel + { + Operations = new List() + { + new ScimPatchModel.OperationModel { Op = "replace", Value = JsonDocument.Parse("{\"active\":true}").RootElement }, + }, + Schemas = new List() + }; + + var context = await _factory.UsersPatchAsync(ScimApplicationFactory.TestOrganizationId1, organizationUserId, inputModel); + + Assert.Equal(StatusCodes.Status204NoContent, context.Response.StatusCode); + + var databaseContext = _factory.GetDatabaseContext(); + + var organizationUser = databaseContext.OrganizationUsers.FirstOrDefault(g => g.Id.ToString() == organizationUserId); + Assert.NotEqual(OrganizationUserStatusType.Revoked, organizationUser.Status); + } + + [Fact] + public async Task Patch_NotFound() + { + var organizationUserId = Guid.NewGuid().ToString(); + var inputModel = new Models.ScimPatchModel + { + Operations = new List(), + Schemas = new List() + }; + var expectedResponse = new ScimErrorResponseModel + { + Status = StatusCodes.Status404NotFound, + Detail = "User not found.", + Schemas = new List { ScimConstants.Scim2SchemaError } + }; + + var context = await _factory.UsersPatchAsync(ScimApplicationFactory.TestOrganizationId1, organizationUserId, inputModel); + + Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + } + + [Fact] + public async Task Delete_Success() + { + var organizationUserId = ScimApplicationFactory.TestOrganizationUserId1; + var inputModel = new ScimUserRequestModel(); + + var context = await _factory.UsersDeleteAsync(ScimApplicationFactory.TestOrganizationId1, organizationUserId, inputModel); + + Assert.Equal(StatusCodes.Status204NoContent, context.Response.StatusCode); + + var databaseContext = _factory.GetDatabaseContext(); + Assert.Equal(_initialUserCount - 1, databaseContext.OrganizationUsers.Count()); + Assert.False(databaseContext.OrganizationUsers.Any(g => g.Id.ToString() == organizationUserId)); + } + + [Fact] + public async Task Delete_NotFound() + { + var organizationUserId = Guid.NewGuid().ToString(); + var inputModel = new ScimUserRequestModel(); + var expectedResponse = new ScimErrorResponseModel + { + Status = StatusCodes.Status404NotFound, + Detail = "User not found.", + Schemas = new List { ScimConstants.Scim2SchemaError } + }; + + var context = await _factory.UsersDeleteAsync(ScimApplicationFactory.TestOrganizationId1, organizationUserId, inputModel); + + Assert.Equal(StatusCodes.Status404NotFound, context.Response.StatusCode); + + var responseModel = JsonSerializer.Deserialize(context.Response.Body, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + AssertHelper.AssertPropertyEqual(expectedResponse, responseModel); + + var databaseContext = _factory.GetDatabaseContext(); + Assert.Equal(_initialUserCount, databaseContext.OrganizationUsers.Count()); + } +} diff --git a/bitwarden_license/test/Scim.IntegrationTest/Factories/ScimApplicationFactory.cs b/bitwarden_license/test/Scim.IntegrationTest/Factories/ScimApplicationFactory.cs new file mode 100644 index 000000000..ade54efdc --- /dev/null +++ b/bitwarden_license/test/Scim.IntegrationTest/Factories/ScimApplicationFactory.cs @@ -0,0 +1,253 @@ +using System.Net.Mime; +using System.Security.Claims; +using System.Text; +using System.Text.Encodings.Web; +using System.Text.Json; +using Bit.Core.Services; +using Bit.Infrastructure.EntityFramework.Repositories; +using Bit.IntegrationTestCommon.Factories; +using Bit.Scim.Models; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.Options; +using Microsoft.Net.Http.Headers; + +namespace Bit.Scim.IntegrationTest.Factories; + +public class ScimApplicationFactory : WebApplicationFactoryBase +{ + public readonly new TestServer Server; + + public const string TestUserId1 = "2e8173db-8e8d-4de1-ac38-91b15c6d8dcb"; + public const string TestUserId2 = "b57846fc-0e94-4c93-9de5-9d0389eeadfb"; + public const string TestUserId3 = "20713eb8-d0c5-4655-b855-1a0f3472ccb5"; + public const string TestUserId4 = "cee613af-d0cb-4db9-ab9d-579bb120fd2a"; + public const string TestGroupId1 = "dcb232e8-761d-4152-a510-be2778d037cb"; + public const string TestGroupId2 = "562e5371-7020-40b6-b092-099ac66dbdf9"; + public const string TestGroupId3 = "362c2782-0f1f-4c86-95dd-edbdf7d6040b"; + public const string TestOrganizationId1 = "fb98e04f-0303-4914-9b37-a983943bf1ca"; + public const string TestOrganizationUserId1 = "5d421196-8c59-485b-8926-2d6d0101e05f"; + public const string TestOrganizationUserId2 = "3a63d520-0d84-4679-b887-13fe2058d53b"; + public const string TestOrganizationUserId3 = "be2f9045-e2b6-4173-ad44-4c69c3ea8140"; + public const string TestOrganizationUserId4 = "1f5689b7-e96e-4840-b0b1-eb3d5b5fd514"; + + public ScimApplicationFactory() + { + WebApplicationFactory webApplicationFactory = WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => + { + services + .AddAuthentication("Test") + .AddScheme("Test", options => { }); + + // Override to bypass SCIM authorization + services.AddAuthorization(config => + { + config.AddPolicy("Scim", policy => + { + policy.RequireAssertion(a => true); + }); + }); + + var mailService = services.First(sd => sd.ServiceType == typeof(IMailService)); + services.Remove(mailService); + services.AddSingleton(); + }); + }); + + Server = webApplicationFactory.Server; + } + + public async Task GroupsGetAsync(string organizationId, string id) + { + return await Server.GetAsync($"/v2/{organizationId}/groups/{id}"); + } + + public async Task GroupsGetListAsync(string organizationId, string filter, int? count, int? startIndex) + { + var queryString = new QueryString("?"); + + if (!string.IsNullOrWhiteSpace(filter)) + { + queryString = queryString.Add("filter", filter); + } + + if (count.HasValue) + { + queryString = queryString.Add("count", count.ToString()); + } + + if (startIndex.HasValue) + { + queryString = queryString.Add("startIndex", startIndex.ToString()); + } + + return await Server.GetAsync($"/v2/{organizationId}/groups", httpContext => httpContext.Request.QueryString = queryString); + } + + public async Task GroupsPostAsync(string organizationId, ScimGroupRequestModel model) + { + return await Server.PostAsync($"/v2/{organizationId}/groups", GetStringContent(model), httpContext => httpContext.Request.Headers.Add(HeaderNames.UserAgent, "Okta")); + } + + public async Task GroupsPutAsync(string organizationId, string id, ScimGroupRequestModel model) + { + return await Server.PutAsync($"/v2/{organizationId}/groups/{id}", GetStringContent(model), httpContext => httpContext.Request.Headers.Add(HeaderNames.UserAgent, "Okta")); + } + + public async Task GroupsPatchAsync(string organizationId, string id, ScimPatchModel model) + { + return await Server.PatchAsync($"/v2/{organizationId}/groups/{id}", GetStringContent(model)); + } + + public async Task GroupsDeleteAsync(string organizationId, string id) + { + return await Server.DeleteAsync($"/v2/{organizationId}/groups/{id}", null); + } + + public async Task UsersGetAsync(string organizationId, string id) + { + return await Server.GetAsync($"/v2/{organizationId}/users/{id}"); + } + + public async Task UsersGetListAsync(string organizationId, string filter, int? count, int? startIndex) + { + var queryString = new QueryString("?"); + + if (!string.IsNullOrWhiteSpace(filter)) + { + queryString = queryString.Add("filter", filter); + } + + if (count.HasValue) + { + queryString = queryString.Add("count", count.ToString()); + } + + if (startIndex.HasValue) + { + queryString = queryString.Add("startIndex", startIndex.ToString()); + } + + return await Server.GetAsync($"/v2/{organizationId}/users", httpContext => httpContext.Request.QueryString = queryString); + } + + public async Task UsersPostAsync(string organizationId, ScimUserRequestModel model) + { + return await Server.PostAsync($"/v2/{organizationId}/users", GetStringContent(model)); + } + + public async Task UsersPutAsync(string organizationId, string id, ScimUserRequestModel model) + { + return await Server.PutAsync($"/v2/{organizationId}/users/{id}", GetStringContent(model)); + } + + public async Task UsersPatchAsync(string organizationId, string id, ScimPatchModel model) + { + return await Server.PatchAsync($"/v2/{organizationId}/users/{id}", GetStringContent(model)); + } + + public async Task UsersDeleteAsync(string organizationId, string id, ScimUserRequestModel model) + { + return await Server.DeleteAsync($"/v2/{organizationId}/users/{id}", GetStringContent(model)); + } + + public void InitializeDbForTests(DatabaseContext databaseContext) + { + databaseContext.Organizations.AddRange(GetSeedingOrganizations()); + databaseContext.Groups.AddRange(GetSeedingGroups()); + databaseContext.Users.AddRange(GetSeedingUsers()); + databaseContext.OrganizationUsers.AddRange(GetSeedingOrganizationUsers()); + databaseContext.GroupUsers.AddRange(GetSeedingGroupUsers()); + databaseContext.SaveChanges(); + } + + public void ReinitializeDbForTests(DatabaseContext databaseContext) + { + databaseContext.Organizations.RemoveRange(databaseContext.Organizations); + databaseContext.Groups.RemoveRange(databaseContext.Groups); + databaseContext.Users.RemoveRange(databaseContext.Users); + databaseContext.OrganizationUsers.RemoveRange(databaseContext.OrganizationUsers); + databaseContext.GroupUsers.RemoveRange(databaseContext.GroupUsers); + databaseContext.SaveChanges(); + InitializeDbForTests(databaseContext); + } + + private List GetSeedingUsers() + { + return new List() + { + new Infrastructure.EntityFramework.Models.User { Id = Guid.Parse(TestUserId1), Name = "Test User 1", ApiKey = "", Email = "user1@example.com", SecurityStamp = "" }, + new Infrastructure.EntityFramework.Models.User { Id = Guid.Parse(TestUserId2), Name = "Test User 2", ApiKey = "", Email = "user2@example.com", SecurityStamp = "" }, + new Infrastructure.EntityFramework.Models.User { Id = Guid.Parse(TestUserId3), Name = "Test User 3", ApiKey = "", Email = "user3@example.com", SecurityStamp = "" }, + new Infrastructure.EntityFramework.Models.User { Id = Guid.Parse(TestUserId4), Name = "Test User 4", ApiKey = "", Email = "user4@example.com", SecurityStamp = "" }, + }; + } + + private List GetSeedingGroups() + { + return new List() + { + new Infrastructure.EntityFramework.Models.Group { Id = Guid.Parse(TestGroupId1), OrganizationId = Guid.Parse(TestOrganizationId1), Name = "Test Group 1", ExternalId = "A" }, + new Infrastructure.EntityFramework.Models.Group { Id = Guid.Parse(TestGroupId2), OrganizationId = Guid.Parse(TestOrganizationId1), Name = "Test Group 2", ExternalId = "B" }, + new Infrastructure.EntityFramework.Models.Group { Id = Guid.Parse(TestGroupId3), OrganizationId = Guid.Parse(TestOrganizationId1), Name = "Test Group 3", ExternalId = "C" } + }; + } + + private List GetSeedingOrganizations() + { + return new List() + { + new Infrastructure.EntityFramework.Models.Organization { Id = Guid.Parse(TestOrganizationId1), Name = "Test Organization 1", UseGroups = true } + }; + } + + private List GetSeedingOrganizationUsers() + { + return new List() + { + new Infrastructure.EntityFramework.Models.OrganizationUser { Id = Guid.Parse(TestOrganizationUserId1), OrganizationId = Guid.Parse(TestOrganizationId1), UserId = Guid.Parse(TestUserId1), Status = Core.Enums.OrganizationUserStatusType.Confirmed, ExternalId = "UA", Email = "user1@example.com" }, + new Infrastructure.EntityFramework.Models.OrganizationUser { Id = Guid.Parse(TestOrganizationUserId2), OrganizationId = Guid.Parse(TestOrganizationId1), UserId = Guid.Parse(TestUserId2), Status = Core.Enums.OrganizationUserStatusType.Confirmed, ExternalId = "UB", Email = "user2@example.com" }, + new Infrastructure.EntityFramework.Models.OrganizationUser { Id = Guid.Parse(TestOrganizationUserId3), OrganizationId = Guid.Parse(TestOrganizationId1), UserId = Guid.Parse(TestUserId3), Status = Core.Enums.OrganizationUserStatusType.Revoked, ExternalId = "UC", Email = "user3@example.com" }, + new Infrastructure.EntityFramework.Models.OrganizationUser { Id = Guid.Parse(TestOrganizationUserId4), OrganizationId = Guid.Parse(TestOrganizationId1), UserId = Guid.Parse(TestUserId4), Status = Core.Enums.OrganizationUserStatusType.Confirmed, ExternalId = "UD", Email = "user4@example.com" }, + }; + } + + private List GetSeedingGroupUsers() + { + return new List() + { + new Infrastructure.EntityFramework.Models.GroupUser { GroupId = Guid.Parse(TestGroupId1), OrganizationUserId = Guid.Parse(TestOrganizationUserId1) }, + new Infrastructure.EntityFramework.Models.GroupUser { GroupId = Guid.Parse(TestGroupId1), OrganizationUserId = Guid.Parse(TestOrganizationUserId4) } + }; + } + + private static StringContent GetStringContent(object obj) => new(JsonSerializer.Serialize(obj), Encoding.Default, MediaTypeNames.Application.Json); + + public class TestAuthHandler : AuthenticationHandler + { + public TestAuthHandler(IOptionsMonitor options, + ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) + : base(options, logger, encoder, clock) + { + } + + protected override Task HandleAuthenticateAsync() + { + var claims = new[] + { + new Claim(ClaimTypes.Name, "Test user"), + new Claim("orgadmin", TestOrganizationId1) + }; + var identity = new ClaimsIdentity(claims, "Test"); + var principal = new ClaimsPrincipal(identity); + var ticket = new AuthenticationTicket(principal, "Test"); + + var result = AuthenticateResult.Success(ticket); + + return Task.FromResult(result); + } + } +} diff --git a/bitwarden_license/test/Scim.IntegrationTest/Scim.IntegrationTest.csproj b/bitwarden_license/test/Scim.IntegrationTest/Scim.IntegrationTest.csproj new file mode 100644 index 000000000..8e54d6270 --- /dev/null +++ b/bitwarden_license/test/Scim.IntegrationTest/Scim.IntegrationTest.csproj @@ -0,0 +1,28 @@ + + + + false + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + diff --git a/bitwarden_license/test/Scim.IntegrationTest/packages.lock.json b/bitwarden_license/test/Scim.IntegrationTest/packages.lock.json new file mode 100644 index 000000000..787f71bdc --- /dev/null +++ b/bitwarden_license/test/Scim.IntegrationTest/packages.lock.json @@ -0,0 +1,3493 @@ +{ + "version": 1, + "dependencies": { + "net6.0": { + "AutoFixture.Xunit2": { + "type": "Direct", + "requested": "[4.17.0, )", + "resolved": "4.17.0", + "contentHash": "lrURL/LhJLPkn2tSPUEW8Wscr5LoV2Mr8A+ikn5gwkofex3o7qWUsBswlLw+KCA7EOpeqwZOldp3k91zDF+48Q==", + "dependencies": { + "AutoFixture": "4.17.0", + "xunit.extensibility.core": "[2.2.0, 3.0.0)" + } + }, + "coverlet.collector": { + "type": "Direct", + "requested": "[3.1.2, )", + "resolved": "3.1.2", + "contentHash": "wuLDIDKD5XMt0A7lE31JPenT7QQwZPFkP5rRpdJeblyXZ9MGLI8rYjvm5fvAKln+2/X+4IxxQDxBtwdrqKNLZw==" + }, + "Microsoft.AspNetCore.Mvc.Testing": { + "type": "Direct", + "requested": "[6.0.5, )", + "resolved": "6.0.5", + "contentHash": "Mcb9c86ALCTfXZ53Wsd+nC6QpPTQilUTcQpNWiAyomPUidY5LyQfTbnp6zOJ22dSRbGiGbIOBJzrviYqe47RpQ==", + "dependencies": { + "Microsoft.AspNetCore.TestHost": "6.0.5", + "Microsoft.Extensions.DependencyModel": "6.0.0", + "Microsoft.Extensions.Hosting": "6.0.1" + } + }, + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[17.1.0, )", + "resolved": "17.1.0", + "contentHash": "MVKvOsHIfrZrvg+8aqOF5dknO/qWrR1sWZjMPQ1N42MKMlL/zQL30FQFZxPeWfmVKWUWAOmAHYsqB5OerTKziw==", + "dependencies": { + "Microsoft.CodeCoverage": "17.1.0", + "Microsoft.TestPlatform.TestHost": "17.1.0" + } + }, + "NSubstitute": { + "type": "Direct", + "requested": "[4.3.0, )", + "resolved": "4.3.0", + "contentHash": "c0nY4GGSe5KidQemTk+CTuDLdv7hLvHHftH6vRbKoYb6bw07wzJ6DdgA0NWrwbW3xjmp/ByEskCsUEWAaMC20g==", + "dependencies": { + "Castle.Core": "4.4.1" + } + }, + "xunit": { + "type": "Direct", + "requested": "[2.4.1, )", + "resolved": "2.4.1", + "contentHash": "XNR3Yz9QTtec16O0aKcO6+baVNpXmOnPUxDkCY97J+8krUYxPvXT1szYYEUdKk4sB8GOI2YbAjRIOm8ZnXRfzQ==", + "dependencies": { + "xunit.analyzers": "0.10.0", + "xunit.assert": "[2.4.1]", + "xunit.core": "[2.4.1]" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[2.4.3, )", + "resolved": "2.4.3", + "contentHash": "kZZSmOmKA8OBlAJaquPXnJJLM9RwQ27H7BMVqfMLUcTi9xHinWGJiWksa3D4NEtz0wZ/nxd2mogObvBgJKCRhQ==" + }, + "AspNetCoreRateLimit": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "FzXAJFgaRjKfnKAVwjEEC7OAGQM5v/I3sQw2tpzmR0yHTCGhUAxZzDuwZiXTk8XLrI6vovzkqKkfKmiDl3nYMg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.1", + "Microsoft.Extensions.Options": "6.0.0", + "Newtonsoft.Json": "13.0.1" + } + }, + "AspNetCoreRateLimit.Redis": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "CsSGy/7SXt6iBOKg0xCvsRjb/ZHshbtr2Of1MHc912L2sLnZqadUrTboyXZC+ZlgEBeJ14GyjPTu8ZyfEhGUnw==", + "dependencies": { + "AspNetCoreRateLimit": "4.0.2", + "StackExchange.Redis": "2.5.43" + } + }, + "AutoFixture": { + "type": "Transitive", + "resolved": "4.17.0", + "contentHash": "efMRCG3Epc4QDELwdmQGf6/caQUleRXPRCnLAq5gLMpTuOTcOQWV12vEJ8qo678Rj97/TjjxHYu/34rGkXdVAA==", + "dependencies": { + "Fare": "[2.1.1, 3.0.0)", + "System.ComponentModel.Annotations": "4.3.0" + } + }, + "AutoFixture.AutoNSubstitute": { + "type": "Transitive", + "resolved": "4.17.0", + "contentHash": "iWsRiDQ7T8s6F4mvYbSvPTq0GDtxJD6D+E1Fu9gVbHUvJiNikC1yIDNTH+3tQF7RK864HH/3R8ETj9m2X8UXvg==", + "dependencies": { + "AutoFixture": "4.17.0", + "NSubstitute": "[2.0.3, 5.0.0)" + } + }, + "AutoMapper": { + "type": "Transitive", + "resolved": "11.0.0", + "contentHash": "+596AnKykYCk9RxXCEF4GYuapSebQtFVvIA1oVG1rrRkCLAC7AkWehJ0brCfYUbdDW3v1H/p0W3hob7JoXGjMw==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "AutoMapper.Extensions.Microsoft.DependencyInjection": { + "type": "Transitive", + "resolved": "11.0.0", + "contentHash": "0asw5WxdCFh2OTi9Gv+oKyH9SzxwYQSnO8TV5Dd0GggovILzJW4UimP26JAcxc3yB5NnC5urooZ1BBs8ElpiBw==", + "dependencies": { + "AutoMapper": "11.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "AWSSDK.Core": { + "type": "Transitive", + "resolved": "3.7.10.11", + "contentHash": "B+M7ggPC0FogATRPQxDXL0eTusCQtXulW4zCuX39yiHV8+u9MEXRytcAw0ZA3zFBYYx6ovl9lklho6OQo1DRRQ==" + }, + "AWSSDK.SimpleEmail": { + "type": "Transitive", + "resolved": "3.7.0.150", + "contentHash": "rc/4ZnISfbgTfqz5/BWqMHBAzk4R09qfe1xkdJf2jXo44Zn2X72W8IiLLweBtmNhL7d8Tcf6UCtOHYkFwxHvug==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "AWSSDK.SQS": { + "type": "Transitive", + "resolved": "3.7.2.47", + "contentHash": "RPTVBsY333n+aIEqw148Envx9OQkE1/jhjlioNXDP6BrA3fAPN9A+2HoA02c0KSp/sazXYWg8w/kDL8FchH8Dw==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.24.0", + "contentHash": "+/qI1j2oU1S4/nvxb2k/wDsol00iGf1AyJX5g3epV7eOpQEP/2xcgh/cxgKMeFgn3U2fmgSiBnQZdkV+l5y0Uw==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Numerics.Vectors": "4.5.0", + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Extensions.AspNetCore.DataProtection.Blobs": { + "type": "Transitive", + "resolved": "1.2.1", + "contentHash": "wxvkC6DeWThBtaPbsWdicp5Ltya4J8JuhxmZJDQkhnXG7oihfu8RqBV6w/X1nMieuIOq1qQaGTvjx7nEHHfxSQ==", + "dependencies": { + "Azure.Core": "1.14.0", + "Azure.Storage.Blobs": "12.8.0", + "Microsoft.AspNetCore.DataProtection": "2.1.0" + } + }, + "Azure.Identity": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "EycyMsb6rD2PK9P0SyibFfEhvWWttdrYhyPF4f41uzdB/44yQlV+2Wehxyg489Rj6gbPvSPgbKq0xsHJBhipZA==", + "dependencies": { + "Azure.Core": "1.24.0", + "Microsoft.Identity.Client": "4.39.0", + "Microsoft.Identity.Client.Extensions.Msal": "2.19.3", + "System.Memory": "4.5.4", + "System.Security.Cryptography.ProtectedData": "4.7.0", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Storage.Blobs": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "50eRjIhY7Q1JN7kT2MSawDKCcwSb7uRZUkz00P/BLjSg47gm2hxUYsnJPyvzCHntYMbOWzrvaVQTwYwXabaR5Q==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Text.Json": "4.7.2" + } + }, + "Azure.Storage.Common": { + "type": "Transitive", + "resolved": "12.10.0", + "contentHash": "vYkHGzUkdZTace/cDPZLG+Mh/EoPqQuGxDIBOau9D+XWoDPmuUFGk325aXplkFE4JFGpSwoytNYzk/qBCaiHqg==", + "dependencies": { + "Azure.Core": "1.22.0", + "System.IO.Hashing": "6.0.0" + } + }, + "Azure.Storage.Queues": { + "type": "Transitive", + "resolved": "12.9.0", + "contentHash": "jDiyHtsCUCrWNvZW7SjJnJb46UhpdgQrWCbL8aWpapDHlq9LvbvxYpfLh4dfKAz09QiTznLMIU3i+md9+7GzqQ==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, + "BitPay.Light": { + "type": "Transitive", + "resolved": "1.0.1907", + "contentHash": "QTTIgXakHrRNQPxNyH7bZ7frm0bI8N6gRDtiqVyKG/QYQ+KfjN70xt0zQ0kO0zf8UBaKuwcV5B7vvpXtzR9ijg==", + "dependencies": { + "Newtonsoft.Json": "12.0.2" + } + }, + "Braintree": { + "type": "Transitive", + "resolved": "5.12.0", + "contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "System.Xml.XPath.XmlDocument": "4.3.0" + } + }, + "Castle.Core": { + "type": "Transitive", + "resolved": "4.4.1", + "contentHash": "zanbjWC0Y05gbx4eGXkzVycOQqVOFVeCjVsDSyuao9P4mtN1w3WxxTo193NGC7j3o2u3AJRswaoC6hEbnGACnQ==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "System.Collections.Specialized": "4.3.0", + "System.ComponentModel": "4.3.0", + "System.ComponentModel.TypeConverter": "4.3.0", + "System.Diagnostics.TraceSource": "4.3.0", + "System.Dynamic.Runtime": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "Dapper": { + "type": "Transitive", + "resolved": "2.0.123", + "contentHash": "RDFF4rBLLmbpi6pwkY7q/M6UXHRJEOerplDGE5jwEkP/JGJnBauAClYavNKJPW1yOTWRPIyfj4is3EaJxQXILQ==" + }, + "Fare": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "HaI8puqA66YU7/9cK4Sgbs1taUTP1Ssa4QT2PIzqJ7GvAbN1QgkjbRsjH+FSbMh1MJdvS0CIwQNLtFT+KF6KpA==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "Fido2": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "S0Bz1vfcKlO4Jase3AWp5XnQ746psf4oGx5kL+D2A10j1SsjoAOAIIpanSwfi0cEepDHgk1bClcOKY5TjOzGdA==", + "dependencies": { + "Fido2.Models": "3.0.1", + "Microsoft.Extensions.Http": "6.0.0", + "NSec.Cryptography": "22.4.0", + "System.Formats.Cbor": "6.0.0", + "System.IdentityModel.Tokens.Jwt": "6.17.0" + } + }, + "Fido2.AspNet": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "5n5shEXD7RFUyTesjUHGDjkpgES7j4KotQo1GwUcS08k+fx+1tl/zCFHJ9RFDuUwO+S681ZILT2PyA67IPYpaA==", + "dependencies": { + "Fido2": "3.0.1", + "Fido2.Models": "3.0.1" + } + }, + "Fido2.Models": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "mgjcuGETuYSCUEaZG+jQeeuuEMkDLc4GDJHBvKDdOz6oSOWp5adPdWP4btZx7Pi+9fu4szN3JIjJmby67MaILw==" + }, + "Handlebars.Net": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "p60QyeBYpZmcZdIXRMqs9XySIBaxJ0lj3+QD0EJVr4ybTigOTCumXMMin5dPwjo9At1UwkDZ3gGwa1lmGjG6DA==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "Humanizer.Core": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "rsYXB7+iUPP8AHgQ8JP2UZI2xK2KhjcdGr9E6zX3CsZaTLCaw8M35vaAJRo1rfxeaZEVMuXeaquLVCkZ7JcZ5Q==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "IdentityModel": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "System.Text.Encodings.Web": "4.7.0" + } + }, + "IdentityModel.AspNetCore.OAuth2Introspection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==", + "dependencies": { + "IdentityModel": "4.0.0" + } + }, + "IdentityServer4": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==", + "dependencies": { + "IdentityModel": "4.4.0", + "IdentityServer4.Storage": "4.1.2", + "Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0", + "Newtonsoft.Json": "12.0.2" + } + }, + "IdentityServer4.AccessTokenValidation": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==", + "dependencies": { + "IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1", + "Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0" + } + }, + "IdentityServer4.Storage": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==", + "dependencies": { + "IdentityModel": "4.4.0" + } + }, + "Kralizek.AutoFixture.Extensions.MockHttp": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "6zmks7/5mVczazv910N7V2EdiU6B+rY61lwdgVO0o2iZuTI6KI3T+Hgkrjv0eGOKYucq2OMC+gnAc5Ej2ajoTQ==", + "dependencies": { + "AutoFixture": "4.11.0", + "RichardSzalay.MockHttp": "6.0.0" + } + }, + "libsodium": { + "type": "Transitive", + "resolved": "1.0.18.2", + "contentHash": "flArHoVdscSzyV8ZdPV+bqqY2TTFlaN+xZf/vIqsmHI51KVcD/mOdUPaK3n/k/wGKz8dppiktXUqSmf3AXFgig==" + }, + "linq2db": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "6/u1EzQlV25bhN0Ej/I5dLV5Hgxun+ww/TX2VnMBnSVytED2VzQGeFIO/14I624GkfPOtB79x1ooL3F18dAbdw==" + }, + "linq2db.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.11.0", + "contentHash": "mS+L6HyVHP3oJaTuFVZswNmPpTfYleGjDTo2IWBJmYXZpSQ5EPw1DpHzmyLAiQd+93ofy0Ala+9HWzv6/k73ZQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "6.0.5", + "linq2db": "4.4.0" + } + }, + "MailKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "5MTpTqmjqT7HPvYbP3HozRZMth5vSaT0ReN0iM3rAM4CgLI/R1qqtLDDNWGnFFIlcNzeJkZQRJJMkv8cgzWBbA==", + "dependencies": { + "MimeKit": "3.2.0" + } + }, + "Microsoft.AspNetCore.Authentication.JwtBearer": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "joDS3+lD1i9qcdFLWP4D316t3bHpezmTNOzbMIf9ZcRPX4QTuiUutZcQn/kZplf3BiLHqwUChZXxPjCAMKaKAQ==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0" + } + }, + "Microsoft.AspNetCore.Authentication.OpenIdConnect": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0" + } + }, + "Microsoft.AspNetCore.Cryptography.Internal": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "/0FX1OqckMmXAAlsHgBFNymTZuq4nuAOMhiwm6e8CEMi2aOjnMYwiMc7mtvpGTAO0O4C0zwx+iaChxDgvqit2A==" + }, + "Microsoft.AspNetCore.Cryptography.KeyDerivation": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "1Lbwrxg/HRY/nbrkcrB3EUXUYQN8Tkw7Ktgb6/2on2P7ybT5aM59H05gk+OBC8ZTBxwdle9e1tyT3wxEYKw5xw==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "6.0.4" + } + }, + "Microsoft.AspNetCore.DataProtection": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "G+UoMHL0xiyFh30wkL7Bv/XL6eugTAKYhLPS53k1/Me1bYRwOOw+8VL/q0ppq3/yMzpHX+MkExaCTDlYl48FgA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "2.1.0", + "Microsoft.AspNetCore.DataProtection.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.1.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0", + "Microsoft.Extensions.Logging.Abstractions": "2.1.0", + "Microsoft.Extensions.Options": "2.1.0", + "Microsoft.Win32.Registry": "4.5.0", + "System.Security.Cryptography.Xml": "4.5.0", + "System.Security.Principal.Windows": "4.5.0" + } + }, + "Microsoft.AspNetCore.DataProtection.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "2+HVDhUqrnV9+EJNEewSy+Gk4hOVPzLPMpFDZI7kuH7NWxtbNkI6A6gT5lO2/kEPMyM8/iLWtohbOwjpC9rHVw==" + }, + "Microsoft.AspNetCore.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "1TQgBfd/NPZLR2o/h6l5Cml2ZCF5hsyV4h9WEwWwAIavrbdTnaNozGGcTOd4AOgQvogMM9UM1ajflm9Cwd0jLQ==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Http.Abstractions": "2.1.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "YTKMi2vHX6P+WHEVpW/DS+eFHnwivCSMklkyamcK1ETtc/4j8H3VR0kgW8XIBqukNxhD8k5wYt22P7PhrWSXjQ==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "Microsoft.Extensions.Configuration.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Html.Abstractions": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "Y4rs5aMEXY8G7wJo5S3EEt6ltqyOTr/qOeZzfn+hw/fuQj5GppGckMY5psGLETo1U9hcT5MmAhaT5xtusM1b5g==", + "dependencies": { + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "vbFDyKsSYBnxl3+RABtN79b0vsTcG66fDY8vD6Nqvu9uLtSej70Q5NcbGlnN6bJpZci5orSdgFTHMhBywivDPg==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Features": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "UmkUePxRjsQW0j5euFFscBwjvTu25b8+qIK/2fI3GvcqQ+mkwgbWNAT8b/Gkoei1m2bTWC07lSdutuRDPPLcJA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.0" + } + }, + "Microsoft.AspNetCore.Razor": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "V54PIyDCFl8COnTp9gezNHpUNHk7F9UnerGeZy3UfbnwYvfzbo+ipqQmSgeoESH8e0JvKhRTyQyZquW2EPtCmg==", + "dependencies": { + "Microsoft.AspNetCore.Html.Abstractions": "2.2.0" + } + }, + "Microsoft.AspNetCore.Razor.Language": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "6yOBBASGfXMx1fY6hyjvG+oM3eR8vovIehDdEZW7jAV4gKlY4xuAvTm7Iw1fEq7KPunh2VrJwo7oRK1XxUn1OQ==" + }, + "Microsoft.AspNetCore.Razor.Runtime": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "7YqK+H61lN6yj9RiQUko7oaOhKtRR9Q/kBcoWNRemhJdTIWOh1OmdvJKzZrMWOlff3BAjejkPQm+0V0qXk+B1w==", + "dependencies": { + "Microsoft.AspNetCore.Html.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Razor": "2.2.0" + } + }, + "Microsoft.AspNetCore.TestHost": { + "type": "Transitive", + "resolved": "6.0.5", + "contentHash": "Q8LYosH/nGhIPIRFD60sxOfreUu7xOtKSuxoLN8+vTv6IGrE5Vf7+SRMumgWOCl3ZiZXJDmkjtmevurS1D1QBA==", + "dependencies": { + "System.IO.Pipelines": "6.0.3" + } + }, + "Microsoft.Azure.Amqp": { + "type": "Transitive", + "resolved": "2.4.11", + "contentHash": "7x5fu2f6TLQDDJS0sY5qW8/daFwJaY9O75YvU8RcUfRzbug+9YGjXUBxoRrprgyi0jxdBAMQL05p1s783SOSFQ==", + "dependencies": { + "System.Net.WebSockets.Client": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.Azure.Cosmos": { + "type": "Transitive", + "resolved": "3.24.0", + "contentHash": "QpUe5ho6OzlXwgcJVgAmOR7t3XLC9RI4t8T96RZY61pSOIllPOJdp30L0LwA16tKcqi5r2KayEgWO/MS9fh/6A==", + "dependencies": { + "Azure.Core": "1.3.0", + "Microsoft.Bcl.AsyncInterfaces": "1.0.0", + "Microsoft.Bcl.HashCode": "1.1.0", + "Newtonsoft.Json": "10.0.2", + "System.Buffers": "4.5.1", + "System.Collections.Immutable": "1.7.0", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Memory": "4.5.4", + "System.Numerics.Vectors": "4.5.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3", + "System.Threading.Tasks.Extensions": "4.5.4", + "System.ValueTuple": "4.5.0" + } + }, + "Microsoft.Azure.Cosmos.Table": { + "type": "Transitive", + "resolved": "1.0.8", + "contentHash": "ToeEd1yijM7nQfLYvdFLG//RjKPmfqm45eOm86UAKrxtyGI/CXqP8iL74mzBp6mZ9A/K/ZYA2fVdpH0xHR5Keg==", + "dependencies": { + "Microsoft.Azure.DocumentDB.Core": "2.11.2", + "Microsoft.OData.Core": "7.6.4", + "Newtonsoft.Json": "10.0.2" + } + }, + "Microsoft.Azure.DocumentDB.Core": { + "type": "Transitive", + "resolved": "2.11.2", + "contentHash": "cA8eWrTFbYrkHrz095x4CUGb7wqQgA1slzFZCYexhNwz6Zcn3v+S1yvWMGwGRmRjT0MKU9tYdFWgLfT0OjSycw==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "Newtonsoft.Json": "9.0.1", + "System.Collections.Immutable": "1.3.0", + "System.Collections.NonGeneric": "4.0.1", + "System.Collections.Specialized": "4.0.1", + "System.Diagnostics.TraceSource": "4.0.0", + "System.Dynamic.Runtime": "4.0.11", + "System.Linq.Queryable": "4.0.1", + "System.Net.Http": "4.3.4", + "System.Net.NameResolution": "4.0.0", + "System.Net.NetworkInformation": "4.1.0", + "System.Net.Requests": "4.0.11", + "System.Net.Security": "4.3.2", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Security.SecureString": "4.0.0" + } + }, + "Microsoft.Azure.NotificationHubs": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "C2SssjX3e6/HIo1OCImQDDVOn64d1+gkgEmgxJryzkwixyivJHWH2YIgxZs33pyzVQcZWx5PR2tqLkQ7riSq8Q==", + "dependencies": { + "Microsoft.Extensions.Caching.Memory": "3.1.8", + "Newtonsoft.Json": "12.0.3" + } + }, + "Microsoft.Azure.ServiceBus": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "wyZNJggyFNtKxd+HgvcTiuRYuTjDGi+pgE4RcBvFbfvNiarKr5AOlE4Ne7on1eUJZuMuEa19wN5dj694HlP60A==", + "dependencies": { + "Microsoft.Azure.Amqp": "2.4.11", + "Microsoft.Azure.Services.AppAuthentication": "[1.0.3, 2.0.0)", + "Newtonsoft.Json": "10.0.3", + "System.Diagnostics.DiagnosticSource": "4.5.1", + "System.IdentityModel.Tokens.Jwt": "5.4.0" + } + }, + "Microsoft.Azure.Services.AppAuthentication": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "ywpQaK1klu1IoX4VUf+TBmU4kR71aWNI6O5rEIJU8z28L2xhJhnIm7k2Nf1Zu/PygeuOtt5g0QPCk5+lLltbeQ==", + "dependencies": { + "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.14.2", + "NETStandard.Library": "1.6.1", + "System.Diagnostics.Process": "4.3.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "yuvf07qFWFqtK3P/MRkEKLhn5r2UbSpVueRziSqj0yJQIKFwG1pq9mOayK3zE5qZCTs0CbrwL9M6R8VwqyGy2w==" + }, + "Microsoft.Bcl.HashCode": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "J2G1k+u5unBV+aYcwxo94ip16Rkp65pgWFb0R6zwJipzWNMgvqlWeuI7/+R+e8bob66LnSG+llLJ+z8wI94cHg==" + }, + "Microsoft.CodeAnalysis.Analyzers": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "ojG5pGAhTPmjxRGTNvuszO3H8XPZqksDwr9xLd4Ae/JBjZZdl6GuoLk7uLMf+o7yl5wO0TAqoWcEKkEWqrZE5g==" + }, + "Microsoft.CodeAnalysis.Common": { + "type": "Transitive", + "resolved": "3.8.0", + "contentHash": "8YTZ7GpsbTdC08DITx7/kwV0k4SC6cbBAFqc13cOm5vKJZcEIAh51tNSyGSkWisMgYCr96B2wb5Zri1bsla3+g==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.0.0", + "System.Collections.Immutable": "5.0.0", + "System.Memory": "4.5.4", + "System.Reflection.Metadata": "5.0.0", + "System.Runtime.CompilerServices.Unsafe": "4.7.1", + "System.Text.Encoding.CodePages": "4.5.1", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Microsoft.CodeAnalysis.CSharp": { + "type": "Transitive", + "resolved": "3.8.0", + "contentHash": "hKqFCUSk9TIMBDjiYMF8/ZfK9p9mzpU+slM73CaCHu4ctfkoqJGHLQhyT8wvrYsIg+ufrUWBF8hcJYmyr5rc5Q==", + "dependencies": { + "Microsoft.CodeAnalysis.Common": "[3.8.0]" + } + }, + "Microsoft.CodeAnalysis.CSharp.Workspaces": { + "type": "Transitive", + "resolved": "3.8.0", + "contentHash": "rdEBvPWqe/IIscsnp7OkZ4tQin8khxBcSLyV9tU+sHdw9uW9U0GKL+Dv2rD4voC1bZBaO18Hp+m4Vkyfmaz0OA==", + "dependencies": { + "Humanizer.Core": "2.2.0", + "Microsoft.CodeAnalysis.CSharp": "[3.8.0]", + "Microsoft.CodeAnalysis.Common": "[3.8.0]", + "Microsoft.CodeAnalysis.Workspaces.Common": "[3.8.0]" + } + }, + "Microsoft.CodeAnalysis.Razor": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "s4u/6z/MQ35y/egrXf4WgJlUZf5GGvuba9mZ700dH4XxLBrA9Fw9kFZ8uymoATry7hwz5owvFhBVo+2VnoiGRg==", + "dependencies": { + "Microsoft.AspNetCore.Razor.Language": "5.0.0", + "Microsoft.CodeAnalysis.CSharp": "3.7.0", + "Microsoft.CodeAnalysis.Common": "3.7.0" + } + }, + "Microsoft.CodeAnalysis.Workspaces.Common": { + "type": "Transitive", + "resolved": "3.8.0", + "contentHash": "GPYVydsmOmScOWDJA1LFky7/MkoXpx1JI3lZJShxC+bvVUvL9zVKE8WDZMLsYJ5MAbry2xkZftdfeMpZ+kvLDQ==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "Microsoft.CodeAnalysis.Common": "[3.8.0]", + "System.Composition": "1.0.31" + } + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "0N/ZJ71ncCxQWhgtkEYKOgu2oMHa8h1tsOUbhmIKXF8UwtSUCe4vHAsJ3DVcNWRwNfQzSTy263ZE+QF6MdIhhQ==" + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, + "Microsoft.Data.SqlClient": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "uu8dfrsx081cSbEevWuZAvqdmANDGJkbLBL2G3j0LAZxX1Oy8RCVAaC4Lcuak6jNicWP6CWvHqBTIEmQNSxQlw==", + "dependencies": { + "Azure.Identity": "1.6.0", + "Microsoft.Data.SqlClient.SNI.runtime": "5.0.1", + "Microsoft.Identity.Client": "4.45.0", + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.21.0", + "Microsoft.SqlServer.Server": "1.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Buffers": "4.5.1", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Diagnostics.DiagnosticSource": "5.0.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime.Caching": "5.0.0", + "System.Security.Cryptography.Cng": "5.0.0", + "System.Security.Principal.Windows": "5.0.0", + "System.Text.Encoding.CodePages": "5.0.0", + "System.Text.Encodings.Web": "4.7.2" + } + }, + "Microsoft.Data.SqlClient.SNI.runtime": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "y0X5MxiNdbITJYoafJ2ruaX6hqO0twpCGR/ipiDOe85JKLU8WL4TuAQfDe5qtt3bND5Je26HnrarLSAMMnVTNg==" + }, + "Microsoft.Data.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bui5wPPqq9OwTL5A+YJPcVStTPrOFcLwg/kAVWyqdjrTief4kTK/3bNv0MqUDVNgAUG8pcFbtdc674CIh1F3gw==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "xb10XFoPf/gWu8ik5v7xnVyUY7W21LBOLtT7PidzwYVdnE3aKuQ/bIZLcQuY7rdDNT89/wse2q5FRjm207cIMQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Analyzers": "6.0.12", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.DependencyInjection": "6.0.1", + "Microsoft.Extensions.Logging": "6.0.0", + "System.Collections.Immutable": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Abstractions": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "hvRytAcLhrb35HmtMjYWsNZZLt39ryuN7j04lDchRa9VToreyqgo5gMniTdQ6MfCflxtGnDes65V/Y2pjbEyWg==" + }, + "Microsoft.EntityFrameworkCore.Analyzers": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "ZDUY+KlsIyKdfvIJeNdqRiPExFQ5GRZVdx/Cp52vhpCJRImYv34O0Xfmw2eiLu4qe1jmM2pTzAAFKELaKwtj/w==" + }, + "Microsoft.EntityFrameworkCore.InMemory": { + "type": "Transitive", + "resolved": "6.0.5", + "contentHash": "EkN5W28f18acApSn7uxglOXI6h98s7ahlh0T4+0TJ+dahO1dqhO1VwNXcjkfwxq1Oz1FZdR9HD0fAWTQjWU1Kw==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.5" + } + }, + "Microsoft.EntityFrameworkCore.Relational": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "HBtRGHtF0Vf+BIQTkRGiopmE5rLYhj59xPpd17S1tLgYpiHDVbepCuHwh5H63fzjO99Z4tW5wmmEGF7KnD91WQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "2Hutlqt07bnWZFtYqT1lj0otX8ygMyBikysGnfQNF2TK3i5GqSTeJ8tqNi/URiI9II7Cyl15A0rflXmFoySuIw==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Sqlite.Core": "6.0.12", + "SQLitePCLRaw.bundle_e_sqlite3": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "07vKE7+t9Z2BfGmHuJwNZNv8m1GWt7ZpYYHFh1tQg1oC6FJ78bSaFzLawsf2NK6CLhbB8DBsjE0rRhxMJ4rXsA==", + "dependencies": { + "Microsoft.Data.Sqlite.Core": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Microsoft.Extensions.DependencyModel": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bcz5sSFJbganH0+YrfvIjJDIcKNW7TL07C4d1eTmXy/wOt52iz4LVogJb6pazs7W0+74j0YpXFErvp++Aq5Bsw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.Memory": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "B4y+Cev05eMcjf1na0v9gza6GUtahXbtY1JCypIgx3B4Ea/KAgsWyXEmW4q6zMbmTMtKzmPVk09rvFJirvMwTg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.StackExchangeRedis": { + "type": "Transitive", + "resolved": "6.0.6", + "contentHash": "bdVQpYm1hcHf0pyAypMjtDw3HjWQJ89UzloyyF1OBs56QlgA1naM498tP2Vjlho5vVRALMGPYzdRKCen8koubw==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "StackExchange.Redis": "2.2.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "BUyFU9t+HzlSE7ri4B+AQN2BgTgHv/uM82s5ZkgU1BApyzWzIl48nDsG5wR1t0pniNuuyTBzG3qCW8152/NtSw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "b3ErKzND8LIC7o08QAVlKfaEIYEvLJbtmVbFZVBRXeu9YkKfSSzLZfR1SUfQPBIy9mKLhEtJgGYImkcMNaKE0A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.CommandLine": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "3nL1qCkZ1Oxx14ZTzgo4MmlO7tso7F+TtMZAY2jUAtTLyAcDp+EDjk3RqafoKiNaePyPvvlleEcBxh3b2Hzl1g==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "pnyXV1LFOsYjGveuC07xp0YHIyGq7jRq5Ncb5zrrIieMLWVwgMyYxcOH0jTnBedDT4Gh1QinSqsjqzcieHk1og==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "V4Dth2cYMZpw3HhGw9XUDIijpI6gN+22LDt0AhufIgOppCUfpWX4483OmN+dFXRJkJLc8Tv0Q8QK+1ingT2+KQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GJGery6QytCzS/BxJ96klgG9in3uH26KcUBbiVG/coNDXCRq6LGVVlUT4vXq34KPuM+R2av+LeYdX9h4IZOCUg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "Fy8yr4V6obi7ZxvKYI1i85jqtwMq8tqyxQVZpRSkgeA8enqy/KvBIMdcuNdznlxQMZa72mvbHqb7vbg4Pyx95w==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "vWXPg3HJQIpZkENn1KWq8SfbqVujVD7S7vIAyFXXqK5xkf1Vho+vG0bLBCHxU36lD1cLLtmGpfYf0B3MYFi9tQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.DependencyModel": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "TD5QHg98m3+QhgEV1YVoNMl5KtBw/4rjfxLHO0e/YV9bPUBDKntApP4xdrVtGgCeQZHVfC2EXIGsdpRNrr87Pg==", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" + }, + "Microsoft.Extensions.Hosting": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "hbmizc9KPWOacLU8Z8YMaBG6KWdZFppczYV/KwnPGU/8xebWxQxdDeJmLOgg968prb7g2oQgnp6JVLX6lgby8g==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Binder": "6.0.0", + "Microsoft.Extensions.Configuration.CommandLine": "6.0.0", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.Configuration.UserSecrets": "6.0.1", + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Hosting.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Configuration": "6.0.0", + "Microsoft.Extensions.Logging.Console": "6.0.0", + "Microsoft.Extensions.Logging.Debug": "6.0.0", + "Microsoft.Extensions.Logging.EventLog": "6.0.0", + "Microsoft.Extensions.Logging.EventSource": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "15+pa2G0bAMHbHewaQIdr/y6ag2H3yh4rd9hTXavtWDzQBkvpe2RMqFg8BxDpcQWssmjmBApGPcw93QRz6YcMg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Core": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "8vBsyGkA8ZI3lZvm1nf+9ynRC/TzPD+UtbdgTlKk+cz+AW5I41LrK8f/adGej5uXgprOA2DMjZw33vZG6vyXxA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Stores": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "linRCnWBfnqg8qjrd9u/KMISy8O4a6X/GRhpHXU0ar654YQw9LJ/Ht+psx8QLqSX5EsCBbBCZzuamatH2FWIyQ==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Identity.Core": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + }, + "Microsoft.Extensions.Logging.Configuration": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ZDskjagmBAbv+K8rYW9VhjPplhbOE63xUD0DiuydZJwt15dRyoqicYklLd86zzeintUc7AptDkHn+YhhYkYo8A==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Binder": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Console": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "gsqKzOEdsvq28QiXFxagmn1oRB9GeI5GgYCkoybZtQA0IUb7QPwf1WmN3AwJeNIsadTvIFQCiVK0OVIgKfOBGg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Configuration": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Debug": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "M9g/JixseSZATJE9tcMn9uzoD4+DbSglivFqVx8YkRJ7VVPmnvCEbOZ0AAaxsL1EKyI4cz07DXOOJExxNsUOHw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.EventLog": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rlo0RxlMd0WtLG3CHI0qOTp6fFn7MvQjlrCjucA31RqmiMFCZkF8CHNbe8O7tbBIyyoLGWB1he9CbaA5iyHthg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.EventLog": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.EventSource": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "BeDyyqt7nkm/nr+Gdk+L8n1tUT/u33VkbXAOesgYSNsxDM9hJ1NOBGoZfj9rCbeD2+9myElI6JOVVFmnzgeWQA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bXWINbTn0vC0FYc9GaQTISbxhQLAMrvtbuvD9N6JelEaIS/Pr62wUCinrq5bf1WRBGczt1v4wDhxFtVFNcMdUQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Binder": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Identity.Client": { + "type": "Transitive", + "resolved": "4.45.0", + "contentHash": "ircobISCLWbtE5eEoLKU+ldfZ8O41vg4lcy38KRj/znH17jvBiAl8oxcyNp89CsuqE3onxIpn21Ca7riyDDrRw==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.18.0" + } + }, + "Microsoft.Identity.Client.Extensions.Msal": { + "type": "Transitive", + "resolved": "2.19.3", + "contentHash": "zVVZjn8aW7W79rC1crioDgdOwaFTQorsSO6RgVlDDjc7MvbEGz071wSNrjVhzR0CdQn6Sefx7Abf1o7vasmrLg==", + "dependencies": { + "Microsoft.Identity.Client": "4.38.0", + "System.Security.Cryptography.ProtectedData": "4.5.0" + } + }, + "Microsoft.IdentityModel.Abstractions": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "XeE6LQtD719Qs2IG7HDi1TSw9LIkDbJ33xFiOBoHbApVw/8GpIBCbW+t7RwOjErUDyXZvjhZliwRkkLb8Z1uzg==" + }, + "Microsoft.IdentityModel.Clients.ActiveDirectory": { + "type": "Transitive", + "resolved": "3.14.2", + "contentHash": "TNsJJMiRnkeby1ovThVoV9yFsPWjAdluwOA+Nf0LtSsBVVrKQv8Qp4kYOgyNwMVj+pDwbhXISySk+4HyHVWNZQ==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "System.Runtime.Serialization.Json": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.IdentityModel.JsonWebTokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "d3h1/BaMeylKTkdP6XwRCxuOoDJZ44V9xaXr6gl5QxmpnZGdoK3bySo3OQN8ehRLJHShb94ElLUvoXyglQtgAw==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "tuEhHIQwvBEhMf8I50hy8FHmRSUkffDFP5EdLsSDV4qRcl2wvOPkQxYqEzWkh+ytW6sbdJGEXElGhmhDfAxAKg==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "0FqY5cTLQKtHrClzHEI+QxJl8OBT2vUiEQQB7UKk832JDiJJmetzYZ3AdSrPjN/3l3nkhByeWzXnhrX0JbifKg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "vtSKL7n6EnAsLyxmiviusm6LKrblT2ndnNqN6rvVq6iIHAnPCK9E2DkDx6h1Jrpy1cvbp40r0cnTg23nhEAGTA==", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "6.21.0", + "System.IdentityModel.Tokens.Jwt": "6.21.0" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "AAEHZvZyb597a+QJSmtxH3n2P1nIJGpZ4Q89GTenknRx6T6zyfzf592yW/jA5e8EHN4tNMjjXHQaYWEq5+L05w==", + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "Microsoft.IdentityModel.Logging": "6.21.0", + "System.Security.Cryptography.Cng": "4.5.0" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.OData.Core": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "/EjnJezMBjXf8OjcShhGzPY7pOO0CopgoZGhS6xsP3t2uhC+O72IBHgtQ7F3v1rRXWVtJwLGhzE1GfJUlx3c4Q==", + "dependencies": { + "Microsoft.OData.Edm": "[7.6.4]", + "Microsoft.Spatial": "[7.6.4]" + } + }, + "Microsoft.OData.Edm": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "MSSmA6kIfpgFTtNpOnnayoSj/6KSzHC1U9KOjF7cTA1PG4tZ7rIMi1pvjFc8CmYEvP4cxGl/+vrCn+HpK26HTQ==" + }, + "Microsoft.OpenApi": { + "type": "Transitive", + "resolved": "1.2.3", + "contentHash": "Nug3rO+7Kl5/SBAadzSMAVgqDlfGjJZ0GenQrLywJ84XGKO0uRqkunz5Wyl0SDwcR71bAATXvSdbdzPrYRYKGw==" + }, + "Microsoft.Spatial": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "3mB+Frn4LU4yb5ie9R752QiRn0Hvp9PITkSRofV/Lzm9EyLM87Fy9ziqgz75O/c712dh6GxuypMSBUGmNFwMeA==" + }, + "Microsoft.SqlServer.Server": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug==" + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "OMo/FYnKGy3lZEK0gfitskRM3ga/YBt6MyCyFPq0xNLeybGOQ6HnYNAAvzyePo5WPuMiw3LX+HiuRWNjnas1fA==", + "dependencies": { + "NuGet.Frameworks": "5.11.0", + "System.Reflection.Metadata": "1.6.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "JS0JDLniDhIzkSPLHz7N/x1CG8ywJOtwInFDYA3KQvbz+ojGoT5MT2YDVReL1b86zmNRV8339vsTSm/zh0RcMg==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.1.0", + "Newtonsoft.Json": "9.0.1" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "YUah81QG5q/ViVbr1BZcTbDLNJ5/k84fr+xx3/IoDVJR8KEUm89HmPAGM+FMMyWOjit+CIVpyOq7yEmRBBWXxQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore": "5.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Contracts": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "34v6AkkRJykgFq7rHwNbzXBsLFquevLuegM9XDQl2j+wyOfj+ql1++jUR1WdZoPkv04WoM09mD47S3lMzJmHrQ==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "System.Collections.Immutable": "1.7.0" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Core": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "R7mrxvTtv/MiEH42OtHYi/3L0A/vaAH8mwg+3yAyQtVuy6v9CeeVyL30lfTQ7EYV4ezUmuQKFwfjcU6PP0/KSQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.VisualStudio.Web.CodeGeneration.Templating": "5.0.2", + "Newtonsoft.Json": "11.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Design": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "9eTZV7W+S2iO2AJD03xXyXJZ+Nf71Y25gMXhqyXb8bB63jPfn+VQhV8I1lb6J+NR3jW98m5EB9QBftBSrjgiYQ==", + "dependencies": { + "Microsoft.VisualStudio.Web.CodeGenerators.Mvc": "5.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "f9XeBRS9ICosrCpbO9jnAVMd/ISLhaZgx388XNBjigiyBJuq577J6tQgQWZA8PQTiPj6MKe9HVIW2GnKXDiUrQ==", + "dependencies": { + "Microsoft.VisualStudio.Web.CodeGeneration.Core": "5.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Templating": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "P3z/JZTGP5DhSc8ik4xrimWuCZ2ZaEZ6q7WGgfgmSVibfXxwh2Oo+dtdkiXwq8MNlkrcP0AZAo3+1wowYUzluA==", + "dependencies": { + "Microsoft.AspNetCore.Razor.Language": "5.0.0", + "Microsoft.AspNetCore.Razor.Runtime": "2.2.0", + "Microsoft.CodeAnalysis.CSharp": "3.8.0", + "Microsoft.CodeAnalysis.Razor": "5.0.0", + "Microsoft.VisualStudio.Web.CodeGeneration.Utils": "5.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Utils": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "4zViWGIFeKsGxDmc5xpn2G8kWs2FSHiLOolw85ZPHihDXc2jiFKp7qjA3SRt8U23kR3zeb0vZiFlETxgTHwAUA==", + "dependencies": { + "Microsoft.CodeAnalysis.CSharp.Workspaces": "3.8.0", + "Microsoft.VisualStudio.Web.CodeGeneration.Contracts": "5.0.2", + "Newtonsoft.Json": "11.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGenerators.Mvc": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "W4Uk2y0oja+4E+XP5d5OFu+ViTEtlqm3a6nYuuC3tjA+lTK6dLaMf0G6WnO4BO18i0kM0l49XjTwwXd5XpjnAQ==", + "dependencies": { + "Microsoft.VisualStudio.Web.CodeGeneration": "5.0.2" + } + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "Microsoft.Win32.Registry": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "Microsoft.Win32.SystemEvents": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==" + }, + "MimeKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "l9YHMBhBUwY7qQHUp8fw0EvjcbmhN4Iggz6MdjqIShBf42+0nJTa5gu0kuupCOPuiARc9ZaS9c9f0gKz4OnxKw==", + "dependencies": { + "Portable.BouncyCastle": "1.9.0", + "System.Security.Cryptography.Pkcs": "6.0.0" + } + }, + "MySqlConnector": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "JVokQTUNN3WHAu9Vw8ieeq1dXTFokJiig5P0VJ4f439UxRrsPo6SaVWC8Zdm6mkPeQFhZ0/9afdWa02EY/1j/w==" + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "Npgsql": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "wKa8MJEJaj0xQXUQZGv7q/KfPID23jSSvFFtljMworrv7dNajr0GN8PCU1SpywqHjMWdYEfK29DY1aYbiISbQg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Npgsql.EntityFrameworkCore.PostgreSQL": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "YJRpO+3wXQyWuwRUCVJj/Rsn46sY0bZ6uCGOEFApiRe0ZYJ6N6TxZUWKbTNJYjesickcLGzynOerpSbDJX1AYg==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Npgsql": "6.0.8" + } + }, + "NSec.Cryptography": { + "type": "Transitive", + "resolved": "22.4.0", + "contentHash": "lEntcPYd7h3aZ8xxi/y/4TML7o8w0GEGqd+w4L1omqFLbdCBmhxJAeO2YBmv/fXbJKgKCQLm7+TD4bR605PEUQ==", + "dependencies": { + "libsodium": "[1.0.18.2, 1.0.19)" + } + }, + "NuGet.Frameworks": { + "type": "Transitive", + "resolved": "5.11.0", + "contentHash": "eaiXkUjC4NPcquGWzAGMXjuxvLwc6XGKMptSyOGQeT0X70BUZObuybJFZLA0OfTdueLd3US23NBPTBb6iF3V1Q==" + }, + "Otp.NET": { + "type": "Transitive", + "resolved": "1.2.2", + "contentHash": "2hrZfkbzeWJ3tNXXt/1beg4IY+nS4F3gIfh4NVFvW0f6Pj51hGpiJ4prBz7Dmrr4ZYrA96rTERVGieZ4xYm7jA==" + }, + "Pipelines.Sockets.Unofficial": { + "type": "Transitive", + "resolved": "2.2.2", + "contentHash": "Bhk0FWxH1paI+18zr1g5cTL+ebeuDcBCR+rRFO+fKEhretgjs7MF2Mc1P64FGLecWp4zKCUOPzngBNrqVyY7Zg==", + "dependencies": { + "System.IO.Pipelines": "5.0.1" + } + }, + "Pomelo.EntityFrameworkCore.MySql": { + "type": "Transitive", + "resolved": "6.0.2", + "contentHash": "KvlZ800CnEuEGnxj5OT1fCKGjQXxW5kpPlCP91JqBYG+2Z3927eqXmlX6LLKUt4swqE8ZsEQ+Zkpab8bqstf4g==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "[6.0.7, 7.0.0)", + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "MySqlConnector": "2.1.2" + } + }, + "Portable.BouncyCastle": { + "type": "Transitive", + "resolved": "1.9.0", + "contentHash": "eZZBCABzVOek+id9Xy04HhmgykF0wZg9wpByzrWN7q8qEI0Qen9b7tfd7w8VA3dOeesumMG7C5ZPy0jk7PSRHw==" + }, + "Quartz": { + "type": "Transitive", + "resolved": "3.4.0", + "contentHash": "N8350OAlQhd8zKg0ARFikGjh3bfAW/CF/KVxu2fTIlAALB/oC1eg54n/QAPYR5ryHuYyDr5G8/Qa4k+D/7OFRQ==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "RichardSzalay.MockHttp": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bStGNqIX/MGYtML7K3EzdsE/k5HGVAcg7XgN23TQXGXqxNC9fvYFR94fA0sGM5hAT36R+BBGet6ZDQxXL/IPxg==" + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" + }, + "SendGrid": { + "type": "Transitive", + "resolved": "9.27.0", + "contentHash": "kMyXRQ8hmN2bG3tYZ7T31Ufl1kXkpuP5+WBh1BJ32WY31DTnBTCVGURoIqfbTo/tRuQfAYLxra6C8cQGN6kk+A==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "starkbank-ecdsa": "[1.3.3, 2.0.0)" + } + }, + "Sentry": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "Pkw4+51EDUQ0X02jdCZIpaM2Q4UO06VKGDE+dYYNxgvOirRXGKTKxRk4NPKJTLSTNl+2JyT9HoE7C6BTlYhLOw==" + }, + "Sentry.Serilog": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "GFTVfQdOFqZ9Vmo8EEZTx1EQMDRJjka/4v2CwxnAUh+sqHDICga4eOm4AyGzDBbE4s9iAHMgMUCceIqo+7z84w==", + "dependencies": { + "Sentry": "3.16.0", + "Serilog": "2.10.0" + } + }, + "Serilog": { + "type": "Transitive", + "resolved": "2.10.0", + "contentHash": "+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA==" + }, + "Serilog.AspNetCore": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "/JO/txIxRR61x1UXQAgUzG2Sx05o1QHCkokVBWrKzmAoDu+p5EtCAj7L/TVVg7Ezhh3GPiZ0JI9OJCmRO9tSRw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.Extensions.Logging": "5.0.0", + "Serilog": "2.10.0", + "Serilog.Extensions.Hosting": "4.2.0", + "Serilog.Formatting.Compact": "1.1.0", + "Serilog.Settings.Configuration": "3.3.0", + "Serilog.Sinks.Console": "4.0.1", + "Serilog.Sinks.Debug": "2.0.0", + "Serilog.Sinks.File": "5.0.0" + } + }, + "Serilog.Extensions.Hosting": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "gT2keceCmPQR9EX0VpXQZvUgELdfE7yqJ7MOxBhm3WLCblcvRgswEOOTgok/DHObbM15A3V/DtF3VdVDQPIZzQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.Hosting.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8", + "Serilog": "2.10.0", + "Serilog.Extensions.Logging": "3.1.0" + } + }, + "Serilog.Extensions.Logging": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "IWfem7wfrFbB3iw1OikqPFNPEzfayvDuN4WP7Ue1AVFskalMByeWk3QbtUXQR34SBkv1EbZ3AySHda/ErDgpcg==", + "dependencies": { + "Microsoft.Extensions.Logging": "2.0.0", + "Serilog": "2.9.0" + } + }, + "Serilog.Extensions.Logging.File": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "usO0qr4v9VCMBWiTJ1nQmAbPNCt40FrkDol6CpfCXbsxGZS/hH+YCueF7vvPQ32ATI0GWcMWiKRdjXEE7/HxTQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Serilog": "2.5.0", + "Serilog.Extensions.Logging": "2.0.2", + "Serilog.Formatting.Compact": "1.0.0", + "Serilog.Sinks.Async": "1.1.0", + "Serilog.Sinks.RollingFile": "3.3.0" + } + }, + "Serilog.Formatting.Compact": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "pNroKVjo+rDqlxNG5PXkRLpfSCuDOBY0ri6jp9PLe505ljqwhwZz8ospy2vWhQlFu5GkIesh3FcDs4n7sWZODA==", + "dependencies": { + "Serilog": "2.8.0" + } + }, + "Serilog.Settings.Configuration": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "7GNudISZwqaT902hqEL2OFGTZeUFWfnrNLupJkOqeF41AR3GjcxX+Hwb30xb8gG2/CDXsCMVfF8o0+8KY0fJNg==", + "dependencies": { + "Microsoft.Extensions.DependencyModel": "3.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "2.0.0", + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Async": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "xll0Kanz2BkCxuv+F3p1WXr47jdsVM0GU1n1LZvK+18QiRZ/WGFNxSNw9EMKFV5ED5gr7MUpAe6PCMNL1HGUMA==", + "dependencies": { + "Serilog": "2.1.0", + "System.Collections.Concurrent": "4.0.12" + } + }, + "Serilog.Sinks.AzureCosmosDB": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Im2/ZqjXQIpsd727qEo5Pq+br0MiNVuTvI40Yk7736tgjCpEx+omPHv4+c4fEAxnOP2kL9Ge6UoDFoDw3cjF2A==", + "dependencies": { + "Microsoft.Azure.Cosmos": "3.24.0", + "Microsoft.CSharp": "4.7.0", + "Newtonsoft.Json": "13.0.1", + "Serilog": "2.10.0", + "Serilog.Sinks.PeriodicBatching": "2.3.1" + } + }, + "Serilog.Sinks.Console": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Debug": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y6g3OBJ4JzTyyw16fDqtFcQ41qQAydnEvEqmXjhwhgjsnG/FaJ8GUqF5ldsC/bVkK8KYmqrPhDO+tm4dF6xx4A==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.File": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.PeriodicBatching": { + "type": "Transitive", + "resolved": "2.3.1", + "contentHash": "LVYvqpqjSTD8dhfxRnzpxTs8/ys3V2q01MvaY3r0eKsDgpKK1U1y/5N6gFHgiesbxG0V+O5IWdz4+c1DzoNyOQ==", + "dependencies": { + "Serilog": "2.0.0" + } + }, + "Serilog.Sinks.RollingFile": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "2lT5X1r3GH4P0bRWJfhA7etGl8Q2Ipw9AACvtAHWRUSpYZ42NGVyHoVs2ALBZ/cAkkS+tA4jl80Zie144eLQPg==", + "dependencies": { + "Serilog.Sinks.File": "3.2.0", + "System.IO": "4.1.0", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Serilog.Sinks.SyslogMessages": { + "type": "Transitive", + "resolved": "2.0.6", + "contentHash": "V2Yq2GEbk7taEPbpBLFzLXhrHrUzKf4sQu/zLrANU8XIoUn/Mr08M2E8PrcrWVXCj0R4xLMWYe0Z1sxOrMF3IA==", + "dependencies": { + "Serilog": "2.5.0", + "Serilog.Sinks.PeriodicBatching": "2.3.0" + } + }, + "SQLitePCLRaw.bundle_e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "ilkvNhrTersLmIVAcDwwPqfhUFCg19Z1GVMvCSi3xk6Akq94f4qadLORQCq/T8+9JgMiPs+F/NECw5uauviaNw==", + "dependencies": { + "SQLitePCLRaw.lib.e_sqlite3": "2.1.2", + "SQLitePCLRaw.provider.e_sqlite3": "2.1.2" + } + }, + "SQLitePCLRaw.core": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "A8EBepVqY2lnAp3a8jnhbgzF2tlj2S3HcJQGANTYg/TbYbKa8Z5cM1h74An/vy0svhfzT7tVY0sFmUglLgv+2g==", + "dependencies": { + "System.Memory": "4.5.3" + } + }, + "SQLitePCLRaw.lib.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "zibGtku8M4Eea1R3ZCAxc86QbNvyEN17mAcQkvWKBuHvRpMiK2g5anG4R5Be7cWKSd1i6baYz8y4dMMAKcXKPg==" + }, + "SQLitePCLRaw.provider.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "lxCZarZdvAsMl2zw9bXHrXK6RxVhB4b23iTFhCOdHFhxfbsxLxWf+ocvswJwR/9Wh/E//ddMi+wJGqUKV7VwoA==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "StackExchange.Redis": { + "type": "Transitive", + "resolved": "2.5.43", + "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "dependencies": { + "Pipelines.Sockets.Unofficial": "2.2.2", + "System.Diagnostics.PerformanceCounter": "5.0.0" + } + }, + "starkbank-ecdsa": { + "type": "Transitive", + "resolved": "1.3.3", + "contentHash": "OblOaKb1enXn+dSp7tsx9yjwV+/BEKM9jFhshIkZTwCk7LuTFTp+wSon6rFzuPiIiTGtvVWQNUw2slHjGktJog==" + }, + "Stripe.net": { + "type": "Transitive", + "resolved": "40.0.0", + "contentHash": "SD1bGiF+sVQG3p2LXNTZ5rEG2aCnXIHokcxYS9yyW3dR01J0ryf+iNFOwid148yePZ0gCBcRxj3wiW1mTmP7UQ==", + "dependencies": { + "Newtonsoft.Json": "12.0.3", + "System.Configuration.ConfigurationManager": "6.0.0" + } + }, + "Swashbuckle.AspNetCore.Swagger": { + "type": "Transitive", + "resolved": "6.5.0", + "contentHash": "XWmCmqyFmoItXKFsQSwQbEAsjDKcxlNf1l+/Ki42hcb6LjKL8m5Db69OTvz5vLonMSRntYO1XLqz0OP+n3vKnA==", + "dependencies": { + "Microsoft.OpenApi": "1.2.3" + } + }, + "Swashbuckle.AspNetCore.SwaggerGen": { + "type": "Transitive", + "resolved": "6.5.0", + "contentHash": "Y/qW8Qdg9OEs7V013tt+94OdPxbRdbhcEbw4NiwGvf4YBcfhL/y7qp/Mjv/cENsQ2L3NqJ2AOu94weBy/h4KvA==", + "dependencies": { + "Swashbuckle.AspNetCore.Swagger": "6.5.0" + } + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Collections.NonGeneric": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "prtjIEMhGUnQq6RnPEYLpFt8AtLbp9yq2zxOSrY7KJJZrw25Fi97IzBqY7iqssbM61Ek5b8f3MG/sG1N2sN5KA==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Collections.Specialized": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Epx8PoVZR0iuOnJJDzp7pWvdfMMOAvpUo95pC4ScH2mJuXkKA2Y4aR3cG9qt2klHgSons1WFh4kcGW7cSXvrxg==", + "dependencies": { + "System.Collections.NonGeneric": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.ComponentModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VyGn1jGRZVfxnh8EdvDCi71v3bMXrsu8aYJOwoV7SNDLVhiEqwP86pPMyRGsDsxhXAm2b3o9OIqeETfN5qfezw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.ComponentModel.Annotations": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "SY2RLItHt43rd8J9D8M8e8NM4m+9WLN2uUd9G0n1I4hj/7w+v3pzK6ZBjexlG1/2xvLKQsqir3UGVSyBTXMLWA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.ComponentModel": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.ComponentModel.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "j8GUkCpM8V4d4vhLIIoBLGey2Z5bCkMVNjEZseyAlm4n5arcsJOeI3zkUP+zvZgzsbLTYh4lYeP/ZD/gdIAPrw==", + "dependencies": { + "System.ComponentModel": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.ComponentModel.TypeConverter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "16pQ6P+EdhcXzPiEK4kbA953Fu0MNG2ovxTZU81/qsCd1zPRsKc3uif5NgvllCY598k6bI0KUyKW8fanlfaDQg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Collections.NonGeneric": "4.3.0", + "System.Collections.Specialized": "4.3.0", + "System.ComponentModel": "4.3.0", + "System.ComponentModel.Primitives": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Composition": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "I+D26qpYdoklyAVUdqwUBrEIckMNjAYnuPJy/h9dsQItpQwVREkDFs4b4tkBza0kT2Yk48Lcfsv2QQ9hWsh9Iw==", + "dependencies": { + "System.Composition.AttributedModel": "1.0.31", + "System.Composition.Convention": "1.0.31", + "System.Composition.Hosting": "1.0.31", + "System.Composition.Runtime": "1.0.31", + "System.Composition.TypedParts": "1.0.31" + } + }, + "System.Composition.AttributedModel": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "NHWhkM3ZkspmA0XJEsKdtTt1ViDYuojgSND3yHhTzwxepiwqZf+BCWuvCbjUt4fe0NxxQhUDGJ5km6sLjo9qnQ==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Composition.Convention": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "GLjh2Ju71k6C0qxMMtl4efHa68NmWeIUYh4fkUI8xbjQrEBvFmRwMDFcylT8/PR9SQbeeL48IkFxU/+gd0nYEQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Composition.AttributedModel": "1.0.31", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Composition.Hosting": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "fN1bT4RX4vUqjbgoyuJFVUizAl2mYF5VAb+bVIxIYZSSc0BdnX+yGAxcavxJuDDCQ1K+/mdpgyEFc8e9ikjvrg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Composition.Runtime": "1.0.31", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Composition.Runtime": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "0LEJN+2NVM89CE4SekDrrk5tHV5LeATltkp+9WNYrR+Huiyt0vaCqHbbHtVAjPyeLWIc8dOz/3kthRBj32wGQg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Composition.TypedParts": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "0Zae/FtzeFgDBBuILeIbC/T9HMYbW4olAmi8XqqAGosSOWvXfiQLfARZEhiGd0LVXaYgXr0NhxiU1LldRP1fpQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Composition.AttributedModel": "1.0.31", + "System.Composition.Hosting": "1.0.31", + "System.Composition.Runtime": "1.0.31", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "6.0.0", + "System.Security.Permissions": "6.0.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Diagnostics.EventLog": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "lcyUiXTsETK2ALsZrX+nWuHSIQeazhqPphLfaRxzdGaG93+0kELqpgEHtwWOlQe7+jSFnKwaCAgL4kjeZCQJnw==" + }, + "System.Diagnostics.PerformanceCounter": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "kcQWWtGVC3MWMNXdMDWfrmIlFZZ2OdoeT6pSNVRtk9+Sa7jwdPiMlNwb0ZQcS7NRlT92pCfmjRtkSWUW3RAKwg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.Diagnostics.Process": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "J0wOX07+QASQblsfxmIMFc9Iq7KTXYL3zs2G/Xc704Ylv3NpuVdo6gij6V3PGiptTxqsK0K7CdXenRvKUnkA2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "Microsoft.Win32.Registry": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.TraceSource": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VnYp1NxGx8Ww731y2LJ1vpfb/DKVNKEZ8Jsh5SgQTZREL/YpWRArgh9pI8CDLmgHspZmLL697CaLvH85qQpRiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Drawing.Common": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + } + }, + "System.Dynamic.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "SNVi1E/vfWUAs/WYKhE9+qlS6KqK0YVhnlT0HQtr8pMIA8YX3lwy3uPMownDwdYISBdmAF/2holEIldVp85Wag==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Formats.Asn1": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==" + }, + "System.Formats.Cbor": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "mGaLOoiw7KurJagOOcIsWUoCT5ACIiGxKlCcbYQASefBGXjnCcKTq5Hdjb94eEAKg38zXKlHw4c6EjzgBl9dIw==" + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IdentityModel.Tokens.Jwt": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "JRD8AuypBE+2zYxT3dMJomQVsPYsCqlyZhWel3J1d5nzQokSRyTueF+Q4ID3Jcu6zSZKuzOdJ1MLTkbQsDqcvQ==", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Rfm2jYCaUeGysFEZjDe7j1R4x6Z6BzumS/vUT5a1AA/AWJuGX71PoGB0RmpyX3VmrGqVnAwtfMn39OHR8Y/5+g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "6.0.3", + "contentHash": "ryTgF+iFkpGZY1vRQhfCzX0xTdlV3pyaTTqRu2ETbEv+HlV7O6y7hyQURnghNIXvctl5DuZ//Dpks6HdL/Txgw==" + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Linq.Queryable": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "Yn/WfYe9RoRfmSLvUt2JerP0BTGGykCZkQPgojaxgzF2N0oPo+/AhB8TXOpdCcNlrG3VRtsamtK2uzsp3cqRVw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==", + "dependencies": { + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.6.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.4", + "contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.1", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.NameResolution": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "JdqRdM1Qym3YehqdKIi5LHrpypP4JMfxKQSNCJ2z4WawkG0il+N3XfNeJOxll2XrTnG7WgYYPoeiu/KOwg0DQw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.NetworkInformation": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "Q0rfeiW6QsiZuicGjrFA7cRr2+kXex0JIljTTxzI09GIftB8k+aNL31VsQD1sI2g31cw7UGDTgozA/FgeNSzsQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Linq": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.Sockets": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Overlapped": "4.0.1", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Requests": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "vxGt7C0cZixN+VqoSW4Yakc1Y9WknmxauDqzxgpw/FnBdz4kQNN51l4wxdXX5VY1xjqy//+G+4CvJWp1+f+y6Q==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Net.Http": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Claims": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Security.Principal": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Security": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Net.WebHeaderCollection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "XX2TIAN+wBSAIV51BU2FvvXMdstUa8b0FBSZmDWjZdwUMmggQSifpTOZ5fNH20z9ZCg2fkV1L5SsZnpO2RQDRQ==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0" + } + }, + "System.Net.WebSockets": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", + "dependencies": { + "Microsoft.Win32.Primitives": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.WebSockets.Client": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "NUCcDroX4lCQXgOrzlwIZ1u9YJ0krfyF0wk0ONnyLUmcQoEiYV2/OfUPRqUwQBbpH1BlGApkLgoQUwMqb5+c1g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.2", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Net.WebSockets": "4.0.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.X509Certificates": "4.1.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Numerics.Vectors": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Private.DataContractSerialization": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "lcqFBUaCZxPiUkA4dlSOoPZGtZsAuuElH2XHgLwGLxd7ZozWetV5yiz0qGAV2AUYOqw97MtZBjbLMN16Xz4vXA==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Collections.Concurrent": "4.0.12", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Emit.Lightweight": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1", + "System.Xml.XmlSerializer": "4.0.11" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Caching": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "30D6MkO8WF9jVGWZIP0hmCN8l9BTY4LCsAzLIe4xFSXzs+AjDotR7DpSmj27pFskDURzUvqYYY0ikModgBTxWw==", + "dependencies": { + "System.Configuration.ConfigurationManager": "5.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Runtime.Serialization.Json": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "+7DIJhnKYgCzUgcLbVTtRQb2l1M0FP549XFlFkQM5lmNiUBl44AfNbx4bz61xA8PzLtlYwfmif4JJJW7MPPnjg==", + "dependencies": { + "System.IO": "4.1.0", + "System.Private.DataContractSerialization": "4.1.1", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" + }, + "System.Security.Claims": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Security.Principal": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==", + "dependencies": { + "System.Formats.Asn1": "5.0.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Pkcs": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "elM3x+xSRhzQysiqo85SbidJJ2YbZlnvmh+53TuSZHsD7dNuuEWser+9EFtY+rYupBwkq2avc6ZCO3/6qACgmg==", + "dependencies": { + "System.Formats.Asn1": "6.0.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ==" + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Xml": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "i2Jn6rGXR63J0zIklImGRkDIJL4b1NfPSEbIVHBlqoIb12lfXIigCbDRpDmIEzwSo/v1U5y/rYJdzZYSyCWxvg==", + "dependencies": { + "System.Security.Cryptography.Pkcs": "4.5.0", + "System.Security.Permissions": "4.5.0" + } + }, + "System.Security.Permissions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==", + "dependencies": { + "System.Security.AccessControl": "6.0.0", + "System.Windows.Extensions": "6.0.0" + } + }, + "System.Security.Principal": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, + "System.Security.SecureString": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "sqzq9GD6/b0yqPuMpgIKBuoLf4VKAj8oAfh4kXSzPaN6eoKY3hRi9C5L27uip25qlU+BGPfb0xh2Rmbwc4jFVA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "NyscU59xX6Uo91qvhOs2Ccho3AR2TnZPomo1Z0K6YpyztBPM/A5VbkzOO19sy3A3i1TtEnTxA7bCe3Us+r5MWg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "zaJsHfESQvJ11vbXnNlkrR46IaMULk/gHxYsJphzSF+07kTjPHv+Oc14w6QEOfo3Q4hqLJgStUaYB9DBl0TmWg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Overlapped": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "f7aLuLkBoCQM2kng7zqLFBXz9Gk48gDK8lk1ih9rH/1arJJzZK9gJwNvPDhL6Ps/l6rwOr8jw+4FCHL0KKWiEg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Threading.Thread": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OHmbT+Zz065NKII/ZHcH9XO1dEuLGI1L2k7uYss+9C1jLxTC9kTZZuzUOyXHayRk+dft9CiDf3I/QZ0t8JKyBQ==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading.ThreadPool": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.ValueTuple": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" + }, + "System.Windows.Extensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==", + "dependencies": { + "System.Drawing.Common": "6.0.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "lJ8AxvkX7GQxpC6GFCeBj8ThYVyQczx2+f/cWHJU8tjS7YfI6Cv6bon70jVEgs2CiFbmmM8b9j1oZVx0dSI2Ww==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlSerializer": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "FrazwwqfIXTfq23mfv4zH+BjqkSFNaNFBtjzu3I9NRmG8EELYyrv/fJnttCIwRMFRR/YKXF1hmsMmMEnl55HGw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1" + } + }, + "System.Xml.XPath": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "v1JQ5SETnQusqmS3RwStF7vwQ3L02imIzl++sewmt23VGygix04pEH+FCj1yWb+z4GDzKiljr1W7Wfvrx0YwgA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XPath.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "A/uxsWi/Ifzkmd4ArTLISMbfFs6XpRPsXZonrIqyTY70xi8t+mDtvSM5Os0RqyRDobjMBwIDHDL4NOIbkDwf7A==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XPath": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "xunit.abstractions": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" + }, + "xunit.analyzers": { + "type": "Transitive", + "resolved": "0.10.0", + "contentHash": "4/IDFCJfIeg6bix9apmUtIMwvOsiwqdEexeO/R2D4GReIGPLIRODTpId/l4LRSrAJk9lEO3Zx1H0Zx6uohJDNg==" + }, + "xunit.assert": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "O/Oe0BS5RmSsM+LQOb041TzuPo5MdH2Rov+qXGS37X+KFG1Hxz7kopYklM5+1Y+tRGeXrOx5+Xne1RuqLFQoyQ==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "xunit.core": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "Zsj5OMU6JasNGERXZy8s72+pcheG6Q15atS5XpZXqAtULuyQiQ6XNnUsp1gyfC6WgqScqMvySiEHmHcOG6Eg0Q==", + "dependencies": { + "xunit.extensibility.core": "[2.4.1]", + "xunit.extensibility.execution": "[2.4.1]" + } + }, + "xunit.extensibility.core": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "yKZKm/8QNZnBnGZFD9SewkllHBiK0DThybQD/G4PiAmQjKtEZyHi6ET70QPU9KtSMJGRYS6Syk7EyR2EVDU4Kg==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.abstractions": "2.0.3" + } + }, + "xunit.extensibility.execution": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "7e/1jqBpcb7frLkB6XDrHCGXAbKN4Rtdb88epYxCSRQuZDRW8UtTfdTEVpdTl8s4T56e07hOBVd4G0OdCxIY2A==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.extensibility.core": "[2.4.1]" + } + }, + "YubicoDotNetClient": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "uP5F3Ko1gqZi3lwS2R/jAAwhBxXs/6PKDpS6FdQjsBA5qmF0hQmbtfxM6QHTXOMoWbUtfetG7+LtgmG8T5zDIg==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "common": { + "type": "Project", + "dependencies": { + "AutoFixture.AutoNSubstitute": "[4.17.0, )", + "AutoFixture.Xunit2": "[4.17.0, )", + "Core": "[2023.1.0, )", + "Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )", + "Microsoft.NET.Test.Sdk": "[17.1.0, )", + "NSubstitute": "[4.3.0, )", + "xunit": "[2.4.1, )" + } + }, + "core": { + "type": "Project", + "dependencies": { + "AWSSDK.SQS": "[3.7.2.47, )", + "AWSSDK.SimpleEmail": "[3.7.0.150, )", + "AspNetCoreRateLimit": "[4.0.2, )", + "AspNetCoreRateLimit.Redis": "[1.0.1, )", + "Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.2.1, )", + "Azure.Storage.Blobs": "[12.11.0, )", + "Azure.Storage.Queues": "[12.9.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "Fido2.AspNet": "[3.0.1, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "MailKit": "[3.2.0, )", + "Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )", + "Microsoft.Azure.Cosmos.Table": "[1.0.8, )", + "Microsoft.Azure.NotificationHubs": "[4.1.0, )", + "Microsoft.Azure.ServiceBus": "[5.2.0, )", + "Microsoft.Data.SqlClient": "[5.0.1, )", + "Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )", + "Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )", + "Microsoft.Extensions.Identity.Stores": "[6.0.4, )", + "Newtonsoft.Json": "[13.0.1, )", + "Otp.NET": "[1.2.2, )", + "Quartz": "[3.4.0, )", + "SendGrid": "[9.27.0, )", + "Sentry.Serilog": "[3.16.0, )", + "Serilog.AspNetCore": "[5.0.0, )", + "Serilog.Extensions.Logging": "[3.1.0, )", + "Serilog.Extensions.Logging.File": "[2.0.0, )", + "Serilog.Sinks.AzureCosmosDB": "[2.0.0, )", + "Serilog.Sinks.SyslogMessages": "[2.0.6, )", + "Stripe.net": "[40.0.0, )", + "YubicoDotNetClient": "[1.2.0, )" + } + }, + "identity": { + "type": "Project", + "dependencies": { + "Core": "[2023.1.0, )", + "SharedWeb": "[2023.1.0, )", + "Swashbuckle.AspNetCore.SwaggerGen": "[6.5.0, )" + } + }, + "infrastructure.dapper": { + "type": "Project", + "dependencies": { + "Core": "[2023.1.0, )", + "Dapper": "[2.0.123, )" + } + }, + "infrastructure.entityframework": { + "type": "Project", + "dependencies": { + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", + "Core": "[2023.1.0, )", + "Microsoft.EntityFrameworkCore.Relational": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.SqlServer": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.Sqlite": "[6.0.12, )", + "Npgsql.EntityFrameworkCore.PostgreSQL": "[6.0.8, )", + "Pomelo.EntityFrameworkCore.MySql": "[6.0.2, )", + "linq2db.EntityFrameworkCore": "[6.11.0, )" + } + }, + "integrationtestcommon": { + "type": "Project", + "dependencies": { + "Common": "[2023.1.0, )", + "Identity": "[2023.1.0, )", + "Microsoft.AspNetCore.Mvc.Testing": "[6.0.5, )", + "Microsoft.EntityFrameworkCore.InMemory": "[6.0.5, )", + "Microsoft.Extensions.Configuration": "[6.0.1, )" + } + }, + "scim": { + "type": "Project", + "dependencies": { + "Core": "[2023.1.0, )", + "Microsoft.VisualStudio.Web.CodeGeneration.Design": "[5.0.2, )", + "SharedWeb": "[2023.1.0, )" + } + }, + "sharedweb": { + "type": "Project", + "dependencies": { + "Core": "[2023.1.0, )", + "Infrastructure.Dapper": "[2023.1.0, )", + "Infrastructure.EntityFramework": "[2023.1.0, )" + } + } + } + } +} \ No newline at end of file diff --git a/bitwarden_license/test/Scim.Test/Groups/GetGroupsListQueryTests.cs b/bitwarden_license/test/Scim.Test/Groups/GetGroupsListQueryTests.cs new file mode 100644 index 000000000..fa8997580 --- /dev/null +++ b/bitwarden_license/test/Scim.Test/Groups/GetGroupsListQueryTests.cs @@ -0,0 +1,129 @@ +using Bit.Core.Entities; +using Bit.Core.Repositories; +using Bit.Scim.Groups; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Scim.Test.Groups; + +[SutProviderCustomize] +public class GetGroupsListCommandTests +{ + [Theory] + [BitAutoData(10, 1)] + [BitAutoData(2, 1)] + [BitAutoData(1, 3)] + public async Task GetGroupsList_Success(int count, int startIndex, SutProvider sutProvider, Guid organizationId, IList groups) + { + groups = SetGroupsOrganizationId(groups, organizationId); + + sutProvider.GetDependency() + .GetManyByOrganizationIdAsync(organizationId) + .Returns(groups); + + var result = await sutProvider.Sut.GetGroupsListAsync(organizationId, null, count, startIndex); + + AssertHelper.AssertPropertyEqual(groups.Skip(startIndex - 1).Take(count).ToList(), result.groupList); + AssertHelper.AssertPropertyEqual(groups.Count, result.totalResults); + } + + [Theory] + [BitAutoData] + public async Task GetGroupsList_FilterDisplayName_Success(SutProvider sutProvider, Guid organizationId, IList groups) + { + groups = SetGroupsOrganizationId(groups, organizationId); + string name = groups.First().Name; + string filter = $"displayName eq {name}"; + + var expectedGroupList = groups + .Where(g => g.Name == name) + .ToList(); + var expectedTotalResults = expectedGroupList.Count; + + sutProvider.GetDependency() + .GetManyByOrganizationIdAsync(organizationId) + .Returns(groups); + + var result = await sutProvider.Sut.GetGroupsListAsync(organizationId, filter, null, null); + + AssertHelper.AssertPropertyEqual(expectedGroupList, result.groupList); + AssertHelper.AssertPropertyEqual(expectedTotalResults, result.totalResults); + } + + [Theory] + [BitAutoData] + public async Task GetGroupsList_FilterDisplayName_Empty(string name, SutProvider sutProvider, Guid organizationId, IList groups) + { + groups = SetGroupsOrganizationId(groups, organizationId); + string filter = $"displayName eq {name}"; + + var expectedGroupList = new List(); + var expectedTotalResults = expectedGroupList.Count; + + sutProvider.GetDependency() + .GetManyByOrganizationIdAsync(organizationId) + .Returns(groups); + + var result = await sutProvider.Sut.GetGroupsListAsync(organizationId, filter, null, null); + + AssertHelper.AssertPropertyEqual(expectedGroupList, result.groupList); + AssertHelper.AssertPropertyEqual(expectedTotalResults, result.totalResults); + } + + [Theory] + [BitAutoData] + public async Task GetGroupsList_FilterExternalId_Success(SutProvider sutProvider, Guid organizationId, IList groups) + { + groups = SetGroupsOrganizationId(groups, organizationId); + string externalId = groups.First().ExternalId; + string filter = $"externalId eq {externalId}"; + + var expectedGroupList = groups + .Where(ou => ou.ExternalId == externalId) + .ToList(); + var expectedTotalResults = expectedGroupList.Count; + + sutProvider.GetDependency() + .GetManyByOrganizationIdAsync(organizationId) + .Returns(groups); + + var result = await sutProvider.Sut.GetGroupsListAsync(organizationId, filter, null, null); + + AssertHelper.AssertPropertyEqual(expectedGroupList, result.groupList); + AssertHelper.AssertPropertyEqual(expectedTotalResults, result.totalResults); + } + + [Theory] + [BitAutoData] + public async Task GetGroupsList_FilterExternalId_Empty(string externalId, SutProvider sutProvider, Guid organizationId, IList groups) + { + groups = SetGroupsOrganizationId(groups, organizationId); + string filter = $"externalId eq {externalId}"; + + var expectedGroupList = groups + .Where(ou => ou.ExternalId == externalId) + .ToList(); + var expectedTotalResults = expectedGroupList.Count; + + sutProvider.GetDependency() + .GetManyByOrganizationIdAsync(organizationId) + .Returns(groups); + + var result = await sutProvider.Sut.GetGroupsListAsync(organizationId, filter, null, null); + + AssertHelper.AssertPropertyEqual(expectedGroupList, result.groupList); + AssertHelper.AssertPropertyEqual(expectedTotalResults, result.totalResults); + } + + private IList SetGroupsOrganizationId(IList groups, Guid organizationId) + { + return groups.Select(g => + { + g.OrganizationId = organizationId; + return g; + }).ToList(); + } +} diff --git a/bitwarden_license/test/Scim.Test/Groups/PatchGroupCommandTests.cs b/bitwarden_license/test/Scim.Test/Groups/PatchGroupCommandTests.cs new file mode 100644 index 000000000..505a67f57 --- /dev/null +++ b/bitwarden_license/test/Scim.Test/Groups/PatchGroupCommandTests.cs @@ -0,0 +1,292 @@ +using System.Text.Json; +using Bit.Core.Entities; +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.OrganizationFeatures.Groups.Interfaces; +using Bit.Core.Repositories; +using Bit.Core.Services; +using Bit.Scim.Groups; +using Bit.Scim.Models; +using Bit.Scim.Utilities; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using NSubstitute; +using Xunit; + +namespace Bit.Scim.Test.Groups; + +[SutProviderCustomize] +public class PatchGroupCommandTests +{ + [Theory] + [BitAutoData] + public async Task PatchGroup_ReplaceListMembers_Success(SutProvider sutProvider, Organization organization, Group group, IEnumerable userIds) + { + group.OrganizationId = organization.Id; + + sutProvider.GetDependency() + .GetByIdAsync(group.Id) + .Returns(group); + + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List + { + new ScimPatchModel.OperationModel + { + Op = "replace", + Path = "members", + Value = JsonDocument.Parse(JsonSerializer.Serialize(userIds.Select(uid => new { value = uid }).ToArray())).RootElement + } + }, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await sutProvider.Sut.PatchGroupAsync(organization, group.Id, scimPatchModel); + + await sutProvider.GetDependency().Received(1).UpdateUsersAsync(group.Id, Arg.Is>(arg => arg.All(id => userIds.Contains(id)))); + } + + [Theory] + [BitAutoData] + public async Task PatchGroup_ReplaceDisplayNameFromPath_Success(SutProvider sutProvider, Organization organization, Group group, string displayName) + { + group.OrganizationId = organization.Id; + + sutProvider.GetDependency() + .GetByIdAsync(group.Id) + .Returns(group); + + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List + { + new ScimPatchModel.OperationModel + { + Op = "replace", + Path = "displayname", + Value = JsonDocument.Parse($"\"{displayName}\"").RootElement + } + }, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await sutProvider.Sut.PatchGroupAsync(organization, group.Id, scimPatchModel); + + await sutProvider.GetDependency().Received(1).UpdateGroupAsync(group, organization, EventSystemUser.SCIM); + Assert.Equal(displayName, group.Name); + } + + [Theory] + [BitAutoData] + public async Task PatchGroup_ReplaceDisplayNameFromValueObject_Success(SutProvider sutProvider, Organization organization, Group group, string displayName) + { + group.OrganizationId = organization.Id; + + sutProvider.GetDependency() + .GetByIdAsync(group.Id) + .Returns(group); + + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List + { + new ScimPatchModel.OperationModel + { + Op = "replace", + Value = JsonDocument.Parse($"{{\"displayName\":\"{displayName}\"}}").RootElement + } + }, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await sutProvider.Sut.PatchGroupAsync(organization, group.Id, scimPatchModel); + + await sutProvider.GetDependency().Received(1).UpdateGroupAsync(group, organization, EventSystemUser.SCIM); + Assert.Equal(displayName, group.Name); + } + + [Theory] + [BitAutoData] + public async Task PatchGroup_AddSingleMember_Success(SutProvider sutProvider, Organization organization, Group group, ICollection existingMembers, Guid userId) + { + group.OrganizationId = organization.Id; + + sutProvider.GetDependency() + .GetByIdAsync(group.Id) + .Returns(group); + + sutProvider.GetDependency() + .GetManyUserIdsByIdAsync(group.Id) + .Returns(existingMembers); + + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List + { + new ScimPatchModel.OperationModel + { + Op = "add", + Path = $"members[value eq \"{userId}\"]", + } + }, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await sutProvider.Sut.PatchGroupAsync(organization, group.Id, scimPatchModel); + + await sutProvider.GetDependency().Received(1).UpdateUsersAsync(group.Id, Arg.Is>(arg => arg.All(id => existingMembers.Append(userId).Contains(id)))); + } + + [Theory] + [BitAutoData] + public async Task PatchGroup_AddListMembers_Success(SutProvider sutProvider, Organization organization, Group group, ICollection existingMembers, ICollection userIds) + { + group.OrganizationId = organization.Id; + + sutProvider.GetDependency() + .GetByIdAsync(group.Id) + .Returns(group); + + sutProvider.GetDependency() + .GetManyUserIdsByIdAsync(group.Id) + .Returns(existingMembers); + + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List + { + new ScimPatchModel.OperationModel + { + Op = "add", + Path = $"members", + Value = JsonDocument.Parse(JsonSerializer.Serialize(userIds.Select(uid => new { value = uid }).ToArray())).RootElement + } + }, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await sutProvider.Sut.PatchGroupAsync(organization, group.Id, scimPatchModel); + + await sutProvider.GetDependency().Received(1).UpdateUsersAsync(group.Id, Arg.Is>(arg => arg.All(id => existingMembers.Concat(userIds).Contains(id)))); + } + + [Theory] + [BitAutoData] + public async Task PatchGroup_RemoveSingleMember_Success(SutProvider sutProvider, Organization organization, Group group, Guid userId) + { + group.OrganizationId = organization.Id; + + sutProvider.GetDependency() + .GetByIdAsync(group.Id) + .Returns(group); + + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List + { + new ScimPatchModel.OperationModel + { + Op = "remove", + Path = $"members[value eq \"{userId}\"]", + } + }, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await sutProvider.Sut.PatchGroupAsync(organization, group.Id, scimPatchModel); + + await sutProvider.GetDependency().Received(1).DeleteUserAsync(group, userId, EventSystemUser.SCIM); + } + + [Theory] + [BitAutoData] + public async Task PatchGroup_RemoveListMembers_Success(SutProvider sutProvider, Organization organization, Group group, ICollection existingMembers) + { + group.OrganizationId = organization.Id; + + sutProvider.GetDependency() + .GetByIdAsync(group.Id) + .Returns(group); + + sutProvider.GetDependency() + .GetManyUserIdsByIdAsync(group.Id) + .Returns(existingMembers); + + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List + { + new ScimPatchModel.OperationModel + { + Op = "remove", + Path = $"members", + Value = JsonDocument.Parse(JsonSerializer.Serialize(existingMembers.Select(uid => new { value = uid }).ToArray())).RootElement + } + }, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await sutProvider.Sut.PatchGroupAsync(organization, group.Id, scimPatchModel); + + await sutProvider.GetDependency().Received(1).UpdateUsersAsync(group.Id, Arg.Is>(arg => arg.All(id => existingMembers.Contains(id)))); + } + + [Theory] + [BitAutoData] + public async Task PatchGroup_NoAction_Success(SutProvider sutProvider, Organization organization, Group group) + { + group.OrganizationId = organization.Id; + + sutProvider.GetDependency() + .GetByIdAsync(group.Id) + .Returns(group); + + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List(), + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await sutProvider.Sut.PatchGroupAsync(organization, group.Id, scimPatchModel); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().UpdateUsersAsync(default, default); + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().GetManyUserIdsByIdAsync(default); + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().UpdateGroupAsync(default, default); + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().DeleteUserAsync(default, default); + } + + [Theory] + [BitAutoData] + public async Task PatchGroup_NotFound_Throws(SutProvider sutProvider, Organization organization, Guid groupId) + { + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List(), + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await Assert.ThrowsAsync(async () => await sutProvider.Sut.PatchGroupAsync(organization, groupId, scimPatchModel)); + } + + [Theory] + [BitAutoData] + public async Task PatchGroup_MismatchingOrganizationId_Throws(SutProvider sutProvider, Organization organization, Guid groupId) + { + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List(), + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + sutProvider.GetDependency() + .GetByIdAsync(groupId) + .Returns(new Group + { + Id = groupId, + OrganizationId = Guid.NewGuid() + }); + + await Assert.ThrowsAsync(async () => await sutProvider.Sut.PatchGroupAsync(organization, groupId, scimPatchModel)); + } +} diff --git a/bitwarden_license/test/Scim.Test/Groups/PostGroupCommandTests.cs b/bitwarden_license/test/Scim.Test/Groups/PostGroupCommandTests.cs new file mode 100644 index 000000000..f7efb022d --- /dev/null +++ b/bitwarden_license/test/Scim.Test/Groups/PostGroupCommandTests.cs @@ -0,0 +1,122 @@ +using Bit.Core.Entities; +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.OrganizationFeatures.Groups.Interfaces; +using Bit.Core.Repositories; +using Bit.Scim.Context; +using Bit.Scim.Groups; +using Bit.Scim.Models; +using Bit.Scim.Utilities; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Scim.Test.Groups; + +[SutProviderCustomize] +public class PostGroupCommandTests +{ + [Theory] + [BitAutoData] + public async Task PostGroup_Success(SutProvider sutProvider, string displayName, string externalId, Organization organization, ICollection groups) + { + var scimGroupRequestModel = new ScimGroupRequestModel + { + DisplayName = displayName, + ExternalId = externalId, + Members = new List(), + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + var expectedResult = new Group + { + OrganizationId = organization.Id, + Name = displayName, + ExternalId = externalId, + }; + + sutProvider.GetDependency() + .GetManyByOrganizationIdAsync(organization.Id) + .Returns(groups); + + var group = await sutProvider.Sut.PostGroupAsync(organization, scimGroupRequestModel); + + await sutProvider.GetDependency().Received(1).CreateGroupAsync(group, organization, EventSystemUser.SCIM, null); + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().UpdateUsersAsync(default, default); + + AssertHelper.AssertPropertyEqual(expectedResult, group, "Id", "CreationDate", "RevisionDate"); + } + + [Theory] + [BitAutoData] + public async Task PostGroup_WithMembers_Success(SutProvider sutProvider, string displayName, string externalId, Organization organization, ICollection groups, IEnumerable membersUserIds) + { + var scimGroupRequestModel = new ScimGroupRequestModel + { + DisplayName = displayName, + ExternalId = externalId, + Members = membersUserIds.Select(uid => new ScimGroupRequestModel.GroupMembersModel { Value = uid.ToString() }).ToList(), + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + var expectedResult = new Group + { + OrganizationId = organization.Id, + Name = displayName, + ExternalId = externalId + }; + + sutProvider.GetDependency() + .GetManyByOrganizationIdAsync(organization.Id) + .Returns(groups); + + sutProvider.GetDependency() + .RequestScimProvider + .Returns(Core.Enums.ScimProviderType.Okta); + + var group = await sutProvider.Sut.PostGroupAsync(organization, scimGroupRequestModel); + + await sutProvider.GetDependency().Received(1).CreateGroupAsync(group, organization, EventSystemUser.SCIM, null); + await sutProvider.GetDependency().Received(1).UpdateUsersAsync(Arg.Any(), Arg.Is>(arg => arg.All(id => membersUserIds.Contains(id)))); + + AssertHelper.AssertPropertyEqual(expectedResult, group, "Id", "CreationDate", "RevisionDate"); + } + + [Theory] + [BitAutoData((string)null)] + [BitAutoData("")] + [BitAutoData(" ")] + public async Task PostGroup_NullDisplayName_Throws(string displayName, SutProvider sutProvider, Organization organization) + { + var scimGroupRequestModel = new ScimGroupRequestModel + { + DisplayName = displayName, + ExternalId = Guid.NewGuid().ToString(), + Members = new List(), + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await Assert.ThrowsAsync(async () => await sutProvider.Sut.PostGroupAsync(organization, scimGroupRequestModel)); + } + + [Theory] + [BitAutoData] + public async Task PostGroup_ExistingExternalId_Throws(string displayName, SutProvider sutProvider, Organization organization, ICollection groups) + { + var scimGroupRequestModel = new ScimGroupRequestModel + { + DisplayName = displayName, + ExternalId = groups.First().ExternalId, + Members = new List(), + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + sutProvider.GetDependency() + .GetManyByOrganizationIdAsync(organization.Id) + .Returns(groups); + + await Assert.ThrowsAsync(async () => await sutProvider.Sut.PostGroupAsync(organization, scimGroupRequestModel)); + } +} diff --git a/bitwarden_license/test/Scim.Test/Groups/PutGroupCommandTests.cs b/bitwarden_license/test/Scim.Test/Groups/PutGroupCommandTests.cs new file mode 100644 index 000000000..4bcc3c0c8 --- /dev/null +++ b/bitwarden_license/test/Scim.Test/Groups/PutGroupCommandTests.cs @@ -0,0 +1,127 @@ +using Bit.Core.Entities; +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.OrganizationFeatures.Groups.Interfaces; +using Bit.Core.Repositories; +using Bit.Scim.Context; +using Bit.Scim.Groups; +using Bit.Scim.Models; +using Bit.Scim.Utilities; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Scim.Test.Groups; + +[SutProviderCustomize] +public class PutGroupCommandTests +{ + [Theory] + [BitAutoData] + public async Task PutGroup_Success(SutProvider sutProvider, Organization organization, Group group, string displayName) + { + group.OrganizationId = organization.Id; + + sutProvider.GetDependency() + .GetByIdAsync(group.Id) + .Returns(group); + + var inputModel = new ScimGroupRequestModel + { + DisplayName = displayName, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + var expectedResult = new Group + { + Id = group.Id, + AccessAll = group.AccessAll, + ExternalId = group.ExternalId, + Name = displayName, + OrganizationId = group.OrganizationId + }; + + var result = await sutProvider.Sut.PutGroupAsync(organization, group.Id, inputModel); + + AssertHelper.AssertPropertyEqual(expectedResult, result, "CreationDate", "RevisionDate"); + Assert.Equal(displayName, group.Name); + + await sutProvider.GetDependency().Received(1).UpdateGroupAsync(group, organization, EventSystemUser.SCIM); + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().UpdateUsersAsync(default, default); + } + + [Theory] + [BitAutoData] + public async Task PutGroup_ChangeMembers_Success(SutProvider sutProvider, Organization organization, Group group, string displayName, IEnumerable membersUserIds) + { + group.OrganizationId = organization.Id; + + sutProvider.GetDependency() + .GetByIdAsync(group.Id) + .Returns(group); + + sutProvider.GetDependency() + .RequestScimProvider + .Returns(Core.Enums.ScimProviderType.Okta); + + var inputModel = new ScimGroupRequestModel + { + DisplayName = displayName, + Members = membersUserIds.Select(uid => new ScimGroupRequestModel.GroupMembersModel { Value = uid.ToString() }).ToList(), + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + var expectedResult = new Group + { + Id = group.Id, + AccessAll = group.AccessAll, + ExternalId = group.ExternalId, + Name = displayName, + OrganizationId = group.OrganizationId + }; + + var result = await sutProvider.Sut.PutGroupAsync(organization, group.Id, inputModel); + + AssertHelper.AssertPropertyEqual(expectedResult, result, "CreationDate", "RevisionDate"); + Assert.Equal(displayName, group.Name); + + await sutProvider.GetDependency().Received(1).UpdateGroupAsync(group, organization, EventSystemUser.SCIM); + await sutProvider.GetDependency().Received(1).UpdateUsersAsync(group.Id, Arg.Is>(arg => arg.All(id => membersUserIds.Contains(id)))); + } + + [Theory] + [BitAutoData] + public async Task PutGroup_NotFound_Throws(SutProvider sutProvider, Organization organization, Guid groupId, string displayName) + { + var scimGroupRequestModel = new ScimGroupRequestModel + { + DisplayName = displayName, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await Assert.ThrowsAsync(async () => await sutProvider.Sut.PutGroupAsync(organization, groupId, scimGroupRequestModel)); + } + + [Theory] + [BitAutoData] + public async Task PutGroup_MismatchingOrganizationId_Throws(SutProvider sutProvider, Organization organization, Guid groupId, string displayName) + { + var scimGroupRequestModel = new ScimGroupRequestModel + { + DisplayName = displayName, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + sutProvider.GetDependency() + .GetByIdAsync(groupId) + .Returns(new Group + { + Id = groupId, + OrganizationId = Guid.NewGuid() + }); + + await Assert.ThrowsAsync(async () => await sutProvider.Sut.PutGroupAsync(organization, groupId, scimGroupRequestModel)); + } +} diff --git a/bitwarden_license/test/Scim.Test/Scim.Test.csproj b/bitwarden_license/test/Scim.Test/Scim.Test.csproj new file mode 100644 index 000000000..35e4df83a --- /dev/null +++ b/bitwarden_license/test/Scim.Test/Scim.Test.csproj @@ -0,0 +1,25 @@ + + + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + \ No newline at end of file diff --git a/bitwarden_license/test/Scim.Test/Users/GetUsersListQueryTests.cs b/bitwarden_license/test/Scim.Test/Users/GetUsersListQueryTests.cs new file mode 100644 index 000000000..b7497e281 --- /dev/null +++ b/bitwarden_license/test/Scim.Test/Users/GetUsersListQueryTests.cs @@ -0,0 +1,139 @@ +using Bit.Core.Models.Data.Organizations.OrganizationUsers; +using Bit.Core.Repositories; +using Bit.Scim.Users; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Scim.Test.Users; + +[SutProviderCustomize] +public class GetUsersListQueryTests +{ + [Theory] + [BitAutoData(10, 1)] + [BitAutoData(2, 1)] + [BitAutoData(1, 3)] + public async Task GetUsersList_Success(int count, int startIndex, SutProvider sutProvider, Guid organizationId, IList organizationUserUserDetails) + { + organizationUserUserDetails = SetUsersOrganizationId(organizationUserUserDetails, organizationId); + + sutProvider.GetDependency() + .GetManyDetailsByOrganizationAsync(organizationId) + .Returns(organizationUserUserDetails); + + var result = await sutProvider.Sut.GetUsersListAsync(organizationId, null, count, startIndex); + + await sutProvider.GetDependency().Received(1).GetManyDetailsByOrganizationAsync(organizationId); + + AssertHelper.AssertPropertyEqual(organizationUserUserDetails.Skip(startIndex - 1).Take(count).ToList(), result.userList); + AssertHelper.AssertPropertyEqual(organizationUserUserDetails.Count, result.totalResults); + } + + [Theory] + [BitAutoData("user1@example.com")] + public async Task GetUsersList_FilterUserName_Success(string email, SutProvider sutProvider, Guid organizationId, IList organizationUserUserDetails) + { + organizationUserUserDetails = SetUsersOrganizationId(organizationUserUserDetails, organizationId); + organizationUserUserDetails.First().Email = email; + string filter = $"userName eq {email}"; + + var expectedUserList = organizationUserUserDetails + .Where(u => u.Email == email) + .ToList(); + var expectedTotalResults = expectedUserList.Count; + + sutProvider.GetDependency() + .GetManyDetailsByOrganizationAsync(organizationId) + .Returns(organizationUserUserDetails); + + var result = await sutProvider.Sut.GetUsersListAsync(organizationId, filter, null, null); + + await sutProvider.GetDependency().Received(1).GetManyDetailsByOrganizationAsync(organizationId); + + AssertHelper.AssertPropertyEqual(expectedUserList, result.userList); + AssertHelper.AssertPropertyEqual(expectedTotalResults, result.totalResults); + } + + [Theory] + [BitAutoData("user1@example.com")] + public async Task GetUsersList_FilterUserName_Empty(string email, SutProvider sutProvider, Guid organizationId, IList organizationUserUserDetails) + { + organizationUserUserDetails = SetUsersOrganizationId(organizationUserUserDetails, organizationId); + string filter = $"userName eq {email}"; + + var expectedUserList = new List(); + var expectedTotalResults = expectedUserList.Count; + + sutProvider.GetDependency() + .GetManyDetailsByOrganizationAsync(organizationId) + .Returns(organizationUserUserDetails); + + var result = await sutProvider.Sut.GetUsersListAsync(organizationId, filter, null, null); + + await sutProvider.GetDependency().Received(1).GetManyDetailsByOrganizationAsync(organizationId); + + AssertHelper.AssertPropertyEqual(expectedUserList, result.userList); + AssertHelper.AssertPropertyEqual(expectedTotalResults, result.totalResults); + } + + [Theory] + [BitAutoData] + public async Task GetUsersList_FilterExternalId_Success(SutProvider sutProvider, Guid organizationId, IList organizationUserUserDetails) + { + organizationUserUserDetails = SetUsersOrganizationId(organizationUserUserDetails, organizationId); + string externalId = organizationUserUserDetails.First().ExternalId; + string filter = $"externalId eq {externalId}"; + + var expectedUserList = organizationUserUserDetails + .Where(u => u.ExternalId == externalId) + .ToList(); + var expectedTotalResults = expectedUserList.Count; + + sutProvider.GetDependency() + .GetManyDetailsByOrganizationAsync(organizationId) + .Returns(organizationUserUserDetails); + + var result = await sutProvider.Sut.GetUsersListAsync(organizationId, filter, null, null); + + await sutProvider.GetDependency().Received(1).GetManyDetailsByOrganizationAsync(organizationId); + + AssertHelper.AssertPropertyEqual(expectedUserList, result.userList); + AssertHelper.AssertPropertyEqual(expectedTotalResults, result.totalResults); + } + + [Theory] + [BitAutoData] + public async Task GetUsersList_FilterExternalId_Empty(string externalId, SutProvider sutProvider, Guid organizationId, IList organizationUserUserDetails) + { + organizationUserUserDetails = SetUsersOrganizationId(organizationUserUserDetails, organizationId); + string filter = $"externalId eq {externalId}"; + + var expectedUserList = organizationUserUserDetails + .Where(u => u.ExternalId == externalId) + .ToList(); + var expectedTotalResults = expectedUserList.Count; + + sutProvider.GetDependency() + .GetManyDetailsByOrganizationAsync(organizationId) + .Returns(organizationUserUserDetails); + + var result = await sutProvider.Sut.GetUsersListAsync(organizationId, filter, null, null); + + await sutProvider.GetDependency().Received(1).GetManyDetailsByOrganizationAsync(organizationId); + + AssertHelper.AssertPropertyEqual(expectedUserList, result.userList); + AssertHelper.AssertPropertyEqual(expectedTotalResults, result.totalResults); + } + + private IList SetUsersOrganizationId(IList organizationUserUserDetails, Guid organizationId) + { + return organizationUserUserDetails.Select(ouud => + { + ouud.OrganizationId = organizationId; + return ouud; + }).ToList(); + } +} diff --git a/bitwarden_license/test/Scim.Test/Users/PatchUserCommandTests.cs b/bitwarden_license/test/Scim.Test/Users/PatchUserCommandTests.cs new file mode 100644 index 000000000..977011b35 --- /dev/null +++ b/bitwarden_license/test/Scim.Test/Users/PatchUserCommandTests.cs @@ -0,0 +1,187 @@ +using System.Text.Json; +using Bit.Core.Entities; +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Core.Services; +using Bit.Scim.Models; +using Bit.Scim.Users; +using Bit.Scim.Utilities; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using NSubstitute; +using Xunit; + +namespace Bit.Scim.Test.Users; + +[SutProviderCustomize] +public class PatchUserCommandTests +{ + [Theory] + [BitAutoData] + public async Task PatchUser_RestorePath_Success(SutProvider sutProvider, OrganizationUser organizationUser) + { + organizationUser.Status = Core.Enums.OrganizationUserStatusType.Revoked; + + sutProvider.GetDependency() + .GetByIdAsync(organizationUser.Id) + .Returns(organizationUser); + + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List + { + new ScimPatchModel.OperationModel + { + Op = "replace", + Path = "active", + Value = JsonDocument.Parse("true").RootElement + } + }, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await sutProvider.Sut.PatchUserAsync(organizationUser.OrganizationId, organizationUser.Id, scimPatchModel); + + await sutProvider.GetDependency().Received(1).RestoreUserAsync(organizationUser, EventSystemUser.SCIM, Arg.Any()); + } + + [Theory] + [BitAutoData] + public async Task PatchUser_RestoreValue_Success(SutProvider sutProvider, OrganizationUser organizationUser) + { + organizationUser.Status = Core.Enums.OrganizationUserStatusType.Revoked; + + sutProvider.GetDependency() + .GetByIdAsync(organizationUser.Id) + .Returns(organizationUser); + + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List + { + new ScimPatchModel.OperationModel + { + Op = "replace", + Value = JsonDocument.Parse("{\"active\":true}").RootElement + } + }, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await sutProvider.Sut.PatchUserAsync(organizationUser.OrganizationId, organizationUser.Id, scimPatchModel); + + await sutProvider.GetDependency().Received(1).RestoreUserAsync(organizationUser, EventSystemUser.SCIM, Arg.Any()); + } + + [Theory] + [BitAutoData] + public async Task PatchUser_RevokePath_Success(SutProvider sutProvider, OrganizationUser organizationUser) + { + organizationUser.Status = Core.Enums.OrganizationUserStatusType.Confirmed; + + sutProvider.GetDependency() + .GetByIdAsync(organizationUser.Id) + .Returns(organizationUser); + + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List + { + new ScimPatchModel.OperationModel + { + Op = "replace", + Path = "active", + Value = JsonDocument.Parse("false").RootElement + } + }, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await sutProvider.Sut.PatchUserAsync(organizationUser.OrganizationId, organizationUser.Id, scimPatchModel); + + await sutProvider.GetDependency().Received(1).RevokeUserAsync(organizationUser, EventSystemUser.SCIM); + } + + [Theory] + [BitAutoData] + public async Task PatchUser_RevokeValue_Success(SutProvider sutProvider, OrganizationUser organizationUser) + { + organizationUser.Status = Core.Enums.OrganizationUserStatusType.Confirmed; + + sutProvider.GetDependency() + .GetByIdAsync(organizationUser.Id) + .Returns(organizationUser); + + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List + { + new ScimPatchModel.OperationModel + { + Op = "replace", + Value = JsonDocument.Parse("{\"active\":false}").RootElement + } + }, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await sutProvider.Sut.PatchUserAsync(organizationUser.OrganizationId, organizationUser.Id, scimPatchModel); + + await sutProvider.GetDependency().Received(1).RevokeUserAsync(organizationUser, EventSystemUser.SCIM); + } + + [Theory] + [BitAutoData] + public async Task PatchUser_NoAction_Success(SutProvider sutProvider, OrganizationUser organizationUser) + { + sutProvider.GetDependency() + .GetByIdAsync(organizationUser.Id) + .Returns(organizationUser); + + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List(), + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await sutProvider.Sut.PatchUserAsync(organizationUser.OrganizationId, organizationUser.Id, scimPatchModel); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().RestoreUserAsync(default, EventSystemUser.SCIM, default); + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().RevokeUserAsync(default, EventSystemUser.SCIM); + } + + [Theory] + [BitAutoData] + public async Task PatchUser_NotFound_Throws(SutProvider sutProvider, Guid organizationId, Guid organizationUserId) + { + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List(), + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await Assert.ThrowsAsync(async () => await sutProvider.Sut.PatchUserAsync(organizationId, organizationUserId, scimPatchModel)); + } + + [Theory] + [BitAutoData] + public async Task PatchUser_MismatchingOrganizationId_Throws(SutProvider sutProvider, Guid organizationId, Guid organizationUserId) + { + var scimPatchModel = new Models.ScimPatchModel + { + Operations = new List(), + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + sutProvider.GetDependency() + .GetByIdAsync(organizationUserId) + .Returns(new OrganizationUser + { + Id = organizationUserId, + OrganizationId = Guid.NewGuid() + }); + + await Assert.ThrowsAsync(async () => await sutProvider.Sut.PatchUserAsync(organizationId, organizationUserId, scimPatchModel)); + } +} diff --git a/bitwarden_license/test/Scim.Test/Users/PostUserCommandTests.cs b/bitwarden_license/test/Scim.Test/Users/PostUserCommandTests.cs new file mode 100644 index 000000000..304a29070 --- /dev/null +++ b/bitwarden_license/test/Scim.Test/Users/PostUserCommandTests.cs @@ -0,0 +1,114 @@ +using Bit.Core.Enums; +using Bit.Core.Exceptions; +using Bit.Core.Models.Data; +using Bit.Core.Models.Data.Organizations.OrganizationUsers; +using Bit.Core.Repositories; +using Bit.Core.Services; +using Bit.Scim.Models; +using Bit.Scim.Users; +using Bit.Scim.Utilities; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using NSubstitute; +using Xunit; + +namespace Bit.Scim.Test.Users; + +[SutProviderCustomize] +public class PostUserCommandTests +{ + [Theory] + [BitAutoData] + public async Task PostUser_Success(SutProvider sutProvider, string externalId, Guid organizationId, List emails, ICollection organizationUsers, Core.Entities.OrganizationUser newUser) + { + var scimUserRequestModel = new ScimUserRequestModel + { + ExternalId = externalId, + Emails = emails, + Active = true, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + sutProvider.GetDependency() + .GetManyDetailsByOrganizationAsync(organizationId) + .Returns(organizationUsers); + + sutProvider.GetDependency() + .InviteUserAsync(organizationId, EventSystemUser.SCIM, scimUserRequestModel.PrimaryEmail.ToLowerInvariant(), + OrganizationUserType.User, false, externalId, Arg.Any>(), + Arg.Any>()) + .Returns(newUser); + + var user = await sutProvider.Sut.PostUserAsync(organizationId, scimUserRequestModel); + + await sutProvider.GetDependency().Received(1).InviteUserAsync(organizationId, EventSystemUser.SCIM, scimUserRequestModel.PrimaryEmail.ToLowerInvariant(), + OrganizationUserType.User, false, scimUserRequestModel.ExternalId, Arg.Any>(), Arg.Any>()); + await sutProvider.GetDependency().Received(1).GetDetailsByIdAsync(newUser.Id); + } + + [Theory] + [BitAutoData] + public async Task PostUser_NullEmail_Throws(SutProvider sutProvider, Guid organizationId) + { + var scimUserRequestModel = new ScimUserRequestModel + { + Emails = new List(), + Active = true, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await Assert.ThrowsAsync(async () => await sutProvider.Sut.PostUserAsync(organizationId, scimUserRequestModel)); + } + + [Theory] + [BitAutoData] + public async Task PostUser_Inactive_Throws(SutProvider sutProvider, Guid organizationId, List emails) + { + var scimUserRequestModel = new ScimUserRequestModel + { + Emails = emails, + Active = false, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + await Assert.ThrowsAsync(async () => await sutProvider.Sut.PostUserAsync(organizationId, scimUserRequestModel)); + } + + [Theory] + [BitAutoData] + public async Task PostUser_DuplicateExternalId_Throws(SutProvider sutProvider, Guid organizationId, List emails, ICollection organizationUsers) + { + var scimUserRequestModel = new ScimUserRequestModel + { + ExternalId = organizationUsers.First().ExternalId, + Emails = emails, + Active = true, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + sutProvider.GetDependency() + .GetManyDetailsByOrganizationAsync(organizationId) + .Returns(organizationUsers); + + await Assert.ThrowsAsync(async () => await sutProvider.Sut.PostUserAsync(organizationId, scimUserRequestModel)); + } + + [Theory] + [BitAutoData] + public async Task PostUser_DuplicateUserName_Throws(SutProvider sutProvider, Guid organizationId, List emails, ICollection organizationUsers) + { + var scimUserRequestModel = new ScimUserRequestModel + { + UserName = organizationUsers.First().ExternalId, + Emails = emails, + Active = true, + Schemas = new List { ScimConstants.Scim2SchemaUser } + }; + + sutProvider.GetDependency() + .GetManyDetailsByOrganizationAsync(organizationId) + .Returns(organizationUsers); + + await Assert.ThrowsAsync(async () => await sutProvider.Sut.PostUserAsync(organizationId, scimUserRequestModel)); + } +} diff --git a/bitwarden_license/test/Scim.Test/packages.lock.json b/bitwarden_license/test/Scim.Test/packages.lock.json new file mode 100644 index 000000000..8f391f166 --- /dev/null +++ b/bitwarden_license/test/Scim.Test/packages.lock.json @@ -0,0 +1,3320 @@ +{ + "version": 1, + "dependencies": { + "net6.0": { + "coverlet.collector": { + "type": "Direct", + "requested": "[3.1.2, )", + "resolved": "3.1.2", + "contentHash": "wuLDIDKD5XMt0A7lE31JPenT7QQwZPFkP5rRpdJeblyXZ9MGLI8rYjvm5fvAKln+2/X+4IxxQDxBtwdrqKNLZw==" + }, + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[17.1.0, )", + "resolved": "17.1.0", + "contentHash": "MVKvOsHIfrZrvg+8aqOF5dknO/qWrR1sWZjMPQ1N42MKMlL/zQL30FQFZxPeWfmVKWUWAOmAHYsqB5OerTKziw==", + "dependencies": { + "Microsoft.CodeCoverage": "17.1.0", + "Microsoft.TestPlatform.TestHost": "17.1.0" + } + }, + "NSubstitute": { + "type": "Direct", + "requested": "[4.3.0, )", + "resolved": "4.3.0", + "contentHash": "c0nY4GGSe5KidQemTk+CTuDLdv7hLvHHftH6vRbKoYb6bw07wzJ6DdgA0NWrwbW3xjmp/ByEskCsUEWAaMC20g==", + "dependencies": { + "Castle.Core": "4.4.1" + } + }, + "xunit": { + "type": "Direct", + "requested": "[2.4.1, )", + "resolved": "2.4.1", + "contentHash": "XNR3Yz9QTtec16O0aKcO6+baVNpXmOnPUxDkCY97J+8krUYxPvXT1szYYEUdKk4sB8GOI2YbAjRIOm8ZnXRfzQ==", + "dependencies": { + "xunit.analyzers": "0.10.0", + "xunit.assert": "[2.4.1]", + "xunit.core": "[2.4.1]" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[2.4.3, )", + "resolved": "2.4.3", + "contentHash": "kZZSmOmKA8OBlAJaquPXnJJLM9RwQ27H7BMVqfMLUcTi9xHinWGJiWksa3D4NEtz0wZ/nxd2mogObvBgJKCRhQ==" + }, + "AspNetCoreRateLimit": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "FzXAJFgaRjKfnKAVwjEEC7OAGQM5v/I3sQw2tpzmR0yHTCGhUAxZzDuwZiXTk8XLrI6vovzkqKkfKmiDl3nYMg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.1", + "Microsoft.Extensions.Options": "6.0.0", + "Newtonsoft.Json": "13.0.1" + } + }, + "AspNetCoreRateLimit.Redis": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "CsSGy/7SXt6iBOKg0xCvsRjb/ZHshbtr2Of1MHc912L2sLnZqadUrTboyXZC+ZlgEBeJ14GyjPTu8ZyfEhGUnw==", + "dependencies": { + "AspNetCoreRateLimit": "4.0.2", + "StackExchange.Redis": "2.5.43" + } + }, + "AutoFixture": { + "type": "Transitive", + "resolved": "4.17.0", + "contentHash": "efMRCG3Epc4QDELwdmQGf6/caQUleRXPRCnLAq5gLMpTuOTcOQWV12vEJ8qo678Rj97/TjjxHYu/34rGkXdVAA==", + "dependencies": { + "Fare": "[2.1.1, 3.0.0)", + "System.ComponentModel.Annotations": "4.3.0" + } + }, + "AutoFixture.AutoNSubstitute": { + "type": "Transitive", + "resolved": "4.17.0", + "contentHash": "iWsRiDQ7T8s6F4mvYbSvPTq0GDtxJD6D+E1Fu9gVbHUvJiNikC1yIDNTH+3tQF7RK864HH/3R8ETj9m2X8UXvg==", + "dependencies": { + "AutoFixture": "4.17.0", + "NSubstitute": "[2.0.3, 5.0.0)" + } + }, + "AutoFixture.Xunit2": { + "type": "Transitive", + "resolved": "4.17.0", + "contentHash": "lrURL/LhJLPkn2tSPUEW8Wscr5LoV2Mr8A+ikn5gwkofex3o7qWUsBswlLw+KCA7EOpeqwZOldp3k91zDF+48Q==", + "dependencies": { + "AutoFixture": "4.17.0", + "xunit.extensibility.core": "[2.2.0, 3.0.0)" + } + }, + "AutoMapper": { + "type": "Transitive", + "resolved": "11.0.0", + "contentHash": "+596AnKykYCk9RxXCEF4GYuapSebQtFVvIA1oVG1rrRkCLAC7AkWehJ0brCfYUbdDW3v1H/p0W3hob7JoXGjMw==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "AutoMapper.Extensions.Microsoft.DependencyInjection": { + "type": "Transitive", + "resolved": "11.0.0", + "contentHash": "0asw5WxdCFh2OTi9Gv+oKyH9SzxwYQSnO8TV5Dd0GggovILzJW4UimP26JAcxc3yB5NnC5urooZ1BBs8ElpiBw==", + "dependencies": { + "AutoMapper": "11.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "AWSSDK.Core": { + "type": "Transitive", + "resolved": "3.7.10.11", + "contentHash": "B+M7ggPC0FogATRPQxDXL0eTusCQtXulW4zCuX39yiHV8+u9MEXRytcAw0ZA3zFBYYx6ovl9lklho6OQo1DRRQ==" + }, + "AWSSDK.SimpleEmail": { + "type": "Transitive", + "resolved": "3.7.0.150", + "contentHash": "rc/4ZnISfbgTfqz5/BWqMHBAzk4R09qfe1xkdJf2jXo44Zn2X72W8IiLLweBtmNhL7d8Tcf6UCtOHYkFwxHvug==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "AWSSDK.SQS": { + "type": "Transitive", + "resolved": "3.7.2.47", + "contentHash": "RPTVBsY333n+aIEqw148Envx9OQkE1/jhjlioNXDP6BrA3fAPN9A+2HoA02c0KSp/sazXYWg8w/kDL8FchH8Dw==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.24.0", + "contentHash": "+/qI1j2oU1S4/nvxb2k/wDsol00iGf1AyJX5g3epV7eOpQEP/2xcgh/cxgKMeFgn3U2fmgSiBnQZdkV+l5y0Uw==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Numerics.Vectors": "4.5.0", + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Extensions.AspNetCore.DataProtection.Blobs": { + "type": "Transitive", + "resolved": "1.2.1", + "contentHash": "wxvkC6DeWThBtaPbsWdicp5Ltya4J8JuhxmZJDQkhnXG7oihfu8RqBV6w/X1nMieuIOq1qQaGTvjx7nEHHfxSQ==", + "dependencies": { + "Azure.Core": "1.14.0", + "Azure.Storage.Blobs": "12.8.0", + "Microsoft.AspNetCore.DataProtection": "2.1.0" + } + }, + "Azure.Identity": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "EycyMsb6rD2PK9P0SyibFfEhvWWttdrYhyPF4f41uzdB/44yQlV+2Wehxyg489Rj6gbPvSPgbKq0xsHJBhipZA==", + "dependencies": { + "Azure.Core": "1.24.0", + "Microsoft.Identity.Client": "4.39.0", + "Microsoft.Identity.Client.Extensions.Msal": "2.19.3", + "System.Memory": "4.5.4", + "System.Security.Cryptography.ProtectedData": "4.7.0", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Storage.Blobs": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "50eRjIhY7Q1JN7kT2MSawDKCcwSb7uRZUkz00P/BLjSg47gm2hxUYsnJPyvzCHntYMbOWzrvaVQTwYwXabaR5Q==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Text.Json": "4.7.2" + } + }, + "Azure.Storage.Common": { + "type": "Transitive", + "resolved": "12.10.0", + "contentHash": "vYkHGzUkdZTace/cDPZLG+Mh/EoPqQuGxDIBOau9D+XWoDPmuUFGk325aXplkFE4JFGpSwoytNYzk/qBCaiHqg==", + "dependencies": { + "Azure.Core": "1.22.0", + "System.IO.Hashing": "6.0.0" + } + }, + "Azure.Storage.Queues": { + "type": "Transitive", + "resolved": "12.9.0", + "contentHash": "jDiyHtsCUCrWNvZW7SjJnJb46UhpdgQrWCbL8aWpapDHlq9LvbvxYpfLh4dfKAz09QiTznLMIU3i+md9+7GzqQ==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, + "BitPay.Light": { + "type": "Transitive", + "resolved": "1.0.1907", + "contentHash": "QTTIgXakHrRNQPxNyH7bZ7frm0bI8N6gRDtiqVyKG/QYQ+KfjN70xt0zQ0kO0zf8UBaKuwcV5B7vvpXtzR9ijg==", + "dependencies": { + "Newtonsoft.Json": "12.0.2" + } + }, + "Braintree": { + "type": "Transitive", + "resolved": "5.12.0", + "contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "System.Xml.XPath.XmlDocument": "4.3.0" + } + }, + "Castle.Core": { + "type": "Transitive", + "resolved": "4.4.1", + "contentHash": "zanbjWC0Y05gbx4eGXkzVycOQqVOFVeCjVsDSyuao9P4mtN1w3WxxTo193NGC7j3o2u3AJRswaoC6hEbnGACnQ==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "System.Collections.Specialized": "4.3.0", + "System.ComponentModel": "4.3.0", + "System.ComponentModel.TypeConverter": "4.3.0", + "System.Diagnostics.TraceSource": "4.3.0", + "System.Dynamic.Runtime": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "Dapper": { + "type": "Transitive", + "resolved": "2.0.123", + "contentHash": "RDFF4rBLLmbpi6pwkY7q/M6UXHRJEOerplDGE5jwEkP/JGJnBauAClYavNKJPW1yOTWRPIyfj4is3EaJxQXILQ==" + }, + "Fare": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "HaI8puqA66YU7/9cK4Sgbs1taUTP1Ssa4QT2PIzqJ7GvAbN1QgkjbRsjH+FSbMh1MJdvS0CIwQNLtFT+KF6KpA==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "Fido2": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "S0Bz1vfcKlO4Jase3AWp5XnQ746psf4oGx5kL+D2A10j1SsjoAOAIIpanSwfi0cEepDHgk1bClcOKY5TjOzGdA==", + "dependencies": { + "Fido2.Models": "3.0.1", + "Microsoft.Extensions.Http": "6.0.0", + "NSec.Cryptography": "22.4.0", + "System.Formats.Cbor": "6.0.0", + "System.IdentityModel.Tokens.Jwt": "6.17.0" + } + }, + "Fido2.AspNet": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "5n5shEXD7RFUyTesjUHGDjkpgES7j4KotQo1GwUcS08k+fx+1tl/zCFHJ9RFDuUwO+S681ZILT2PyA67IPYpaA==", + "dependencies": { + "Fido2": "3.0.1", + "Fido2.Models": "3.0.1" + } + }, + "Fido2.Models": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "mgjcuGETuYSCUEaZG+jQeeuuEMkDLc4GDJHBvKDdOz6oSOWp5adPdWP4btZx7Pi+9fu4szN3JIjJmby67MaILw==" + }, + "Handlebars.Net": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "p60QyeBYpZmcZdIXRMqs9XySIBaxJ0lj3+QD0EJVr4ybTigOTCumXMMin5dPwjo9At1UwkDZ3gGwa1lmGjG6DA==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "Humanizer.Core": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "rsYXB7+iUPP8AHgQ8JP2UZI2xK2KhjcdGr9E6zX3CsZaTLCaw8M35vaAJRo1rfxeaZEVMuXeaquLVCkZ7JcZ5Q==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "IdentityModel": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "System.Text.Encodings.Web": "4.7.0" + } + }, + "IdentityModel.AspNetCore.OAuth2Introspection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==", + "dependencies": { + "IdentityModel": "4.0.0" + } + }, + "IdentityServer4": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==", + "dependencies": { + "IdentityModel": "4.4.0", + "IdentityServer4.Storage": "4.1.2", + "Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0", + "Newtonsoft.Json": "12.0.2" + } + }, + "IdentityServer4.AccessTokenValidation": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==", + "dependencies": { + "IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1", + "Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0" + } + }, + "IdentityServer4.Storage": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==", + "dependencies": { + "IdentityModel": "4.4.0" + } + }, + "Kralizek.AutoFixture.Extensions.MockHttp": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "6zmks7/5mVczazv910N7V2EdiU6B+rY61lwdgVO0o2iZuTI6KI3T+Hgkrjv0eGOKYucq2OMC+gnAc5Ej2ajoTQ==", + "dependencies": { + "AutoFixture": "4.11.0", + "RichardSzalay.MockHttp": "6.0.0" + } + }, + "libsodium": { + "type": "Transitive", + "resolved": "1.0.18.2", + "contentHash": "flArHoVdscSzyV8ZdPV+bqqY2TTFlaN+xZf/vIqsmHI51KVcD/mOdUPaK3n/k/wGKz8dppiktXUqSmf3AXFgig==" + }, + "linq2db": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "6/u1EzQlV25bhN0Ej/I5dLV5Hgxun+ww/TX2VnMBnSVytED2VzQGeFIO/14I624GkfPOtB79x1ooL3F18dAbdw==" + }, + "linq2db.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.11.0", + "contentHash": "mS+L6HyVHP3oJaTuFVZswNmPpTfYleGjDTo2IWBJmYXZpSQ5EPw1DpHzmyLAiQd+93ofy0Ala+9HWzv6/k73ZQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "6.0.5", + "linq2db": "4.4.0" + } + }, + "MailKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "5MTpTqmjqT7HPvYbP3HozRZMth5vSaT0ReN0iM3rAM4CgLI/R1qqtLDDNWGnFFIlcNzeJkZQRJJMkv8cgzWBbA==", + "dependencies": { + "MimeKit": "3.2.0" + } + }, + "Microsoft.AspNetCore.Authentication.JwtBearer": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "joDS3+lD1i9qcdFLWP4D316t3bHpezmTNOzbMIf9ZcRPX4QTuiUutZcQn/kZplf3BiLHqwUChZXxPjCAMKaKAQ==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0" + } + }, + "Microsoft.AspNetCore.Authentication.OpenIdConnect": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0" + } + }, + "Microsoft.AspNetCore.Cryptography.Internal": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "/0FX1OqckMmXAAlsHgBFNymTZuq4nuAOMhiwm6e8CEMi2aOjnMYwiMc7mtvpGTAO0O4C0zwx+iaChxDgvqit2A==" + }, + "Microsoft.AspNetCore.Cryptography.KeyDerivation": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "1Lbwrxg/HRY/nbrkcrB3EUXUYQN8Tkw7Ktgb6/2on2P7ybT5aM59H05gk+OBC8ZTBxwdle9e1tyT3wxEYKw5xw==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "6.0.4" + } + }, + "Microsoft.AspNetCore.DataProtection": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "G+UoMHL0xiyFh30wkL7Bv/XL6eugTAKYhLPS53k1/Me1bYRwOOw+8VL/q0ppq3/yMzpHX+MkExaCTDlYl48FgA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "2.1.0", + "Microsoft.AspNetCore.DataProtection.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.1.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0", + "Microsoft.Extensions.Logging.Abstractions": "2.1.0", + "Microsoft.Extensions.Options": "2.1.0", + "Microsoft.Win32.Registry": "4.5.0", + "System.Security.Cryptography.Xml": "4.5.0", + "System.Security.Principal.Windows": "4.5.0" + } + }, + "Microsoft.AspNetCore.DataProtection.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "2+HVDhUqrnV9+EJNEewSy+Gk4hOVPzLPMpFDZI7kuH7NWxtbNkI6A6gT5lO2/kEPMyM8/iLWtohbOwjpC9rHVw==" + }, + "Microsoft.AspNetCore.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "1TQgBfd/NPZLR2o/h6l5Cml2ZCF5hsyV4h9WEwWwAIavrbdTnaNozGGcTOd4AOgQvogMM9UM1ajflm9Cwd0jLQ==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Http.Abstractions": "2.1.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "YTKMi2vHX6P+WHEVpW/DS+eFHnwivCSMklkyamcK1ETtc/4j8H3VR0kgW8XIBqukNxhD8k5wYt22P7PhrWSXjQ==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "Microsoft.Extensions.Configuration.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Html.Abstractions": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "Y4rs5aMEXY8G7wJo5S3EEt6ltqyOTr/qOeZzfn+hw/fuQj5GppGckMY5psGLETo1U9hcT5MmAhaT5xtusM1b5g==", + "dependencies": { + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "vbFDyKsSYBnxl3+RABtN79b0vsTcG66fDY8vD6Nqvu9uLtSej70Q5NcbGlnN6bJpZci5orSdgFTHMhBywivDPg==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Features": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "UmkUePxRjsQW0j5euFFscBwjvTu25b8+qIK/2fI3GvcqQ+mkwgbWNAT8b/Gkoei1m2bTWC07lSdutuRDPPLcJA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.0" + } + }, + "Microsoft.AspNetCore.Razor": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "V54PIyDCFl8COnTp9gezNHpUNHk7F9UnerGeZy3UfbnwYvfzbo+ipqQmSgeoESH8e0JvKhRTyQyZquW2EPtCmg==", + "dependencies": { + "Microsoft.AspNetCore.Html.Abstractions": "2.2.0" + } + }, + "Microsoft.AspNetCore.Razor.Language": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "6yOBBASGfXMx1fY6hyjvG+oM3eR8vovIehDdEZW7jAV4gKlY4xuAvTm7Iw1fEq7KPunh2VrJwo7oRK1XxUn1OQ==" + }, + "Microsoft.AspNetCore.Razor.Runtime": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "7YqK+H61lN6yj9RiQUko7oaOhKtRR9Q/kBcoWNRemhJdTIWOh1OmdvJKzZrMWOlff3BAjejkPQm+0V0qXk+B1w==", + "dependencies": { + "Microsoft.AspNetCore.Html.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Razor": "2.2.0" + } + }, + "Microsoft.Azure.Amqp": { + "type": "Transitive", + "resolved": "2.4.11", + "contentHash": "7x5fu2f6TLQDDJS0sY5qW8/daFwJaY9O75YvU8RcUfRzbug+9YGjXUBxoRrprgyi0jxdBAMQL05p1s783SOSFQ==", + "dependencies": { + "System.Net.WebSockets.Client": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.Azure.Cosmos": { + "type": "Transitive", + "resolved": "3.24.0", + "contentHash": "QpUe5ho6OzlXwgcJVgAmOR7t3XLC9RI4t8T96RZY61pSOIllPOJdp30L0LwA16tKcqi5r2KayEgWO/MS9fh/6A==", + "dependencies": { + "Azure.Core": "1.3.0", + "Microsoft.Bcl.AsyncInterfaces": "1.0.0", + "Microsoft.Bcl.HashCode": "1.1.0", + "Newtonsoft.Json": "10.0.2", + "System.Buffers": "4.5.1", + "System.Collections.Immutable": "1.7.0", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Memory": "4.5.4", + "System.Numerics.Vectors": "4.5.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3", + "System.Threading.Tasks.Extensions": "4.5.4", + "System.ValueTuple": "4.5.0" + } + }, + "Microsoft.Azure.Cosmos.Table": { + "type": "Transitive", + "resolved": "1.0.8", + "contentHash": "ToeEd1yijM7nQfLYvdFLG//RjKPmfqm45eOm86UAKrxtyGI/CXqP8iL74mzBp6mZ9A/K/ZYA2fVdpH0xHR5Keg==", + "dependencies": { + "Microsoft.Azure.DocumentDB.Core": "2.11.2", + "Microsoft.OData.Core": "7.6.4", + "Newtonsoft.Json": "10.0.2" + } + }, + "Microsoft.Azure.DocumentDB.Core": { + "type": "Transitive", + "resolved": "2.11.2", + "contentHash": "cA8eWrTFbYrkHrz095x4CUGb7wqQgA1slzFZCYexhNwz6Zcn3v+S1yvWMGwGRmRjT0MKU9tYdFWgLfT0OjSycw==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "Newtonsoft.Json": "9.0.1", + "System.Collections.Immutable": "1.3.0", + "System.Collections.NonGeneric": "4.0.1", + "System.Collections.Specialized": "4.0.1", + "System.Diagnostics.TraceSource": "4.0.0", + "System.Dynamic.Runtime": "4.0.11", + "System.Linq.Queryable": "4.0.1", + "System.Net.Http": "4.3.4", + "System.Net.NameResolution": "4.0.0", + "System.Net.NetworkInformation": "4.1.0", + "System.Net.Requests": "4.0.11", + "System.Net.Security": "4.3.2", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Security.SecureString": "4.0.0" + } + }, + "Microsoft.Azure.NotificationHubs": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "C2SssjX3e6/HIo1OCImQDDVOn64d1+gkgEmgxJryzkwixyivJHWH2YIgxZs33pyzVQcZWx5PR2tqLkQ7riSq8Q==", + "dependencies": { + "Microsoft.Extensions.Caching.Memory": "3.1.8", + "Newtonsoft.Json": "12.0.3" + } + }, + "Microsoft.Azure.ServiceBus": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "wyZNJggyFNtKxd+HgvcTiuRYuTjDGi+pgE4RcBvFbfvNiarKr5AOlE4Ne7on1eUJZuMuEa19wN5dj694HlP60A==", + "dependencies": { + "Microsoft.Azure.Amqp": "2.4.11", + "Microsoft.Azure.Services.AppAuthentication": "[1.0.3, 2.0.0)", + "Newtonsoft.Json": "10.0.3", + "System.Diagnostics.DiagnosticSource": "4.5.1", + "System.IdentityModel.Tokens.Jwt": "5.4.0" + } + }, + "Microsoft.Azure.Services.AppAuthentication": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "ywpQaK1klu1IoX4VUf+TBmU4kR71aWNI6O5rEIJU8z28L2xhJhnIm7k2Nf1Zu/PygeuOtt5g0QPCk5+lLltbeQ==", + "dependencies": { + "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.14.2", + "NETStandard.Library": "1.6.1", + "System.Diagnostics.Process": "4.3.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "yuvf07qFWFqtK3P/MRkEKLhn5r2UbSpVueRziSqj0yJQIKFwG1pq9mOayK3zE5qZCTs0CbrwL9M6R8VwqyGy2w==" + }, + "Microsoft.Bcl.HashCode": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "J2G1k+u5unBV+aYcwxo94ip16Rkp65pgWFb0R6zwJipzWNMgvqlWeuI7/+R+e8bob66LnSG+llLJ+z8wI94cHg==" + }, + "Microsoft.CodeAnalysis.Analyzers": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "ojG5pGAhTPmjxRGTNvuszO3H8XPZqksDwr9xLd4Ae/JBjZZdl6GuoLk7uLMf+o7yl5wO0TAqoWcEKkEWqrZE5g==" + }, + "Microsoft.CodeAnalysis.Common": { + "type": "Transitive", + "resolved": "3.8.0", + "contentHash": "8YTZ7GpsbTdC08DITx7/kwV0k4SC6cbBAFqc13cOm5vKJZcEIAh51tNSyGSkWisMgYCr96B2wb5Zri1bsla3+g==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.0.0", + "System.Collections.Immutable": "5.0.0", + "System.Memory": "4.5.4", + "System.Reflection.Metadata": "5.0.0", + "System.Runtime.CompilerServices.Unsafe": "4.7.1", + "System.Text.Encoding.CodePages": "4.5.1", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Microsoft.CodeAnalysis.CSharp": { + "type": "Transitive", + "resolved": "3.8.0", + "contentHash": "hKqFCUSk9TIMBDjiYMF8/ZfK9p9mzpU+slM73CaCHu4ctfkoqJGHLQhyT8wvrYsIg+ufrUWBF8hcJYmyr5rc5Q==", + "dependencies": { + "Microsoft.CodeAnalysis.Common": "[3.8.0]" + } + }, + "Microsoft.CodeAnalysis.CSharp.Workspaces": { + "type": "Transitive", + "resolved": "3.8.0", + "contentHash": "rdEBvPWqe/IIscsnp7OkZ4tQin8khxBcSLyV9tU+sHdw9uW9U0GKL+Dv2rD4voC1bZBaO18Hp+m4Vkyfmaz0OA==", + "dependencies": { + "Humanizer.Core": "2.2.0", + "Microsoft.CodeAnalysis.CSharp": "[3.8.0]", + "Microsoft.CodeAnalysis.Common": "[3.8.0]", + "Microsoft.CodeAnalysis.Workspaces.Common": "[3.8.0]" + } + }, + "Microsoft.CodeAnalysis.Razor": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "s4u/6z/MQ35y/egrXf4WgJlUZf5GGvuba9mZ700dH4XxLBrA9Fw9kFZ8uymoATry7hwz5owvFhBVo+2VnoiGRg==", + "dependencies": { + "Microsoft.AspNetCore.Razor.Language": "5.0.0", + "Microsoft.CodeAnalysis.CSharp": "3.7.0", + "Microsoft.CodeAnalysis.Common": "3.7.0" + } + }, + "Microsoft.CodeAnalysis.Workspaces.Common": { + "type": "Transitive", + "resolved": "3.8.0", + "contentHash": "GPYVydsmOmScOWDJA1LFky7/MkoXpx1JI3lZJShxC+bvVUvL9zVKE8WDZMLsYJ5MAbry2xkZftdfeMpZ+kvLDQ==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "Microsoft.CodeAnalysis.Common": "[3.8.0]", + "System.Composition": "1.0.31" + } + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "0N/ZJ71ncCxQWhgtkEYKOgu2oMHa8h1tsOUbhmIKXF8UwtSUCe4vHAsJ3DVcNWRwNfQzSTy263ZE+QF6MdIhhQ==" + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, + "Microsoft.Data.SqlClient": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "uu8dfrsx081cSbEevWuZAvqdmANDGJkbLBL2G3j0LAZxX1Oy8RCVAaC4Lcuak6jNicWP6CWvHqBTIEmQNSxQlw==", + "dependencies": { + "Azure.Identity": "1.6.0", + "Microsoft.Data.SqlClient.SNI.runtime": "5.0.1", + "Microsoft.Identity.Client": "4.45.0", + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.21.0", + "Microsoft.SqlServer.Server": "1.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Buffers": "4.5.1", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Diagnostics.DiagnosticSource": "5.0.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime.Caching": "5.0.0", + "System.Security.Cryptography.Cng": "5.0.0", + "System.Security.Principal.Windows": "5.0.0", + "System.Text.Encoding.CodePages": "5.0.0", + "System.Text.Encodings.Web": "4.7.2" + } + }, + "Microsoft.Data.SqlClient.SNI.runtime": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "y0X5MxiNdbITJYoafJ2ruaX6hqO0twpCGR/ipiDOe85JKLU8WL4TuAQfDe5qtt3bND5Je26HnrarLSAMMnVTNg==" + }, + "Microsoft.Data.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bui5wPPqq9OwTL5A+YJPcVStTPrOFcLwg/kAVWyqdjrTief4kTK/3bNv0MqUDVNgAUG8pcFbtdc674CIh1F3gw==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "xb10XFoPf/gWu8ik5v7xnVyUY7W21LBOLtT7PidzwYVdnE3aKuQ/bIZLcQuY7rdDNT89/wse2q5FRjm207cIMQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Analyzers": "6.0.12", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.DependencyInjection": "6.0.1", + "Microsoft.Extensions.Logging": "6.0.0", + "System.Collections.Immutable": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Abstractions": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "hvRytAcLhrb35HmtMjYWsNZZLt39ryuN7j04lDchRa9VToreyqgo5gMniTdQ6MfCflxtGnDes65V/Y2pjbEyWg==" + }, + "Microsoft.EntityFrameworkCore.Analyzers": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "ZDUY+KlsIyKdfvIJeNdqRiPExFQ5GRZVdx/Cp52vhpCJRImYv34O0Xfmw2eiLu4qe1jmM2pTzAAFKELaKwtj/w==" + }, + "Microsoft.EntityFrameworkCore.Relational": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "HBtRGHtF0Vf+BIQTkRGiopmE5rLYhj59xPpd17S1tLgYpiHDVbepCuHwh5H63fzjO99Z4tW5wmmEGF7KnD91WQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "2Hutlqt07bnWZFtYqT1lj0otX8ygMyBikysGnfQNF2TK3i5GqSTeJ8tqNi/URiI9II7Cyl15A0rflXmFoySuIw==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Sqlite.Core": "6.0.12", + "SQLitePCLRaw.bundle_e_sqlite3": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "07vKE7+t9Z2BfGmHuJwNZNv8m1GWt7ZpYYHFh1tQg1oC6FJ78bSaFzLawsf2NK6CLhbB8DBsjE0rRhxMJ4rXsA==", + "dependencies": { + "Microsoft.Data.Sqlite.Core": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Microsoft.Extensions.DependencyModel": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bcz5sSFJbganH0+YrfvIjJDIcKNW7TL07C4d1eTmXy/wOt52iz4LVogJb6pazs7W0+74j0YpXFErvp++Aq5Bsw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.Memory": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "B4y+Cev05eMcjf1na0v9gza6GUtahXbtY1JCypIgx3B4Ea/KAgsWyXEmW4q6zMbmTMtKzmPVk09rvFJirvMwTg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.StackExchangeRedis": { + "type": "Transitive", + "resolved": "6.0.6", + "contentHash": "bdVQpYm1hcHf0pyAypMjtDw3HjWQJ89UzloyyF1OBs56QlgA1naM498tP2Vjlho5vVRALMGPYzdRKCen8koubw==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "StackExchange.Redis": "2.2.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "tq2wXyh3fL17EMF2bXgRhU7JrbO3on93MRKYxzz4JzzvuGSA1l0W3GI9/tl8EO89TH+KWEymP7bcFway6z9fXg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "IznHHzGUtrdpuQqIUdmzF6TYPcsYHONhHh3o9dGp39sX/9Zfmt476UnhvU0UhXgJnXXAikt/MpN6AuSLCCMdEQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.0.0" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "pnyXV1LFOsYjGveuC07xp0YHIyGq7jRq5Ncb5zrrIieMLWVwgMyYxcOH0jTnBedDT4Gh1QinSqsjqzcieHk1og==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "V4Dth2cYMZpw3HhGw9XUDIijpI6gN+22LDt0AhufIgOppCUfpWX4483OmN+dFXRJkJLc8Tv0Q8QK+1ingT2+KQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GJGery6QytCzS/BxJ96klgG9in3uH26KcUBbiVG/coNDXCRq6LGVVlUT4vXq34KPuM+R2av+LeYdX9h4IZOCUg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "Fy8yr4V6obi7ZxvKYI1i85jqtwMq8tqyxQVZpRSkgeA8enqy/KvBIMdcuNdznlxQMZa72mvbHqb7vbg4Pyx95w==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "vWXPg3HJQIpZkENn1KWq8SfbqVujVD7S7vIAyFXXqK5xkf1Vho+vG0bLBCHxU36lD1cLLtmGpfYf0B3MYFi9tQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.DependencyModel": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "TD5QHg98m3+QhgEV1YVoNMl5KtBw/4rjfxLHO0e/YV9bPUBDKntApP4xdrVtGgCeQZHVfC2EXIGsdpRNrr87Pg==", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "3.1.8", + "contentHash": "7ZJUKwPipkDvuv2KJPZ3r01wp2AWNMiYH+61i0dL89F7QICknjKpWgLKLpTSUYFgl77S3b4264I6i4HzDdrb2A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.8", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.FileProviders.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "15+pa2G0bAMHbHewaQIdr/y6ag2H3yh4rd9hTXavtWDzQBkvpe2RMqFg8BxDpcQWssmjmBApGPcw93QRz6YcMg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Core": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "8vBsyGkA8ZI3lZvm1nf+9ynRC/TzPD+UtbdgTlKk+cz+AW5I41LrK8f/adGej5uXgprOA2DMjZw33vZG6vyXxA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Stores": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "linRCnWBfnqg8qjrd9u/KMISy8O4a6X/GRhpHXU0ar654YQw9LJ/Ht+psx8QLqSX5EsCBbBCZzuamatH2FWIyQ==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Identity.Core": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y/lGICwO27fCkQRK3tZseVzFjZaxfGmui990E67sB4MuiPzdJHnJDS/BeYWrHShSSBgCl4KyKRx4ux686fftPg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.0.0", + "Microsoft.Extensions.Options": "2.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Identity.Client": { + "type": "Transitive", + "resolved": "4.45.0", + "contentHash": "ircobISCLWbtE5eEoLKU+ldfZ8O41vg4lcy38KRj/znH17jvBiAl8oxcyNp89CsuqE3onxIpn21Ca7riyDDrRw==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.18.0" + } + }, + "Microsoft.Identity.Client.Extensions.Msal": { + "type": "Transitive", + "resolved": "2.19.3", + "contentHash": "zVVZjn8aW7W79rC1crioDgdOwaFTQorsSO6RgVlDDjc7MvbEGz071wSNrjVhzR0CdQn6Sefx7Abf1o7vasmrLg==", + "dependencies": { + "Microsoft.Identity.Client": "4.38.0", + "System.Security.Cryptography.ProtectedData": "4.5.0" + } + }, + "Microsoft.IdentityModel.Abstractions": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "XeE6LQtD719Qs2IG7HDi1TSw9LIkDbJ33xFiOBoHbApVw/8GpIBCbW+t7RwOjErUDyXZvjhZliwRkkLb8Z1uzg==" + }, + "Microsoft.IdentityModel.Clients.ActiveDirectory": { + "type": "Transitive", + "resolved": "3.14.2", + "contentHash": "TNsJJMiRnkeby1ovThVoV9yFsPWjAdluwOA+Nf0LtSsBVVrKQv8Qp4kYOgyNwMVj+pDwbhXISySk+4HyHVWNZQ==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "System.Runtime.Serialization.Json": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.IdentityModel.JsonWebTokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "d3h1/BaMeylKTkdP6XwRCxuOoDJZ44V9xaXr6gl5QxmpnZGdoK3bySo3OQN8ehRLJHShb94ElLUvoXyglQtgAw==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "tuEhHIQwvBEhMf8I50hy8FHmRSUkffDFP5EdLsSDV4qRcl2wvOPkQxYqEzWkh+ytW6sbdJGEXElGhmhDfAxAKg==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "0FqY5cTLQKtHrClzHEI+QxJl8OBT2vUiEQQB7UKk832JDiJJmetzYZ3AdSrPjN/3l3nkhByeWzXnhrX0JbifKg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "vtSKL7n6EnAsLyxmiviusm6LKrblT2ndnNqN6rvVq6iIHAnPCK9E2DkDx6h1Jrpy1cvbp40r0cnTg23nhEAGTA==", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "6.21.0", + "System.IdentityModel.Tokens.Jwt": "6.21.0" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "AAEHZvZyb597a+QJSmtxH3n2P1nIJGpZ4Q89GTenknRx6T6zyfzf592yW/jA5e8EHN4tNMjjXHQaYWEq5+L05w==", + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "Microsoft.IdentityModel.Logging": "6.21.0", + "System.Security.Cryptography.Cng": "4.5.0" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.OData.Core": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "/EjnJezMBjXf8OjcShhGzPY7pOO0CopgoZGhS6xsP3t2uhC+O72IBHgtQ7F3v1rRXWVtJwLGhzE1GfJUlx3c4Q==", + "dependencies": { + "Microsoft.OData.Edm": "[7.6.4]", + "Microsoft.Spatial": "[7.6.4]" + } + }, + "Microsoft.OData.Edm": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "MSSmA6kIfpgFTtNpOnnayoSj/6KSzHC1U9KOjF7cTA1PG4tZ7rIMi1pvjFc8CmYEvP4cxGl/+vrCn+HpK26HTQ==" + }, + "Microsoft.Spatial": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "3mB+Frn4LU4yb5ie9R752QiRn0Hvp9PITkSRofV/Lzm9EyLM87Fy9ziqgz75O/c712dh6GxuypMSBUGmNFwMeA==" + }, + "Microsoft.SqlServer.Server": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug==" + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "OMo/FYnKGy3lZEK0gfitskRM3ga/YBt6MyCyFPq0xNLeybGOQ6HnYNAAvzyePo5WPuMiw3LX+HiuRWNjnas1fA==", + "dependencies": { + "NuGet.Frameworks": "5.11.0", + "System.Reflection.Metadata": "1.6.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "JS0JDLniDhIzkSPLHz7N/x1CG8ywJOtwInFDYA3KQvbz+ojGoT5MT2YDVReL1b86zmNRV8339vsTSm/zh0RcMg==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.1.0", + "Newtonsoft.Json": "9.0.1" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "YUah81QG5q/ViVbr1BZcTbDLNJ5/k84fr+xx3/IoDVJR8KEUm89HmPAGM+FMMyWOjit+CIVpyOq7yEmRBBWXxQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore": "5.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Contracts": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "34v6AkkRJykgFq7rHwNbzXBsLFquevLuegM9XDQl2j+wyOfj+ql1++jUR1WdZoPkv04WoM09mD47S3lMzJmHrQ==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "System.Collections.Immutable": "1.7.0" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Core": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "R7mrxvTtv/MiEH42OtHYi/3L0A/vaAH8mwg+3yAyQtVuy6v9CeeVyL30lfTQ7EYV4ezUmuQKFwfjcU6PP0/KSQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.VisualStudio.Web.CodeGeneration.Templating": "5.0.2", + "Newtonsoft.Json": "11.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Design": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "9eTZV7W+S2iO2AJD03xXyXJZ+Nf71Y25gMXhqyXb8bB63jPfn+VQhV8I1lb6J+NR3jW98m5EB9QBftBSrjgiYQ==", + "dependencies": { + "Microsoft.VisualStudio.Web.CodeGenerators.Mvc": "5.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "f9XeBRS9ICosrCpbO9jnAVMd/ISLhaZgx388XNBjigiyBJuq577J6tQgQWZA8PQTiPj6MKe9HVIW2GnKXDiUrQ==", + "dependencies": { + "Microsoft.VisualStudio.Web.CodeGeneration.Core": "5.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Templating": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "P3z/JZTGP5DhSc8ik4xrimWuCZ2ZaEZ6q7WGgfgmSVibfXxwh2Oo+dtdkiXwq8MNlkrcP0AZAo3+1wowYUzluA==", + "dependencies": { + "Microsoft.AspNetCore.Razor.Language": "5.0.0", + "Microsoft.AspNetCore.Razor.Runtime": "2.2.0", + "Microsoft.CodeAnalysis.CSharp": "3.8.0", + "Microsoft.CodeAnalysis.Razor": "5.0.0", + "Microsoft.VisualStudio.Web.CodeGeneration.Utils": "5.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGeneration.Utils": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "4zViWGIFeKsGxDmc5xpn2G8kWs2FSHiLOolw85ZPHihDXc2jiFKp7qjA3SRt8U23kR3zeb0vZiFlETxgTHwAUA==", + "dependencies": { + "Microsoft.CodeAnalysis.CSharp.Workspaces": "3.8.0", + "Microsoft.VisualStudio.Web.CodeGeneration.Contracts": "5.0.2", + "Newtonsoft.Json": "11.0.2" + } + }, + "Microsoft.VisualStudio.Web.CodeGenerators.Mvc": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "W4Uk2y0oja+4E+XP5d5OFu+ViTEtlqm3a6nYuuC3tjA+lTK6dLaMf0G6WnO4BO18i0kM0l49XjTwwXd5XpjnAQ==", + "dependencies": { + "Microsoft.VisualStudio.Web.CodeGeneration": "5.0.2" + } + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "Microsoft.Win32.Registry": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "Microsoft.Win32.SystemEvents": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==" + }, + "MimeKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "l9YHMBhBUwY7qQHUp8fw0EvjcbmhN4Iggz6MdjqIShBf42+0nJTa5gu0kuupCOPuiARc9ZaS9c9f0gKz4OnxKw==", + "dependencies": { + "Portable.BouncyCastle": "1.9.0", + "System.Security.Cryptography.Pkcs": "6.0.0" + } + }, + "MySqlConnector": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "JVokQTUNN3WHAu9Vw8ieeq1dXTFokJiig5P0VJ4f439UxRrsPo6SaVWC8Zdm6mkPeQFhZ0/9afdWa02EY/1j/w==" + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "Npgsql": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "wKa8MJEJaj0xQXUQZGv7q/KfPID23jSSvFFtljMworrv7dNajr0GN8PCU1SpywqHjMWdYEfK29DY1aYbiISbQg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Npgsql.EntityFrameworkCore.PostgreSQL": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "YJRpO+3wXQyWuwRUCVJj/Rsn46sY0bZ6uCGOEFApiRe0ZYJ6N6TxZUWKbTNJYjesickcLGzynOerpSbDJX1AYg==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Npgsql": "6.0.8" + } + }, + "NSec.Cryptography": { + "type": "Transitive", + "resolved": "22.4.0", + "contentHash": "lEntcPYd7h3aZ8xxi/y/4TML7o8w0GEGqd+w4L1omqFLbdCBmhxJAeO2YBmv/fXbJKgKCQLm7+TD4bR605PEUQ==", + "dependencies": { + "libsodium": "[1.0.18.2, 1.0.19)" + } + }, + "NuGet.Frameworks": { + "type": "Transitive", + "resolved": "5.11.0", + "contentHash": "eaiXkUjC4NPcquGWzAGMXjuxvLwc6XGKMptSyOGQeT0X70BUZObuybJFZLA0OfTdueLd3US23NBPTBb6iF3V1Q==" + }, + "Otp.NET": { + "type": "Transitive", + "resolved": "1.2.2", + "contentHash": "2hrZfkbzeWJ3tNXXt/1beg4IY+nS4F3gIfh4NVFvW0f6Pj51hGpiJ4prBz7Dmrr4ZYrA96rTERVGieZ4xYm7jA==" + }, + "Pipelines.Sockets.Unofficial": { + "type": "Transitive", + "resolved": "2.2.2", + "contentHash": "Bhk0FWxH1paI+18zr1g5cTL+ebeuDcBCR+rRFO+fKEhretgjs7MF2Mc1P64FGLecWp4zKCUOPzngBNrqVyY7Zg==", + "dependencies": { + "System.IO.Pipelines": "5.0.1" + } + }, + "Pomelo.EntityFrameworkCore.MySql": { + "type": "Transitive", + "resolved": "6.0.2", + "contentHash": "KvlZ800CnEuEGnxj5OT1fCKGjQXxW5kpPlCP91JqBYG+2Z3927eqXmlX6LLKUt4swqE8ZsEQ+Zkpab8bqstf4g==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "[6.0.7, 7.0.0)", + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "MySqlConnector": "2.1.2" + } + }, + "Portable.BouncyCastle": { + "type": "Transitive", + "resolved": "1.9.0", + "contentHash": "eZZBCABzVOek+id9Xy04HhmgykF0wZg9wpByzrWN7q8qEI0Qen9b7tfd7w8VA3dOeesumMG7C5ZPy0jk7PSRHw==" + }, + "Quartz": { + "type": "Transitive", + "resolved": "3.4.0", + "contentHash": "N8350OAlQhd8zKg0ARFikGjh3bfAW/CF/KVxu2fTIlAALB/oC1eg54n/QAPYR5ryHuYyDr5G8/Qa4k+D/7OFRQ==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "RichardSzalay.MockHttp": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bStGNqIX/MGYtML7K3EzdsE/k5HGVAcg7XgN23TQXGXqxNC9fvYFR94fA0sGM5hAT36R+BBGet6ZDQxXL/IPxg==" + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" + }, + "SendGrid": { + "type": "Transitive", + "resolved": "9.27.0", + "contentHash": "kMyXRQ8hmN2bG3tYZ7T31Ufl1kXkpuP5+WBh1BJ32WY31DTnBTCVGURoIqfbTo/tRuQfAYLxra6C8cQGN6kk+A==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "starkbank-ecdsa": "[1.3.3, 2.0.0)" + } + }, + "Sentry": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "Pkw4+51EDUQ0X02jdCZIpaM2Q4UO06VKGDE+dYYNxgvOirRXGKTKxRk4NPKJTLSTNl+2JyT9HoE7C6BTlYhLOw==" + }, + "Sentry.Serilog": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "GFTVfQdOFqZ9Vmo8EEZTx1EQMDRJjka/4v2CwxnAUh+sqHDICga4eOm4AyGzDBbE4s9iAHMgMUCceIqo+7z84w==", + "dependencies": { + "Sentry": "3.16.0", + "Serilog": "2.10.0" + } + }, + "Serilog": { + "type": "Transitive", + "resolved": "2.10.0", + "contentHash": "+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA==" + }, + "Serilog.AspNetCore": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "/JO/txIxRR61x1UXQAgUzG2Sx05o1QHCkokVBWrKzmAoDu+p5EtCAj7L/TVVg7Ezhh3GPiZ0JI9OJCmRO9tSRw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.Extensions.Logging": "5.0.0", + "Serilog": "2.10.0", + "Serilog.Extensions.Hosting": "4.2.0", + "Serilog.Formatting.Compact": "1.1.0", + "Serilog.Settings.Configuration": "3.3.0", + "Serilog.Sinks.Console": "4.0.1", + "Serilog.Sinks.Debug": "2.0.0", + "Serilog.Sinks.File": "5.0.0" + } + }, + "Serilog.Extensions.Hosting": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "gT2keceCmPQR9EX0VpXQZvUgELdfE7yqJ7MOxBhm3WLCblcvRgswEOOTgok/DHObbM15A3V/DtF3VdVDQPIZzQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.Hosting.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8", + "Serilog": "2.10.0", + "Serilog.Extensions.Logging": "3.1.0" + } + }, + "Serilog.Extensions.Logging": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "IWfem7wfrFbB3iw1OikqPFNPEzfayvDuN4WP7Ue1AVFskalMByeWk3QbtUXQR34SBkv1EbZ3AySHda/ErDgpcg==", + "dependencies": { + "Microsoft.Extensions.Logging": "2.0.0", + "Serilog": "2.9.0" + } + }, + "Serilog.Extensions.Logging.File": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "usO0qr4v9VCMBWiTJ1nQmAbPNCt40FrkDol6CpfCXbsxGZS/hH+YCueF7vvPQ32ATI0GWcMWiKRdjXEE7/HxTQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Serilog": "2.5.0", + "Serilog.Extensions.Logging": "2.0.2", + "Serilog.Formatting.Compact": "1.0.0", + "Serilog.Sinks.Async": "1.1.0", + "Serilog.Sinks.RollingFile": "3.3.0" + } + }, + "Serilog.Formatting.Compact": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "pNroKVjo+rDqlxNG5PXkRLpfSCuDOBY0ri6jp9PLe505ljqwhwZz8ospy2vWhQlFu5GkIesh3FcDs4n7sWZODA==", + "dependencies": { + "Serilog": "2.8.0" + } + }, + "Serilog.Settings.Configuration": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "7GNudISZwqaT902hqEL2OFGTZeUFWfnrNLupJkOqeF41AR3GjcxX+Hwb30xb8gG2/CDXsCMVfF8o0+8KY0fJNg==", + "dependencies": { + "Microsoft.Extensions.DependencyModel": "3.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "2.0.0", + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Async": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "xll0Kanz2BkCxuv+F3p1WXr47jdsVM0GU1n1LZvK+18QiRZ/WGFNxSNw9EMKFV5ED5gr7MUpAe6PCMNL1HGUMA==", + "dependencies": { + "Serilog": "2.1.0", + "System.Collections.Concurrent": "4.0.12" + } + }, + "Serilog.Sinks.AzureCosmosDB": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Im2/ZqjXQIpsd727qEo5Pq+br0MiNVuTvI40Yk7736tgjCpEx+omPHv4+c4fEAxnOP2kL9Ge6UoDFoDw3cjF2A==", + "dependencies": { + "Microsoft.Azure.Cosmos": "3.24.0", + "Microsoft.CSharp": "4.7.0", + "Newtonsoft.Json": "13.0.1", + "Serilog": "2.10.0", + "Serilog.Sinks.PeriodicBatching": "2.3.1" + } + }, + "Serilog.Sinks.Console": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Debug": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y6g3OBJ4JzTyyw16fDqtFcQ41qQAydnEvEqmXjhwhgjsnG/FaJ8GUqF5ldsC/bVkK8KYmqrPhDO+tm4dF6xx4A==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.File": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.PeriodicBatching": { + "type": "Transitive", + "resolved": "2.3.1", + "contentHash": "LVYvqpqjSTD8dhfxRnzpxTs8/ys3V2q01MvaY3r0eKsDgpKK1U1y/5N6gFHgiesbxG0V+O5IWdz4+c1DzoNyOQ==", + "dependencies": { + "Serilog": "2.0.0" + } + }, + "Serilog.Sinks.RollingFile": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "2lT5X1r3GH4P0bRWJfhA7etGl8Q2Ipw9AACvtAHWRUSpYZ42NGVyHoVs2ALBZ/cAkkS+tA4jl80Zie144eLQPg==", + "dependencies": { + "Serilog.Sinks.File": "3.2.0", + "System.IO": "4.1.0", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Serilog.Sinks.SyslogMessages": { + "type": "Transitive", + "resolved": "2.0.6", + "contentHash": "V2Yq2GEbk7taEPbpBLFzLXhrHrUzKf4sQu/zLrANU8XIoUn/Mr08M2E8PrcrWVXCj0R4xLMWYe0Z1sxOrMF3IA==", + "dependencies": { + "Serilog": "2.5.0", + "Serilog.Sinks.PeriodicBatching": "2.3.0" + } + }, + "SQLitePCLRaw.bundle_e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "ilkvNhrTersLmIVAcDwwPqfhUFCg19Z1GVMvCSi3xk6Akq94f4qadLORQCq/T8+9JgMiPs+F/NECw5uauviaNw==", + "dependencies": { + "SQLitePCLRaw.lib.e_sqlite3": "2.1.2", + "SQLitePCLRaw.provider.e_sqlite3": "2.1.2" + } + }, + "SQLitePCLRaw.core": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "A8EBepVqY2lnAp3a8jnhbgzF2tlj2S3HcJQGANTYg/TbYbKa8Z5cM1h74An/vy0svhfzT7tVY0sFmUglLgv+2g==", + "dependencies": { + "System.Memory": "4.5.3" + } + }, + "SQLitePCLRaw.lib.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "zibGtku8M4Eea1R3ZCAxc86QbNvyEN17mAcQkvWKBuHvRpMiK2g5anG4R5Be7cWKSd1i6baYz8y4dMMAKcXKPg==" + }, + "SQLitePCLRaw.provider.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "lxCZarZdvAsMl2zw9bXHrXK6RxVhB4b23iTFhCOdHFhxfbsxLxWf+ocvswJwR/9Wh/E//ddMi+wJGqUKV7VwoA==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "StackExchange.Redis": { + "type": "Transitive", + "resolved": "2.5.43", + "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "dependencies": { + "Pipelines.Sockets.Unofficial": "2.2.2", + "System.Diagnostics.PerformanceCounter": "5.0.0" + } + }, + "starkbank-ecdsa": { + "type": "Transitive", + "resolved": "1.3.3", + "contentHash": "OblOaKb1enXn+dSp7tsx9yjwV+/BEKM9jFhshIkZTwCk7LuTFTp+wSon6rFzuPiIiTGtvVWQNUw2slHjGktJog==" + }, + "Stripe.net": { + "type": "Transitive", + "resolved": "40.0.0", + "contentHash": "SD1bGiF+sVQG3p2LXNTZ5rEG2aCnXIHokcxYS9yyW3dR01J0ryf+iNFOwid148yePZ0gCBcRxj3wiW1mTmP7UQ==", + "dependencies": { + "Newtonsoft.Json": "12.0.3", + "System.Configuration.ConfigurationManager": "6.0.0" + } + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Collections.NonGeneric": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "prtjIEMhGUnQq6RnPEYLpFt8AtLbp9yq2zxOSrY7KJJZrw25Fi97IzBqY7iqssbM61Ek5b8f3MG/sG1N2sN5KA==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Collections.Specialized": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Epx8PoVZR0iuOnJJDzp7pWvdfMMOAvpUo95pC4ScH2mJuXkKA2Y4aR3cG9qt2klHgSons1WFh4kcGW7cSXvrxg==", + "dependencies": { + "System.Collections.NonGeneric": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.ComponentModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VyGn1jGRZVfxnh8EdvDCi71v3bMXrsu8aYJOwoV7SNDLVhiEqwP86pPMyRGsDsxhXAm2b3o9OIqeETfN5qfezw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.ComponentModel.Annotations": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "SY2RLItHt43rd8J9D8M8e8NM4m+9WLN2uUd9G0n1I4hj/7w+v3pzK6ZBjexlG1/2xvLKQsqir3UGVSyBTXMLWA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.ComponentModel": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.ComponentModel.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "j8GUkCpM8V4d4vhLIIoBLGey2Z5bCkMVNjEZseyAlm4n5arcsJOeI3zkUP+zvZgzsbLTYh4lYeP/ZD/gdIAPrw==", + "dependencies": { + "System.ComponentModel": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.ComponentModel.TypeConverter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "16pQ6P+EdhcXzPiEK4kbA953Fu0MNG2ovxTZU81/qsCd1zPRsKc3uif5NgvllCY598k6bI0KUyKW8fanlfaDQg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Collections.NonGeneric": "4.3.0", + "System.Collections.Specialized": "4.3.0", + "System.ComponentModel": "4.3.0", + "System.ComponentModel.Primitives": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Composition": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "I+D26qpYdoklyAVUdqwUBrEIckMNjAYnuPJy/h9dsQItpQwVREkDFs4b4tkBza0kT2Yk48Lcfsv2QQ9hWsh9Iw==", + "dependencies": { + "System.Composition.AttributedModel": "1.0.31", + "System.Composition.Convention": "1.0.31", + "System.Composition.Hosting": "1.0.31", + "System.Composition.Runtime": "1.0.31", + "System.Composition.TypedParts": "1.0.31" + } + }, + "System.Composition.AttributedModel": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "NHWhkM3ZkspmA0XJEsKdtTt1ViDYuojgSND3yHhTzwxepiwqZf+BCWuvCbjUt4fe0NxxQhUDGJ5km6sLjo9qnQ==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Composition.Convention": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "GLjh2Ju71k6C0qxMMtl4efHa68NmWeIUYh4fkUI8xbjQrEBvFmRwMDFcylT8/PR9SQbeeL48IkFxU/+gd0nYEQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Composition.AttributedModel": "1.0.31", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Composition.Hosting": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "fN1bT4RX4vUqjbgoyuJFVUizAl2mYF5VAb+bVIxIYZSSc0BdnX+yGAxcavxJuDDCQ1K+/mdpgyEFc8e9ikjvrg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Composition.Runtime": "1.0.31", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Composition.Runtime": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "0LEJN+2NVM89CE4SekDrrk5tHV5LeATltkp+9WNYrR+Huiyt0vaCqHbbHtVAjPyeLWIc8dOz/3kthRBj32wGQg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Composition.TypedParts": { + "type": "Transitive", + "resolved": "1.0.31", + "contentHash": "0Zae/FtzeFgDBBuILeIbC/T9HMYbW4olAmi8XqqAGosSOWvXfiQLfARZEhiGd0LVXaYgXr0NhxiU1LldRP1fpQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Composition.AttributedModel": "1.0.31", + "System.Composition.Hosting": "1.0.31", + "System.Composition.Runtime": "1.0.31", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "6.0.0", + "System.Security.Permissions": "6.0.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Diagnostics.PerformanceCounter": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "kcQWWtGVC3MWMNXdMDWfrmIlFZZ2OdoeT6pSNVRtk9+Sa7jwdPiMlNwb0ZQcS7NRlT92pCfmjRtkSWUW3RAKwg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.Diagnostics.Process": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "J0wOX07+QASQblsfxmIMFc9Iq7KTXYL3zs2G/Xc704Ylv3NpuVdo6gij6V3PGiptTxqsK0K7CdXenRvKUnkA2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "Microsoft.Win32.Registry": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.TraceSource": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VnYp1NxGx8Ww731y2LJ1vpfb/DKVNKEZ8Jsh5SgQTZREL/YpWRArgh9pI8CDLmgHspZmLL697CaLvH85qQpRiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Drawing.Common": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + } + }, + "System.Dynamic.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "SNVi1E/vfWUAs/WYKhE9+qlS6KqK0YVhnlT0HQtr8pMIA8YX3lwy3uPMownDwdYISBdmAF/2holEIldVp85Wag==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Formats.Asn1": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==" + }, + "System.Formats.Cbor": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "mGaLOoiw7KurJagOOcIsWUoCT5ACIiGxKlCcbYQASefBGXjnCcKTq5Hdjb94eEAKg38zXKlHw4c6EjzgBl9dIw==" + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IdentityModel.Tokens.Jwt": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "JRD8AuypBE+2zYxT3dMJomQVsPYsCqlyZhWel3J1d5nzQokSRyTueF+Q4ID3Jcu6zSZKuzOdJ1MLTkbQsDqcvQ==", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Rfm2jYCaUeGysFEZjDe7j1R4x6Z6BzumS/vUT5a1AA/AWJuGX71PoGB0RmpyX3VmrGqVnAwtfMn39OHR8Y/5+g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "qEePWsaq9LoEEIqhbGe6D5J8c9IqQOUuTzzV6wn1POlfdLkJliZY3OlB0j0f17uMWlqZYjH7txj+2YbyrIA8Yg==" + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Linq.Queryable": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "Yn/WfYe9RoRfmSLvUt2JerP0BTGGykCZkQPgojaxgzF2N0oPo+/AhB8TXOpdCcNlrG3VRtsamtK2uzsp3cqRVw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==", + "dependencies": { + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.6.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.4", + "contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.1", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.NameResolution": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "JdqRdM1Qym3YehqdKIi5LHrpypP4JMfxKQSNCJ2z4WawkG0il+N3XfNeJOxll2XrTnG7WgYYPoeiu/KOwg0DQw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.NetworkInformation": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "Q0rfeiW6QsiZuicGjrFA7cRr2+kXex0JIljTTxzI09GIftB8k+aNL31VsQD1sI2g31cw7UGDTgozA/FgeNSzsQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Linq": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.Sockets": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Overlapped": "4.0.1", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Requests": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "vxGt7C0cZixN+VqoSW4Yakc1Y9WknmxauDqzxgpw/FnBdz4kQNN51l4wxdXX5VY1xjqy//+G+4CvJWp1+f+y6Q==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Net.Http": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Claims": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Security.Principal": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Security": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Net.WebHeaderCollection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "XX2TIAN+wBSAIV51BU2FvvXMdstUa8b0FBSZmDWjZdwUMmggQSifpTOZ5fNH20z9ZCg2fkV1L5SsZnpO2RQDRQ==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0" + } + }, + "System.Net.WebSockets": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", + "dependencies": { + "Microsoft.Win32.Primitives": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.WebSockets.Client": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "NUCcDroX4lCQXgOrzlwIZ1u9YJ0krfyF0wk0ONnyLUmcQoEiYV2/OfUPRqUwQBbpH1BlGApkLgoQUwMqb5+c1g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.2", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Net.WebSockets": "4.0.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.X509Certificates": "4.1.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Numerics.Vectors": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Private.DataContractSerialization": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "lcqFBUaCZxPiUkA4dlSOoPZGtZsAuuElH2XHgLwGLxd7ZozWetV5yiz0qGAV2AUYOqw97MtZBjbLMN16Xz4vXA==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Collections.Concurrent": "4.0.12", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Emit.Lightweight": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1", + "System.Xml.XmlSerializer": "4.0.11" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Caching": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "30D6MkO8WF9jVGWZIP0hmCN8l9BTY4LCsAzLIe4xFSXzs+AjDotR7DpSmj27pFskDURzUvqYYY0ikModgBTxWw==", + "dependencies": { + "System.Configuration.ConfigurationManager": "5.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Runtime.Serialization.Json": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "+7DIJhnKYgCzUgcLbVTtRQb2l1M0FP549XFlFkQM5lmNiUBl44AfNbx4bz61xA8PzLtlYwfmif4JJJW7MPPnjg==", + "dependencies": { + "System.IO": "4.1.0", + "System.Private.DataContractSerialization": "4.1.1", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" + }, + "System.Security.Claims": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Security.Principal": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==", + "dependencies": { + "System.Formats.Asn1": "5.0.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Pkcs": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "elM3x+xSRhzQysiqo85SbidJJ2YbZlnvmh+53TuSZHsD7dNuuEWser+9EFtY+rYupBwkq2avc6ZCO3/6qACgmg==", + "dependencies": { + "System.Formats.Asn1": "6.0.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ==" + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Xml": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "i2Jn6rGXR63J0zIklImGRkDIJL4b1NfPSEbIVHBlqoIb12lfXIigCbDRpDmIEzwSo/v1U5y/rYJdzZYSyCWxvg==", + "dependencies": { + "System.Security.Cryptography.Pkcs": "4.5.0", + "System.Security.Permissions": "4.5.0" + } + }, + "System.Security.Permissions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==", + "dependencies": { + "System.Security.AccessControl": "6.0.0", + "System.Windows.Extensions": "6.0.0" + } + }, + "System.Security.Principal": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, + "System.Security.SecureString": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "sqzq9GD6/b0yqPuMpgIKBuoLf4VKAj8oAfh4kXSzPaN6eoKY3hRi9C5L27uip25qlU+BGPfb0xh2Rmbwc4jFVA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "NyscU59xX6Uo91qvhOs2Ccho3AR2TnZPomo1Z0K6YpyztBPM/A5VbkzOO19sy3A3i1TtEnTxA7bCe3Us+r5MWg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "zaJsHfESQvJ11vbXnNlkrR46IaMULk/gHxYsJphzSF+07kTjPHv+Oc14w6QEOfo3Q4hqLJgStUaYB9DBl0TmWg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Overlapped": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "f7aLuLkBoCQM2kng7zqLFBXz9Gk48gDK8lk1ih9rH/1arJJzZK9gJwNvPDhL6Ps/l6rwOr8jw+4FCHL0KKWiEg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Threading.Thread": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OHmbT+Zz065NKII/ZHcH9XO1dEuLGI1L2k7uYss+9C1jLxTC9kTZZuzUOyXHayRk+dft9CiDf3I/QZ0t8JKyBQ==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading.ThreadPool": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.ValueTuple": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" + }, + "System.Windows.Extensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==", + "dependencies": { + "System.Drawing.Common": "6.0.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "lJ8AxvkX7GQxpC6GFCeBj8ThYVyQczx2+f/cWHJU8tjS7YfI6Cv6bon70jVEgs2CiFbmmM8b9j1oZVx0dSI2Ww==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlSerializer": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "FrazwwqfIXTfq23mfv4zH+BjqkSFNaNFBtjzu3I9NRmG8EELYyrv/fJnttCIwRMFRR/YKXF1hmsMmMEnl55HGw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1" + } + }, + "System.Xml.XPath": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "v1JQ5SETnQusqmS3RwStF7vwQ3L02imIzl++sewmt23VGygix04pEH+FCj1yWb+z4GDzKiljr1W7Wfvrx0YwgA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XPath.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "A/uxsWi/Ifzkmd4ArTLISMbfFs6XpRPsXZonrIqyTY70xi8t+mDtvSM5Os0RqyRDobjMBwIDHDL4NOIbkDwf7A==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XPath": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "xunit.abstractions": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" + }, + "xunit.analyzers": { + "type": "Transitive", + "resolved": "0.10.0", + "contentHash": "4/IDFCJfIeg6bix9apmUtIMwvOsiwqdEexeO/R2D4GReIGPLIRODTpId/l4LRSrAJk9lEO3Zx1H0Zx6uohJDNg==" + }, + "xunit.assert": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "O/Oe0BS5RmSsM+LQOb041TzuPo5MdH2Rov+qXGS37X+KFG1Hxz7kopYklM5+1Y+tRGeXrOx5+Xne1RuqLFQoyQ==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "xunit.core": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "Zsj5OMU6JasNGERXZy8s72+pcheG6Q15atS5XpZXqAtULuyQiQ6XNnUsp1gyfC6WgqScqMvySiEHmHcOG6Eg0Q==", + "dependencies": { + "xunit.extensibility.core": "[2.4.1]", + "xunit.extensibility.execution": "[2.4.1]" + } + }, + "xunit.extensibility.core": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "yKZKm/8QNZnBnGZFD9SewkllHBiK0DThybQD/G4PiAmQjKtEZyHi6ET70QPU9KtSMJGRYS6Syk7EyR2EVDU4Kg==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.abstractions": "2.0.3" + } + }, + "xunit.extensibility.execution": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "7e/1jqBpcb7frLkB6XDrHCGXAbKN4Rtdb88epYxCSRQuZDRW8UtTfdTEVpdTl8s4T56e07hOBVd4G0OdCxIY2A==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.extensibility.core": "[2.4.1]" + } + }, + "YubicoDotNetClient": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "uP5F3Ko1gqZi3lwS2R/jAAwhBxXs/6PKDpS6FdQjsBA5qmF0hQmbtfxM6QHTXOMoWbUtfetG7+LtgmG8T5zDIg==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "common": { + "type": "Project", + "dependencies": { + "AutoFixture.AutoNSubstitute": "[4.17.0, )", + "AutoFixture.Xunit2": "[4.17.0, )", + "Core": "[2023.1.0, )", + "Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )", + "Microsoft.NET.Test.Sdk": "[17.1.0, )", + "NSubstitute": "[4.3.0, )", + "xunit": "[2.4.1, )" + } + }, + "core": { + "type": "Project", + "dependencies": { + "AWSSDK.SQS": "[3.7.2.47, )", + "AWSSDK.SimpleEmail": "[3.7.0.150, )", + "AspNetCoreRateLimit": "[4.0.2, )", + "AspNetCoreRateLimit.Redis": "[1.0.1, )", + "Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.2.1, )", + "Azure.Storage.Blobs": "[12.11.0, )", + "Azure.Storage.Queues": "[12.9.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "Fido2.AspNet": "[3.0.1, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "MailKit": "[3.2.0, )", + "Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )", + "Microsoft.Azure.Cosmos.Table": "[1.0.8, )", + "Microsoft.Azure.NotificationHubs": "[4.1.0, )", + "Microsoft.Azure.ServiceBus": "[5.2.0, )", + "Microsoft.Data.SqlClient": "[5.0.1, )", + "Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )", + "Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )", + "Microsoft.Extensions.Identity.Stores": "[6.0.4, )", + "Newtonsoft.Json": "[13.0.1, )", + "Otp.NET": "[1.2.2, )", + "Quartz": "[3.4.0, )", + "SendGrid": "[9.27.0, )", + "Sentry.Serilog": "[3.16.0, )", + "Serilog.AspNetCore": "[5.0.0, )", + "Serilog.Extensions.Logging": "[3.1.0, )", + "Serilog.Extensions.Logging.File": "[2.0.0, )", + "Serilog.Sinks.AzureCosmosDB": "[2.0.0, )", + "Serilog.Sinks.SyslogMessages": "[2.0.6, )", + "Stripe.net": "[40.0.0, )", + "YubicoDotNetClient": "[1.2.0, )" + } + }, + "infrastructure.dapper": { + "type": "Project", + "dependencies": { + "Core": "[2023.1.0, )", + "Dapper": "[2.0.123, )" + } + }, + "infrastructure.entityframework": { + "type": "Project", + "dependencies": { + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", + "Core": "[2023.1.0, )", + "Microsoft.EntityFrameworkCore.Relational": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.SqlServer": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.Sqlite": "[6.0.12, )", + "Npgsql.EntityFrameworkCore.PostgreSQL": "[6.0.8, )", + "Pomelo.EntityFrameworkCore.MySql": "[6.0.2, )", + "linq2db.EntityFrameworkCore": "[6.11.0, )" + } + }, + "scim": { + "type": "Project", + "dependencies": { + "Core": "[2023.1.0, )", + "Microsoft.VisualStudio.Web.CodeGeneration.Design": "[5.0.2, )", + "SharedWeb": "[2023.1.0, )" + } + }, + "sharedweb": { + "type": "Project", + "dependencies": { + "Core": "[2023.1.0, )", + "Infrastructure.Dapper": "[2023.1.0, )", + "Infrastructure.EntityFramework": "[2023.1.0, )" + } + } + } + } +} \ No newline at end of file diff --git a/bitwarden_license/test/bitwarden_license.tests.sln b/bitwarden_license/test/bitwarden_license.tests.sln new file mode 100644 index 000000000..c125c5bd1 --- /dev/null +++ b/bitwarden_license/test/bitwarden_license.tests.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 25.0.1703.8 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commercial.Core.Test", "Commercial.Core.Test\Commercial.Core.Test.csproj", "{70F03E72-2F38-4497-BF31-EA19B13B2161}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Scim.Test", "Scim.Test\Scim.Test.csproj", "{9BC8E2C9-400D-4FA7-86CA-3E1794E7CA4C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Scim.IntegrationTest", "Scim.IntegrationTest\Scim.IntegrationTest.csproj", "{45CD3F1B-127E-44B7-B22B-28D677B621D9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {70F03E72-2F38-4497-BF31-EA19B13B2161}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {70F03E72-2F38-4497-BF31-EA19B13B2161}.Debug|Any CPU.Build.0 = Debug|Any CPU + {70F03E72-2F38-4497-BF31-EA19B13B2161}.Release|Any CPU.ActiveCfg = Release|Any CPU + {70F03E72-2F38-4497-BF31-EA19B13B2161}.Release|Any CPU.Build.0 = Release|Any CPU + {9BC8E2C9-400D-4FA7-86CA-3E1794E7CA4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9BC8E2C9-400D-4FA7-86CA-3E1794E7CA4C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9BC8E2C9-400D-4FA7-86CA-3E1794E7CA4C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9BC8E2C9-400D-4FA7-86CA-3E1794E7CA4C}.Release|Any CPU.Build.0 = Release|Any CPU + {45CD3F1B-127E-44B7-B22B-28D677B621D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {45CD3F1B-127E-44B7-B22B-28D677B621D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {45CD3F1B-127E-44B7-B22B-28D677B621D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {45CD3F1B-127E-44B7-B22B-28D677B621D9}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BAD5FA17-2653-401A-A1E5-A31C420B9DE8} + EndGlobalSection +EndGlobal diff --git a/dev/.env.example b/dev/.env.example index 68d33e07f..62024d19e 100644 --- a/dev/.env.example +++ b/dev/.env.example @@ -1,3 +1,19 @@ COMPOSE_PROJECT_NAME=BitwardenServer +# Ensure the MSSQL_PASSWORD is complex and follows the password policy defined at +# https://docs.microsoft.com/en-us/sql/relational-databases/security/password-policy?view=sql-server-ver15 MSSQL_PASSWORD=SET_A_PASSWORD_HERE_123 MAILCATCHER_PORT=1080 + +# Alternative databases +POSTGRES_PASSWORD=SET_A_PASSWORD_HERE_123 +MYSQL_ROOT_PASSWORD=SET_A_PASSWORD_HERE_123 + +# IdP configuration +# Complete using the values from the Manage SSO page in the web vault +IDP_SP_ENTITY_ID=http://localhost:51822/saml2 +IDP_SP_ACS_URL=http://localhost:51822/saml2/yourOrgIdHere/Acs + +# Optional reverse proxy configuration +# Should match server listen ports in reverse-proxy.conf +API_PROXY_PORT=4100 +IDENTITY_PROXY_PORT=33756 \ No newline at end of file diff --git a/dev/.gitignore b/dev/.gitignore index 2e0c6f8f6..a9962f37b 100644 --- a/dev/.gitignore +++ b/dev/.gitignore @@ -1,10 +1,19 @@ .data secrets.json -.env +db +# Docker container configurations +.env +authsources.php +directory.ldif + +# Development certificates identity_server_dev.crt identity_server_dev.key identity_server_dev.pfx data_protection_dev.crt data_protection_dev.key data_protection_dev.pfx + +# Reverse Proxy Conifg +reverse-proxy.conf diff --git a/dev/authsources.php.example b/dev/authsources.php.example new file mode 100644 index 000000000..ce7907ba6 --- /dev/null +++ b/dev/authsources.php.example @@ -0,0 +1,20 @@ + array( + 'core:AdminPassword', + ), + + 'example-userpass' => array( + 'exampleauth:UserPass', + 'user1:password' => array( + 'email' => 'user1@example.com', + 'uid' => array('user1'), + ), + 'user2:password' => array( + 'email' => 'user2@example.com', + 'uid' => array('user2'), + ), + ), + +); diff --git a/dev/docker-compose.yml b/dev/docker-compose.yml index 27a90c668..66d07b56e 100644 --- a/dev/docker-compose.yml +++ b/dev/docker-compose.yml @@ -2,14 +2,13 @@ version: "3.9" services: mssql: - image: mcr.microsoft.com/mssql/server:2017-latest - restart: always + image: mcr.microsoft.com/azure-sql-edge:latest environment: ACCEPT_EULA: Y - SA_PASSWORD: ${MSSQL_PASSWORD} + MSSQL_SA_PASSWORD: ${MSSQL_PASSWORD} MSSQL_PID: Developer volumes: - - mssql_dev_data:/var/opt/mssql/data + - edgesql_dev_data:/var/opt/mssql - ../util/Migrator:/mnt/migrator/ - ./helpers/mssql:/mnt/helpers - ./.data/mssql:/mnt/data @@ -39,5 +38,75 @@ services: profiles: - mail + postgres: + image: postgres:14 + ports: + - "5432:5432" + environment: + POSTGRES_DB: vault_dev + POSTGRES_USER: postgres + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + volumes: + - postgres_dev_data:/var/lib/postgresql/data + - ./.data/postgres/config:/etc/postgresql + - ./.data/postgres/log:/var/log/postgresql + profiles: + - postgres + + mysql: + image: mysql:8 + container_name: bw-mysql + ports: + - "3306:3306" + command: --default-authentication-plugin=mysql_native_password + environment: + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} + MYSQL_DATABASE: vault_dev + volumes: + - mysql_dev_data:/var/lib/mysql + profiles: + - mysql + + idp: + image: kenchan0130/simplesamlphp:1.19.3 + container_name: idp + ports: + - "8090:8080" + environment: + SIMPLESAMLPHP_SP_ENTITY_ID: ${IDP_SP_ENTITY_ID} + SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE: ${IDP_SP_ACS_URL} + SIMPLESAMLPHP_SP_SINGLE_LOGOUT_SERVICE: null + volumes: + - ./authsources.php:/var/www/simplesamlphp/config/authsources.php + profiles: + - idp + + open-ldap: + image: osixia/openldap:1.5.0 + command: --copy-service + environment: + LDAP_ORGANISATION: "Bitwarden" + LDAP_DOMAIN: "bitwarden.com" + volumes: + - ./directory.ldif:/container/service/slapd/assets/config/bootstrap/ldif/output.ldif + ports: + - '389:389' + - '636:636' + profiles: + - ldap + + reverse-proxy: + image: nginx:alpine + container_name: reverse-proxy + volumes: + - "./reverse-proxy.conf:/etc/nginx/conf.d/default.conf" + ports: + - "${API_PROXY_PORT}:${API_PROXY_PORT}" + - "${IDENTITY_PROXY_PORT}:${IDENTITY_PROXY_PORT}" + profiles: + - proxy + volumes: - mssql_dev_data: + edgesql_dev_data: + postgres_dev_data: + mysql_dev_data: diff --git a/dev/ef_migrate.ps1 b/dev/ef_migrate.ps1 new file mode 100644 index 000000000..97e993934 --- /dev/null +++ b/dev/ef_migrate.ps1 @@ -0,0 +1,19 @@ +#!/usr/bin/env pwsh +param ( + [Parameter(Mandatory)] + $Name +) + +dotnet tool restore + +$providers = @{ + MySql = "../util/MySqlMigrations" + Postgres = "../util/PostgresMigrations" + Sqlite = "../util/SqliteMigrations" +} + +foreach ($key in $providers.keys) { + Write-Output "--- START $key ---" + dotnet ef migrations add $Name -s $providers[$key] + Write-Output "--- END $key ---" +} diff --git a/dev/helpers/mssql/migrate_migrations.sh b/dev/helpers/mssql/migrate_migrations.sh new file mode 100755 index 000000000..56f8da555 --- /dev/null +++ b/dev/helpers/mssql/migrate_migrations.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# There seems to be [a bug with docker-compose](https://github.com/docker/compose/issues/4076#issuecomment-324932294) +# where it takes ~40ms to connect to the terminal output of the container, so stuff logged to the terminal in this time is lost. +# The best workaround seems to be adding tiny delay like so: +sleep 0.1; + +MIGRATE_DIRECTORY="/mnt/migrator/DbScripts" +LAST_MIGRATION_FILE="/mnt/data/last_migration" +SERVER='mssql' +DATABASE="vault_dev" +USER="SA" +PASSWD=$MSSQL_PASSWORD + +while getopts "s" arg; do + case $arg in + s) + echo "Running for self-host environment" + LAST_MIGRATION_FILE="/mnt/data/last_self_host_migration" + DATABASE="vault_dev_self_host" + ;; + esac +done + +if [ ! -f "$LAST_MIGRATION_FILE" ]; then + echo "No migration file, nothing to migrate to a database store" + exit 1 +else + LAST_MIGRATION=$(cat $LAST_MIGRATION_FILE) + rm $LAST_MIGRATION_FILE +fi + +[ -z "$LAST_MIGRATION" ] +PERFORM_MIGRATION=$? + +# Create database if it does not already exist +QUERY="IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = 'migrations_$DATABASE') +BEGIN + CREATE DATABASE migrations_$DATABASE; +END; +" + +/opt/mssql-tools/bin/sqlcmd -S $SERVER -d master -U $USER -P $PASSWD -I -Q "$QUERY" + +QUERY="IF OBJECT_ID('[dbo].[migrations_$DATABASE]') IS NULL +BEGIN + CREATE TABLE [migrations_$DATABASE].[dbo].[migrations] ( + [Id] INT IDENTITY(1,1) PRIMARY KEY, + [Filename] NVARCHAR(MAX) NOT NULL, + [CreationDate] DATETIME2 (7) NULL, + ); +END;" + +/opt/mssql-tools/bin/sqlcmd -S $SERVER -d master -U $USER -P $PASSWD -I -Q "$QUERY" + +record_migration () { + echo "recording $1" + local file=$(basename $1) + echo $file + local query="INSERT INTO [migrations] ([Filename], [CreationDate]) VALUES ('$file', GETUTCDATE())" + /opt/mssql-tools/bin/sqlcmd -S $SERVER -d migrations_$DATABASE -U $USER -P $PASSWD -I -Q "$query" +} + +for f in `ls -v $MIGRATE_DIRECTORY/*.sql`; do + if (( PERFORM_MIGRATION == 0 )); then + echo "Still need to migrate $f" + else + record_migration $f + if [ "$LAST_MIGRATION" == "$f" ]; then + PERFORM_MIGRATION=0 + fi + fi +done; diff --git a/dev/helpers/mssql/run_migrations.sh b/dev/helpers/mssql/run_migrations.sh old mode 100644 new mode 100755 index 069252706..2ff75e7c5 --- a/dev/helpers/mssql/run_migrations.sh +++ b/dev/helpers/mssql/run_migrations.sh @@ -6,70 +6,89 @@ sleep 0.1; MIGRATE_DIRECTORY="/mnt/migrator/DbScripts" -LAST_MIGRATION_FILE="/mnt/data/last_migration" -SERVER='localhost' +SERVER='mssql' DATABASE="vault_dev" USER="SA" -PASSWD=$SA_PASSWORD +PASSWD=$MSSQL_PASSWORD -if [ ! -f "$LAST_MIGRATION_FILE" ]; then - echo "$LAST_MIGRATION_FILE not found!" - echo "This will run all migrations which might cause unexpected behaviour if the database is not empty." - echo - read -p "Run all Migrations? (y/N) " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Yy]$ ]] - then - exit 1 - fi - LAST_MIGRATION="" -else - LAST_MIGRATION=$(cat $LAST_MIGRATION_FILE) -fi - -[ -z "$LAST_MIGRATION" ] -PERFORM_MIGRATION=$? - -while getopts "r" arg; do +while getopts "sp" arg; do case $arg in - r) - RERUN=1 + s) + echo "Running for self-host environment" + DATABASE="vault_dev_self_host" ;; + p) + echo "Running for pipeline" + MIGRATE_DIRECTORY=$MSSQL_MIGRATIONS_DIRECTORY + SERVER=$MSSQL_HOST + DATABASE=$MSSQL_DATABASE + USER=$MSSQL_USER + PASSWD=$MSSQL_PASS esac done -if [ -n "$RERUN" ]; then - echo "Rerunning the last migration" -fi - -# Create database if it does not already exist -QUERY="IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = 'vault_dev') +# Create databases if they do not already exist +QUERY="IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = '$DATABASE') BEGIN - CREATE DATABASE vault_dev; -END;" + CREATE DATABASE $DATABASE; +END; +GO +IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = 'migrations_$DATABASE') +BEGIN + CREATE DATABASE migrations_$DATABASE; +END; + +GO +" /opt/mssql-tools/bin/sqlcmd -S $SERVER -d master -U $USER -P $PASSWD -I -Q "$QUERY" +echo "Return code: $?" + +# Create migrations table if it does not already exist +QUERY="IF OBJECT_ID('[migrations_$DATABASE].[dbo].[migrations]') IS NULL +BEGIN + CREATE TABLE [migrations_$DATABASE].[dbo].[migrations] ( + [Id] INT IDENTITY(1,1) PRIMARY KEY, + [Filename] NVARCHAR(MAX) NOT NULL, + [CreationDate] DATETIME2 (7) NULL, + ); +END; +GO +" +/opt/mssql-tools/bin/sqlcmd -S $SERVER -d migrations_$DATABASE -U $USER -P $PASSWD -I -Q "$QUERY" +echo "Return code: $?" + +should_migrate () { + local file=$(basename $1) + local query="SELECT * FROM [migrations] WHERE [Filename] = '$file'" + local result=$(/opt/mssql-tools/bin/sqlcmd -S $SERVER -d migrations_$DATABASE -U $USER -P $PASSWD -I -Q "$query") + if [[ "$result" =~ .*"$file".* ]]; then + return 1; + else + return 0; + fi +} + +record_migration () { + echo "recording $1" + local file=$(basename $1) + echo $file + local query="INSERT INTO [migrations] ([Filename], [CreationDate]) VALUES ('$file', GETUTCDATE())" + /opt/mssql-tools/bin/sqlcmd -S $SERVER -d migrations_$DATABASE -U $USER -P $PASSWD -I -Q "$query" +} migrate () { local file=$1 echo "Performing $file" /opt/mssql-tools/bin/sqlcmd -S $SERVER -d $DATABASE -U $USER -P $PASSWD -I -i $file - echo $file > $LAST_MIGRATION_FILE } for f in `ls -v $MIGRATE_DIRECTORY/*.sql`; do - if (( PERFORM_MIGRATION == 0 )); then + BASENAME=$(basename $f) + if should_migrate $f == 1 ; then migrate $f + record_migration $f else - echo "Skipping $f" - if [ "$LAST_MIGRATION" == "$f" ]; then - PERFORM_MIGRATION=0 - - # Rerun last migration - if [ -n "$RERUN" ]; then - migrate $f - unset RERUN - fi - fi + echo "Skipping $f, $BASENAME" fi done; diff --git a/dev/migrate.ps1 b/dev/migrate.ps1 old mode 100644 new mode 100755 index 3100869cc..4c878a5d1 --- a/dev/migrate.ps1 +++ b/dev/migrate.ps1 @@ -1,4 +1,48 @@ #!/usr/bin/env pwsh # Creates the vault_dev database, and runs all the migrations. -docker-compose --profile mssql exec mssql bash /mnt/helpers/run_migrations.sh @args +# Due to azure-edge-sql not containing the mssql-tools on ARM, we manually use +# the mssql-tools container which runs under x86_64. We should monitor this +# in the future and investigate if we can migrate back. +# docker-compose --profile mssql exec mssql bash /mnt/helpers/run_migrations.sh @args + +param([switch]$all = $false, [switch]$postgres = $false, [switch]$mysql = $false, [switch]$mssql = $false, [switch]$sqlite = $false) + +if (!$all -and !$postgres -and !$mysql -and !$sqlite) { + $mssql = $true; +} + +if ($all -or $postgres -or $mysql -or $sqlite) { + dotnet ef *> $null + if ($LASTEXITCODE -ne 0) { + Write-Host "Entity Framework Core tools were not found in the dotnet global tools. Attempting to install" + dotnet tool install dotnet-ef -g + } +} + +if ($all -or $mssql) { + Write-Host "Starting Microsoft SQL Server Migrations" + docker run ` + -v "$(pwd)/helpers/mssql:/mnt/helpers" ` + -v "$(pwd)/../util/Migrator:/mnt/migrator/" ` + -v "$(pwd)/.data/mssql:/mnt/data" ` + --env-file .env ` + --network=bitwardenserver_default ` + --rm ` + mcr.microsoft.com/mssql-tools ` + /mnt/helpers/run_migrations.sh @args +} + +$currentDir = Get-Location + +Foreach ($item in @(@($mysql, "MySQL", "MySqlMigrations"), @($postgres, "PostgreSQL", "PostgresMigrations"), @($sqlite, "SQLite", "SqliteMigrations"))) { + if (!$item[0] -and !$all) { + continue + } + + Write-Host "Starting $($item[1]) Migrations" + Set-Location "$currentDir/../util/$($item[2])/" + dotnet ef database update +} + +Set-Location "$currentDir" diff --git a/dev/migrate_migration_record.ps1 b/dev/migrate_migration_record.ps1 new file mode 100755 index 000000000..7ec8f89b3 --- /dev/null +++ b/dev/migrate_migration_record.ps1 @@ -0,0 +1,23 @@ +#!/usr/bin/env pwsh +# This script need only be run once +# +# This is a migration script for updating recording the last migration run +# in a file to recording migrations in a database table. It will create a +# migrations_vault table and store all of the previously run migrations as +# indicated by a last_migrations file. It will then delete this file. + +# Due to azure-edge-sql not containing the mssql-tools on ARM, we manually use +# the mssql-tools container which runs under x86_64. We should monitor this +# in the future and investigate if we can migrate back. +# docker-compose --profile mssql exec mssql bash /mnt/helpers/run_migrations.sh @args + +docker run ` + -v "$(pwd)/helpers/mssql:/mnt/helpers" ` + -v "$(pwd)/../util/Migrator:/mnt/migrator/" ` + -v "$(pwd)/.data/mssql:/mnt/data" ` + --env-file .env ` + --network=bitwardenserver_default ` + --rm ` + -it ` + mcr.microsoft.com/mssql-tools ` + /mnt/helpers/migrate_migrations.sh @args diff --git a/dev/reverse-proxy.conf.example b/dev/reverse-proxy.conf.example new file mode 100644 index 000000000..d132bc849 --- /dev/null +++ b/dev/reverse-proxy.conf.example @@ -0,0 +1,35 @@ +# Begin API Service + +upstream api_loadbalancer { + # Add additional API services here uniquely identified by their port + # Below assumes two services running on the docker host machine on ports 4000 and 4002 + server host.docker.internal:4000; + server host.docker.internal:4002; +} + +server { + listen 4100; # The port clients will connect to for the Api, must be exposed via Docker + location / { + proxy_pass http://api_loadbalancer; + } +} + +# End API Service + +# Begin Identity Service + +upstream identity_loadbalancer { + # Add additional Identity services here uniquely identified by their port + # Below assumes two services running on the docker host machine on ports 33656 and 33658 + server host.docker.internal:33656; + server host.docker.internal:33658; +} + +server { + listen 33756; # The port clients will connect to for the Identiy, must be exposed via Docker + location / { + proxy_pass http://identity_loadbalancer; + } +} + +# End Identity Service \ No newline at end of file diff --git a/dev/secrets.json.example b/dev/secrets.json.example index 543ceb7d7..a45aec5e6 100644 --- a/dev/secrets.json.example +++ b/dev/secrets.json.example @@ -5,7 +5,16 @@ "globalSettings": { "selfHosted": true, "sqlServer": { - "connectionString": "Server=localhost;Database=vault_dev;User Id=SA;Password=SET_A_PASSWORD_HERE_123;" + "connectionString": "Server=localhost;Database=vault_dev;User Id=SA;Password=SET_A_PASSWORD_HERE_123;Encrypt=True;TrustServerCertificate=True" + }, + "postgreSql": { + "connectionString": "Host=localhost;Username=postgres;Password=SET_A_PASSWORD_HERE_123;Database=vault_dev;Include Error Detail=true", + }, + "mySql": { + "connectionString": "server=localhost;uid=root;pwd=SET_A_PASSWORD_HERE_123;database=vault_dev" + }, + "sqlite": { + "connectionString": "Data Source=/path/to/bitwardenServer/repository/server/dev/db/bitwarden.sqlite" }, "identityServer": { "certificateThumbprint": "" diff --git a/dev/setup_secrets.ps1 b/dev/setup_secrets.ps1 index c3c717a92..e9903bf4d 100644 --- a/dev/setup_secrets.ps1 +++ b/dev/setup_secrets.ps1 @@ -25,6 +25,7 @@ $projects = @{ Identity = "../src/Identity" Notifications = "../src/Notifications" Sso = "../bitwarden_license/src/Sso" + Scim = "../bitwarden_license/src/Scim" } foreach ($key in $projects.keys) { diff --git a/docker-unified/.env.example b/docker-unified/.env.example new file mode 100644 index 000000000..06a987dc1 --- /dev/null +++ b/docker-unified/.env.example @@ -0,0 +1,3 @@ +COMPOSE_PROJECT_NAME=bitwarden +REGISTRY=bitwarden +TAG=dev diff --git a/docker-unified/Dockerfile b/docker-unified/Dockerfile new file mode 100644 index 000000000..0814ec9f0 --- /dev/null +++ b/docker-unified/Dockerfile @@ -0,0 +1,275 @@ +############################################### +# Build stage # +############################################### +FROM --platform=$BUILDPLATFORM debian AS web-setup + +# Add packages +RUN apt-get update && apt-get install -y \ + curl \ + jq \ + unzip \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /tmp + +# Download tags from 'clients' repository +RUN curl https://api.github.com/repos/bitwarden/clients/git/refs/tags --output tags.json + +# Grab last tag/release of the 'web' client +RUN cat tags.json | jq -r 'last(.[] | select(.ref|test("refs/tags/web-v[0-9]{4}.[0-9]{1,2}.[0-9]+"))) | .ref | split("/")[2]' > tag.txt + +# Extract the version of the 'web' client +RUN cat tag.txt | grep -o -E "[0-9]{4}\.[0-9]{1,2}\.[0-9]+" > version.txt + +# Download the built release artifact for the 'web' client +RUN TAG=$(cat tag.txt) \ + && VERSION=$(cat version.txt) \ + && curl -L https://github.com/bitwarden/clients/releases/download/$TAG/web-$VERSION-selfhosted-COMMERCIAL.zip -O + +# Unzip the 'web' client to /tmp/build +RUN VERSION=$(cat version.txt) \ + && unzip web-$VERSION-selfhosted-COMMERCIAL.zip + +############################################### +# Build stage # +############################################### +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:6.0 AS dotnet-build + +# Docker buildx supplies the value for this arg +ARG TARGETPLATFORM + +# Determine proper runtime value for .NET +# We put the value in a file to be read by later layers. +RUN if [ "$TARGETPLATFORM" = "linux/amd64" ]; then \ + RID=linux-x64 ; \ + elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then \ + RID=linux-arm64 ; \ + elif [ "$TARGETPLATFORM" = "linux/arm/v7" ]; then \ + RID=linux-arm ; \ + fi \ + && echo "RID=$RID" > /tmp/rid.txt + +# Add packages +RUN apt-get update && apt-get install -y \ + npm \ + && rm -rf /var/lib/apt/lists/* + +RUN npm install -g gulp + +# Copy csproj files as distinct layers +WORKDIR /source +COPY src/Admin/*.csproj ./src/Admin/ +COPY src/Api/*.csproj ./src/Api/ +COPY src/Events/*.csproj ./src/Events/ +COPY src/Icons/*.csproj ./src/Icons/ +COPY src/Identity/*.csproj ./src/Identity/ +COPY src/Notifications/*.csproj ./src/Notifications/ +COPY bitwarden_license/src/Sso/*.csproj ./bitwarden_license/src/Sso/ +COPY bitwarden_license/src/Scim/*.csproj ./bitwarden_license/src/Scim/ +COPY src/Core/*.csproj ./src/Core/ +COPY src/Infrastructure.Dapper/*.csproj ./src/Infrastructure.Dapper/ +COPY src/Infrastructure.EntityFramework/*.csproj ./src/Infrastructure.EntityFramework/ +COPY src/SharedWeb/*.csproj ./src/SharedWeb/ +COPY util/Migrator/*.csproj ./util/Migrator/ +COPY util/MySqlMigrations/*.csproj ./util/MySqlMigrations/ +COPY util/PostgresMigrations/*.csproj ./util/PostgresMigrations/ +COPY util/SqliteMigrations/*.csproj ./util/SqliteMigrations/ +COPY bitwarden_license/src/Commercial.Core/*.csproj ./bitwarden_license/src/Commercial.Core/ +COPY bitwarden_license/src/Commercial.Infrastructure.EntityFramework/*.csproj ./bitwarden_license/src/Commercial.Infrastructure.EntityFramework/ +COPY Directory.Build.props . + +# Restore Admin project dependencies and tools +WORKDIR /source/src/Admin +RUN . /tmp/rid.txt && dotnet restore -r $RID + +# Restore Api project dependencies and tools +WORKDIR /source/src/Api +RUN . /tmp/rid.txt && dotnet restore -r $RID + +# Restore Events project dependencies and tools +WORKDIR /source/src/Events +RUN . /tmp/rid.txt && dotnet restore -r $RID + +# Restore Icons project dependencies and tools +WORKDIR /source/src/Icons +RUN . /tmp/rid.txt && dotnet restore -r $RID + +# Restore Identity project dependencies and tools +WORKDIR /source/src/Identity +RUN . /tmp/rid.txt && dotnet restore -r $RID + +# Restore Notifications project dependencies and tools +WORKDIR /source/src/Notifications +RUN . /tmp/rid.txt && dotnet restore -r $RID + +# Restore Sso project dependencies and tools +WORKDIR /source/bitwarden_license/src/Sso +RUN . /tmp/rid.txt && dotnet restore -r $RID + +# Restore Scim project dependencies and tools +WORKDIR /source/bitwarden_license/src/Scim +RUN . /tmp/rid.txt && dotnet restore -r $RID + +# Copy required project files +WORKDIR /source +COPY src/Admin/. ./src/Admin/ +COPY src/Api/. ./src/Api/ +COPY src/Events/. ./src/Events/ +COPY src/Icons/. ./src/Icons/ +COPY src/Identity/. ./src/Identity/ +COPY src/Notifications/. ./src/Notifications/ +COPY bitwarden_license/src/Sso/. ./bitwarden_license/src/Sso/ +COPY bitwarden_license/src/Scim/. ./bitwarden_license/src/Scim/ +COPY src/Core/. ./src/Core/ +COPY src/Infrastructure.Dapper/. ./src/Infrastructure.Dapper/ +COPY src/Infrastructure.EntityFramework/. ./src/Infrastructure.EntityFramework/ +COPY src/SharedWeb/. ./src/SharedWeb/ +COPY util/Migrator/. ./util/Migrator/ +COPY util/MySqlMigrations/. ./util/MySqlMigrations/ +COPY util/PostgresMigrations/. ./util/PostgresMigrations/ +COPY util/SqliteMigrations/. ./util/SqliteMigrations/ +COPY util/EfShared/. ./util/EfShared/ +COPY bitwarden_license/src/Commercial.Core/. ./bitwarden_license/src/Commercial.Core/ +COPY bitwarden_license/src/Commercial.Infrastructure.EntityFramework/. ./bitwarden_license/src/Commercial.Infrastructure.EntityFramework/ +COPY .git/. ./.git/ + +# Build Admin app +WORKDIR /source/src/Admin +RUN npm install +RUN gulp --gulpfile "gulpfile.js" build +RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Admin --no-restore --no-self-contained -r $RID + +# Build Api app +WORKDIR /source/src/Api +RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Api --no-restore --no-self-contained -r $RID + +# Build Events app +WORKDIR /source/src/Events +RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Events --no-restore --no-self-contained -r $RID + +# Build Icons app +WORKDIR /source/src/Icons +RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Icons --no-restore --no-self-contained -r $RID + +# Build Identity app +WORKDIR /source/src/Identity +RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Identity --no-restore --no-self-contained -r $RID + +# Build Notifications app +WORKDIR /source/src/Notifications +RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Notifications --no-restore --no-self-contained -r $RID + +# Build Sso app +WORKDIR /source/bitwarden_license/src/Sso +RUN npm install +RUN gulp --gulpfile "gulpfile.js" build +RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Sso --no-restore --no-self-contained -r $RID + +# Build Scim app +WORKDIR /source/bitwarden_license/src/Scim +RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Scim --no-restore --no-self-contained -r $RID + +############################################### +# App stage # +############################################### +FROM mcr.microsoft.com/dotnet/aspnet:6.0 +ARG TARGETPLATFORM +LABEL com.bitwarden.product="bitwarden" +LABEL com.bitwarden.project="unified" +ENV ASPNETCORE_ENVIRONMENT=Production +ENV BW_ENABLE_ADMIN=true +ENV BW_ENABLE_API=true +ENV BW_ENABLE_EVENTS=false +ENV BW_ENABLE_ICONS=true +ENV BW_ENABLE_IDENTITY=true +ENV BW_ENABLE_NOTIFICATIONS=true +ENV BW_ENABLE_SCIM=false +ENV BW_ENABLE_SSO=false +ENV BW_DB_FILE="/etc/bitwarden/vault.db" +ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false +ENV globalSettings__selfHosted="true" +ENV globalSettings__pushRelayBaseUri="https://push.bitwarden.com" +ENV globalSettings__baseServiceUri__internalAdmin="http://localhost:5000" +ENV globalSettings__baseServiceUri__internalApi="http://localhost:5001" +ENV globalSettings__baseServiceUri__internalEvents="http://localhost:5003" +ENV globalSettings__baseServiceUri__internalIcons="http://localhost:5004" +ENV globalSettings__baseServiceUri__internalIdentity="http://localhost:5005" +ENV globalSettings__baseServiceUri__internalNotifications="http://localhost:5006" +ENV globalSettings__baseServiceUri__internalSso="http://localhost:5007" +ENV globalSettings__baseServiceUri__internalScim="http://localhost:5002" +ENV globalSettings__baseServiceUri__internalVault="http://localhost:80" +ENV globalSettings__identityServer__certificatePassword="default_cert_password" +ENV globalSettings__dataProtection__directory="/etc/bitwarden/data-protection" +ENV globalSettings__attachment__baseDirectory="/etc/bitwarden/attachments" +ENV globalSettings__send__baseDirectory="/etc/bitwarden/attachments/send" +ENV globalSettings__licenseDirectory="/etc/bitwarden/licenses" +ENV globalSettings__logDirectoryByProject="false" +ENV globalSettings__logRollBySizeLimit="1073741824" + +# Add packages +RUN apt-get update && apt-get install -y \ + curl \ + nginx \ + openssl \ + supervisor \ + tzdata \ + unzip \ + && rm -rf /var/lib/apt/lists/* + +# Create required directories +RUN mkdir -p /etc/bitwarden/attachments/send +RUN mkdir -p /etc/bitwarden/data-protection +RUN mkdir -p /etc/bitwarden/licenses +RUN mkdir -p /etc/bitwarden/logs +RUN mkdir -p /etc/supervisor +RUN mkdir -p /etc/supervisor.d +RUN mkdir -p /var/log/bitwarden +RUN mkdir -p /var/log/nginx/logs +RUN mkdir -p /etc/nginx/http.d +RUN mkdir -p /var/run/nginx +RUN touch /var/run/nginx/nginx.pid +RUN mkdir -p /app + +# Copy all apps from dotnet-build stage +WORKDIR /app +COPY --from=dotnet-build /app ./ + +# Copy Web files from web-setup stage +COPY --from=web-setup /tmp/build /app/Web + +# Set up supervisord +COPY docker-unified/supervisord/*.ini /etc/supervisor.d/ +COPY docker-unified/supervisord/supervisord.conf /etc/supervisor/supervisord.conf +RUN rm -f /etc/supervisord.conf + +# Set up nginx +COPY docker-unified/nginx/nginx.conf /etc/nginx +COPY docker-unified/nginx/proxy.conf /etc/nginx +COPY docker-unified/nginx/mime.types /etc/nginx +COPY docker-unified/nginx/security-headers.conf /etc/nginx +COPY docker-unified/nginx/security-headers-ssl.conf /etc/nginx +COPY docker-unified/nginx/logrotate.sh / +RUN chmod +x /logrotate.sh + +# Copy configuration templates +COPY docker-unified/hbs/nginx-config.hbs /etc/hbs/ +COPY docker-unified/hbs/app-id.hbs /etc/hbs/ +COPY docker-unified/hbs/config.yaml /etc/hbs/ + +# Download hbs tool for generating final configurations +RUN if [ "$TARGETPLATFORM" = "linux/amd64" ] ; then curl -L --output hbs.zip https://github.com/bitwarden/Handlebars.conf/releases/download/v1.3.0/hbs_linux-x64_dotnet.zip; fi +RUN if [ "$TARGETPLATFORM" = "linux/arm/v7" ] ; then curl -L --output hbs.zip https://github.com/bitwarden/Handlebars.conf/releases/download/v1.3.0/hbs_linux-armv7_dotnet.zip; fi +RUN if [ "$TARGETPLATFORM" = "linux/arm64" ] ; then curl -L --output hbs.zip https://github.com/bitwarden/Handlebars.conf/releases/download/v1.3.0/hbs_linux-arm64_dotnet.zip; fi + +# Extract hbs +RUN unzip hbs.zip -d /usr/local/bin && rm hbs.zip +RUN chmod +x /usr/local/bin/hbs + +# Copy entrypoint script and make it executable +COPY docker-unified/entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +VOLUME ["/etc/bitwarden"] + +WORKDIR /app +ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker-unified/docker-compose.yml b/docker-unified/docker-compose.yml new file mode 100644 index 000000000..25e3bcd03 --- /dev/null +++ b/docker-unified/docker-compose.yml @@ -0,0 +1,56 @@ +--- +version: "3.8" + +services: + bitwarden: + depends_on: + - db + env_file: + - settings.env + image: ${REGISTRY:-bitwarden}/self-host:${TAG:-beta} + restart: always + ports: + - "80:8080" + - "443:8443" + volumes: + - bitwarden:/etc/bitwarden + - logs:/var/log/bitwarden + + # MariaDB Example + db: + environment: + MARIADB_USER: "bitwarden" + MARIADB_PASSWORD: "super_strong_password" + MARIADB_DATABASE: "bitwarden_vault" + MARIADB_RANDOM_ROOT_PASSWORD: "true" + image: mariadb:10 + restart: always + volumes: + - data:/var/lib/mysql + + # PostgreSQL Example + # db: + # environment: + # POSTGRES_USER: "bitwarden" + # POSTGRES_PASSWORD: "super_strong_password" + # POSTGRES_DB: "bitwarden_vault" + # image: postgres:14 + # restart: always + # volumes: + # - data:/var/lib/postgresql/data + + # MS SQL Server Example + # Docs: https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-docker-container-deployment + # db: + # environment: + # MSSQL_SA_PASSWORD: "super_strong_password" + # ACCEPT_EULA: Y + # image: mcr.microsoft.com/mssql/server:2019-latest + # restart: always + # volumes: + # - data:/var/opt/mssql + +volumes: + bitwarden: + logs: + data: diff --git a/docker-unified/entrypoint.sh b/docker-unified/entrypoint.sh new file mode 100755 index 000000000..86c739398 --- /dev/null +++ b/docker-unified/entrypoint.sh @@ -0,0 +1,102 @@ +#!/bin/bash + +# Set up user group +PGID="${PGID:-1000}" +addgroup --gid $PGID bitwarden + +# Set up user +PUID="${PUID:-1000}" +adduser --no-create-home --shell /bin/bash --disabled-password --uid $PUID --gid $PGID --gecos "" bitwarden + +# Translate environment variables for application settings +VAULT_SERVICE_URI=https://$BW_DOMAIN +MYSQL_CONNECTION_STRING="server=$BW_DB_SERVER;port=${BW_DB_PORT:-3306};database=$BW_DB_DATABASE;user=$BW_DB_USERNAME;password=$BW_DB_PASSWORD" +POSTGRESQL_CONNECTION_STRING="Host=$BW_DB_SERVER;Port=${BW_DB_PORT:-5432};Database=$BW_DB_DATABASE;Username=$BW_DB_USERNAME;Password=$BW_DB_PASSWORD" +SQLSERVER_CONNECTION_STRING="Server=$BW_DB_SERVER,${BW_DB_PORT:-1433};Database=$BW_DB_DATABASE;User Id=$BW_DB_USERNAME;Password=$BW_DB_PASSWORD;Encrypt=True;TrustServerCertificate=True" +SQLITE_CONNECTION_STRING="Data Source=$BW_DB_FILE;" +INTERNAL_IDENTITY_KEY=$(openssl rand -hex 30) +OIDC_IDENTITY_CLIENT_KEY=$(openssl rand -hex 30) +DUO_AKEY=$(openssl rand -hex 30) + +export globalSettings__baseServiceUri__vault=${globalSettings__baseServiceUri__vault:-$VAULT_SERVICE_URI} +export globalSettings__installation__id=$BW_INSTALLATION_ID +export globalSettings__installation__key=$BW_INSTALLATION_KEY +export globalSettings__internalIdentityKey=${globalSettings__internalIdentityKey:-$INTERNAL_IDENTITY_KEY} +export globalSettings__oidcIdentityClientKey=${globalSettings__oidcIdentityClientKey:-$OIDC_IDENTITY_CLIENT_KEY} +export globalSettings__duo__aKey=${globalSettings__duo__aKey:-$DUO_AKEY} + +export globalSettings__databaseProvider=$BW_DB_PROVIDER +export globalSettings__mysql__connectionString=${globalSettings__mysql__connectionString:-$MYSQL_CONNECTION_STRING} +export globalSettings__postgreSql__connectionString=${globalSettings__postgreSql__connectionString:-$POSTGRESQL_CONNECTION_STRING} +export globalSettings__sqlServer__connectionString=${globalSettings__sqlServer__connectionString:-$SQLSERVER_CONNECTION_STRING} +export globalSettings__sqlite__connectionString=${globalSettings__sqlite__connectionString:-$SQLITE_CONNECTION_STRING} + +# Generate Identity certificate +if [ ! -f /etc/bitwarden/identity.pfx ]; then + openssl req \ + -x509 \ + -newkey rsa:4096 \ + -sha256 \ + -nodes \ + -keyout /etc/bitwarden/identity.key \ + -out /etc/bitwarden/identity.crt \ + -subj "/CN=Bitwarden IdentityServer" \ + -days 36500 + + openssl pkcs12 \ + -export \ + -out /etc/bitwarden/identity.pfx \ + -inkey /etc/bitwarden/identity.key \ + -in /etc/bitwarden/identity.crt \ + -passout pass:$globalSettings__identityServer__certificatePassword + + rm /etc/bitwarden/identity.crt + rm /etc/bitwarden/identity.key +fi + +cp /etc/bitwarden/identity.pfx /app/Identity/identity.pfx +cp /etc/bitwarden/identity.pfx /app/Sso/identity.pfx + +# Generate SSL certificates +if [ "$BW_ENABLE_SSL" = "true" -a ! -f /etc/bitwarden/${BW_SSL_KEY:-ssl.key} ]; then + openssl req \ + -x509 \ + -newkey rsa:4096 \ + -sha256 \ + -nodes \ + -days 36500 \ + -keyout /etc/bitwarden/${BW_SSL_KEY:-ssl.key} \ + -out /etc/bitwarden/${BW_SSL_CERT:-ssl.crt} \ + -reqexts SAN \ + -extensions SAN \ + -config <(cat /usr/lib/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:${BW_DOMAIN:-localhost}\nbasicConstraints=CA:true")) \ + -subj "/C=US/ST=California/L=Santa Barbara/O=Bitwarden Inc./OU=Bitwarden/CN=${BW_DOMAIN:-localhost}" +fi + +# Launch a loop to rotate nginx logs on a daily basis +/bin/sh -c "/logrotate.sh loop >/dev/null 2>&1 &" + +/usr/local/bin/hbs + +# Enable/Disable services +sed -i "s/autostart=true/autostart=${BW_ENABLE_ADMIN}/" /etc/supervisor.d/admin.ini +sed -i "s/autostart=true/autostart=${BW_ENABLE_API}/" /etc/supervisor.d/api.ini +sed -i "s/autostart=true/autostart=${BW_ENABLE_EVENTS}/" /etc/supervisor.d/events.ini +sed -i "s/autostart=true/autostart=${BW_ENABLE_ICONS}/" /etc/supervisor.d/icons.ini +sed -i "s/autostart=true/autostart=${BW_ENABLE_IDENTITY}/" /etc/supervisor.d/identity.ini +sed -i "s/autostart=true/autostart=${BW_ENABLE_NOTIFICATIONS}/" /etc/supervisor.d/notifications.ini +sed -i "s/autostart=true/autostart=${BW_ENABLE_SCIM}/" /etc/supervisor.d/scim.ini +sed -i "s/autostart=true/autostart=${BW_ENABLE_SSO}/" /etc/supervisor.d/sso.ini + +chown -R $PUID:$PGID \ + /app \ + /etc/bitwarden \ + /etc/nginx/http.d \ + /etc/supervisor \ + /etc/supervisor.d \ + /var/lib/nginx \ + /var/log \ + /var/run/nginx \ + /run + +exec setpriv --reuid=$PUID --regid=$PGID --init-groups /usr/bin/supervisord \ No newline at end of file diff --git a/docker-unified/hbs/app-id.hbs b/docker-unified/hbs/app-id.hbs new file mode 100644 index 000000000..eed8768b4 --- /dev/null +++ b/docker-unified/hbs/app-id.hbs @@ -0,0 +1,15 @@ +{ + "trustedFacets": [ + { + "version": { + "major": 1, + "minor": 0 + }, + "ids": [ + "{{{String.Coalesce env.globalSettings__baseServiceUri__vault "https://localhost"}}}", + "ios:bundle-id:com.8bit.bitwarden", + "android:apk-key-hash:dUGFzUzf3lmHSLBDBIv+WaFyZMI" + ] + } + ] +} diff --git a/docker-unified/hbs/config.yaml b/docker-unified/hbs/config.yaml new file mode 100644 index 000000000..2dc04a658 --- /dev/null +++ b/docker-unified/hbs/config.yaml @@ -0,0 +1,7 @@ +helper_categories: + - String +templates: + - src: /etc/hbs/app-id.hbs + dest: /app/Web/app-id.json + - src: /etc/hbs/nginx-config.hbs + dest: /etc/nginx/http.d/bitwarden.conf \ No newline at end of file diff --git a/docker-unified/hbs/nginx-config.hbs b/docker-unified/hbs/nginx-config.hbs new file mode 100644 index 000000000..3698c89af --- /dev/null +++ b/docker-unified/hbs/nginx-config.hbs @@ -0,0 +1,189 @@ +server { + listen {{{String.Coalesce env.BW_PORT_HTTP "8080"}}} default_server; + #listen [::]:{{{String.Coalesce env.BW_PORT_HTTP "8080"}}} default_server; + server_name {{{String.Coalesce env.BW_DOMAIN "localhost"}}}; +{{#if (String.Equal env.BW_ENABLE_SSL "true")}} + + return 301 https://{{{String.Coalesce env.BW_DOMAIN "localhost"}}}:{{{String.Coalesce env.BW_PORT_HTTPS "8443"}}}$request_uri; +} + +server { + listen {{{String.Coalesce env.BW_PORT_HTTPS "8443"}}} ssl http2; + #listen [::]:{{{String.Coalesce env.BW_PORT_HTTPS "8443"}}} ssl http2; + server_name {{{String.Coalesce env.BW_DOMAIN "localhost"}}}; + + ssl_certificate /etc/bitwarden/{{{String.Coalesce env.BW_SSL_CERT "ssl.crt"}}}; + ssl_certificate_key /etc/bitwarden/{{{String.Coalesce env.BW_SSL_KEY "ssl.key"}}}; + ssl_session_timeout 30m; + ssl_session_cache shared:SSL:20m; + ssl_session_tickets off; +{{#if (String.Equal env.BW_ENABLE_SSL_DH "true")}} + + # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits + ssl_dhparam /etc/bitwarden/{{{String.Coalesce env.BW_SSL_DH_CERT "dh.pem"}}}; +{{/if}} + + ssl_protocols {{{String.Coalesce env.BW_SSL_PROTOCOLS "TLSv1.2"}}}; + ssl_ciphers "{{{String.Coalesce env.BW_SSL_CIPHERS "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"}}}"; + # Enables server-side protection from BEAST attacks + ssl_prefer_server_ciphers on; +{{#if (String.Equal env.BW_ENABLE_SSL_CA "true")}} + + # OCSP Stapling --- + # Fetch OCSP records from URL in ssl_certificate and cache them + ssl_stapling on; + ssl_stapling_verify on; + + # Verify chain of trust of OCSP response using Root CA and Intermediate certs + ssl_trusted_certificate /etc/bitwarden/{{{String.Coalesce env.BW_SSL_CA_CERT "ca.crt"}}}; + resolver 1.1.1.1 1.0.0.1 9.9.9.9 149.112.112.112 valid=300s; +{{/if}} + + include /etc/nginx/security-headers-ssl.conf; +{{/if}} + include /etc/nginx/security-headers.conf; +{{#if (String.IsNotNullOrWhitespace env.BW_REAL_IPS)}} + +{{#each (String.Split env.BW_REAL_IPS ",")}} + set_real_ip_from {{{String.Trim .}}}; +{{/each}} + real_ip_header X-Forwarded-For; + real_ip_recursive on; +{{/if}} + + location / { + root /app/Web; +{{#if (String.Equal env.BW_ENABLE_SSL "true")}} + include /etc/nginx/security-headers-ssl.conf; +{{/if}} + include /etc/nginx/security-headers.conf; + add_header Content-Security-Policy "{{{String.Coalesce env.BW_CSP "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://haveibeenpwned.com; child-src 'self' https://*.duosecurity.com https://*.duofederal.com; frame-src 'self' https://*.duosecurity.com https://*.duofederal.com; connect-src 'self' https://api.pwnedpasswords.com https://api.2fa.directory; object-src 'self' blob:;"}}}"; + add_header X-Frame-Options SAMEORIGIN; + add_header X-Robots-Tag "noindex, nofollow"; + } + + location /alive { + default_type text/plain; + return 200 $date_gmt; + } + + location = /app-id.json { + root /app/Web; +{{#if (String.Equal env.BW_ENABLE_SSL "true")}} + include /etc/nginx/security-headers-ssl.conf; +{{/if}} + include /etc/nginx/security-headers.conf; + proxy_hide_header Content-Type; + add_header Content-Type $fido_content_type; + } + + location = /duo-connector.html { + root /app/Web; + } + + location = /webauthn-connector.html { + root /app/Web; + } + + location = /webauthn-fallback-connector.html { + root /app/Web; + } + + location = /sso-connector.html { + root /app/Web; + } + + location = /captcha-connector.html { + root /app/Web; + } + + location = /captcha-mobile-connector.html { + root /app/Web; + } + + location /attachments/ { + alias /etc/bitwarden/attachments/; + } +{{#if (String.Equal env.BW_ENABLE_API "true")}} + + location /api/ { + proxy_pass http://localhost:5001/; + } +{{/if}} +{{#if (String.Equal env.BW_ENABLE_ICONS "true")}} + + location /icons/ { +{{#if (String.Equal env.BW_ICONS_PROXY_TO_CLOUD "true")}} + proxy_pass https://icons.bitwarden.net/; + proxy_set_header Host icons.bitwarden.net; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_ssl_server_name on; +{{else}} + proxy_pass http://localhost:5004/; +{{/if}} + } +{{/if}} +{{#if (String.Equal env.BW_ENABLE_NOTIFICATIONS "true")}} + + location /notifications/ { + proxy_pass http://localhost:5006/; + } + + location /notifications/hub { + proxy_pass http://localhost:5006/hub; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $http_connection; + } +{{/if}} +{{#if (String.Equal env.BW_ENABLE_EVENTS "true")}} + + location /events/ { + proxy_pass http://localhost:5003/; + } +{{/if}} +{{#if (String.Equal env.BW_ENABLE_SSO "true")}} + + location /sso { + proxy_pass http://localhost:5007; +{{#if (String.Equal env.BW_ENABLE_SSL "true")}} + include /etc/nginx/security-headers-ssl.conf; +{{/if}} + include /etc/nginx/security-headers.conf; + add_header X-Frame-Options SAMEORIGIN; + } +{{/if}} +{{#if (String.Equal env.BW_ENABLE_IDENTITY "true")}} + + location /identity { + proxy_pass http://localhost:5005; +{{#if (String.Equal env.BW_ENABLE_SSL "true")}} + include /etc/nginx/security-headers-ssl.conf; +{{/if}} + include /etc/nginx/security-headers.conf; + add_header X-Frame-Options SAMEORIGIN; + } +{{/if}} +{{#if (String.Equal env.BW_ENABLE_ADMIN "true")}} + + location /admin { + proxy_pass http://localhost:5000; +{{#if (String.Equal env.BW_ENABLE_SSL "true")}} + include /etc/nginx/security-headers-ssl.conf; +{{/if}} + include /etc/nginx/security-headers.conf; + add_header X-Frame-Options SAMEORIGIN; + } +{{/if}} +{{#if (String.Equal env.BW_ENABLE_SCIM "true")}} + + location /scim/ { + proxy_pass http://localhost:5002/; + } +{{/if}} +{{#if (String.Equal env.BW_ENABLE_KEY_CONNECTOR "true")}} + + location /key-connector/ { + proxy_pass {{{env.BW_KEY_CONNECTOR_INTERNAL_URL}}}/; + } +{{/if}} +} diff --git a/docker-unified/nginx/logrotate.sh b/docker-unified/nginx/logrotate.sh new file mode 100644 index 000000000..d86c79c5d --- /dev/null +++ b/docker-unified/nginx/logrotate.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +while true +do + [ "$1" = "loop" ] && sleep $((24 * 3600 - (`date +%_H` * 3600 + `date +%_M` * 60 + `date +%_S`))) + ts=$(date +%Y%m%d_%H%M%S) + mv /var/log/nginx/access.log /var/log/nginx/access.$ts.log + mv /var/log/nginx/error.log /var/log/nginx/error.$ts.log + kill -USR1 `cat /var/run/nginx/nginx.pid` + sleep 1 + gzip /var/log/nginx/access.$ts.log + gzip /var/log/nginx/error.$ts.log + find /var/log/nginx/ -name "*.gz" -mtime +32 -delete + [ "$1" != "loop" ] && break +done diff --git a/docker-unified/nginx/mime.types b/docker-unified/nginx/mime.types new file mode 100644 index 000000000..7c3b1e738 --- /dev/null +++ b/docker-unified/nginx/mime.types @@ -0,0 +1,138 @@ +types { + + # Data interchange + + application/atom+xml atom; + application/json json map topojson; + application/ld+json jsonld; + application/rss+xml rss; + application/vnd.geo+json geojson; + application/xml rdf xml; + + + # JavaScript + + # Normalize to standard type. + # https://tools.ietf.org/html/rfc4329#section-7.2 + application/javascript js; + + + # Manifest files + + application/manifest+json webmanifest; + application/x-web-app-manifest+json webapp; + text/cache-manifest appcache; + + + # Media files + + audio/midi mid midi kar; + audio/mp4 aac f4a f4b m4a; + audio/mpeg mp3; + audio/ogg oga ogg opus; + audio/x-realaudio ra; + audio/x-wav wav; + image/bmp bmp; + image/gif gif; + image/jpeg jpeg jpg; + image/jxr jxr hdp wdp; + image/png png; + image/svg+xml svg svgz; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/webp webp; + image/x-jng jng; + video/3gpp 3gp 3gpp; + video/mp4 f4p f4v m4v mp4; + video/mpeg mpeg mpg; + video/ogg ogv; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-mng mng; + video/x-ms-asf asf asx; + video/x-ms-wmv wmv; + video/x-msvideo avi; + + # Serving `.ico` image files with a different media type + # prevents Internet Explorer from displaying then as images: + # https://github.com/h5bp/html5-boilerplate/commit/37b5fec090d00f38de64b591bcddcb205aadf8ee + + image/x-icon cur ico; + + + # Microsoft Office + + application/msword doc; + application/vnd.ms-excel xls; + application/vnd.ms-powerpoint ppt; + application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; + application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; + + + # Web fonts + + application/font-woff woff; + application/font-woff2 woff2; + application/vnd.ms-fontobject eot; + + # Browsers usually ignore the font media types and simply sniff + # the bytes to figure out the font type. + # https://mimesniff.spec.whatwg.org/#matching-a-font-type-pattern + # + # However, Blink and WebKit based browsers will show a warning + # in the console if the following font types are served with any + # other media types. + + application/x-font-ttf ttc ttf; + font/opentype otf; + + + # Other + + application/java-archive ear jar war; + application/mac-binhex40 hqx; + application/octet-stream bin deb dll dmg exe img iso msi msm msp safariextz; + application/pdf pdf; + application/postscript ai eps ps; + application/rtf rtf; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/vnd.wap.wmlc wmlc; + application/x-7z-compressed 7z; + application/x-bb-appworld bbaw; + application/x-bittorrent torrent; + application/x-chrome-extension crx; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-opera-extension oex; + application/x-perl pl pm; + application/x-pilot pdb prc; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert crt der pem; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/xslt+xml xsl; + application/zip zip; + text/css css; + text/csv csv; + text/html htm html shtml; + text/markdown md; + text/mathml mml; + text/plain txt; + text/vcard vcard vcf; + text/vnd.rim.location.xloc xloc; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/vtt vtt; + text/x-component htc; + +} diff --git a/docker-unified/nginx/nginx.conf b/docker-unified/nginx/nginx.conf new file mode 100644 index 000000000..93445e8a2 --- /dev/null +++ b/docker-unified/nginx/nginx.conf @@ -0,0 +1,147 @@ +# nginx Configuration File +# http://wiki.nginx.org/Configuration + +daemon off; + +# Run as a less privileged user for security reasons. +# user www www; + +# How many worker threads to run; +# "auto" sets it to the number of CPU cores available in the system, and +# offers the best performance. Don't set it higher than the number of CPU +# cores if changing this parameter. + +# The maximum number of connections for Nginx is calculated by: +# max_clients = worker_processes * worker_connections +worker_processes auto; + +# Maximum open file descriptors per process; +# should be > worker_connections. +worker_rlimit_nofile 8192; + +events { + # When you need > 8000 * cpu_cores connections, you start optimizing your OS, + # and this is probably the point at which you hire people who are smarter than + # you, as this is *a lot* of requests. + worker_connections 8000; +} + +# Default error log file +# (this is only used when you don't override error_log on a server{} level) +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx/nginx.pid; + +http { + # Include proxy and server configuration. + include /etc/nginx/proxy.conf; + include /etc/nginx/http.d/bitwarden.conf; + + # Hide nginx version information. + server_tokens off; + + # Define the MIME types for files. + include /etc/nginx/mime.types; + default_type application/octet-stream; + + # Update charset_types to match updated mime.types. + # text/html is always included by charset module. + # Default: text/html text/xml text/plain text/vnd.wap.wml application/javascript application/rss+xml + charset_types + text/css + text/plain + text/vnd.wap.wml + application/javascript + application/json + application/rss+xml + application/xml; + + # Format to use in log files + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + # Default log file + # (this is only used when you don't override access_log on a server{} level) + access_log /var/log/nginx/access.log main; + + # How long to allow each connection to stay idle; longer values are better + # for each individual client, particularly for SSL, but means that worker + # connections are tied up longer. (Default: 65) + keepalive_timeout 20; + + # Speed up file transfers by using sendfile() to copy directly + # between descriptors rather than using read()/write(). + # For performance reasons, on FreeBSD systems w/ ZFS + # this option should be disabled as ZFS's ARC caches + # frequently used files in RAM by default. + sendfile on; + + # Tell Nginx not to send out partial frames; this increases throughput + # since TCP frames are filled up before being sent out. (adds TCP_CORK) + tcp_nopush on; + + + # Compression + + # Enable Gzip compressed. + gzip on; + + # Compression level (1-9). + # 5 is a perfect compromise between size and cpu usage, offering about + # 75% reduction for most ascii files (almost identical to level 9). + gzip_comp_level 5; + + # Don't compress anything that's already small and unlikely to shrink much + # if at all (the default is 20 bytes, which is bad as that usually leads to + # larger files after gzipping). + gzip_min_length 256; + + # Compress data even for clients that are connecting to us via proxies, + # identified by the "Via" header (required for CloudFront). + gzip_proxied any; + + # Tell proxies to cache both the gzipped and regular version of a resource + # whenever the client's Accept-Encoding capabilities header varies; + # Avoids the issue where a non-gzip capable client (which is extremely rare + # today) would display gibberish if their proxy gave them the gzipped version. + gzip_vary on; + + # Compress all output labeled with one of the following MIME-types. + gzip_types + application/atom+xml + application/javascript + application/json + application/ld+json + application/manifest+json + application/rss+xml + application/vnd.geo+json + application/vnd.ms-fontobject + application/x-font-ttf + application/x-web-app-manifest+json + application/xhtml+xml + application/xml + font/opentype + image/bmp + image/svg+xml + image/x-icon + text/cache-manifest + text/css + text/plain + text/vcard + text/vnd.rim.location.xloc + text/vtt + text/x-component + text/x-cross-domain-policy; + # text/html is always compressed by HttpGzipModule + + # This should be turned on if you are going to have pre-compressed copies (.gz) of + # static files available. If not it should be left off as it will cause extra I/O + # for the check. It is best if you enable this in a location{} block for + # a specific directory, or on an individual server{} level. + # gzip_static on; + + # Content type for FIDO U2F facets + map $uri $fido_content_type { + default "application/fido.trusted-apps+json"; + } +} diff --git a/docker-unified/nginx/proxy.conf b/docker-unified/nginx/proxy.conf new file mode 100644 index 000000000..7e7941513 --- /dev/null +++ b/docker-unified/nginx/proxy.conf @@ -0,0 +1,15 @@ +proxy_redirect off; +proxy_set_header Host $host; +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Url-Scheme $scheme; +proxy_set_header X-Forwarded-Proto $scheme; +client_max_body_size 505m; +client_body_buffer_size 128k; +proxy_connect_timeout 90; +proxy_send_timeout 90; +proxy_read_timeout 90; +proxy_buffer_size 128k; +proxy_buffers 4 256k; +proxy_busy_buffers_size 256k; +large_client_header_buffers 4 32k; diff --git a/docker-unified/nginx/security-headers-ssl.conf b/docker-unified/nginx/security-headers-ssl.conf new file mode 100644 index 000000000..d94e835c4 --- /dev/null +++ b/docker-unified/nginx/security-headers-ssl.conf @@ -0,0 +1,2 @@ +# This will enforce HTTP browsing into HTTPS and avoid ssl stripping attack. 6 months age +add_header Strict-Transport-Security max-age=15768000; \ No newline at end of file diff --git a/docker-unified/nginx/security-headers.conf b/docker-unified/nginx/security-headers.conf new file mode 100644 index 000000000..c23d1b497 --- /dev/null +++ b/docker-unified/nginx/security-headers.conf @@ -0,0 +1,3 @@ +add_header Referrer-Policy same-origin; +add_header X-Content-Type-Options nosniff; +add_header X-XSS-Protection "1; mode=block"; \ No newline at end of file diff --git a/docker-unified/settings.env b/docker-unified/settings.env new file mode 100644 index 000000000..d86baa6c2 --- /dev/null +++ b/docker-unified/settings.env @@ -0,0 +1,69 @@ +##################### +# Required Settings # +##################### + +# Server hostname +BW_DOMAIN=bitwarden.yourdomain.com + +# Database +# Available providers are sqlserver, postgresql, mysql/mariadb, or sqlite +BW_DB_PROVIDER=mysql +BW_DB_SERVER=db +BW_DB_DATABASE=bitwarden_vault +BW_DB_USERNAME=bitwarden +BW_DB_PASSWORD=super_strong_password + +# Installation information +# Get your ID and key from https://bitwarden.com/host/ +BW_INSTALLATION_ID=00000000-0000-0000-0000-000000000000 +BW_INSTALLATION_KEY=xxxxxxxxxxxx + +##################### +# Optional Settings # +##################### +# Learn more here: https://bitwarden.com/help/environment-variables/ + +# Container user ID/group ID +#PUID=1000 +#PGID=1000 + +# Webserver ports +#BW_PORT_HTTP=8080 +#BW_PORT_HTTPS=8443 + +# SSL +#BW_ENABLE_SSL=true +#BW_ENABLE_SSL_CA=true +#BW_SSL_CERT=ssl.crt +#BW_SSL_KEY=ssl.key +#BW_SSL_CA_CERT=ca.crt + +# Services +# Some services, namely for enterprise use cases, are disabled by default. Defaults shown below. +#BW_ENABLE_ADMIN=true +#BW_ENABLE_API=true +#BW_ENABLE_EVENTS=false +#BW_ENABLE_ICONS=true +#BW_ENABLE_IDENTITY=true +#BW_ENABLE_NOTIFICATIONS=true +#BW_ENABLE_SCIM=false +#BW_ENABLE_SSO=false + +#BW_ICONS_PROXY_TO_CLOUD=false + +# Mail +#globalSettings__mail__replyToEmail=noreply@$BW_DOMAIN +#globalSettings__mail__smtp__host=smtphost.example.com +#globalSettings__mail__smtp__port=587 +#globalSettings__mail__smtp__ssl=false +#globalSettings__mail__smtp__username=smtpusername +#globalSettings__mail__smtp__password=smtppassword + +# Yubikey +#globalSettings__yubico__clientId=REPLACE +#globalSettings__yubico__key=REPLACE + +# Other +#globalSettings__disableUserRegistration=false +#globalSettings__hibpApiKey=REPLACE +#adminSettings__admins=admin1@email.com,admin2@email.com diff --git a/docker-unified/supervisord/admin.ini b/docker-unified/supervisord/admin.ini new file mode 100644 index 000000000..113da5e99 --- /dev/null +++ b/docker-unified/supervisord/admin.ini @@ -0,0 +1,9 @@ +[program:admin] +autostart=true +autorestart=true +command=/usr/bin/dotnet "Admin.dll" +directory=/app/Admin +environment=ASPNETCORE_URLS="http://+:5000" +redirect_stderr=true +startsecs=15 +stdout_logfile=/var/log/bitwarden/admin.log diff --git a/docker-unified/supervisord/api.ini b/docker-unified/supervisord/api.ini new file mode 100644 index 000000000..410e1d8b8 --- /dev/null +++ b/docker-unified/supervisord/api.ini @@ -0,0 +1,9 @@ +[program:api] +autostart=true +autorestart=true +command=/usr/bin/dotnet "Api.dll" +directory=/app/Api +environment=ASPNETCORE_URLS="http://+:5001" +redirect_stderr=true +startsecs=15 +stdout_logfile=/var/log/bitwarden/api.log diff --git a/docker-unified/supervisord/events.ini b/docker-unified/supervisord/events.ini new file mode 100644 index 000000000..32093d2d1 --- /dev/null +++ b/docker-unified/supervisord/events.ini @@ -0,0 +1,9 @@ +[program:events] +autostart=true +autorestart=true +command=/usr/bin/dotnet "Events.dll" +directory=/app/Events +environment=ASPNETCORE_URLS="http://+:5003" +redirect_stderr=true +startsecs=15 +stdout_logfile=/var/log/bitwarden/events.log diff --git a/docker-unified/supervisord/icons.ini b/docker-unified/supervisord/icons.ini new file mode 100644 index 000000000..36489e8bb --- /dev/null +++ b/docker-unified/supervisord/icons.ini @@ -0,0 +1,9 @@ +[program:icons] +autostart=true +autorestart=true +command=/usr/bin/dotnet "Icons.dll" +directory=/app/Icons +environment=ASPNETCORE_URLS="http://+:5004" +redirect_stderr=true +startsecs=15 +stdout_logfile=/var/log/bitwarden/icons.log diff --git a/docker-unified/supervisord/identity.ini b/docker-unified/supervisord/identity.ini new file mode 100644 index 000000000..4b1600ce9 --- /dev/null +++ b/docker-unified/supervisord/identity.ini @@ -0,0 +1,10 @@ +[program:identity] +autostart=true +autorestart=true +command=/usr/bin/dotnet "Identity.dll" +directory=/app/Identity +environment=ASPNETCORE_URLS="http://+:5005" +priority=1 +redirect_stderr=true +startsecs=15 +stdout_logfile=/var/log/bitwarden/identity.log diff --git a/docker-unified/supervisord/nginx.ini b/docker-unified/supervisord/nginx.ini new file mode 100644 index 000000000..bc52f3f91 --- /dev/null +++ b/docker-unified/supervisord/nginx.ini @@ -0,0 +1,7 @@ +[program:nginx] +autostart=true +autorestart=true +command=nginx +redirect_stderr=true +startsecs=15 +stdout_logfile=/var/log/bitwarden/nginx.log diff --git a/docker-unified/supervisord/notifications.ini b/docker-unified/supervisord/notifications.ini new file mode 100644 index 000000000..2744ff711 --- /dev/null +++ b/docker-unified/supervisord/notifications.ini @@ -0,0 +1,9 @@ +[program:notifications] +autostart=true +autorestart=true +command=/usr/bin/dotnet "Notifications.dll" +directory=/app/Notifications +environment=ASPNETCORE_URLS="http://+:5006" +redirect_stderr=true +startsecs=15 +stdout_logfile=/var/log/bitwarden/notifications.log diff --git a/docker-unified/supervisord/scim.ini b/docker-unified/supervisord/scim.ini new file mode 100644 index 000000000..11d00d4c2 --- /dev/null +++ b/docker-unified/supervisord/scim.ini @@ -0,0 +1,9 @@ +[program:scim] +autostart=true +autorestart=true +command=/usr/bin/dotnet "Scim.dll" +directory=/app/Scim +environment=ASPNETCORE_URLS="http://+:5002" +redirect_stderr=true +startsecs=15 +stdout_logfile=/var/log/bitwarden/scim.log diff --git a/docker-unified/supervisord/sso.ini b/docker-unified/supervisord/sso.ini new file mode 100644 index 000000000..cb29c731a --- /dev/null +++ b/docker-unified/supervisord/sso.ini @@ -0,0 +1,9 @@ +[program:sso] +autostart=true +autorestart=true +command=/usr/bin/dotnet "Sso.dll" +directory=/app/Sso +environment=ASPNETCORE_URLS="http://+:5007" +redirect_stderr=true +startsecs=15 +stdout_logfile=/var/log/bitwarden/sso.log diff --git a/docker-unified/supervisord/supervisord.conf b/docker-unified/supervisord/supervisord.conf new file mode 100644 index 000000000..4cd6a8cb4 --- /dev/null +++ b/docker-unified/supervisord/supervisord.conf @@ -0,0 +1,15 @@ +[unix_http_server] +file=/run/supervisord.sock ; the path to the socket file + +[supervisord] +logfile=/var/log/supervisord.log ; main log file; default $CWD/supervisord.log +nodaemon=true ; start in foreground if true; default false + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[supervisorctl] +serverurl=unix:///run/supervisord.sock ; use a unix:// URL for a unix socket + +[include] +files = /etc/supervisor.d/*.ini diff --git a/dotnet-tools.json b/dotnet-tools.json deleted file mode 100644 index cff10c3ea..000000000 --- a/dotnet-tools.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "version": 1, - "isRoot": true, - "tools": { - "swashbuckle.aspnetcore.cli": { - "version": "5.0.0-rc4", - "commands": [ - "swagger" - ] - }, - "coverlet.console": { - "version": "3.0.3", - "commands": [ - "coverlet" - ] - }, - "dotnet-reportgenerator-globaltool": { - "version": "4.8.8", - "commands": [ - "reportgenerator" - ] - } - } -} \ No newline at end of file diff --git a/perf/MicroBenchmarks/Core/EncryptedStringAttributeTests.cs b/perf/MicroBenchmarks/Core/EncryptedStringAttributeTests.cs new file mode 100644 index 000000000..b7c397dfe --- /dev/null +++ b/perf/MicroBenchmarks/Core/EncryptedStringAttributeTests.cs @@ -0,0 +1,23 @@ +using BenchmarkDotNet.Attributes; +using Bit.Core.Utilities; + +namespace Bit.MicroBenchmarks.Core; + +[MemoryDiagnoser] +public class EncryptedStringAttributeTests +{ + private readonly EncryptedStringAttribute _encryptedStringAttribute; + public EncryptedStringAttributeTests() + { + _encryptedStringAttribute = new EncryptedStringAttribute(); + } + + public const string Short = @"2.QmFzZTY0UGFydA==|QmFzZTY0UGFydA==|QmFzZTY0UGFydA=="; + public const string Long = @"2.KllcSp3E124kblnMlCNQuQ==|G0jvyocNBOEzCyJ/f951Pz348MPi2RLzmsbfOAOtszi5L9WAkWe4L5T2gJukRMgDSvdE76MVUqREsgQZME52t8JFpVzsQU7Ee56szoJu\u002BAHHQkBNd5J2WirgprDRmIGiSdbvv2GoCszr1b2Ox/Pc\u002B9wjjzMjR6ZA3xhvy1UPyFdT5edQvIFVRSOEG7ivtV7RmGxiq7buP/g\u002BL/epeuiljkjU7KU8JbZRKaxhGLSiofEMlBtaTZtTGh3VKAHslUgPnRIRlHpjPDaT1Yw3la4YHbEOs4Y/XJ5sI4q5xXlK60gMgAlvlyH0mspezaBy367WBLu\u002BWC/4GqGBudhftSOED/aIS4PoCUvMdftwHunXjE2s5zDUwT66w30lvEvJbs7m/36fKAj9ujqOv9vEm1Ukjxhzk\u002BHHkLUcjrD57Zfn0P\u002BzK6wbneYBORObF70gUhcINv64GqgLFlEUecmKjK0ZgcmTXp8XuG2ZfplXAN1y8gySM3UAREhFj4oQtZq/QB64SlnOTAPkRjqy0khqWCmySqSSqKYCnzTfE7RUhR6FAgpWTo9qHZHkwNVk2EBWvMN0UctjmYIpoUBtqKPF2Oidhjnck\u002BqCa7jGIqGetERq9Cdg\u002Btk6bvzLexj/bVEJpiK53ghrDJKs5Ncox7cmLjIfoL5cb3ZUgiV3g\u002Bzqpq2RWn16d85Edmir4zlJPSA77BEGhFzZET3PyYqdWWcaAlDQbqeQ39zyuKUzRI0JH6yXsfCcTqZmsQ9Mj5OpqQdcgVlMXyvsY/mCsocpGKA0\u002BcQGQPZGgZ3cDcN13K4MTjiZ8BO9P7aLvgk5k5a3GFFsYVhe2lgbPeoASDHY48AX9yTnPTXGCHAB\u002BHiybFRyIabXhSnU491vRxPyCsEBMbL/GTUr0oulzixdOMYCKBYw3WcLGuA2gG1JyAl\u002BEzS/iU1G97bWvi8yMG6QsDhiAvgAt3BjU1C7kgHseM\u002BZHdpe1cwyFV\u002BzSfS0Hn5iVYcJVnkO7JiiTaMSQEjIk0q54stRGJ\u002BHC81F2kaf\u002Bi4aQ4rpq82yAJJMoGsdSyzeC8P2jR4HpsfJroJRYAPHUl8CIe0ZeWdvWjFwKGqxmPeFU2lazMEyyMZGFB1/8zP4Gxu2KarubWG1NRQY1sGCnH1\u002BvBsQrKtyBxyuwshNrUCN9UifOZDmYZ2FPHHdnNdGiaHyQVSDYqx/EpWkgkNl6h1Itpkb7sW/ByAu2EhHUJODfciYgyF4CsCs2iNboZNoMctY5H0VT704tt3AuS369PMWJzwKum\u002BHUrpLEyav0SUUSUlhWUvkWfW1O/Q3bADW72IXWS\u002BHUZ0E96tjpUDv60V7X0qLOCcjlhxRgGwPVw1V4FuxhmkX8UxSwlU39/aQUj8gpGr8Um8LWxIYw/mkV1ItTPh4IxpXxSnuGAIBjEBlRlqedFLF97tVDzYLddEh6SlIEh6ppdpDS6ghSpiylyh4JsaXtp1QGpoPUfkwcl1jWrRarj5G2hbQW3gkuug8cfGB0zHxfLwmKSHswFPa1Ne2kqf7jlO19ckIxqmHpbrn9myVcnqPQLhSxtzIjJUN6HG7xQdJ7Q7Tumj8gN9dN06IUEfhoYhUxcabTqm9jTspVQ7iXsvml3YeF8qJX/d\u002BnSUqcOmOod6/B1k54Dd9mhosi0So9XTGuVmgKz82r185wTx7mVgcaKPQZXIVxIPqxtsk1UI6IK5wpyWhB77nS3L83KGdxpdRTbPAhAj8tIKDrELzr3u5WytStGeH8melF7KnIzWmAs2vUJIlByFxgjm26u0C4Eid0DQVJJ4xWp5yt62WodZ80B3dUyjXUUuTyyVL8Y26zRZNuF/3G\u002BKc\u002BkN/lja44BPG5/FoDofgto3IlWvYzkoKB8oXhhL58Rc8fNr5LZIz\u002BTrweFXO2eoSP1xIcEuq2J\u002BZGLHElEmkwQA1u3UE\u002BySsElNAeWlx\u002BkQ0f\u002B0AqZzhei1PJ0VHqRXvwxYTqkeBQA2/95UTyKv15R/cbHVHexttqrc40oRwp7Cl\u002BzIJcRvKSUdfXa6MiQ13HvBpiG\u002BBoyvC2RHLlg\u002BwToSmCZFoPDt5wEP9TOMmG2HbCab1fLGkfQ2Sov1cRnPWt6SgtZFsIRyxxOglr44O\u002B56\u002B9QH7KmpEHjXANdOhYnNsw47TQEoMy9v8r23CUu\u002BX2yUcLxplTDxQXb5pNo5PXH0DlhIu3SGp/xu5tU5I7UXNdO85I9za/1wp/ylcl1PjXXnKx0E5FvXsOdUndgSE8TNxD8u6hfrbizTuAnFiJWCQzbDBMCT1SLggoq03iN\u002BKTSEWoh4l28GF\u002BwJsVU5PygNLuZVaDjlHVgeU5u5AhPO/0clIsFvJPaJ5WhstDlxGRXq0\u002BRBrx1ikMDXwFLfdbtj/U7O8cPCeU0UIJRzjjd9mG1Uyk2UNccJHzXt7RWKk7pCuNhG7cVOo55cICvndT1n6hwTC6mpXXv1pHiB8Ddg1csw7p2E6BVj0YhV1vTWTlKHYrNjv2F2f1NNPtRsCzOh2rOd7UCtV5wfB92PorADP9r3FNAQupVwCVkYymMPfaOPm5lpvT1WdORQZbKQRc10OzTnnOtFNaKWI4DffPuIR93wHj7JByG7MGmRkW1sAnmOuif24sMOYULcjTS0SdvUQhvvkCMfl/rtsFYDXnnCrzhcWPQ\u002BS2nIKt89h5rtjk73/rOmvAnIC8f\u002Bl84yM54Ifm2jGC8H1VZS6HmEFAJmciKsPHaBEGRxBL9FxTOzPM3KKXEUFANvm0lGQrzrpl4PlhauSf04BwxM9s9iikCVtEVA1E9e4dNs/MZmwNzwQLN36ZkABdu8ZVzfW4CpXO0aA3ZXbtNQuEpDWvpIsMTZUL9IYcLFtLI9ITuEhrluPVX6vnzRghM/DmSLr5zH\u002BDat9saZxvzpDpq4JW\u002BXcJ\u002Bk1D469N4grVNvbcymcQ8ZinJbyOOQS9t7H5hOG7zWbYb/paRQChCeCqGindCxnxjymGRnbShGtKzDq8GZHKDkkS0pm6g3laV6pPBlF0FMwzTm6IDFrWUXOjRgkPTr46t8PRkdEMKXHSNWMn4QiWC5\u002BiKUEvqt\u002BjeY1RzKQB2gd1xBfI9hLs2L\u002BK7S3GOblvM/R1FAK3Rnd3oZ41hZ2wHSH4x1mvLjDWVWmLOQt9pzn3DSX7\u002BJqhnWtF6nYNm\u002BIyu5bZRtyBz1tpo1FezJxx1o2r1QTi3M1FTLLndAaxtXCwzcBLBxG7PZKI0rfVExcK3FYO2bUYZS/HpALLVkuWg\u002BTuaZPmkDyUkxSsXIU9ERIVOz0\u002BYgsCQrBj/Z/xY38jy5jCVvXAbmAwv1ZsyZOp657LXHUTz6EmQAVWDuMZfX97WyIn5stWtT\u002B8Ppeda82TecJBVVKaDduMwvBb3jRNTtCappRoQm2ea1rBjvpWXEtGsAZcIu74Exz\u002BmS\u002BpKEOR0JAElqMIRLTNmCXVSXEjF5Oo1s3vIR4IZ2XGm9EF0Lm9Gld5OR1ganZR1AyPJpHOGclq2FGKSlamwyh6TzZDUnnExsyaQjr9Dkuy5mQdIeg8RdsjjvMqeCVZXV/jIo//dwkGm9nCVLud9jsKOdyl5ELhKyNHryXkyZVngF7qL\u002BWpoEQkW9G5j5aO5FrIt\u002B3fgqDr5KP/wJkdfKQM0GG0FI989t6CzzajfGxWgn\u002B1nUhkjOyHBee6zBtoT8GA/K0g8SvrKCJQeaic1UFC\u002BXZ1UcwbFZK43pc9iYyoxMboxi\u002Bq5ZX0nQXseiv8OsijrFmm5d/0R\u002BRpSLeHIz9uetBKZpSbLJnCNvugTVlFmYgocPC1zqWAj2MrqdYaf5Vzy0uXj5gKMZxAD9ZYeTatiL5C/GuMsaidvb8bh1E7XV5apf3lgLAKxHnqjE5CJzU9I/itBTHXysMeCZrkhDeAS0UhtRyNiMoahKBc6qFkiphnPi1kM0x0lzZRRnBz8cgkvdEt769c3BYqHa7gWC3DlDjaHKuvqSd1t4eDjSlU2PeI7RYwJwBfF5LdPLevsAkyvGCIHKmfjX38SeSrlgL9E2JsRQpeypKWiVpRunM9he/9jADAVFwEpck3bBz/ANo2c6gX3/haAw1xXunkq6\u002BIp80XVLeoys44vFv3QPvZ6GZ5QCSJ/AP42fSdENTYkB7MhBwMgLmcyATVFYA16yS7q8dIAowO5GL3/vCTe4\u002B47Sg6U9vgclFw1T55oZ/apQ5bdPCZ7N4M2nD5DfI74XuoQPfrDkXIhCP\u002BHh/v8BV9t2mPH0LyXGviwl4ewrtrtsOCV3H4/KsxiMPVkTFofHjjXU30WkcBaCB985p1oPWii4d4QJvnubN3z4\u002B51mhYPMCs7Uu05we9zEDH0tPfWC2Jm9C7Hv\u002BT5LgWFOV/d7\u002BYR0AajpF3xKWulZu\u002BwDXruRAHhLqCwsGxq9GlLal8DURCGxQG6Keyx/PTv9L6yEZmMIlNdP3xNEOPaDNwNIWczPC6CkuPbufgsFxn9I3krlZS2x/5/ZuIdoZu9CqPr5af7TIqsXWdczEQZ7NhefA0\u002BXeImBoflGx2I45UG8CeiF0FMnX16rzpF48rx/YZkl/PFwQYcN\u002BVrQmXrqD6eSzyHvRWSi8KQP7te2LqBFw1p5dxgREbCTLlcvQckcGgiyctDjS1wYe1VaagedfrsQpYXdQkOxhL9aE6r1\u002Bj8eHenC6ezxMc6LnsLog2wDMAXlzmq9KkladqyltzL2sgTyg7R57agFrjJtGQfLb0IY0O8vhkwqq2KYhWJ7jOJA\u002BR0k62HZEeNMsreNBNO5l0QCQ0\u002BUGKpEtvX/F5DNj07Swz\u002BoiHWq2933yQ4pzXnYnIfNgb8Ni5Js/GMn5HNJFvsNgYQ/xV1iKnIH43qDoyw55t22Sg4kcHhQBSBSWEZ7u/iVHCSN3hW7ma5Eabbk15/Jg4TurDpthtufZqZ2ZAiOWBaiOUC/OHUI8PjquycGpOGrTauVh\u002BCiS47S5nMPrF6ROVTT\u002BjrfaC9cw0\u002BIf0wEMG/W/p57n5YE7JnLr5kwKEDHCk3mMdxqhYzIoRBiKndblcM1\u002B7Glm5dN78R4mgt2QUGERnVkP\u002BoDxszTshjeZ0EX1l9zuF3V2zt1WzzDH8BiY/zVrhuJsRGSwLsVCpBKZArSfa1cLIufuF9cj5QtYu9NyKi2aVDILdN1fsFqaZ9i5Zsg8ohsLHzYQtY1RZVhNrmI=|MiBu248yFOf9eakCDaO\u002BK7aU2gu/T9R8YSbf7kkHuXg="; + + [Params(Short, Long)] + public string EncryptedString { get; set; } = null!; + + [Benchmark] + public bool IsValid() => _encryptedStringAttribute.IsValid(EncryptedString); +} diff --git a/perf/MicroBenchmarks/MicroBenchmarks.csproj b/perf/MicroBenchmarks/MicroBenchmarks.csproj new file mode 100644 index 000000000..b29687af4 --- /dev/null +++ b/perf/MicroBenchmarks/MicroBenchmarks.csproj @@ -0,0 +1,18 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + + + + + diff --git a/perf/MicroBenchmarks/Program.cs b/perf/MicroBenchmarks/Program.cs new file mode 100644 index 000000000..4112e920d --- /dev/null +++ b/perf/MicroBenchmarks/Program.cs @@ -0,0 +1,4 @@ +using System.Reflection; +using BenchmarkDotNet.Running; + +BenchmarkRunner.Run(Assembly.GetEntryAssembly()); diff --git a/perf/MicroBenchmarks/packages.lock.json b/perf/MicroBenchmarks/packages.lock.json new file mode 100644 index 000000000..94f9b5bb6 --- /dev/null +++ b/perf/MicroBenchmarks/packages.lock.json @@ -0,0 +1,2693 @@ +{ + "version": 1, + "dependencies": { + "net6.0": { + "BenchmarkDotNet": { + "type": "Direct", + "requested": "[0.13.2, )", + "resolved": "0.13.2", + "contentHash": "82IflYxY8qnQXEA3kXtqC9pntrkJYJZbQ9PV7hEV/XcfCtOdwLz84ilyO8tLRVbiliWttvmt/v44P+visN+fPQ==", + "dependencies": { + "BenchmarkDotNet.Annotations": "0.13.2", + "CommandLineParser": "2.4.3", + "Iced": "1.17.0", + "Microsoft.CodeAnalysis.CSharp": "3.0.0", + "Microsoft.Diagnostics.Runtime": "2.2.332302", + "Microsoft.Diagnostics.Tracing.TraceEvent": "3.0.2", + "Microsoft.DotNet.PlatformAbstractions": "3.1.6", + "Perfolizer": "0.2.1", + "System.Management": "6.0.0", + "System.Reflection.Emit": "4.7.0", + "System.Reflection.Emit.Lightweight": "4.7.0", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "AspNetCoreRateLimit": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "FzXAJFgaRjKfnKAVwjEEC7OAGQM5v/I3sQw2tpzmR0yHTCGhUAxZzDuwZiXTk8XLrI6vovzkqKkfKmiDl3nYMg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.1", + "Microsoft.Extensions.Options": "6.0.0", + "Newtonsoft.Json": "13.0.1" + } + }, + "AspNetCoreRateLimit.Redis": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "CsSGy/7SXt6iBOKg0xCvsRjb/ZHshbtr2Of1MHc912L2sLnZqadUrTboyXZC+ZlgEBeJ14GyjPTu8ZyfEhGUnw==", + "dependencies": { + "AspNetCoreRateLimit": "4.0.2", + "StackExchange.Redis": "2.5.43" + } + }, + "AWSSDK.Core": { + "type": "Transitive", + "resolved": "3.7.10.11", + "contentHash": "B+M7ggPC0FogATRPQxDXL0eTusCQtXulW4zCuX39yiHV8+u9MEXRytcAw0ZA3zFBYYx6ovl9lklho6OQo1DRRQ==" + }, + "AWSSDK.SimpleEmail": { + "type": "Transitive", + "resolved": "3.7.0.150", + "contentHash": "rc/4ZnISfbgTfqz5/BWqMHBAzk4R09qfe1xkdJf2jXo44Zn2X72W8IiLLweBtmNhL7d8Tcf6UCtOHYkFwxHvug==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "AWSSDK.SQS": { + "type": "Transitive", + "resolved": "3.7.2.47", + "contentHash": "RPTVBsY333n+aIEqw148Envx9OQkE1/jhjlioNXDP6BrA3fAPN9A+2HoA02c0KSp/sazXYWg8w/kDL8FchH8Dw==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.24.0", + "contentHash": "+/qI1j2oU1S4/nvxb2k/wDsol00iGf1AyJX5g3epV7eOpQEP/2xcgh/cxgKMeFgn3U2fmgSiBnQZdkV+l5y0Uw==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Numerics.Vectors": "4.5.0", + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Extensions.AspNetCore.DataProtection.Blobs": { + "type": "Transitive", + "resolved": "1.2.1", + "contentHash": "wxvkC6DeWThBtaPbsWdicp5Ltya4J8JuhxmZJDQkhnXG7oihfu8RqBV6w/X1nMieuIOq1qQaGTvjx7nEHHfxSQ==", + "dependencies": { + "Azure.Core": "1.14.0", + "Azure.Storage.Blobs": "12.8.0", + "Microsoft.AspNetCore.DataProtection": "2.1.0" + } + }, + "Azure.Identity": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "EycyMsb6rD2PK9P0SyibFfEhvWWttdrYhyPF4f41uzdB/44yQlV+2Wehxyg489Rj6gbPvSPgbKq0xsHJBhipZA==", + "dependencies": { + "Azure.Core": "1.24.0", + "Microsoft.Identity.Client": "4.39.0", + "Microsoft.Identity.Client.Extensions.Msal": "2.19.3", + "System.Memory": "4.5.4", + "System.Security.Cryptography.ProtectedData": "4.7.0", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Storage.Blobs": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "50eRjIhY7Q1JN7kT2MSawDKCcwSb7uRZUkz00P/BLjSg47gm2hxUYsnJPyvzCHntYMbOWzrvaVQTwYwXabaR5Q==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Text.Json": "4.7.2" + } + }, + "Azure.Storage.Common": { + "type": "Transitive", + "resolved": "12.10.0", + "contentHash": "vYkHGzUkdZTace/cDPZLG+Mh/EoPqQuGxDIBOau9D+XWoDPmuUFGk325aXplkFE4JFGpSwoytNYzk/qBCaiHqg==", + "dependencies": { + "Azure.Core": "1.22.0", + "System.IO.Hashing": "6.0.0" + } + }, + "Azure.Storage.Queues": { + "type": "Transitive", + "resolved": "12.9.0", + "contentHash": "jDiyHtsCUCrWNvZW7SjJnJb46UhpdgQrWCbL8aWpapDHlq9LvbvxYpfLh4dfKAz09QiTznLMIU3i+md9+7GzqQ==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, + "BenchmarkDotNet.Annotations": { + "type": "Transitive", + "resolved": "0.13.2", + "contentHash": "+SGOYyXT6fiagbtrni38B8BqBgjruYKU3PfROI0lDIYo8jQ+APUmLKMEswK7zwR5fEOCrDmoAHSH6oykBkqPgA==" + }, + "BitPay.Light": { + "type": "Transitive", + "resolved": "1.0.1907", + "contentHash": "QTTIgXakHrRNQPxNyH7bZ7frm0bI8N6gRDtiqVyKG/QYQ+KfjN70xt0zQ0kO0zf8UBaKuwcV5B7vvpXtzR9ijg==", + "dependencies": { + "Newtonsoft.Json": "12.0.2" + } + }, + "Braintree": { + "type": "Transitive", + "resolved": "5.12.0", + "contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "System.Xml.XPath.XmlDocument": "4.3.0" + } + }, + "CommandLineParser": { + "type": "Transitive", + "resolved": "2.4.3", + "contentHash": "U2FC9Y8NyIxxU6MpFFdWWu1xwiqz/61v/Doou7kmVjpeIEMLWyiNNkzNlSE84kyJ0O1LKApuEj5z48Ow0Hi4OQ==" + }, + "Fido2": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "S0Bz1vfcKlO4Jase3AWp5XnQ746psf4oGx5kL+D2A10j1SsjoAOAIIpanSwfi0cEepDHgk1bClcOKY5TjOzGdA==", + "dependencies": { + "Fido2.Models": "3.0.1", + "Microsoft.Extensions.Http": "6.0.0", + "NSec.Cryptography": "22.4.0", + "System.Formats.Cbor": "6.0.0", + "System.IdentityModel.Tokens.Jwt": "6.17.0" + } + }, + "Fido2.AspNet": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "5n5shEXD7RFUyTesjUHGDjkpgES7j4KotQo1GwUcS08k+fx+1tl/zCFHJ9RFDuUwO+S681ZILT2PyA67IPYpaA==", + "dependencies": { + "Fido2": "3.0.1", + "Fido2.Models": "3.0.1" + } + }, + "Fido2.Models": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "mgjcuGETuYSCUEaZG+jQeeuuEMkDLc4GDJHBvKDdOz6oSOWp5adPdWP4btZx7Pi+9fu4szN3JIjJmby67MaILw==" + }, + "Handlebars.Net": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "p60QyeBYpZmcZdIXRMqs9XySIBaxJ0lj3+QD0EJVr4ybTigOTCumXMMin5dPwjo9At1UwkDZ3gGwa1lmGjG6DA==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "Iced": { + "type": "Transitive", + "resolved": "1.17.0", + "contentHash": "8x+HCVTl/HHTGpscH3vMBhV8sknN/muZFw9s3TsI8SA6+c43cOTCi2+jE4KsU8pNLbJ++iF2ZFcpcXHXtDglnw==" + }, + "IdentityModel": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "System.Text.Encodings.Web": "4.7.0" + } + }, + "IdentityModel.AspNetCore.OAuth2Introspection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==", + "dependencies": { + "IdentityModel": "4.0.0" + } + }, + "IdentityServer4": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==", + "dependencies": { + "IdentityModel": "4.4.0", + "IdentityServer4.Storage": "4.1.2", + "Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0", + "Newtonsoft.Json": "12.0.2" + } + }, + "IdentityServer4.AccessTokenValidation": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==", + "dependencies": { + "IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1", + "Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0" + } + }, + "IdentityServer4.Storage": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==", + "dependencies": { + "IdentityModel": "4.4.0" + } + }, + "libsodium": { + "type": "Transitive", + "resolved": "1.0.18.2", + "contentHash": "flArHoVdscSzyV8ZdPV+bqqY2TTFlaN+xZf/vIqsmHI51KVcD/mOdUPaK3n/k/wGKz8dppiktXUqSmf3AXFgig==" + }, + "MailKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "5MTpTqmjqT7HPvYbP3HozRZMth5vSaT0ReN0iM3rAM4CgLI/R1qqtLDDNWGnFFIlcNzeJkZQRJJMkv8cgzWBbA==", + "dependencies": { + "MimeKit": "3.2.0" + } + }, + "Microsoft.AspNetCore.Authentication.JwtBearer": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "joDS3+lD1i9qcdFLWP4D316t3bHpezmTNOzbMIf9ZcRPX4QTuiUutZcQn/kZplf3BiLHqwUChZXxPjCAMKaKAQ==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0" + } + }, + "Microsoft.AspNetCore.Authentication.OpenIdConnect": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0" + } + }, + "Microsoft.AspNetCore.Cryptography.Internal": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "/0FX1OqckMmXAAlsHgBFNymTZuq4nuAOMhiwm6e8CEMi2aOjnMYwiMc7mtvpGTAO0O4C0zwx+iaChxDgvqit2A==" + }, + "Microsoft.AspNetCore.Cryptography.KeyDerivation": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "1Lbwrxg/HRY/nbrkcrB3EUXUYQN8Tkw7Ktgb6/2on2P7ybT5aM59H05gk+OBC8ZTBxwdle9e1tyT3wxEYKw5xw==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "6.0.4" + } + }, + "Microsoft.AspNetCore.DataProtection": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "G+UoMHL0xiyFh30wkL7Bv/XL6eugTAKYhLPS53k1/Me1bYRwOOw+8VL/q0ppq3/yMzpHX+MkExaCTDlYl48FgA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "2.1.0", + "Microsoft.AspNetCore.DataProtection.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.1.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0", + "Microsoft.Extensions.Logging.Abstractions": "2.1.0", + "Microsoft.Extensions.Options": "2.1.0", + "Microsoft.Win32.Registry": "4.5.0", + "System.Security.Cryptography.Xml": "4.5.0", + "System.Security.Principal.Windows": "4.5.0" + } + }, + "Microsoft.AspNetCore.DataProtection.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "2+HVDhUqrnV9+EJNEewSy+Gk4hOVPzLPMpFDZI7kuH7NWxtbNkI6A6gT5lO2/kEPMyM8/iLWtohbOwjpC9rHVw==" + }, + "Microsoft.AspNetCore.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "1TQgBfd/NPZLR2o/h6l5Cml2ZCF5hsyV4h9WEwWwAIavrbdTnaNozGGcTOd4AOgQvogMM9UM1ajflm9Cwd0jLQ==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Http.Abstractions": "2.1.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "YTKMi2vHX6P+WHEVpW/DS+eFHnwivCSMklkyamcK1ETtc/4j8H3VR0kgW8XIBqukNxhD8k5wYt22P7PhrWSXjQ==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "Microsoft.Extensions.Configuration.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Http.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "vbFDyKsSYBnxl3+RABtN79b0vsTcG66fDY8vD6Nqvu9uLtSej70Q5NcbGlnN6bJpZci5orSdgFTHMhBywivDPg==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Features": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "UmkUePxRjsQW0j5euFFscBwjvTu25b8+qIK/2fI3GvcqQ+mkwgbWNAT8b/Gkoei1m2bTWC07lSdutuRDPPLcJA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.0" + } + }, + "Microsoft.Azure.Amqp": { + "type": "Transitive", + "resolved": "2.4.11", + "contentHash": "7x5fu2f6TLQDDJS0sY5qW8/daFwJaY9O75YvU8RcUfRzbug+9YGjXUBxoRrprgyi0jxdBAMQL05p1s783SOSFQ==", + "dependencies": { + "System.Net.WebSockets.Client": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.Azure.Cosmos": { + "type": "Transitive", + "resolved": "3.24.0", + "contentHash": "QpUe5ho6OzlXwgcJVgAmOR7t3XLC9RI4t8T96RZY61pSOIllPOJdp30L0LwA16tKcqi5r2KayEgWO/MS9fh/6A==", + "dependencies": { + "Azure.Core": "1.3.0", + "Microsoft.Bcl.AsyncInterfaces": "1.0.0", + "Microsoft.Bcl.HashCode": "1.1.0", + "Newtonsoft.Json": "10.0.2", + "System.Buffers": "4.5.1", + "System.Collections.Immutable": "1.7.0", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Memory": "4.5.4", + "System.Numerics.Vectors": "4.5.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3", + "System.Threading.Tasks.Extensions": "4.5.4", + "System.ValueTuple": "4.5.0" + } + }, + "Microsoft.Azure.Cosmos.Table": { + "type": "Transitive", + "resolved": "1.0.8", + "contentHash": "ToeEd1yijM7nQfLYvdFLG//RjKPmfqm45eOm86UAKrxtyGI/CXqP8iL74mzBp6mZ9A/K/ZYA2fVdpH0xHR5Keg==", + "dependencies": { + "Microsoft.Azure.DocumentDB.Core": "2.11.2", + "Microsoft.OData.Core": "7.6.4", + "Newtonsoft.Json": "10.0.2" + } + }, + "Microsoft.Azure.DocumentDB.Core": { + "type": "Transitive", + "resolved": "2.11.2", + "contentHash": "cA8eWrTFbYrkHrz095x4CUGb7wqQgA1slzFZCYexhNwz6Zcn3v+S1yvWMGwGRmRjT0MKU9tYdFWgLfT0OjSycw==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "Newtonsoft.Json": "9.0.1", + "System.Collections.Immutable": "1.3.0", + "System.Collections.NonGeneric": "4.0.1", + "System.Collections.Specialized": "4.0.1", + "System.Diagnostics.TraceSource": "4.0.0", + "System.Dynamic.Runtime": "4.0.11", + "System.Linq.Queryable": "4.0.1", + "System.Net.Http": "4.3.4", + "System.Net.NameResolution": "4.0.0", + "System.Net.NetworkInformation": "4.1.0", + "System.Net.Requests": "4.0.11", + "System.Net.Security": "4.3.2", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Security.SecureString": "4.0.0" + } + }, + "Microsoft.Azure.NotificationHubs": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "C2SssjX3e6/HIo1OCImQDDVOn64d1+gkgEmgxJryzkwixyivJHWH2YIgxZs33pyzVQcZWx5PR2tqLkQ7riSq8Q==", + "dependencies": { + "Microsoft.Extensions.Caching.Memory": "3.1.8", + "Newtonsoft.Json": "12.0.3" + } + }, + "Microsoft.Azure.ServiceBus": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "wyZNJggyFNtKxd+HgvcTiuRYuTjDGi+pgE4RcBvFbfvNiarKr5AOlE4Ne7on1eUJZuMuEa19wN5dj694HlP60A==", + "dependencies": { + "Microsoft.Azure.Amqp": "2.4.11", + "Microsoft.Azure.Services.AppAuthentication": "[1.0.3, 2.0.0)", + "Newtonsoft.Json": "10.0.3", + "System.Diagnostics.DiagnosticSource": "4.5.1", + "System.IdentityModel.Tokens.Jwt": "5.4.0" + } + }, + "Microsoft.Azure.Services.AppAuthentication": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "ywpQaK1klu1IoX4VUf+TBmU4kR71aWNI6O5rEIJU8z28L2xhJhnIm7k2Nf1Zu/PygeuOtt5g0QPCk5+lLltbeQ==", + "dependencies": { + "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.14.2", + "NETStandard.Library": "1.6.1", + "System.Diagnostics.Process": "4.3.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "yuvf07qFWFqtK3P/MRkEKLhn5r2UbSpVueRziSqj0yJQIKFwG1pq9mOayK3zE5qZCTs0CbrwL9M6R8VwqyGy2w==" + }, + "Microsoft.Bcl.HashCode": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "J2G1k+u5unBV+aYcwxo94ip16Rkp65pgWFb0R6zwJipzWNMgvqlWeuI7/+R+e8bob66LnSG+llLJ+z8wI94cHg==" + }, + "Microsoft.CodeAnalysis.Analyzers": { + "type": "Transitive", + "resolved": "2.6.2-beta2", + "contentHash": "rg5Ql73AmGCMG5Q40Kzbndq7C7S4XvsJA+2QXfZBCy2dRqD+a7BSbx/3942EoRUJ/8Wh9+kLg2G2qC46o3f1Aw==" + }, + "Microsoft.CodeAnalysis.Common": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "HEnLZ9Op5IoXeuokhfSLIXstXfEyPzXhQ/xsnvUmxzb+7YpwuLk57txArzGs/Wne5bWmU7Uey4Q1jUZ3++heqg==", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "2.6.2-beta2", + "System.Collections.Immutable": "1.5.0", + "System.Memory": "4.5.1", + "System.Reflection.Metadata": "1.6.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.0", + "System.Text.Encoding.CodePages": "4.5.0", + "System.Threading.Tasks.Extensions": "4.5.0" + } + }, + "Microsoft.CodeAnalysis.CSharp": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "hWFUxc0iUbVvIKWJODErOeOa5GiqZuEcetxaCfHqZ04zHy0ZCLx3v4/TdF/6Erx1mXPHfoT2Tiz5rZCQZ6OyxQ==", + "dependencies": { + "Microsoft.CodeAnalysis.Common": "[3.0.0]" + } + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, + "Microsoft.Data.SqlClient": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "uu8dfrsx081cSbEevWuZAvqdmANDGJkbLBL2G3j0LAZxX1Oy8RCVAaC4Lcuak6jNicWP6CWvHqBTIEmQNSxQlw==", + "dependencies": { + "Azure.Identity": "1.6.0", + "Microsoft.Data.SqlClient.SNI.runtime": "5.0.1", + "Microsoft.Identity.Client": "4.45.0", + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.21.0", + "Microsoft.SqlServer.Server": "1.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Buffers": "4.5.1", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Diagnostics.DiagnosticSource": "5.0.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime.Caching": "5.0.0", + "System.Security.Cryptography.Cng": "5.0.0", + "System.Security.Principal.Windows": "5.0.0", + "System.Text.Encoding.CodePages": "5.0.0", + "System.Text.Encodings.Web": "4.7.2" + } + }, + "Microsoft.Data.SqlClient.SNI.runtime": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "y0X5MxiNdbITJYoafJ2ruaX6hqO0twpCGR/ipiDOe85JKLU8WL4TuAQfDe5qtt3bND5Je26HnrarLSAMMnVTNg==" + }, + "Microsoft.Diagnostics.NETCore.Client": { + "type": "Transitive", + "resolved": "0.2.251802", + "contentHash": "bqnYl6AdSeboeN4v25hSukK6Odm6/54E3Y2B8rBvgqvAW0mF8fo7XNRVE2DMOG7Rk0fiuA079QIH28+V+W1Zdg==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.0", + "Microsoft.Extensions.Logging": "2.1.1" + } + }, + "Microsoft.Diagnostics.Runtime": { + "type": "Transitive", + "resolved": "2.2.332302", + "contentHash": "Hp84ivxSKIMTBzYSATxmUsm3YSXHWivcwiRRbsydGmqujMUK8BAueLN0ssAVEOkOBmh0vjUBhrq7YcroT7VCug==", + "dependencies": { + "Microsoft.Diagnostics.NETCore.Client": "0.2.251802", + "System.Collections.Immutable": "5.0.0", + "System.Runtime.CompilerServices.Unsafe": "5.0.0" + } + }, + "Microsoft.Diagnostics.Tracing.TraceEvent": { + "type": "Transitive", + "resolved": "3.0.2", + "contentHash": "Pr7t+Z/qBe6DxCow4BmYmDycHe2MrGESaflWXRcSUI4XNGyznx1ttS+9JNOxLuBZSoBSPTKw9Dyheo01Yi6anQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "4.5.3" + } + }, + "Microsoft.DotNet.PlatformAbstractions": { + "type": "Transitive", + "resolved": "3.1.6", + "contentHash": "jek4XYaQ/PGUwDKKhwR8K47Uh1189PFzMeLqO83mXrXQVIpARZCcfuDedH50YDTepBkfijCZN5U/vZi++erxtg==" + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bcz5sSFJbganH0+YrfvIjJDIcKNW7TL07C4d1eTmXy/wOt52iz4LVogJb6pazs7W0+74j0YpXFErvp++Aq5Bsw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.Memory": { + "type": "Transitive", + "resolved": "3.1.8", + "contentHash": "u04q7+tgc8l6pQ5HOcr6scgapkQQHnrhpGoCaaAZd24R36/NxGsGxuhSmhHOrQx9CsBLe2CVBN/4CkLlxtnnXw==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "3.1.8", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8", + "Microsoft.Extensions.Options": "3.1.8" + } + }, + "Microsoft.Extensions.Caching.StackExchangeRedis": { + "type": "Transitive", + "resolved": "6.0.6", + "contentHash": "bdVQpYm1hcHf0pyAypMjtDw3HjWQJ89UzloyyF1OBs56QlgA1naM498tP2Vjlho5vVRALMGPYzdRKCen8koubw==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "StackExchange.Redis": "2.2.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "tq2wXyh3fL17EMF2bXgRhU7JrbO3on93MRKYxzz4JzzvuGSA1l0W3GI9/tl8EO89TH+KWEymP7bcFway6z9fXg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "IznHHzGUtrdpuQqIUdmzF6TYPcsYHONhHh3o9dGp39sX/9Zfmt476UnhvU0UhXgJnXXAikt/MpN6AuSLCCMdEQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.0.0" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "pnyXV1LFOsYjGveuC07xp0YHIyGq7jRq5Ncb5zrrIieMLWVwgMyYxcOH0jTnBedDT4Gh1QinSqsjqzcieHk1og==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "V4Dth2cYMZpw3HhGw9XUDIijpI6gN+22LDt0AhufIgOppCUfpWX4483OmN+dFXRJkJLc8Tv0Q8QK+1ingT2+KQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GJGery6QytCzS/BxJ96klgG9in3uH26KcUBbiVG/coNDXCRq6LGVVlUT4vXq34KPuM+R2av+LeYdX9h4IZOCUg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "Fy8yr4V6obi7ZxvKYI1i85jqtwMq8tqyxQVZpRSkgeA8enqy/KvBIMdcuNdznlxQMZa72mvbHqb7vbg4Pyx95w==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "k6PWQMuoBDGGHOQTtyois2u4AwyVcIwL2LaSLlTZQm2CYcJ1pxbt6jfAnpWmzENA/wfrYRI/X9DTLoUkE4AsLw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.DependencyModel": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "Iaectmzg9Dc4ZbKX/FurrRjgO/I8rTumL5UU+Uube6vZuGetcnXoIgTA94RthFWePhdMVm8MMhVFJZdbzMsdyQ==", + "dependencies": { + "System.Text.Json": "4.6.0" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "3.1.8", + "contentHash": "7ZJUKwPipkDvuv2KJPZ3r01wp2AWNMiYH+61i0dL89F7QICknjKpWgLKLpTSUYFgl77S3b4264I6i4HzDdrb2A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.8", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.FileProviders.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "15+pa2G0bAMHbHewaQIdr/y6ag2H3yh4rd9hTXavtWDzQBkvpe2RMqFg8BxDpcQWssmjmBApGPcw93QRz6YcMg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Core": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "8vBsyGkA8ZI3lZvm1nf+9ynRC/TzPD+UtbdgTlKk+cz+AW5I41LrK8f/adGej5uXgprOA2DMjZw33vZG6vyXxA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Stores": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "linRCnWBfnqg8qjrd9u/KMISy8O4a6X/GRhpHXU0ar654YQw9LJ/Ht+psx8QLqSX5EsCBbBCZzuamatH2FWIyQ==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Identity.Core": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y/lGICwO27fCkQRK3tZseVzFjZaxfGmui990E67sB4MuiPzdJHnJDS/BeYWrHShSSBgCl4KyKRx4ux686fftPg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.0.0", + "Microsoft.Extensions.Options": "2.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Identity.Client": { + "type": "Transitive", + "resolved": "4.45.0", + "contentHash": "ircobISCLWbtE5eEoLKU+ldfZ8O41vg4lcy38KRj/znH17jvBiAl8oxcyNp89CsuqE3onxIpn21Ca7riyDDrRw==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.18.0" + } + }, + "Microsoft.Identity.Client.Extensions.Msal": { + "type": "Transitive", + "resolved": "2.19.3", + "contentHash": "zVVZjn8aW7W79rC1crioDgdOwaFTQorsSO6RgVlDDjc7MvbEGz071wSNrjVhzR0CdQn6Sefx7Abf1o7vasmrLg==", + "dependencies": { + "Microsoft.Identity.Client": "4.38.0", + "System.Security.Cryptography.ProtectedData": "4.5.0" + } + }, + "Microsoft.IdentityModel.Abstractions": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "XeE6LQtD719Qs2IG7HDi1TSw9LIkDbJ33xFiOBoHbApVw/8GpIBCbW+t7RwOjErUDyXZvjhZliwRkkLb8Z1uzg==" + }, + "Microsoft.IdentityModel.Clients.ActiveDirectory": { + "type": "Transitive", + "resolved": "3.14.2", + "contentHash": "TNsJJMiRnkeby1ovThVoV9yFsPWjAdluwOA+Nf0LtSsBVVrKQv8Qp4kYOgyNwMVj+pDwbhXISySk+4HyHVWNZQ==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "System.Runtime.Serialization.Json": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.IdentityModel.JsonWebTokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "d3h1/BaMeylKTkdP6XwRCxuOoDJZ44V9xaXr6gl5QxmpnZGdoK3bySo3OQN8ehRLJHShb94ElLUvoXyglQtgAw==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "tuEhHIQwvBEhMf8I50hy8FHmRSUkffDFP5EdLsSDV4qRcl2wvOPkQxYqEzWkh+ytW6sbdJGEXElGhmhDfAxAKg==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "0FqY5cTLQKtHrClzHEI+QxJl8OBT2vUiEQQB7UKk832JDiJJmetzYZ3AdSrPjN/3l3nkhByeWzXnhrX0JbifKg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "vtSKL7n6EnAsLyxmiviusm6LKrblT2ndnNqN6rvVq6iIHAnPCK9E2DkDx6h1Jrpy1cvbp40r0cnTg23nhEAGTA==", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "6.21.0", + "System.IdentityModel.Tokens.Jwt": "6.21.0" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "AAEHZvZyb597a+QJSmtxH3n2P1nIJGpZ4Q89GTenknRx6T6zyfzf592yW/jA5e8EHN4tNMjjXHQaYWEq5+L05w==", + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "Microsoft.IdentityModel.Logging": "6.21.0", + "System.Security.Cryptography.Cng": "4.5.0" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.OData.Core": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "/EjnJezMBjXf8OjcShhGzPY7pOO0CopgoZGhS6xsP3t2uhC+O72IBHgtQ7F3v1rRXWVtJwLGhzE1GfJUlx3c4Q==", + "dependencies": { + "Microsoft.OData.Edm": "[7.6.4]", + "Microsoft.Spatial": "[7.6.4]" + } + }, + "Microsoft.OData.Edm": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "MSSmA6kIfpgFTtNpOnnayoSj/6KSzHC1U9KOjF7cTA1PG4tZ7rIMi1pvjFc8CmYEvP4cxGl/+vrCn+HpK26HTQ==" + }, + "Microsoft.Spatial": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "3mB+Frn4LU4yb5ie9R752QiRn0Hvp9PITkSRofV/Lzm9EyLM87Fy9ziqgz75O/c712dh6GxuypMSBUGmNFwMeA==" + }, + "Microsoft.SqlServer.Server": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug==" + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "Microsoft.Win32.Registry": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "Microsoft.Win32.SystemEvents": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==" + }, + "MimeKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "l9YHMBhBUwY7qQHUp8fw0EvjcbmhN4Iggz6MdjqIShBf42+0nJTa5gu0kuupCOPuiARc9ZaS9c9f0gKz4OnxKw==", + "dependencies": { + "Portable.BouncyCastle": "1.9.0", + "System.Security.Cryptography.Pkcs": "6.0.0" + } + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "NSec.Cryptography": { + "type": "Transitive", + "resolved": "22.4.0", + "contentHash": "lEntcPYd7h3aZ8xxi/y/4TML7o8w0GEGqd+w4L1omqFLbdCBmhxJAeO2YBmv/fXbJKgKCQLm7+TD4bR605PEUQ==", + "dependencies": { + "libsodium": "[1.0.18.2, 1.0.19)" + } + }, + "Otp.NET": { + "type": "Transitive", + "resolved": "1.2.2", + "contentHash": "2hrZfkbzeWJ3tNXXt/1beg4IY+nS4F3gIfh4NVFvW0f6Pj51hGpiJ4prBz7Dmrr4ZYrA96rTERVGieZ4xYm7jA==" + }, + "Perfolizer": { + "type": "Transitive", + "resolved": "0.2.1", + "contentHash": "Dt4aCxCT8NPtWBKA8k+FsN/RezOQ2C6omNGm5o/qmYRiIwlQYF93UgFmeF1ezVNsztTnkg7P5P63AE+uNkLfrw==", + "dependencies": { + "System.Memory": "4.5.3" + } + }, + "Pipelines.Sockets.Unofficial": { + "type": "Transitive", + "resolved": "2.2.2", + "contentHash": "Bhk0FWxH1paI+18zr1g5cTL+ebeuDcBCR+rRFO+fKEhretgjs7MF2Mc1P64FGLecWp4zKCUOPzngBNrqVyY7Zg==", + "dependencies": { + "System.IO.Pipelines": "5.0.1" + } + }, + "Portable.BouncyCastle": { + "type": "Transitive", + "resolved": "1.9.0", + "contentHash": "eZZBCABzVOek+id9Xy04HhmgykF0wZg9wpByzrWN7q8qEI0Qen9b7tfd7w8VA3dOeesumMG7C5ZPy0jk7PSRHw==" + }, + "Quartz": { + "type": "Transitive", + "resolved": "3.4.0", + "contentHash": "N8350OAlQhd8zKg0ARFikGjh3bfAW/CF/KVxu2fTIlAALB/oC1eg54n/QAPYR5ryHuYyDr5G8/Qa4k+D/7OFRQ==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" + }, + "SendGrid": { + "type": "Transitive", + "resolved": "9.27.0", + "contentHash": "kMyXRQ8hmN2bG3tYZ7T31Ufl1kXkpuP5+WBh1BJ32WY31DTnBTCVGURoIqfbTo/tRuQfAYLxra6C8cQGN6kk+A==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "starkbank-ecdsa": "[1.3.3, 2.0.0)" + } + }, + "Sentry": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "Pkw4+51EDUQ0X02jdCZIpaM2Q4UO06VKGDE+dYYNxgvOirRXGKTKxRk4NPKJTLSTNl+2JyT9HoE7C6BTlYhLOw==" + }, + "Sentry.Serilog": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "GFTVfQdOFqZ9Vmo8EEZTx1EQMDRJjka/4v2CwxnAUh+sqHDICga4eOm4AyGzDBbE4s9iAHMgMUCceIqo+7z84w==", + "dependencies": { + "Sentry": "3.16.0", + "Serilog": "2.10.0" + } + }, + "Serilog": { + "type": "Transitive", + "resolved": "2.10.0", + "contentHash": "+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA==" + }, + "Serilog.AspNetCore": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "/JO/txIxRR61x1UXQAgUzG2Sx05o1QHCkokVBWrKzmAoDu+p5EtCAj7L/TVVg7Ezhh3GPiZ0JI9OJCmRO9tSRw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.Extensions.Logging": "5.0.0", + "Serilog": "2.10.0", + "Serilog.Extensions.Hosting": "4.2.0", + "Serilog.Formatting.Compact": "1.1.0", + "Serilog.Settings.Configuration": "3.3.0", + "Serilog.Sinks.Console": "4.0.1", + "Serilog.Sinks.Debug": "2.0.0", + "Serilog.Sinks.File": "5.0.0" + } + }, + "Serilog.Extensions.Hosting": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "gT2keceCmPQR9EX0VpXQZvUgELdfE7yqJ7MOxBhm3WLCblcvRgswEOOTgok/DHObbM15A3V/DtF3VdVDQPIZzQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.Hosting.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8", + "Serilog": "2.10.0", + "Serilog.Extensions.Logging": "3.1.0" + } + }, + "Serilog.Extensions.Logging": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "IWfem7wfrFbB3iw1OikqPFNPEzfayvDuN4WP7Ue1AVFskalMByeWk3QbtUXQR34SBkv1EbZ3AySHda/ErDgpcg==", + "dependencies": { + "Microsoft.Extensions.Logging": "2.0.0", + "Serilog": "2.9.0" + } + }, + "Serilog.Extensions.Logging.File": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "usO0qr4v9VCMBWiTJ1nQmAbPNCt40FrkDol6CpfCXbsxGZS/hH+YCueF7vvPQ32ATI0GWcMWiKRdjXEE7/HxTQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Serilog": "2.5.0", + "Serilog.Extensions.Logging": "2.0.2", + "Serilog.Formatting.Compact": "1.0.0", + "Serilog.Sinks.Async": "1.1.0", + "Serilog.Sinks.RollingFile": "3.3.0" + } + }, + "Serilog.Formatting.Compact": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "pNroKVjo+rDqlxNG5PXkRLpfSCuDOBY0ri6jp9PLe505ljqwhwZz8ospy2vWhQlFu5GkIesh3FcDs4n7sWZODA==", + "dependencies": { + "Serilog": "2.8.0" + } + }, + "Serilog.Settings.Configuration": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "7GNudISZwqaT902hqEL2OFGTZeUFWfnrNLupJkOqeF41AR3GjcxX+Hwb30xb8gG2/CDXsCMVfF8o0+8KY0fJNg==", + "dependencies": { + "Microsoft.Extensions.DependencyModel": "3.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "2.0.0", + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Async": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "xll0Kanz2BkCxuv+F3p1WXr47jdsVM0GU1n1LZvK+18QiRZ/WGFNxSNw9EMKFV5ED5gr7MUpAe6PCMNL1HGUMA==", + "dependencies": { + "Serilog": "2.1.0", + "System.Collections.Concurrent": "4.0.12" + } + }, + "Serilog.Sinks.AzureCosmosDB": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Im2/ZqjXQIpsd727qEo5Pq+br0MiNVuTvI40Yk7736tgjCpEx+omPHv4+c4fEAxnOP2kL9Ge6UoDFoDw3cjF2A==", + "dependencies": { + "Microsoft.Azure.Cosmos": "3.24.0", + "Microsoft.CSharp": "4.7.0", + "Newtonsoft.Json": "13.0.1", + "Serilog": "2.10.0", + "Serilog.Sinks.PeriodicBatching": "2.3.1" + } + }, + "Serilog.Sinks.Console": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Debug": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y6g3OBJ4JzTyyw16fDqtFcQ41qQAydnEvEqmXjhwhgjsnG/FaJ8GUqF5ldsC/bVkK8KYmqrPhDO+tm4dF6xx4A==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.File": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.PeriodicBatching": { + "type": "Transitive", + "resolved": "2.3.1", + "contentHash": "LVYvqpqjSTD8dhfxRnzpxTs8/ys3V2q01MvaY3r0eKsDgpKK1U1y/5N6gFHgiesbxG0V+O5IWdz4+c1DzoNyOQ==", + "dependencies": { + "Serilog": "2.0.0" + } + }, + "Serilog.Sinks.RollingFile": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "2lT5X1r3GH4P0bRWJfhA7etGl8Q2Ipw9AACvtAHWRUSpYZ42NGVyHoVs2ALBZ/cAkkS+tA4jl80Zie144eLQPg==", + "dependencies": { + "Serilog.Sinks.File": "3.2.0", + "System.IO": "4.1.0", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Serilog.Sinks.SyslogMessages": { + "type": "Transitive", + "resolved": "2.0.6", + "contentHash": "V2Yq2GEbk7taEPbpBLFzLXhrHrUzKf4sQu/zLrANU8XIoUn/Mr08M2E8PrcrWVXCj0R4xLMWYe0Z1sxOrMF3IA==", + "dependencies": { + "Serilog": "2.5.0", + "Serilog.Sinks.PeriodicBatching": "2.3.0" + } + }, + "StackExchange.Redis": { + "type": "Transitive", + "resolved": "2.5.43", + "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "dependencies": { + "Pipelines.Sockets.Unofficial": "2.2.2", + "System.Diagnostics.PerformanceCounter": "5.0.0" + } + }, + "starkbank-ecdsa": { + "type": "Transitive", + "resolved": "1.3.3", + "contentHash": "OblOaKb1enXn+dSp7tsx9yjwV+/BEKM9jFhshIkZTwCk7LuTFTp+wSon6rFzuPiIiTGtvVWQNUw2slHjGktJog==" + }, + "Stripe.net": { + "type": "Transitive", + "resolved": "40.0.0", + "contentHash": "SD1bGiF+sVQG3p2LXNTZ5rEG2aCnXIHokcxYS9yyW3dR01J0ryf+iNFOwid148yePZ0gCBcRxj3wiW1mTmP7UQ==", + "dependencies": { + "Newtonsoft.Json": "12.0.3", + "System.Configuration.ConfigurationManager": "6.0.0" + } + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.CodeDom": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "CPc6tWO1LAer3IzfZufDBRL+UZQcj5uS207NHALQzP84Vp/z6wF0Aa0YZImOQY8iStY0A2zI/e3ihKNPfUm8XA==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==" + }, + "System.Collections.NonGeneric": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "hMxFT2RhhlffyCdKLDXjx8WEC5JfCvNozAZxCablAuFRH74SCV4AgzE8yJCh/73bFnEoZgJ9MJmkjQ0dJmnKqA==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Collections.Specialized": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "/HKQyVP0yH1I0YtK7KJL/28snxHNH/bi+0lgk/+MbURF6ULhAE31MDI+NZDerNWu264YbxklXCCygISgm+HMug==", + "dependencies": { + "System.Collections.NonGeneric": "4.0.1", + "System.Globalization": "4.0.11", + "System.Globalization.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "6.0.0", + "System.Security.Permissions": "6.0.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Diagnostics.PerformanceCounter": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "kcQWWtGVC3MWMNXdMDWfrmIlFZZ2OdoeT6pSNVRtk9+Sa7jwdPiMlNwb0ZQcS7NRlT92pCfmjRtkSWUW3RAKwg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.Diagnostics.Process": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "J0wOX07+QASQblsfxmIMFc9Iq7KTXYL3zs2G/Xc704Ylv3NpuVdo6gij6V3PGiptTxqsK0K7CdXenRvKUnkA2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "Microsoft.Win32.Registry": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.TraceSource": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "6WVCczFZKXwpWpzd/iJkYnsmWTSFFiU24Xx/YdHXBcu+nFI/ehTgeqdJQFbtRPzbrO3KtRNjvkhtj4t5/WwWsA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Drawing.Common": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + } + }, + "System.Dynamic.Runtime": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "db34f6LHYM0U0JpE+sOmjar27BnqTVkbLJhgfwMpTdgTigG/Hna3m2MYVwnFzGGKnEJk2UXFuoVTr8WUbU91/A==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Formats.Asn1": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==" + }, + "System.Formats.Cbor": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "mGaLOoiw7KurJagOOcIsWUoCT5ACIiGxKlCcbYQASefBGXjnCcKTq5Hdjb94eEAKg38zXKlHw4c6EjzgBl9dIw==" + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IdentityModel.Tokens.Jwt": { + "type": "Transitive", + "resolved": "6.21.0", + "contentHash": "JRD8AuypBE+2zYxT3dMJomQVsPYsCqlyZhWel3J1d5nzQokSRyTueF+Q4ID3Jcu6zSZKuzOdJ1MLTkbQsDqcvQ==", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "6.21.0", + "Microsoft.IdentityModel.Tokens": "6.21.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Rfm2jYCaUeGysFEZjDe7j1R4x6Z6BzumS/vUT5a1AA/AWJuGX71PoGB0RmpyX3VmrGqVnAwtfMn39OHR8Y/5+g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "qEePWsaq9LoEEIqhbGe6D5J8c9IqQOUuTzzV6wn1POlfdLkJliZY3OlB0j0f17uMWlqZYjH7txj+2YbyrIA8Yg==" + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Linq.Queryable": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "Yn/WfYe9RoRfmSLvUt2JerP0BTGGykCZkQPgojaxgzF2N0oPo+/AhB8TXOpdCcNlrG3VRtsamtK2uzsp3cqRVw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Management": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "sHsESYMmPDhQuOC66h6AEOs/XowzKsbT9srMbX71TCXP58hkpn1BqBjdmKj1+DCA/WlBETX1K5WjQHwmV0Txrg==", + "dependencies": { + "System.CodeDom": "6.0.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==", + "dependencies": { + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.6.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.4", + "contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.1", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.NameResolution": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "JdqRdM1Qym3YehqdKIi5LHrpypP4JMfxKQSNCJ2z4WawkG0il+N3XfNeJOxll2XrTnG7WgYYPoeiu/KOwg0DQw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.NetworkInformation": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "Q0rfeiW6QsiZuicGjrFA7cRr2+kXex0JIljTTxzI09GIftB8k+aNL31VsQD1sI2g31cw7UGDTgozA/FgeNSzsQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Linq": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.Sockets": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Overlapped": "4.0.1", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Requests": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "vxGt7C0cZixN+VqoSW4Yakc1Y9WknmxauDqzxgpw/FnBdz4kQNN51l4wxdXX5VY1xjqy//+G+4CvJWp1+f+y6Q==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Net.Http": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Claims": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Security.Principal": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Security": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Net.WebHeaderCollection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "XX2TIAN+wBSAIV51BU2FvvXMdstUa8b0FBSZmDWjZdwUMmggQSifpTOZ5fNH20z9ZCg2fkV1L5SsZnpO2RQDRQ==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0" + } + }, + "System.Net.WebSockets": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", + "dependencies": { + "Microsoft.Win32.Primitives": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.WebSockets.Client": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "NUCcDroX4lCQXgOrzlwIZ1u9YJ0krfyF0wk0ONnyLUmcQoEiYV2/OfUPRqUwQBbpH1BlGApkLgoQUwMqb5+c1g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.2", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Net.WebSockets": "4.0.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.X509Certificates": "4.1.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Numerics.Vectors": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Private.DataContractSerialization": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "lcqFBUaCZxPiUkA4dlSOoPZGtZsAuuElH2XHgLwGLxd7ZozWetV5yiz0qGAV2AUYOqw97MtZBjbLMN16Xz4vXA==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Collections.Concurrent": "4.0.12", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Emit.Lightweight": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1", + "System.Xml.XmlSerializer": "4.0.11" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "VR4kk8XLKebQ4MZuKuIni/7oh+QGFmZW3qORd1GvBq/8026OpW501SzT/oypwiQl4TvT8ErnReh/NzY9u+C6wQ==" + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "a4OLB4IITxAXJeV74MDx49Oq2+PsF6Sml54XAFv+2RyWwtDBcabzoxiiJRhdhx+gaohLh4hEGCLQyBozXoQPqA==" + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Caching": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "30D6MkO8WF9jVGWZIP0hmCN8l9BTY4LCsAzLIe4xFSXzs+AjDotR7DpSmj27pFskDURzUvqYYY0ikModgBTxWw==", + "dependencies": { + "System.Configuration.ConfigurationManager": "5.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Runtime.Serialization.Json": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "+7DIJhnKYgCzUgcLbVTtRQb2l1M0FP549XFlFkQM5lmNiUBl44AfNbx4bz61xA8PzLtlYwfmif4JJJW7MPPnjg==", + "dependencies": { + "System.IO": "4.1.0", + "System.Private.DataContractSerialization": "4.1.1", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" + }, + "System.Security.Claims": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Security.Principal": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==", + "dependencies": { + "System.Formats.Asn1": "5.0.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Pkcs": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "elM3x+xSRhzQysiqo85SbidJJ2YbZlnvmh+53TuSZHsD7dNuuEWser+9EFtY+rYupBwkq2avc6ZCO3/6qACgmg==", + "dependencies": { + "System.Formats.Asn1": "6.0.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ==" + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Xml": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "i2Jn6rGXR63J0zIklImGRkDIJL4b1NfPSEbIVHBlqoIb12lfXIigCbDRpDmIEzwSo/v1U5y/rYJdzZYSyCWxvg==", + "dependencies": { + "System.Security.Cryptography.Pkcs": "4.5.0", + "System.Security.Permissions": "4.5.0" + } + }, + "System.Security.Permissions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==", + "dependencies": { + "System.Security.AccessControl": "6.0.0", + "System.Windows.Extensions": "6.0.0" + } + }, + "System.Security.Principal": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, + "System.Security.SecureString": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "sqzq9GD6/b0yqPuMpgIKBuoLf4VKAj8oAfh4kXSzPaN6eoKY3hRi9C5L27uip25qlU+BGPfb0xh2Rmbwc4jFVA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "NyscU59xX6Uo91qvhOs2Ccho3AR2TnZPomo1Z0K6YpyztBPM/A5VbkzOO19sy3A3i1TtEnTxA7bCe3Us+r5MWg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "zaJsHfESQvJ11vbXnNlkrR46IaMULk/gHxYsJphzSF+07kTjPHv+Oc14w6QEOfo3Q4hqLJgStUaYB9DBl0TmWg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Overlapped": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "f7aLuLkBoCQM2kng7zqLFBXz9Gk48gDK8lk1ih9rH/1arJJzZK9gJwNvPDhL6Ps/l6rwOr8jw+4FCHL0KKWiEg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Threading.Thread": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OHmbT+Zz065NKII/ZHcH9XO1dEuLGI1L2k7uYss+9C1jLxTC9kTZZuzUOyXHayRk+dft9CiDf3I/QZ0t8JKyBQ==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading.ThreadPool": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.ValueTuple": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" + }, + "System.Windows.Extensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==", + "dependencies": { + "System.Drawing.Common": "6.0.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "lJ8AxvkX7GQxpC6GFCeBj8ThYVyQczx2+f/cWHJU8tjS7YfI6Cv6bon70jVEgs2CiFbmmM8b9j1oZVx0dSI2Ww==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlSerializer": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "FrazwwqfIXTfq23mfv4zH+BjqkSFNaNFBtjzu3I9NRmG8EELYyrv/fJnttCIwRMFRR/YKXF1hmsMmMEnl55HGw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1" + } + }, + "System.Xml.XPath": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "v1JQ5SETnQusqmS3RwStF7vwQ3L02imIzl++sewmt23VGygix04pEH+FCj1yWb+z4GDzKiljr1W7Wfvrx0YwgA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XPath.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "A/uxsWi/Ifzkmd4ArTLISMbfFs6XpRPsXZonrIqyTY70xi8t+mDtvSM5Os0RqyRDobjMBwIDHDL4NOIbkDwf7A==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XPath": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "YubicoDotNetClient": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "uP5F3Ko1gqZi3lwS2R/jAAwhBxXs/6PKDpS6FdQjsBA5qmF0hQmbtfxM6QHTXOMoWbUtfetG7+LtgmG8T5zDIg==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "core": { + "type": "Project", + "dependencies": { + "AWSSDK.SQS": "[3.7.2.47, )", + "AWSSDK.SimpleEmail": "[3.7.0.150, )", + "AspNetCoreRateLimit": "[4.0.2, )", + "AspNetCoreRateLimit.Redis": "[1.0.1, )", + "Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.2.1, )", + "Azure.Storage.Blobs": "[12.11.0, )", + "Azure.Storage.Queues": "[12.9.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "Fido2.AspNet": "[3.0.1, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "MailKit": "[3.2.0, )", + "Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )", + "Microsoft.Azure.Cosmos.Table": "[1.0.8, )", + "Microsoft.Azure.NotificationHubs": "[4.1.0, )", + "Microsoft.Azure.ServiceBus": "[5.2.0, )", + "Microsoft.Data.SqlClient": "[5.0.1, )", + "Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )", + "Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )", + "Microsoft.Extensions.Identity.Stores": "[6.0.4, )", + "Newtonsoft.Json": "[13.0.1, )", + "Otp.NET": "[1.2.2, )", + "Quartz": "[3.4.0, )", + "SendGrid": "[9.27.0, )", + "Sentry.Serilog": "[3.16.0, )", + "Serilog.AspNetCore": "[5.0.0, )", + "Serilog.Extensions.Logging": "[3.1.0, )", + "Serilog.Extensions.Logging.File": "[2.0.0, )", + "Serilog.Sinks.AzureCosmosDB": "[2.0.0, )", + "Serilog.Sinks.SyslogMessages": "[2.0.6, )", + "Stripe.net": "[40.0.0, )", + "YubicoDotNetClient": "[1.2.0, )" + } + } + } + } +} \ No newline at end of file diff --git a/scripts/bitwarden.ps1 b/scripts/bitwarden.ps1 index 90b66998a..3d4f70ac4 100644 --- a/scripts/bitwarden.ps1 +++ b/scripts/bitwarden.ps1 @@ -1,164 +1,3 @@ -param ( - [switch] $install, - [switch] $start, - [switch] $restart, - [switch] $stop, - [switch] $update, - [switch] $rebuild, - [switch] $updateconf, - [switch] $renewcert, - [switch] $updatedb, - [switch] $updaterun, - [switch] $updateself, - [switch] $help, - [string] $output = "" -) - -# Setup - $scriptPath = $MyInvocation.MyCommand.Path -$dir = Split-Path -Parent $MyInvocation.MyCommand.Path -if ($output -eq "") { - $output = "${dir}\bwdata" -} - -$scriptsDir = "${output}\scripts" -$githubBaseUrl = "https://raw.githubusercontent.com/bitwarden/server/master" - -# Please do not create pull requests modifying the version numbers. -$coreVersion = "1.44.1" -$webVersion = "2.24.2" - -# Functions - -function Download-Self { - Invoke-RestMethod -OutFile $scriptPath -Uri "${githubBaseUrl}/scripts/bitwarden.ps1" -} - -function Download-Run-File { - if (!(Test-Path -Path $scriptsDir)) { - New-Item -ItemType directory -Path $scriptsDir | Out-Null - } - Invoke-RestMethod -OutFile $scriptsDir\run.ps1 -Uri "${githubBaseUrl}/scripts/run.ps1" -} - -function Check-Output-Dir-Exists { - if (!(Test-Path -Path $output)) { - throw "Cannot find a Bitwarden installation at $output." - } -} - -function Check-Output-Dir-Not-Exists { - if (Test-Path -Path "$output\docker") { - throw "Looks like Bitwarden is already installed at $output." - } -} - -function List-Commands { - Write-Line " -Available commands: - --install --start --restart --stop --update --updatedb --updaterun --updateself --updateconf --renewcert --rebuild --help - -See more at https://bitwarden.com/help/article/install-on-premise/#script-commands-reference -" -} - -function Write-Line($str) { - if($env:BITWARDEN_QUIET -ne "true") { - Write-Host $str - } -} - -# Intro - -$year = (Get-Date).year - -Write-Line @' - _ _ _ _ -| |__ (_) |___ ____ _ _ __ __| | ___ _ __ -| '_ \| | __\ \ /\ / / _` | '__/ _` |/ _ \ '_ \ -| |_) | | |_ \ V V / (_| | | | (_| | __/ | | | -|_.__/|_|\__| \_/\_/ \__,_|_| \__,_|\___|_| |_| -'@ - -Write-Line " -Open source password management solutions -Copyright 2015-${year}, 8bit Solutions LLC -https://bitwarden.com, https://github.com/bitwarden - -=================================================== -" - -if($env:BITWARDEN_QUIET -ne "true") { - Write-Line "bitwarden.ps1 version ${coreVersion}" - docker --version - docker-compose --version -} - -Write-Line "" - -# Commands - -if ($install) { - Check-Output-Dir-Not-Exists - New-Item -ItemType directory -Path $output -ErrorAction Ignore | Out-Null - Download-Run-File - Invoke-Expression "& `"$scriptsDir\run.ps1`" -install -outputDir `"$output`" -coreVersion $coreVersion -webVersion $webVersion" -} -elseif ($start -Or $restart) { - Check-Output-Dir-Exists - Invoke-Expression "& `"$scriptsDir\run.ps1`" -restart -outputDir `"$output`" -coreVersion $coreVersion -webVersion $webVersion" -} -elseif ($update) { - Check-Output-Dir-Exists - Download-Run-File - Invoke-Expression "& `"$scriptsDir\run.ps1`" -update -outputDir `"$output`" -coreVersion $coreVersion -webVersion $webVersion" -} -elseif ($rebuild) { - Check-Output-Dir-Exists - Invoke-Expression "& `"$scriptsDir\run.ps1`" -rebuild -outputDir `"$output`" -coreVersion $coreVersion -webVersion $webVersion" -} -elseif ($updateconf) { - Check-Output-Dir-Exists - Invoke-Expression "& `"$scriptsDir\run.ps1`" -updateconf -outputDir `"$output`" -coreVersion $coreVersion -webVersion $webVersion" -} -elseif ($updatedb) { - Check-Output-Dir-Exists - Invoke-Expression "& `"$scriptsDir\run.ps1`" -updatedb -outputDir `"$output`" -coreVersion $coreVersion -webVersion $webVersion" -} -elseif ($stop) { - Check-Output-Dir-Exists - Invoke-Expression "& `"$scriptsDir\run.ps1`" -stop -outputDir `"$output`" -coreVersion $coreVersion -webVersion $webVersion" -} -elseif ($renewcert) { - Check-Output-Dir-Exists - Invoke-Expression "& `"$scriptsDir\run.ps1`" -renewcert -outputDir `"$output`" -coreVersion $coreVersion -webVersion $webVersion" -} -elseif ($updaterun) { - Check-Output-Dir-Exists - Download-Run-File -} -elseif ($updateself) { - Download-Self - Write-Line "Updated self." -} -elseif ($help) { - List-Commands -} -else { - Write-Line "No command found." - Write-Line "" - List-Commands -} +Invoke-RestMethod -OutFile $scriptPath -Uri "https://go.btwrdn.co/bw-ps" +Write-Output "We have moved our self-hosted scripts to their own repository (https://github.com/bitwarden/self-host). Your 'bitwarden.ps1' script has been automatically upgraded. Please run it again." diff --git a/scripts/bitwarden.sh b/scripts/bitwarden.sh index 79f4b768e..4f9da295d 100755 --- a/scripts/bitwarden.sh +++ b/scripts/bitwarden.sh @@ -7,152 +7,25 @@ cat << "EOF" | '_ \| | __\ \ /\ / / _` | '__/ _` |/ _ \ '_ \ | |_) | | |_ \ V V / (_| | | | (_| | __/ | | | |_.__/|_|\__| \_/\_/ \__,_|_| \__,_|\___|_| |_| - EOF cat << EOF Open source password management solutions Copyright 2015-$(date +'%Y'), 8bit Solutions LLC https://bitwarden.com, https://github.com/bitwarden - =================================================== - EOF -# Setup - DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -SCRIPT_NAME=`basename "$0"` +SCRIPT_NAME=$(basename "$0") SCRIPT_PATH="$DIR/$SCRIPT_NAME" -OUTPUT="$DIR/bwdata" -if [ $# -eq 2 ] +BITWARDEN_SCRIPT_URL="https://go.btwrdn.co/bw-sh" + +if curl -L -s -w "http_code %{http_code}" -o $SCRIPT_PATH.1 $BITWARDEN_SCRIPT_URL | grep -q "^http_code 20[0-9]" then - OUTPUT=$2 + mv $SCRIPT_PATH.1 $SCRIPT_PATH + chmod u+x $SCRIPT_PATH + echo "We have moved our self-hosted scripts to their own repository (https://github.com/bitwarden/self-host). Your 'bitwarden.sh' script has been automatically upgraded. Please run it again." +else + rm -f $SCRIPT_PATH.1 fi - -SCRIPTS_DIR="$OUTPUT/scripts" -GITHUB_BASE_URL="https://raw.githubusercontent.com/bitwarden/server/master" - -# Please do not create pull requests modifying the version numbers. -COREVERSION="1.44.1" -WEBVERSION="2.24.2" - -echo "bitwarden.sh version $COREVERSION" -docker --version -docker-compose --version - -echo "" - -# Functions - -function downloadSelf() { - if curl -s -w "http_code %{http_code}" -o $SCRIPT_PATH.1 $GITHUB_BASE_URL/scripts/bitwarden.sh | grep -q "^http_code 20[0-9]" - then - mv $SCRIPT_PATH.1 $SCRIPT_PATH - chmod u+x $SCRIPT_PATH - else - rm -f $SCRIPT_PATH.1 - fi -} - -function downloadRunFile() { - if [ ! -d "$SCRIPTS_DIR" ] - then - mkdir $SCRIPTS_DIR - fi - curl -s -o $SCRIPTS_DIR/run.sh $GITHUB_BASE_URL/scripts/run.sh - chmod u+x $SCRIPTS_DIR/run.sh - rm -f $SCRIPTS_DIR/install.sh -} - -function checkOutputDirExists() { - if [ ! -d "$OUTPUT" ] - then - echo "Cannot find a Bitwarden installation at $OUTPUT." - exit 1 - fi -} - -function checkOutputDirNotExists() { - if [ -d "$OUTPUT/docker" ] - then - echo "Looks like Bitwarden is already installed at $OUTPUT." - exit 1 - fi -} - -function listCommands() { -cat << EOT -Available commands: - -install -start -restart -stop -update -updatedb -updaterun -updateself -updateconf -renewcert -rebuild -help - -See more at https://bitwarden.com/help/article/install-on-premise/#script-commands-reference - -EOT -} - -# Commands - -case $1 in - "install") - checkOutputDirNotExists - mkdir -p $OUTPUT - downloadRunFile - $SCRIPTS_DIR/run.sh install $OUTPUT $COREVERSION $WEBVERSION - ;; - "start" | "restart") - checkOutputDirExists - $SCRIPTS_DIR/run.sh restart $OUTPUT $COREVERSION $WEBVERSION - ;; - "update") - checkOutputDirExists - downloadRunFile - $SCRIPTS_DIR/run.sh update $OUTPUT $COREVERSION $WEBVERSION - ;; - "rebuild") - checkOutputDirExists - $SCRIPTS_DIR/run.sh rebuild $OUTPUT $COREVERSION $WEBVERSION - ;; - "updateconf") - checkOutputDirExists - $SCRIPTS_DIR/run.sh updateconf $OUTPUT $COREVERSION $WEBVERSION - ;; - "updatedb") - checkOutputDirExists - $SCRIPTS_DIR/run.sh updatedb $OUTPUT $COREVERSION $WEBVERSION - ;; - "stop") - checkOutputDirExists - $SCRIPTS_DIR/run.sh stop $OUTPUT $COREVERSION $WEBVERSION - ;; - "renewcert") - checkOutputDirExists - $SCRIPTS_DIR/run.sh renewcert $OUTPUT $COREVERSION $WEBVERSION - ;; - "updaterun") - checkOutputDirExists - downloadRunFile - ;; - "updateself") - downloadSelf && echo "Updated self." && exit - ;; - "help") - listCommands - ;; - *) - echo "No command found." - echo - listCommands -esac diff --git a/scripts/build b/scripts/build index c8b5cdff0..38b457f85 100755 --- a/scripts/build +++ b/scripts/build @@ -22,27 +22,26 @@ build() { PROJECT=$1; shift case "$PROJECT" in - "api" | "Api") build Api $PWD/src/Api ;; "admin" | "Admin") build Admin $PWD/src/Admin ;; - "identity" | "Identity") build Identity $PWD/src/Identity ;; - "events" | "Events") build Events $PWD/src/Events ;; + "api" | "Api") build Api $PWD/src/Api ;; "billing" | "Billing") build Billing $PWD/src/Billing ;; - "sso" | "Sso") build Sso $PWD/bitwarden_license/src/Sso ;; - "server" | "Server") build Server $PWD/util/Server ;; - "icons" | "Icons") build Icons $PWD/src/Icons ;; - "notifications" | "Notifications") build Notifications $PWD/src/Notifications ;; - "setup" | "Setup") build Setup $PWD/util/Setup ;; + "events" | "Events") build Events $PWD/src/Events ;; "eventsprocessor" | "EventsProcessor") build EventsProcessor $PWD/src/EventsProcessor ;; + "icons" | "Icons") build Icons $PWD/src/Icons ;; + "identity" | "Identity") build Identity $PWD/src/Identity ;; + "notifications" | "Notifications") build Notifications $PWD/src/Notifications ;; + "server" | "Server") build Server $PWD/util/Server ;; + "sso" | "Sso") build Sso $PWD/bitwarden_license/src/Sso ;; "") - build Api $PWD/src/Api - build Admin $PWD/src/Admin - build Identity $PWD/src/Identity - build Events $PWD/src/Events - build Billing $PWD/src/Billing - build Sso $PWD/bitwarden_license/src/Sso - build Server $PWD/util/Server - build Icons $PWD/src/Icons - build Notifications $PWD/src/Notifications + build Admin $PWD/src/Admin + build Api $PWD/src/Api + build Billing $PWD/src/Billing + build Events $PWD/src/Events build EventsProcessor $PWD/src/EventsProcessor + build Icons $PWD/src/Icons + build Identity $PWD/src/Identity + build Notifications $PWD/src/Notifications + build Server $PWD/util/Server + build Sso $PWD/bitwarden_license/src/Sso ;; esac diff --git a/scripts/build-docker b/scripts/build-docker index 36d83e2fd..b1c643319 100755 --- a/scripts/build-docker +++ b/scripts/build-docker @@ -22,10 +22,6 @@ docker_build() { echo "Building docker image: bitwarden/$project_name_lower:$docker_tag" echo "==============================" - if [ "$project_name_lower" == "k8s-proxy" ]; then - docker build -f $project_dir/Dockerfile-k8s -t bitwarden/$project_name_lower:$docker_tag $project_dir - fi - docker build -t bitwarden/$project_name_lower:$docker_tag $project_dir if [ "$docker_push" == "1" ]; then @@ -59,35 +55,34 @@ done case "$PROJECT" in - "api" | "Api") docker_build Api $PWD/src/Api $TAG $PUSH ;; "admin" | "Admin") docker_build Admin $PWD/src/Admin $TAG $PUSH ;; - "identity" | "Identity") docker_build Identity $PWD/src/Identity $TAG $PUSH ;; - "events" | "Events") docker_build Events $PWD/src/Events $TAG $PUSH ;; + "api" | "Api") docker_build Api $PWD/src/Api $TAG $PUSH ;; + "attachments" | "Attachments") docker_build Attachments $PWD/util/Attachments $TAG $PUSH ;; #"billing" | "Billing") docker_build Billing $PWD/src/Billing $TAG $PUSH ;; - "sso" | "Sso") docker_build Sso $PWD/bitwarden_license/src/Sso $TAG $PUSH ;; - "server" | "Server") docker_build Server $PWD/util/Server $TAG $PUSH ;; - "nginx" | "Nginx") docker_build Nginx $PWD/util/Nginx $TAG $PUSH ;; - "k8s-proxy" | "K8s-Proxy") docker_build K8s-Proxy $PWD/util/Nginx $TAG $PUSH ;; - "attachments" | "Attachments") docker_build Attachemnts $PWD/util/Attachments $TAG $PUSH ;; + "events" | "Events") docker_build Events $PWD/src/Events $TAG $PUSH ;; + "eventsprocessor" | "EventsProcessor") docker_build EventsProcessor $PWD/src/EventsProcessor $TAG $PUSH ;; "icons" | "Icons") docker_build Icons $PWD/src/Icons $TAG $PUSH ;; - "notifications" | "Notifications") docker_build Notifications $PWD/src/Notifications $TAG $PUSH ;; + "identity" | "Identity") docker_build Identity $PWD/src/Identity $TAG $PUSH ;; "mssql" | "MsSql" | "Mssql") docker_build MsSql $PWD/util/MsSql $TAG $PUSH ;; - "seteup" | "Setup") docker_build Setup $PWD/util/Setup $TAG $PUSH - "eventsprocessor" | "EventsProcessor") docker_build EventsProcessor $PWD/src/EventsProcessor $TAG $PUSH + "nginx" | "Nginx") docker_build Nginx $PWD/util/Nginx $TAG $PUSH ;; + "notifications" | "Notifications") docker_build Notifications $PWD/src/Notifications $TAG $PUSH ;; + "server" | "Server") docker_build Server $PWD/util/Server $TAG $PUSH ;; + "setup" | "Setup") docker_build Setup $PWD/util/Setup $TAG $PUSH ;; + "sso" | "Sso") docker_build Sso $PWD/bitwarden_license/src/Sso $TAG $PUSH ;; "") - docker_build Api $PWD/src/Api $TAG $PUSH docker_build Admin $PWD/src/Admin $TAG $PUSH - docker_build Identity $PWD/src/Identity $TAG $PUSH - docker_build Events $PWD/src/Events $TAG $PUSH + docker_build Api $PWD/src/Api $TAG $PUSH + docker_build Attachments $PWD/util/Attachments $TAG $PUSH #docker_build Billing $PWD/src/Billing $TAG $PUSH - docker_build Sso $PWD/bitwarden_license/src/Sso $TAG $PUSH - docker_build Server $PWD/util/Server $TAG $PUSH - docker_build Nginx $PWD/util/Nginx $TAG $PUSH - docker_build Attachemnts $PWD/util/Attachments $TAG $PUSH - docker_build Icons $PWD/src/Icons $TAG $PUSH - docker_build Notifications $PWD/src/Notifications $TAG $PUSH - docker_build MsSql $PWD/util/MsSql $TAG $PUSH$TAG $PUSH - docker_build Setup $PWD/util/Setup $TAG $PUSH + docker_build Events $PWD/src/Events $TAG $PUSH docker_build EventsProcessor $PWD/src/EventsProcessor $TAG $PUSH + docker_build Icons $PWD/src/Icons $TAG $PUSH + docker_build Identity $PWD/src/Identity $TAG $PUSH + docker_build MsSql $PWD/util/MsSql $TAG $PUSH + docker_build Nginx $PWD/util/Nginx $TAG $PUSH + docker_build Notifications $PWD/src/Notifications $TAG $PUSH + docker_build Server $PWD/util/Server $TAG $PUSH + docker_build Setup $PWD/util/Setup $TAG $PUSH + docker_build Sso $PWD/bitwarden_license/src/Sso $TAG $PUSH ;; esac diff --git a/scripts/run.ps1 b/scripts/run.ps1 index 8ff0ea345..a2b5b438a 100644 --- a/scripts/run.ps1 +++ b/scripts/run.ps1 @@ -1,252 +1,16 @@ -param ( - [string]$outputDir = "../.", - [string]$coreVersion = "latest", - [string]$webVersion = "latest", - [switch] $install, - [switch] $start, - [switch] $restart, - [switch] $stop, - [switch] $pull, - [switch] $updateconf, - [switch] $renewcert, - [switch] $updatedb, - [switch] $update -) - -# Setup - -$dockerDir = "${outputDir}\docker" -$setupQuiet = 0 -$qFlag = "" -$quietPullFlag = "" -$certbotHttpPort = "80" -$certbotHttpsPort = "443" -if ($env:BITWARDEN_QUIET -eq "true") { - $setupQuiet = 1 - $qFlag = " -q" - $quietPullFlag = " --quiet-pull" -} -if ("${env:BITWARDEN_CERTBOT_HTTP_PORT}" -ne "") { - $certbotHttpPort = $env:BITWARDEN_CERTBOT_HTTP_PORT -} -if ("${env:BITWARDEN_CERTBOT_HTTPS_PORT}" -ne "") { - $certbotHttpsPort = $env:BITWARDEN_CERTBOT_HTTPS_PORT -} - -# Functions - -function Install() { - [string]$letsEncrypt = "n" - Write-Host "(!) " -f cyan -nonewline - [string]$domain = $( Read-Host "Enter the domain name for your Bitwarden instance (ex. bitwarden.example.com)" ) - echo "" - - if ($domain -eq "") { - $domain = "localhost" - } - - if ($domain -ne "localhost") { - Write-Host "(!) " -f cyan -nonewline - $letsEncrypt = $( Read-Host "Do you want to use Let's Encrypt to generate a free SSL certificate? (y/n)" ) - echo "" - - if ($letsEncrypt -eq "y") { - Write-Host "(!) " -f cyan -nonewline - [string]$email = $( Read-Host ("Enter your email address (Let's Encrypt will send you certificate " + - "expiration reminders)") ) - echo "" - - $letsEncryptPath = "${outputDir}/letsencrypt" - if (!(Test-Path -Path $letsEncryptPath )) { - New-Item -ItemType directory -Path $letsEncryptPath | Out-Null - } - Invoke-Expression ("docker pull{0} certbot/certbot" -f "") #TODO: qFlag - $certbotExp = "docker run -it --rm --name certbot -p ${certbotHttpsPort}:443 -p ${certbotHttpPort}:80 " + ` - "-v ${outputDir}/letsencrypt:/etc/letsencrypt/ certbot/certbot " + ` - "certonly{0} --standalone --noninteractive --agree-tos --preferred-challenges http " + ` - "--email ${email} -d ${domain} --logs-dir /etc/letsencrypt/logs" - Invoke-Expression ($certbotExp -f $qFlag) - } - } - - Write-Host "(!) " -f cyan -nonewline - [string]$database = $( Read-Host "Enter the database name for your Bitwarden instance (ex. vault): ") - echo "" - - if ($database -eq "") { - $database = "vault" - } - - Pull-Setup - docker run -it --rm --name setup -v ${outputDir}:/bitwarden bitwarden/setup:$coreVersion ` - dotnet Setup.dll -install 1 -domain ${domain} -letsencrypt ${letsEncrypt} ` - -os win -corev $coreVersion -webv $webVersion -q $setupQuiet -dbname "$database" -} - -function Docker-Compose-Up { - Docker-Compose-Files - Docker-Compose-Volumes - Invoke-Expression ("docker-compose up -d{0}" -f $quietPullFlag) -} - -function Docker-Compose-Down { - Docker-Compose-Files - if ((Invoke-Expression ("docker-compose ps{0}" -f "") | Measure-Object -Line).lines -gt 2 ) { - Invoke-Expression ("docker-compose down{0}" -f "") #TODO: qFlag +$scriptPath = $MyInvocation.MyCommand.Path +$bitwardenPath = Split-Path $scriptPath | Split-Path | Split-Path +$files = Get-ChildItem $bitwardenPath +$scriptFound = $false +foreach ($file in $files) { + if ($file.Name -eq "bitwarden.ps1") { + $scriptFound = $true + Invoke-RestMethod -OutFile "$($bitwardenPath)/bitwarden.ps1" -Uri "https://go.btwrdn.co/bw-ps" + Write-Output "We have moved our self-hosted scripts to their own repository (https://github.com/bitwarden/self-host). Your 'bitwarden.ps1' script has been automatically upgraded. Please run it again." + break } } -function Docker-Compose-Pull { - Docker-Compose-Files - Invoke-Expression ("docker-compose pull{0}" -f $qFlag) -} - -function Docker-Compose-Files { - if (Test-Path -Path "${dockerDir}\docker-compose.override.yml" -PathType leaf) { - $env:COMPOSE_FILE = "${dockerDir}\docker-compose.yml;${dockerDir}\docker-compose.override.yml" - } - else { - $env:COMPOSE_FILE = "${dockerDir}\docker-compose.yml" - } - $env:COMPOSE_HTTP_TIMEOUT = "300" -} - -function Docker-Compose-Volumes { - Create-Dir "core" - Create-Dir "core/attachments" - Create-Dir "logs" - Create-Dir "logs/admin" - Create-Dir "logs/api" - Create-Dir "logs/events" - Create-Dir "logs/icons" - Create-Dir "logs/identity" - Create-Dir "logs/mssql" - Create-Dir "logs/nginx" - Create-Dir "logs/notifications" - Create-Dir "logs/sso" - Create-Dir "logs/portal" - Create-Dir "mssql/backups" - Create-Dir "mssql/data" -} - -function Create-Dir($str) { - $outPath = "${outputDir}/$str" - if (!(Test-Path -Path $outPath )) { - Write-Line "Creating directory $outPath" - New-Item -ItemType directory -Path $outPath | Out-Null - } -} - -function Docker-Prune { - docker image prune --all --force --filter="label=com.bitwarden.product=bitwarden" ` - --filter="label!=com.bitwarden.project=setup" -} - -function Update-Lets-Encrypt { - if (Test-Path -Path "${outputDir}\letsencrypt\live") { - Invoke-Expression ("docker pull{0} certbot/certbot" -f "") #TODO: qFlag - $certbotExp = "docker run -it --rm --name certbot -p ${certbotHttpsPort}:443 -p ${certbotHttpPort}:80 " + ` - "-v ${outputDir}/letsencrypt:/etc/letsencrypt/ certbot/certbot " + ` - "renew{0} --logs-dir /etc/letsencrypt/logs" -f $qFlag - Invoke-Expression $certbotExp - } -} - -function Force-Update-Lets-Encrypt { - if (Test-Path -Path "${outputDir}\letsencrypt\live") { - Invoke-Expression ("docker pull{0} certbot/certbot" -f "") #TODO: qFlag - $certbotExp = "docker run -it --rm --name certbot -p ${certbotHttpsPort}:443 -p ${certbotHttpPort}:80 " + ` - "-v ${outputDir}/letsencrypt:/etc/letsencrypt/ certbot/certbot " + ` - "renew{0} --logs-dir /etc/letsencrypt/logs --force-renew" -f $qFlag - Invoke-Expression $certbotExp - } -} - -function Update-Database { - Pull-Setup - Docker-Compose-Files - $mssqlId = docker-compose ps -q mssql - docker run -it --rm --name setup --network container:$mssqlId ` - -v ${outputDir}:/bitwarden bitwarden/setup:$coreVersion ` - dotnet Setup.dll -update 1 -db 1 -os win -corev $coreVersion -webv $webVersion -q $setupQuiet - Write-Line "Database update complete" -} - -function Update([switch] $withpull) { - if ($withpull) { - Pull-Setup - } - docker run -it --rm --name setup -v ${outputDir}:/bitwarden bitwarden/setup:$coreVersion ` - dotnet Setup.dll -update 1 -os win -corev $coreVersion -webv $webVersion -q $setupQuiet -} - -function Print-Environment { - Pull-Setup - docker run -it --rm --name setup -v ${outputDir}:/bitwarden bitwarden/setup:$coreVersion ` - dotnet Setup.dll -printenv 1 -os win -corev $coreVersion -webv $webVersion -q $setupQuiet -} - -function Restart { - Docker-Compose-Down - Docker-Compose-Pull - Update-Lets-Encrypt - Docker-Compose-Up - Print-Environment -} - -function Cert-Restart { - Docker-Compose-Down - Docker-Compose-Pull - Force-Update-Lets-Encrypt - Docker-Compose-Up - Print-Environment -} - - -function Pull-Setup { - Invoke-Expression ("docker pull{0} bitwarden/setup:${coreVersion}" -f "") #TODO: qFlag -} - -function Write-Line($str) { - if ($env:BITWARDEN_QUIET -ne "true") { - Write-Host $str - } -} - -# Commands - -if ($install) { - Install -} -elseif ($start -Or $restart) { - Restart -} -elseif ($pull) { - Docker-Compose-Pull -} -elseif ($stop) { - Docker-Compose-Down -} -elseif ($renewcert) { - Cert-Restart -} -elseif ($updateconf) { - Docker-Compose-Down - Update -withpull -} -elseif ($updatedb) { - Update-Database -} -elseif ($update) { - Docker-Compose-Down - Update -withpull - Restart - Docker-Prune - Write-Line "Pausing 60 seconds for database to come online. Please wait..." - Start-Sleep -s 60 - Update-Database -} -elseif ($rebuild) { - Docker-Compose-Down - Update +if (-not $scriptFound) { + Write-Output "We have moved our self-hosted scripts to their own repository (https://github.com/bitwarden/self-host). Please run 'bitwarden.ps1 -updateself' before updating." } diff --git a/scripts/run.sh b/scripts/run.sh index 822806039..65828bd2f 100755 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -1,272 +1,45 @@ #!/usr/bin/env bash set -e -# Setup +cat << "EOF" + _ _ _ _ +| |__ (_) |___ ____ _ _ __ __| | ___ _ __ +| '_ \| | __\ \ /\ / / _` | '__/ _` |/ _ \ '_ \ +| |_) | | |_ \ V V / (_| | | | (_| | __/ | | | +|_.__/|_|\__| \_/\_/ \__,_|_| \__,_|\___|_| |_| +EOF -CYAN='\033[0;36m' -NC='\033[0m' # No Color +cat << EOF +Open source password management solutions +Copyright 2015-$(date +'%Y'), 8bit Solutions LLC +https://bitwarden.com, https://github.com/bitwarden +=================================================== +EOF DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +BITWARDEN_SCRIPT_URL="https://go.btwrdn.co/bw-sh" -OUTPUT_DIR=".." -if [ $# -gt 1 ] -then - OUTPUT_DIR=$2 -fi +cd $DIR +cd ../../ -COREVERSION="latest" -if [ $# -gt 2 ] -then - COREVERSION=$3 -fi +FOUND=false -WEBVERSION="latest" -if [ $# -gt 3 ] -then - WEBVERSION=$4 -fi - -OS="lin" -[ "$(uname)" == "Darwin" ] && OS="mac" -ENV_DIR="$OUTPUT_DIR/env" -DOCKER_DIR="$OUTPUT_DIR/docker" - -# Initialize UID/GID which will be used to run services from within containers -if ! grep -q "^LOCAL_UID=" $ENV_DIR/uid.env 2>/dev/null || ! grep -q "^LOCAL_GID=" $ENV_DIR/uid.env 2>/dev/null -then - LUID="LOCAL_UID=`id -u $USER`" - [ "$LUID" == "LOCAL_UID=0" ] && LUID="LOCAL_UID=65534" - LGID="LOCAL_GID=`id -g $USER`" - [ "$LGID" == "LOCAL_GID=0" ] && LGID="LOCAL_GID=65534" - mkdir -p $ENV_DIR - echo $LUID >$ENV_DIR/uid.env - echo $LGID >>$ENV_DIR/uid.env -fi - -# Functions - -function install() { - LETS_ENCRYPT="n" - echo -e -n "${CYAN}(!)${NC} Enter the domain name for your Bitwarden instance (ex. bitwarden.example.com): " - read DOMAIN - echo "" - - if [ "$DOMAIN" == "" ] +for i in *.sh; do + if [ $i = "bitwarden.sh" ] + then + FOUND=true + if curl -L -s -w "http_code %{http_code}" -o bitwarden.sh.1 $BITWARDEN_SCRIPT_URL | grep -q "^http_code 20[0-9]" then - DOMAIN="localhost" - fi - - if [ "$DOMAIN" != "localhost" ] - then - echo -e -n "${CYAN}(!)${NC} Do you want to use Let's Encrypt to generate a free SSL certificate? (y/n): " - read LETS_ENCRYPT - echo "" - - if [ "$LETS_ENCRYPT" == "y" ] - then - echo -e -n "${CYAN}(!)${NC} Enter your email address (Let's Encrypt will send you certificate expiration reminders): " - read EMAIL - echo "" - - mkdir -p $OUTPUT_DIR/letsencrypt - docker pull certbot/certbot - docker run -it --rm --name certbot -p 80:80 -v $OUTPUT_DIR/letsencrypt:/etc/letsencrypt/ certbot/certbot \ - certonly --standalone --noninteractive --agree-tos --preferred-challenges http \ - --email $EMAIL -d $DOMAIN --logs-dir /etc/letsencrypt/logs - fi - fi - - echo -e -n "${CYAN}(!)${NC} Enter the database name for your Bitwarden instance (ex. vault): " - read DATABASE - echo "" - - if [ "$DATABASE" == "" ] - then - DATABASE="vault" - fi - - pullSetup - docker run -it --rm --name setup -v $OUTPUT_DIR:/bitwarden \ - --env-file $ENV_DIR/uid.env bitwarden/setup:$COREVERSION \ - dotnet Setup.dll -install 1 -domain $DOMAIN -letsencrypt $LETS_ENCRYPT -os $OS \ - -corev $COREVERSION -webv $WEBVERSION -dbname "$DATABASE" -} - -function dockerComposeUp() { - dockerComposeFiles - dockerComposeVolumes - docker-compose up -d -} - -function dockerComposeDown() { - dockerComposeFiles - if [ $(docker-compose ps | wc -l) -gt 2 ]; then - docker-compose down - fi -} - -function dockerComposePull() { - dockerComposeFiles - docker-compose pull -} - -function dockerComposeFiles() { - if [ -f "${DOCKER_DIR}/docker-compose.override.yml" ] - then - export COMPOSE_FILE="$DOCKER_DIR/docker-compose.yml:$DOCKER_DIR/docker-compose.override.yml" + mv bitwarden.sh.1 bitwarden.sh + chmod u+x bitwarden.sh + echo "We have moved our self-hosted scripts to their own repository (https://github.com/bitwarden/self-host). Your 'bitwarden.sh' script has been automatically upgraded. Please run it again." else - export COMPOSE_FILE="$DOCKER_DIR/docker-compose.yml" + rm -f bitwarden.sh.1 fi - export COMPOSE_HTTP_TIMEOUT="300" -} + fi +done -function dockerComposeVolumes() { - createDir "core" - createDir "core/attachments" - createDir "logs" - createDir "logs/admin" - createDir "logs/api" - createDir "logs/events" - createDir "logs/icons" - createDir "logs/identity" - createDir "logs/mssql" - createDir "logs/nginx" - createDir "logs/notifications" - createDir "logs/sso" - createDir "logs/portal" - createDir "mssql/backups" - createDir "mssql/data" -} - -function createDir() { - if [ ! -d "${OUTPUT_DIR}/$1" ] - then - echo "Creating directory $OUTPUT_DIR/$1" - mkdir -p $OUTPUT_DIR/$1 - fi -} - -function dockerPrune() { - docker image prune --all --force --filter="label=com.bitwarden.product=bitwarden" \ - --filter="label!=com.bitwarden.project=setup" -} - -function updateLetsEncrypt() { - if [ -d "${OUTPUT_DIR}/letsencrypt/live" ] - then - docker pull certbot/certbot - docker run -i --rm --name certbot -p 443:443 -p 80:80 \ - -v $OUTPUT_DIR/letsencrypt:/etc/letsencrypt/ certbot/certbot \ - renew --logs-dir /etc/letsencrypt/logs - fi -} - -function forceUpdateLetsEncrypt() { - if [ -d "${OUTPUT_DIR}/letsencrypt/live" ] - then - docker pull certbot/certbot - docker run -i --rm --name certbot -p 443:443 -p 80:80 \ - -v $OUTPUT_DIR/letsencrypt:/etc/letsencrypt/ certbot/certbot \ - renew --logs-dir /etc/letsencrypt/logs --force-renew - fi -} - -function updateDatabase() { - pullSetup - dockerComposeFiles - MSSQL_ID=$(docker-compose ps -q mssql) - docker run -i --rm --name setup --network container:$MSSQL_ID \ - -v $OUTPUT_DIR:/bitwarden --env-file $ENV_DIR/uid.env bitwarden/setup:$COREVERSION \ - dotnet Setup.dll -update 1 -db 1 -os $OS -corev $COREVERSION -webv $WEBVERSION - echo "Database update complete" -} - -function updatebw() { - CORE_ID=$(docker-compose ps -q admin) - WEB_ID=$(docker-compose ps -q web) - if docker inspect --format='{{.Config.Image}}:' $CORE_ID | grep -F ":$COREVERSION:" | grep -q ":[0-9.]*:$" && - docker inspect --format='{{.Config.Image}}:' $WEB_ID | grep -F ":$WEBVERSION:" | grep -q ":[0-9.]*:$" - then - echo "Update not needed" - exit - fi - dockerComposeDown - update withpull - restart - dockerPrune - echo "Pausing 60 seconds for database to come online. Please wait..." - sleep 60 -} - -function update() { - if [ "$1" == "withpull" ] - then - pullSetup - fi - docker run -i --rm --name setup -v $OUTPUT_DIR:/bitwarden \ - --env-file $ENV_DIR/uid.env bitwarden/setup:$COREVERSION \ - dotnet Setup.dll -update 1 -os $OS -corev $COREVERSION -webv $WEBVERSION -} - -function printEnvironment() { - pullSetup - docker run -i --rm --name setup -v $OUTPUT_DIR:/bitwarden \ - --env-file $ENV_DIR/uid.env bitwarden/setup:$COREVERSION \ - dotnet Setup.dll -printenv 1 -os $OS -corev $COREVERSION -webv $WEBVERSION -} - -function restart() { - dockerComposeDown - dockerComposePull - updateLetsEncrypt - dockerComposeUp - printEnvironment -} - -function certRestart() { - dockerComposeDown - dockerComposePull - forceUpdateLetsEncrypt - dockerComposeUp - printEnvironment -} - -function pullSetup() { - docker pull bitwarden/setup:$COREVERSION -} - -# Commands - -case $1 in - "install") - install - ;; - "start" | "restart") - restart - ;; - "pull") - dockerComposePull - ;; - "stop") - dockerComposeDown - ;; - "renewcert") - certRestart - ;; - "updateconf") - dockerComposeDown - update withpull - ;; - "updatedb") - updateDatabase - ;; - "update") - dockerComposeFiles - updatebw - updateDatabase - ;; - "rebuild") - dockerComposeDown - update nopull - ;; -esac +if [ $FOUND = false ] +then + echo "We have moved our self-hosted scripts to their own repository (https://github.com/bitwarden/self-host). Please run 'bitwarden.sh updateself' before updating." +fi diff --git a/src/Admin/Admin.csproj b/src/Admin/Admin.csproj index d6a7d849b..31d3b6067 100644 --- a/src/Admin/Admin.csproj +++ b/src/Admin/Admin.csproj @@ -5,22 +5,25 @@ + + + + - + - - - + + diff --git a/src/Admin/AdminSettings.cs b/src/Admin/AdminSettings.cs index 64de4f083..6941bbc8f 100644 --- a/src/Admin/AdminSettings.cs +++ b/src/Admin/AdminSettings.cs @@ -1,16 +1,15 @@ -namespace Bit.Admin -{ - public class AdminSettings - { - public virtual string Admins { get; set; } - public virtual CloudflareSettings Cloudflare { get; set; } - public int? DeleteTrashDaysAgo { get; set; } +namespace Bit.Admin; - public class CloudflareSettings - { - public string ZoneId { get; set; } - public string AuthEmail { get; set; } - public string AuthKey { get; set; } - } +public class AdminSettings +{ + public virtual string Admins { get; set; } + public virtual CloudflareSettings Cloudflare { get; set; } + public int? DeleteTrashDaysAgo { get; set; } + + public class CloudflareSettings + { + public string ZoneId { get; set; } + public string AuthEmail { get; set; } + public string AuthKey { get; set; } } } diff --git a/src/Admin/Controllers/ErrorController.cs b/src/Admin/Controllers/ErrorController.cs index bef21cd12..9216537ff 100644 --- a/src/Admin/Controllers/ErrorController.cs +++ b/src/Admin/Controllers/ErrorController.cs @@ -1,24 +1,23 @@ -using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Mvc; -namespace Bit.Admin.Controllers -{ - public class ErrorController : Controller - { - [Route("/error")] - public IActionResult Error(int? statusCode = null) - { - var exceptionHandlerPathFeature = HttpContext.Features.Get(); - TempData["Error"] = HttpContext.Features.Get()?.Error.Message; +namespace Bit.Admin.Controllers; - if (exceptionHandlerPathFeature != null) - { - return Redirect(exceptionHandlerPathFeature.Path); - } - else - { - return Redirect("/Home"); - } +public class ErrorController : Controller +{ + [Route("/error")] + public IActionResult Error(int? statusCode = null) + { + var exceptionHandlerPathFeature = HttpContext.Features.Get(); + TempData["Error"] = HttpContext.Features.Get()?.Error.Message; + + if (exceptionHandlerPathFeature != null) + { + return Redirect(exceptionHandlerPathFeature.Path); + } + else + { + return Redirect("/Home"); } } } diff --git a/src/Admin/Controllers/HomeController.cs b/src/Admin/Controllers/HomeController.cs index 6b9fb9fb4..20c1be70d 100644 --- a/src/Admin/Controllers/HomeController.cs +++ b/src/Admin/Controllers/HomeController.cs @@ -1,92 +1,113 @@ -using System; -using System.Diagnostics; -using Microsoft.AspNetCore.Mvc; +using System.Diagnostics; +using System.Text.Json; using Bit.Admin.Models; -using Microsoft.AspNetCore.Authorization; using Bit.Core.Settings; -using System.Net.Http; -using System.Threading.Tasks; -using Newtonsoft.Json.Linq; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; -namespace Bit.Admin.Controllers +namespace Bit.Admin.Controllers; + +public class HomeController : Controller { - public class HomeController : Controller + private readonly GlobalSettings _globalSettings; + private readonly HttpClient _httpClient = new HttpClient(); + private readonly ILogger _logger; + + public HomeController(GlobalSettings globalSettings, ILogger logger) { - private readonly GlobalSettings _globalSettings; - private HttpClient _httpClient = new HttpClient(); + _globalSettings = globalSettings; + _logger = logger; + } - public HomeController(GlobalSettings globalSettings) + [Authorize] + public IActionResult Index() + { + return View(new HomeModel { - _globalSettings = globalSettings; - } + GlobalSettings = _globalSettings, + CurrentVersion = Core.Utilities.AssemblyHelpers.GetVersion() + }); + } - [Authorize] - public IActionResult Index() + public IActionResult Error() + { + return View(new ErrorViewModel { - return View(new HomeModel + RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier + }); + } + + + public async Task GetLatestVersion(ProjectType project, CancellationToken cancellationToken) + { + var requestUri = $"https://selfhost.bitwarden.com/version.json"; + try + { + var response = await _httpClient.GetAsync(requestUri, cancellationToken); + if (response.IsSuccessStatusCode) { - GlobalSettings = _globalSettings, - CurrentVersion = Core.Utilities.CoreHelpers.GetVersion() - }); - } - - [HttpGet("~/alive")] - [HttpGet("~/now")] - public DateTime Get() - { - return DateTime.UtcNow; - } - - public IActionResult Error() - { - return View(new ErrorViewModel - { - RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier - }); - } - - public async Task GetLatestDockerHubVersion(string repository) - { - try - { - var response = await _httpClient.GetAsync( - $"https://hub.docker.com/v2/repositories/bitwarden/{repository}/tags/"); - if (response.IsSuccessStatusCode) + var latestVersions = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); + return project switch { - var json = await response.Content.ReadAsStringAsync(); - var data = JObject.Parse(json); - var results = data["results"] as JArray; - foreach (var result in results) - { - var name = result["name"].ToString(); - if (!string.IsNullOrWhiteSpace(name) && name.Length > 0 && char.IsNumber(name[0])) - { - return new JsonResult(name); - } - } - } + ProjectType.Core => new JsonResult(latestVersions.Versions.CoreVersion), + ProjectType.Web => new JsonResult(latestVersions.Versions.WebVersion), + _ => throw new System.NotImplementedException(), + }; } - catch (HttpRequestException) { } - - return new JsonResult("-"); } - - public async Task GetInstalledWebVersion() + catch (HttpRequestException e) { - try - { - var response = await _httpClient.GetAsync( - $"{_globalSettings.BaseServiceUri.InternalVault}/version.json"); - if (response.IsSuccessStatusCode) - { - var json = await response.Content.ReadAsStringAsync(); - var data = JObject.Parse(json); - return new JsonResult(data["version"].ToString()); - } - } - catch (HttpRequestException) { } - - return new JsonResult("-"); + _logger.LogError(e, $"Error encountered while sending GET request to {requestUri}"); + return new JsonResult("Unable to fetch latest version") { StatusCode = StatusCodes.Status500InternalServerError }; } + + return new JsonResult("-"); + } + + public async Task GetInstalledWebVersion(CancellationToken cancellationToken) + { + var requestUri = $"{_globalSettings.BaseServiceUri.InternalVault}/version.json"; + try + { + var response = await _httpClient.GetAsync(requestUri, cancellationToken); + if (response.IsSuccessStatusCode) + { + using var jsonDocument = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync(cancellationToken), cancellationToken: cancellationToken); + var root = jsonDocument.RootElement; + return new JsonResult(root.GetProperty("version").GetString()); + } + } + catch (HttpRequestException e) + { + _logger.LogError(e, $"Error encountered while sending GET request to {requestUri}"); + return new JsonResult("Unable to fetch installed version") { StatusCode = StatusCodes.Status500InternalServerError }; + } + + return new JsonResult("-"); + } + + private class LatestVersions + { + [JsonProperty("versions")] + public Versions Versions { get; set; } + } + + private class Versions + { + [JsonProperty("coreVersion")] + public string CoreVersion { get; set; } + + [JsonProperty("webVersion")] + public string WebVersion { get; set; } + + [JsonProperty("keyConnectorVersion")] + public string KeyConnectorVersion { get; set; } } } + +public enum ProjectType +{ + Core, + Web, +} diff --git a/src/Admin/Controllers/InfoController.cs b/src/Admin/Controllers/InfoController.cs new file mode 100644 index 000000000..dc41721de --- /dev/null +++ b/src/Admin/Controllers/InfoController.cs @@ -0,0 +1,20 @@ +using Bit.Core.Utilities; +using Microsoft.AspNetCore.Mvc; + +namespace Bit.Admin.Controllers; + +public class InfoController : Controller +{ + [HttpGet("~/alive")] + [HttpGet("~/now")] + public DateTime GetAlive() + { + return DateTime.UtcNow; + } + + [HttpGet("~/version")] + public JsonResult GetVersion() + { + return Json(AssemblyHelpers.GetVersion()); + } +} diff --git a/src/Admin/Controllers/LoginController.cs b/src/Admin/Controllers/LoginController.cs index d3fc14862..a6ee8e37f 100644 --- a/src/Admin/Controllers/LoginController.cs +++ b/src/Admin/Controllers/LoginController.cs @@ -1,94 +1,92 @@ -using System.Threading.Tasks; +using Bit.Admin.IdentityServer; using Bit.Admin.Models; -using Bit.Core.Identity; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; -namespace Bit.Admin.Controllers +namespace Bit.Admin.Controllers; + +public class LoginController : Controller { - public class LoginController : Controller + private readonly PasswordlessSignInManager _signInManager; + + public LoginController( + PasswordlessSignInManager signInManager) { - private readonly PasswordlessSignInManager _signInManager; + _signInManager = signInManager; + } - public LoginController( - PasswordlessSignInManager signInManager) + public IActionResult Index(string returnUrl = null, int? error = null, int? success = null, + bool accessDenied = false) + { + if (!error.HasValue && accessDenied) { - _signInManager = signInManager; + error = 4; } - public IActionResult Index(string returnUrl = null, int? error = null, int? success = null, - bool accessDenied = false) + return View(new LoginModel { - if (!error.HasValue && accessDenied) - { - error = 4; - } + ReturnUrl = returnUrl, + Error = GetMessage(error), + Success = GetMessage(success) + }); + } - return View(new LoginModel - { - ReturnUrl = returnUrl, - Error = GetMessage(error), - Success = GetMessage(success) - }); - } - - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Index(LoginModel model) + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Index(LoginModel model) + { + if (ModelState.IsValid) { - if (ModelState.IsValid) - { - await _signInManager.PasswordlessSignInAsync(model.Email, model.ReturnUrl); - return RedirectToAction("Index", new - { - success = 3 - }); - } - - return View(model); - } - - public async Task Confirm(string email, string token, string returnUrl) - { - var result = await _signInManager.PasswordlessSignInAsync(email, token, true); - if (!result.Succeeded) - { - return RedirectToAction("Index", new - { - error = 2 - }); - } - - if (!string.IsNullOrWhiteSpace(returnUrl) && Url.IsLocalUrl(returnUrl)) - { - return Redirect(returnUrl); - } - - return RedirectToAction("Index", "Home"); - } - - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Logout() - { - await _signInManager.SignOutAsync(); + await _signInManager.PasswordlessSignInAsync(model.Email, model.ReturnUrl); return RedirectToAction("Index", new { - success = 1 + success = 3 }); } - private string GetMessage(int? messageCode) + return View(model); + } + + public async Task Confirm(string email, string token, string returnUrl) + { + var result = await _signInManager.PasswordlessSignInAsync(email, token, true); + if (!result.Succeeded) { - return messageCode switch + return RedirectToAction("Index", new { - 1 => "You have been logged out.", - 2 => "This login confirmation link is invalid. Try logging in again.", - 3 => "If a valid admin user with this email address exists, " + - "we've sent you an email with a secure link to log in.", - 4 => "Access denied. Please log in.", - _ => null, - }; + error = 2 + }); } + + if (!string.IsNullOrWhiteSpace(returnUrl) && Url.IsLocalUrl(returnUrl)) + { + return Redirect(returnUrl); + } + + return RedirectToAction("Index", "Home"); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Logout() + { + await _signInManager.SignOutAsync(); + return RedirectToAction("Index", new + { + success = 1 + }); + } + + private string GetMessage(int? messageCode) + { + return messageCode switch + { + 1 => "You have been logged out.", + 2 => "This login confirmation link is invalid. Try logging in again.", + 3 => "If a valid admin user with this email address exists, " + + "we've sent you an email with a secure link to log in.", + 4 => "Access denied. Please log in.", + _ => null, + }; } } diff --git a/src/Admin/Controllers/LogsController.cs b/src/Admin/Controllers/LogsController.cs index 716c5631c..449c8cc86 100644 --- a/src/Admin/Controllers/LogsController.cs +++ b/src/Admin/Controllers/LogsController.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Bit.Admin.Models; +using Bit.Admin.Models; using Bit.Core.Settings; using Bit.Core.Utilities; using Microsoft.AspNetCore.Authorization; @@ -11,87 +7,86 @@ using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos.Linq; using Serilog.Events; -namespace Bit.Admin.Controllers +namespace Bit.Admin.Controllers; + +[Authorize] +[SelfHosted(NotSelfHostedOnly = true)] +public class LogsController : Controller { - [Authorize] - [SelfHosted(NotSelfHostedOnly = true)] - public class LogsController : Controller + private const string Database = "Diagnostics"; + private const string Container = "Logs"; + + private readonly GlobalSettings _globalSettings; + + public LogsController(GlobalSettings globalSettings) { - private const string Database = "Diagnostics"; - private const string Container = "Logs"; + _globalSettings = globalSettings; + } - private readonly GlobalSettings _globalSettings; - - public LogsController(GlobalSettings globalSettings) + public async Task Index(string cursor = null, int count = 50, + LogEventLevel? level = null, string project = null, DateTime? start = null, DateTime? end = null) + { + using (var client = new CosmosClient(_globalSettings.DocumentDb.Uri, + _globalSettings.DocumentDb.Key)) { - _globalSettings = globalSettings; - } + var cosmosContainer = client.GetContainer(Database, Container); + var query = cosmosContainer.GetItemLinqQueryable( + requestOptions: new QueryRequestOptions() + { + MaxItemCount = count + }, + continuationToken: cursor + ).AsQueryable(); - public async Task Index(string cursor = null, int count = 50, - LogEventLevel? level = null, string project = null, DateTime? start = null, DateTime? end = null) - { - using (var client = new CosmosClient(_globalSettings.DocumentDb.Uri, - _globalSettings.DocumentDb.Key)) + if (level.HasValue) { - var cosmosContainer = client.GetContainer(Database, Container); - var query = cosmosContainer.GetItemLinqQueryable( - requestOptions: new QueryRequestOptions() - { - MaxItemCount = count - }, - continuationToken: cursor - ).AsQueryable(); - - if (level.HasValue) - { - query = query.Where(l => l.Level == level.Value.ToString()); - } - if (!string.IsNullOrWhiteSpace(project)) - { - query = query.Where(l => l.Properties != null && l.Properties["Project"] == (object)project); - } - if (start.HasValue) - { - query = query.Where(l => l.Timestamp >= start.Value); - } - if (end.HasValue) - { - query = query.Where(l => l.Timestamp <= end.Value); - } - var feedIterator = query.OrderByDescending(l => l.Timestamp).ToFeedIterator(); - var response = await feedIterator.ReadNextAsync(); - - return View(new LogsModel - { - Level = level, - Project = project, - Start = start, - End = end, - Items = response.ToList(), - Count = count, - Cursor = cursor, - NextCursor = response.ContinuationToken - }); + query = query.Where(l => l.Level == level.Value.ToString()); } - } - - public async Task View(Guid id) - { - using (var client = new CosmosClient(_globalSettings.DocumentDb.Uri, - _globalSettings.DocumentDb.Key)) + if (!string.IsNullOrWhiteSpace(project)) { - var cosmosContainer = client.GetContainer(Database, Container); - var query = cosmosContainer.GetItemLinqQueryable() - .AsQueryable() - .Where(l => l.Id == id.ToString()); - - var response = await query.ToFeedIterator().ReadNextAsync(); - if (response == null || response.Count == 0) - { - return RedirectToAction("Index"); - } - return View(response.First()); + query = query.Where(l => l.Properties != null && l.Properties["Project"] == (object)project); } + if (start.HasValue) + { + query = query.Where(l => l.Timestamp >= start.Value); + } + if (end.HasValue) + { + query = query.Where(l => l.Timestamp <= end.Value); + } + var feedIterator = query.OrderByDescending(l => l.Timestamp).ToFeedIterator(); + var response = await feedIterator.ReadNextAsync(); + + return View(new LogsModel + { + Level = level, + Project = project, + Start = start, + End = end, + Items = response.ToList(), + Count = count, + Cursor = cursor, + NextCursor = response.ContinuationToken + }); + } + } + + public async Task View(Guid id) + { + using (var client = new CosmosClient(_globalSettings.DocumentDb.Uri, + _globalSettings.DocumentDb.Key)) + { + var cosmosContainer = client.GetContainer(Database, Container); + var query = cosmosContainer.GetItemLinqQueryable() + .AsQueryable() + .Where(l => l.Id == id.ToString()); + + var response = await query.ToFeedIterator().ReadNextAsync(); + if (response == null || response.Count == 0) + { + return RedirectToAction("Index"); + } + return View(response.First()); } } } diff --git a/src/Admin/Controllers/OrganizationsController.cs b/src/Admin/Controllers/OrganizationsController.cs index b7054c28e..76c00d025 100644 --- a/src/Admin/Controllers/OrganizationsController.cs +++ b/src/Admin/Controllers/OrganizationsController.cs @@ -1,167 +1,216 @@ -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Authorization; +using Bit.Admin.Models; +using Bit.Core.Entities; +using Bit.Core.Enums; +using Bit.Core.Models.Business; +using Bit.Core.Models.OrganizationConnectionConfigs; +using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces; using Bit.Core.Repositories; -using System.Threading.Tasks; -using Bit.Admin.Models; -using System.Collections.Generic; -using Bit.Core.Models.Table; -using Bit.Core.Utilities; using Bit.Core.Services; using Bit.Core.Settings; -using Bit.Core.Models.Business; -using Bit.Core.Enums; +using Bit.Core.Utilities; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; -namespace Bit.Admin.Controllers +namespace Bit.Admin.Controllers; + +[Authorize] +public class OrganizationsController : Controller { - [Authorize] - public class OrganizationsController : Controller + private readonly IOrganizationRepository _organizationRepository; + private readonly IOrganizationUserRepository _organizationUserRepository; + private readonly IOrganizationConnectionRepository _organizationConnectionRepository; + private readonly ISelfHostedSyncSponsorshipsCommand _syncSponsorshipsCommand; + private readonly ICipherRepository _cipherRepository; + private readonly ICollectionRepository _collectionRepository; + private readonly IGroupRepository _groupRepository; + private readonly IPolicyRepository _policyRepository; + private readonly IPaymentService _paymentService; + private readonly ILicensingService _licensingService; + private readonly IApplicationCacheService _applicationCacheService; + private readonly GlobalSettings _globalSettings; + private readonly IReferenceEventService _referenceEventService; + private readonly IUserService _userService; + private readonly ILogger _logger; + + public OrganizationsController( + IOrganizationRepository organizationRepository, + IOrganizationUserRepository organizationUserRepository, + IOrganizationConnectionRepository organizationConnectionRepository, + ISelfHostedSyncSponsorshipsCommand syncSponsorshipsCommand, + ICipherRepository cipherRepository, + ICollectionRepository collectionRepository, + IGroupRepository groupRepository, + IPolicyRepository policyRepository, + IPaymentService paymentService, + ILicensingService licensingService, + IApplicationCacheService applicationCacheService, + GlobalSettings globalSettings, + IReferenceEventService referenceEventService, + IUserService userService, + ILogger logger) { - private readonly IOrganizationRepository _organizationRepository; - private readonly IOrganizationUserRepository _organizationUserRepository; - private readonly ICipherRepository _cipherRepository; - private readonly ICollectionRepository _collectionRepository; - private readonly IGroupRepository _groupRepository; - private readonly IPolicyRepository _policyRepository; - private readonly IPaymentService _paymentService; - private readonly IApplicationCacheService _applicationCacheService; - private readonly GlobalSettings _globalSettings; - private readonly IReferenceEventService _referenceEventService; - private readonly IUserService _userService; + _organizationRepository = organizationRepository; + _organizationUserRepository = organizationUserRepository; + _organizationConnectionRepository = organizationConnectionRepository; + _syncSponsorshipsCommand = syncSponsorshipsCommand; + _cipherRepository = cipherRepository; + _collectionRepository = collectionRepository; + _groupRepository = groupRepository; + _policyRepository = policyRepository; + _paymentService = paymentService; + _licensingService = licensingService; + _applicationCacheService = applicationCacheService; + _globalSettings = globalSettings; + _referenceEventService = referenceEventService; + _userService = userService; + _logger = logger; + } - public OrganizationsController( - IOrganizationRepository organizationRepository, - IOrganizationUserRepository organizationUserRepository, - ICipherRepository cipherRepository, - ICollectionRepository collectionRepository, - IGroupRepository groupRepository, - IPolicyRepository policyRepository, - IPaymentService paymentService, - IApplicationCacheService applicationCacheService, - GlobalSettings globalSettings, - IReferenceEventService referenceEventService, - IUserService userService) + public async Task Index(string name = null, string userEmail = null, bool? paid = null, + int page = 1, int count = 25) + { + if (page < 1) { - _organizationRepository = organizationRepository; - _organizationUserRepository = organizationUserRepository; - _cipherRepository = cipherRepository; - _collectionRepository = collectionRepository; - _groupRepository = groupRepository; - _policyRepository = policyRepository; - _paymentService = paymentService; - _applicationCacheService = applicationCacheService; - _globalSettings = globalSettings; - _referenceEventService = referenceEventService; - _userService = userService; + page = 1; } - public async Task Index(string name = null, string userEmail = null, bool? paid = null, - int page = 1, int count = 25) + if (count < 1) { - if (page < 1) - { - page = 1; - } - - if (count < 1) - { - count = 1; - } - - var skip = (page - 1) * count; - var organizations = await _organizationRepository.SearchAsync(name, userEmail, paid, skip, count); - return View(new OrganizationsModel - { - Items = organizations as List, - Name = string.IsNullOrWhiteSpace(name) ? null : name, - UserEmail = string.IsNullOrWhiteSpace(userEmail) ? null : userEmail, - Paid = paid, - Page = page, - Count = count, - Action = _globalSettings.SelfHosted ? "View" : "Edit", - SelfHosted = _globalSettings.SelfHosted - }); + count = 1; } - public async Task View(Guid id) + var skip = (page - 1) * count; + var organizations = await _organizationRepository.SearchAsync(name, userEmail, paid, skip, count); + return View(new OrganizationsModel { - var organization = await _organizationRepository.GetByIdAsync(id); - if (organization == null) - { - return RedirectToAction("Index"); - } + Items = organizations as List, + Name = string.IsNullOrWhiteSpace(name) ? null : name, + UserEmail = string.IsNullOrWhiteSpace(userEmail) ? null : userEmail, + Paid = paid, + Page = page, + Count = count, + Action = _globalSettings.SelfHosted ? "View" : "Edit", + SelfHosted = _globalSettings.SelfHosted + }); + } - var ciphers = await _cipherRepository.GetManyByOrganizationIdAsync(id); - var collections = await _collectionRepository.GetManyByOrganizationIdAsync(id); - IEnumerable groups = null; - if (organization.UseGroups) - { - groups = await _groupRepository.GetManyByOrganizationIdAsync(id); - } - IEnumerable policies = null; - if (organization.UsePolicies) - { - policies = await _policyRepository.GetManyByOrganizationIdAsync(id); - } - var users = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(id); - return View(new OrganizationViewModel(organization, users, ciphers, collections, groups, policies)); - } - - [SelfHosted(NotSelfHostedOnly = true)] - public async Task Edit(Guid id) + public async Task View(Guid id) + { + var organization = await _organizationRepository.GetByIdAsync(id); + if (organization == null) { - var organization = await _organizationRepository.GetByIdAsync(id); - if (organization == null) - { - return RedirectToAction("Index"); - } - - var ciphers = await _cipherRepository.GetManyByOrganizationIdAsync(id); - var collections = await _collectionRepository.GetManyByOrganizationIdAsync(id); - IEnumerable groups = null; - if (organization.UseGroups) - { - groups = await _groupRepository.GetManyByOrganizationIdAsync(id); - } - IEnumerable policies = null; - if (organization.UsePolicies) - { - policies = await _policyRepository.GetManyByOrganizationIdAsync(id); - } - var users = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(id); - var billingInfo = await _paymentService.GetBillingAsync(organization); - return View(new OrganizationEditModel(organization, users, ciphers, collections, groups, policies, - billingInfo, _globalSettings)); - } - - [HttpPost] - [ValidateAntiForgeryToken] - [SelfHosted(NotSelfHostedOnly = true)] - public async Task Edit(Guid id, OrganizationEditModel model) - { - var organization = await _organizationRepository.GetByIdAsync(id); - model.ToOrganization(organization); - await _organizationRepository.ReplaceAsync(organization); - await _applicationCacheService.UpsertOrganizationAbilityAsync(organization); - await _referenceEventService.RaiseEventAsync(new ReferenceEvent(ReferenceEventType.OrganizationEditedByAdmin, organization) { - EventRaisedByUser = _userService.GetUserName(User), - SalesAssistedTrialStarted = model.SalesAssistedTrialStarted, - }); - return RedirectToAction("Edit", new { id }); - } - - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Delete(Guid id) - { - var organization = await _organizationRepository.GetByIdAsync(id); - if (organization != null) - { - await _organizationRepository.DeleteAsync(organization); - await _applicationCacheService.DeleteOrganizationAbilityAsync(organization.Id); - } - return RedirectToAction("Index"); } + + var ciphers = await _cipherRepository.GetManyByOrganizationIdAsync(id); + var collections = await _collectionRepository.GetManyByOrganizationIdAsync(id); + IEnumerable groups = null; + if (organization.UseGroups) + { + groups = await _groupRepository.GetManyByOrganizationIdAsync(id); + } + IEnumerable policies = null; + if (organization.UsePolicies) + { + policies = await _policyRepository.GetManyByOrganizationIdAsync(id); + } + var users = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(id); + var billingSyncConnection = _globalSettings.EnableCloudCommunication ? await _organizationConnectionRepository.GetByOrganizationIdTypeAsync(id, OrganizationConnectionType.CloudBillingSync) : null; + return View(new OrganizationViewModel(organization, billingSyncConnection, users, ciphers, collections, groups, policies)); } + + [SelfHosted(NotSelfHostedOnly = true)] + public async Task Edit(Guid id) + { + var organization = await _organizationRepository.GetByIdAsync(id); + if (organization == null) + { + return RedirectToAction("Index"); + } + + var ciphers = await _cipherRepository.GetManyByOrganizationIdAsync(id); + var collections = await _collectionRepository.GetManyByOrganizationIdAsync(id); + IEnumerable groups = null; + if (organization.UseGroups) + { + groups = await _groupRepository.GetManyByOrganizationIdAsync(id); + } + IEnumerable policies = null; + if (organization.UsePolicies) + { + policies = await _policyRepository.GetManyByOrganizationIdAsync(id); + } + var users = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(id); + var billingInfo = await _paymentService.GetBillingAsync(organization); + var billingSyncConnection = _globalSettings.EnableCloudCommunication ? await _organizationConnectionRepository.GetByOrganizationIdTypeAsync(id, OrganizationConnectionType.CloudBillingSync) : null; + return View(new OrganizationEditModel(organization, users, ciphers, collections, groups, policies, + billingInfo, billingSyncConnection, _globalSettings)); + } + + [HttpPost] + [ValidateAntiForgeryToken] + [SelfHosted(NotSelfHostedOnly = true)] + public async Task Edit(Guid id, OrganizationEditModel model) + { + var organization = await _organizationRepository.GetByIdAsync(id); + model.ToOrganization(organization); + await _organizationRepository.ReplaceAsync(organization); + await _applicationCacheService.UpsertOrganizationAbilityAsync(organization); + await _referenceEventService.RaiseEventAsync(new ReferenceEvent(ReferenceEventType.OrganizationEditedByAdmin, organization) + { + EventRaisedByUser = _userService.GetUserName(User), + SalesAssistedTrialStarted = model.SalesAssistedTrialStarted, + }); + return RedirectToAction("Edit", new { id }); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Delete(Guid id) + { + var organization = await _organizationRepository.GetByIdAsync(id); + if (organization != null) + { + await _organizationRepository.DeleteAsync(organization); + await _applicationCacheService.DeleteOrganizationAbilityAsync(organization.Id); + } + + return RedirectToAction("Index"); + } + + public async Task TriggerBillingSync(Guid id) + { + var organization = await _organizationRepository.GetByIdAsync(id); + if (organization == null) + { + return RedirectToAction("Index"); + } + var connection = (await _organizationConnectionRepository.GetEnabledByOrganizationIdTypeAsync(id, OrganizationConnectionType.CloudBillingSync)).FirstOrDefault(); + if (connection != null) + { + try + { + var config = connection.GetConfig(); + await _syncSponsorshipsCommand.SyncOrganization(id, config.CloudOrganizationId, connection); + TempData["ConnectionActivated"] = id; + TempData["ConnectionError"] = null; + } + catch (Exception ex) + { + TempData["ConnectionError"] = ex.Message; + _logger.LogWarning(ex, "Error while attempting to do billing sync for organization with id '{OrganizationId}'", id); + } + + if (_globalSettings.SelfHosted) + { + return RedirectToAction("View", new { id }); + } + else + { + return RedirectToAction("Edit", new { id }); + } + } + return RedirectToAction("Index"); + } + } diff --git a/src/Admin/Controllers/ProvidersController.cs b/src/Admin/Controllers/ProvidersController.cs index e27396aa1..a141b9fd0 100644 --- a/src/Admin/Controllers/ProvidersController.cs +++ b/src/Admin/Controllers/ProvidersController.cs @@ -1,8 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Bit.Admin.Models; -using Bit.Core.Models.Table.Provider; +using Bit.Admin.Models; +using Bit.Core.Entities.Provider; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Settings; @@ -10,128 +7,127 @@ using Bit.Core.Utilities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace Bit.Admin.Controllers +namespace Bit.Admin.Controllers; + +[Authorize] +[SelfHosted(NotSelfHostedOnly = true)] +public class ProvidersController : Controller { - [Authorize] - [SelfHosted(NotSelfHostedOnly = true)] - public class ProvidersController : Controller + private readonly IProviderRepository _providerRepository; + private readonly IProviderUserRepository _providerUserRepository; + private readonly IProviderOrganizationRepository _providerOrganizationRepository; + private readonly GlobalSettings _globalSettings; + private readonly IApplicationCacheService _applicationCacheService; + private readonly IProviderService _providerService; + + public ProvidersController(IProviderRepository providerRepository, IProviderUserRepository providerUserRepository, + IProviderOrganizationRepository providerOrganizationRepository, IProviderService providerService, + GlobalSettings globalSettings, IApplicationCacheService applicationCacheService) { - private readonly IProviderRepository _providerRepository; - private readonly IProviderUserRepository _providerUserRepository; - private readonly IProviderOrganizationRepository _providerOrganizationRepository; - private readonly GlobalSettings _globalSettings; - private readonly IApplicationCacheService _applicationCacheService; - private readonly IProviderService _providerService; + _providerRepository = providerRepository; + _providerUserRepository = providerUserRepository; + _providerOrganizationRepository = providerOrganizationRepository; + _providerService = providerService; + _globalSettings = globalSettings; + _applicationCacheService = applicationCacheService; + } - public ProvidersController(IProviderRepository providerRepository, IProviderUserRepository providerUserRepository, - IProviderOrganizationRepository providerOrganizationRepository, IProviderService providerService, - GlobalSettings globalSettings, IApplicationCacheService applicationCacheService) + public async Task Index(string name = null, string userEmail = null, int page = 1, int count = 25) + { + if (page < 1) { - _providerRepository = providerRepository; - _providerUserRepository = providerUserRepository; - _providerOrganizationRepository = providerOrganizationRepository; - _providerService = providerService; - _globalSettings = globalSettings; - _applicationCacheService = applicationCacheService; + page = 1; } - public async Task Index(string name = null, string userEmail = null, int page = 1, int count = 25) + if (count < 1) { - if (page < 1) - { - page = 1; - } - - if (count < 1) - { - count = 1; - } - - var skip = (page - 1) * count; - var providers = await _providerRepository.SearchAsync(name, userEmail, skip, count); - return View(new ProvidersModel - { - Items = providers as List, - Name = string.IsNullOrWhiteSpace(name) ? null : name, - UserEmail = string.IsNullOrWhiteSpace(userEmail) ? null : userEmail, - Page = page, - Count = count, - Action = _globalSettings.SelfHosted ? "View" : "Edit", - SelfHosted = _globalSettings.SelfHosted - }); + count = 1; } - public IActionResult Create(string ownerEmail = null) + var skip = (page - 1) * count; + var providers = await _providerRepository.SearchAsync(name, userEmail, skip, count); + return View(new ProvidersModel { - return View(new CreateProviderModel - { - OwnerEmail = ownerEmail - }); + Items = providers as List, + Name = string.IsNullOrWhiteSpace(name) ? null : name, + UserEmail = string.IsNullOrWhiteSpace(userEmail) ? null : userEmail, + Page = page, + Count = count, + Action = _globalSettings.SelfHosted ? "View" : "Edit", + SelfHosted = _globalSettings.SelfHosted + }); + } + + public IActionResult Create(string ownerEmail = null) + { + return View(new CreateProviderModel + { + OwnerEmail = ownerEmail + }); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Create(CreateProviderModel model) + { + if (!ModelState.IsValid) + { + return View(model); } - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Create(CreateProviderModel model) + await _providerService.CreateAsync(model.OwnerEmail); + + return RedirectToAction("Index"); + } + + public async Task View(Guid id) + { + var provider = await _providerRepository.GetByIdAsync(id); + if (provider == null) { - if (!ModelState.IsValid) - { - return View(model); - } - - await _providerService.CreateAsync(model.OwnerEmail); - return RedirectToAction("Index"); } - public async Task View(Guid id) - { - var provider = await _providerRepository.GetByIdAsync(id); - if (provider == null) - { - return RedirectToAction("Index"); - } + var users = await _providerUserRepository.GetManyDetailsByProviderAsync(id); + var providerOrganizations = await _providerOrganizationRepository.GetManyDetailsByProviderAsync(id); + return View(new ProviderViewModel(provider, users, providerOrganizations)); + } - var users = await _providerUserRepository.GetManyDetailsByProviderAsync(id); - var providerOrganizations = await _providerOrganizationRepository.GetManyDetailsByProviderAsync(id); - return View(new ProviderViewModel(provider, users, providerOrganizations)); + [SelfHosted(NotSelfHostedOnly = true)] + public async Task Edit(Guid id) + { + var provider = await _providerRepository.GetByIdAsync(id); + if (provider == null) + { + return RedirectToAction("Index"); } - [SelfHosted(NotSelfHostedOnly = true)] - public async Task Edit(Guid id) - { - var provider = await _providerRepository.GetByIdAsync(id); - if (provider == null) - { - return RedirectToAction("Index"); - } + var users = await _providerUserRepository.GetManyDetailsByProviderAsync(id); + var providerOrganizations = await _providerOrganizationRepository.GetManyDetailsByProviderAsync(id); + return View(new ProviderEditModel(provider, users, providerOrganizations)); + } - var users = await _providerUserRepository.GetManyDetailsByProviderAsync(id); - var providerOrganizations = await _providerOrganizationRepository.GetManyDetailsByProviderAsync(id); - return View(new ProviderEditModel(provider, users, providerOrganizations)); + [HttpPost] + [ValidateAntiForgeryToken] + [SelfHosted(NotSelfHostedOnly = true)] + public async Task Edit(Guid id, ProviderEditModel model) + { + var provider = await _providerRepository.GetByIdAsync(id); + if (provider == null) + { + return RedirectToAction("Index"); } - [HttpPost] - [ValidateAntiForgeryToken] - [SelfHosted(NotSelfHostedOnly = true)] - public async Task Edit(Guid id, ProviderEditModel model) - { - var provider = await _providerRepository.GetByIdAsync(id); - if (provider == null) - { - return RedirectToAction("Index"); - } + model.ToProvider(provider); + await _providerRepository.ReplaceAsync(provider); + await _applicationCacheService.UpsertProviderAbilityAsync(provider); + return RedirectToAction("Edit", new { id }); + } - model.ToProvider(provider); - await _providerRepository.ReplaceAsync(provider); - await _applicationCacheService.UpsertProviderAbilityAsync(provider); - return RedirectToAction("Edit", new { id }); - } - - public async Task ResendInvite(Guid ownerId, Guid providerId) - { - await _providerService.ResendProviderSetupInviteEmailAsync(providerId, ownerId); - TempData["InviteResentTo"] = ownerId; - return RedirectToAction("Edit", new { id = providerId }); - } + public async Task ResendInvite(Guid ownerId, Guid providerId) + { + await _providerService.ResendProviderSetupInviteEmailAsync(providerId, ownerId); + TempData["InviteResentTo"] = ownerId; + return RedirectToAction("Edit", new { id = providerId }); } } diff --git a/src/Admin/Controllers/ToolsController.cs b/src/Admin/Controllers/ToolsController.cs index 28dff84af..9bd6189b3 100644 --- a/src/Admin/Controllers/ToolsController.cs +++ b/src/Admin/Controllers/ToolsController.cs @@ -1,417 +1,382 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Text; +using System.Text.Json; using Bit.Admin.Models; -using Bit.Core; -using Bit.Core.Models.Table; +using Bit.Core.Entities; +using Bit.Core.Models.BitStripe; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Settings; using Bit.Core.Utilities; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using Newtonsoft.Json; -namespace Bit.Admin.Controllers +namespace Bit.Admin.Controllers; + +[Authorize] +[SelfHosted(NotSelfHostedOnly = true)] +public class ToolsController : Controller { - [Authorize] - [SelfHosted(NotSelfHostedOnly = true)] - public class ToolsController : Controller + private readonly GlobalSettings _globalSettings; + private readonly IOrganizationRepository _organizationRepository; + private readonly IOrganizationService _organizationService; + private readonly IUserService _userService; + private readonly ITransactionRepository _transactionRepository; + private readonly IInstallationRepository _installationRepository; + private readonly IOrganizationUserRepository _organizationUserRepository; + private readonly IPaymentService _paymentService; + private readonly ITaxRateRepository _taxRateRepository; + private readonly IStripeAdapter _stripeAdapter; + + public ToolsController( + GlobalSettings globalSettings, + IOrganizationRepository organizationRepository, + IOrganizationService organizationService, + IUserService userService, + ITransactionRepository transactionRepository, + IInstallationRepository installationRepository, + IOrganizationUserRepository organizationUserRepository, + ITaxRateRepository taxRateRepository, + IPaymentService paymentService, + IStripeAdapter stripeAdapter) { - private readonly GlobalSettings _globalSettings; - private readonly IOrganizationRepository _organizationRepository; - private readonly IOrganizationService _organizationService; - private readonly IUserService _userService; - private readonly ITransactionRepository _transactionRepository; - private readonly IInstallationRepository _installationRepository; - private readonly IOrganizationUserRepository _organizationUserRepository; - private readonly IPaymentService _paymentService; - private readonly ITaxRateRepository _taxRateRepository; + _globalSettings = globalSettings; + _organizationRepository = organizationRepository; + _organizationService = organizationService; + _userService = userService; + _transactionRepository = transactionRepository; + _installationRepository = installationRepository; + _organizationUserRepository = organizationUserRepository; + _taxRateRepository = taxRateRepository; + _paymentService = paymentService; + _stripeAdapter = stripeAdapter; + } - public ToolsController( - GlobalSettings globalSettings, - IOrganizationRepository organizationRepository, - IOrganizationService organizationService, - IUserService userService, - ITransactionRepository transactionRepository, - IInstallationRepository installationRepository, - IOrganizationUserRepository organizationUserRepository, - ITaxRateRepository taxRateRepository, - IPaymentService paymentService) + public IActionResult ChargeBraintree() + { + return View(new ChargeBraintreeModel()); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task ChargeBraintree(ChargeBraintreeModel model) + { + if (!ModelState.IsValid) { - _globalSettings = globalSettings; - _organizationRepository = organizationRepository; - _organizationService = organizationService; - _userService = userService; - _transactionRepository = transactionRepository; - _installationRepository = installationRepository; - _organizationUserRepository = organizationUserRepository; - _taxRateRepository = taxRateRepository; - _paymentService = paymentService; - } - - public IActionResult ChargeBraintree() - { - return View(new ChargeBraintreeModel()); - } - - [HttpPost] - [ValidateAntiForgeryToken] - public async Task ChargeBraintree(ChargeBraintreeModel model) - { - if (!ModelState.IsValid) - { - return View(model); - } - - var btGateway = new Braintree.BraintreeGateway - { - Environment = _globalSettings.Braintree.Production ? - Braintree.Environment.PRODUCTION : Braintree.Environment.SANDBOX, - MerchantId = _globalSettings.Braintree.MerchantId, - PublicKey = _globalSettings.Braintree.PublicKey, - PrivateKey = _globalSettings.Braintree.PrivateKey - }; - - var btObjIdField = model.Id[0] == 'o' ? "organization_id" : "user_id"; - var btObjId = new Guid(model.Id.Substring(1, 32)); - - var transactionResult = await btGateway.Transaction.SaleAsync( - new Braintree.TransactionRequest - { - Amount = model.Amount.Value, - CustomerId = model.Id, - Options = new Braintree.TransactionOptionsRequest - { - SubmitForSettlement = true, - PayPal = new Braintree.TransactionOptionsPayPalRequest - { - CustomField = $"{btObjIdField}:{btObjId}" - } - }, - CustomFields = new Dictionary - { - [btObjIdField] = btObjId.ToString() - } - }); - - if (!transactionResult.IsSuccess()) - { - ModelState.AddModelError(string.Empty, "Charge failed. " + - "Refer to Braintree admin portal for more information."); - } - else - { - model.TransactionId = transactionResult.Target.Id; - model.PayPalTransactionId = transactionResult.Target?.PayPalDetails?.CaptureId; - } return View(model); } - public IActionResult CreateTransaction(Guid? organizationId = null, Guid? userId = null) + var btGateway = new Braintree.BraintreeGateway { - return View("CreateUpdateTransaction", new CreateUpdateTransactionModel + Environment = _globalSettings.Braintree.Production ? + Braintree.Environment.PRODUCTION : Braintree.Environment.SANDBOX, + MerchantId = _globalSettings.Braintree.MerchantId, + PublicKey = _globalSettings.Braintree.PublicKey, + PrivateKey = _globalSettings.Braintree.PrivateKey + }; + + var btObjIdField = model.Id[0] == 'o' ? "organization_id" : "user_id"; + var btObjId = new Guid(model.Id.Substring(1, 32)); + + var transactionResult = await btGateway.Transaction.SaleAsync( + new Braintree.TransactionRequest { - OrganizationId = organizationId, - UserId = userId + Amount = model.Amount.Value, + CustomerId = model.Id, + Options = new Braintree.TransactionOptionsRequest + { + SubmitForSettlement = true, + PayPal = new Braintree.TransactionOptionsPayPalRequest + { + CustomField = $"{btObjIdField}:{btObjId}" + } + }, + CustomFields = new Dictionary + { + [btObjIdField] = btObjId.ToString() + } }); + + if (!transactionResult.IsSuccess()) + { + ModelState.AddModelError(string.Empty, "Charge failed. " + + "Refer to Braintree admin portal for more information."); + } + else + { + model.TransactionId = transactionResult.Target.Id; + model.PayPalTransactionId = transactionResult.Target?.PayPalDetails?.CaptureId; + } + return View(model); + } + + public IActionResult CreateTransaction(Guid? organizationId = null, Guid? userId = null) + { + return View("CreateUpdateTransaction", new CreateUpdateTransactionModel + { + OrganizationId = organizationId, + UserId = userId + }); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task CreateTransaction(CreateUpdateTransactionModel model) + { + if (!ModelState.IsValid) + { + return View("CreateUpdateTransaction", model); } - [HttpPost] - [ValidateAntiForgeryToken] - public async Task CreateTransaction(CreateUpdateTransactionModel model) + await _transactionRepository.CreateAsync(model.ToTransaction()); + if (model.UserId.HasValue) { - if (!ModelState.IsValid) - { - return View("CreateUpdateTransaction", model); - } + return RedirectToAction("Edit", "Users", new { id = model.UserId }); + } + else + { + return RedirectToAction("Edit", "Organizations", new { id = model.OrganizationId }); + } + } - await _transactionRepository.CreateAsync(model.ToTransaction()); - if (model.UserId.HasValue) - { - return RedirectToAction("Edit", "Users", new { id = model.UserId }); - } - else - { - return RedirectToAction("Edit", "Organizations", new { id = model.OrganizationId }); - } + public async Task EditTransaction(Guid id) + { + var transaction = await _transactionRepository.GetByIdAsync(id); + if (transaction == null) + { + return RedirectToAction("Index", "Home"); + } + return View("CreateUpdateTransaction", new CreateUpdateTransactionModel(transaction)); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task EditTransaction(Guid id, CreateUpdateTransactionModel model) + { + if (!ModelState.IsValid) + { + return View("CreateUpdateTransaction", model); + } + await _transactionRepository.ReplaceAsync(model.ToTransaction(id)); + if (model.UserId.HasValue) + { + return RedirectToAction("Edit", "Users", new { id = model.UserId }); + } + else + { + return RedirectToAction("Edit", "Organizations", new { id = model.OrganizationId }); + } + } + + public IActionResult PromoteAdmin() + { + return View(); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task PromoteAdmin(PromoteAdminModel model) + { + if (!ModelState.IsValid) + { + return View(model); } - public async Task EditTransaction(Guid id) + var orgUsers = await _organizationUserRepository.GetManyByOrganizationAsync( + model.OrganizationId.Value, null); + var user = orgUsers.FirstOrDefault(u => u.UserId == model.UserId.Value); + if (user == null) { - var transaction = await _transactionRepository.GetByIdAsync(id); - if (transaction == null) - { - return RedirectToAction("Index", "Home"); - } - return View("CreateUpdateTransaction", new CreateUpdateTransactionModel(transaction)); + ModelState.AddModelError(nameof(model.UserId), "User Id not found in this organization."); + } + else if (user.Type != Core.Enums.OrganizationUserType.Admin) + { + ModelState.AddModelError(nameof(model.UserId), "User is not an admin of this organization."); } - [HttpPost] - [ValidateAntiForgeryToken] - public async Task EditTransaction(Guid id, CreateUpdateTransactionModel model) + if (!ModelState.IsValid) { - if (!ModelState.IsValid) - { - return View("CreateUpdateTransaction", model); - } - await _transactionRepository.ReplaceAsync(model.ToTransaction(id)); - if (model.UserId.HasValue) - { - return RedirectToAction("Edit", "Users", new { id = model.UserId }); - } - else - { - return RedirectToAction("Edit", "Organizations", new { id = model.OrganizationId }); - } + return View(model); } - public IActionResult PromoteAdmin() + user.Type = Core.Enums.OrganizationUserType.Owner; + await _organizationUserRepository.ReplaceAsync(user); + return RedirectToAction("Edit", "Organizations", new { id = model.OrganizationId.Value }); + } + + public IActionResult GenerateLicense() + { + return View(); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task GenerateLicense(LicenseModel model) + { + if (!ModelState.IsValid) { - return View(); + return View(model); } - [HttpPost] - [ValidateAntiForgeryToken] - public async Task PromoteAdmin(PromoteAdminModel model) + User user = null; + Organization organization = null; + if (model.UserId.HasValue) { - if (!ModelState.IsValid) - { - return View(model); - } - - var orgUsers = await _organizationUserRepository.GetManyByOrganizationAsync( - model.OrganizationId.Value, null); - var user = orgUsers.FirstOrDefault(u => u.UserId == model.UserId.Value); + user = await _userService.GetUserByIdAsync(model.UserId.Value); if (user == null) { - ModelState.AddModelError(nameof(model.UserId), "User Id not found in this organization."); + ModelState.AddModelError(nameof(model.UserId), "User Id not found."); } - else if (user.Type != Core.Enums.OrganizationUserType.Admin) - { - ModelState.AddModelError(nameof(model.UserId), "User is not an admin of this organization."); - } - - if (!ModelState.IsValid) - { - return View(model); - } - - user.Type = Core.Enums.OrganizationUserType.Owner; - await _organizationUserRepository.ReplaceAsync(user); - return RedirectToAction("Edit", "Organizations", new { id = model.OrganizationId.Value }); } - - public IActionResult GenerateLicense() + else if (model.OrganizationId.HasValue) { - return View(); + organization = await _organizationRepository.GetByIdAsync(model.OrganizationId.Value); + if (organization == null) + { + ModelState.AddModelError(nameof(model.OrganizationId), "Organization not found."); + } + else if (!organization.Enabled) + { + ModelState.AddModelError(nameof(model.OrganizationId), "Organization is disabled."); + } } - - [HttpPost] - [ValidateAntiForgeryToken] - public async Task GenerateLicense(LicenseModel model) + if (model.InstallationId.HasValue) { - if (!ModelState.IsValid) + var installation = await _installationRepository.GetByIdAsync(model.InstallationId.Value); + if (installation == null) { - return View(model); + ModelState.AddModelError(nameof(model.InstallationId), "Installation not found."); } - - User user = null; - Organization organization = null; - if (model.UserId.HasValue) + else if (!installation.Enabled) { - user = await _userService.GetUserByIdAsync(model.UserId.Value); - if (user == null) - { - ModelState.AddModelError(nameof(model.UserId), "User Id not found."); - } - } - else if (model.OrganizationId.HasValue) - { - organization = await _organizationRepository.GetByIdAsync(model.OrganizationId.Value); - if (organization == null) - { - ModelState.AddModelError(nameof(model.OrganizationId), "Organization not found."); - } - else if (!organization.Enabled) - { - ModelState.AddModelError(nameof(model.OrganizationId), "Organization is disabled."); - } - } - if (model.InstallationId.HasValue) - { - var installation = await _installationRepository.GetByIdAsync(model.InstallationId.Value); - if (installation == null) - { - ModelState.AddModelError(nameof(model.InstallationId), "Installation not found."); - } - else if (!installation.Enabled) - { - ModelState.AddModelError(nameof(model.OrganizationId), "Installation is disabled."); - } - } - - if (!ModelState.IsValid) - { - return View(model); - } - - if (organization != null) - { - var license = await _organizationService.GenerateLicenseAsync(organization, - model.InstallationId.Value, model.Version); - return File(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(license, Formatting.Indented)), - "text/plain", "bitwarden_organization_license.json"); - } - else if (user != null) - { - var license = await _userService.GenerateLicenseAsync(user, null, model.Version); - return File(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(license, Formatting.Indented)), - "text/plain", "bitwarden_premium_license.json"); - } - else - { - throw new Exception("No license to generate."); + ModelState.AddModelError(nameof(model.OrganizationId), "Installation is disabled."); } } - public async Task TaxRate(int page = 1, int count = 25) + if (!ModelState.IsValid) { - if (page < 1) - { - page = 1; - } - - if (count < 1) - { - count = 1; - } - - var skip = (page - 1) * count; - var rates = await _taxRateRepository.SearchAsync(skip, count); - return View(new TaxRatesModel - { - Items = rates.ToList(), - Page = page, - Count = count - }); - } - - public async Task TaxRateAddEdit(string stripeTaxRateId = null) - { - if (string.IsNullOrWhiteSpace(stripeTaxRateId)) - { - return View(new TaxRateAddEditModel()); - } - - var rate = await _taxRateRepository.GetByIdAsync(stripeTaxRateId); - var model = new TaxRateAddEditModel() - { - StripeTaxRateId = stripeTaxRateId, - Country = rate.Country, - State = rate.State, - PostalCode = rate.PostalCode, - Rate = rate.Rate - }; - return View(model); - } - - [ValidateAntiForgeryToken] - public async Task TaxRateUpload(IFormFile file) - { - if (file == null || file.Length == 0) - { - throw new ArgumentNullException(nameof(file)); - } - - // Build rates and validate them first before updating DB & Stripe - var taxRateUpdates = new List(); - var currentTaxRates = await _taxRateRepository.GetAllActiveAsync(); - using var reader = new StreamReader(file.OpenReadStream()); - while (!reader.EndOfStream) - { - var line = await reader.ReadLineAsync(); - if (string.IsNullOrWhiteSpace(line)) - { - continue; - } - var taxParts = line.Split(','); - if (taxParts.Length < 2) - { - throw new Exception($"This line is not in the format of ,,,: {line}"); - } - var postalCode = taxParts[0].Trim(); - if (string.IsNullOrWhiteSpace(postalCode)) - { - throw new Exception($"'{line}' is not valid, the first element must contain a postal code."); - } - if (!decimal.TryParse(taxParts[1], out var rate) || rate <= 0M || rate > 100) - { - throw new Exception($"{taxParts[1]} is not a valid rate/decimal for {postalCode}"); - } - var state = taxParts.Length > 2 ? taxParts[2] : null; - var country = (taxParts.Length > 3 ? taxParts[3] : null); - if (string.IsNullOrWhiteSpace(country)) - { - country = "US"; - } - var taxRate = currentTaxRates.FirstOrDefault(r => r.Country == country && r.PostalCode == postalCode) ?? - new TaxRate - { - Country = country, - PostalCode = postalCode, - Active = true, - }; - taxRate.Rate = rate; - taxRate.State = state ?? taxRate.State; - taxRateUpdates.Add(taxRate); - } - - foreach (var taxRate in taxRateUpdates) - { - if (!string.IsNullOrWhiteSpace(taxRate.Id)) - { - await _paymentService.UpdateTaxRateAsync(taxRate); - } - else - { - await _paymentService.CreateTaxRateAsync(taxRate); - } - } - - return RedirectToAction("TaxRate"); } - [HttpPost] - [ValidateAntiForgeryToken] - public async Task TaxRateAddEdit(TaxRateAddEditModel model) + if (organization != null) { - var existingRateCheck = await _taxRateRepository.GetByLocationAsync(new TaxRate() { Country = model.Country, PostalCode = model.PostalCode }); - if (existingRateCheck.Any()) + var license = await _organizationService.GenerateLicenseAsync(organization, + model.InstallationId.Value, model.Version); + var ms = new MemoryStream(); + await JsonSerializer.SerializeAsync(ms, license, JsonHelpers.Indented); + ms.Seek(0, SeekOrigin.Begin); + return File(ms, "text/plain", "bitwarden_organization_license.json"); + } + else if (user != null) + { + var license = await _userService.GenerateLicenseAsync(user, null, model.Version); + var ms = new MemoryStream(); + ms.Seek(0, SeekOrigin.Begin); + await JsonSerializer.SerializeAsync(ms, license, JsonHelpers.Indented); + ms.Seek(0, SeekOrigin.Begin); + return File(ms, "text/plain", "bitwarden_premium_license.json"); + } + else + { + throw new Exception("No license to generate."); + } + } + + public async Task TaxRate(int page = 1, int count = 25) + { + if (page < 1) + { + page = 1; + } + + if (count < 1) + { + count = 1; + } + + var skip = (page - 1) * count; + var rates = await _taxRateRepository.SearchAsync(skip, count); + return View(new TaxRatesModel + { + Items = rates.ToList(), + Page = page, + Count = count + }); + } + + public async Task TaxRateAddEdit(string stripeTaxRateId = null) + { + if (string.IsNullOrWhiteSpace(stripeTaxRateId)) + { + return View(new TaxRateAddEditModel()); + } + + var rate = await _taxRateRepository.GetByIdAsync(stripeTaxRateId); + var model = new TaxRateAddEditModel() + { + StripeTaxRateId = stripeTaxRateId, + Country = rate.Country, + State = rate.State, + PostalCode = rate.PostalCode, + Rate = rate.Rate + }; + + return View(model); + } + + [ValidateAntiForgeryToken] + public async Task TaxRateUpload(IFormFile file) + { + if (file == null || file.Length == 0) + { + throw new ArgumentNullException(nameof(file)); + } + + // Build rates and validate them first before updating DB & Stripe + var taxRateUpdates = new List(); + var currentTaxRates = await _taxRateRepository.GetAllActiveAsync(); + using var reader = new StreamReader(file.OpenReadStream()); + while (!reader.EndOfStream) + { + var line = await reader.ReadLineAsync(); + if (string.IsNullOrWhiteSpace(line)) { - ModelState.AddModelError(nameof(model.PostalCode), "A tax rate already exists for this Country/Postal Code combination."); + continue; } - - if (!ModelState.IsValid) + var taxParts = line.Split(','); + if (taxParts.Length < 2) { - return View(model); + throw new Exception($"This line is not in the format of ,,,: {line}"); } - - var taxRate = new TaxRate() + var postalCode = taxParts[0].Trim(); + if (string.IsNullOrWhiteSpace(postalCode)) { - Id = model.StripeTaxRateId, - Country = model.Country, - State = model.State, - PostalCode = model.PostalCode, - Rate = model.Rate - }; + throw new Exception($"'{line}' is not valid, the first element must contain a postal code."); + } + if (!decimal.TryParse(taxParts[1], out var rate) || rate <= 0M || rate > 100) + { + throw new Exception($"{taxParts[1]} is not a valid rate/decimal for {postalCode}"); + } + var state = taxParts.Length > 2 ? taxParts[2] : null; + var country = (taxParts.Length > 3 ? taxParts[3] : null); + if (string.IsNullOrWhiteSpace(country)) + { + country = "US"; + } + var taxRate = currentTaxRates.FirstOrDefault(r => r.Country == country && r.PostalCode == postalCode) ?? + new TaxRate + { + Country = country, + PostalCode = postalCode, + Active = true, + }; + taxRate.Rate = rate; + taxRate.State = state ?? taxRate.State; + taxRateUpdates.Add(taxRate); + } - if (!string.IsNullOrWhiteSpace(model.StripeTaxRateId)) + foreach (var taxRate in taxRateUpdates) + { + if (!string.IsNullOrWhiteSpace(taxRate.Id)) { await _paymentService.UpdateTaxRateAsync(taxRate); } @@ -419,18 +384,175 @@ namespace Bit.Admin.Controllers { await _paymentService.CreateTaxRateAsync(taxRate); } - - return RedirectToAction("TaxRate"); } - public async Task TaxRateArchive(string stripeTaxRateId) + return RedirectToAction("TaxRate"); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task TaxRateAddEdit(TaxRateAddEditModel model) + { + var existingRateCheck = await _taxRateRepository.GetByLocationAsync(new TaxRate() { Country = model.Country, PostalCode = model.PostalCode }); + if (existingRateCheck.Any()) { - if (!string.IsNullOrWhiteSpace(stripeTaxRateId)) + ModelState.AddModelError(nameof(model.PostalCode), "A tax rate already exists for this Country/Postal Code combination."); + } + + if (!ModelState.IsValid) + { + return View(model); + } + + var taxRate = new TaxRate() + { + Id = model.StripeTaxRateId, + Country = model.Country, + State = model.State, + PostalCode = model.PostalCode, + Rate = model.Rate + }; + + if (!string.IsNullOrWhiteSpace(model.StripeTaxRateId)) + { + await _paymentService.UpdateTaxRateAsync(taxRate); + } + else + { + await _paymentService.CreateTaxRateAsync(taxRate); + } + + return RedirectToAction("TaxRate"); + } + + public async Task TaxRateArchive(string stripeTaxRateId) + { + if (!string.IsNullOrWhiteSpace(stripeTaxRateId)) + { + await _paymentService.ArchiveTaxRateAsync(new TaxRate() { Id = stripeTaxRateId }); + } + + return RedirectToAction("TaxRate"); + } + + public async Task StripeSubscriptions(StripeSubscriptionListOptions options) + { + options = options ?? new StripeSubscriptionListOptions(); + options.Limit = 10; + options.Expand = new List() { "data.customer", "data.latest_invoice" }; + options.SelectAll = false; + + var subscriptions = await _stripeAdapter.SubscriptionListAsync(options); + + options.StartingAfter = subscriptions.LastOrDefault()?.Id; + options.EndingBefore = await StripeSubscriptionsGetHasPreviousPage(subscriptions, options) ? + subscriptions.FirstOrDefault()?.Id : + null; + + var model = new StripeSubscriptionsModel() + { + Items = subscriptions.Select(s => new StripeSubscriptionRowModel(s)).ToList(), + Prices = (await _stripeAdapter.PriceListAsync(new Stripe.PriceListOptions() { Limit = 100 })).Data, + TestClocks = await _stripeAdapter.TestClockListAsync(), + Filter = options + }; + return View(model); + } + + [HttpPost] + public async Task StripeSubscriptions([FromForm] StripeSubscriptionsModel model) + { + if (!ModelState.IsValid) + { + model.Prices = (await _stripeAdapter.PriceListAsync(new Stripe.PriceListOptions() { Limit = 100 })).Data; + model.TestClocks = await _stripeAdapter.TestClockListAsync(); + return View(model); + } + + if (model.Action == StripeSubscriptionsAction.Export || model.Action == StripeSubscriptionsAction.BulkCancel) + { + var subscriptions = model.Filter.SelectAll ? + await _stripeAdapter.SubscriptionListAsync(model.Filter) : + model.Items.Where(x => x.Selected).Select(x => x.Subscription); + + if (model.Action == StripeSubscriptionsAction.Export) { - await _paymentService.ArchiveTaxRateAsync(new TaxRate() { Id = stripeTaxRateId }); + return StripeSubscriptionsExport(subscriptions); } - return RedirectToAction("TaxRate"); + if (model.Action == StripeSubscriptionsAction.BulkCancel) + { + await StripeSubscriptionsCancel(subscriptions); + } + } + else + { + if (model.Action == StripeSubscriptionsAction.PreviousPage || model.Action == StripeSubscriptionsAction.Search) + { + model.Filter.StartingAfter = null; + } + if (model.Action == StripeSubscriptionsAction.NextPage || model.Action == StripeSubscriptionsAction.Search) + { + model.Filter.EndingBefore = null; + } + } + + + return RedirectToAction("StripeSubscriptions", model.Filter); + } + + // This requires a redundant API call to Stripe because of the way they handle pagination. + // The StartingBefore value has to be infered from the list we get, and isn't supplied by Stripe. + private async Task StripeSubscriptionsGetHasPreviousPage(List subscriptions, StripeSubscriptionListOptions options) + { + var hasPreviousPage = false; + if (subscriptions.FirstOrDefault()?.Id != null) + { + var previousPageSearchOptions = new StripeSubscriptionListOptions() + { + EndingBefore = subscriptions.FirstOrDefault().Id, + Limit = 1, + Status = options.Status, + CurrentPeriodEndDate = options.CurrentPeriodEndDate, + CurrentPeriodEndRange = options.CurrentPeriodEndRange, + Price = options.Price + }; + hasPreviousPage = (await _stripeAdapter.SubscriptionListAsync(previousPageSearchOptions)).Count > 0; + } + return hasPreviousPage; + } + + private async Task StripeSubscriptionsCancel(IEnumerable subscriptions) + { + foreach (var s in subscriptions) + { + await _stripeAdapter.SubscriptionCancelAsync(s.Id); + if (s.LatestInvoice?.Status == "open") + { + await _stripeAdapter.InvoiceVoidInvoiceAsync(s.LatestInvoiceId); + } } } + + private FileResult StripeSubscriptionsExport(IEnumerable subscriptions) + { + var fieldsToExport = subscriptions.Select(s => new + { + StripeId = s.Id, + CustomerEmail = s.Customer?.Email, + SubscriptionStatus = s.Status, + InvoiceDueDate = s.CurrentPeriodEnd, + SubscriptionProducts = s.Items?.Data.Select(p => p.Plan.Id) + }); + + var options = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + WriteIndented = true + }; + + var result = System.Text.Json.JsonSerializer.Serialize(fieldsToExport, options); + var bytes = Encoding.UTF8.GetBytes(result); + return File(bytes, "application/json", "StripeSubscriptionsSearch.json"); + } } diff --git a/src/Admin/Controllers/UsersController.cs b/src/Admin/Controllers/UsersController.cs index 08f2ae765..0a4becb69 100644 --- a/src/Admin/Controllers/UsersController.cs +++ b/src/Admin/Controllers/UsersController.cs @@ -1,114 +1,110 @@ -using System; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Authorization; +using Bit.Admin.Models; +using Bit.Core.Entities; using Bit.Core.Repositories; -using System.Threading.Tasks; -using Bit.Admin.Models; -using System.Collections.Generic; -using Bit.Core.Models.Table; -using Bit.Core.Utilities; using Bit.Core.Services; using Bit.Core.Settings; +using Bit.Core.Utilities; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; -namespace Bit.Admin.Controllers +namespace Bit.Admin.Controllers; + +[Authorize] +public class UsersController : Controller { - [Authorize] - public class UsersController : Controller + private readonly IUserRepository _userRepository; + private readonly ICipherRepository _cipherRepository; + private readonly IPaymentService _paymentService; + private readonly GlobalSettings _globalSettings; + + public UsersController( + IUserRepository userRepository, + ICipherRepository cipherRepository, + IPaymentService paymentService, + GlobalSettings globalSettings) { - private readonly IUserRepository _userRepository; - private readonly ICipherRepository _cipherRepository; - private readonly IPaymentService _paymentService; - private readonly GlobalSettings _globalSettings; + _userRepository = userRepository; + _cipherRepository = cipherRepository; + _paymentService = paymentService; + _globalSettings = globalSettings; + } - public UsersController( - IUserRepository userRepository, - ICipherRepository cipherRepository, - IPaymentService paymentService, - GlobalSettings globalSettings) + public async Task Index(string email, int page = 1, int count = 25) + { + if (page < 1) { - _userRepository = userRepository; - _cipherRepository = cipherRepository; - _paymentService = paymentService; - _globalSettings = globalSettings; + page = 1; } - public async Task Index(string email, int page = 1, int count = 25) + if (count < 1) { - if (page < 1) - { - page = 1; - } - - if (count < 1) - { - count = 1; - } - - var skip = (page - 1) * count; - var users = await _userRepository.SearchAsync(email, skip, count); - return View(new UsersModel - { - Items = users as List, - Email = string.IsNullOrWhiteSpace(email) ? null : email, - Page = page, - Count = count, - Action = _globalSettings.SelfHosted ? "View" : "Edit" - }); + count = 1; } - public async Task View(Guid id) + var skip = (page - 1) * count; + var users = await _userRepository.SearchAsync(email, skip, count); + return View(new UsersModel { - var user = await _userRepository.GetByIdAsync(id); - if (user == null) - { - return RedirectToAction("Index"); - } + Items = users as List, + Email = string.IsNullOrWhiteSpace(email) ? null : email, + Page = page, + Count = count, + Action = _globalSettings.SelfHosted ? "View" : "Edit" + }); + } - var ciphers = await _cipherRepository.GetManyByUserIdAsync(id); - return View(new UserViewModel(user, ciphers)); - } - - [SelfHosted(NotSelfHostedOnly = true)] - public async Task Edit(Guid id) + public async Task View(Guid id) + { + var user = await _userRepository.GetByIdAsync(id); + if (user == null) { - var user = await _userRepository.GetByIdAsync(id); - if (user == null) - { - return RedirectToAction("Index"); - } - - var ciphers = await _cipherRepository.GetManyByUserIdAsync(id); - var billingInfo = await _paymentService.GetBillingAsync(user); - return View(new UserEditModel(user, ciphers, billingInfo, _globalSettings)); - } - - [HttpPost] - [ValidateAntiForgeryToken] - [SelfHosted(NotSelfHostedOnly = true)] - public async Task Edit(Guid id, UserEditModel model) - { - var user = await _userRepository.GetByIdAsync(id); - if (user == null) - { - return RedirectToAction("Index"); - } - - model.ToUser(user); - await _userRepository.ReplaceAsync(user); - return RedirectToAction("Edit", new { id }); - } - - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Delete(Guid id) - { - var user = await _userRepository.GetByIdAsync(id); - if (user != null) - { - await _userRepository.DeleteAsync(user); - } - return RedirectToAction("Index"); } + + var ciphers = await _cipherRepository.GetManyByUserIdAsync(id); + return View(new UserViewModel(user, ciphers)); + } + + [SelfHosted(NotSelfHostedOnly = true)] + public async Task Edit(Guid id) + { + var user = await _userRepository.GetByIdAsync(id); + if (user == null) + { + return RedirectToAction("Index"); + } + + var ciphers = await _cipherRepository.GetManyByUserIdAsync(id); + var billingInfo = await _paymentService.GetBillingAsync(user); + return View(new UserEditModel(user, ciphers, billingInfo, _globalSettings)); + } + + [HttpPost] + [ValidateAntiForgeryToken] + [SelfHosted(NotSelfHostedOnly = true)] + public async Task Edit(Guid id, UserEditModel model) + { + var user = await _userRepository.GetByIdAsync(id); + if (user == null) + { + return RedirectToAction("Index"); + } + + model.ToUser(user); + await _userRepository.ReplaceAsync(user); + return RedirectToAction("Edit", new { id }); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Delete(Guid id) + { + var user = await _userRepository.GetByIdAsync(id); + if (user != null) + { + await _userRepository.DeleteAsync(user); + } + + return RedirectToAction("Index"); } } diff --git a/src/Admin/Dockerfile b/src/Admin/Dockerfile index f5a46d67f..1c2264bf2 100644 --- a/src/Admin/Dockerfile +++ b/src/Admin/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 +FROM mcr.microsoft.com/dotnet/aspnet:6.0 LABEL com.bitwarden.product="bitwarden" diff --git a/src/Admin/HostedServices/AmazonSqsBlockIpHostedService.cs b/src/Admin/HostedServices/AmazonSqsBlockIpHostedService.cs index 3211008bc..646da09c5 100644 --- a/src/Admin/HostedServices/AmazonSqsBlockIpHostedService.cs +++ b/src/Admin/HostedServices/AmazonSqsBlockIpHostedService.cs @@ -1,89 +1,83 @@ -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Amazon; +using Amazon; using Amazon.SQS; using Amazon.SQS.Model; using Bit.Core.Settings; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace Bit.Admin.HostedServices +namespace Bit.Admin.HostedServices; + +public class AmazonSqsBlockIpHostedService : BlockIpHostedService { - public class AmazonSqsBlockIpHostedService : BlockIpHostedService + private AmazonSQSClient _client; + + public AmazonSqsBlockIpHostedService( + ILogger logger, + IOptions adminSettings, + GlobalSettings globalSettings) + : base(logger, adminSettings, globalSettings) + { } + + public override void Dispose() { - private AmazonSQSClient _client; + _client?.Dispose(); + } - public AmazonSqsBlockIpHostedService( - ILogger logger, - IOptions adminSettings, - GlobalSettings globalSettings) - : base(logger, adminSettings, globalSettings) - { } + protected override async Task ExecuteAsync(CancellationToken cancellationToken) + { + _client = new AmazonSQSClient(_globalSettings.Amazon.AccessKeyId, + _globalSettings.Amazon.AccessKeySecret, RegionEndpoint.GetBySystemName(_globalSettings.Amazon.Region)); + var blockIpQueue = await _client.GetQueueUrlAsync("block-ip", cancellationToken); + var blockIpQueueUrl = blockIpQueue.QueueUrl; + var unblockIpQueue = await _client.GetQueueUrlAsync("unblock-ip", cancellationToken); + var unblockIpQueueUrl = unblockIpQueue.QueueUrl; - public override void Dispose() + while (!cancellationToken.IsCancellationRequested) { - _client?.Dispose(); - } - - protected override async Task ExecuteAsync(CancellationToken cancellationToken) - { - _client = new AmazonSQSClient(_globalSettings.Amazon.AccessKeyId, - _globalSettings.Amazon.AccessKeySecret, RegionEndpoint.GetBySystemName(_globalSettings.Amazon.Region)); - var blockIpQueue = await _client.GetQueueUrlAsync("block-ip", cancellationToken); - var blockIpQueueUrl = blockIpQueue.QueueUrl; - var unblockIpQueue = await _client.GetQueueUrlAsync("unblock-ip", cancellationToken); - var unblockIpQueueUrl = unblockIpQueue.QueueUrl; - - while (!cancellationToken.IsCancellationRequested) + var blockMessageResponse = await _client.ReceiveMessageAsync(new ReceiveMessageRequest { - var blockMessageResponse = await _client.ReceiveMessageAsync(new ReceiveMessageRequest + QueueUrl = blockIpQueueUrl, + MaxNumberOfMessages = 10, + WaitTimeSeconds = 15 + }, cancellationToken); + if (blockMessageResponse.Messages.Any()) + { + foreach (var message in blockMessageResponse.Messages) { - QueueUrl = blockIpQueueUrl, - MaxNumberOfMessages = 10, - WaitTimeSeconds = 15 - }, cancellationToken); - if (blockMessageResponse.Messages.Any()) - { - foreach (var message in blockMessageResponse.Messages) + try { - try - { - await BlockIpAsync(message.Body, cancellationToken); - } - catch (Exception e) - { - _logger.LogError(e, "Failed to block IP."); - } - await _client.DeleteMessageAsync(blockIpQueueUrl, message.ReceiptHandle, cancellationToken); + await BlockIpAsync(message.Body, cancellationToken); } - } - - var unblockMessageResponse = await _client.ReceiveMessageAsync(new ReceiveMessageRequest - { - QueueUrl = unblockIpQueueUrl, - MaxNumberOfMessages = 10, - WaitTimeSeconds = 15 - }, cancellationToken); - if (unblockMessageResponse.Messages.Any()) - { - foreach (var message in unblockMessageResponse.Messages) + catch (Exception e) { - try - { - await UnblockIpAsync(message.Body, cancellationToken); - } - catch (Exception e) - { - _logger.LogError(e, "Failed to unblock IP."); - } - await _client.DeleteMessageAsync(unblockIpQueueUrl, message.ReceiptHandle, cancellationToken); + _logger.LogError(e, "Failed to block IP."); } + await _client.DeleteMessageAsync(blockIpQueueUrl, message.ReceiptHandle, cancellationToken); } - - await Task.Delay(TimeSpan.FromSeconds(15)); } + + var unblockMessageResponse = await _client.ReceiveMessageAsync(new ReceiveMessageRequest + { + QueueUrl = unblockIpQueueUrl, + MaxNumberOfMessages = 10, + WaitTimeSeconds = 15 + }, cancellationToken); + if (unblockMessageResponse.Messages.Any()) + { + foreach (var message in unblockMessageResponse.Messages) + { + try + { + await UnblockIpAsync(message.Body, cancellationToken); + } + catch (Exception e) + { + _logger.LogError(e, "Failed to unblock IP."); + } + await _client.DeleteMessageAsync(unblockIpQueueUrl, message.ReceiptHandle, cancellationToken); + } + } + + await Task.Delay(TimeSpan.FromSeconds(15)); } } } diff --git a/src/Admin/HostedServices/AzureQueueBlockIpHostedService.cs b/src/Admin/HostedServices/AzureQueueBlockIpHostedService.cs index f7e11ba4a..f1590377e 100644 --- a/src/Admin/HostedServices/AzureQueueBlockIpHostedService.cs +++ b/src/Admin/HostedServices/AzureQueueBlockIpHostedService.cs @@ -1,69 +1,63 @@ -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using Azure.Storage.Queues; using Bit.Core.Settings; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Azure.Storage.Queues; -namespace Bit.Admin.HostedServices +namespace Bit.Admin.HostedServices; + +public class AzureQueueBlockIpHostedService : BlockIpHostedService { - public class AzureQueueBlockIpHostedService : BlockIpHostedService + private QueueClient _blockIpQueueClient; + private QueueClient _unblockIpQueueClient; + + public AzureQueueBlockIpHostedService( + ILogger logger, + IOptions adminSettings, + GlobalSettings globalSettings) + : base(logger, adminSettings, globalSettings) + { } + + protected override async Task ExecuteAsync(CancellationToken cancellationToken) { - private QueueClient _blockIpQueueClient; - private QueueClient _unblockIpQueueClient; + _blockIpQueueClient = new QueueClient(_globalSettings.Storage.ConnectionString, "blockip"); + _unblockIpQueueClient = new QueueClient(_globalSettings.Storage.ConnectionString, "unblockip"); - public AzureQueueBlockIpHostedService( - ILogger logger, - IOptions adminSettings, - GlobalSettings globalSettings) - : base(logger, adminSettings, globalSettings) - { } - - protected override async Task ExecuteAsync(CancellationToken cancellationToken) + while (!cancellationToken.IsCancellationRequested) { - _blockIpQueueClient = new QueueClient(_globalSettings.Storage.ConnectionString, "blockip"); - _unblockIpQueueClient = new QueueClient(_globalSettings.Storage.ConnectionString, "unblockip"); - - while (!cancellationToken.IsCancellationRequested) + var blockMessages = await _blockIpQueueClient.ReceiveMessagesAsync(maxMessages: 32); + if (blockMessages.Value?.Any() ?? false) { - var blockMessages = await _blockIpQueueClient.ReceiveMessagesAsync(maxMessages: 32); - if (blockMessages.Value?.Any() ?? false) + foreach (var message in blockMessages.Value) { - foreach (var message in blockMessages.Value) + try { - try - { - await BlockIpAsync(message.MessageText, cancellationToken); - } - catch (Exception e) - { - _logger.LogError(e, "Failed to block IP."); - } - await _blockIpQueueClient.DeleteMessageAsync(message.MessageId, message.PopReceipt); + await BlockIpAsync(message.MessageText, cancellationToken); } - } - - var unblockMessages = await _unblockIpQueueClient.ReceiveMessagesAsync(maxMessages: 32); - if (unblockMessages.Value?.Any() ?? false) - { - foreach (var message in unblockMessages.Value) + catch (Exception e) { - try - { - await UnblockIpAsync(message.MessageText, cancellationToken); - } - catch (Exception e) - { - _logger.LogError(e, "Failed to unblock IP."); - } - await _unblockIpQueueClient.DeleteMessageAsync(message.MessageId, message.PopReceipt); + _logger.LogError(e, "Failed to block IP."); } + await _blockIpQueueClient.DeleteMessageAsync(message.MessageId, message.PopReceipt); } - - await Task.Delay(TimeSpan.FromSeconds(15)); } + + var unblockMessages = await _unblockIpQueueClient.ReceiveMessagesAsync(maxMessages: 32); + if (unblockMessages.Value?.Any() ?? false) + { + foreach (var message in unblockMessages.Value) + { + try + { + await UnblockIpAsync(message.MessageText, cancellationToken); + } + catch (Exception e) + { + _logger.LogError(e, "Failed to unblock IP."); + } + await _unblockIpQueueClient.DeleteMessageAsync(message.MessageId, message.PopReceipt); + } + } + + await Task.Delay(TimeSpan.FromSeconds(15)); } } } diff --git a/src/Admin/HostedServices/AzureQueueMailHostedService.cs b/src/Admin/HostedServices/AzureQueueMailHostedService.cs index 17d4b2fc5..b2031a405 100644 --- a/src/Admin/HostedServices/AzureQueueMailHostedService.cs +++ b/src/Admin/HostedServices/AzureQueueMailHostedService.cs @@ -1,108 +1,101 @@ -using System; -using Microsoft.Extensions.Hosting; +using System.Text.Json; using Azure.Storage.Queues; -using Microsoft.Extensions.Logging; -using Bit.Core.Settings; -using System.Threading.Tasks; -using System.Threading; -using Bit.Core.Services; -using Newtonsoft.Json; -using Bit.Core.Models.Mail; using Azure.Storage.Queues.Models; -using System.Linq; -using System.Collections.Generic; -using Newtonsoft.Json.Linq; +using Bit.Core.Models.Mail; +using Bit.Core.Services; +using Bit.Core.Settings; using Bit.Core.Utilities; -namespace Bit.Admin.HostedServices +namespace Bit.Admin.HostedServices; + +public class AzureQueueMailHostedService : IHostedService { - public class AzureQueueMailHostedService : IHostedService + private readonly ILogger _logger; + private readonly GlobalSettings _globalSettings; + private readonly IMailService _mailService; + private CancellationTokenSource _cts; + private Task _executingTask; + + private QueueClient _mailQueueClient; + + public AzureQueueMailHostedService( + ILogger logger, + IMailService mailService, + GlobalSettings globalSettings) { - private readonly ILogger _logger; - private readonly GlobalSettings _globalSettings; - private readonly IMailService _mailService; - private CancellationTokenSource _cts; - private Task _executingTask; + _logger = logger; + _mailService = mailService; + _globalSettings = globalSettings; + } - private QueueClient _mailQueueClient; + public Task StartAsync(CancellationToken cancellationToken) + { + _cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + _executingTask = ExecuteAsync(_cts.Token); + return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask; + } - public AzureQueueMailHostedService( - ILogger logger, - IMailService mailService, - GlobalSettings globalSettings) - { - _logger = logger; - _mailService = mailService; - _globalSettings = globalSettings; - } - - public Task StartAsync(CancellationToken cancellationToken) + public async Task StopAsync(CancellationToken cancellationToken) + { + if (_executingTask == null) { - _cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - _executingTask = ExecuteAsync(_cts.Token); - return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask; + return; } + _cts.Cancel(); + await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken)); + cancellationToken.ThrowIfCancellationRequested(); + } - public async Task StopAsync(CancellationToken cancellationToken) + private async Task ExecuteAsync(CancellationToken cancellationToken) + { + _mailQueueClient = new QueueClient(_globalSettings.Mail.ConnectionString, "mail"); + + QueueMessage[] mailMessages; + while (!cancellationToken.IsCancellationRequested) { - if (_executingTask == null) + if (!(mailMessages = await RetrieveMessagesAsync()).Any()) { - return; + await Task.Delay(TimeSpan.FromSeconds(15)); } - _cts.Cancel(); - await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken)); - cancellationToken.ThrowIfCancellationRequested(); - } - private async Task ExecuteAsync(CancellationToken cancellationToken) - { - _mailQueueClient = new QueueClient(_globalSettings.Mail.ConnectionString, "mail"); - - QueueMessage[] mailMessages; - while (!cancellationToken.IsCancellationRequested) + foreach (var message in mailMessages) { - if (!(mailMessages = await RetrieveMessagesAsync()).Any()) + try { - await Task.Delay(TimeSpan.FromSeconds(15)); - } + using var document = JsonDocument.Parse(message.DecodeMessageText()); + var root = document.RootElement; - foreach (var message in mailMessages) - { - try + if (root.ValueKind == JsonValueKind.Array) { - var token = JToken.Parse(message.DecodeMessageText()); - if (token is JArray) + foreach (var mailQueueMessage in root.ToObject>()) { - foreach (var mailQueueMessage in token.ToObject>()) - { - await _mailService.SendEnqueuedMailMessageAsync(mailQueueMessage); - } - } - else if (token is JObject) - { - var mailQueueMessage = token.ToObject(); await _mailService.SendEnqueuedMailMessageAsync(mailQueueMessage); } } - catch (Exception e) + else if (root.ValueKind == JsonValueKind.Object) { - _logger.LogError(e, "Failed to send email"); - // TODO: retries? + var mailQueueMessage = root.ToObject(); + await _mailService.SendEnqueuedMailMessageAsync(mailQueueMessage); } - - await _mailQueueClient.DeleteMessageAsync(message.MessageId, message.PopReceipt); + } + catch (Exception e) + { + _logger.LogError(e, "Failed to send email"); + // TODO: retries? + } - if (cancellationToken.IsCancellationRequested) - { - break; - } + await _mailQueueClient.DeleteMessageAsync(message.MessageId, message.PopReceipt); + + if (cancellationToken.IsCancellationRequested) + { + break; } } } + } - private async Task RetrieveMessagesAsync() - { - return (await _mailQueueClient.ReceiveMessagesAsync(maxMessages: 32))?.Value ?? new QueueMessage[] { }; - } + private async Task RetrieveMessagesAsync() + { + return (await _mailQueueClient.ReceiveMessagesAsync(maxMessages: 32))?.Value ?? new QueueMessage[] { }; } } diff --git a/src/Admin/HostedServices/BlockIpHostedService.cs b/src/Admin/HostedServices/BlockIpHostedService.cs index 09dcac352..6a1f58c6b 100644 --- a/src/Admin/HostedServices/BlockIpHostedService.cs +++ b/src/Admin/HostedServices/BlockIpHostedService.cs @@ -1,81 +1,105 @@ -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Bit.Core.Settings; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; +using Bit.Core.Settings; using Microsoft.Extensions.Options; -using Newtonsoft.Json; -namespace Bit.Admin.HostedServices +namespace Bit.Admin.HostedServices; + +public abstract class BlockIpHostedService : IHostedService, IDisposable { - public abstract class BlockIpHostedService : IHostedService, IDisposable + protected readonly ILogger _logger; + protected readonly GlobalSettings _globalSettings; + private readonly AdminSettings _adminSettings; + + private Task _executingTask; + private CancellationTokenSource _cts; + private HttpClient _httpClient = new HttpClient(); + + public BlockIpHostedService( + ILogger logger, + IOptions adminSettings, + GlobalSettings globalSettings) { - protected readonly ILogger _logger; - protected readonly GlobalSettings _globalSettings; - private readonly AdminSettings _adminSettings; + _logger = logger; + _globalSettings = globalSettings; + _adminSettings = adminSettings?.Value; + } - private Task _executingTask; - private CancellationTokenSource _cts; - private HttpClient _httpClient = new HttpClient(); + public Task StartAsync(CancellationToken cancellationToken) + { + _cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + _executingTask = ExecuteAsync(_cts.Token); + return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask; + } - public BlockIpHostedService( - ILogger logger, - IOptions adminSettings, - GlobalSettings globalSettings) + public async Task StopAsync(CancellationToken cancellationToken) + { + if (_executingTask == null) { - _logger = logger; - _globalSettings = globalSettings; - _adminSettings = adminSettings?.Value; + return; } + _cts.Cancel(); + await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken)); + cancellationToken.ThrowIfCancellationRequested(); + } - public Task StartAsync(CancellationToken cancellationToken) - { - _cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - _executingTask = ExecuteAsync(_cts.Token); - return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask; - } + public virtual void Dispose() + { } - public async Task StopAsync(CancellationToken cancellationToken) + protected abstract Task ExecuteAsync(CancellationToken cancellationToken); + + protected async Task BlockIpAsync(string message, CancellationToken cancellationToken) + { + var request = new HttpRequestMessage(); + request.Headers.Accept.Clear(); + request.Headers.Add("X-Auth-Email", _adminSettings.Cloudflare.AuthEmail); + request.Headers.Add("X-Auth-Key", _adminSettings.Cloudflare.AuthKey); + request.Method = HttpMethod.Post; + request.RequestUri = new Uri("https://api.cloudflare.com/" + + $"client/v4/zones/{_adminSettings.Cloudflare.ZoneId}/firewall/access_rules/rules"); + + request.Content = JsonContent.Create(new { - if (_executingTask == null) + mode = "block", + configuration = new { - return; - } - _cts.Cancel(); - await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken)); - cancellationToken.ThrowIfCancellationRequested(); + target = "ip", + value = message + }, + notes = $"Rate limit abuse on {DateTime.UtcNow.ToString()}." + }); + + var response = await _httpClient.SendAsync(request, cancellationToken); + if (!response.IsSuccessStatusCode) + { + return; } - public virtual void Dispose() - { } - - protected abstract Task ExecuteAsync(CancellationToken cancellationToken); - - protected async Task BlockIpAsync(string message, CancellationToken cancellationToken) + var accessRuleResponse = await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); + if (!accessRuleResponse.Success) { + return; + } + + // TODO: Send `accessRuleResponse.Result?.Id` message to unblock queue + } + + protected async Task UnblockIpAsync(string message, CancellationToken cancellationToken) + { + if (string.IsNullOrWhiteSpace(message)) + { + return; + } + + if (message.Contains(".") || message.Contains(":")) + { + // IP address messages var request = new HttpRequestMessage(); request.Headers.Accept.Clear(); request.Headers.Add("X-Auth-Email", _adminSettings.Cloudflare.AuthEmail); request.Headers.Add("X-Auth-Key", _adminSettings.Cloudflare.AuthKey); - request.Method = HttpMethod.Post; + request.Method = HttpMethod.Get; request.RequestUri = new Uri("https://api.cloudflare.com/" + - $"client/v4/zones/{_adminSettings.Cloudflare.ZoneId}/firewall/access_rules/rules"); - - var bodyContent = JsonConvert.SerializeObject(new - { - mode = "block", - configuration = new - { - target = "ip", - value = message - }, - notes = $"Rate limit abuse on {DateTime.UtcNow.ToString()}." - }); - request.Content = new StringContent(bodyContent, Encoding.UTF8, "application/json"); + $"client/v4/zones/{_adminSettings.Cloudflare.ZoneId}/firewall/access_rules/rules?" + + $"configuration_target=ip&configuration_value={message}"); var response = await _httpClient.SendAsync(request, cancellationToken); if (!response.IsSuccessStatusCode) @@ -83,95 +107,58 @@ namespace Bit.Admin.HostedServices return; } - var responseString = await response.Content.ReadAsStringAsync(); - var accessRuleResponse = JsonConvert.DeserializeObject(responseString); - if (!accessRuleResponse.Success) + var listResponse = await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); + if (!listResponse.Success) { return; } - // TODO: Send `accessRuleResponse.Result?.Id` message to unblock queue - } - - protected async Task UnblockIpAsync(string message, CancellationToken cancellationToken) - { - if (string.IsNullOrWhiteSpace(message)) + foreach (var rule in listResponse.Result) { - return; - } - - if (message.Contains(".") || message.Contains(":")) - { - // IP address messages - var request = new HttpRequestMessage(); - request.Headers.Accept.Clear(); - request.Headers.Add("X-Auth-Email", _adminSettings.Cloudflare.AuthEmail); - request.Headers.Add("X-Auth-Key", _adminSettings.Cloudflare.AuthKey); - request.Method = HttpMethod.Get; - request.RequestUri = new Uri("https://api.cloudflare.com/" + - $"client/v4/zones/{_adminSettings.Cloudflare.ZoneId}/firewall/access_rules/rules?" + - $"configuration_target=ip&configuration_value={message}"); - - var response = await _httpClient.SendAsync(request, cancellationToken); - if (!response.IsSuccessStatusCode) - { - return; - } - - var responseString = await response.Content.ReadAsStringAsync(); - var listResponse = JsonConvert.DeserializeObject(responseString); - if (!listResponse.Success) - { - return; - } - - foreach (var rule in listResponse.Result) - { - await DeleteAccessRuleAsync(rule.Id, cancellationToken); - } - } - else - { - // Rule Id messages - await DeleteAccessRuleAsync(message, cancellationToken); + await DeleteAccessRuleAsync(rule.Id, cancellationToken); } } - - protected async Task DeleteAccessRuleAsync(string ruleId, CancellationToken cancellationToken) + else { - var request = new HttpRequestMessage(); - request.Headers.Accept.Clear(); - request.Headers.Add("X-Auth-Email", _adminSettings.Cloudflare.AuthEmail); - request.Headers.Add("X-Auth-Key", _adminSettings.Cloudflare.AuthKey); - request.Method = HttpMethod.Delete; - request.RequestUri = new Uri("https://api.cloudflare.com/" + - $"client/v4/zones/{_adminSettings.Cloudflare.ZoneId}/firewall/access_rules/rules/{ruleId}"); - await _httpClient.SendAsync(request, cancellationToken); + // Rule Id messages + await DeleteAccessRuleAsync(message, cancellationToken); } + } - public class ListResponse + protected async Task DeleteAccessRuleAsync(string ruleId, CancellationToken cancellationToken) + { + var request = new HttpRequestMessage(); + request.Headers.Accept.Clear(); + request.Headers.Add("X-Auth-Email", _adminSettings.Cloudflare.AuthEmail); + request.Headers.Add("X-Auth-Key", _adminSettings.Cloudflare.AuthKey); + request.Method = HttpMethod.Delete; + request.RequestUri = new Uri("https://api.cloudflare.com/" + + $"client/v4/zones/{_adminSettings.Cloudflare.ZoneId}/firewall/access_rules/rules/{ruleId}"); + await _httpClient.SendAsync(request, cancellationToken); + } + + public class ListResponse + { + public bool Success { get; set; } + public List Result { get; set; } + } + + public class AccessRuleResponse + { + public bool Success { get; set; } + public AccessRuleResultResponse Result { get; set; } + } + + public class AccessRuleResultResponse + { + public string Id { get; set; } + public string Notes { get; set; } + public ConfigurationResponse Configuration { get; set; } + + public class ConfigurationResponse { - public bool Success { get; set; } - public List Result { get; set; } - } - - public class AccessRuleResponse - { - public bool Success { get; set; } - public AccessRuleResultResponse Result { get; set; } - } - - public class AccessRuleResultResponse - { - public string Id { get; set; } - public string Notes { get; set; } - public ConfigurationResponse Configuration { get; set; } - - public class ConfigurationResponse - { - public string Target { get; set; } - public string Value { get; set; } - } + public string Target { get; set; } + public string Value { get; set; } } } } diff --git a/src/Admin/HostedServices/DatabaseMigrationHostedService.cs b/src/Admin/HostedServices/DatabaseMigrationHostedService.cs index 4c3cb2610..434c265f2 100644 --- a/src/Admin/HostedServices/DatabaseMigrationHostedService.cs +++ b/src/Admin/HostedServices/DatabaseMigrationHostedService.cs @@ -1,69 +1,57 @@ -using System; -using System.Data.SqlClient; -using System.Threading; -using System.Threading.Tasks; -using Bit.Core.Jobs; -using Bit.Core.Settings; -using Bit.Migrator; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; +using Bit.Core.Utilities; +using Microsoft.Data.SqlClient; -namespace Bit.Admin.HostedServices +namespace Bit.Admin.HostedServices; + +public class DatabaseMigrationHostedService : IHostedService, IDisposable { - public class DatabaseMigrationHostedService : IHostedService, IDisposable + private readonly ILogger _logger; + private readonly IDbMigrator _dbMigrator; + + public DatabaseMigrationHostedService( + IDbMigrator dbMigrator, + ILogger logger) { - private readonly GlobalSettings _globalSettings; - private readonly ILogger _logger; - private readonly DbMigrator _dbMigrator; + _logger = logger; + _dbMigrator = dbMigrator; + } - public DatabaseMigrationHostedService( - GlobalSettings globalSettings, - ILogger logger, - ILogger migratorLogger, - ILogger listenerLogger) + public virtual async Task StartAsync(CancellationToken cancellationToken) + { + // Wait 20 seconds to allow database to come online + await Task.Delay(20000); + + var maxMigrationAttempts = 10; + for (var i = 1; i <= maxMigrationAttempts; i++) { - _globalSettings = globalSettings; - _logger = logger; - _dbMigrator = new DbMigrator(globalSettings.SqlServer.ConnectionString, migratorLogger); - } - - public virtual async Task StartAsync(CancellationToken cancellationToken) - { - // Wait 20 seconds to allow database to come online - await Task.Delay(20000); - - var maxMigrationAttempts = 10; - for (var i = 1; i <= maxMigrationAttempts; i++) + try { - try + _dbMigrator.MigrateDatabase(true, cancellationToken); + // TODO: Maybe flip a flag somewhere to indicate migration is complete?? + break; + } + catch (SqlException e) + { + if (i >= maxMigrationAttempts) { - _dbMigrator.MigrateMsSqlDatabase(true, cancellationToken); - // TODO: Maybe flip a flag somewhere to indicate migration is complete?? - break; + _logger.LogError(e, "Database failed to migrate."); + throw; } - catch (SqlException e) + else { - if (i >= maxMigrationAttempts) - { - _logger.LogError(e, "Database failed to migrate."); - throw e; - } - else - { - _logger.LogError(e, - "Database unavailable for migration. Trying again (attempt #{0})...", i + 1); - await Task.Delay(20000); - } + _logger.LogError(e, + "Database unavailable for migration. Trying again (attempt #{0})...", i + 1); + await Task.Delay(20000); } } } - - public virtual Task StopAsync(CancellationToken cancellationToken) - { - return Task.FromResult(0); - } - - public virtual void Dispose() - { } } + + public virtual Task StopAsync(CancellationToken cancellationToken) + { + return Task.FromResult(0); + } + + public virtual void Dispose() + { } } diff --git a/src/Admin/IdentityServer/PasswordlessSignInManager.cs b/src/Admin/IdentityServer/PasswordlessSignInManager.cs new file mode 100644 index 000000000..6c346158e --- /dev/null +++ b/src/Admin/IdentityServer/PasswordlessSignInManager.cs @@ -0,0 +1,87 @@ +using Bit.Core.Services; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; + +namespace Bit.Admin.IdentityServer; + +public class PasswordlessSignInManager : SignInManager where TUser : class +{ + public const string PasswordlessSignInPurpose = "PasswordlessSignIn"; + + private readonly IMailService _mailService; + + public PasswordlessSignInManager(UserManager userManager, + IHttpContextAccessor contextAccessor, + IUserClaimsPrincipalFactory claimsFactory, + IOptions optionsAccessor, + ILogger> logger, + IAuthenticationSchemeProvider schemes, + IUserConfirmation confirmation, + IMailService mailService) + : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation) + { + _mailService = mailService; + } + + public async Task PasswordlessSignInAsync(string email, string returnUrl) + { + var user = await UserManager.FindByEmailAsync(email); + if (user == null) + { + return SignInResult.Failed; + } + + var token = await UserManager.GenerateUserTokenAsync(user, Options.Tokens.PasswordResetTokenProvider, + PasswordlessSignInPurpose); + await _mailService.SendPasswordlessSignInAsync(returnUrl, token, email); + return SignInResult.Success; + } + + public async Task PasswordlessSignInAsync(TUser user, string token, bool isPersistent) + { + if (user == null) + { + throw new ArgumentNullException(nameof(user)); + } + + var attempt = await CheckPasswordlessSignInAsync(user, token); + return attempt.Succeeded ? + await SignInOrTwoFactorAsync(user, isPersistent, bypassTwoFactor: true) : attempt; + } + + public async Task PasswordlessSignInAsync(string email, string token, bool isPersistent) + { + var user = await UserManager.FindByEmailAsync(email); + if (user == null) + { + return SignInResult.Failed; + } + + return await PasswordlessSignInAsync(user, token, isPersistent); + } + + public virtual async Task CheckPasswordlessSignInAsync(TUser user, string token) + { + if (user == null) + { + throw new ArgumentNullException(nameof(user)); + } + + var error = await PreSignInCheck(user); + if (error != null) + { + return error; + } + + if (await UserManager.VerifyUserTokenAsync(user, Options.Tokens.PasswordResetTokenProvider, + PasswordlessSignInPurpose, token)) + { + return SignInResult.Success; + } + + Logger.LogWarning(2, "User {userId} failed to provide the correct token.", + await UserManager.GetUserIdAsync(user)); + return SignInResult.Failed; + } +} diff --git a/src/Admin/IdentityServer/ReadOnlyEnvIdentityUserStore.cs b/src/Admin/IdentityServer/ReadOnlyEnvIdentityUserStore.cs new file mode 100644 index 000000000..15b8d894b --- /dev/null +++ b/src/Admin/IdentityServer/ReadOnlyEnvIdentityUserStore.cs @@ -0,0 +1,65 @@ +using Bit.Core.Utilities; +using Microsoft.AspNetCore.Identity; + +namespace Bit.Admin.IdentityServer; + +public class ReadOnlyEnvIdentityUserStore : ReadOnlyIdentityUserStore +{ + private readonly IConfiguration _configuration; + + public ReadOnlyEnvIdentityUserStore(IConfiguration configuration) + { + _configuration = configuration; + } + + public override Task FindByEmailAsync(string normalizedEmail, + CancellationToken cancellationToken = default) + { + var usersCsv = _configuration["adminSettings:admins"]; + if (!CoreHelpers.SettingHasValue(usersCsv)) + { + return Task.FromResult(null); + } + + var users = usersCsv.ToLowerInvariant().Split(','); + var usersDict = new Dictionary(); + foreach (var u in users) + { + var parts = u.Split(':'); + if (parts.Length == 2) + { + var email = parts[0].Trim(); + var stamp = parts[1].Trim(); + usersDict.Add(email, stamp); + } + else + { + var email = parts[0].Trim(); + usersDict.Add(email, email); + } + } + + var userStamp = usersDict.ContainsKey(normalizedEmail) ? usersDict[normalizedEmail] : null; + if (userStamp == null) + { + return Task.FromResult(null); + } + + return Task.FromResult(new IdentityUser + { + Id = normalizedEmail, + Email = normalizedEmail, + NormalizedEmail = normalizedEmail, + EmailConfirmed = true, + UserName = normalizedEmail, + NormalizedUserName = normalizedEmail, + SecurityStamp = userStamp + }); + } + + public override Task FindByIdAsync(string userId, + CancellationToken cancellationToken = default) + { + return FindByEmailAsync(userId, cancellationToken); + } +} diff --git a/src/Admin/IdentityServer/ReadOnlyIdentityUserStore.cs b/src/Admin/IdentityServer/ReadOnlyIdentityUserStore.cs new file mode 100644 index 000000000..88f3a40b1 --- /dev/null +++ b/src/Admin/IdentityServer/ReadOnlyIdentityUserStore.cs @@ -0,0 +1,118 @@ +using Microsoft.AspNetCore.Identity; + +namespace Bit.Admin.IdentityServer; + +public abstract class ReadOnlyIdentityUserStore : + IUserEmailStore, + IUserSecurityStampStore +{ + public void Dispose() { } + + public Task CreateAsync(IdentityUser user, + CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public Task DeleteAsync(IdentityUser user, + CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public abstract Task FindByEmailAsync(string normalizedEmail, + CancellationToken cancellationToken = default); + + public abstract Task FindByIdAsync(string userId, + CancellationToken cancellationToken = default); + + public async Task FindByNameAsync(string normalizedUserName, + CancellationToken cancellationToken = default) + { + return await FindByEmailAsync(normalizedUserName, cancellationToken); + } + + public Task GetEmailAsync(IdentityUser user, + CancellationToken cancellationToken = default) + { + return Task.FromResult(user.Email); + } + + public Task GetEmailConfirmedAsync(IdentityUser user, + CancellationToken cancellationToken = default) + { + return Task.FromResult(user.EmailConfirmed); + } + + public Task GetNormalizedEmailAsync(IdentityUser user, + CancellationToken cancellationToken = default) + { + return Task.FromResult(user.Email); + } + + public Task GetNormalizedUserNameAsync(IdentityUser user, + CancellationToken cancellationToken = default) + { + return Task.FromResult(user.Email); + } + + public Task GetUserIdAsync(IdentityUser user, + CancellationToken cancellationToken = default) + { + return Task.FromResult(user.Id); + } + + public Task GetUserNameAsync(IdentityUser user, + CancellationToken cancellationToken = default) + { + return Task.FromResult(user.Email); + } + + public Task SetEmailAsync(IdentityUser user, string email, + CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public Task SetEmailConfirmedAsync(IdentityUser user, bool confirmed, + CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public Task SetNormalizedEmailAsync(IdentityUser user, string normalizedEmail, + CancellationToken cancellationToken = default) + { + user.NormalizedEmail = normalizedEmail; + return Task.FromResult(0); + } + + public Task SetNormalizedUserNameAsync(IdentityUser user, string normalizedName, + CancellationToken cancellationToken = default) + { + user.NormalizedUserName = normalizedName; + return Task.FromResult(0); + } + + public Task SetUserNameAsync(IdentityUser user, string userName, + CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public Task UpdateAsync(IdentityUser user, + CancellationToken cancellationToken = default) + { + return Task.FromResult(IdentityResult.Success); + } + + public Task SetSecurityStampAsync(IdentityUser user, string stamp, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task GetSecurityStampAsync(IdentityUser user, CancellationToken cancellationToken) + { + return Task.FromResult(user.SecurityStamp); + } +} diff --git a/src/Admin/IdentityServer/ServiceCollectionExtensions.cs b/src/Admin/IdentityServer/ServiceCollectionExtensions.cs new file mode 100644 index 000000000..bf4ac66cc --- /dev/null +++ b/src/Admin/IdentityServer/ServiceCollectionExtensions.cs @@ -0,0 +1,44 @@ +using Bit.Core.Entities; +using Bit.Core.Identity; +using Bit.Core.Settings; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Bit.Admin.IdentityServer; + +public static class ServiceCollectionExtensions +{ + public static Tuple AddPasswordlessIdentityServices( + this IServiceCollection services, GlobalSettings globalSettings) where TUserStore : class + { + services.TryAddTransient(); + services.Configure(options => + { + options.TokenLifespan = TimeSpan.FromMinutes(15); + }); + + var passwordlessIdentityBuilder = services.AddIdentity() + .AddUserStore() + .AddRoleStore() + .AddDefaultTokenProviders(); + + var regularIdentityBuilder = services.AddIdentityCore() + .AddUserStore(); + + services.TryAddScoped, PasswordlessSignInManager>(); + + services.ConfigureApplicationCookie(options => + { + options.LoginPath = "/login"; + options.LogoutPath = "/"; + options.AccessDeniedPath = "/login?accessDenied=true"; + options.Cookie.Name = $"Bitwarden_{globalSettings.ProjectName}"; + options.Cookie.HttpOnly = true; + options.ExpireTimeSpan = TimeSpan.FromDays(2); + options.ReturnUrlParameter = "returnUrl"; + options.SlidingExpiration = true; + }); + + return new Tuple(passwordlessIdentityBuilder, regularIdentityBuilder); + } +} diff --git a/src/Admin/Jobs/AliveJob.cs b/src/Admin/Jobs/AliveJob.cs index 65b19c3f1..b97d597e5 100644 --- a/src/Admin/Jobs/AliveJob.cs +++ b/src/Admin/Jobs/AliveJob.cs @@ -1,32 +1,28 @@ -using System.Net.Http; -using System.Threading.Tasks; -using Bit.Core; +using Bit.Core; using Bit.Core.Jobs; using Bit.Core.Settings; -using Microsoft.Extensions.Logging; using Quartz; -namespace Bit.Admin.Jobs +namespace Bit.Admin.Jobs; + +public class AliveJob : BaseJob { - public class AliveJob : BaseJob + private readonly GlobalSettings _globalSettings; + private HttpClient _httpClient = new HttpClient(); + + public AliveJob( + GlobalSettings globalSettings, + ILogger logger) + : base(logger) { - private readonly GlobalSettings _globalSettings; - private HttpClient _httpClient = new HttpClient(); + _globalSettings = globalSettings; + } - public AliveJob( - GlobalSettings globalSettings, - ILogger logger) - : base(logger) - { - _globalSettings = globalSettings; - } - - protected async override Task ExecuteJobAsync(IJobExecutionContext context) - { - _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: Keep alive"); - var response = await _httpClient.GetAsync(_globalSettings.BaseServiceUri.Admin); - _logger.LogInformation(Constants.BypassFiltersEventId, "Finished job task: Keep alive, " + - response.StatusCode); - } + protected async override Task ExecuteJobAsync(IJobExecutionContext context) + { + _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: Keep alive"); + var response = await _httpClient.GetAsync(_globalSettings.BaseServiceUri.Admin); + _logger.LogInformation(Constants.BypassFiltersEventId, "Finished job task: Keep alive, " + + response.StatusCode); } } diff --git a/src/Admin/Jobs/DatabaseExpiredGrantsJob.cs b/src/Admin/Jobs/DatabaseExpiredGrantsJob.cs index 9d425feaf..626eb00d5 100644 --- a/src/Admin/Jobs/DatabaseExpiredGrantsJob.cs +++ b/src/Admin/Jobs/DatabaseExpiredGrantsJob.cs @@ -1,30 +1,26 @@ -using System; -using System.Threading.Tasks; -using Bit.Core; +using Bit.Core; using Bit.Core.Jobs; using Bit.Core.Repositories; -using Microsoft.Extensions.Logging; using Quartz; -namespace Bit.Admin.Jobs +namespace Bit.Admin.Jobs; + +public class DatabaseExpiredGrantsJob : BaseJob { - public class DatabaseExpiredGrantsJob : BaseJob + private readonly IMaintenanceRepository _maintenanceRepository; + + public DatabaseExpiredGrantsJob( + IMaintenanceRepository maintenanceRepository, + ILogger logger) + : base(logger) { - private readonly IMaintenanceRepository _maintenanceRepository; + _maintenanceRepository = maintenanceRepository; + } - public DatabaseExpiredGrantsJob( - IMaintenanceRepository maintenanceRepository, - ILogger logger) - : base(logger) - { - _maintenanceRepository = maintenanceRepository; - } - - protected async override Task ExecuteJobAsync(IJobExecutionContext context) - { - _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: DeleteExpiredGrantsAsync"); - await _maintenanceRepository.DeleteExpiredGrantsAsync(); - _logger.LogInformation(Constants.BypassFiltersEventId, "Finished job task: DeleteExpiredGrantsAsync"); - } + protected async override Task ExecuteJobAsync(IJobExecutionContext context) + { + _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: DeleteExpiredGrantsAsync"); + await _maintenanceRepository.DeleteExpiredGrantsAsync(); + _logger.LogInformation(Constants.BypassFiltersEventId, "Finished job task: DeleteExpiredGrantsAsync"); } } diff --git a/src/Admin/Jobs/DatabaseExpiredSponsorshipsJob.cs b/src/Admin/Jobs/DatabaseExpiredSponsorshipsJob.cs new file mode 100644 index 000000000..7a00445fd --- /dev/null +++ b/src/Admin/Jobs/DatabaseExpiredSponsorshipsJob.cs @@ -0,0 +1,38 @@ +using Bit.Core; +using Bit.Core.Jobs; +using Bit.Core.Repositories; +using Bit.Core.Settings; +using Quartz; + +namespace Bit.Admin.Jobs; + +public class DatabaseExpiredSponsorshipsJob : BaseJob +{ + private GlobalSettings _globalSettings; + private readonly IMaintenanceRepository _maintenanceRepository; + + public DatabaseExpiredSponsorshipsJob( + IMaintenanceRepository maintenanceRepository, + ILogger logger, + GlobalSettings globalSettings) + : base(logger) + { + _maintenanceRepository = maintenanceRepository; + _globalSettings = globalSettings; + } + + protected override async Task ExecuteJobAsync(IJobExecutionContext context) + { + if (_globalSettings.SelfHosted && !_globalSettings.EnableCloudCommunication) + { + return; + } + _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: DeleteExpiredSponsorshipsAsync"); + + // allow a 90 day grace period before deleting + var deleteDate = DateTime.UtcNow.AddDays(-90); + + await _maintenanceRepository.DeleteExpiredSponsorshipsAsync(deleteDate); + _logger.LogInformation(Constants.BypassFiltersEventId, "Finished job task: DeleteExpiredSponsorshipsAsync"); + } +} diff --git a/src/Admin/Jobs/DatabaseRebuildlIndexesJob.cs b/src/Admin/Jobs/DatabaseRebuildlIndexesJob.cs index 7267ee3c2..78e48bb6f 100644 --- a/src/Admin/Jobs/DatabaseRebuildlIndexesJob.cs +++ b/src/Admin/Jobs/DatabaseRebuildlIndexesJob.cs @@ -1,30 +1,26 @@ -using System; -using System.Threading.Tasks; -using Bit.Core; +using Bit.Core; using Bit.Core.Jobs; using Bit.Core.Repositories; -using Microsoft.Extensions.Logging; using Quartz; -namespace Bit.Admin.Jobs +namespace Bit.Admin.Jobs; + +public class DatabaseRebuildlIndexesJob : BaseJob { - public class DatabaseRebuildlIndexesJob : BaseJob + private readonly IMaintenanceRepository _maintenanceRepository; + + public DatabaseRebuildlIndexesJob( + IMaintenanceRepository maintenanceRepository, + ILogger logger) + : base(logger) { - private readonly IMaintenanceRepository _maintenanceRepository; + _maintenanceRepository = maintenanceRepository; + } - public DatabaseRebuildlIndexesJob( - IMaintenanceRepository maintenanceRepository, - ILogger logger) - : base(logger) - { - _maintenanceRepository = maintenanceRepository; - } - - protected async override Task ExecuteJobAsync(IJobExecutionContext context) - { - _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: RebuildIndexesAsync"); - await _maintenanceRepository.RebuildIndexesAsync(); - _logger.LogInformation(Constants.BypassFiltersEventId, "Finished job task: RebuildIndexesAsync"); - } + protected async override Task ExecuteJobAsync(IJobExecutionContext context) + { + _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: RebuildIndexesAsync"); + await _maintenanceRepository.RebuildIndexesAsync(); + _logger.LogInformation(Constants.BypassFiltersEventId, "Finished job task: RebuildIndexesAsync"); } } diff --git a/src/Admin/Jobs/DatabaseUpdateStatisticsJob.cs b/src/Admin/Jobs/DatabaseUpdateStatisticsJob.cs index 36410c755..14c13918b 100644 --- a/src/Admin/Jobs/DatabaseUpdateStatisticsJob.cs +++ b/src/Admin/Jobs/DatabaseUpdateStatisticsJob.cs @@ -1,33 +1,29 @@ -using System; -using System.Threading.Tasks; -using Bit.Core; +using Bit.Core; using Bit.Core.Jobs; using Bit.Core.Repositories; -using Microsoft.Extensions.Logging; using Quartz; -namespace Bit.Admin.Jobs +namespace Bit.Admin.Jobs; + +public class DatabaseUpdateStatisticsJob : BaseJob { - public class DatabaseUpdateStatisticsJob : BaseJob + private readonly IMaintenanceRepository _maintenanceRepository; + + public DatabaseUpdateStatisticsJob( + IMaintenanceRepository maintenanceRepository, + ILogger logger) + : base(logger) { - private readonly IMaintenanceRepository _maintenanceRepository; + _maintenanceRepository = maintenanceRepository; + } - public DatabaseUpdateStatisticsJob( - IMaintenanceRepository maintenanceRepository, - ILogger logger) - : base(logger) - { - _maintenanceRepository = maintenanceRepository; - } - - protected async override Task ExecuteJobAsync(IJobExecutionContext context) - { - _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: UpdateStatisticsAsync"); - await _maintenanceRepository.UpdateStatisticsAsync(); - _logger.LogInformation(Constants.BypassFiltersEventId, "Finished job task: UpdateStatisticsAsync"); - _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: DisableCipherAutoStatsAsync"); - await _maintenanceRepository.DisableCipherAutoStatsAsync(); - _logger.LogInformation(Constants.BypassFiltersEventId, "Finished job task: DisableCipherAutoStatsAsync"); - } + protected async override Task ExecuteJobAsync(IJobExecutionContext context) + { + _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: UpdateStatisticsAsync"); + await _maintenanceRepository.UpdateStatisticsAsync(); + _logger.LogInformation(Constants.BypassFiltersEventId, "Finished job task: UpdateStatisticsAsync"); + _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: DisableCipherAutoStatsAsync"); + await _maintenanceRepository.DisableCipherAutoStatsAsync(); + _logger.LogInformation(Constants.BypassFiltersEventId, "Finished job task: DisableCipherAutoStatsAsync"); } } diff --git a/src/Admin/Jobs/DeleteAuthRequestsJob.cs b/src/Admin/Jobs/DeleteAuthRequestsJob.cs new file mode 100644 index 000000000..f0d26a33a --- /dev/null +++ b/src/Admin/Jobs/DeleteAuthRequestsJob.cs @@ -0,0 +1,27 @@ +using Bit.Core; +using Bit.Core.Jobs; +using Bit.Core.Repositories; +using Quartz; + +namespace Bit.Admin.Jobs; + +public class DeleteAuthRequestsJob : BaseJob +{ + private readonly IAuthRequestRepository _authRepo; + + public DeleteAuthRequestsJob( + IAuthRequestRepository authrepo, + ILogger logger) + : base(logger) + { + _authRepo = authrepo; + } + + protected async override Task ExecuteJobAsync(IJobExecutionContext context) + { + _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: DeleteAuthRequestsJob: Start"); + var count = await _authRepo.DeleteExpiredAsync(); + _logger.LogInformation(Constants.BypassFiltersEventId, $"{count} records deleted from AuthRequests."); + _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: DeleteAuthRequestsJob: End"); + } +} diff --git a/src/Admin/Jobs/DeleteCiphersJob.cs b/src/Admin/Jobs/DeleteCiphersJob.cs index 62b1f1305..ecf13401e 100644 --- a/src/Admin/Jobs/DeleteCiphersJob.cs +++ b/src/Admin/Jobs/DeleteCiphersJob.cs @@ -1,40 +1,36 @@ -using System; -using System.Threading.Tasks; -using Bit.Core; +using Bit.Core; using Bit.Core.Jobs; using Bit.Core.Repositories; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Quartz; -namespace Bit.Admin.Jobs +namespace Bit.Admin.Jobs; + +public class DeleteCiphersJob : BaseJob { - public class DeleteCiphersJob : BaseJob + private readonly ICipherRepository _cipherRepository; + private readonly AdminSettings _adminSettings; + + public DeleteCiphersJob( + ICipherRepository cipherRepository, + IOptions adminSettings, + ILogger logger) + : base(logger) { - private readonly ICipherRepository _cipherRepository; - private readonly AdminSettings _adminSettings; + _cipherRepository = cipherRepository; + _adminSettings = adminSettings?.Value; + } - public DeleteCiphersJob( - ICipherRepository cipherRepository, - IOptions adminSettings, - ILogger logger) - : base(logger) + protected async override Task ExecuteJobAsync(IJobExecutionContext context) + { + _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: DeleteDeletedAsync"); + var deleteDate = DateTime.UtcNow.AddDays(-30); + var daysAgoSetting = (_adminSettings?.DeleteTrashDaysAgo).GetValueOrDefault(); + if (daysAgoSetting > 0) { - _cipherRepository = cipherRepository; - _adminSettings = adminSettings?.Value; - } - - protected async override Task ExecuteJobAsync(IJobExecutionContext context) - { - _logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: DeleteDeletedAsync"); - var deleteDate = DateTime.UtcNow.AddDays(-30); - var daysAgoSetting = (_adminSettings?.DeleteTrashDaysAgo).GetValueOrDefault(); - if (daysAgoSetting > 0) - { - deleteDate = DateTime.UtcNow.AddDays(-1 * daysAgoSetting); - } - await _cipherRepository.DeleteDeletedAsync(deleteDate); - _logger.LogInformation(Constants.BypassFiltersEventId, "Finished job task: DeleteDeletedAsync"); + deleteDate = DateTime.UtcNow.AddDays(-1 * daysAgoSetting); } + await _cipherRepository.DeleteDeletedAsync(deleteDate); + _logger.LogInformation(Constants.BypassFiltersEventId, "Finished job task: DeleteDeletedAsync"); } } diff --git a/src/Admin/Jobs/DeleteSendsJob.cs b/src/Admin/Jobs/DeleteSendsJob.cs index 6f45abb51..9f3ed96ef 100644 --- a/src/Admin/Jobs/DeleteSendsJob.cs +++ b/src/Admin/Jobs/DeleteSendsJob.cs @@ -1,47 +1,40 @@ -using System; -using System.Threading.Tasks; -using System.Linq; -using Bit.Core; -using Bit.Core.Context; +using Bit.Core; using Bit.Core.Jobs; using Bit.Core.Repositories; using Bit.Core.Services; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using Quartz; -namespace Bit.Admin.Jobs +namespace Bit.Admin.Jobs; + +public class DeleteSendsJob : BaseJob { - public class DeleteSendsJob : BaseJob + private readonly ISendRepository _sendRepository; + private readonly IServiceProvider _serviceProvider; + + public DeleteSendsJob( + ISendRepository sendRepository, + IServiceProvider serviceProvider, + ILogger logger) + : base(logger) { - private readonly ISendRepository _sendRepository; - private readonly IServiceProvider _serviceProvider; + _sendRepository = sendRepository; + _serviceProvider = serviceProvider; + } - public DeleteSendsJob( - ISendRepository sendRepository, - IServiceProvider serviceProvider, - ILogger logger) - : base(logger) + protected async override Task ExecuteJobAsync(IJobExecutionContext context) + { + var sends = await _sendRepository.GetManyByDeletionDateAsync(DateTime.UtcNow); + _logger.LogInformation(Constants.BypassFiltersEventId, "Deleting {0} sends.", sends.Count); + if (!sends.Any()) { - _sendRepository = sendRepository; - _serviceProvider = serviceProvider; + return; } - - protected async override Task ExecuteJobAsync(IJobExecutionContext context) + using (var scope = _serviceProvider.CreateScope()) { - var sends = await _sendRepository.GetManyByDeletionDateAsync(DateTime.UtcNow); - _logger.LogInformation(Constants.BypassFiltersEventId, "Deleting {0} sends.", sends.Count); - if (!sends.Any()) + var sendService = scope.ServiceProvider.GetRequiredService(); + foreach (var send in sends) { - return; - } - using (var scope = _serviceProvider.CreateScope()) - { - var sendService = scope.ServiceProvider.GetRequiredService(); - foreach (var send in sends) - { - await sendService.DeleteSendAsync(send); - } + await sendService.DeleteSendAsync(send); } } } diff --git a/src/Admin/Jobs/JobsHostedService.cs b/src/Admin/Jobs/JobsHostedService.cs index 8bef67ff4..fd83e07af 100644 --- a/src/Admin/Jobs/JobsHostedService.cs +++ b/src/Admin/Jobs/JobsHostedService.cs @@ -1,95 +1,102 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; +using System.Runtime.InteropServices; using Bit.Core.Jobs; using Bit.Core.Settings; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using Quartz; -namespace Bit.Admin.Jobs +namespace Bit.Admin.Jobs; + +public class JobsHostedService : BaseJobsHostedService { - public class JobsHostedService : BaseJobsHostedService + public JobsHostedService( + GlobalSettings globalSettings, + IServiceProvider serviceProvider, + ILogger logger, + ILogger listenerLogger) + : base(globalSettings, serviceProvider, logger, listenerLogger) { } + + public override async Task StartAsync(CancellationToken cancellationToken) { - public JobsHostedService( - GlobalSettings globalSettings, - IServiceProvider serviceProvider, - ILogger logger, - ILogger listenerLogger) - : base(globalSettings, serviceProvider, logger, listenerLogger) { } - - public override async Task StartAsync(CancellationToken cancellationToken) + var timeZone = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? + TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time") : + TimeZoneInfo.FindSystemTimeZoneById("America/New_York"); + if (_globalSettings.SelfHosted) { - var timeZone = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? - TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time") : - TimeZoneInfo.FindSystemTimeZoneById("America/New_York"); - if (_globalSettings.SelfHosted) - { - timeZone = TimeZoneInfo.Local; - } - - var everyTopOfTheHourTrigger = TriggerBuilder.Create() - .WithIdentity("EveryTopOfTheHourTrigger") - .StartNow() - .WithCronSchedule("0 0 * * * ?") - .Build(); - var everyFiveMinutesTrigger = TriggerBuilder.Create() - .WithIdentity("EveryFiveMinutesTrigger") - .StartNow() - .WithCronSchedule("0 */5 * * * ?") - .Build(); - var everyFridayAt10pmTrigger = TriggerBuilder.Create() - .WithIdentity("EveryFridayAt10pmTrigger") - .StartNow() - .WithCronSchedule("0 0 22 ? * FRI", x => x.InTimeZone(timeZone)) - .Build(); - var everySaturdayAtMidnightTrigger = TriggerBuilder.Create() - .WithIdentity("EverySaturdayAtMidnightTrigger") - .StartNow() - .WithCronSchedule("0 0 0 ? * SAT", x => x.InTimeZone(timeZone)) - .Build(); - var everySundayAtMidnightTrigger = TriggerBuilder.Create() - .WithIdentity("EverySundayAtMidnightTrigger") - .StartNow() - .WithCronSchedule("0 0 0 ? * SUN", x => x.InTimeZone(timeZone)) - .Build(); - var everyDayAtMidnightUtc = TriggerBuilder.Create() - .WithIdentity("EveryDayAtMidnightUtc") - .StartNow() - .WithCronSchedule("0 0 0 * * ?") - .Build(); - - var jobs = new List> - { - new Tuple(typeof(DeleteSendsJob), everyFiveMinutesTrigger), - new Tuple(typeof(DatabaseExpiredGrantsJob), everyFridayAt10pmTrigger), - new Tuple(typeof(DatabaseUpdateStatisticsJob), everySaturdayAtMidnightTrigger), - new Tuple(typeof(DatabaseRebuildlIndexesJob), everySundayAtMidnightTrigger), - new Tuple(typeof(DeleteCiphersJob), everyDayAtMidnightUtc) - }; - - if (!_globalSettings.SelfHosted) - { - jobs.Add(new Tuple(typeof(AliveJob), everyTopOfTheHourTrigger)); - } - - Jobs = jobs; - await base.StartAsync(cancellationToken); + timeZone = TimeZoneInfo.Local; } - public static void AddJobsServices(IServiceCollection services, bool selfHosted) + var everyTopOfTheHourTrigger = TriggerBuilder.Create() + .WithIdentity("EveryTopOfTheHourTrigger") + .StartNow() + .WithCronSchedule("0 0 * * * ?") + .Build(); + var everyFiveMinutesTrigger = TriggerBuilder.Create() + .WithIdentity("EveryFiveMinutesTrigger") + .StartNow() + .WithCronSchedule("0 */5 * * * ?") + .Build(); + var everyFridayAt10pmTrigger = TriggerBuilder.Create() + .WithIdentity("EveryFridayAt10pmTrigger") + .StartNow() + .WithCronSchedule("0 0 22 ? * FRI", x => x.InTimeZone(timeZone)) + .Build(); + var everySaturdayAtMidnightTrigger = TriggerBuilder.Create() + .WithIdentity("EverySaturdayAtMidnightTrigger") + .StartNow() + .WithCronSchedule("0 0 0 ? * SAT", x => x.InTimeZone(timeZone)) + .Build(); + var everySundayAtMidnightTrigger = TriggerBuilder.Create() + .WithIdentity("EverySundayAtMidnightTrigger") + .StartNow() + .WithCronSchedule("0 0 0 ? * SUN", x => x.InTimeZone(timeZone)) + .Build(); + var everyMondayAtMidnightTrigger = TriggerBuilder.Create() + .WithIdentity("EveryMondayAtMidnightTrigger") + .StartNow() + .WithCronSchedule("0 0 0 ? * MON", x => x.InTimeZone(timeZone)) + .Build(); + var everyDayAtMidnightUtc = TriggerBuilder.Create() + .WithIdentity("EveryDayAtMidnightUtc") + .StartNow() + .WithCronSchedule("0 0 0 * * ?") + .Build(); + var everyFifteenMinutesTrigger = TriggerBuilder.Create() + .WithIdentity("everyFifteenMinutesTrigger") + .StartNow() + .WithCronSchedule("0 */15 * ? * *") + .Build(); + + var jobs = new List> { - if (!selfHosted) - { - services.AddTransient(); - } - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + new Tuple(typeof(DeleteSendsJob), everyFiveMinutesTrigger), + new Tuple(typeof(DatabaseExpiredGrantsJob), everyFridayAt10pmTrigger), + new Tuple(typeof(DatabaseUpdateStatisticsJob), everySaturdayAtMidnightTrigger), + new Tuple(typeof(DatabaseRebuildlIndexesJob), everySundayAtMidnightTrigger), + new Tuple(typeof(DeleteCiphersJob), everyDayAtMidnightUtc), + new Tuple(typeof(DatabaseExpiredSponsorshipsJob), everyMondayAtMidnightTrigger), + new Tuple(typeof(DeleteAuthRequestsJob), everyFifteenMinutesTrigger), + }; + + if (!_globalSettings.SelfHosted) + { + jobs.Add(new Tuple(typeof(AliveJob), everyTopOfTheHourTrigger)); } + + Jobs = jobs; + await base.StartAsync(cancellationToken); + } + + public static void AddJobsServices(IServiceCollection services, bool selfHosted) + { + if (!selfHosted) + { + services.AddTransient(); + } + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); } } diff --git a/src/Admin/Models/BillingInformationModel.cs b/src/Admin/Models/BillingInformationModel.cs index 317a9e8f1..a90ec7955 100644 --- a/src/Admin/Models/BillingInformationModel.cs +++ b/src/Admin/Models/BillingInformationModel.cs @@ -1,12 +1,10 @@ -using System; -using Bit.Core.Models.Business; +using Bit.Core.Models.Business; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class BillingInformationModel { - public class BillingInformationModel - { - public BillingInfo BillingInfo { get; set; } - public Guid? UserId { get; set; } - public Guid? OrganizationId { get; set; } - } + public BillingInfo BillingInfo { get; set; } + public Guid? UserId { get; set; } + public Guid? OrganizationId { get; set; } } diff --git a/src/Admin/Models/ChargeBraintreeModel.cs b/src/Admin/Models/ChargeBraintreeModel.cs index 5b3a94f16..2ba06cb98 100644 --- a/src/Admin/Models/ChargeBraintreeModel.cs +++ b/src/Admin/Models/ChargeBraintreeModel.cs @@ -1,29 +1,26 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class ChargeBraintreeModel : IValidatableObject { - public class ChargeBraintreeModel : IValidatableObject - { - [Required] - [Display(Name = "Braintree Customer Id")] - public string Id { get; set; } - [Required] - [Display(Name = "Amount")] - public decimal? Amount { get; set; } - public string TransactionId { get; set; } - public string PayPalTransactionId { get; set; } + [Required] + [Display(Name = "Braintree Customer Id")] + public string Id { get; set; } + [Required] + [Display(Name = "Amount")] + public decimal? Amount { get; set; } + public string TransactionId { get; set; } + public string PayPalTransactionId { get; set; } - public IEnumerable Validate(ValidationContext validationContext) + public IEnumerable Validate(ValidationContext validationContext) + { + if (Id != null) { - if (Id != null) + if (Id.Length != 36 || (Id[0] != 'o' && Id[0] != 'u') || + !Guid.TryParse(Id.Substring(1, 32), out var guid)) { - if (Id.Length != 36 || (Id[0] != 'o' && Id[0] != 'u') || - !Guid.TryParse(Id.Substring(1, 32), out var guid)) - { - yield return new ValidationResult("Customer Id is not a valid format."); - } + yield return new ValidationResult("Customer Id is not a valid format."); } } } diff --git a/src/Admin/Models/CreateProviderModel.cs b/src/Admin/Models/CreateProviderModel.cs index ad4c547f4..9bcbf1f75 100644 --- a/src/Admin/Models/CreateProviderModel.cs +++ b/src/Admin/Models/CreateProviderModel.cs @@ -1,13 +1,12 @@ using System.ComponentModel.DataAnnotations; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class CreateProviderModel { - public class CreateProviderModel - { - public CreateProviderModel() { } - - [Display(Name = "Owner Email")] - [Required] - public string OwnerEmail { get; set; } - } + public CreateProviderModel() { } + + [Display(Name = "Owner Email")] + [Required] + public string OwnerEmail { get; set; } } diff --git a/src/Admin/Models/CreateUpdateTransactionModel.cs b/src/Admin/Models/CreateUpdateTransactionModel.cs index ed2f5116c..8004546f9 100644 --- a/src/Admin/Models/CreateUpdateTransactionModel.cs +++ b/src/Admin/Models/CreateUpdateTransactionModel.cs @@ -1,80 +1,77 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; +using Bit.Core.Entities; using Bit.Core.Enums; -using Bit.Core.Models.Table; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class CreateUpdateTransactionModel : IValidatableObject { - public class CreateUpdateTransactionModel : IValidatableObject + public CreateUpdateTransactionModel() { } + + public CreateUpdateTransactionModel(Transaction transaction) { - public CreateUpdateTransactionModel() { } + Edit = true; + UserId = transaction.UserId; + OrganizationId = transaction.OrganizationId; + Amount = transaction.Amount; + RefundedAmount = transaction.RefundedAmount; + Refunded = transaction.Refunded.GetValueOrDefault(); + Details = transaction.Details; + Date = transaction.CreationDate; + PaymentMethod = transaction.PaymentMethodType; + Gateway = transaction.Gateway; + GatewayId = transaction.GatewayId; + Type = transaction.Type; + } - public CreateUpdateTransactionModel(Transaction transaction) + public bool Edit { get; set; } + + [Display(Name = "User Id")] + public Guid? UserId { get; set; } + [Display(Name = "Organization Id")] + public Guid? OrganizationId { get; set; } + [Required] + public decimal? Amount { get; set; } + [Display(Name = "Refunded Amount")] + public decimal? RefundedAmount { get; set; } + public bool Refunded { get; set; } + [Required] + public string Details { get; set; } + [Required] + public DateTime? Date { get; set; } + [Display(Name = "Payment Method")] + public PaymentMethodType? PaymentMethod { get; set; } + public GatewayType? Gateway { get; set; } + [Display(Name = "Gateway Id")] + public string GatewayId { get; set; } + [Required] + public TransactionType? Type { get; set; } + + + public IEnumerable Validate(ValidationContext validationContext) + { + if ((!UserId.HasValue && !OrganizationId.HasValue) || (UserId.HasValue && OrganizationId.HasValue)) { - Edit = true; - UserId = transaction.UserId; - OrganizationId = transaction.OrganizationId; - Amount = transaction.Amount; - RefundedAmount = transaction.RefundedAmount; - Refunded = transaction.Refunded.GetValueOrDefault(); - Details = transaction.Details; - Date = transaction.CreationDate; - PaymentMethod = transaction.PaymentMethodType; - Gateway = transaction.Gateway; - GatewayId = transaction.GatewayId; - Type = transaction.Type; - } - - public bool Edit { get; set; } - - [Display(Name = "User Id")] - public Guid? UserId { get; set; } - [Display(Name = "Organization Id")] - public Guid? OrganizationId { get; set; } - [Required] - public decimal? Amount { get; set; } - [Display(Name = "Refunded Amount")] - public decimal? RefundedAmount { get; set; } - public bool Refunded { get; set; } - [Required] - public string Details { get; set; } - [Required] - public DateTime? Date { get; set; } - [Display(Name = "Payment Method")] - public PaymentMethodType? PaymentMethod { get; set; } - public GatewayType? Gateway { get; set; } - [Display(Name = "Gateway Id")] - public string GatewayId { get; set; } - [Required] - public TransactionType? Type { get; set; } - - - public IEnumerable Validate(ValidationContext validationContext) - { - if ((!UserId.HasValue && !OrganizationId.HasValue) || (UserId.HasValue && OrganizationId.HasValue)) - { - yield return new ValidationResult("Must provide either User Id, or Organization Id."); - } - } - - public Transaction ToTransaction(Guid? id = null) - { - return new Transaction - { - Id = id.GetValueOrDefault(), - UserId = UserId, - OrganizationId = OrganizationId, - Amount = Amount.Value, - RefundedAmount = RefundedAmount, - Refunded = Refunded ? true : (bool?)null, - Details = Details, - CreationDate = Date.Value, - PaymentMethodType = PaymentMethod, - Gateway = Gateway, - GatewayId = GatewayId, - Type = Type.Value - }; + yield return new ValidationResult("Must provide either User Id, or Organization Id."); } } + + public Transaction ToTransaction(Guid? id = null) + { + return new Transaction + { + Id = id.GetValueOrDefault(), + UserId = UserId, + OrganizationId = OrganizationId, + Amount = Amount.Value, + RefundedAmount = RefundedAmount, + Refunded = Refunded ? true : (bool?)null, + Details = Details, + CreationDate = Date.Value, + PaymentMethodType = PaymentMethod, + Gateway = Gateway, + GatewayId = GatewayId, + Type = Type.Value + }; + } } diff --git a/src/Admin/Models/CursorPagedModel.cs b/src/Admin/Models/CursorPagedModel.cs index b9e3fdb38..35a4de922 100644 --- a/src/Admin/Models/CursorPagedModel.cs +++ b/src/Admin/Models/CursorPagedModel.cs @@ -1,12 +1,9 @@ -using System.Collections.Generic; +namespace Bit.Admin.Models; -namespace Bit.Admin.Models +public class CursorPagedModel { - public class CursorPagedModel - { - public List Items { get; set; } - public int Count { get; set; } - public string Cursor { get; set; } - public string NextCursor { get; set; } - } + public List Items { get; set; } + public int Count { get; set; } + public string Cursor { get; set; } + public string NextCursor { get; set; } } diff --git a/src/Admin/Models/ErrorViewModel.cs b/src/Admin/Models/ErrorViewModel.cs index 54717ed20..3b24a1ece 100644 --- a/src/Admin/Models/ErrorViewModel.cs +++ b/src/Admin/Models/ErrorViewModel.cs @@ -1,11 +1,8 @@ -using System; +namespace Bit.Admin.Models; -namespace Bit.Admin.Models +public class ErrorViewModel { - public class ErrorViewModel - { - public string RequestId { get; set; } + public string RequestId { get; set; } - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - } + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); } diff --git a/src/Admin/Models/HomeModel.cs b/src/Admin/Models/HomeModel.cs index b5887e402..900a04e41 100644 --- a/src/Admin/Models/HomeModel.cs +++ b/src/Admin/Models/HomeModel.cs @@ -1,11 +1,9 @@ -using System; -using Bit.Core.Settings; +using Bit.Core.Settings; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class HomeModel { - public class HomeModel - { - public string CurrentVersion { get; set; } - public GlobalSettings GlobalSettings { get; set; } - } + public string CurrentVersion { get; set; } + public GlobalSettings GlobalSettings { get; set; } } diff --git a/src/Admin/Models/LicenseModel.cs b/src/Admin/Models/LicenseModel.cs index c8a598449..b0fd91201 100644 --- a/src/Admin/Models/LicenseModel.cs +++ b/src/Admin/Models/LicenseModel.cs @@ -1,37 +1,34 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class LicenseModel : IValidatableObject { - public class LicenseModel : IValidatableObject + [Display(Name = "User Id")] + public Guid? UserId { get; set; } + [Display(Name = "Organization Id")] + public Guid? OrganizationId { get; set; } + [Display(Name = "Installation Id")] + public Guid? InstallationId { get; set; } + [Required] + [Display(Name = "Version")] + public int Version { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) { - [Display(Name = "User Id")] - public Guid? UserId { get; set; } - [Display(Name = "Organization Id")] - public Guid? OrganizationId { get; set; } - [Display(Name = "Installation Id")] - public Guid? InstallationId { get; set; } - [Required] - [Display(Name = "Version")] - public int Version { get; set; } - - public IEnumerable Validate(ValidationContext validationContext) + if (UserId.HasValue && OrganizationId.HasValue) { - if (UserId.HasValue && OrganizationId.HasValue) - { - yield return new ValidationResult("Use either User Id or Organization Id. Not both."); - } + yield return new ValidationResult("Use either User Id or Organization Id. Not both."); + } - if (!UserId.HasValue && !OrganizationId.HasValue) - { - yield return new ValidationResult("User Id or Organization Id is required."); - } + if (!UserId.HasValue && !OrganizationId.HasValue) + { + yield return new ValidationResult("User Id or Organization Id is required."); + } - if (OrganizationId.HasValue && !InstallationId.HasValue) - { - yield return new ValidationResult("Installation Id is required for organization licenses."); - } + if (OrganizationId.HasValue && !InstallationId.HasValue) + { + yield return new ValidationResult("Installation Id is required for organization licenses."); } } } diff --git a/src/Admin/Models/LogModel.cs b/src/Admin/Models/LogModel.cs index 16f90b5df..8967025d1 100644 --- a/src/Admin/Models/LogModel.cs +++ b/src/Admin/Models/LogModel.cs @@ -1,56 +1,54 @@ -using System.Collections.Generic; -using Microsoft.Azure.Documents; +using Microsoft.Azure.Documents; using Newtonsoft.Json.Linq; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class LogModel : Resource { - public class LogModel : Resource - { - public long EventIdHash { get; set; } - public string Level { get; set; } - public string Message { get; set; } - public string MessageTruncated => Message.Length > 200 ? $"{Message.Substring(0, 200)}..." : Message; - public string MessageTemplate { get; set; } - public IDictionary Properties { get; set; } - public string Project => Properties?.ContainsKey("Project") ?? false ? Properties["Project"].ToString() : null; - } + public long EventIdHash { get; set; } + public string Level { get; set; } + public string Message { get; set; } + public string MessageTruncated => Message.Length > 200 ? $"{Message.Substring(0, 200)}..." : Message; + public string MessageTemplate { get; set; } + public IDictionary Properties { get; set; } + public string Project => Properties?.ContainsKey("Project") ?? false ? Properties["Project"].ToString() : null; +} - public class LogDetailsModel : LogModel - { - public JObject Exception { get; set; } +public class LogDetailsModel : LogModel +{ + public JObject Exception { get; set; } - public string ExceptionToString(JObject e) + public string ExceptionToString(JObject e) + { + if (e == null) { - if (e == null) - { - return null; - } - - var val = string.Empty; - if (e["Message"] != null && e["Message"].ToObject() != null) - { - val += "Message:\n"; - val += e["Message"] + "\n"; - } - - if (e["StackTrace"] != null && e["StackTrace"].ToObject() != null) - { - val += "\nStack Trace:\n"; - val += e["StackTrace"]; - } - else if (e["StackTraceString"] != null && e["StackTraceString"].ToObject() != null) - { - val += "\nStack Trace String:\n"; - val += e["StackTraceString"]; - } - - if (e["InnerException"] != null && e["InnerException"].ToObject() != null) - { - val += "\n\n=== Inner Exception ===\n\n"; - val += ExceptionToString(e["InnerException"].ToObject()); - } - - return val; + return null; } + + var val = string.Empty; + if (e["Message"] != null && e["Message"].ToObject() != null) + { + val += "Message:\n"; + val += e["Message"] + "\n"; + } + + if (e["StackTrace"] != null && e["StackTrace"].ToObject() != null) + { + val += "\nStack Trace:\n"; + val += e["StackTrace"]; + } + else if (e["StackTraceString"] != null && e["StackTraceString"].ToObject() != null) + { + val += "\nStack Trace String:\n"; + val += e["StackTraceString"]; + } + + if (e["InnerException"] != null && e["InnerException"].ToObject() != null) + { + val += "\n\n=== Inner Exception ===\n\n"; + val += ExceptionToString(e["InnerException"].ToObject()); + } + + return val; } } diff --git a/src/Admin/Models/LoginModel.cs b/src/Admin/Models/LoginModel.cs index fa77ddfe1..7f147874b 100644 --- a/src/Admin/Models/LoginModel.cs +++ b/src/Admin/Models/LoginModel.cs @@ -1,14 +1,13 @@ using System.ComponentModel.DataAnnotations; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class LoginModel { - public class LoginModel - { - [Required] - [EmailAddress] - public string Email { get; set; } - public string ReturnUrl { get; set; } - public string Error { get; set; } - public string Success { get; set; } - } + [Required] + [EmailAddress] + public string Email { get; set; } + public string ReturnUrl { get; set; } + public string Error { get; set; } + public string Success { get; set; } } diff --git a/src/Admin/Models/LogsModel.cs b/src/Admin/Models/LogsModel.cs index f21874bfa..c5527a319 100644 --- a/src/Admin/Models/LogsModel.cs +++ b/src/Admin/Models/LogsModel.cs @@ -1,13 +1,11 @@ -using System; -using Serilog.Events; +using Serilog.Events; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class LogsModel : CursorPagedModel { - public class LogsModel : CursorPagedModel - { - public LogEventLevel? Level { get; set; } - public string Project { get; set; } - public DateTime? Start { get; set; } - public DateTime? End { get; set; } - } + public LogEventLevel? Level { get; set; } + public string Project { get; set; } + public DateTime? Start { get; set; } + public DateTime? End { get; set; } } diff --git a/src/Admin/Models/OrganizationEditModel.cs b/src/Admin/Models/OrganizationEditModel.cs index fe9c445cb..2eeafb77a 100644 --- a/src/Admin/Models/OrganizationEditModel.cs +++ b/src/Admin/Models/OrganizationEditModel.cs @@ -1,150 +1,160 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; +using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Models.Business; -using Bit.Core.Models.Data; -using Bit.Core.Models.Table; -using Bit.Core.Utilities; +using Bit.Core.Models.Data.Organizations.OrganizationUsers; using Bit.Core.Settings; +using Bit.Core.Utilities; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class OrganizationEditModel : OrganizationViewModel { - public class OrganizationEditModel : OrganizationViewModel + public OrganizationEditModel() { } + + public OrganizationEditModel(Organization org, IEnumerable orgUsers, + IEnumerable ciphers, IEnumerable collections, IEnumerable groups, + IEnumerable policies, BillingInfo billingInfo, IEnumerable connections, + GlobalSettings globalSettings) + : base(org, connections, orgUsers, ciphers, collections, groups, policies) { - public OrganizationEditModel() { } + BillingInfo = billingInfo; + BraintreeMerchantId = globalSettings.Braintree.MerchantId; - public OrganizationEditModel(Organization org, IEnumerable orgUsers, - IEnumerable ciphers, IEnumerable collections, IEnumerable groups, - IEnumerable policies, BillingInfo billingInfo, GlobalSettings globalSettings) - : base(org, orgUsers, ciphers, collections, groups, policies) - { - BillingInfo = billingInfo; - BraintreeMerchantId = globalSettings.Braintree.MerchantId; + Name = org.Name; + BusinessName = org.BusinessName; + BillingEmail = org.BillingEmail; + PlanType = org.PlanType; + Plan = org.Plan; + Seats = org.Seats; + MaxAutoscaleSeats = org.MaxAutoscaleSeats; + MaxCollections = org.MaxCollections; + UsePolicies = org.UsePolicies; + UseSso = org.UseSso; + UseKeyConnector = org.UseKeyConnector; + UseScim = org.UseScim; + UseGroups = org.UseGroups; + UseDirectory = org.UseDirectory; + UseEvents = org.UseEvents; + UseTotp = org.UseTotp; + Use2fa = org.Use2fa; + UseApi = org.UseApi; + UseSecretsManager = org.UseSecretsManager; + UseResetPassword = org.UseResetPassword; + SelfHost = org.SelfHost; + UsersGetPremium = org.UsersGetPremium; + UseCustomPermissions = org.UseCustomPermissions; + MaxStorageGb = org.MaxStorageGb; + Gateway = org.Gateway; + GatewayCustomerId = org.GatewayCustomerId; + GatewaySubscriptionId = org.GatewaySubscriptionId; + Enabled = org.Enabled; + LicenseKey = org.LicenseKey; + ExpirationDate = org.ExpirationDate; + } - Name = org.Name; - BusinessName = org.BusinessName; - BillingEmail = org.BillingEmail; - PlanType = org.PlanType; - Plan = org.Plan; - Seats = org.Seats; - MaxAutoscaleSeats = org.MaxAutoscaleSeats; - MaxCollections = org.MaxCollections; - UsePolicies = org.UsePolicies; - UseSso = org.UseSso; - UseKeyConnector = org.UseKeyConnector; - UseGroups = org.UseGroups; - UseDirectory = org.UseDirectory; - UseEvents = org.UseEvents; - UseTotp = org.UseTotp; - Use2fa = org.Use2fa; - UseApi = org.UseApi; - UseResetPassword = org.UseResetPassword; - SelfHost = org.SelfHost; - UsersGetPremium = org.UsersGetPremium; - MaxStorageGb = org.MaxStorageGb; - Gateway = org.Gateway; - GatewayCustomerId = org.GatewayCustomerId; - GatewaySubscriptionId = org.GatewaySubscriptionId; - Enabled = org.Enabled; - LicenseKey = org.LicenseKey; - ExpirationDate = org.ExpirationDate; - } + public BillingInfo BillingInfo { get; set; } + public string RandomLicenseKey => CoreHelpers.SecureRandomString(20); + public string FourteenDayExpirationDate => DateTime.Now.AddDays(14).ToString("yyyy-MM-ddTHH:mm"); + public string BraintreeMerchantId { get; set; } - public BillingInfo BillingInfo { get; set; } - public string RandomLicenseKey => CoreHelpers.SecureRandomString(20); - public string FourteenDayExpirationDate => DateTime.Now.AddDays(14).ToString("yyyy-MM-ddTHH:mm"); - public string BraintreeMerchantId { get; set; } + [Required] + [Display(Name = "Name")] + public string Name { get; set; } + [Display(Name = "Business Name")] + public string BusinessName { get; set; } + [Display(Name = "Billing Email")] + public string BillingEmail { get; set; } + [Required] + [Display(Name = "Plan")] + public PlanType? PlanType { get; set; } + [Required] + [Display(Name = "Plan Name")] + public string Plan { get; set; } + [Display(Name = "Seats")] + public int? Seats { get; set; } + [Display(Name = "Max. Autoscale Seats")] + public int? MaxAutoscaleSeats { get; set; } + [Display(Name = "Max. Collections")] + public short? MaxCollections { get; set; } + [Display(Name = "Policies")] + public bool UsePolicies { get; set; } + [Display(Name = "SSO")] + public bool UseSso { get; set; } + [Display(Name = "Key Connector with Customer Encryption")] + public bool UseKeyConnector { get; set; } + [Display(Name = "Groups")] + public bool UseGroups { get; set; } + [Display(Name = "Directory")] + public bool UseDirectory { get; set; } + [Display(Name = "Events")] + public bool UseEvents { get; set; } + [Display(Name = "TOTP")] + public bool UseTotp { get; set; } + [Display(Name = "2FA")] + public bool Use2fa { get; set; } + [Display(Name = "API")] + public bool UseApi { get; set; } + [Display(Name = "Reset Password")] + public bool UseResetPassword { get; set; } + [Display(Name = "SCIM")] + public bool UseScim { get; set; } + [Display(Name = "Secrets Manager")] + public bool UseSecretsManager { get; set; } + [Display(Name = "Self Host")] + public bool SelfHost { get; set; } + [Display(Name = "Users Get Premium")] + public bool UsersGetPremium { get; set; } + [Display(Name = "Custom Permissions")] + public bool UseCustomPermissions { get; set; } + [Display(Name = "Max. Storage GB")] + public short? MaxStorageGb { get; set; } + [Display(Name = "Gateway")] + public GatewayType? Gateway { get; set; } + [Display(Name = "Gateway Customer Id")] + public string GatewayCustomerId { get; set; } + [Display(Name = "Gateway Subscription Id")] + public string GatewaySubscriptionId { get; set; } + [Display(Name = "Enabled")] + public bool Enabled { get; set; } + [Display(Name = "License Key")] + public string LicenseKey { get; set; } + [Display(Name = "Expiration Date")] + public DateTime? ExpirationDate { get; set; } + public bool SalesAssistedTrialStarted { get; set; } - [Required] - [Display(Name = "Name")] - public string Name { get; set; } - [Display(Name = "Business Name")] - public string BusinessName { get; set; } - [Display(Name = "Billing Email")] - public string BillingEmail { get; set; } - [Required] - [Display(Name = "Plan")] - public PlanType? PlanType { get; set; } - [Required] - [Display(Name = "Plan Name")] - public string Plan { get; set; } - [Display(Name = "Seats")] - public int? Seats { get; set; } - [Display(Name = "Max. Autoscale Seats")] - public int? MaxAutoscaleSeats { get; set; } - [Display(Name = "Max. Collections")] - public short? MaxCollections { get; set; } - [Display(Name = "Policies")] - public bool UsePolicies { get; set; } - [Display(Name = "SSO")] - public bool UseSso { get; set; } - [Display(Name = "Key Connector with Customer Encryption")] - public bool UseKeyConnector { get; set; } - [Display(Name = "Groups")] - public bool UseGroups { get; set; } - [Display(Name = "Directory")] - public bool UseDirectory { get; set; } - [Display(Name = "Events")] - public bool UseEvents { get; set; } - [Display(Name = "TOTP")] - public bool UseTotp { get; set; } - [Display(Name = "2FA")] - public bool Use2fa { get; set; } - [Display(Name = "API")] - public bool UseApi{ get; set; } - [Display(Name = "Reset Password")] - public bool UseResetPassword { get; set; } - [Display(Name = "Self Host")] - public bool SelfHost { get; set; } - [Display(Name = "Users Get Premium")] - public bool UsersGetPremium { get; set; } - [Display(Name = "Max. Storage GB")] - public short? MaxStorageGb { get; set; } - [Display(Name = "Gateway")] - public GatewayType? Gateway { get; set; } - [Display(Name = "Gateway Customer Id")] - public string GatewayCustomerId { get; set; } - [Display(Name = "Gateway Subscription Id")] - public string GatewaySubscriptionId { get; set; } - [Display(Name = "Enabled")] - public bool Enabled { get; set; } - [Display(Name = "License Key")] - public string LicenseKey { get; set; } - [Display(Name = "Expiration Date")] - public DateTime? ExpirationDate { get; set; } - public bool SalesAssistedTrialStarted { get; set; } - - public Organization ToOrganization(Organization existingOrganization) - { - existingOrganization.Name = Name; - existingOrganization.BusinessName = BusinessName; - existingOrganization.BillingEmail = BillingEmail?.ToLowerInvariant()?.Trim(); - existingOrganization.PlanType = PlanType.Value; - existingOrganization.Plan = Plan; - existingOrganization.Seats = Seats; - existingOrganization.MaxCollections = MaxCollections; - existingOrganization.UsePolicies = UsePolicies; - existingOrganization.UseSso = UseSso; - existingOrganization.UseKeyConnector = UseKeyConnector; - existingOrganization.UseGroups = UseGroups; - existingOrganization.UseDirectory = UseDirectory; - existingOrganization.UseEvents = UseEvents; - existingOrganization.UseTotp = UseTotp; - existingOrganization.Use2fa = Use2fa; - existingOrganization.UseApi = UseApi; - existingOrganization.UseResetPassword = UseResetPassword; - existingOrganization.SelfHost = SelfHost; - existingOrganization.UsersGetPremium = UsersGetPremium; - existingOrganization.MaxStorageGb = MaxStorageGb; - existingOrganization.Gateway = Gateway; - existingOrganization.GatewayCustomerId = GatewayCustomerId; - existingOrganization.GatewaySubscriptionId = GatewaySubscriptionId; - existingOrganization.Enabled = Enabled; - existingOrganization.LicenseKey = LicenseKey; - existingOrganization.ExpirationDate = ExpirationDate; - existingOrganization.MaxAutoscaleSeats = MaxAutoscaleSeats; - return existingOrganization; - } + public Organization ToOrganization(Organization existingOrganization) + { + existingOrganization.Name = Name; + existingOrganization.BusinessName = BusinessName; + existingOrganization.BillingEmail = BillingEmail?.ToLowerInvariant()?.Trim(); + existingOrganization.PlanType = PlanType.Value; + existingOrganization.Plan = Plan; + existingOrganization.Seats = Seats; + existingOrganization.MaxCollections = MaxCollections; + existingOrganization.UsePolicies = UsePolicies; + existingOrganization.UseSso = UseSso; + existingOrganization.UseKeyConnector = UseKeyConnector; + existingOrganization.UseScim = UseScim; + existingOrganization.UseGroups = UseGroups; + existingOrganization.UseDirectory = UseDirectory; + existingOrganization.UseEvents = UseEvents; + existingOrganization.UseTotp = UseTotp; + existingOrganization.Use2fa = Use2fa; + existingOrganization.UseApi = UseApi; + existingOrganization.UseSecretsManager = UseSecretsManager; + existingOrganization.UseResetPassword = UseResetPassword; + existingOrganization.SelfHost = SelfHost; + existingOrganization.UsersGetPremium = UsersGetPremium; + existingOrganization.UseCustomPermissions = UseCustomPermissions; + existingOrganization.MaxStorageGb = MaxStorageGb; + existingOrganization.Gateway = Gateway; + existingOrganization.GatewayCustomerId = GatewayCustomerId; + existingOrganization.GatewaySubscriptionId = GatewaySubscriptionId; + existingOrganization.Enabled = Enabled; + existingOrganization.LicenseKey = LicenseKey; + existingOrganization.ExpirationDate = ExpirationDate; + existingOrganization.MaxAutoscaleSeats = MaxAutoscaleSeats; + return existingOrganization; } } diff --git a/src/Admin/Models/OrganizationViewModel.cs b/src/Admin/Models/OrganizationViewModel.cs index 5a9bc4452..31504f937 100644 --- a/src/Admin/Models/OrganizationViewModel.cs +++ b/src/Admin/Models/OrganizationViewModel.cs @@ -1,51 +1,49 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using Bit.Core.Entities; using Bit.Core.Enums; -using Bit.Core.Models.Data; -using Bit.Core.Models.Table; +using Bit.Core.Models.Data.Organizations.OrganizationUsers; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class OrganizationViewModel { - public class OrganizationViewModel + public OrganizationViewModel() { } + + public OrganizationViewModel(Organization org, IEnumerable connections, + IEnumerable orgUsers, IEnumerable ciphers, IEnumerable collections, + IEnumerable groups, IEnumerable policies) { - public OrganizationViewModel() { } - - public OrganizationViewModel(Organization org, IEnumerable orgUsers, - IEnumerable ciphers, IEnumerable collections, IEnumerable groups, - IEnumerable policies) - { - Organization = org; - HasPublicPrivateKeys = org.PublicKey != null && org.PrivateKey != null; - UserInvitedCount = orgUsers.Count(u => u.Status == OrganizationUserStatusType.Invited); - UserAcceptedCount = orgUsers.Count(u => u.Status == OrganizationUserStatusType.Accepted); - UserConfirmedCount = orgUsers.Count(u => u.Status == OrganizationUserStatusType.Confirmed); - UserCount = orgUsers.Count(); - CipherCount = ciphers.Count(); - CollectionCount = collections.Count(); - GroupCount = groups?.Count() ?? 0; - PolicyCount = policies?.Count() ?? 0; - Owners = string.Join(", ", - orgUsers - .Where(u => u.Type == OrganizationUserType.Owner && u.Status == OrganizationUserStatusType.Confirmed) - .Select(u => u.Email)); - Admins = string.Join(", ", - orgUsers - .Where(u => u.Type == OrganizationUserType.Admin && u.Status == OrganizationUserStatusType.Confirmed) - .Select(u => u.Email)); - } - - public Organization Organization { get; set; } - public string Owners { get; set; } - public string Admins { get; set; } - public int UserInvitedCount { get; set; } - public int UserConfirmedCount { get; set; } - public int UserAcceptedCount { get; set; } - public int UserCount { get; set; } - public int CipherCount { get; set; } - public int CollectionCount { get; set; } - public int GroupCount { get; set; } - public int PolicyCount { get; set; } - public bool HasPublicPrivateKeys { get; set; } + Organization = org; + Connections = connections ?? Enumerable.Empty(); + HasPublicPrivateKeys = org.PublicKey != null && org.PrivateKey != null; + UserInvitedCount = orgUsers.Count(u => u.Status == OrganizationUserStatusType.Invited); + UserAcceptedCount = orgUsers.Count(u => u.Status == OrganizationUserStatusType.Accepted); + UserConfirmedCount = orgUsers.Count(u => u.Status == OrganizationUserStatusType.Confirmed); + OccupiedSeatCount = orgUsers.Count(u => u.OccupiesOrganizationSeat); + CipherCount = ciphers.Count(); + CollectionCount = collections.Count(); + GroupCount = groups?.Count() ?? 0; + PolicyCount = policies?.Count() ?? 0; + Owners = string.Join(", ", + orgUsers + .Where(u => u.Type == OrganizationUserType.Owner && u.Status == OrganizationUserStatusType.Confirmed) + .Select(u => u.Email)); + Admins = string.Join(", ", + orgUsers + .Where(u => u.Type == OrganizationUserType.Admin && u.Status == OrganizationUserStatusType.Confirmed) + .Select(u => u.Email)); } + + public Organization Organization { get; set; } + public IEnumerable Connections { get; set; } + public string Owners { get; set; } + public string Admins { get; set; } + public int UserInvitedCount { get; set; } + public int UserConfirmedCount { get; set; } + public int UserAcceptedCount { get; set; } + public int OccupiedSeatCount { get; set; } + public int CipherCount { get; set; } + public int CollectionCount { get; set; } + public int GroupCount { get; set; } + public int PolicyCount { get; set; } + public bool HasPublicPrivateKeys { get; set; } } diff --git a/src/Admin/Models/OrganizationsModel.cs b/src/Admin/Models/OrganizationsModel.cs index d8696086b..706377f8e 100644 --- a/src/Admin/Models/OrganizationsModel.cs +++ b/src/Admin/Models/OrganizationsModel.cs @@ -1,13 +1,12 @@ -using Bit.Core.Models.Table; +using Bit.Core.Entities; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class OrganizationsModel : PagedModel { - public class OrganizationsModel : PagedModel - { - public string Name { get; set; } - public string UserEmail { get; set; } - public bool? Paid { get; set; } - public string Action { get; set; } - public bool SelfHosted { get; set; } - } + public string Name { get; set; } + public string UserEmail { get; set; } + public bool? Paid { get; set; } + public string Action { get; set; } + public bool SelfHosted { get; set; } } diff --git a/src/Admin/Models/PagedModel.cs b/src/Admin/Models/PagedModel.cs index a4e4087ac..4c9c8e171 100644 --- a/src/Admin/Models/PagedModel.cs +++ b/src/Admin/Models/PagedModel.cs @@ -1,13 +1,10 @@ -using System.Collections.Generic; +namespace Bit.Admin.Models; -namespace Bit.Admin.Models +public abstract class PagedModel { - public abstract class PagedModel - { - public List Items { get; set; } - public int Page { get; set; } - public int Count { get; set; } - public int? PreviousPage => Page < 2 ? (int?)null : Page - 1; - public int? NextPage => Items.Count < Count ? (int?)null : Page + 1; - } + public List Items { get; set; } + public int Page { get; set; } + public int Count { get; set; } + public int? PreviousPage => Page < 2 ? (int?)null : Page - 1; + public int? NextPage => Items.Count < Count ? (int?)null : Page + 1; } diff --git a/src/Admin/Models/PromoteAdminModel.cs b/src/Admin/Models/PromoteAdminModel.cs index d7f73839f..bc076d6ab 100644 --- a/src/Admin/Models/PromoteAdminModel.cs +++ b/src/Admin/Models/PromoteAdminModel.cs @@ -1,15 +1,13 @@ -using System; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class PromoteAdminModel { - public class PromoteAdminModel - { - [Required] - [Display(Name = "Admin User Id")] - public Guid? UserId { get; set; } - [Required] - [Display(Name = "Organization Id")] - public Guid? OrganizationId { get; set; } - } + [Required] + [Display(Name = "Admin User Id")] + public Guid? UserId { get; set; } + [Required] + [Display(Name = "Organization Id")] + public Guid? OrganizationId { get; set; } } diff --git a/src/Admin/Models/ProviderEditModel.cs b/src/Admin/Models/ProviderEditModel.cs index 6d4a2ad39..92b2f89e9 100644 --- a/src/Admin/Models/ProviderEditModel.cs +++ b/src/Admin/Models/ProviderEditModel.cs @@ -1,35 +1,33 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; +using Bit.Core.Entities.Provider; using Bit.Core.Models.Data; -using Bit.Core.Models.Table.Provider; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class ProviderEditModel : ProviderViewModel { - public class ProviderEditModel : ProviderViewModel + public ProviderEditModel() { } + + public ProviderEditModel(Provider provider, IEnumerable providerUsers, IEnumerable organizations) + : base(provider, providerUsers, organizations) { - public ProviderEditModel() { } + Name = provider.Name; + BusinessName = provider.BusinessName; + BillingEmail = provider.BillingEmail; + } - public ProviderEditModel(Provider provider, IEnumerable providerUsers, IEnumerable organizations) - : base(provider, providerUsers, organizations) - { - Name = provider.Name; - BusinessName = provider.BusinessName; - BillingEmail = provider.BillingEmail; - } + [Display(Name = "Billing Email")] + public string BillingEmail { get; set; } + [Display(Name = "Business Name")] + public string BusinessName { get; set; } + public string Name { get; set; } + [Display(Name = "Events")] - [Display(Name = "Billing Email")] - public string BillingEmail { get; set; } - [Display(Name = "Business Name")] - public string BusinessName { get; set; } - public string Name { get; set; } - [Display(Name = "Events")] - - public Provider ToProvider(Provider existingProvider) - { - existingProvider.Name = Name; - existingProvider.BusinessName = BusinessName; - existingProvider.BillingEmail = BillingEmail?.ToLowerInvariant()?.Trim(); - return existingProvider; - } + public Provider ToProvider(Provider existingProvider) + { + existingProvider.Name = Name; + existingProvider.BusinessName = BusinessName; + existingProvider.BillingEmail = BillingEmail?.ToLowerInvariant()?.Trim(); + return existingProvider; } } diff --git a/src/Admin/Models/ProviderViewModel.cs b/src/Admin/Models/ProviderViewModel.cs index 2439c7435..766101e88 100644 --- a/src/Admin/Models/ProviderViewModel.cs +++ b/src/Admin/Models/ProviderViewModel.cs @@ -1,27 +1,24 @@ -using System.Collections.Generic; -using System.Linq; +using Bit.Core.Entities.Provider; using Bit.Core.Enums.Provider; using Bit.Core.Models.Data; -using Bit.Core.Models.Table.Provider; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class ProviderViewModel { - public class ProviderViewModel + public ProviderViewModel() { } + + public ProviderViewModel(Provider provider, IEnumerable providerUsers, IEnumerable organizations) { - public ProviderViewModel() { } + Provider = provider; + UserCount = providerUsers.Count(); + ProviderAdmins = providerUsers.Where(u => u.Type == ProviderUserType.ProviderAdmin); - public ProviderViewModel(Provider provider, IEnumerable providerUsers, IEnumerable organizations) - { - Provider = provider; - UserCount = providerUsers.Count(); - ProviderAdmins = providerUsers.Where(u => u.Type == ProviderUserType.ProviderAdmin); - - ProviderOrganizations = organizations.Where(o => o.ProviderId == provider.Id); - } - - public int UserCount { get; set; } - public Provider Provider { get; set; } - public IEnumerable ProviderAdmins { get; set; } - public IEnumerable ProviderOrganizations { get; set; } + ProviderOrganizations = organizations.Where(o => o.ProviderId == provider.Id); } + + public int UserCount { get; set; } + public Provider Provider { get; set; } + public IEnumerable ProviderAdmins { get; set; } + public IEnumerable ProviderOrganizations { get; set; } } diff --git a/src/Admin/Models/ProvidersModel.cs b/src/Admin/Models/ProvidersModel.cs index dc2d1e87b..dccf4a4d7 100644 --- a/src/Admin/Models/ProvidersModel.cs +++ b/src/Admin/Models/ProvidersModel.cs @@ -1,14 +1,12 @@ -using Bit.Core.Models.Table; -using Bit.Core.Models.Table.Provider; +using Bit.Core.Entities.Provider; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class ProvidersModel : PagedModel { - public class ProvidersModel : PagedModel - { - public string Name { get; set; } - public string UserEmail { get; set; } - public bool? Paid { get; set; } - public string Action { get; set; } - public bool SelfHosted { get; set; } - } + public string Name { get; set; } + public string UserEmail { get; set; } + public bool? Paid { get; set; } + public string Action { get; set; } + public bool SelfHosted { get; set; } } diff --git a/src/Admin/Models/StripeSubscriptionsModel.cs b/src/Admin/Models/StripeSubscriptionsModel.cs new file mode 100644 index 000000000..99e9c5b77 --- /dev/null +++ b/src/Admin/Models/StripeSubscriptionsModel.cs @@ -0,0 +1,42 @@ +using System.ComponentModel.DataAnnotations; +using Bit.Core.Models.BitStripe; + +namespace Bit.Admin.Models; + +public class StripeSubscriptionRowModel +{ + public Stripe.Subscription Subscription { get; set; } + public bool Selected { get; set; } + + public StripeSubscriptionRowModel() { } + public StripeSubscriptionRowModel(Stripe.Subscription subscription) + { + Subscription = subscription; + } +} + +public enum StripeSubscriptionsAction +{ + Search, + PreviousPage, + NextPage, + Export, + BulkCancel +} + +public class StripeSubscriptionsModel : IValidatableObject +{ + public List Items { get; set; } + public StripeSubscriptionsAction Action { get; set; } = StripeSubscriptionsAction.Search; + public string Message { get; set; } + public List Prices { get; set; } + public List TestClocks { get; set; } + public StripeSubscriptionListOptions Filter { get; set; } = new StripeSubscriptionListOptions(); + public IEnumerable Validate(ValidationContext validationContext) + { + if (Action == StripeSubscriptionsAction.BulkCancel && Filter.Status != "unpaid") + { + yield return new ValidationResult("Bulk cancel is currently only supported for unpaid subscriptions"); + } + } +} diff --git a/src/Admin/Models/TaxRateAddEditModel.cs b/src/Admin/Models/TaxRateAddEditModel.cs index 7d098cd86..bfa87d7cc 100644 --- a/src/Admin/Models/TaxRateAddEditModel.cs +++ b/src/Admin/Models/TaxRateAddEditModel.cs @@ -1,11 +1,10 @@ -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class TaxRateAddEditModel { - public class TaxRateAddEditModel - { - public string StripeTaxRateId { get; set; } - public string Country { get; set; } - public string State { get; set; } - public string PostalCode { get; set; } - public decimal Rate { get; set; } - } + public string StripeTaxRateId { get; set; } + public string Country { get; set; } + public string State { get; set; } + public string PostalCode { get; set; } + public decimal Rate { get; set; } } diff --git a/src/Admin/Models/TaxRatesModel.cs b/src/Admin/Models/TaxRatesModel.cs index 4af8540fa..0af073f38 100644 --- a/src/Admin/Models/TaxRatesModel.cs +++ b/src/Admin/Models/TaxRatesModel.cs @@ -1,9 +1,8 @@ -using Bit.Core.Models.Table; +using Bit.Core.Entities; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class TaxRatesModel : PagedModel { - public class TaxRatesModel: PagedModel - { - public string Message { get; set; } - } + public string Message { get; set; } } diff --git a/src/Admin/Models/UserEditModel.cs b/src/Admin/Models/UserEditModel.cs index 624e0cb8c..d7ef56f08 100644 --- a/src/Admin/Models/UserEditModel.cs +++ b/src/Admin/Models/UserEditModel.cs @@ -1,76 +1,73 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; +using Bit.Core.Entities; using Bit.Core.Models.Business; -using Bit.Core.Models.Table; -using Bit.Core.Utilities; using Bit.Core.Settings; +using Bit.Core.Utilities; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class UserEditModel : UserViewModel { - public class UserEditModel : UserViewModel + public UserEditModel() { } + + public UserEditModel(User user, IEnumerable ciphers, BillingInfo billingInfo, + GlobalSettings globalSettings) + : base(user, ciphers) { - public UserEditModel() { } + BillingInfo = billingInfo; + BraintreeMerchantId = globalSettings.Braintree.MerchantId; - public UserEditModel(User user, IEnumerable ciphers, BillingInfo billingInfo, - GlobalSettings globalSettings) - : base(user, ciphers) - { - BillingInfo = billingInfo; - BraintreeMerchantId = globalSettings.Braintree.MerchantId; + Name = user.Name; + Email = user.Email; + EmailVerified = user.EmailVerified; + Premium = user.Premium; + MaxStorageGb = user.MaxStorageGb; + Gateway = user.Gateway; + GatewayCustomerId = user.GatewayCustomerId; + GatewaySubscriptionId = user.GatewaySubscriptionId; + LicenseKey = user.LicenseKey; + PremiumExpirationDate = user.PremiumExpirationDate; + } - Name = user.Name; - Email = user.Email; - EmailVerified = user.EmailVerified; - Premium = user.Premium; - MaxStorageGb = user.MaxStorageGb; - Gateway = user.Gateway; - GatewayCustomerId = user.GatewayCustomerId; - GatewaySubscriptionId = user.GatewaySubscriptionId; - LicenseKey = user.LicenseKey; - PremiumExpirationDate = user.PremiumExpirationDate; - } - - public BillingInfo BillingInfo { get; set; } - public string RandomLicenseKey => CoreHelpers.SecureRandomString(20); - public string OneYearExpirationDate => DateTime.Now.AddYears(1).ToString("yyyy-MM-ddTHH:mm"); - public string BraintreeMerchantId { get; set; } + public BillingInfo BillingInfo { get; set; } + public string RandomLicenseKey => CoreHelpers.SecureRandomString(20); + public string OneYearExpirationDate => DateTime.Now.AddYears(1).ToString("yyyy-MM-ddTHH:mm"); + public string BraintreeMerchantId { get; set; } - [Display(Name = "Name")] - public string Name { get; set; } - [Required] - [Display(Name = "Email")] - public string Email { get; set; } - [Display(Name = "Email Verified")] - public bool EmailVerified { get; set; } - [Display(Name = "Premium")] - public bool Premium { get; set; } - [Display(Name = "Max. Storage GB")] - public short? MaxStorageGb { get; set; } - [Display(Name = "Gateway")] - public Core.Enums.GatewayType? Gateway { get; set; } - [Display(Name = "Gateway Customer Id")] - public string GatewayCustomerId { get; set; } - [Display(Name = "Gateway Subscription Id")] - public string GatewaySubscriptionId { get; set; } - [Display(Name = "License Key")] - public string LicenseKey { get; set; } - [Display(Name = "Premium Expiration Date")] - public DateTime? PremiumExpirationDate { get; set; } + [Display(Name = "Name")] + public string Name { get; set; } + [Required] + [Display(Name = "Email")] + public string Email { get; set; } + [Display(Name = "Email Verified")] + public bool EmailVerified { get; set; } + [Display(Name = "Premium")] + public bool Premium { get; set; } + [Display(Name = "Max. Storage GB")] + public short? MaxStorageGb { get; set; } + [Display(Name = "Gateway")] + public Core.Enums.GatewayType? Gateway { get; set; } + [Display(Name = "Gateway Customer Id")] + public string GatewayCustomerId { get; set; } + [Display(Name = "Gateway Subscription Id")] + public string GatewaySubscriptionId { get; set; } + [Display(Name = "License Key")] + public string LicenseKey { get; set; } + [Display(Name = "Premium Expiration Date")] + public DateTime? PremiumExpirationDate { get; set; } - public User ToUser(User existingUser) - { - existingUser.Name = Name; - existingUser.Email = Email; - existingUser.EmailVerified = EmailVerified; - existingUser.Premium = Premium; - existingUser.MaxStorageGb = MaxStorageGb; - existingUser.Gateway = Gateway; - existingUser.GatewayCustomerId = GatewayCustomerId; - existingUser.GatewaySubscriptionId = GatewaySubscriptionId; - existingUser.LicenseKey = LicenseKey; - existingUser.PremiumExpirationDate = PremiumExpirationDate; - return existingUser; - } + public User ToUser(User existingUser) + { + existingUser.Name = Name; + existingUser.Email = Email; + existingUser.EmailVerified = EmailVerified; + existingUser.Premium = Premium; + existingUser.MaxStorageGb = MaxStorageGb; + existingUser.Gateway = Gateway; + existingUser.GatewayCustomerId = GatewayCustomerId; + existingUser.GatewaySubscriptionId = GatewaySubscriptionId; + existingUser.LicenseKey = LicenseKey; + existingUser.PremiumExpirationDate = PremiumExpirationDate; + return existingUser; } } diff --git a/src/Admin/Models/UserViewModel.cs b/src/Admin/Models/UserViewModel.cs index 1bf4095ff..f493f68f2 100644 --- a/src/Admin/Models/UserViewModel.cs +++ b/src/Admin/Models/UserViewModel.cs @@ -1,21 +1,17 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Bit.Core.Models.Table; +using Bit.Core.Entities; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class UserViewModel { - public class UserViewModel + public UserViewModel() { } + + public UserViewModel(User user, IEnumerable ciphers) { - public UserViewModel() { } - - public UserViewModel(User user, IEnumerable ciphers) - { - User = user; - CipherCount = ciphers.Count(); - } - - public User User { get; set; } - public int CipherCount { get; set; } + User = user; + CipherCount = ciphers.Count(); } + + public User User { get; set; } + public int CipherCount { get; set; } } diff --git a/src/Admin/Models/UsersModel.cs b/src/Admin/Models/UsersModel.cs index 7c0d146df..0a54e318d 100644 --- a/src/Admin/Models/UsersModel.cs +++ b/src/Admin/Models/UsersModel.cs @@ -1,10 +1,9 @@ -using Bit.Core.Models.Table; +using Bit.Core.Entities; -namespace Bit.Admin.Models +namespace Bit.Admin.Models; + +public class UsersModel : PagedModel { - public class UsersModel : PagedModel - { - public string Email { get; set; } - public string Action { get; set; } - } + public string Email { get; set; } + public string Action { get; set; } } diff --git a/src/Admin/Program.cs b/src/Admin/Program.cs index 4885edc1a..fb5dc7e08 100644 --- a/src/Admin/Program.cs +++ b/src/Admin/Program.cs @@ -1,39 +1,35 @@ using Bit.Core.Utilities; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Hosting; -using Serilog.Events; -namespace Bit.Admin +namespace Bit.Admin; + +public class Program { - public class Program + public static void Main(string[] args) { - public static void Main(string[] args) - { - Host - .CreateDefaultBuilder(args) - .ConfigureCustomAppConfiguration(args) - .ConfigureWebHostDefaults(webBuilder => + Host + .CreateDefaultBuilder(args) + .ConfigureCustomAppConfiguration(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.ConfigureKestrel(o => { - webBuilder.ConfigureKestrel(o => + o.Limits.MaxRequestLineSize = 20_000; + }); + webBuilder.UseStartup(); + webBuilder.ConfigureLogging((hostingContext, logging) => + logging.AddSerilog(hostingContext, (e, globalSettings) => + { + var context = e.Properties["SourceContext"].ToString(); + if (e.Properties.ContainsKey("RequestPath") && + !string.IsNullOrWhiteSpace(e.Properties["RequestPath"]?.ToString()) && + (context.Contains(".Server.Kestrel") || context.Contains(".Core.IISHttpServer"))) { - o.Limits.MaxRequestLineSize = 20_000; - }); - webBuilder.UseStartup(); - webBuilder.ConfigureLogging((hostingContext, logging) => - logging.AddSerilog(hostingContext, e => - { - var context = e.Properties["SourceContext"].ToString(); - if (e.Properties.ContainsKey("RequestPath") && - !string.IsNullOrWhiteSpace(e.Properties["RequestPath"]?.ToString()) && - (context.Contains(".Server.Kestrel") || context.Contains(".Core.IISHttpServer"))) - { - return false; - } - return e.Level >= LogEventLevel.Error; - })); - }) - .Build() - .Run(); - } + return false; + } + return e.Level >= globalSettings.MinLogLevel.AdminSettings.Default; + })); + }) + .Build() + .Run(); } } diff --git a/src/Admin/Properties/launchSettings.json b/src/Admin/Properties/launchSettings.json index 4e1b92a71..579b1e11a 100644 --- a/src/Admin/Properties/launchSettings.json +++ b/src/Admin/Properties/launchSettings.json @@ -22,6 +22,15 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "applicationUrl": "http://localhost:62911/" + }, + "Admin-SelfHost": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "developSelfHosted": "true" + }, + "applicationUrl": "http://localhost:62912/" } } } diff --git a/src/Admin/Sass/webfonts.css b/src/Admin/Sass/webfonts.scss similarity index 100% rename from src/Admin/Sass/webfonts.css rename to src/Admin/Sass/webfonts.scss diff --git a/src/Admin/Startup.cs b/src/Admin/Startup.cs index 285a35ad3..55dfa99b3 100644 --- a/src/Admin/Startup.cs +++ b/src/Admin/Startup.cs @@ -1,143 +1,154 @@ -using System; -using System.Globalization; +using System.Globalization; +using Bit.Admin.IdentityServer; using Bit.Core.Context; -using Bit.Core.Identity; using Bit.Core.Settings; using Bit.Core.Utilities; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; +using Bit.SharedWeb.Utilities; using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Stripe; #if !OSS -using Bit.CommCore.Utilities; +using Bit.Commercial.Core.Utilities; #endif -namespace Bit.Admin +namespace Bit.Admin; + +public class Startup { - public class Startup + public Startup(IWebHostEnvironment env, IConfiguration configuration) { - public Startup(IWebHostEnvironment env, IConfiguration configuration) + CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); + Configuration = configuration; + Environment = env; + } + + public IConfiguration Configuration { get; private set; } + public IWebHostEnvironment Environment { get; set; } + + public void ConfigureServices(IServiceCollection services) + { + // Options + services.AddOptions(); + + // Settings + var globalSettings = services.AddGlobalSettingsServices(Configuration, Environment); + services.Configure(Configuration.GetSection("AdminSettings")); + + // Data Protection + services.AddCustomDataProtectionServices(Environment, globalSettings); + + // Stripe Billing + StripeConfiguration.ApiKey = globalSettings.Stripe.ApiKey; + StripeConfiguration.MaxNetworkRetries = globalSettings.Stripe.MaxNetworkRetries; + + // Repositories + var databaseProvider = services.AddDatabaseRepositories(globalSettings); + switch (databaseProvider) { - CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US"); - Configuration = configuration; - Environment = env; + case Core.Enums.SupportedDatabaseProviders.SqlServer: + services.AddSingleton(); + break; + case Core.Enums.SupportedDatabaseProviders.MySql: + services.AddSingleton(); + break; + case Core.Enums.SupportedDatabaseProviders.Postgres: + services.AddSingleton(); + break; + case Core.Enums.SupportedDatabaseProviders.Sqlite: + services.AddSingleton(); + break; + default: + break; } - public IConfiguration Configuration { get; private set; } - public IWebHostEnvironment Environment { get; set; } + // Context + services.AddScoped(); - public void ConfigureServices(IServiceCollection services) + // Identity + services.AddPasswordlessIdentityServices(globalSettings); + services.Configure(options => { - // Options - services.AddOptions(); - - // Settings - var globalSettings = services.AddGlobalSettingsServices(Configuration); - services.Configure(Configuration.GetSection("AdminSettings")); - - // Data Protection - services.AddCustomDataProtectionServices(Environment, globalSettings); - - // Stripe Billing - StripeConfiguration.ApiKey = globalSettings.StripeApiKey; - - // Repositories - services.AddSqlServerRepositories(globalSettings); - - // Context - services.AddScoped(); - - // Identity - services.AddPasswordlessIdentityServices(globalSettings); - services.Configure(options => + options.ValidationInterval = TimeSpan.FromMinutes(5); + }); + if (globalSettings.SelfHosted) + { + services.ConfigureApplicationCookie(options => { - options.ValidationInterval = TimeSpan.FromMinutes(5); + options.Cookie.Path = "/admin"; }); - if (globalSettings.SelfHosted) - { - services.ConfigureApplicationCookie(options => - { - options.Cookie.Path = "/admin"; - }); - } - - // Services - services.AddBaseServices(); - services.AddDefaultServices(globalSettings); - - #if OSS - services.AddOosServices(); - #else - services.AddCommCoreServices(); - #endif - - // Mvc - services.AddMvc(config => - { - config.Filters.Add(new LoggingExceptionHandlerFilterAttribute()); - }); - services.Configure(options => options.LowercaseUrls = true); - - // Jobs service - Jobs.JobsHostedService.AddJobsServices(services, globalSettings.SelfHosted); - services.AddHostedService(); - if (globalSettings.SelfHosted) - { - services.AddHostedService(); - } - else - { - if (CoreHelpers.SettingHasValue(globalSettings.Storage.ConnectionString)) - { - services.AddHostedService(); - } - else if (CoreHelpers.SettingHasValue(globalSettings.Amazon?.AccessKeySecret)) - { - services.AddHostedService(); - } - if (CoreHelpers.SettingHasValue(globalSettings.Mail.ConnectionString)) - { - services.AddHostedService(); - } - } } - public void Configure( - IApplicationBuilder app, - IWebHostEnvironment env, - IHostApplicationLifetime appLifetime, - GlobalSettings globalSettings) + // Services + services.AddBaseServices(globalSettings); + services.AddDefaultServices(globalSettings); + +#if OSS + services.AddOosServices(); +#else + services.AddCommercialCoreServices(); +#endif + + // Mvc + services.AddMvc(config => { - app.UseSerilog(env, appLifetime, globalSettings); + config.Filters.Add(new LoggingExceptionHandlerFilterAttribute()); + }); + services.Configure(options => options.LowercaseUrls = true); - // Add general security headers - app.UseMiddleware(); - - if (globalSettings.SelfHosted) + // Jobs service + Jobs.JobsHostedService.AddJobsServices(services, globalSettings.SelfHosted); + services.AddHostedService(); + if (globalSettings.SelfHosted) + { + services.AddHostedService(); + } + else + { + if (CoreHelpers.SettingHasValue(globalSettings.Storage.ConnectionString)) { - app.UsePathBase("/admin"); - app.UseForwardedHeaders(globalSettings); + services.AddHostedService(); } - - if (env.IsDevelopment()) + else if (CoreHelpers.SettingHasValue(globalSettings.Amazon?.AccessKeySecret)) { - app.UseDeveloperExceptionPage(); + services.AddHostedService(); } - else + if (CoreHelpers.SettingHasValue(globalSettings.Mail.ConnectionString)) { - app.UseExceptionHandler("/error"); + services.AddHostedService(); } - - app.UseStaticFiles(); - app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); - app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute()); } } + + public void Configure( + IApplicationBuilder app, + IWebHostEnvironment env, + IHostApplicationLifetime appLifetime, + GlobalSettings globalSettings) + { + app.UseSerilog(env, appLifetime, globalSettings); + + // Add general security headers + app.UseMiddleware(); + + if (globalSettings.SelfHosted) + { + app.UsePathBase("/admin"); + app.UseForwardedHeaders(globalSettings); + } + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + app.UseExceptionHandler("/error"); + } + + app.UseStaticFiles(); + app.UseRouting(); + app.UseAuthentication(); + app.UseAuthorization(); + app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute()); + } } diff --git a/src/Admin/TagHelpers/ActivePageTagHelper.cs b/src/Admin/TagHelpers/ActivePageTagHelper.cs index 208c19dff..a148e3cdf 100644 --- a/src/Admin/TagHelpers/ActivePageTagHelper.cs +++ b/src/Admin/TagHelpers/ActivePageTagHelper.cs @@ -1,76 +1,73 @@ -using System; -using System.Linq; -using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Bit.Admin.TagHelpers +namespace Bit.Admin.TagHelpers; + +[HtmlTargetElement("li", Attributes = ActiveControllerName)] +[HtmlTargetElement("li", Attributes = ActiveActionName)] +public class ActivePageTagHelper : TagHelper { - [HtmlTargetElement("li", Attributes = ActiveControllerName)] - [HtmlTargetElement("li", Attributes = ActiveActionName)] - public class ActivePageTagHelper : TagHelper + private const string ActiveControllerName = "active-controller"; + private const string ActiveActionName = "active-action"; + + private readonly IHtmlGenerator _generator; + + public ActivePageTagHelper(IHtmlGenerator generator) { - private const string ActiveControllerName = "active-controller"; - private const string ActiveActionName = "active-action"; + _generator = generator; + } - private readonly IHtmlGenerator _generator; + [HtmlAttributeNotBound] + [ViewContext] + public ViewContext ViewContext { get; set; } + [HtmlAttributeName(ActiveControllerName)] + public string ActiveController { get; set; } + [HtmlAttributeName(ActiveActionName)] + public string ActiveAction { get; set; } - public ActivePageTagHelper(IHtmlGenerator generator) + public override void Process(TagHelperContext context, TagHelperOutput output) + { + if (context == null) { - _generator = generator; + throw new ArgumentNullException(nameof(context)); } - [HtmlAttributeNotBound] - [ViewContext] - public ViewContext ViewContext { get; set; } - [HtmlAttributeName(ActiveControllerName)] - public string ActiveController { get; set; } - [HtmlAttributeName(ActiveActionName)] - public string ActiveAction { get; set; } - - public override void Process(TagHelperContext context, TagHelperOutput output) + if (output == null) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (output == null) - { - throw new ArgumentNullException(nameof(output)); - } - - if (ActiveAction == null && ActiveController == null) - { - return; - } - - var descriptor = ViewContext.ActionDescriptor as ControllerActionDescriptor; - if (descriptor == null) - { - return; - } - - var controllerMatch = ActiveMatch(ActiveController, descriptor.ControllerName); - var actionMatch = ActiveMatch(ActiveAction, descriptor.ActionName); - if (controllerMatch && actionMatch) - { - var classValue = "active"; - if (output.Attributes["class"] != null) - { - classValue += " " + output.Attributes["class"].Value; - output.Attributes.Remove(output.Attributes["class"]); - } - - output.Attributes.Add("class", classValue); - } + throw new ArgumentNullException(nameof(output)); } - private bool ActiveMatch(string route, string descriptor) + if (ActiveAction == null && ActiveController == null) { - return route == null || route == "*" || - route.Split(',').Any(c => c.Trim().ToLower() == descriptor.ToLower()); + return; + } + + var descriptor = ViewContext.ActionDescriptor as ControllerActionDescriptor; + if (descriptor == null) + { + return; + } + + var controllerMatch = ActiveMatch(ActiveController, descriptor.ControllerName); + var actionMatch = ActiveMatch(ActiveAction, descriptor.ActionName); + if (controllerMatch && actionMatch) + { + var classValue = "active"; + if (output.Attributes["class"] != null) + { + classValue += " " + output.Attributes["class"].Value; + output.Attributes.Remove(output.Attributes["class"]); + } + + output.Attributes.Add("class", classValue); } } + + private bool ActiveMatch(string route, string descriptor) + { + return route == null || route == "*" || + route.Split(',').Any(c => c.Trim().ToLower() == descriptor.ToLower()); + } } diff --git a/src/Admin/TagHelpers/OptionSelectedTagHelper.cs b/src/Admin/TagHelpers/OptionSelectedTagHelper.cs index fa696fed4..3dc9562a0 100644 --- a/src/Admin/TagHelpers/OptionSelectedTagHelper.cs +++ b/src/Admin/TagHelpers/OptionSelectedTagHelper.cs @@ -1,44 +1,42 @@ -using System; -using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; -namespace Bit.Admin.TagHelpers +namespace Bit.Admin.TagHelpers; + +[HtmlTargetElement("option", Attributes = SelectedName)] +public class OptionSelectedTagHelper : TagHelper { - [HtmlTargetElement("option", Attributes = SelectedName)] - public class OptionSelectedTagHelper : TagHelper + private const string SelectedName = "asp-selected"; + + private readonly IHtmlGenerator _generator; + + public OptionSelectedTagHelper(IHtmlGenerator generator) { - private const string SelectedName = "asp-selected"; + _generator = generator; + } - private readonly IHtmlGenerator _generator; + [HtmlAttributeName(SelectedName)] + public bool Selected { get; set; } - public OptionSelectedTagHelper(IHtmlGenerator generator) + public override void Process(TagHelperContext context, TagHelperOutput output) + { + if (context == null) { - _generator = generator; + throw new ArgumentNullException(nameof(context)); } - [HtmlAttributeName(SelectedName)] - public bool Selected { get; set; } - - public override void Process(TagHelperContext context, TagHelperOutput output) + if (output == null) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } + throw new ArgumentNullException(nameof(output)); + } - if (output == null) - { - throw new ArgumentNullException(nameof(output)); - } - - if (Selected) - { - output.Attributes.Add("selected", "selected"); - } - else - { - output.Attributes.RemoveAll("selected"); - } + if (Selected) + { + output.Attributes.Add("selected", "selected"); + } + else + { + output.Attributes.RemoveAll("selected"); } } } diff --git a/src/Admin/Views/Home/Index.cshtml b/src/Admin/Views/Home/Index.cshtml index 3de2f74c8..9e2ddd111 100644 --- a/src/Admin/Views/Home/Index.cshtml +++ b/src/Admin/Views/Home/Index.cshtml @@ -1,4 +1,5 @@ -@model HomeModel +@using Bit.Admin.Controllers +@model HomeModel @{ ViewData["Title"] = "Dashboard"; } @@ -9,7 +10,7 @@ let loadedWebLatest = false; let loadedWebInstalled = false; - fetch('@Url.Action("GetLatestDockerHubVersion", new { repository = "web" })').then((response) => { + fetch('@Url.Action("GetLatestVersion", new { project = @ProjectType.Web })').then((response) => { return response.json(); }).then((version) => { document.getElementById('web-latest').innerText = version; @@ -19,7 +20,7 @@ } }); - fetch('@Url.Action("GetLatestDockerHubVersion", new { repository = "api" })').then((response) => { + fetch('@Url.Action("GetLatestVersion", new { project = @ProjectType.Core })').then((response) => { return response.json(); }).then((version) => { document.getElementById('server-latest').innerText = version; diff --git a/src/Admin/Views/Logs/Index.cshtml b/src/Admin/Views/Logs/Index.cshtml index 988f97f96..93eeb05e4 100644 --- a/src/Admin/Views/Logs/Index.cshtml +++ b/src/Admin/Views/Logs/Index.cshtml @@ -24,8 +24,8 @@ - + diff --git a/src/Admin/Views/Organizations/Connections.cshtml b/src/Admin/Views/Organizations/Connections.cshtml new file mode 100644 index 000000000..f1f8f4a8d --- /dev/null +++ b/src/Admin/Views/Organizations/Connections.cshtml @@ -0,0 +1,81 @@ +@model OrganizationViewModel +

Connections

+
+
+
+ + + + + + + + + + @if(!Model.Connections.Any()) + { + + + + } + else + { + @foreach(var connection in Model.Connections) + { + + + + + + } + } + +
TypeStatus
No results to list.
+ @if(connection.Type == OrganizationConnectionType.CloudBillingSync) + { + @:Billing Sync + } + + @if(@TempData["ConnectionError"] != null) + { + + @TempData["ConnectionError"] + + } + else + { + @if(connection.Enabled) + { + @:Enabled + } + else + { + @:Disabled + } + } + + @if(connection.Enabled) + { + @if(@TempData["ConnectionActivated"] != null && @TempData["ConnectionActivated"].ToString() == @Model.Organization.Id.ToString()) + { + @if(connection.Type.Equals(OrganizationConnectionType.CloudBillingSync)) + { + + } + } + else + { + @if(connection.Type.Equals(OrganizationConnectionType.CloudBillingSync)) + { + + Manually Sync + + } + } + } +
+
+
+
\ No newline at end of file diff --git a/src/Admin/Views/Organizations/Edit.cshtml b/src/Admin/Views/Organizations/Edit.cshtml index c154ea245..b77be0d72 100644 --- a/src/Admin/Views/Organizations/Edit.cshtml +++ b/src/Admin/Views/Organizations/Edit.cshtml @@ -27,11 +27,13 @@ document.getElementById('@(nameof(Model.UseDirectory))').checked = true; document.getElementById('@(nameof(Model.UseEvents))').checked = true; document.getElementById('@(nameof(Model.UsersGetPremium))').checked = true; + document.getElementById('@(nameof(Model.UseCustomPermissions))').checked = false; document.getElementById('@(nameof(Model.UseTotp))').checked = true; document.getElementById('@(nameof(Model.Use2fa))').checked = true; document.getElementById('@(nameof(Model.UseApi))').checked = true; document.getElementById('@(nameof(Model.SelfHost))').checked = false; document.getElementById('@(nameof(Model.UseResetPassword))').checked = false; + document.getElementById('@(nameof(Model.UseScim))').checked = false; // Licensing document.getElementById('@(nameof(Model.LicenseKey))').value = '@Model.RandomLicenseKey'; document.getElementById('@(nameof(Model.ExpirationDate))').value = '@Model.FourteenDayExpirationDate'; @@ -60,11 +62,13 @@ document.getElementById('@(nameof(Model.UseDirectory))').checked = true; document.getElementById('@(nameof(Model.UseEvents))').checked = true; document.getElementById('@(nameof(Model.UsersGetPremium))').checked = true; + document.getElementById('@(nameof(Model.UseCustomPermissions))').checked = true; document.getElementById('@(nameof(Model.UseTotp))').checked = true; document.getElementById('@(nameof(Model.Use2fa))').checked = true; document.getElementById('@(nameof(Model.UseApi))').checked = true; document.getElementById('@(nameof(Model.SelfHost))').checked = true; document.getElementById('@(nameof(Model.UseResetPassword))').checked = true; + document.getElementById('@(nameof(Model.UseScim))').checked = true; // Licensing document.getElementById('@(nameof(Model.LicenseKey))').value = '@Model.RandomLicenseKey'; document.getElementById('@(nameof(Model.ExpirationDate))').value = '@Model.FourteenDayExpirationDate'; @@ -187,54 +191,78 @@

Features

-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - +
+
+

General

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+

Password Manager

+
+ + +
+
+ + +
+
+
+

Secrets Manager

+
+ + +
+
+

Licensing

diff --git a/src/Admin/Views/Organizations/View.cshtml b/src/Admin/Views/Organizations/View.cshtml index b7d8e00a2..38d58e61a 100644 --- a/src/Admin/Views/Organizations/View.cshtml +++ b/src/Admin/Views/Organizations/View.cshtml @@ -1,4 +1,5 @@ -@model OrganizationViewModel +@inject Bit.Core.Settings.GlobalSettings GlobalSettings +@model OrganizationViewModel @{ ViewData["Title"] = "Organization: " + Model.Organization.Name; } @@ -7,6 +8,10 @@

Information

@await Html.PartialAsync("_ViewInformation", Model) +@if(GlobalSettings.SelfHosted) +{ + @await Html.PartialAsync("Connections", Model) +}
diff --git a/src/Admin/Views/Organizations/_ViewInformation.cshtml b/src/Admin/Views/Organizations/_ViewInformation.cshtml index 3c5a5ca8a..24e69d298 100644 --- a/src/Admin/Views/Organizations/_ViewInformation.cshtml +++ b/src/Admin/Views/Organizations/_ViewInformation.cshtml @@ -11,7 +11,7 @@
Users
- @Model.UserCount / @(Model.Organization.Seats?.ToString() ?? "-") + @Model.OccupiedSeatCount / @(Model.Organization.Seats?.ToString() ?? "-") (@Model.UserInvitedCount / @Model.UserAcceptedCount / @Model.UserConfirmedCount) diff --git a/src/Admin/Views/Shared/_Layout.cshtml b/src/Admin/Views/Shared/_Layout.cshtml index 9165424dc..395409133 100644 --- a/src/Admin/Views/Shared/_Layout.cshtml +++ b/src/Admin/Views/Shared/_Layout.cshtml @@ -66,6 +66,9 @@ Manage Tax Rates + + Manage Stripe Subscriptions +