mirror of
https://github.com/bitwarden/server
synced 2025-12-18 01:03:17 +00:00
Merge remote-tracking branch 'origin/master' into feature/sm-billing
This commit is contained in:
10
.github/workflows/automatic-issue-responses.yml
vendored
10
.github/workflows/automatic-issue-responses.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
# Feature request
|
||||
- if: github.event.label.name == 'feature-request'
|
||||
name: Feature request
|
||||
uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
|
||||
uses: peter-evans/close-issue@1373cadf1f0c96c1420bc000cfba2273ea307fd1 # v2.2.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.
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
# Intended behavior
|
||||
- if: github.event.label.name == 'intended-behavior'
|
||||
name: Intended behaviour
|
||||
uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
|
||||
uses: peter-evans/close-issue@1373cadf1f0c96c1420bc000cfba2273ea307fd1 # v2.2.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.
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
# Customer support request
|
||||
- if: github.event.label.name == 'customer-support'
|
||||
name: Customer Support request
|
||||
uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
|
||||
uses: peter-evans/close-issue@1373cadf1f0c96c1420bc000cfba2273ea307fd1 # v2.2.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.
|
||||
@@ -49,14 +49,14 @@ jobs:
|
||||
# Resolved
|
||||
- if: github.event.label.name == 'resolved'
|
||||
name: Resolved
|
||||
uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
|
||||
uses: peter-evans/close-issue@1373cadf1f0c96c1420bc000cfba2273ea307fd1 # v2.2.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
|
||||
uses: peter-evans/close-issue@1373cadf1f0c96c1420bc000cfba2273ea307fd1 # v2.2.0
|
||||
with:
|
||||
comment: |
|
||||
As we haven’t heard from you about this problem in some time, this issue will now be closed.
|
||||
|
||||
52
.github/workflows/build.yml
vendored
52
.github/workflows/build.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
|
||||
- name: Install cloc
|
||||
run: |
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
|
||||
- name: Verify Format
|
||||
run: dotnet format --verify-no-changes
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
|
||||
steps:
|
||||
- name: Set up dotnet
|
||||
uses: actions/setup-dotnet@9211491ffb35dd6a6657ca4f45d43dfe6e97c829 # v2.0.0
|
||||
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0
|
||||
with:
|
||||
dotnet-version: "6.0.x"
|
||||
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
echo "GitHub event: $GITHUB_EVENT"
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore --locked-mode
|
||||
@@ -131,10 +131,10 @@ jobs:
|
||||
dotnet: true
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
|
||||
with:
|
||||
cache: "npm"
|
||||
cache-dependency-path: "**/package-lock.json"
|
||||
@@ -178,7 +178,7 @@ jobs:
|
||||
ls -atlh ../../../
|
||||
|
||||
- name: Upload project artifact
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
||||
with:
|
||||
name: ${{ matrix.project_name }}.zip
|
||||
path: ${{ matrix.base_path }}/${{ matrix.project_name }}/${{ matrix.project_name }}.zip
|
||||
@@ -255,7 +255,7 @@ jobs:
|
||||
dotnet: true
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
|
||||
- name: Check Branch to Publish
|
||||
env:
|
||||
@@ -272,7 +272,7 @@ jobs:
|
||||
|
||||
########## ACRs ##########
|
||||
- name: Login to Azure - QA Subscription
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }}
|
||||
|
||||
@@ -280,7 +280,7 @@ jobs:
|
||||
run: az acr login -n bitwardenqa
|
||||
|
||||
- name: Login to Azure - PROD Subscription
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
||||
|
||||
@@ -288,13 +288,13 @@ jobs:
|
||||
run: az acr login -n bitwardenprod
|
||||
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
- name: Retrieve github PAT secrets
|
||||
id: retrieve-secret-pat
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
with:
|
||||
keyvault: "bitwarden-ci"
|
||||
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
|
||||
@@ -302,7 +302,7 @@ jobs:
|
||||
- name: Retrieve secrets
|
||||
if: ${{ env.is_publish_branch == 'true' }}
|
||||
id: retrieve-secrets
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
with:
|
||||
keyvault: "bitwarden-ci"
|
||||
secrets: "docker-password,
|
||||
@@ -319,7 +319,7 @@ jobs:
|
||||
|
||||
- name: Setup Docker Content Trust (DCT)
|
||||
if: ${{ env.is_publish_branch == 'true' }}
|
||||
uses: bitwarden/gh-actions/setup-docker-trust@f955298c7a982b3fb5dbb73afd582c584fd5beec
|
||||
uses: bitwarden/gh-actions/setup-docker-trust@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
with:
|
||||
azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
azure-keyvault-name: "bitwarden-ci"
|
||||
@@ -351,7 +351,7 @@ jobs:
|
||||
|
||||
- name: Get build artifact
|
||||
if: ${{ matrix.dotnet }}
|
||||
uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 # v3.0.0
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: ${{ matrix.project_name }}.zip
|
||||
|
||||
@@ -363,7 +363,7 @@ jobs:
|
||||
-d ${{ matrix.base_path }}/${{ matrix.project_name }}/obj/build-output/publish
|
||||
|
||||
- name: Build Docker image
|
||||
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 # v3.2.0
|
||||
uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # v3.3.1
|
||||
with:
|
||||
context: ${{ matrix.base_path }}/${{ matrix.project_name }}
|
||||
file: ${{ matrix.base_path }}/${{ matrix.project_name }}/Dockerfile
|
||||
@@ -393,12 +393,12 @@ jobs:
|
||||
needs: build-docker
|
||||
steps:
|
||||
- name: Set up dotnet
|
||||
uses: actions/setup-dotnet@9211491ffb35dd6a6657ca4f45d43dfe6e97c829 # v3.0.3
|
||||
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0
|
||||
with:
|
||||
dotnet-version: "6.0.x"
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
|
||||
- name: Restore
|
||||
run: dotnet tool restore
|
||||
@@ -431,7 +431,7 @@ jobs:
|
||||
|
||||
- name: Upload Docker stub artifact
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/rc' || github.ref == 'refs/heads/hotfix-rc'
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
||||
with:
|
||||
name: docker-stub.zip
|
||||
path: docker-stub.zip
|
||||
@@ -439,7 +439,7 @@ jobs:
|
||||
|
||||
- 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 # v3.0.0
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
||||
with:
|
||||
name: docker-stub-sha256.txt
|
||||
path: docker-stub-sha256.txt
|
||||
@@ -465,7 +465,7 @@ jobs:
|
||||
GLOBALSETTINGS__SQLSERVER__CONNECTIONSTRING: "placeholder"
|
||||
|
||||
- name: Upload Swagger artifact
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
||||
with:
|
||||
name: swagger.json
|
||||
path: swagger.json
|
||||
@@ -490,7 +490,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
|
||||
- name: Print environment
|
||||
run: |
|
||||
@@ -509,7 +509,7 @@ jobs:
|
||||
|
||||
- name: Upload project artifact Windows
|
||||
if: ${{ contains(matrix.target, 'win') == true }}
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
||||
with:
|
||||
name: MsSqlMigratorUtility-${{ matrix.target }}
|
||||
path: util/MsSqlMigratorUtility/obj/build-output/publish/MsSqlMigratorUtility.exe
|
||||
@@ -517,7 +517,7 @@ jobs:
|
||||
|
||||
- name: Upload project artifact
|
||||
if: ${{ contains(matrix.target, 'win') == false }}
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
||||
with:
|
||||
name: MsSqlMigratorUtility-${{ matrix.target }}
|
||||
path: util/MsSqlMigratorUtility/obj/build-output/publish/MsSqlMigratorUtility
|
||||
@@ -579,14 +579,14 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Login to Azure - CI subscription
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
if: failure()
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
if: failure()
|
||||
with:
|
||||
keyvault: "bitwarden-ci"
|
||||
|
||||
6
.github/workflows/cleanup-after-pr.yml
vendored
6
.github/workflows/cleanup-after-pr.yml
vendored
@@ -11,11 +11,11 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
|
||||
########## ACR ##########
|
||||
- name: Login to Azure - QA Subscription
|
||||
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a # v1.3.0
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }}
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
run: az acr login -n bitwardenqa
|
||||
|
||||
- name: Login to Azure - PROD Subscription
|
||||
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a # v1.3.0
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
||||
|
||||
@@ -85,14 +85,14 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Login to Azure - CI subscription
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
if: failure()
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
if: failure()
|
||||
with:
|
||||
keyvault: "bitwarden-ci"
|
||||
|
||||
8
.github/workflows/database.yml
vendored
8
.github/workflows/database.yml
vendored
@@ -25,10 +25,10 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.5.2
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
|
||||
- name: Set up dotnet
|
||||
uses: actions/setup-dotnet@9211491ffb35dd6a6657ca4f45d43dfe6e97c829 # v3.0.3
|
||||
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0
|
||||
with:
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
shell: pwsh
|
||||
|
||||
- name: Upload DACPAC
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.1.2
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
||||
with:
|
||||
name: sql.dacpac
|
||||
path: Sql.dacpac
|
||||
@@ -70,7 +70,7 @@ jobs:
|
||||
shell: pwsh
|
||||
|
||||
- name: Upload Report
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.1.2
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
||||
with:
|
||||
name: report.xml
|
||||
path: |
|
||||
|
||||
4
.github/workflows/infrastructure-tests.yml
vendored
4
.github/workflows/infrastructure-tests.yml
vendored
@@ -38,10 +38,10 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
|
||||
- name: Set up dotnet
|
||||
uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # v3.0.3
|
||||
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0
|
||||
with:
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
|
||||
2
.github/workflows/protect-files.yml
vendored
2
.github/workflows/protect-files.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
label: "DB-migrations-changed"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
|
||||
24
.github/workflows/release.yml
vendored
24
.github/workflows/release.yml
vendored
@@ -34,11 +34,11 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
|
||||
- name: Check Release Version
|
||||
id: version
|
||||
uses: bitwarden/gh-actions/release-version-check@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b
|
||||
uses: bitwarden/gh-actions/release-version-check@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
with:
|
||||
release-type: ${{ github.event.inputs.release_type }}
|
||||
project-type: dotnet
|
||||
@@ -87,7 +87,7 @@ jobs:
|
||||
|
||||
- name: Download latest Release ${{ matrix.name }} asset
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
uses: bitwarden/gh-actions/download-artifacts@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b
|
||||
uses: bitwarden/gh-actions/download-artifacts@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
|
||||
- name: Download latest Release ${{ matrix.name }} asset
|
||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||
uses: bitwarden/gh-actions/download-artifacts@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b
|
||||
uses: bitwarden/gh-actions/download-artifacts@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
@@ -104,7 +104,7 @@ jobs:
|
||||
artifacts: ${{ matrix.name }}.zip
|
||||
|
||||
- name: Login to Azure - CI subscription
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
@@ -129,12 +129,12 @@ jobs:
|
||||
echo "publish-profile=$publish_profile" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
||||
|
||||
- name: Deploy App
|
||||
uses: azure/webapps-deploy@016bdd3f9b7cec60310bcf9da98f671628795644 # v2.2.4
|
||||
uses: azure/webapps-deploy@fb8292eb575db1bb18a90627e8959cd51dbb355c # v2.2.10
|
||||
with:
|
||||
app-name: ${{ steps.retrieve-secrets.outputs.webapp-name }}
|
||||
publish-profile: ${{ steps.retrieve-secrets.outputs.publish-profile }}
|
||||
@@ -229,7 +229,7 @@ jobs:
|
||||
echo "Github Release Option: $RELEASE_OPTION"
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
|
||||
- name: Setup project name
|
||||
id: setup
|
||||
@@ -243,7 +243,7 @@ jobs:
|
||||
- name: Setup DCT
|
||||
id: setup-dct
|
||||
if: matrix.origin_docker_repo == 'bitwarden'
|
||||
uses: bitwarden/gh-actions/setup-docker-trust@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b
|
||||
uses: bitwarden/gh-actions/setup-docker-trust@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
with:
|
||||
azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
azure-keyvault-name: "bitwarden-ci"
|
||||
@@ -286,7 +286,7 @@ jobs:
|
||||
|
||||
########## ACR PROD ##########
|
||||
- name: Login to Azure - PROD Subscription
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
||||
|
||||
@@ -340,7 +340,7 @@ jobs:
|
||||
steps:
|
||||
- name: Download latest Release docker-stub
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
uses: bitwarden/gh-actions/download-artifacts@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b
|
||||
uses: bitwarden/gh-actions/download-artifacts@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
@@ -351,7 +351,7 @@ jobs:
|
||||
|
||||
- name: Download latest Release docker-stub
|
||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||
uses: bitwarden/gh-actions/download-artifacts@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b
|
||||
uses: bitwarden/gh-actions/download-artifacts@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
|
||||
2
.github/workflows/stale-bot.yml
vendored
2
.github/workflows/stale-bot.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: 'Run stale action'
|
||||
uses: actions/stale@3cc123766321e9f15a6676375c154ccffb12a358 # v5.0.0
|
||||
uses: actions/stale@f7176fd3007623b69d27091f9b9d4ab7995f0a06 # v5.2.1
|
||||
with:
|
||||
stale-issue-label: 'needs-reply'
|
||||
stale-pr-label: 'needs-changes'
|
||||
|
||||
4
.github/workflows/stop-staging-slots.yml
vendored
4
.github/workflows/stop-staging-slots.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
echo "name_lower=$NAME_LOWER" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
echo "webapp-name=$webapp_name" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Login to Azure
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
||||
|
||||
|
||||
10
.github/workflows/version-bump.yml
vendored
10
.github/workflows/version-bump.yml
vendored
@@ -14,22 +14,22 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout Branch
|
||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
|
||||
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
with:
|
||||
keyvault: "bitwarden-ci"
|
||||
secrets: "github-gpg-private-key, github-gpg-private-key-passphrase"
|
||||
|
||||
- name: Import GPG key
|
||||
uses: crazy-max/ghaction-import-gpg@111c56156bcc6918c056dbef52164cfa583dc549 # v5.2.0
|
||||
uses: crazy-max/ghaction-import-gpg@72b6676b71ab476b77e676928516f6982eef7a41 # v5.3.0
|
||||
with:
|
||||
gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }}
|
||||
passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }}
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
run: git switch -c version_bump_${{ github.event.inputs.version_number }}
|
||||
|
||||
- name: Bump Version - Props
|
||||
uses: bitwarden/gh-actions/version-bump@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b
|
||||
uses: bitwarden/gh-actions/version-bump@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
with:
|
||||
version: ${{ github.event.inputs.version_number }}
|
||||
file_path: "Directory.Build.props"
|
||||
|
||||
2
.github/workflows/workflow-linter.yml
vendored
2
.github/workflows/workflow-linter.yml
vendored
@@ -8,4 +8,4 @@ on:
|
||||
|
||||
jobs:
|
||||
call-workflow:
|
||||
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b
|
||||
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@74f4ac01c9abe0a7331c9a5de822a558fd4a4710
|
||||
|
||||
@@ -52,7 +52,7 @@ public class ProjectAuthorizationHandler : AuthorizationHandler<ProjectOperation
|
||||
{
|
||||
AccessClientType.NoAccessCheck => true,
|
||||
AccessClientType.User => true,
|
||||
AccessClientType.ServiceAccount => false,
|
||||
AccessClientType.ServiceAccount => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
@@ -67,10 +67,6 @@ public class ProjectAuthorizationHandler : AuthorizationHandler<ProjectOperation
|
||||
{
|
||||
var (accessClient, userId) =
|
||||
await _accessClientQuery.GetAccessClientAsync(context.User, resource.OrganizationId);
|
||||
if (accessClient == AccessClientType.ServiceAccount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var access = await _projectRepository.AccessToProjectAsync(resource.Id, userId, accessClient);
|
||||
|
||||
|
||||
@@ -74,7 +74,8 @@ public class SecretAuthorizationHandler : AuthorizationHandler<SecretOperationRe
|
||||
AccessClientType.NoAccessCheck => true,
|
||||
AccessClientType.User => (await _projectRepository.AccessToProjectAsync(project!.Id, userId, accessClient))
|
||||
.Write,
|
||||
AccessClientType.ServiceAccount => false,
|
||||
AccessClientType.ServiceAccount => (await _projectRepository.AccessToProjectAsync(project!.Id, userId, accessClient))
|
||||
.Write,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
@@ -84,6 +85,7 @@ public class SecretAuthorizationHandler : AuthorizationHandler<SecretOperationRe
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task CanUpdateSecretAsync(AuthorizationHandlerContext context,
|
||||
SecretOperationRequirement requirement, Secret resource)
|
||||
{
|
||||
@@ -106,12 +108,10 @@ public class SecretAuthorizationHandler : AuthorizationHandler<SecretOperationRe
|
||||
hasAccess = true;
|
||||
break;
|
||||
case AccessClientType.User:
|
||||
var newProject = resource.Projects?.FirstOrDefault();
|
||||
var access = (await _secretRepository.AccessToSecretAsync(resource.Id, userId, accessClient)).Write;
|
||||
var accessToNew = newProject != null &&
|
||||
(await _projectRepository.AccessToProjectAsync(newProject.Id, userId, accessClient))
|
||||
.Write;
|
||||
hasAccess = access && accessToNew;
|
||||
hasAccess = await GetAccessToUpdateSecretAsync(resource, userId, accessClient);
|
||||
break;
|
||||
case AccessClientType.ServiceAccount:
|
||||
hasAccess = await GetAccessToUpdateSecretAsync(resource, userId, accessClient);
|
||||
break;
|
||||
default:
|
||||
hasAccess = false;
|
||||
@@ -129,11 +129,6 @@ public class SecretAuthorizationHandler : AuthorizationHandler<SecretOperationRe
|
||||
{
|
||||
var (accessClient, userId) = await _accessClientQuery.GetAccessClientAsync(context.User, resource.OrganizationId);
|
||||
|
||||
if (accessClient == AccessClientType.ServiceAccount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var access = await _secretRepository.AccessToSecretAsync(resource.Id, userId, accessClient);
|
||||
|
||||
if (access.Write)
|
||||
@@ -141,4 +136,14 @@ public class SecretAuthorizationHandler : AuthorizationHandler<SecretOperationRe
|
||||
context.Succeed(requirement);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> GetAccessToUpdateSecretAsync(Secret resource, Guid userId, AccessClientType accessClient)
|
||||
{
|
||||
var newProject = resource.Projects?.FirstOrDefault();
|
||||
var access = (await _secretRepository.AccessToSecretAsync(resource.Id, userId, accessClient)).Write;
|
||||
var accessToNew = newProject != null &&
|
||||
(await _projectRepository.AccessToProjectAsync(newProject.Id, userId, accessClient))
|
||||
.Write;
|
||||
return access && accessToNew;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Identity;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.SecretsManager.Commands.Projects.Interfaces;
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
using Bit.Core.SecretsManager.Repositories;
|
||||
@@ -10,31 +13,58 @@ public class CreateProjectCommand : ICreateProjectCommand
|
||||
private readonly IAccessPolicyRepository _accessPolicyRepository;
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly IProjectRepository _projectRepository;
|
||||
private readonly ICurrentContext _currentContext;
|
||||
|
||||
|
||||
public CreateProjectCommand(
|
||||
IAccessPolicyRepository accessPolicyRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IProjectRepository projectRepository)
|
||||
IProjectRepository projectRepository,
|
||||
ICurrentContext currentContext)
|
||||
{
|
||||
_accessPolicyRepository = accessPolicyRepository;
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_projectRepository = projectRepository;
|
||||
_currentContext = currentContext;
|
||||
}
|
||||
|
||||
public async Task<Project> CreateAsync(Project project, Guid userId)
|
||||
public async Task<Project> CreateAsync(Project project, Guid id, ClientType clientType)
|
||||
{
|
||||
if (clientType != ClientType.User && clientType != ClientType.ServiceAccount)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var createdProject = await _projectRepository.CreateAsync(project);
|
||||
|
||||
var orgUser = await _organizationUserRepository.GetByOrganizationAsync(createdProject.OrganizationId,
|
||||
userId);
|
||||
var accessPolicy = new UserProjectAccessPolicy()
|
||||
if (clientType == ClientType.User)
|
||||
{
|
||||
OrganizationUserId = orgUser.Id,
|
||||
GrantedProjectId = createdProject.Id,
|
||||
Read = true,
|
||||
Write = true,
|
||||
};
|
||||
await _accessPolicyRepository.CreateManyAsync(new List<BaseAccessPolicy> { accessPolicy });
|
||||
var orgUser = await _organizationUserRepository.GetByOrganizationAsync(createdProject.OrganizationId, id);
|
||||
|
||||
var accessPolicy = new UserProjectAccessPolicy()
|
||||
{
|
||||
OrganizationUserId = orgUser.Id,
|
||||
GrantedProjectId = createdProject.Id,
|
||||
Read = true,
|
||||
Write = true,
|
||||
};
|
||||
|
||||
await _accessPolicyRepository.CreateManyAsync(new List<BaseAccessPolicy> { accessPolicy });
|
||||
|
||||
}
|
||||
else if (clientType == ClientType.ServiceAccount)
|
||||
{
|
||||
var serviceAccountProjectAccessPolicy = new ServiceAccountProjectAccessPolicy()
|
||||
{
|
||||
ServiceAccountId = id,
|
||||
GrantedProjectId = createdProject.Id,
|
||||
Read = true,
|
||||
Write = true,
|
||||
};
|
||||
|
||||
await _accessPolicyRepository.CreateManyAsync(new List<BaseAccessPolicy> { serviceAccountProjectAccessPolicy });
|
||||
}
|
||||
|
||||
return createdProject;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public class DeleteProjectCommand : IDeleteProjectCommand
|
||||
foreach (var project in projects)
|
||||
{
|
||||
var access = await _projectRepository.AccessToProjectAsync(project.Id, userId, accessClient);
|
||||
if (!access.Write || accessClient == AccessClientType.ServiceAccount)
|
||||
if (!access.Write)
|
||||
{
|
||||
results.Add(new Tuple<Project, string>(project, "access denied"));
|
||||
}
|
||||
|
||||
@@ -2783,7 +2783,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
|
||||
@@ -2786,7 +2786,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2794,7 +2794,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2806,9 +2806,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
<PropertyGroup Condition=" '$(RunConfiguration)' == 'Sso' " />
|
||||
<PropertyGroup Condition=" '$(RunConfiguration)' == 'Sso-SelfHost' " />
|
||||
<ItemGroup>
|
||||
<!-- This is a transitive dependency to Sustainsys.Saml2.AspNetCore2 -->
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.1.22" />
|
||||
|
||||
<PackageReference Include="Sustainsys.Saml2.AspNetCore2" Version="2.9.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
14
bitwarden_license/src/Sso/package-lock.json
generated
14
bitwarden_license/src/Sso/package-lock.json
generated
@@ -17,7 +17,7 @@
|
||||
"jquery": "3.5.1",
|
||||
"merge-stream": "2.0.0",
|
||||
"popper.js": "1.16.1",
|
||||
"sass": "^1.49.7"
|
||||
"sass": "1.49.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
@@ -3924,9 +3924,9 @@
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
@@ -8158,9 +8158,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"anymatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"normalize-path": "^3.0.0",
|
||||
|
||||
@@ -16,6 +16,6 @@
|
||||
"jquery": "3.5.1",
|
||||
"merge-stream": "2.0.0",
|
||||
"popper.js": "1.16.1",
|
||||
"sass": "^1.49.7"
|
||||
"sass": "1.49.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,19 @@
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net6.0": {
|
||||
"Microsoft.AspNetCore.Http": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.1.22, )",
|
||||
"resolved": "2.1.22",
|
||||
"contentHash": "+Blk++1JWqghbl8+3azQmKhiNZA5wAepL9dY2I6KVmu2Ri07MAcvAVC888qUvO7yd7xgRgZOMfihezKg14O/2A==",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"Sustainsys.Saml2.AspNetCore2": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.9.0, )",
|
||||
@@ -418,18 +431,6 @@
|
||||
"resolved": "3.1.32",
|
||||
"contentHash": "MPL4iVyiaRxnOUY5VATHjvhDWaAEFb77KFiUxVRklv3Z3v+STofUr1UG/aCt1O9cgN7FVTDaC5A7U+zsLub8Xg=="
|
||||
},
|
||||
"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",
|
||||
@@ -2945,7 +2946,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2953,7 +2954,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2965,9 +2966,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,11 @@ public class ProjectAuthorizationHandlerTests
|
||||
.ReturnsForAnyArgs(
|
||||
(AccessClientType.User, userId));
|
||||
break;
|
||||
case PermissionType.RunAsServiceAccountWithPermission:
|
||||
sutProvider.GetDependency<IAccessClientQuery>().GetAccessClientAsync(default, organizationId)
|
||||
.ReturnsForAnyArgs(
|
||||
(AccessClientType.ServiceAccount, userId));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(permissionType), permissionType, null);
|
||||
}
|
||||
@@ -103,7 +108,6 @@ public class ProjectAuthorizationHandlerTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(AccessClientType.ServiceAccount)]
|
||||
[BitAutoData(AccessClientType.Organization)]
|
||||
public async Task CanCreateProject_NotSupportedClientTypes_DoesNotSucceed(AccessClientType clientType,
|
||||
SutProvider<ProjectAuthorizationHandler> sutProvider, Project project, ClaimsPrincipal claimsPrincipal)
|
||||
@@ -125,6 +129,7 @@ public class ProjectAuthorizationHandlerTests
|
||||
[Theory]
|
||||
[BitAutoData(PermissionType.RunAsAdmin)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission)]
|
||||
public async Task CanCreateProject_Success(PermissionType permissionType,
|
||||
SutProvider<ProjectAuthorizationHandler> sutProvider, Project project, ClaimsPrincipal claimsPrincipal)
|
||||
{
|
||||
@@ -199,6 +204,8 @@ public class ProjectAuthorizationHandlerTests
|
||||
[Theory]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, true, false)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, false, false)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, true, false)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, false, false)]
|
||||
public async Task CanUpdateProject_ShouldNotSucceed(PermissionType permissionType, bool read, bool write,
|
||||
SutProvider<ProjectAuthorizationHandler> sutProvider, Project project, ClaimsPrincipal claimsPrincipal,
|
||||
Guid userId)
|
||||
@@ -221,6 +228,8 @@ public class ProjectAuthorizationHandlerTests
|
||||
[BitAutoData(PermissionType.RunAsAdmin, false, true)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, true, true)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, false, true)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, true, true)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, false, true)]
|
||||
public async Task CanUpdateProject_Success(PermissionType permissionType, bool read, bool write,
|
||||
SutProvider<ProjectAuthorizationHandler> sutProvider, Project project, ClaimsPrincipal claimsPrincipal,
|
||||
Guid userId)
|
||||
|
||||
@@ -41,6 +41,10 @@ public class SecretAuthorizationHandlerTests
|
||||
sutProvider.GetDependency<IAccessClientQuery>().GetAccessClientAsync(default, organizationId).ReturnsForAnyArgs(
|
||||
(clientType, userId));
|
||||
break;
|
||||
case PermissionType.RunAsServiceAccountWithPermission:
|
||||
sutProvider.GetDependency<IAccessClientQuery>().GetAccessClientAsync(default, organizationId).ReturnsForAnyArgs(
|
||||
(AccessClientType.ServiceAccount, userId));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(permissionType), permissionType, null);
|
||||
}
|
||||
@@ -105,7 +109,6 @@ public class SecretAuthorizationHandlerTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(AccessClientType.ServiceAccount)]
|
||||
[BitAutoData(AccessClientType.Organization)]
|
||||
public async Task CanCreateSecret_NotSupportedClientTypes_DoesNotSucceed(AccessClientType clientType,
|
||||
SutProvider<SecretAuthorizationHandler> sutProvider, Secret secret, Guid userId,
|
||||
@@ -114,7 +117,7 @@ public class SecretAuthorizationHandlerTests
|
||||
var requirement = SecretOperations.Create;
|
||||
SetupPermission(sutProvider, PermissionType.RunAsUserWithPermission, secret.OrganizationId, userId, clientType);
|
||||
sutProvider.GetDependency<IProjectRepository>()
|
||||
.AccessToProjectAsync(secret.Projects!.FirstOrDefault()!.Id, userId, default).Returns(
|
||||
.AccessToProjectAsync(secret.Projects!.FirstOrDefault()!.Id, userId, Arg.Any<AccessClientType>()).Returns(
|
||||
(true, true));
|
||||
var authzContext = new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement },
|
||||
claimsPrincipal, secret);
|
||||
@@ -182,6 +185,8 @@ public class SecretAuthorizationHandlerTests
|
||||
[Theory]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, true, false)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, false, false)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, true, false)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, false, false)]
|
||||
public async Task CanCreateSecret_DoesNotSucceed(PermissionType permissionType, bool read, bool write,
|
||||
SutProvider<SecretAuthorizationHandler> sutProvider, Secret secret,
|
||||
Guid userId,
|
||||
@@ -190,7 +195,7 @@ public class SecretAuthorizationHandlerTests
|
||||
var requirement = SecretOperations.Create;
|
||||
SetupPermission(sutProvider, permissionType, secret.OrganizationId, userId);
|
||||
sutProvider.GetDependency<IProjectRepository>()
|
||||
.AccessToProjectAsync(secret.Projects!.FirstOrDefault()!.Id, userId, default).Returns(
|
||||
.AccessToProjectAsync(secret.Projects!.FirstOrDefault()!.Id, userId, Arg.Any<AccessClientType>()).ReturnsForAnyArgs(
|
||||
(read, write));
|
||||
var authzContext = new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement },
|
||||
claimsPrincipal, secret);
|
||||
@@ -207,6 +212,8 @@ public class SecretAuthorizationHandlerTests
|
||||
[BitAutoData(PermissionType.RunAsAdmin, false, false)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, true, true)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, false, true)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, true, true)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, false, true)]
|
||||
public async Task CanCreateSecret_Success(PermissionType permissionType, bool read, bool write,
|
||||
SutProvider<SecretAuthorizationHandler> sutProvider, Secret secret,
|
||||
Guid userId,
|
||||
@@ -215,7 +222,7 @@ public class SecretAuthorizationHandlerTests
|
||||
var requirement = SecretOperations.Create;
|
||||
SetupPermission(sutProvider, permissionType, secret.OrganizationId, userId);
|
||||
sutProvider.GetDependency<IProjectRepository>()
|
||||
.AccessToProjectAsync(secret.Projects!.FirstOrDefault()!.Id, userId, default).Returns(
|
||||
.AccessToProjectAsync(secret.Projects!.FirstOrDefault()!.Id, userId, Arg.Any<AccessClientType>()).ReturnsForAnyArgs(
|
||||
(read, write));
|
||||
var authzContext = new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement },
|
||||
claimsPrincipal, secret);
|
||||
@@ -243,7 +250,6 @@ public class SecretAuthorizationHandlerTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(AccessClientType.ServiceAccount)]
|
||||
[BitAutoData(AccessClientType.Organization)]
|
||||
public async Task CanUpdateSecret_NotSupportedClientTypes_DoesNotSucceed(AccessClientType clientType,
|
||||
SutProvider<SecretAuthorizationHandler> sutProvider, Secret secret, Guid userId,
|
||||
@@ -252,7 +258,7 @@ public class SecretAuthorizationHandlerTests
|
||||
var requirement = SecretOperations.Update;
|
||||
SetupPermission(sutProvider, PermissionType.RunAsUserWithPermission, secret.OrganizationId, userId, clientType);
|
||||
sutProvider.GetDependency<IProjectRepository>()
|
||||
.AccessToProjectAsync(secret.Projects!.FirstOrDefault()!.Id, userId, default).Returns(
|
||||
.AccessToProjectAsync(secret.Projects!.FirstOrDefault()!.Id, userId, Arg.Any<AccessClientType>()).Returns(
|
||||
(true, true));
|
||||
var authzContext = new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement },
|
||||
claimsPrincipal, secret);
|
||||
@@ -327,6 +333,15 @@ public class SecretAuthorizationHandlerTests
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, true, false, true, true)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, true, false, false, true)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, true, false, false, false)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, true, true, true, false)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, true, true, false, false)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, false, true, true, false)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, false, true, false, false)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, false, false, true, true)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, false, false, false, true)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, true, false, true, true)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, true, false, false, true)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, true, false, false, false)]
|
||||
public async Task CanUpdateSecret_DoesNotSucceed(PermissionType permissionType, bool read, bool write,
|
||||
bool projectRead, bool projectWrite,
|
||||
SutProvider<SecretAuthorizationHandler> sutProvider, Secret secret,
|
||||
@@ -335,10 +350,10 @@ public class SecretAuthorizationHandlerTests
|
||||
{
|
||||
var requirement = SecretOperations.Update;
|
||||
SetupPermission(sutProvider, permissionType, secret.OrganizationId, userId);
|
||||
sutProvider.GetDependency<ISecretRepository>().AccessToSecretAsync(secret.Id, userId, default).Returns(
|
||||
sutProvider.GetDependency<ISecretRepository>().AccessToSecretAsync(secret.Id, userId, Arg.Any<AccessClientType>()).Returns(
|
||||
(read, write));
|
||||
sutProvider.GetDependency<IProjectRepository>()
|
||||
.AccessToProjectAsync(secret.Projects!.FirstOrDefault()!.Id, userId, default).Returns(
|
||||
.AccessToProjectAsync(secret.Projects!.FirstOrDefault()!.Id, userId, Arg.Any<AccessClientType>()).Returns(
|
||||
(projectRead, projectWrite));
|
||||
var authzContext = new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement },
|
||||
claimsPrincipal, secret);
|
||||
@@ -355,6 +370,8 @@ public class SecretAuthorizationHandlerTests
|
||||
[BitAutoData(PermissionType.RunAsAdmin, false, false)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, true, true)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, false, true)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, true, true)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, false, true)]
|
||||
public async Task CanUpdateSecret_Success(PermissionType permissionType, bool read, bool write,
|
||||
SutProvider<SecretAuthorizationHandler> sutProvider, Secret secret,
|
||||
Guid userId,
|
||||
@@ -362,10 +379,10 @@ public class SecretAuthorizationHandlerTests
|
||||
{
|
||||
var requirement = SecretOperations.Update;
|
||||
SetupPermission(sutProvider, permissionType, secret.OrganizationId, userId);
|
||||
sutProvider.GetDependency<ISecretRepository>().AccessToSecretAsync(secret.Id, userId, default).Returns(
|
||||
sutProvider.GetDependency<ISecretRepository>().AccessToSecretAsync(secret.Id, userId, Arg.Any<AccessClientType>()).Returns(
|
||||
(read, write));
|
||||
sutProvider.GetDependency<IProjectRepository>()
|
||||
.AccessToProjectAsync(secret.Projects!.FirstOrDefault()!.Id, userId, default).Returns(
|
||||
.AccessToProjectAsync(secret.Projects!.FirstOrDefault()!.Id, userId, Arg.Any<AccessClientType>()).Returns(
|
||||
(read, write));
|
||||
var authzContext = new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement },
|
||||
claimsPrincipal, secret);
|
||||
@@ -409,32 +426,16 @@ public class SecretAuthorizationHandlerTests
|
||||
Assert.False(authzContext.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task CanDeleteSecret_ServiceAccountClient_DoesNotSucceed(
|
||||
SutProvider<SecretAuthorizationHandler> sutProvider, Secret secret, Guid userId,
|
||||
ClaimsPrincipal claimsPrincipal)
|
||||
{
|
||||
var requirement = SecretOperations.Delete;
|
||||
SetupPermission(sutProvider, PermissionType.RunAsUserWithPermission, secret.OrganizationId, userId,
|
||||
AccessClientType.ServiceAccount);
|
||||
sutProvider.GetDependency<ISecretRepository>()
|
||||
.AccessToSecretAsync(secret.Id, userId, Arg.Any<AccessClientType>())
|
||||
.Returns((true, true));
|
||||
var authzContext = new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement },
|
||||
claimsPrincipal, secret);
|
||||
|
||||
await sutProvider.Sut.HandleAsync(authzContext);
|
||||
|
||||
Assert.False(authzContext.HasSucceeded);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PermissionType.RunAsAdmin, true, true, true)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, false, false, false)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, false, true, true)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, true, false, false)]
|
||||
[BitAutoData(PermissionType.RunAsUserWithPermission, true, true, true)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, false, false, false)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, false, true, true)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, true, false, false)]
|
||||
[BitAutoData(PermissionType.RunAsServiceAccountWithPermission, true, true, true)]
|
||||
public async Task CanDeleteProject_AccessCheck(PermissionType permissionType, bool read, bool write,
|
||||
bool expected,
|
||||
SutProvider<SecretAuthorizationHandler> sutProvider, Secret secret,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Bit.Commercial.Core.SecretsManager.Commands.Projects;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
@@ -29,7 +30,7 @@ public class CreateProjectCommandTests
|
||||
.CreateAsync(Arg.Any<Project>())
|
||||
.Returns(data);
|
||||
|
||||
await sutProvider.Sut.CreateAsync(data, userId);
|
||||
await sutProvider.Sut.CreateAsync(data, userId, sutProvider.GetDependency<ICurrentContext>().ClientType);
|
||||
|
||||
await sutProvider.GetDependency<IProjectRepository>().Received(1)
|
||||
.CreateAsync(Arg.Is(data));
|
||||
|
||||
@@ -4,4 +4,5 @@ public enum PermissionType
|
||||
{
|
||||
RunAsAdmin,
|
||||
RunAsUserWithPermission,
|
||||
RunAsServiceAccountWithPermission
|
||||
}
|
||||
|
||||
@@ -2818,7 +2818,7 @@
|
||||
"commercial.core": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3"
|
||||
"Core": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
@@ -2826,7 +2826,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "17.1.0",
|
||||
"NSubstitute": "4.3.0",
|
||||
@@ -2880,8 +2880,8 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Common": "2023.4.3",
|
||||
"Core": "2023.4.3",
|
||||
"Common": "2023.5.1",
|
||||
"Core": "2023.5.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "17.1.0",
|
||||
"Moq": "4.17.2",
|
||||
|
||||
@@ -3144,7 +3144,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "17.1.0",
|
||||
"NSubstitute": "4.3.0",
|
||||
@@ -3196,15 +3196,15 @@
|
||||
"identity": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"SharedWeb": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"SharedWeb": "2023.5.1",
|
||||
"Swashbuckle.AspNetCore.SwaggerGen": "6.5.0"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -3212,7 +3212,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -3224,8 +3224,8 @@
|
||||
"integrationtestcommon": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Common": "2023.4.3",
|
||||
"Identity": "2023.4.3",
|
||||
"Common": "2023.5.1",
|
||||
"Identity": "2023.5.1",
|
||||
"Microsoft.AspNetCore.Mvc.Testing": "6.0.5",
|
||||
"Microsoft.EntityFrameworkCore.InMemory": "6.0.5",
|
||||
"Microsoft.Extensions.Configuration": "6.0.1"
|
||||
@@ -3234,16 +3234,16 @@
|
||||
"scim": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"SharedWeb": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"SharedWeb": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2989,7 +2989,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "17.1.0",
|
||||
"NSubstitute": "4.3.0",
|
||||
@@ -3041,7 +3041,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -3049,7 +3049,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -3061,16 +3061,16 @@
|
||||
"scim": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"SharedWeb": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"SharedWeb": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
dev/create_certificates_linux.sh
Executable file
48
dev/create_certificates_linux.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# Script for generating and installing the Bitwarden development certificates on Linux.
|
||||
|
||||
IDENTITY_SERVER_KEY=identity_server_dev.key
|
||||
IDENTITY_SERVER_CERT=identity_server_dev.crt
|
||||
IDENTITY_SERVER_CN="Bitwarden Identity Server Dev"
|
||||
DATA_PROTECTION_KEY=data_protection_dev.key
|
||||
DATA_PROTECTION_CERT=data_protection_dev.crt
|
||||
DATA_PROTECTION_CN="Bitwarden Data Protection Dev"
|
||||
|
||||
# Detect management command to trust generated certificates.
|
||||
if [ -x "$(command -v update-ca-certificates)" ]; then
|
||||
# Debian based
|
||||
CA_CERT_DIR=/usr/local/share/ca-certificates/
|
||||
UPDATE_CA_CMD=update-ca-certificates
|
||||
elif [ -x "$(command -v update-ca-trust)" ]; then
|
||||
# Redhat based
|
||||
CA_CERT_DIR=/etc/pki/ca-trust/source/anchors/
|
||||
UPDATE_CA_CMD=update-ca-trust
|
||||
else
|
||||
echo 'Error: Update manager for CA certificates not found!'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
openssl req -x509 -newkey rsa:4096 -sha256 -nodes -days 3650 \
|
||||
-keyout $IDENTITY_SERVER_KEY \
|
||||
-out $IDENTITY_SERVER_CERT \
|
||||
-subj "/CN=$IDENTITY_SERVER_CN"
|
||||
|
||||
sudo cp $IDENTITY_SERVER_CERT $CA_CERT_DIR
|
||||
|
||||
openssl req -x509 -newkey rsa:4096 -sha256 -nodes -days 3650 \
|
||||
-keyout $DATA_PROTECTION_KEY \
|
||||
-out $DATA_PROTECTION_CERT \
|
||||
-subj "/CN=$DATA_PROTECTION_CN"
|
||||
|
||||
sudo cp $DATA_PROTECTION_CERT $CA_CERT_DIR
|
||||
|
||||
sudo $UPDATE_CA_CMD
|
||||
|
||||
identity=($(openssl x509 -in $IDENTITY_SERVER_CERT -outform der | sha1sum | tr a-z A-Z))
|
||||
data=($(openssl x509 -in $DATA_PROTECTION_CERT -outform der | sha1sum | tr a-z A-Z))
|
||||
|
||||
echo "Certificate fingerprints:"
|
||||
|
||||
echo "Identity Server Dev: ${identity}"
|
||||
echo "Data Protection Dev: ${data}"
|
||||
@@ -15,7 +15,7 @@
|
||||
"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",
|
||||
"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"
|
||||
|
||||
@@ -15,15 +15,35 @@ export const options = {
|
||||
name: "Config",
|
||||
},
|
||||
},
|
||||
stages: [
|
||||
{ duration: "30s", target: 10 },
|
||||
{ duration: "1m", target: 20 },
|
||||
{ duration: "2m", target: 25 },
|
||||
{ duration: "30s", target: 0 },
|
||||
],
|
||||
scenarios: {
|
||||
constant_load: {
|
||||
executor: "constant-arrival-rate",
|
||||
rate: 1,
|
||||
timeUnit: "1s", // 1 request / second
|
||||
duration: "10m",
|
||||
preAllocatedVUs: 5,
|
||||
},
|
||||
ramping_load: {
|
||||
executor: "ramping-arrival-rate",
|
||||
startRate: 60,
|
||||
timeUnit: "1m", // 1 request / second to start
|
||||
stages: [
|
||||
{ duration: "30s", target: 60 },
|
||||
{ duration: "2m", target: 150 },
|
||||
{ duration: "1m", target: 90 },
|
||||
{ duration: "2m", target: 200 },
|
||||
{ duration: "2m", target: 120 },
|
||||
{ duration: "1m", target: 180 },
|
||||
{ duration: "30s", target: 250 },
|
||||
{ duration: "30s", target: 90 },
|
||||
{ duration: "30s", target: 0 },
|
||||
],
|
||||
preAllocatedVUs: 40,
|
||||
},
|
||||
},
|
||||
thresholds: {
|
||||
http_req_failed: ["rate<0.01"],
|
||||
http_req_duration: ["p(95)<1000"],
|
||||
http_req_duration: ["p(95)<750"],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -16,15 +16,35 @@ export const options = {
|
||||
name: "Groups",
|
||||
},
|
||||
},
|
||||
stages: [
|
||||
{ duration: "30s", target: 10 },
|
||||
{ duration: "1m", target: 20 },
|
||||
{ duration: "2m", target: 25 },
|
||||
{ duration: "30s", target: 0 },
|
||||
],
|
||||
scenarios: {
|
||||
constant_load: {
|
||||
executor: "constant-arrival-rate",
|
||||
rate: 30,
|
||||
timeUnit: "1m", // 0.5 requests / second
|
||||
duration: "10m",
|
||||
preAllocatedVUs: 5,
|
||||
},
|
||||
ramping_load: {
|
||||
executor: "ramping-arrival-rate",
|
||||
startRate: 30,
|
||||
timeUnit: "1m", // 0.5 requests / second to start
|
||||
stages: [
|
||||
{ duration: "30s", target: 30 },
|
||||
{ duration: "2m", target: 75 },
|
||||
{ duration: "1m", target: 60 },
|
||||
{ duration: "2m", target: 100 },
|
||||
{ duration: "2m", target: 90 },
|
||||
{ duration: "1m", target: 120 },
|
||||
{ duration: "30s", target: 150 },
|
||||
{ duration: "30s", target: 60 },
|
||||
{ duration: "30s", target: 0 },
|
||||
],
|
||||
preAllocatedVUs: 20,
|
||||
},
|
||||
},
|
||||
thresholds: {
|
||||
http_req_failed: ["rate<0.01"],
|
||||
http_req_duration: ["p(95)<1500"],
|
||||
http_req_duration: ["p(95)<900"],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -12,15 +12,33 @@ export const options = {
|
||||
name: "Login",
|
||||
},
|
||||
},
|
||||
stages: [
|
||||
{ duration: "30s", target: 10 },
|
||||
{ duration: "1m", target: 20 },
|
||||
{ duration: "2m", target: 25 },
|
||||
{ duration: "30s", target: 0 },
|
||||
],
|
||||
scenarios: {
|
||||
constant_load: {
|
||||
executor: "constant-arrival-rate",
|
||||
rate: 2,
|
||||
timeUnit: "1s", // 2 requests / second
|
||||
duration: "10m",
|
||||
preAllocatedVUs: 10,
|
||||
},
|
||||
ramping_load: {
|
||||
executor: "ramping-arrival-rate",
|
||||
startRate: 60,
|
||||
timeUnit: "1m", // 1 request / second to start
|
||||
stages: [
|
||||
{ duration: "30s", target: 60 },
|
||||
{ duration: "5m", target: 120 },
|
||||
{ duration: "2m", target: 150 },
|
||||
{ duration: "1m", target: 180 },
|
||||
{ duration: "30s", target: 200 },
|
||||
{ duration: "30s", target: 90 },
|
||||
{ duration: "30s", target: 0 },
|
||||
],
|
||||
preAllocatedVUs: 25,
|
||||
},
|
||||
},
|
||||
thresholds: {
|
||||
http_req_failed: ["rate<0.01"],
|
||||
http_req_duration: ["p(95)<3000"],
|
||||
http_req_duration: ["p(95)<1500"],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ docker_build() {
|
||||
docker build -t bitwarden/$project_name_lower:$docker_tag $project_dir
|
||||
|
||||
if [ "$docker_push" == "1" ]; then
|
||||
docker push bitwarden/$project_name_lower:$docker_tag $project_dir
|
||||
docker push bitwarden/$project_name_lower:$docker_tag
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Bit.Core;
|
||||
using Bit.Core.Jobs;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Settings;
|
||||
using Quartz;
|
||||
|
||||
namespace Bit.Admin.Auth.Jobs;
|
||||
@@ -8,20 +9,26 @@ namespace Bit.Admin.Auth.Jobs;
|
||||
public class DeleteAuthRequestsJob : BaseJob
|
||||
{
|
||||
private readonly IAuthRequestRepository _authRepo;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
|
||||
public DeleteAuthRequestsJob(
|
||||
IAuthRequestRepository authrepo,
|
||||
IGlobalSettings globalSettings,
|
||||
ILogger<DeleteAuthRequestsJob> logger)
|
||||
: base(logger)
|
||||
{
|
||||
_authRepo = authrepo;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
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.");
|
||||
var count = await _authRepo.DeleteExpiredAsync(
|
||||
_globalSettings.PasswordlessAuth.UserRequestExpiration,
|
||||
_globalSettings.PasswordlessAuth.AdminRequestExpiration,
|
||||
_globalSettings.PasswordlessAuth.AfterAdminApprovalExpiration);
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId, "{Count} records deleted from AuthRequests.", count);
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId, "Execute job task: DeleteAuthRequestsJob: End");
|
||||
}
|
||||
}
|
||||
|
||||
20
src/Admin/package-lock.json
generated
20
src/Admin/package-lock.json
generated
@@ -17,8 +17,8 @@
|
||||
"jquery": "3.5.1",
|
||||
"merge-stream": "2.0.0",
|
||||
"popper.js": "1.16.1",
|
||||
"sass": "^1.49.7",
|
||||
"toastr": "^2.1.4"
|
||||
"sass": "1.49.7",
|
||||
"toastr": "2.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
@@ -3925,9 +3925,9 @@
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
@@ -4694,7 +4694,7 @@
|
||||
"node_modules/toastr": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz",
|
||||
"integrity": "sha1-i0O+ZPudDEFIcURvLbjoyk6V8YE=",
|
||||
"integrity": "sha512-LIy77F5n+sz4tefMmFOntcJ6HL0Fv3k1TDnNmFZ0bU/GcvIIfy6eG2v7zQmMiYgaalAiUv75ttFrPn5s0gyqlA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"jquery": ">=1.12.0"
|
||||
@@ -8168,9 +8168,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"anymatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"normalize-path": "^3.0.0",
|
||||
@@ -8774,7 +8774,7 @@
|
||||
"toastr": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz",
|
||||
"integrity": "sha1-i0O+ZPudDEFIcURvLbjoyk6V8YE=",
|
||||
"integrity": "sha512-LIy77F5n+sz4tefMmFOntcJ6HL0Fv3k1TDnNmFZ0bU/GcvIIfy6eG2v7zQmMiYgaalAiUv75ttFrPn5s0gyqlA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jquery": ">=1.12.0"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"jquery": "3.5.1",
|
||||
"merge-stream": "2.0.0",
|
||||
"popper.js": "1.16.1",
|
||||
"sass": "^1.49.7",
|
||||
"toastr": "^2.1.4"
|
||||
"sass": "1.49.7",
|
||||
"toastr": "2.1.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2834,7 +2834,7 @@
|
||||
"commercial.core": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3"
|
||||
"Core": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"core": {
|
||||
@@ -2882,7 +2882,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2890,7 +2890,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2902,7 +2902,7 @@
|
||||
"migrator": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.Extensions.Logging": "6.0.0",
|
||||
"dbup-sqlserver": "5.0.8"
|
||||
}
|
||||
@@ -2910,30 +2910,30 @@
|
||||
"mysqlmigrations": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"postgresmigrations": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"sqlitemigrations": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using Bit.Core.Models.Business;
|
||||
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||
using Bit.Core.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.SecretsManager.Commands.EnableAccessSecretsManager.Interfaces;
|
||||
using Bit.Core.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -19,6 +20,7 @@ namespace Bit.Api.Controllers;
|
||||
[Authorize("Application")]
|
||||
public class OrganizationUsersController : Controller
|
||||
{
|
||||
private readonly IEnableAccessSecretsManagerCommand _enableAccessSecretsManagerCommand;
|
||||
private readonly IOrganizationRepository _organizationRepository;
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly IOrganizationService _organizationService;
|
||||
@@ -29,6 +31,7 @@ public class OrganizationUsersController : Controller
|
||||
private readonly ICurrentContext _currentContext;
|
||||
|
||||
public OrganizationUsersController(
|
||||
IEnableAccessSecretsManagerCommand enableAccessSecretsManagerCommand,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IOrganizationService organizationService,
|
||||
@@ -38,6 +41,7 @@ public class OrganizationUsersController : Controller
|
||||
IPolicyRepository policyRepository,
|
||||
ICurrentContext currentContext)
|
||||
{
|
||||
_enableAccessSecretsManagerCommand = enableAccessSecretsManagerCommand;
|
||||
_organizationRepository = organizationRepository;
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_organizationService = organizationService;
|
||||
@@ -420,6 +424,29 @@ public class OrganizationUsersController : Controller
|
||||
return await RestoreOrRevokeUsersAsync(orgId, model, (orgId, orgUserIds, restoringUserId) => _organizationService.RestoreUsersAsync(orgId, orgUserIds, restoringUserId, _userService));
|
||||
}
|
||||
|
||||
[HttpPatch("enable-secrets-manager")]
|
||||
[HttpPut("enable-secrets-manager")]
|
||||
public async Task<ListResponseModel<OrganizationUserBulkResponseModel>> BulkEnableSecretsManagerAsync(Guid orgId,
|
||||
[FromBody] OrganizationUserBulkRequestModel model)
|
||||
{
|
||||
if (!await _currentContext.ManageUsers(orgId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var orgUsers = (await _organizationUserRepository.GetManyAsync(model.Ids))
|
||||
.Where(ou => ou.OrganizationId == orgId).ToList();
|
||||
if (orgUsers.Count == 0)
|
||||
{
|
||||
throw new BadRequestException("Users invalid.");
|
||||
}
|
||||
|
||||
var results = await _enableAccessSecretsManagerCommand.EnableUsersAsync(orgUsers);
|
||||
|
||||
return new ListResponseModel<OrganizationUserBulkResponseModel>(results.Select(r =>
|
||||
new OrganizationUserBulkResponseModel(r.organizationUser.Id, r.error)));
|
||||
}
|
||||
|
||||
private async Task RestoreOrRevokeUserAsync(
|
||||
Guid orgId,
|
||||
Guid id,
|
||||
|
||||
@@ -28,6 +28,7 @@ public class ConfigResponseModel : ResponseModel
|
||||
GitHash = AssemblyHelpers.GetGitHash();
|
||||
Environment = new EnvironmentConfigResponseModel
|
||||
{
|
||||
CloudRegion = globalSettings.BaseServiceUri.CloudRegion,
|
||||
Vault = globalSettings.BaseServiceUri.Vault,
|
||||
Api = globalSettings.BaseServiceUri.Api,
|
||||
Identity = globalSettings.BaseServiceUri.Identity,
|
||||
@@ -46,6 +47,7 @@ public class ServerConfigResponseModel
|
||||
|
||||
public class EnvironmentConfigResponseModel
|
||||
{
|
||||
public string CloudRegion { get; set; }
|
||||
public string Vault { get; set; }
|
||||
public string Api { get; set; }
|
||||
public string Identity { get; set; }
|
||||
|
||||
@@ -73,9 +73,8 @@ public class ProjectsController : Controller
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var userId = _userService.GetProperUserId(User).Value;
|
||||
var result = await _createProjectCommand.CreateAsync(project, userId);
|
||||
var result = await _createProjectCommand.CreateAsync(project, userId, _currentContext.ClientType);
|
||||
|
||||
// Creating a project means you have read & write permission.
|
||||
return new ProjectResponseModel(result, true, true);
|
||||
|
||||
@@ -136,7 +136,10 @@ public class Startup
|
||||
services.AddCoreLocalizationServices();
|
||||
|
||||
//health check
|
||||
services.AddHealthChecks(globalSettings);
|
||||
if (!globalSettings.SelfHosted)
|
||||
{
|
||||
services.AddHealthChecks(globalSettings);
|
||||
}
|
||||
|
||||
#if OSS
|
||||
services.AddOosServices();
|
||||
@@ -215,12 +218,15 @@ public class Startup
|
||||
{
|
||||
endpoints.MapDefaultControllerRoute();
|
||||
|
||||
endpoints.MapHealthChecks("/healthz");
|
||||
|
||||
endpoints.MapHealthChecks("/healthz/extended", new HealthCheckOptions
|
||||
if (!globalSettings.SelfHosted)
|
||||
{
|
||||
ResponseWriter = HealthCheckServiceExtensions.WriteResponse
|
||||
});
|
||||
endpoints.MapHealthChecks("/healthz");
|
||||
|
||||
endpoints.MapHealthChecks("/healthz/extended", new HealthCheckOptions
|
||||
{
|
||||
ResponseWriter = HealthCheckServiceExtensions.WriteResponse
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Add Swagger
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Bit.Core.IdentityServer;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.SharedWeb.Health;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
@@ -80,35 +81,35 @@ public static class ServiceCollectionExtensions
|
||||
|
||||
builder.AddUrlGroup(identityUri, "identity");
|
||||
|
||||
if (!string.IsNullOrEmpty(globalSettings.SqlServer.ConnectionString))
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.SqlServer.ConnectionString))
|
||||
{
|
||||
builder.AddSqlServer(globalSettings.SqlServer.ConnectionString);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(globalSettings.Redis.ConnectionString))
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Redis.ConnectionString))
|
||||
{
|
||||
builder.AddRedis(globalSettings.Redis.ConnectionString);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(globalSettings.Storage.ConnectionString))
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Storage.ConnectionString))
|
||||
{
|
||||
builder.AddAzureQueueStorage(globalSettings.Storage.ConnectionString, name: "storage_queue")
|
||||
.AddAzureQueueStorage(globalSettings.Events.ConnectionString, name: "events_queue");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(globalSettings.Notifications.ConnectionString))
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Notifications.ConnectionString))
|
||||
{
|
||||
builder.AddAzureQueueStorage(globalSettings.Notifications.ConnectionString,
|
||||
name: "notifications_queue");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(globalSettings.ServiceBus.ConnectionString))
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.ServiceBus.ConnectionString))
|
||||
{
|
||||
builder.AddAzureServiceBusTopic(_ => globalSettings.ServiceBus.ConnectionString,
|
||||
_ => globalSettings.ServiceBus.ApplicationCacheTopicName, name: "service_bus");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(globalSettings.Mail.SendGridApiKey))
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Mail.SendGridApiKey))
|
||||
{
|
||||
builder.AddSendGrid(globalSettings.Mail.SendGridApiKey);
|
||||
}
|
||||
|
||||
@@ -2907,85 +2907,85 @@
|
||||
"commercial.core": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.5.0, )"
|
||||
"Core": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"commercial.infrastructure.entityframework": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.5.0, )",
|
||||
"Infrastructure.EntityFramework": "[2023.5.0, )"
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.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.3.2, )",
|
||||
"Azure.Storage.Blobs": "[12.14.1, )",
|
||||
"Azure.Storage.Queues": "[12.12.0, )",
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.12.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[7.0.0, )",
|
||||
"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, )"
|
||||
"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.3.2",
|
||||
"Azure.Storage.Blobs": "12.14.1",
|
||||
"Azure.Storage.Queues": "12.12.0",
|
||||
"BitPay.Light": "1.0.1907",
|
||||
"Braintree": "5.12.0",
|
||||
"DnsClient": "1.7.0",
|
||||
"Fido2.AspNet": "3.0.1",
|
||||
"Handlebars.Net": "2.1.2",
|
||||
"IdentityServer4": "4.1.2",
|
||||
"IdentityServer4.AccessTokenValidation": "3.0.1",
|
||||
"LaunchDarkly.ServerSdk": "7.0.0",
|
||||
"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.5.0, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
"infrastructure.entityframework": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.5.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, )"
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.5.1",
|
||||
"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.5.0, )",
|
||||
"Infrastructure.Dapper": "[2023.5.0, )",
|
||||
"Infrastructure.EntityFramework": "[2023.5.0, )"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2786,7 +2786,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2794,7 +2794,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2806,9 +2806,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Bit.Core.Repositories;
|
||||
|
||||
public interface IAuthRequestRepository : IRepository<AuthRequest, Guid>
|
||||
{
|
||||
Task<int> DeleteExpiredAsync();
|
||||
Task<int> DeleteExpiredAsync(TimeSpan userRequestExpiration, TimeSpan adminRequestExpiration, TimeSpan afterAdminApprovalExpiration);
|
||||
Task<ICollection<AuthRequest>> GetManyByUserIdAsync(Guid userId);
|
||||
Task<ICollection<OrganizationAdminAuthRequest>> GetManyPendingByOrganizationIdAsync(Guid organizationId);
|
||||
Task<ICollection<OrganizationAdminAuthRequest>> GetManyAdminApprovalRequestsByManyIdsAsync(Guid organizationId, IEnumerable<Guid> ids);
|
||||
|
||||
@@ -3,4 +3,7 @@
|
||||
public interface IPasswordlessAuthSettings
|
||||
{
|
||||
bool KnownDevicesOnly { get; set; }
|
||||
TimeSpan UserRequestExpiration { get; set; }
|
||||
TimeSpan AdminRequestExpiration { get; set; }
|
||||
TimeSpan AfterAdminApprovalExpiration { get; set; }
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterpri
|
||||
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Cloud;
|
||||
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
|
||||
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.SelfHosted;
|
||||
using Bit.Core.SecretsManager.Commands.EnableAccessSecretsManager;
|
||||
using Bit.Core.SecretsManager.Commands.EnableAccessSecretsManager.Interfaces;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Tokens;
|
||||
@@ -29,6 +31,7 @@ public static class OrganizationServiceCollectionExtensions
|
||||
public static void AddOrganizationServices(this IServiceCollection services, IGlobalSettings globalSettings)
|
||||
{
|
||||
services.AddScoped<IOrganizationService, OrganizationService>();
|
||||
services.AddScoped<IEnableAccessSecretsManagerCommand, EnableAccessSecretsManagerCommand>();
|
||||
services.AddTokenizers();
|
||||
services.AddOrganizationGroupCommands();
|
||||
services.AddOrganizationConnectionCommands();
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.SecretsManager.Commands.EnableAccessSecretsManager.Interfaces;
|
||||
|
||||
namespace Bit.Core.SecretsManager.Commands.EnableAccessSecretsManager;
|
||||
|
||||
public class EnableAccessSecretsManagerCommand : IEnableAccessSecretsManagerCommand
|
||||
{
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
|
||||
public EnableAccessSecretsManagerCommand(IOrganizationUserRepository organizationUserRepository)
|
||||
{
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
}
|
||||
|
||||
public async Task<List<(OrganizationUser organizationUser, string error)>> EnableUsersAsync(
|
||||
IEnumerable<OrganizationUser> organizationUsers)
|
||||
{
|
||||
var results = new List<(OrganizationUser organizationUser, string error)>();
|
||||
var usersToEnable = new List<OrganizationUser>();
|
||||
|
||||
foreach (var orgUser in organizationUsers)
|
||||
{
|
||||
if (orgUser.AccessSecretsManager)
|
||||
{
|
||||
results.Add((orgUser, "User already has access to Secrets Manager"));
|
||||
}
|
||||
else
|
||||
{
|
||||
orgUser.AccessSecretsManager = true;
|
||||
usersToEnable.Add(orgUser);
|
||||
results.Add((orgUser, ""));
|
||||
}
|
||||
}
|
||||
|
||||
if (usersToEnable.Any())
|
||||
{
|
||||
await _organizationUserRepository.ReplaceManyAsync(usersToEnable);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Bit.Core.Entities;
|
||||
|
||||
namespace Bit.Core.SecretsManager.Commands.EnableAccessSecretsManager.Interfaces;
|
||||
|
||||
public interface IEnableAccessSecretsManagerCommand
|
||||
{
|
||||
Task<List<(OrganizationUser organizationUser, string error)>> EnableUsersAsync(
|
||||
IEnumerable<OrganizationUser> organizationUsers);
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
using Bit.Core.Identity;
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
|
||||
namespace Bit.Core.SecretsManager.Commands.Projects.Interfaces;
|
||||
|
||||
public interface ICreateProjectCommand
|
||||
{
|
||||
Task<Project> CreateAsync(Project project, Guid userId);
|
||||
Task<Project> CreateAsync(Project project, Guid userId, ClientType clientType);
|
||||
}
|
||||
|
||||
@@ -143,6 +143,7 @@ public class GlobalSettings : IGlobalSettings
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public string CloudRegion { get; set; }
|
||||
public string Vault { get; set; }
|
||||
public string VaultWithHash => $"{Vault}/#";
|
||||
|
||||
@@ -534,6 +535,9 @@ public class GlobalSettings : IGlobalSettings
|
||||
public class PasswordlessAuthSettings : IPasswordlessAuthSettings
|
||||
{
|
||||
public bool KnownDevicesOnly { get; set; } = true;
|
||||
public TimeSpan UserRequestExpiration { get; set; } = TimeSpan.FromMinutes(15);
|
||||
public TimeSpan AdminRequestExpiration { get; set; } = TimeSpan.FromDays(7);
|
||||
public TimeSpan AfterAdminApprovalExpiration { get; set; } = TimeSpan.FromHours(12);
|
||||
}
|
||||
|
||||
public class DomainVerificationSettings : IDomainVerificationSettings
|
||||
|
||||
@@ -3,6 +3,7 @@ namespace Bit.Core.Settings;
|
||||
|
||||
public interface IBaseServiceUriSettings
|
||||
{
|
||||
string CloudRegion { get; set; }
|
||||
string Vault { get; set; }
|
||||
string VaultWithHash { get; }
|
||||
string Api { get; set; }
|
||||
|
||||
@@ -2786,7 +2786,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2794,7 +2794,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2806,9 +2806,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2786,7 +2786,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2794,7 +2794,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2806,9 +2806,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2796,7 +2796,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2804,7 +2804,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2816,9 +2816,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2808,7 +2808,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2816,7 +2816,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2828,9 +2828,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,19 @@ public class AuthRequestRepository : Repository<AuthRequest, Guid>, IAuthRequest
|
||||
: base(connectionString, readOnlyConnectionString)
|
||||
{ }
|
||||
|
||||
public async Task<int> DeleteExpiredAsync()
|
||||
public async Task<int> DeleteExpiredAsync(
|
||||
TimeSpan userRequestExpiration, TimeSpan adminRequestExpiration, TimeSpan afterAdminApprovalExpiration)
|
||||
{
|
||||
using (var connection = new SqlConnection(ConnectionString))
|
||||
{
|
||||
return await connection.ExecuteAsync(
|
||||
$"[{Schema}].[AuthRequest_DeleteIfExpired]",
|
||||
null,
|
||||
new
|
||||
{
|
||||
UserExpirationSeconds = (int)userRequestExpiration.TotalSeconds,
|
||||
AdminExpirationSeconds = (int)adminRequestExpiration.TotalSeconds,
|
||||
AdminApprovalExpirationSeconds = (int)afterAdminApprovalExpiration.TotalSeconds,
|
||||
},
|
||||
commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,15 +15,20 @@ public class AuthRequestRepository : Repository<Core.Auth.Entities.AuthRequest,
|
||||
public AuthRequestRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
|
||||
: base(serviceScopeFactory, mapper, (DatabaseContext context) => context.AuthRequests)
|
||||
{ }
|
||||
public async Task<int> DeleteExpiredAsync()
|
||||
public async Task<int> DeleteExpiredAsync(
|
||||
TimeSpan userRequestExpiration, TimeSpan adminRequestExpiration, TimeSpan afterAdminApprovalExpiration)
|
||||
{
|
||||
|
||||
using (var scope = ServiceScopeFactory.CreateScope())
|
||||
{
|
||||
var dbContext = GetDatabaseContext(scope);
|
||||
var expiredRequests = await dbContext.AuthRequests.Where(a => a.CreationDate < DateTime.Now.AddMinutes(-15)).ToListAsync();
|
||||
var expiredRequests = await dbContext.AuthRequests
|
||||
.Where(a => (a.Type != AuthRequestType.AdminApproval && a.CreationDate.AddSeconds(userRequestExpiration.TotalSeconds) < DateTime.UtcNow)
|
||||
|| (a.Type == AuthRequestType.AdminApproval && a.Approved != true && a.CreationDate.AddSeconds(adminRequestExpiration.TotalSeconds) < DateTime.UtcNow)
|
||||
|| (a.Type == AuthRequestType.AdminApproval && a.Approved == true && a.ResponseDate.Value.AddSeconds(afterAdminApprovalExpiration.TotalSeconds) < DateTime.UtcNow))
|
||||
.ToListAsync();
|
||||
dbContext.AuthRequests.RemoveRange(expiredRequests);
|
||||
await dbContext.SaveChangesAsync();
|
||||
return 1;
|
||||
return await dbContext.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ public class UserCipherDetailsQuery : IQuery<CipherDetails>
|
||||
|
||||
where ou.AccessAll || cu.CollectionId != null || g.AccessAll || cg.CollectionId != null
|
||||
|
||||
select new { c, ou, o, cc, cu, gu, g, cg }.c;
|
||||
select c;
|
||||
|
||||
var query2 = from c in dbContext.Ciphers
|
||||
where c.UserId == _userId
|
||||
@@ -79,14 +79,23 @@ public class UserCipherDetailsQuery : IQuery<CipherDetails>
|
||||
|
||||
private static Guid? GetFolderId(Guid? userId, Cipher cipher)
|
||||
{
|
||||
if (userId.HasValue && !string.IsNullOrWhiteSpace(cipher.Folders))
|
||||
try
|
||||
{
|
||||
var folders = JsonSerializer.Deserialize<Dictionary<Guid, Guid>>(cipher.Folders);
|
||||
if (folders.TryGetValue(userId.Value, out var folder))
|
||||
if (userId.HasValue && !string.IsNullOrWhiteSpace(cipher.Folders))
|
||||
{
|
||||
return folder;
|
||||
var folders = JsonSerializer.Deserialize<Dictionary<Guid, Guid>>(cipher.Folders);
|
||||
if (folders.TryGetValue(userId.Value, out var folder))
|
||||
{
|
||||
return folder;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Some Folders might be in an invalid format like: '{ "", "<ValidGuid>" }'
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using AutoMapper;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using AutoMapper;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Core.Vault.Enums;
|
||||
@@ -13,8 +15,8 @@ using Bit.Infrastructure.EntityFramework.Vault.Repositories.Queries;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NS = Newtonsoft.Json;
|
||||
using NSL = Newtonsoft.Json.Linq;
|
||||
using User = Bit.Core.Entities.User;
|
||||
|
||||
namespace Bit.Infrastructure.EntityFramework.Vault.Repositories;
|
||||
@@ -198,9 +200,9 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
{
|
||||
var dbContext = GetDatabaseContext(scope);
|
||||
var cipher = await dbContext.Ciphers.FindAsync(cipherId);
|
||||
var attachmentsJson = JObject.Parse(cipher.Attachments);
|
||||
var attachmentsJson = NSL.JObject.Parse(cipher.Attachments);
|
||||
attachmentsJson.Remove(attachmentId);
|
||||
cipher.Attachments = JsonConvert.SerializeObject(attachmentsJson);
|
||||
cipher.Attachments = NS.JsonConvert.SerializeObject(attachmentsJson);
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
if (cipher.OrganizationId.HasValue)
|
||||
@@ -396,8 +398,8 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
await idsToMove.ForEachAsync(cipher =>
|
||||
{
|
||||
var foldersJson = string.IsNullOrWhiteSpace(cipher.Folders) ?
|
||||
new JObject() :
|
||||
JObject.Parse(cipher.Folders);
|
||||
new NSL.JObject() :
|
||||
NSL.JObject.Parse(cipher.Folders);
|
||||
|
||||
if (folderId.HasValue)
|
||||
{
|
||||
@@ -409,7 +411,7 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
foldersJson.Remove(userId.ToString());
|
||||
}
|
||||
dbContext.Attach(cipher);
|
||||
cipher.Folders = JsonConvert.SerializeObject(foldersJson);
|
||||
cipher.Folders = NS.JsonConvert.SerializeObject(foldersJson);
|
||||
});
|
||||
await dbContext.UserBumpAccountRevisionDateAsync(userId);
|
||||
await dbContext.SaveChangesAsync();
|
||||
@@ -418,27 +420,27 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
|
||||
public async Task ReplaceAsync(CipherDetails cipher)
|
||||
{
|
||||
cipher.UserId = cipher.OrganizationId.HasValue ?
|
||||
null :
|
||||
cipher.UserId;
|
||||
using (var scope = ServiceScopeFactory.CreateScope())
|
||||
{
|
||||
var dbContext = GetDatabaseContext(scope);
|
||||
var entity = await dbContext.Ciphers.FindAsync(cipher.Id);
|
||||
if (entity != null)
|
||||
{
|
||||
var userIdKey = $"\"{cipher.UserId}\"";
|
||||
if (cipher.Favorite)
|
||||
{
|
||||
if (cipher.Favorites == null)
|
||||
{
|
||||
cipher.Favorites = $"{{{userIdKey}:true}}";
|
||||
var jsonObject = new JsonObject(new[]
|
||||
{
|
||||
new KeyValuePair<string, JsonNode>(cipher.UserId.Value.ToString(), true),
|
||||
});
|
||||
cipher.Favorites = JsonSerializer.Serialize(jsonObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
var favorites = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, bool>>(cipher.Favorites);
|
||||
favorites.Add(cipher.UserId.Value, true);
|
||||
cipher.Favorites = JsonConvert.SerializeObject(favorites);
|
||||
cipher.Favorites = JsonSerializer.Serialize(favorites);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -447,32 +449,45 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
{
|
||||
var favorites = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, bool>>(cipher.Favorites);
|
||||
favorites.Remove(cipher.UserId.Value);
|
||||
cipher.Favorites = JsonConvert.SerializeObject(favorites);
|
||||
cipher.Favorites = JsonSerializer.Serialize(favorites);
|
||||
}
|
||||
}
|
||||
if (cipher.FolderId.HasValue)
|
||||
{
|
||||
if (cipher.Folders == null)
|
||||
{
|
||||
cipher.Folders = $"{{{userIdKey}:\"{cipher.FolderId}\"}}";
|
||||
var jsonObject = new JsonObject(new[]
|
||||
{
|
||||
new KeyValuePair<string, JsonNode>(cipher.UserId.Value.ToString(), cipher.FolderId),
|
||||
});
|
||||
cipher.Folders = JsonSerializer.Serialize(jsonObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
var folders = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, Guid>>(cipher.Folders);
|
||||
folders.Add(cipher.UserId.Value, cipher.FolderId.Value);
|
||||
cipher.Folders = JsonConvert.SerializeObject(folders);
|
||||
cipher.Folders = JsonSerializer.Serialize(folders);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cipher.Folders != null && cipher.Folders.Contains(cipher.UserId.Value.ToString()))
|
||||
{
|
||||
var folders = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, bool>>(cipher.Favorites);
|
||||
var folders = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, Guid>>(cipher.Folders);
|
||||
folders.Remove(cipher.UserId.Value);
|
||||
cipher.Favorites = JsonConvert.SerializeObject(folders);
|
||||
cipher.Folders = JsonSerializer.Serialize(folders);
|
||||
}
|
||||
}
|
||||
var mappedEntity = Mapper.Map<Cipher>((Core.Vault.Entities.Cipher)cipher);
|
||||
|
||||
// Check if this cipher is a part of an organization, and if so do
|
||||
// not save the UserId into the database. This must be done after we
|
||||
// set the user specific data like Folders and Favorites because
|
||||
// the UserId key is used for that
|
||||
cipher.UserId = cipher.OrganizationId.HasValue ?
|
||||
null :
|
||||
cipher.UserId;
|
||||
|
||||
var mappedEntity = Mapper.Map<Cipher>(cipher);
|
||||
dbContext.Entry(entity).CurrentValues.SetValues(mappedEntity);
|
||||
|
||||
if (cipher.OrganizationId.HasValue)
|
||||
@@ -701,10 +716,10 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
var cipher = await dbContext.Ciphers.FindAsync(attachment.Id);
|
||||
var attachments = string.IsNullOrWhiteSpace(cipher.Attachments) ?
|
||||
new Dictionary<string, CipherAttachment.MetaData>() :
|
||||
JsonConvert.DeserializeObject<Dictionary<string, CipherAttachment.MetaData>>(cipher.Attachments);
|
||||
var metaData = JsonConvert.DeserializeObject<CipherAttachment.MetaData>(attachment.AttachmentData);
|
||||
NS.JsonConvert.DeserializeObject<Dictionary<string, CipherAttachment.MetaData>>(cipher.Attachments);
|
||||
var metaData = NS.JsonConvert.DeserializeObject<CipherAttachment.MetaData>(attachment.AttachmentData);
|
||||
attachments[attachment.AttachmentId] = metaData;
|
||||
cipher.Attachments = JsonConvert.SerializeObject(attachments);
|
||||
cipher.Attachments = NS.JsonConvert.SerializeObject(attachments);
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
if (attachment.OrganizationId.HasValue)
|
||||
@@ -744,7 +759,7 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
var dbContext = GetDatabaseContext(scope);
|
||||
var cipher = await dbContext.Ciphers.FindAsync(id);
|
||||
|
||||
var foldersJson = JObject.Parse(cipher.Folders);
|
||||
var foldersJson = NSL.JObject.Parse(cipher.Folders);
|
||||
if (foldersJson == null && folderId.HasValue)
|
||||
{
|
||||
foldersJson.Add(userId.ToString(), folderId.Value);
|
||||
@@ -758,7 +773,7 @@ public class CipherRepository : Repository<Core.Vault.Entities.Cipher, Cipher, G
|
||||
foldersJson.Remove(userId.ToString());
|
||||
}
|
||||
|
||||
var favoritesJson = JObject.Parse(cipher.Favorites);
|
||||
var favoritesJson = NSL.JObject.Parse(cipher.Favorites);
|
||||
if (favorite)
|
||||
{
|
||||
favoritesJson.Add(userId.ToString(), favorite);
|
||||
|
||||
@@ -2836,7 +2836,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2844,7 +2844,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2856,9 +2856,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2786,7 +2786,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2794,7 +2794,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
|
||||
@@ -1,6 +1,19 @@
|
||||
CREATE PROCEDURE [dbo].[AuthRequest_DeleteIfExpired]
|
||||
-- UserExpirationSeconds to 15 minutes (15 * 60)
|
||||
-- AdminExpirationSeconds to 7 days (7 * 24 * 60 * 60)
|
||||
-- AdminApprovalExpirationSeconds to 12 hour (12 * 60 * 60)
|
||||
|
||||
CREATE PROCEDURE [dbo].[AuthRequest_DeleteIfExpired]
|
||||
@UserExpirationSeconds INT = 900,
|
||||
@AdminExpirationSeconds INT = 604800,
|
||||
@AdminApprovalExpirationSeconds INT = 43200
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT OFF
|
||||
DELETE FROM [dbo].[AuthRequest] WHERE [CreationDate] < DATEADD(minute, -15, GETUTCDATE());
|
||||
DELETE FROM [dbo].[AuthRequest]
|
||||
-- User requests expire after 15 minutes (by default) of their creation
|
||||
WHERE ([Type] != 2 AND DATEADD(second, @UserExpirationSeconds, [CreationDate]) < GETUTCDATE())
|
||||
-- Admin requests expire after 7 days (by default) of their creation if they have not been approved
|
||||
OR ([Type] = 2 AND ([Approved] IS NULL OR [Approved] = 0) AND DATEADD(second, @AdminExpirationSeconds,[CreationDate]) < GETUTCDATE())
|
||||
-- Admin requests expire after 12 hours (by default) of their approval
|
||||
OR ([Type] = 2 AND [Approved] = 1 AND DATEADD(second, @AdminApprovalExpirationSeconds, [ResponseDate]) < GETUTCDATE());
|
||||
END
|
||||
|
||||
@@ -3273,133 +3273,133 @@
|
||||
"api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AspNetCore.HealthChecks.AzureServiceBus": "[6.1.0, )",
|
||||
"AspNetCore.HealthChecks.AzureStorage": "[6.1.2, )",
|
||||
"AspNetCore.HealthChecks.Network": "[6.0.4, )",
|
||||
"AspNetCore.HealthChecks.Redis": "[6.0.4, )",
|
||||
"AspNetCore.HealthChecks.SendGrid": "[6.0.2, )",
|
||||
"AspNetCore.HealthChecks.SqlServer": "[6.0.2, )",
|
||||
"AspNetCore.HealthChecks.Uris": "[6.0.3, )",
|
||||
"Azure.Messaging.EventGrid": "[4.10.0, )",
|
||||
"Commercial.Core": "[2023.5.0, )",
|
||||
"Commercial.Infrastructure.EntityFramework": "[2023.5.0, )",
|
||||
"Core": "[2023.5.0, )",
|
||||
"SharedWeb": "[2023.5.0, )",
|
||||
"Swashbuckle.AspNetCore": "[6.5.0, )"
|
||||
"AspNetCore.HealthChecks.AzureServiceBus": "6.1.0",
|
||||
"AspNetCore.HealthChecks.AzureStorage": "6.1.2",
|
||||
"AspNetCore.HealthChecks.Network": "6.0.4",
|
||||
"AspNetCore.HealthChecks.Redis": "6.0.4",
|
||||
"AspNetCore.HealthChecks.SendGrid": "6.0.2",
|
||||
"AspNetCore.HealthChecks.SqlServer": "6.0.2",
|
||||
"AspNetCore.HealthChecks.Uris": "6.0.3",
|
||||
"Azure.Messaging.EventGrid": "4.10.0",
|
||||
"Commercial.Core": "2023.5.1",
|
||||
"Commercial.Infrastructure.EntityFramework": "2023.5.1",
|
||||
"Core": "2023.5.1",
|
||||
"SharedWeb": "2023.5.1",
|
||||
"Swashbuckle.AspNetCore": "6.5.0"
|
||||
}
|
||||
},
|
||||
"commercial.core": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.5.0, )"
|
||||
"Core": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"commercial.infrastructure.entityframework": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.5.0, )",
|
||||
"Infrastructure.EntityFramework": "[2023.5.0, )"
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "[4.17.0, )",
|
||||
"AutoFixture.Xunit2": "[4.17.0, )",
|
||||
"Core": "[2023.5.0, )",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )",
|
||||
"Microsoft.NET.Test.Sdk": "[17.1.0, )",
|
||||
"NSubstitute": "[4.3.0, )",
|
||||
"xunit": "[2.4.1, )"
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Core": "2023.5.1",
|
||||
"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.3.2, )",
|
||||
"Azure.Storage.Blobs": "[12.14.1, )",
|
||||
"Azure.Storage.Queues": "[12.12.0, )",
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.12.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[7.0.0, )",
|
||||
"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, )"
|
||||
"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.3.2",
|
||||
"Azure.Storage.Blobs": "12.14.1",
|
||||
"Azure.Storage.Queues": "12.12.0",
|
||||
"BitPay.Light": "1.0.1907",
|
||||
"Braintree": "5.12.0",
|
||||
"DnsClient": "1.7.0",
|
||||
"Fido2.AspNet": "3.0.1",
|
||||
"Handlebars.Net": "2.1.2",
|
||||
"IdentityServer4": "4.1.2",
|
||||
"IdentityServer4.AccessTokenValidation": "3.0.1",
|
||||
"LaunchDarkly.ServerSdk": "7.0.0",
|
||||
"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.5.0, )",
|
||||
"SharedWeb": "[2023.5.0, )",
|
||||
"Swashbuckle.AspNetCore.SwaggerGen": "[6.5.0, )"
|
||||
"Core": "2023.5.1",
|
||||
"SharedWeb": "2023.5.1",
|
||||
"Swashbuckle.AspNetCore.SwaggerGen": "6.5.0"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.5.0, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
"infrastructure.entityframework": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.5.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, )"
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.5.1",
|
||||
"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.5.0, )",
|
||||
"Identity": "[2023.5.0, )",
|
||||
"Microsoft.AspNetCore.Mvc.Testing": "[6.0.5, )",
|
||||
"Microsoft.EntityFrameworkCore.InMemory": "[6.0.5, )",
|
||||
"Microsoft.Extensions.Configuration": "[6.0.1, )"
|
||||
"Common": "2023.5.1",
|
||||
"Identity": "2023.5.1",
|
||||
"Microsoft.AspNetCore.Mvc.Testing": "6.0.5",
|
||||
"Microsoft.EntityFrameworkCore.InMemory": "6.0.5",
|
||||
"Microsoft.Extensions.Configuration": "6.0.1"
|
||||
}
|
||||
},
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.5.0, )",
|
||||
"Infrastructure.Dapper": "[2023.5.0, )",
|
||||
"Infrastructure.EntityFramework": "[2023.5.0, )"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,12 +114,12 @@ public class ProjectsControllerTests
|
||||
|
||||
var resultProject = data.ToProject(orgId);
|
||||
|
||||
sutProvider.GetDependency<ICreateProjectCommand>().CreateAsync(default, default)
|
||||
sutProvider.GetDependency<ICreateProjectCommand>().CreateAsync(default, default, sutProvider.GetDependency<ICurrentContext>().ClientType)
|
||||
.ReturnsForAnyArgs(resultProject);
|
||||
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.CreateAsync(orgId, data));
|
||||
await sutProvider.GetDependency<ICreateProjectCommand>().DidNotReceiveWithAnyArgs()
|
||||
.CreateAsync(Arg.Any<Project>(), Arg.Any<Guid>());
|
||||
.CreateAsync(Arg.Any<Project>(), Arg.Any<Guid>(), sutProvider.GetDependency<ICurrentContext>().ClientType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -134,13 +134,13 @@ public class ProjectsControllerTests
|
||||
|
||||
var resultProject = data.ToProject(orgId);
|
||||
|
||||
sutProvider.GetDependency<ICreateProjectCommand>().CreateAsync(default, default)
|
||||
sutProvider.GetDependency<ICreateProjectCommand>().CreateAsync(default, default, sutProvider.GetDependency<ICurrentContext>().ClientType)
|
||||
.ReturnsForAnyArgs(resultProject);
|
||||
|
||||
await sutProvider.Sut.CreateAsync(orgId, data);
|
||||
|
||||
await sutProvider.GetDependency<ICreateProjectCommand>().Received(1)
|
||||
.CreateAsync(Arg.Any<Project>(), Arg.Any<Guid>());
|
||||
.CreateAsync(Arg.Any<Project>(), Arg.Any<Guid>(), sutProvider.GetDependency<ICurrentContext>().ClientType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
@@ -3151,129 +3151,129 @@
|
||||
"api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AspNetCore.HealthChecks.AzureServiceBus": "[6.1.0, )",
|
||||
"AspNetCore.HealthChecks.AzureStorage": "[6.1.2, )",
|
||||
"AspNetCore.HealthChecks.Network": "[6.0.4, )",
|
||||
"AspNetCore.HealthChecks.Redis": "[6.0.4, )",
|
||||
"AspNetCore.HealthChecks.SendGrid": "[6.0.2, )",
|
||||
"AspNetCore.HealthChecks.SqlServer": "[6.0.2, )",
|
||||
"AspNetCore.HealthChecks.Uris": "[6.0.3, )",
|
||||
"Azure.Messaging.EventGrid": "[4.10.0, )",
|
||||
"Commercial.Core": "[2023.5.0, )",
|
||||
"Commercial.Infrastructure.EntityFramework": "[2023.5.0, )",
|
||||
"Core": "[2023.5.0, )",
|
||||
"SharedWeb": "[2023.5.0, )",
|
||||
"Swashbuckle.AspNetCore": "[6.5.0, )"
|
||||
"AspNetCore.HealthChecks.AzureServiceBus": "6.1.0",
|
||||
"AspNetCore.HealthChecks.AzureStorage": "6.1.2",
|
||||
"AspNetCore.HealthChecks.Network": "6.0.4",
|
||||
"AspNetCore.HealthChecks.Redis": "6.0.4",
|
||||
"AspNetCore.HealthChecks.SendGrid": "6.0.2",
|
||||
"AspNetCore.HealthChecks.SqlServer": "6.0.2",
|
||||
"AspNetCore.HealthChecks.Uris": "6.0.3",
|
||||
"Azure.Messaging.EventGrid": "4.10.0",
|
||||
"Commercial.Core": "2023.5.1",
|
||||
"Commercial.Infrastructure.EntityFramework": "2023.5.1",
|
||||
"Core": "2023.5.1",
|
||||
"SharedWeb": "2023.5.1",
|
||||
"Swashbuckle.AspNetCore": "6.5.0"
|
||||
}
|
||||
},
|
||||
"commercial.core": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.5.0, )"
|
||||
"Core": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"commercial.infrastructure.entityframework": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.5.0, )",
|
||||
"Infrastructure.EntityFramework": "[2023.5.0, )"
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "[4.17.0, )",
|
||||
"AutoFixture.Xunit2": "[4.17.0, )",
|
||||
"Core": "[2023.5.0, )",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )",
|
||||
"Microsoft.NET.Test.Sdk": "[17.1.0, )",
|
||||
"NSubstitute": "[4.3.0, )",
|
||||
"xunit": "[2.4.1, )"
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Core": "2023.5.1",
|
||||
"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.3.2, )",
|
||||
"Azure.Storage.Blobs": "[12.14.1, )",
|
||||
"Azure.Storage.Queues": "[12.12.0, )",
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.12.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[7.0.0, )",
|
||||
"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, )"
|
||||
"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.3.2",
|
||||
"Azure.Storage.Blobs": "12.14.1",
|
||||
"Azure.Storage.Queues": "12.12.0",
|
||||
"BitPay.Light": "1.0.1907",
|
||||
"Braintree": "5.12.0",
|
||||
"DnsClient": "1.7.0",
|
||||
"Fido2.AspNet": "3.0.1",
|
||||
"Handlebars.Net": "2.1.2",
|
||||
"IdentityServer4": "4.1.2",
|
||||
"IdentityServer4.AccessTokenValidation": "3.0.1",
|
||||
"LaunchDarkly.ServerSdk": "7.0.0",
|
||||
"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.5.0, )",
|
||||
"Core": "[2023.5.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, )"
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Common": "2023.5.1",
|
||||
"Core": "2023.5.1",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.5.0, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
"infrastructure.entityframework": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.5.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, )"
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.5.1",
|
||||
"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.5.0, )",
|
||||
"Infrastructure.Dapper": "[2023.5.0, )",
|
||||
"Infrastructure.EntityFramework": "[2023.5.0, )"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2988,8 +2988,8 @@
|
||||
"billing": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"SharedWeb": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"SharedWeb": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
@@ -2997,7 +2997,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "17.1.0",
|
||||
"NSubstitute": "4.3.0",
|
||||
@@ -3049,7 +3049,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -3057,7 +3057,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -3069,9 +3069,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.SecretsManager.Commands.EnableAccessSecretsManager;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Bit.Test.Common.Helpers;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.SecretsManager.Commands.EnableAccessSecretsManager;
|
||||
|
||||
[SutProviderCustomize]
|
||||
public class EnableAccessSecretsManagerCommandTests
|
||||
{
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task EnableUsers_UsersAlreadyEnabled_DoesNotCallRepository(
|
||||
SutProvider<EnableAccessSecretsManagerCommand> sutProvider, ICollection<OrganizationUser> data)
|
||||
{
|
||||
foreach (var item in data)
|
||||
{
|
||||
item.AccessSecretsManager = true;
|
||||
}
|
||||
|
||||
var result = await sutProvider.Sut.EnableUsersAsync(data);
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationUserRepository>().DidNotReceiveWithAnyArgs()
|
||||
.ReplaceManyAsync(default);
|
||||
|
||||
Assert.Equal(data.Count, result.Count);
|
||||
Assert.Equal(data.Count,
|
||||
result.Where(x => x.error == "User already has access to Secrets Manager").ToList().Count);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task EnableUsers_OneUserNotEnabled_CallsRepositoryForOne(
|
||||
SutProvider<EnableAccessSecretsManagerCommand> sutProvider, ICollection<OrganizationUser> data)
|
||||
{
|
||||
var firstUser = new List<OrganizationUser>();
|
||||
foreach (var item in data)
|
||||
{
|
||||
if (item == data.First())
|
||||
{
|
||||
item.AccessSecretsManager = false;
|
||||
firstUser.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.AccessSecretsManager = true;
|
||||
}
|
||||
}
|
||||
|
||||
var result = await sutProvider.Sut.EnableUsersAsync(data);
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1)
|
||||
.ReplaceManyAsync(Arg.Is(AssertHelper.AssertPropertyEqual(firstUser)));
|
||||
|
||||
Assert.Equal(data.Count, result.Count);
|
||||
Assert.Equal(data.Count - 1,
|
||||
result.Where(x => x.error == "User already has access to Secrets Manager").ToList().Count);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task EnableUsers_Success(
|
||||
SutProvider<EnableAccessSecretsManagerCommand> sutProvider, ICollection<OrganizationUser> data)
|
||||
{
|
||||
foreach (var item in data)
|
||||
{
|
||||
item.AccessSecretsManager = false;
|
||||
}
|
||||
|
||||
var result = await sutProvider.Sut.EnableUsersAsync(data);
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1)
|
||||
.ReplaceManyAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data)));
|
||||
|
||||
Assert.Equal(data.Count, result.Count);
|
||||
}
|
||||
}
|
||||
@@ -2825,7 +2825,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "17.1.0",
|
||||
"NSubstitute": "4.3.0",
|
||||
|
||||
@@ -2972,14 +2972,14 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AngleSharp": "0.16.1",
|
||||
"Core": "2023.4.3",
|
||||
"SharedWeb": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"SharedWeb": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2987,7 +2987,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -2999,9 +2999,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3144,7 +3144,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "17.1.0",
|
||||
"NSubstitute": "4.3.0",
|
||||
@@ -3196,15 +3196,15 @@
|
||||
"identity": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"SharedWeb": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"SharedWeb": "2023.5.1",
|
||||
"Swashbuckle.AspNetCore.SwaggerGen": "6.5.0"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -3212,7 +3212,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -3224,8 +3224,8 @@
|
||||
"integrationtestcommon": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Common": "2023.4.3",
|
||||
"Identity": "2023.4.3",
|
||||
"Common": "2023.5.1",
|
||||
"Identity": "2023.5.1",
|
||||
"Microsoft.AspNetCore.Mvc.Testing": "6.0.5",
|
||||
"Microsoft.EntityFrameworkCore.InMemory": "6.0.5",
|
||||
"Microsoft.Extensions.Configuration": "6.0.1"
|
||||
@@ -3234,9 +3234,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3011,7 +3011,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "17.1.0",
|
||||
"NSubstitute": "4.3.0",
|
||||
@@ -3063,15 +3063,15 @@
|
||||
"identity": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"SharedWeb": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"SharedWeb": "2023.5.1",
|
||||
"Swashbuckle.AspNetCore.SwaggerGen": "6.5.0"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -3079,7 +3079,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -3091,9 +3091,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3001,7 +3001,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "17.1.0",
|
||||
"NSubstitute": "4.3.0",
|
||||
@@ -3055,8 +3055,8 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Common": "2023.4.3",
|
||||
"Core": "2023.4.3",
|
||||
"Common": "2023.5.1",
|
||||
"Core": "2023.5.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "17.1.0",
|
||||
"Moq": "4.17.2",
|
||||
@@ -3067,7 +3067,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -3075,7 +3075,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Repositories;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Infrastructure.IntegrationTest.Auth.Repositories;
|
||||
|
||||
public class AuthRequestRepositoryTests
|
||||
{
|
||||
private readonly static TimeSpan _userRequestExpiration = TimeSpan.FromMinutes(15);
|
||||
private readonly static TimeSpan _adminRequestExpiration = TimeSpan.FromDays(6);
|
||||
private readonly static TimeSpan _afterAdminApprovalExpiration = TimeSpan.FromHours(12);
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task DeleteExpiredAsync_Works(
|
||||
IAuthRequestRepository authRequestRepository,
|
||||
IUserRepository userRepository,
|
||||
ITestDatabaseHelper helper)
|
||||
{
|
||||
var user = await userRepository.CreateAsync(new User
|
||||
{
|
||||
Name = "Test User",
|
||||
Email = $"test+{Guid.NewGuid()}@email.com",
|
||||
ApiKey = "TEST",
|
||||
SecurityStamp = "stamp",
|
||||
});
|
||||
|
||||
// A user auth request type that has passed it's expiration time, should be deleted.
|
||||
var userExpiredAuthRequest = await authRequestRepository.CreateAsync(
|
||||
CreateAuthRequest(user.Id, AuthRequestType.AuthenticateAndUnlock, CreateExpiredDate(_userRequestExpiration)));
|
||||
|
||||
// An AdminApproval request that hasn't had any action taken on it and has passed it's expiration time, should be deleted.
|
||||
var adminApprovalExpiredAuthRequest = await authRequestRepository.CreateAsync(
|
||||
CreateAuthRequest(user.Id, AuthRequestType.AdminApproval, CreateExpiredDate(_adminRequestExpiration)));
|
||||
|
||||
// An AdminApproval request that was approved before it expired but the user has been approved for too long, should be deleted.
|
||||
var adminApprovedExpiredAuthRequest = await authRequestRepository.CreateAsync(
|
||||
CreateAuthRequest(user.Id, AuthRequestType.AdminApproval, DateTime.UtcNow.AddDays(-6), true, CreateExpiredDate(_afterAdminApprovalExpiration)));
|
||||
|
||||
// An AdminApproval request that was rejected within it's allowed lifetime but has no gone past it's expiration time, should be deleted.
|
||||
var adminRejectedExpiredAuthRequest = await authRequestRepository.CreateAsync(
|
||||
CreateAuthRequest(user.Id, AuthRequestType.AdminApproval, CreateExpiredDate(_adminRequestExpiration), false, DateTime.UtcNow.AddHours(-1)));
|
||||
|
||||
// A User AuthRequest that was created just a minute ago.
|
||||
var notExpiredUserAuthRequest = await authRequestRepository.CreateAsync(
|
||||
CreateAuthRequest(user.Id, AuthRequestType.Unlock, DateTime.UtcNow.AddMinutes(-1)));
|
||||
|
||||
// An AdminApproval AuthRequest that was create 6 days 23 hours 59 minutes 59 seconds ago which is right on the edge of still being valid
|
||||
var notExpiredAdminApprovalRequest = await authRequestRepository.CreateAsync(
|
||||
CreateAuthRequest(user.Id, AuthRequestType.AdminApproval, DateTime.UtcNow.Add(new TimeSpan(days: 6, hours: 23, minutes: 59, seconds: 59))));
|
||||
|
||||
// An AdminApproval AuthRequest that was created a week ago but just approved 11 hours ago.
|
||||
var notExpiredApprovedAdminApprovalRequest = await authRequestRepository.CreateAsync(
|
||||
CreateAuthRequest(user.Id, AuthRequestType.AdminApproval, DateTime.UtcNow.AddDays(7), true, DateTime.UtcNow.AddHours(11)));
|
||||
|
||||
helper.ClearTracker();
|
||||
|
||||
var numberOfDeleted = await authRequestRepository.DeleteExpiredAsync(_userRequestExpiration, _adminRequestExpiration, _afterAdminApprovalExpiration);
|
||||
|
||||
// Ensure all the AuthRequests that should have been deleted, have been deleted.
|
||||
Assert.Null(await authRequestRepository.GetByIdAsync(userExpiredAuthRequest.Id));
|
||||
Assert.Null(await authRequestRepository.GetByIdAsync(adminApprovalExpiredAuthRequest.Id));
|
||||
Assert.Null(await authRequestRepository.GetByIdAsync(adminApprovedExpiredAuthRequest.Id));
|
||||
Assert.Null(await authRequestRepository.GetByIdAsync(adminRejectedExpiredAuthRequest.Id));
|
||||
|
||||
// Ensure that all the AuthRequests that should have been left alone, were.
|
||||
Assert.NotNull(await authRequestRepository.GetByIdAsync(notExpiredUserAuthRequest.Id));
|
||||
Assert.NotNull(await authRequestRepository.GetByIdAsync(notExpiredAdminApprovalRequest.Id));
|
||||
Assert.NotNull(await authRequestRepository.GetByIdAsync(notExpiredApprovedAdminApprovalRequest.Id));
|
||||
|
||||
// Ensure the repository responds with the amount of items it deleted and it deleted the right amount.
|
||||
// NOTE: On local development this might fail on it's first run because the developer could have expired AuthRequests
|
||||
// on their machine but aren't running the job that would delete them. The second run of this test should succeed.
|
||||
Assert.Equal(4, numberOfDeleted);
|
||||
}
|
||||
|
||||
private static AuthRequest CreateAuthRequest(Guid userId, AuthRequestType authRequestType, DateTime creationDate, bool? approved = null, DateTime? responseDate = null)
|
||||
{
|
||||
return new AuthRequest
|
||||
{
|
||||
UserId = userId,
|
||||
Type = authRequestType,
|
||||
Approved = approved,
|
||||
RequestDeviceIdentifier = "something", // TODO: EF Doesn't enforce this as not null
|
||||
RequestIpAddress = "1.1.1.1", // TODO: EF Doesn't enforce this as not null
|
||||
AccessCode = "test_access_code", // TODO: EF Doesn't enforce this as not null
|
||||
PublicKey = "test_public_key", // TODO: EF Doesn't enforce this as not null
|
||||
CreationDate = creationDate,
|
||||
ResponseDate = responseDate,
|
||||
};
|
||||
}
|
||||
|
||||
private static DateTime CreateExpiredDate(TimeSpan expirationPeriod)
|
||||
{
|
||||
var exp = expirationPeriod + TimeSpan.FromMinutes(1);
|
||||
return DateTime.UtcNow.Add(exp.Negate());
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Bit.Core.Entities;
|
||||
using System.Text.Json;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Repositories;
|
||||
@@ -121,4 +122,84 @@ public class CipherRepositoryTests
|
||||
var collectionCiphers = await collectionCipherRepository.GetManyByOrganizationIdAsync(organization.Id);
|
||||
Assert.NotEmpty(collectionCiphers);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task ReplaceAsync_SuccessfullyMovesCipherToOrganization(IUserRepository userRepository,
|
||||
ICipherRepository cipherRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IFolderRepository folderRepository,
|
||||
ITestDatabaseHelper helper)
|
||||
{
|
||||
// This tests what happens when a cipher is moved into an organizations
|
||||
var user = await userRepository.CreateAsync(new User
|
||||
{
|
||||
Name = "Test User",
|
||||
Email = $"test+{Guid.NewGuid()}@email.com",
|
||||
ApiKey = "TEST",
|
||||
SecurityStamp = "stamp",
|
||||
});
|
||||
|
||||
|
||||
user = await userRepository.GetByIdAsync(user.Id);
|
||||
|
||||
// Create cipher in personal vault
|
||||
var createdCipher = await cipherRepository.CreateAsync(new Cipher
|
||||
{
|
||||
UserId = user.Id,
|
||||
Data = "", // TODO: EF does not enforce this as NOT NULL
|
||||
});
|
||||
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = "Test Organization",
|
||||
BillingEmail = user.Email,
|
||||
Plan = "Test" // TODO: EF does not enforce this as NOT NULL
|
||||
});
|
||||
|
||||
_ = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
UserId = user.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Type = OrganizationUserType.Owner,
|
||||
});
|
||||
|
||||
var folder = await folderRepository.CreateAsync(new Folder
|
||||
{
|
||||
Name = "FolderName",
|
||||
UserId = user.Id,
|
||||
});
|
||||
|
||||
helper.ClearTracker();
|
||||
|
||||
// Move cipher to organization vault
|
||||
await cipherRepository.ReplaceAsync(new CipherDetails
|
||||
{
|
||||
Id = createdCipher.Id,
|
||||
UserId = user.Id,
|
||||
OrganizationId = organization.Id,
|
||||
FolderId = folder.Id,
|
||||
Data = "", // TODO: EF does not enforce this as NOT NULL
|
||||
});
|
||||
|
||||
var updatedCipher = await cipherRepository.GetByIdAsync(createdCipher.Id);
|
||||
|
||||
Assert.Null(updatedCipher.UserId);
|
||||
Assert.Equal(organization.Id, updatedCipher.OrganizationId);
|
||||
Assert.NotNull(updatedCipher.Folders);
|
||||
|
||||
using var foldersJsonDocument = JsonDocument.Parse(updatedCipher.Folders);
|
||||
var foldersJsonElement = foldersJsonDocument.RootElement;
|
||||
Assert.Equal(JsonValueKind.Object, foldersJsonElement.ValueKind);
|
||||
|
||||
// TODO: Should we force similar casing for guids across DB's
|
||||
// I'd rather we only interact with them as the actual Guid type
|
||||
var userProperty = foldersJsonElement
|
||||
.EnumerateObject()
|
||||
.FirstOrDefault(jp => string.Equals(jp.Name, user.Id.ToString(), StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
Assert.NotEqual(default, userProperty);
|
||||
Assert.Equal(folder.Id, userProperty.Value.GetGuid());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2901,7 +2901,7 @@
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -2909,7 +2909,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
|
||||
@@ -3130,7 +3130,7 @@
|
||||
"dependencies": {
|
||||
"AutoFixture.AutoNSubstitute": "4.17.0",
|
||||
"AutoFixture.Xunit2": "4.17.0",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0",
|
||||
"Microsoft.NET.Test.Sdk": "17.1.0",
|
||||
"NSubstitute": "4.3.0",
|
||||
@@ -3182,15 +3182,15 @@
|
||||
"identity": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"SharedWeb": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"SharedWeb": "2023.5.1",
|
||||
"Swashbuckle.AspNetCore.SwaggerGen": "6.5.0"
|
||||
}
|
||||
},
|
||||
"infrastructure.dapper": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
@@ -3198,7 +3198,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
@@ -3210,9 +3210,9 @@
|
||||
"sharedweb": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Infrastructure.Dapper": "2023.4.3",
|
||||
"Infrastructure.EntityFramework": "2023.4.3"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
IF OBJECT_ID('[dbo].[AuthRequest_DeleteIfExpired]') IS NOT NULL
|
||||
BEGIN
|
||||
DROP PROCEDURE [dbo].[AuthRequest_DeleteIfExpired]
|
||||
END
|
||||
GO
|
||||
|
||||
-- UserExpirationSeconds to 15 minutes (15 * 60)
|
||||
-- AdminExpirationSeconds to 7 days (7 * 24 * 60 * 60)
|
||||
-- AdminApprovalExpirationSeconds to 12 hour (12 * 60 * 60)
|
||||
|
||||
CREATE PROCEDURE [dbo].[AuthRequest_DeleteIfExpired]
|
||||
@UserExpirationSeconds INT = 900,
|
||||
@AdminExpirationSeconds INT = 604800,
|
||||
@AdminApprovalExpirationSeconds INT = 43200
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT OFF
|
||||
DELETE FROM [dbo].[AuthRequest]
|
||||
-- User requests expire after 15 minutes (by default) of their creation
|
||||
WHERE ([Type] != 2 AND DATEADD(second, @UserExpirationSeconds, [CreationDate]) < GETUTCDATE())
|
||||
-- Admin requests expire after 7 days (by default) of their creation if they have not been approved
|
||||
OR ([Type] = 2 AND ([Approved] IS NULL OR [Approved] = 0) AND DATEADD(second, @AdminExpirationSeconds,[CreationDate]) < GETUTCDATE())
|
||||
-- Admin requests expire after 12 hours (by default) of their approval
|
||||
OR ([Type] = 2 AND [Approved] = 1 AND DATEADD(second, @AdminApprovalExpirationSeconds, [ResponseDate]) < GETUTCDATE());
|
||||
END
|
||||
@@ -2729,7 +2729,7 @@
|
||||
"migrator": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.Extensions.Logging": "6.0.0",
|
||||
"dbup-sqlserver": "5.0.8"
|
||||
}
|
||||
|
||||
@@ -2797,7 +2797,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
|
||||
@@ -2797,7 +2797,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
|
||||
@@ -73,6 +73,7 @@ public class EnvironmentFileBuilder
|
||||
_globalOverrideValues = new Dictionary<string, string>
|
||||
{
|
||||
["globalSettings__baseServiceUri__vault"] = _context.Config.Url,
|
||||
["globalSettings__baseServiceUri__cloudVaultRegion"] = "US",
|
||||
["globalSettings__sqlServer__connectionString"] = $"\"{dbConnectionString.Replace("\"", "\\\"")}\"",
|
||||
["globalSettings__identityServer__certificatePassword"] = _context.Install?.IdentityCertPassword,
|
||||
["globalSettings__internalIdentityKey"] = _context.Stub ? "RANDOM_IDENTITY_KEY" :
|
||||
|
||||
@@ -2706,7 +2706,7 @@
|
||||
"migrator": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.Extensions.Logging": "6.0.0",
|
||||
"dbup-sqlserver": "5.0.8"
|
||||
}
|
||||
|
||||
@@ -2913,103 +2913,103 @@
|
||||
"api": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AspNetCore.HealthChecks.AzureServiceBus": "[6.1.0, )",
|
||||
"AspNetCore.HealthChecks.AzureStorage": "[6.1.2, )",
|
||||
"AspNetCore.HealthChecks.Network": "[6.0.4, )",
|
||||
"AspNetCore.HealthChecks.Redis": "[6.0.4, )",
|
||||
"AspNetCore.HealthChecks.SendGrid": "[6.0.2, )",
|
||||
"AspNetCore.HealthChecks.SqlServer": "[6.0.2, )",
|
||||
"AspNetCore.HealthChecks.Uris": "[6.0.3, )",
|
||||
"Azure.Messaging.EventGrid": "[4.10.0, )",
|
||||
"Commercial.Core": "[2023.5.0, )",
|
||||
"Commercial.Infrastructure.EntityFramework": "[2023.5.0, )",
|
||||
"Core": "[2023.5.0, )",
|
||||
"SharedWeb": "[2023.5.0, )",
|
||||
"Swashbuckle.AspNetCore": "[6.5.0, )"
|
||||
"AspNetCore.HealthChecks.AzureServiceBus": "6.1.0",
|
||||
"AspNetCore.HealthChecks.AzureStorage": "6.1.2",
|
||||
"AspNetCore.HealthChecks.Network": "6.0.4",
|
||||
"AspNetCore.HealthChecks.Redis": "6.0.4",
|
||||
"AspNetCore.HealthChecks.SendGrid": "6.0.2",
|
||||
"AspNetCore.HealthChecks.SqlServer": "6.0.2",
|
||||
"AspNetCore.HealthChecks.Uris": "6.0.3",
|
||||
"Azure.Messaging.EventGrid": "4.10.0",
|
||||
"Commercial.Core": "2023.5.1",
|
||||
"Commercial.Infrastructure.EntityFramework": "2023.5.1",
|
||||
"Core": "2023.5.1",
|
||||
"SharedWeb": "2023.5.1",
|
||||
"Swashbuckle.AspNetCore": "6.5.0"
|
||||
}
|
||||
},
|
||||
"commercial.core": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"Core": "[2023.5.0, )"
|
||||
"Core": "2023.5.1"
|
||||
}
|
||||
},
|
||||
"commercial.infrastructure.entityframework": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.5.0, )",
|
||||
"Infrastructure.EntityFramework": "[2023.5.0, )"
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.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.3.2, )",
|
||||
"Azure.Storage.Blobs": "[12.14.1, )",
|
||||
"Azure.Storage.Queues": "[12.12.0, )",
|
||||
"BitPay.Light": "[1.0.1907, )",
|
||||
"Braintree": "[5.12.0, )",
|
||||
"DnsClient": "[1.7.0, )",
|
||||
"Fido2.AspNet": "[3.0.1, )",
|
||||
"Handlebars.Net": "[2.1.2, )",
|
||||
"IdentityServer4": "[4.1.2, )",
|
||||
"IdentityServer4.AccessTokenValidation": "[3.0.1, )",
|
||||
"LaunchDarkly.ServerSdk": "[7.0.0, )",
|
||||
"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, )"
|
||||
"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.3.2",
|
||||
"Azure.Storage.Blobs": "12.14.1",
|
||||
"Azure.Storage.Queues": "12.12.0",
|
||||
"BitPay.Light": "1.0.1907",
|
||||
"Braintree": "5.12.0",
|
||||
"DnsClient": "1.7.0",
|
||||
"Fido2.AspNet": "3.0.1",
|
||||
"Handlebars.Net": "2.1.2",
|
||||
"IdentityServer4": "4.1.2",
|
||||
"IdentityServer4.AccessTokenValidation": "3.0.1",
|
||||
"LaunchDarkly.ServerSdk": "7.0.0",
|
||||
"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.5.0, )",
|
||||
"Dapper": "[2.0.123, )"
|
||||
"Core": "2023.5.1",
|
||||
"Dapper": "2.0.123"
|
||||
}
|
||||
},
|
||||
"infrastructure.entityframework": {
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )",
|
||||
"Core": "[2023.5.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, )"
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.5.1",
|
||||
"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.5.0, )",
|
||||
"Infrastructure.Dapper": "[2023.5.0, )",
|
||||
"Infrastructure.EntityFramework": "[2023.5.0, )"
|
||||
"Core": "2023.5.1",
|
||||
"Infrastructure.Dapper": "2023.5.1",
|
||||
"Infrastructure.EntityFramework": "2023.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2797,7 +2797,7 @@
|
||||
"type": "Project",
|
||||
"dependencies": {
|
||||
"AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1",
|
||||
"Core": "2023.4.3",
|
||||
"Core": "2023.5.1",
|
||||
"Microsoft.EntityFrameworkCore.Relational": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "6.0.12",
|
||||
"Microsoft.EntityFrameworkCore.Sqlite": "6.0.12",
|
||||
|
||||
Reference in New Issue
Block a user