diff --git a/.github/labeler.yml b/.github/labeler.yml index f81c04b78..8c239208b 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -8,11 +8,11 @@ iOS: - src/Core/* - lib/ios/* - src/iOS/* -- src/iOS.Autofill/* -- src/iOS.Core/* -- src/iOS.Extension/* -- src/iOS.ShareExtension/* -- src/iOS.Widget/* +- 'src/iOS.Autofill/*' +- 'src/iOS.Core/*' +- 'src/iOS.Extension/*' +- 'src/iOS.ShareExtension/*' +- 'src/iOS.Widget/*' - src/watchOS/* watchOS: diff --git a/.github/workflows/automatic-issue-responses.yml b/.github/workflows/automatic-issue-responses.yml index 970532ab1..c07b8f15f 100644 --- a/.github/workflows/automatic-issue-responses.yml +++ b/.github/workflows/automatic-issue-responses.yml @@ -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@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1 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@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1 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@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1 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@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1 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@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1 with: comment: | As we haven’t heard from you about this problem in some time, this issue will now be closed. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 99ac13f0f..452fe72b8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout repo - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Set up CLOC run: | @@ -36,7 +36,7 @@ jobs: hotfix_branch_exists: ${{ steps.branch-check.outputs.hotfix_branch_exists }} steps: - name: Checkout repo - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 with: submodules: 'true' @@ -67,12 +67,12 @@ jobs: variant: ["prod", "qa"] steps: - name: Setup NuGet - uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6 + uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 with: nuget-version: 5.9.0 - name: Set up MSBuild - uses: microsoft/setup-msbuild@ab534842b4bdf384b8aaf93765dc6f721d9f5fab + uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # v1.3.1 - name: Setup Windows builder run: choco install checksum --no-progress @@ -105,7 +105,7 @@ jobs: echo "GitHub event: $GITHUB_EVENT" - name: Checkout repo - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 with: fetch-depth: 0 - name: Decrypt secrets @@ -157,7 +157,7 @@ jobs: shell: pwsh - name: Report test results - uses: dorny/test-reporter@c9b3d0e2bd2a4e96aaf424dbaa31c46b42318226 + uses: dorny/test-reporter@c9b3d0e2bd2a4e96aaf424dbaa31c46b42318226 # v1.6.0 if: always() with: name: Test Results @@ -232,7 +232,7 @@ jobs: shell: pwsh - name: Upload Prod .aab artifact if: ${{ matrix.variant == 'prod' }} - uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 with: name: com.x8bit.bitwarden.aab path: ./com.x8bit.bitwarden.aab @@ -240,7 +240,7 @@ jobs: - name: Upload Prod .apk artifact if: ${{ matrix.variant == 'prod' }} - uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 with: name: com.x8bit.bitwarden.apk path: ./com.x8bit.bitwarden.apk @@ -248,7 +248,7 @@ jobs: - name: Upload Other .apk artifact if: ${{ matrix.variant != 'prod' }} - uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 with: name: com.x8bit.bitwarden.${{ matrix.variant }}.apk path: ./com.x8bit.bitwarden.${{ matrix.variant }}.apk @@ -268,7 +268,7 @@ jobs: - name: Upload .apk sha file for prod if: ${{ matrix.variant == 'prod' }} - uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 with: name: bw-android-apk-sha256.txt path: ./bw-android-apk-sha256.txt @@ -276,7 +276,7 @@ jobs: - name: Upload .apk sha file for other if: ${{ matrix.variant != 'prod' }} - uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 with: name: bw-android-${{ matrix.variant }}-apk-sha256.txt path: ./bw-android-${{ matrix.variant }}-apk-sha256.txt @@ -303,12 +303,12 @@ jobs: runs-on: windows-2022 steps: - name: Setup NuGet - uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6 + uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 with: nuget-version: 5.9.0 - name: Set up MSBuild - uses: microsoft/setup-msbuild@ab534842b4bdf384b8aaf93765dc6f721d9f5fab + uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # v1.3.1 - name: Setup Windows builder run: choco install checksum --no-progress @@ -342,7 +342,7 @@ jobs: echo "GitHub event: $GITHUB_EVENT" - name: Checkout repo - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Decrypt secrets env: @@ -477,7 +477,7 @@ jobs: shell: pwsh - name: Upload F-Droid .apk artifact - uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 with: name: com.x8bit.bitwarden-fdroid.apk path: ./com.x8bit.bitwarden-fdroid.apk @@ -489,7 +489,7 @@ jobs: -t sha256 | Out-File -Encoding ASCII ./bw-fdroid-apk-sha256.txt - name: Upload F-Droid sha file - uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 with: name: bw-fdroid-apk-sha256.txt path: ./bw-fdroid-apk-sha256.txt @@ -502,7 +502,7 @@ jobs: needs: setup steps: - name: Setup NuGet - uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6 + uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 with: nuget-version: 5.9.0 @@ -515,12 +515,12 @@ jobs: echo "GitHub event: $GITHUB_EVENT" - name: Checkout repo - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 with: submodules: 'true' - name: Login to Azure - CI Subscription - uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} @@ -698,7 +698,7 @@ jobs: shell: bash - name: Upload App Store .ipa & dSYMs artifacts - uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 with: name: Bitwarden iOS path: | @@ -771,10 +771,10 @@ jobs: _CROWDIN_PROJECT_ID: "269690" steps: - name: Checkout repo - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Login to Azure - CI Subscription - uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} @@ -793,7 +793,7 @@ jobs: done - name: Upload Sources - uses: crowdin/github-action@9237b4cb361788dfce63feb2e2f15c09e2fe7415 + uses: crowdin/github-action@ecd7eb0ef6f3cfa16293c79e9cbc4bc5b5fd9c49 # v1.4.9 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} @@ -840,7 +840,7 @@ jobs: fi - name: Login to Azure - CI Subscription - uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3 if: failure() with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} @@ -861,7 +861,7 @@ jobs: done - name: Notify Slack on failure - uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33 + uses: act10ns/slack@ed1309ab9862e57e9e583e51c7889486b9a00b0f # v2.0.0 if: failure() env: SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }} diff --git a/.github/workflows/crowdin-pull.yml b/.github/workflows/crowdin-pull.yml index 47fb6bf32..36aaaa9ab 100644 --- a/.github/workflows/crowdin-pull.yml +++ b/.github/workflows/crowdin-pull.yml @@ -15,22 +15,22 @@ jobs: _CROWDIN_PROJECT_ID: "269690" steps: - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Login to Azure - CI Subscription - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c3b3285993151c5af47cefcb3b9134c28ab479af + uses: bitwarden/gh-actions/get-keyvault-secrets@34ecb67b2a357795dc893549df0795e7383ff50f with: keyvault: "bitwarden-ci" secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase" - name: Download translations - uses: crowdin/github-action@12143a68c213f3c6d9913c9e5023224f7231face + uses: crowdin/github-action@ecd7eb0ef6f3cfa16293c79e9cbc4bc5b5fd9c49 # v1.4.9 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} diff --git a/.github/workflows/enforce-labels.yml b/.github/workflows/enforce-labels.yml index 9f321cece..417e34e9b 100644 --- a/.github/workflows/enforce-labels.yml +++ b/.github/workflows/enforce-labels.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Enforce Label - uses: yogevbd/enforce-label-action@8d1e1709b1011e6d90400a0e6cf7c0b77aa5efeb + uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 # v2.2.2 with: BANNED_LABELS: "hold,needs-qa" BANNED_LABELS_DESCRIPTION: "PRs with the hold or needs-qa labels cannot be merged" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 41cc4e4d2..f1e57bbe9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,11 +38,11 @@ jobs: fi - name: Checkout repo - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@8f055ef543c7433c967a1b9b04a0f230923233bb + uses: bitwarden/gh-actions/release-version-check@34ecb67b2a357795dc893549df0795e7383ff50f with: release-type: ${{ github.event.inputs.release_type }} project-type: xamarin @@ -56,7 +56,7 @@ jobs: - name: Create GitHub deployment if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: chrnorm/deployment-action@1b599fe41a0ef1f95191e7f2eec4743f2d7dfc48 + uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5 id: deployment with: token: '${{ secrets.GITHUB_TOKEN }}' @@ -104,7 +104,7 @@ jobs: - name: Update deployment status to Success if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }} - uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86 + uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 with: token: '${{ secrets.GITHUB_TOKEN }}' state: 'success' @@ -112,7 +112,7 @@ jobs: - name: Update deployment status to Failure if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }} - uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86 + uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 with: token: '${{ secrets.GITHUB_TOKEN }}' state: 'failure' @@ -126,7 +126,7 @@ jobs: if: inputs.fdroid_publish steps: - name: Checkout repo - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Download F-Droid .apk artifact if: ${{ github.event.inputs.release_type != 'Dry Run' }} diff --git a/.github/workflows/version-auto-bump.yml b/.github/workflows/version-auto-bump.yml index 3bc26d84a..5e2d17fb9 100644 --- a/.github/workflows/version-auto-bump.yml +++ b/.github/workflows/version-auto-bump.yml @@ -14,7 +14,7 @@ jobs: version_number: ${{ steps.version.outputs.new-version }} steps: - name: Checkout Branch - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Calculate bumped version id: version diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index f0f6590fc..bac7c2227 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -22,22 +22,22 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout Branch - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - name: Login to Azure - CI Subscription - uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c3b3285993151c5af47cefcb3b9134c28ab479af + uses: bitwarden/gh-actions/get-keyvault-secrets@34ecb67b2a357795dc893549df0795e7383ff50f with: keyvault: "bitwarden-ci" secrets: "github-gpg-private-key, github-gpg-private-key-passphrase" - name: Import GPG key - uses: crazy-max/ghaction-import-gpg@c8bb57c57e8df1be8c73ff3d59deab1dbc00e0d1 + uses: crazy-max/ghaction-import-gpg@111c56156bcc6918c056dbef52164cfa583dc549 # v5.2.0 with: gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }} passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }} @@ -48,31 +48,31 @@ jobs: run: git switch -c version_bump_${{ github.event.inputs.version_number }} - name: Bump Version - Android XML - uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 + uses: bitwarden/gh-actions/version-bump@34ecb67b2a357795dc893549df0795e7383ff50f with: version: ${{ github.event.inputs.version_number }} file_path: "./src/Android/Properties/AndroidManifest.xml" - name: Bump Version - iOS.Autofill - uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 + uses: bitwarden/gh-actions/version-bump@34ecb67b2a357795dc893549df0795e7383ff50f with: version: ${{ github.event.inputs.version_number }} file_path: "./src/iOS.Autofill/Info.plist" - name: Bump Version - iOS.Extension - uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 + uses: bitwarden/gh-actions/version-bump@34ecb67b2a357795dc893549df0795e7383ff50f with: version: ${{ github.event.inputs.version_number }} file_path: "./src/iOS.Extension/Info.plist" - name: Bump Version - iOS.ShareExtension - uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 + uses: bitwarden/gh-actions/version-bump@34ecb67b2a357795dc893549df0795e7383ff50f with: version: ${{ github.event.inputs.version_number }} file_path: "./src/iOS.ShareExtension/Info.plist" - name: Bump Version - iOS - uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 + uses: bitwarden/gh-actions/version-bump@34ecb67b2a357795dc893549df0795e7383ff50f with: version: ${{ github.event.inputs.version_number }} file_path: "./src/iOS/Info.plist" diff --git a/.github/workflows/workflow-linter.yml b/.github/workflows/workflow-linter.yml index 9fda2eee0..9db5d644a 100644 --- a/.github/workflows/workflow-linter.yml +++ b/.github/workflows/workflow-linter.yml @@ -8,4 +8,4 @@ on: jobs: call-workflow: - uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@master + uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@34ecb67b2a357795dc893549df0795e7383ff50f diff --git a/src/Android/Android.csproj b/src/Android/Android.csproj index c285cad13..4b42db250 100644 --- a/src/Android/Android.csproj +++ b/src/Android/Android.csproj @@ -78,21 +78,20 @@ 1.9.0 - - - - + + + - 1.7.3 + 1.7.5 - 123.0.8 + 123.1.1.1 - - + + - 118.0.1.2 + 118.0.1.3 diff --git a/src/App/App.csproj b/src/App/App.csproj index 7901bcca6..83e1ee879 100644 --- a/src/App/App.csproj +++ b/src/App/App.csproj @@ -14,11 +14,11 @@ - - - + + + - + diff --git a/src/App/App.xaml.cs b/src/App/App.xaml.cs index 059159eb7..aa839370b 100644 --- a/src/App/App.xaml.cs +++ b/src/App/App.xaml.cs @@ -38,6 +38,7 @@ namespace Bit.App private readonly IFileService _fileService; private readonly IAccountsManager _accountsManager; private readonly IPushNotificationService _pushNotificationService; + private readonly IConfigService _configService; private static bool _isResumed; // these variables are static because the app is launching new activities on notification click, creating new instances of App. private static bool _pendingCheckPasswordlessLoginRequests; @@ -61,6 +62,7 @@ namespace Bit.App _fileService = ServiceContainer.Resolve(); _accountsManager = ServiceContainer.Resolve("accountsManager"); _pushNotificationService = ServiceContainer.Resolve(); + _configService = ServiceContainer.Resolve(); _accountsManager.Init(() => Options, this); @@ -169,6 +171,10 @@ namespace Bit.App new NavigationPage(new UpdateTempPasswordPage())); }); } + else if (message.Command == "syncCompleted") + { + await _configService.GetAsync(true); + } else if (message.Command == Constants.PasswordlessLoginRequestKey || message.Command == "unlocked" || message.Command == AccountsManagerMessageCommands.ACCOUNT_SWITCH_COMPLETED) @@ -293,6 +299,8 @@ namespace Bit.App // Reset delay on every start _vaultTimeoutService.DelayLockAndLogoutMs = null; } + + await _configService.GetAsync(); _messagingService.Send("startEventTimer"); } diff --git a/src/App/Pages/Accounts/EnvironmentPageViewModel.cs b/src/App/Pages/Accounts/EnvironmentPageViewModel.cs index 90fc8e698..abac94084 100644 --- a/src/App/Pages/Accounts/EnvironmentPageViewModel.cs +++ b/src/App/Pages/Accounts/EnvironmentPageViewModel.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using System.Windows.Input; using Bit.App.Resources; using Bit.Core.Abstractions; +using Bit.Core.Models.Data; using Bit.Core.Utilities; using Xamarin.CommunityToolkit.ObjectModel; @@ -18,7 +19,8 @@ namespace Bit.App.Pages _environmentService = ServiceContainer.Resolve("environmentService"); PageTitle = AppResources.Settings; - BaseUrl = _environmentService.BaseUrl; + BaseUrl = _environmentService.BaseUrl == EnvironmentUrlData.DefaultEU.Base || EnvironmentUrlData.DefaultUS.Base == _environmentService.BaseUrl ? + string.Empty : _environmentService.BaseUrl; WebVaultUrl = _environmentService.WebVaultUrl; ApiUrl = _environmentService.ApiUrl; IdentityUrl = _environmentService.IdentityUrl; diff --git a/src/App/Pages/Accounts/HomePage.xaml b/src/App/Pages/Accounts/HomePage.xaml index 0bb2b6ebf..b44a243f9 100644 --- a/src/App/Pages/Accounts/HomePage.xaml +++ b/src/App/Pages/Accounts/HomePage.xaml @@ -25,10 +25,6 @@ AutomationProperties.IsInAccessibleTree="True" AutomationProperties.Name="{u:I18n Account}" /> - @@ -66,7 +62,27 @@ + Margin="0, 6, 0 ,0"> + + + + + diff --git a/src/App/Pages/Accounts/HomePage.xaml.cs b/src/App/Pages/Accounts/HomePage.xaml.cs index cc5fdeccc..c374afe9f 100644 --- a/src/App/Pages/Accounts/HomePage.xaml.cs +++ b/src/App/Pages/Accounts/HomePage.xaml.cs @@ -15,6 +15,8 @@ namespace Bit.App.Pages private readonly AppOptions _appOptions; private IBroadcasterService _broadcasterService; + readonly LazyResolve _logger = new LazyResolve(); + public HomePage(AppOptions appOptions = null) { _broadcasterService = ServiceContainer.Resolve("broadcasterService"); @@ -70,6 +72,14 @@ namespace Bit.App.Pages }); } }); + try + { + await _vm.UpdateEnvironment(); + } + catch (Exception ex) + { + _logger.Value?.Exception(ex); + } } protected override bool OnBackButtonPressed() @@ -128,14 +138,6 @@ namespace Bit.App.Pages await Navigation.PushModalAsync(new NavigationPage(page)); } - private void Environment_Clicked(object sender, EventArgs e) - { - if (DoOnce()) - { - _vm.StartEnvironmentAction(); - } - } - private async Task StartEnvironmentAsync() { await _accountListOverlay.HideAsync(); diff --git a/src/App/Pages/Accounts/HomePageViewModel.cs b/src/App/Pages/Accounts/HomePageViewModel.cs index d8a962141..f0ac6e699 100644 --- a/src/App/Pages/Accounts/HomePageViewModel.cs +++ b/src/App/Pages/Accounts/HomePageViewModel.cs @@ -4,7 +4,10 @@ using Bit.App.Abstractions; using Bit.App.Controls; using Bit.App.Resources; using Bit.App.Utilities; +using Bit.Core; using Bit.Core.Abstractions; +using Bit.Core.Models.Data; +using Bit.Core.Models.Response; using Bit.Core.Services; using Bit.Core.Utilities; using Xamarin.CommunityToolkit.ObjectModel; @@ -17,16 +20,19 @@ namespace Bit.App.Pages { private readonly IStateService _stateService; private readonly IMessagingService _messagingService; + private readonly IPlatformUtilsService _platformUtilsService; + private readonly ILogger _logger; + private readonly IEnvironmentService _environmentService; + private readonly IAccountsManager _accountManager; + private readonly IConfigService _configService; private bool _showCancelButton; private bool _rememberEmail; private string _email; + private string _selectedEnvironmentName; private bool _isEmailEnabled; private bool _canLogin; - private IPlatformUtilsService _platformUtilsService; - private ILogger _logger; - private IEnvironmentService _environmentService; - private IAccountsManager _accountManager; + private bool _displayEuEnvironment; public HomeViewModel() { @@ -36,6 +42,7 @@ namespace Bit.App.Pages _logger = ServiceContainer.Resolve(); _environmentService = ServiceContainer.Resolve(); _accountManager = ServiceContainer.Resolve(); + _configService = ServiceContainer.Resolve(); PageTitle = AppResources.Bitwarden; @@ -49,6 +56,8 @@ namespace Bit.App.Pages onException: _logger.Exception, allowsMultipleExecutions: false); CloseCommand = new AsyncCommand(async () => await Device.InvokeOnMainThreadAsync(CloseAction), onException: _logger.Exception, allowsMultipleExecutions: false); + ShowEnvironmentPickerCommand = new AsyncCommand(ShowEnvironmentPickerAsync, + onException: _logger.Exception, allowsMultipleExecutions: false); InitAsync().FireAndForget(); } @@ -71,6 +80,13 @@ namespace Bit.App.Pages additionalPropertyNames: new[] { nameof(CanContinue) }); } + public string SelectedEnvironmentName + { + get => $"{_selectedEnvironmentName} {BitwardenIcons.AngleDown}"; + set => SetProperty(ref _selectedEnvironmentName, value); + } + + public string RegionText => $"{AppResources.Region}:"; public bool CanContinue => !string.IsNullOrEmpty(Email); public FormattedString CreateAccountText @@ -101,11 +117,13 @@ namespace Bit.App.Pages public AsyncCommand ContinueCommand { get; } public AsyncCommand CloseCommand { get; } public AsyncCommand CreateAccountCommand { get; } + public AsyncCommand ShowEnvironmentPickerCommand { get; } public async Task InitAsync() { Email = await _stateService.GetRememberedEmailAsync(); RememberEmail = !string.IsNullOrEmpty(Email); + _displayEuEnvironment = await _configService.GetFeatureFlagBoolAsync(Constants.DisplayEuEnvironmentFlag, forceRefresh: true); } public async Task ContinueToLoginStepAsync() @@ -144,5 +162,56 @@ namespace Bit.App.Pages await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage, AppResources.AnErrorHasOccurred, AppResources.Ok); } } + + public async Task ShowEnvironmentPickerAsync() + { + var options = _displayEuEnvironment + ? new string[] { AppResources.US, AppResources.EU, AppResources.SelfHosted } + : new string[] { AppResources.US, AppResources.SelfHosted }; + + await Device.InvokeOnMainThreadAsync(async () => + { + var result = await Page.DisplayActionSheet(AppResources.DataRegion, AppResources.Cancel, null, options); + + if (result is null || result == AppResources.Cancel) + { + return; + } + + if (result == AppResources.SelfHosted) + { + StartEnvironmentAction?.Invoke(); + return; + } + + await _environmentService.SetUrlsAsync(result == AppResources.EU ? EnvironmentUrlData.DefaultEU : EnvironmentUrlData.DefaultUS); + SelectedEnvironmentName = result; + }); + } + + public async Task UpdateEnvironment() + { + var environmentsSaved = await _stateService.GetPreAuthEnvironmentUrlsAsync(); + if (environmentsSaved == null || environmentsSaved.IsEmpty) + { + await _environmentService.SetUrlsAsync(EnvironmentUrlData.DefaultUS); + environmentsSaved = EnvironmentUrlData.DefaultUS; + SelectedEnvironmentName = AppResources.US; + return; + } + + if (environmentsSaved.Base == EnvironmentUrlData.DefaultUS.Base) + { + SelectedEnvironmentName = AppResources.US; + } + else if (environmentsSaved.Base == EnvironmentUrlData.DefaultEU.Base) + { + SelectedEnvironmentName = AppResources.EU; + } + else + { + SelectedEnvironmentName = AppResources.SelfHosted; + } + } } } diff --git a/src/App/Pages/Accounts/LoginPageViewModel.cs b/src/App/Pages/Accounts/LoginPageViewModel.cs index cebdffdb3..1bf9b91c1 100644 --- a/src/App/Pages/Accounts/LoginPageViewModel.cs +++ b/src/App/Pages/Accounts/LoginPageViewModel.cs @@ -41,6 +41,7 @@ namespace Bit.App.Pages private bool _isEmailEnabled; private bool _isKnownDevice; private bool _isExecutingLogin; + private string _environmentHostName; public LoginPageViewModel() { @@ -115,6 +116,16 @@ namespace Bit.App.Pages set => SetProperty(ref _isKnownDevice, value); } + public string EnvironmentDomainName + { + get => _environmentHostName; + set => SetProperty(ref _environmentHostName, value, + additionalPropertyNames: new string[] + { + nameof(LoggingInAsText) + }); + } + public AccountSwitchingOverlayViewModel AccountSwitchingOverlayViewModel { get; } public Command LogInCommand { get; } public Command TogglePasswordCommand { get; } @@ -122,7 +133,7 @@ namespace Bit.App.Pages public ICommand LogInWithDeviceCommand { get; } public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye; public string PasswordVisibilityAccessibilityText => ShowPassword ? AppResources.PasswordIsVisibleTapToHide : AppResources.PasswordIsNotVisibleTapToShow; - public string LoggingInAsText => string.Format(AppResources.LoggingInAsX, Email); + public string LoggingInAsText => string.Format(AppResources.LoggingInAsXOnY, Email, EnvironmentDomainName); public bool IsIosExtension { get; set; } public bool CanRemoveAccount { get; set; } public Action StartTwoFactorAction { get; set; } @@ -151,6 +162,7 @@ namespace Bit.App.Pages Email = await _stateService.GetRememberedEmailAsync(); } CanRemoveAccount = await _stateService.GetActiveUserEmailAsync() != Email; + EnvironmentDomainName = CoreHelpers.GetDomain((await _stateService.GetPreAuthEnvironmentUrlsAsync())?.Base); IsKnownDevice = await _apiService.GetKnownDeviceAsync(Email, await _appIdService.GetAppIdAsync()); } catch (ApiException apiEx) when (apiEx.Error.StatusCode == System.Net.HttpStatusCode.Unauthorized) diff --git a/src/App/Pages/Accounts/LoginSsoPageViewModel.cs b/src/App/Pages/Accounts/LoginSsoPageViewModel.cs index c6da63df8..fbf9bf4f2 100644 --- a/src/App/Pages/Accounts/LoginSsoPageViewModel.cs +++ b/src/App/Pages/Accounts/LoginSsoPageViewModel.cs @@ -121,9 +121,8 @@ namespace Bit.App.Pages var ssoToken = response.Token; - - var passwordOptions = new PasswordGenerationOptions(true); - passwordOptions.Length = 64; + var passwordOptions = PasswordGenerationOptions.CreateDefault + .WithLength(64); var codeVerifier = await _passwordGenerationService.GeneratePasswordAsync(passwordOptions); var codeVerifierHash = await _cryptoFunctionService.HashAsync(codeVerifier, CryptoHashAlgorithm.Sha256); diff --git a/src/App/Pages/Generator/GeneratorPageViewModel.cs b/src/App/Pages/Generator/GeneratorPageViewModel.cs index 8af5548c5..78436352b 100644 --- a/src/App/Pages/Generator/GeneratorPageViewModel.cs +++ b/src/App/Pages/Generator/GeneratorPageViewModel.cs @@ -827,7 +827,7 @@ namespace Bit.App.Pages private void SetOptions() { _options.AllowAmbiguousChar = AllowAmbiguousChars; - _options.Type = PasswordTypeSelectedIndex == 1 ? "passphrase" : "password"; + _options.Type = PasswordTypeSelectedIndex == 1 ? PasswordGenerationOptions.TYPE_PASSPHRASE : PasswordGenerationOptions.TYPE_PASSWORD; _options.MinNumber = MinNumber; _options.MinSpecial = MinSpecial; _options.Special = Special; diff --git a/src/App/Pages/Settings/SettingsPage/SettingsPageViewModel.cs b/src/App/Pages/Settings/SettingsPage/SettingsPageViewModel.cs index d71bef46e..6767db611 100644 --- a/src/App/Pages/Settings/SettingsPage/SettingsPageViewModel.cs +++ b/src/App/Pages/Settings/SettingsPage/SettingsPageViewModel.cs @@ -131,7 +131,7 @@ namespace Bit.App.Pages { // if we have a vault timeout policy, we need to filter the timeout options _vaultTimeoutPolicy = (await _policyService.GetAll(PolicyType.MaximumVaultTimeout)).First(); - var policyMinutes = _policyService.GetPolicyInt(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_MINUTES); + var policyMinutes = _vaultTimeoutPolicy.GetInt(Policy.MINUTES_KEY); _vaultTimeoutOptions = _vaultTimeoutOptions.Where(t => t.Value <= policyMinutes && (t.Value > 0 || t.Value == CustomVaultTimeoutValue) && @@ -302,7 +302,7 @@ namespace Bit.App.Pages if (_vaultTimeoutPolicy != null) { - var maximumTimeout = _policyService.GetPolicyInt(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_MINUTES); + var maximumTimeout = _vaultTimeoutPolicy.GetInt(Policy.MINUTES_KEY); if (newTimeout > maximumTimeout) { @@ -382,7 +382,7 @@ namespace Bit.App.Pages public async Task VaultTimeoutActionAsync() { if (_vaultTimeoutPolicy != null && - !string.IsNullOrEmpty(_policyService.GetPolicyString(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_ACTION))) + !string.IsNullOrEmpty(_vaultTimeoutPolicy.GetString(Policy.ACTION_KEY))) { // do nothing if we have a policy set return; @@ -610,8 +610,8 @@ namespace Bit.App.Pages } if (_vaultTimeoutPolicy != null) { - var policyMinutes = _policyService.GetPolicyInt(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_MINUTES); - var policyAction = _policyService.GetPolicyString(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_ACTION); + var policyMinutes = _vaultTimeoutPolicy.GetInt(Policy.MINUTES_KEY); + var policyAction = _vaultTimeoutPolicy.GetString(Policy.ACTION_KEY); if (policyMinutes.HasValue || !string.IsNullOrWhiteSpace(policyAction)) { @@ -625,14 +625,14 @@ namespace Bit.App.Pages else if (!policyMinutes.HasValue && !string.IsNullOrWhiteSpace(policyAction)) { policyAlert = string.Format(AppResources.VaultTimeoutActionPolicyInEffect, - policyAction == PolicyService.TIMEOUT_POLICY_ACTION_LOCK ? AppResources.Lock : AppResources.LogOut); + policyAction == Policy.ACTION_LOCK ? AppResources.Lock : AppResources.LogOut); } else { policyAlert = string.Format(AppResources.VaultTimeoutPolicyWithActionInEffect, Math.Floor((float)policyMinutes / 60), policyMinutes % 60, - policyAction == PolicyService.TIMEOUT_POLICY_ACTION_LOCK ? AppResources.Lock : AppResources.LogOut); + policyAction == Policy.ACTION_LOCK ? AppResources.Lock : AppResources.LogOut); } securityItems.Insert(0, new SettingsPageListItem { diff --git a/src/App/Resources/AppResources.Designer.cs b/src/App/Resources/AppResources.Designer.cs index 2245d5f78..3810c9cf9 100644 --- a/src/App/Resources/AppResources.Designer.cs +++ b/src/App/Resources/AppResources.Designer.cs @@ -1750,6 +1750,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Data region. + /// + public static string DataRegion { + get { + return ResourceManager.GetString("DataRegion", resourceCulture); + } + } + /// /// Looks up a localized string similar to Password updated. /// @@ -2326,6 +2335,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to EU. + /// + public static string EU { + get { + return ResourceManager.GetString("EU", resourceCulture); + } + } + /// /// Looks up a localized string similar to Exact. /// @@ -3569,11 +3587,11 @@ namespace Bit.App.Resources { } /// - /// Looks up a localized string similar to Logging in as {0}. + /// Looks up a localized string similar to Logging in as {0} on {1}. /// - public static string LoggingInAsX { + public static string LoggingInAsXOnY { get { - return ResourceManager.GetString("LoggingInAsX", resourceCulture); + return ResourceManager.GetString("LoggingInAsXOnY", resourceCulture); } } @@ -5129,6 +5147,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Region. + /// + public static string Region { + get { + return ResourceManager.GetString("Region", resourceCulture); + } + } + /// /// Looks up a localized string similar to Remember me. /// @@ -5462,6 +5489,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Self-hosted. + /// + public static string SelfHosted { + get { + return ResourceManager.GetString("SelfHosted", resourceCulture); + } + } + /// /// Looks up a localized string similar to Self-hosted environment. /// @@ -6524,6 +6560,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to US. + /// + public static string US { + get { + return ResourceManager.GetString("US", resourceCulture); + } + } + /// /// Looks up a localized string similar to Use another two-step login method. /// diff --git a/src/App/Resources/AppResources.bn.resx b/src/App/Resources/AppResources.bn.resx index da4c6489e..974ad9da4 100644 --- a/src/App/Resources/AppResources.bn.resx +++ b/src/App/Resources/AppResources.bn.resx @@ -160,7 +160,7 @@ The button text that allows a user to copy the login's username to their clipboard. - Credits + কৃতিত্ব Title for page that we use to give credit to resources that we use. @@ -168,11 +168,11 @@ Delete an entity (verb). - Deleting... + মোছা হচ্ছে... Message shown when interacting with the server - Do you really want to delete? This cannot be undone. + আপনি কি সত্যিই মুছে ফেলতে চান? এটিকে পূর্বের মত করা যাবে না।. Confirmation alert message when deleteing something. @@ -190,16 +190,16 @@ Full label for a email address. - Email us + আমাদের ইমেইল করুন - Email us directly to get help or leave feedback. + সাহায্য পেতে বা মতামত দিতে সরাসরি আমাদের ইমেল করুন। - Enter your PIN code. + আপনার পিন কোডটি প্রবেশ করান - Favorites + পছন্দসমূহ Title for your favorite items in the vault. @@ -216,7 +216,7 @@ Label for a folder. - New folder created. + নতুন ফোল্ডার তৈরি হয়েছে। Folder deleted. @@ -276,7 +276,7 @@ আপনি লগ আউট করতে চান? - Remove account + অ্যাকাউন্ট অপসারণ করুন Are you sure you want to remove this account? @@ -315,30 +315,30 @@ Label for notes. - Ok + ঠিক আছে Acknowledgement. - Password + পাসওয়ার্ড Label for a password. - Save + সংরক্ষণ করুন Button text for a save operation (verb). - Move + স্থানান্তর করুন Saving... Message shown when interacting with the server - Settings + সেটিংস The title for the settings page. - Show + দেখান Reveal a hidden value (password). @@ -346,17 +346,17 @@ Confirmation message after successfully deleting a login. - Submit + জমা দিন Sync The title for the sync page. - Thank you + ধন্যবাদ - Tools + টুলস The title for the tools page. @@ -379,7 +379,7 @@ Confirmation message after successfully copying a value to the clipboard. - Verify fingerprint + আঙ্গুলের ছাপ যাচাই করুন প্রধান পাসওয়ার্ড যাচাইকরণ @@ -388,32 +388,32 @@ Verify PIN - Version + সংস্করণ View - Visit our website + আমাদের ওয়েবসাইটে ঢু মেরে আসুন - Visit our website to get help, news, email us, and/or learn more about how to use Bitwarden. + সাহায্য পেতে, খবর পেতে, আমাদের ইমেল করতে এবং/অথবা বিটওয়ার্ডেন কীভাবে ব্যবহার করবেন সে সম্পর্কে আরও জানতে আমাদের ওয়েবসাইট দেখুন। - Website + ওয়েবসাইট Label for a website. - Yes + হ্যাঁ - Account + অ্যাকাউন্ট - Your new account has been created! You may now log in. + আপনার নতুন অ্যাকাউন্ট তৈরি করা হয়েছে! আপনি এখন লগইন করতে পারবেন। - Add an Item + একটি আইটেম যোগ করুন App extension @@ -425,7 +425,7 @@ Auto-fill service - Avoid ambiguous characters + অস্পষ্ট বর্ণগুলি বাদ দিয়ে যান Bitwarden app extension @@ -440,13 +440,13 @@ Bitwarden Auto-fill Service - Use the Bitwarden accessibility service to auto-fill your logins. + আপনার লগইনগুলি স্বয়ংক্রিয়ভাবে পূরণ করতে বিটওয়ার্ডেন অ্যাক্সেসিবিলিটি পরিষেবা ব্যবহার করুন৷ - Change email + ইমেইল পরিবর্তন করুন - You can change your email address on the bitwarden.com web vault. Do you want to visit the website now? + আপনি bitwarden.com ওয়েব ভল্টে আপনার ইমেল ঠিকানা পরিবর্তন করতে পারেন। আপনি কি এখনই ওয়েবসাইট ভিজিট করতে চান? প্রধান পাসওয়ার্ড পরিবর্তন @@ -455,7 +455,7 @@ আপনি bitwarden.com ওয়েব ভল্ট থেকে প্রধান পাসওয়ার্ডটি পরিবর্তন করতে পারেন। আপনি কি এখনই ওয়েবসাইটটি দেখতে চান? - Close + বন্ধ করুন অবিরত @@ -480,7 +480,7 @@ Reactivate app extension - Almost done! + প্রায় হয়ে গেছে! Activate app extension @@ -493,7 +493,7 @@ Get instant access to your passwords! - You're ready to log in! + আপনি লগইন করার জন্য একদম তৈরি! Your logins are now easily accessible from Safari, Chrome, and other supported apps. @@ -511,7 +511,7 @@ প্রিয় - Fingerprint + আঙুলের ছাপ পাসওয়ার্ড তৈরি করুন @@ -584,7 +584,7 @@ যদি আপনি আপনার পাসওয়ার্ড ভুলে যান তাহলে একটি প্রধান পাসওয়ার্ডের ইঙ্গিতটি আপনাকে মনে করাতে সাহায্য করতে পারে। - Master password must be at least {0} characters long. + মাস্টার পাসওয়ার্ড কমপক্ষে {0} অক্ষরের হতে হবে। সর্বনিম্ন সংখ্যা @@ -595,7 +595,7 @@ Minimum special characters for password generator settings - More settings + আরও সেটিংস You must log into the main Bitwarden app before you can use the extension. @@ -651,7 +651,7 @@ Push notifications for apple products - Rate the app + অ্যাপ্লিকেশনটকে রেট দিন দয়া করে একটি ভাল পর্যালোচনার মাধ্যমে সাহায্য করতে আমাদের বিবেচনা করুন! @@ -684,7 +684,7 @@ Item saved - Submitting... + জমা দেওয়া হচ্ছে... Message shown when interacting with the server @@ -701,7 +701,7 @@ Sync vault now - Touch ID + টাচ আইডি What Apple calls their fingerprint reader. @@ -717,17 +717,17 @@ Unlock with PIN code - Validating + কার্যকর করা হচ্ছে Message shown when interacting with the server - Verification code + যাচাইকরণ কোড View item - Bitwarden web vault + বিটওয়ার্ডেন ওয়েব ভল্ট Lost authenticator app? @@ -740,10 +740,10 @@ Extension activated! - Icons + আইকন - Translations + অনুবাদসমূহ Items for {0} @@ -769,19 +769,19 @@ 2. Switch on the toggle and press OK to accept. - Disabled + নিষ্ক্রিয় - Enabled + সক্রিয় - Off + বন্ধ - On + চালু - Status + অবস্থা The easiest way to add new logins to your vault is from the Bitwarden Auto-fill Service. Learn more about using the Bitwarden Auto-fill Service by navigating to the "Settings" screen. @@ -876,7 +876,7 @@ Unable to download file. - Your device cannot open this type of file. + আপনার ডিভাইস এই ধরনের ফাইল খুলতে পারে না। ডাউনলোড হচ্ছে... @@ -904,13 +904,13 @@ Scanning will happen automatically. - Scan QR Code + QR কোড স্ক্যান করুন - Camera + ক্যামেরা - Photos + ছবিসমূহ Copy TOTP @@ -934,7 +934,7 @@ Scanning will happen automatically. Choose file - File + ফাইল No file chosen @@ -1080,7 +1080,7 @@ Scanning will happen automatically. নামের শেষাংশ - Full name + পুরো নাম লাইসেন্স নম্বর @@ -1107,34 +1107,34 @@ Scanning will happen automatically. Mx - November + নভেম্বর - October + অক্টোবর - Passport number + পাসপোর্ট নম্বর - Phone + ফোন - September + সেপ্টেম্বর - Social Security number + সামাজিক সুরক্ষা নম্বর - State / Province + রাজ্য / প্রদেশ - Title + শিরোনাম - Zip / Postal code + জিপ / পোস্টকোড - Address + ঠিকানা Expiration @@ -1204,7 +1204,7 @@ Scanning will happen automatically. Custom field name - Boolean + বুলিয়ান Hidden @@ -1225,7 +1225,7 @@ Scanning will happen automatically. Remove - New URI + নতুন URI URI {0} @@ -1272,7 +1272,7 @@ Scanning will happen automatically. Hold your Yubikey near the top of the device. - Try again + আবার চেষ্টা করুন To continue, hold your YubiKey NEO against the back of the device. @@ -1440,16 +1440,16 @@ Scanning will happen automatically. Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved. - Number of words + শব্দসংখ্যা - Passphrase + গুপ্ত-বাক্যাংশ - Word separator + শব্দ বিভাজক - Clear + পরিষ্কার করুন To clear something out. example: To clear browser history. @@ -1474,42 +1474,42 @@ Scanning will happen automatically. Export vault - Lock now + এখনই লক করুন - PIN + পিন - Unlock + আনলক করুন Unlock vault - 30 minutes + ৩০ মিনিট - Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application. + Bitwarden আনলক করার জন্য আপনার পিন কোডটি সেট করুন। আপনি যদি অ্যাপ্লিকেশনটি থেকে পুরোপুরি লগ আউট করেন তবে আপনার পিন সেটিংস রিসেট করা হবে। - Logged in as {0} on {1}. + {1}-এ {0} হিসেবে লগইন করা হয়েছে। ex: Logged in as user@example.com on bitwarden.com. আপনার ভল্ট লক করা আছে। চালিয়ে যেতে আপনার প্রধান পাসওয়ার্ডটি যাচাই করান। - Your vault is locked. Verify your PIN code to continue. + আপনার ভল্ট লক করা আছে। চালিয়ে যেতে আপনার পিন কোড যাচাই করান। - Your vault is locked. Verify your identity to continue. + আপনার ভল্ট লক করা আছে। চালিয়ে যেতে আপনার পরিচয় যাচাই করান। - Dark + গাঢ় A dark color - Light + উজ্জ্বল A light color @@ -1887,10 +1887,10 @@ Scanning will happen automatically. 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - Text + লেখা - Text + লেখা The text you want to send. @@ -1900,7 +1900,7 @@ Scanning will happen automatically. 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - File + ফাইল The file you want to send. @@ -1918,7 +1918,7 @@ Scanning will happen automatically. Text type is not selected, tap to select. - Deletion date + মুছে ফেলার তারিখ Deletion time @@ -1957,7 +1957,7 @@ Scanning will happen automatically. Current access count - New password + নতুন পাসওয়ার্ড Optionally require a password for users to access this Send. @@ -2030,19 +2030,19 @@ Scanning will happen automatically. 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - 1 day + ১ দিন - 2 days + ২ দিন 3 days - 7 days + ৭ দিন - 30 days + ৩০ দিন Custom @@ -2240,16 +2240,16 @@ Scanning will happen automatically. Options are collapsed, tap to expand. - Uppercase (A to Z) + বড় হাতের অক্ষর (A-Z) Lowercase (A to Z) - Numbers (0 to 9) + সংখ্যা (0-9) - Special characters (!@#$%^&*) + বিশেষ অক্ষর (!@#$%^&*) Tap to go back @@ -2352,10 +2352,10 @@ select Add TOTP to store the key safely Deny login - Just now + এইমাত্র - {0} minutes ago + {0} মিনিট আগে Login confirmed @@ -2548,7 +2548,7 @@ Do you want to switch to this account? Enable camera permission to use the scanner - Language + ভাষা The language has been changed to {0}. Please restart the app to see the change @@ -2575,10 +2575,10 @@ Do you want to switch to this account? Weak - Good + ভালো - Strong + শক্তিশালী Check known data breaches for this password diff --git a/src/App/Resources/AppResources.de.resx b/src/App/Resources/AppResources.de.resx index b53a2c827..f8868282a 100644 --- a/src/App/Resources/AppResources.de.resx +++ b/src/App/Resources/AppResources.de.resx @@ -1753,7 +1753,7 @@ Das Scannen erfolgt automatisch. Confirmation alert message when soft-deleting a cipher. - Biometrie zum Entsperren ist für dieses Konto deaktiviert, bis das Master-Passwort verifiziert wurde. + Das Entsperren über Biometrie ist für dieses Konto deaktiviert, bis das Master-Passwort verifiziert wurde. Das Entsperren von Auto-Ausfüllen über Biometrie ist für dieses Konto deaktiviert, bis das Master-Passwort verifiziert wurde. diff --git a/src/App/Resources/AppResources.el.resx b/src/App/Resources/AppResources.el.resx index e961c0f38..67e71da38 100644 --- a/src/App/Resources/AppResources.el.resx +++ b/src/App/Resources/AppResources.el.resx @@ -1753,10 +1753,10 @@ Confirmation alert message when soft-deleting a cipher. - Biometric unlock for this account is disabled pending verification of master password. + Το βιομετρικό ξεκλείδωμα για αυτόν τον λογαριασμό είναι απενεργοποιημένο εν αναμονή της επαλήθευσης του κύριου κωδικού πρόσβασης. - Autofill biometric unlock for this account is disabled pending verification of master password. + Το βιομετρικό ξεκλείδωμα αυτόματης συμπλήρωσης για αυτό το λογαριασμό είναι απενεργοποιημένο εν αναμονή της επαλήθευσης του κύριου κωδικού πρόσβασης. Ενεργοποίηση συγχρονισμού κατά την ανανέωση @@ -2143,10 +2143,10 @@ Οι πολιτικές του οργανισμού σας επηρεάζουν το χρονικό όριο vault σας. Το μέγιστο επιτρεπόμενο Χρονικό όριο Vault είναι {0} ώρα(ες) και {1} λεπτό(ά) - Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is {0} hour(s) and {1} minute(s). Your vault timeout action is set to {2}. + Οι πολιτικές του οργανισμού σας επηρεάζουν το χρονικό όριο του vault σας. Το μέγιστο επιτρεπόμενο χρονικό όριο vault είναι {0} ώρα(ες) και {1} λεπτό(ά). Το χρονικό όριο του vault σας έχει οριστεί σε {2}. - Your organization policies have set your vault timeout action to {0}. + Οι πολιτικές του οργανισμού σας έχουν ορίσει την ενέργεια χρονικού ορίου vault σε {0}. Το χρονικό όριο του vault σας υπερβαίνει τους περιορισμούς που έχει ορίσει ο οργανισμός σας. @@ -2610,9 +2610,9 @@ Δεν υπάρχουν στοιχεία που να ταιριάζουν με την αναζήτηση - Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour. + Ο κύριος κωδικός πρόσβασής σας δεν πληροί μία ή περισσότερες πολιτικές του οργανισμού σας. Για να αποκτήσετε πρόσβαση στο Vault σας, πρέπει να ενημερώσετε τον κύριο κωδικό πρόσβασής σας τώρα. Η διαδικασία θα σας αποσυνδέσει από την τρέχουσα συνεδρία σας, απαιτώντας από εσάς να συνδεθείτε ξανά. Οι ενεργές συνεδρίες σε άλλες συσκευές ενδέχεται να συνεχίσουν να είναι ενεργές εώς και μία ώρα. - Current master password + Τρέχων κύριος κωδικός diff --git a/src/App/Resources/AppResources.fa.resx b/src/App/Resources/AppResources.fa.resx index 176f0eda3..6ac80f876 100644 --- a/src/App/Resources/AppResources.fa.resx +++ b/src/App/Resources/AppResources.fa.resx @@ -1753,10 +1753,10 @@ Confirmation alert message when soft-deleting a cipher. - Biometric unlock for this account is disabled pending verification of master password. + باز کردن قفل بیومتریک برای این حساب کاربری در انتظار تأیید کلمه عبور اصلی غیرفعال است. - Autofill biometric unlock for this account is disabled pending verification of master password. + باز کردن قفل پر کردن خودکار بیومتریک برای این حساب کاربری در انتظار تأیید کلمه عبور اصلی غیرفعال است. فعال کردن همگام‌سازی در نوسازی @@ -2144,10 +2144,10 @@ سیاست‌های سازمانتان بر مهلت زمانی گاوصندوق شما تأثیر می‌گذارد. حداکثر زمان مجاز گاوصندوق {0} ساعت و {1} دقیقه است - Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is {0} hour(s) and {1} minute(s). Your vault timeout action is set to {2}. + سیاست‌های سازمانتان بر مهلت زمانی گاوصندوق شما تأثیر می‌گذارد. حداکثر زمان مجاز گاوصندوق {0} ساعت و {1} دقیقه است. عملگر مهلت زمانی گاوصندوق شما روی {2} تنظیم شده است. - Your organization policies have set your vault timeout action to {0}. + سباست‌های سازمان شما، عملگر زمان‌بندی گاوصندوق شما را روی {0} تنظیم کرده است. مهلت زمانی شما بیش از محدودیت های تعیین شده توسط سازمانتان است. @@ -2611,9 +2611,9 @@ هیچ موردی وجود ندارد که با جستجو مطابقت داشته باشد - Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour. + کلمه عبور اصلی شما با یک یا چند سیاست سازمان‌تان مطابقت ندارد. برای دسترسی به گاوصندوق، باید همین حالا کلمه عبور اصلی خود را به‌روز کنید. در صورت ادامه، شما از نشست فعلی خود خارج می‌شوید و باید دوباره وارد سیستم شوید. نشست فعال در دستگاه های دیگر ممکن است تا یک ساعت همچنان فعال باقی بمانند. - Current master password + کلمه عبور اصلی فعلی diff --git a/src/App/Resources/AppResources.fi.resx b/src/App/Resources/AppResources.fi.resx index a756bf557..c02d56df2 100644 --- a/src/App/Resources/AppResources.fi.resx +++ b/src/App/Resources/AppResources.fi.resx @@ -1753,10 +1753,10 @@ Koodi luetaan automaattisesti. Confirmation alert message when soft-deleting a cipher. - Biometric unlock for this account is disabled pending verification of master password. + Biometrinen avaus on poistettu käytöstä tältä tililtä, kunnes pääsalasana on vahvistettu. - Autofill biometric unlock for this account is disabled pending verification of master password. + Automaattisen täytön biometrinen avaus on poistettu käytöstä tältä tililtä, kunnes pääsalasana on vahvistettu. Synkronoi holvi päivityksen yhteydessä @@ -2602,7 +2602,7 @@ Haluatko vaihtaa tähän tiliin? Lisää avain olemassa olevaan tai uuteen kohteeseen - Holvissasi ei ole kohteita osoitteelle "{0}" + Holvissasi ei ole kohdetta "{0}" vastavia tietoja Etsi kohdetta tai lisää uusi kohde diff --git a/src/App/Resources/AppResources.fr.resx b/src/App/Resources/AppResources.fr.resx index 59451de96..519235ea5 100644 --- a/src/App/Resources/AppResources.fr.resx +++ b/src/App/Resources/AppResources.fr.resx @@ -1753,10 +1753,10 @@ La numérisation se fera automatiquement. Confirmation alert message when soft-deleting a cipher. - Biometric unlock for this account is disabled pending verification of master password. + Le déverrouillage biométrique pour ce compte est désactivé en attente de vérification du mot de passe maître. - Autofill biometric unlock for this account is disabled pending verification of master password. + Le déverrouillage biométrique de saisie automatique pour ce compte est désactivé en attente de vérification du mot de passe maître. Autoriser la synchronisation au rafraîchissement diff --git a/src/App/Resources/AppResources.hi.resx b/src/App/Resources/AppResources.hi.resx index b257e3fac..1c0e9face 100644 --- a/src/App/Resources/AppResources.hi.resx +++ b/src/App/Resources/AppResources.hi.resx @@ -118,14 +118,14 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - बारे में + हमारे बारे में जोड़ें Add/create a new entity (verb). - नया फोल्डर जोड़ें + फोल्डर जोड़ें चीज़ जोड़ें @@ -136,11 +136,11 @@ Alert title when something goes wrong. - वापस जाएं + पीछे जाएं Navigate back to the previous screen. - bitwarden + बिटवार्डन App name. Shouldn't ever change. @@ -156,105 +156,105 @@ The button text that allows a user to copy the login's password to their clipboard. - उपयोगकर्ता नाम की प्रतिलिपि बनाएँ + यूज़रनाम कॉपी करें The button text that allows a user to copy the login's username to their clipboard. - क्रेडिट्स + क्रेडिट Title for page that we use to give credit to resources that we use. - मिटाए + मिटाएं Delete an entity (verb). - मिटाया जा रहा हैं + मिटाया जा रहा हैं... Message shown when interacting with the server - क्या आप वास्तव में हटाना चाहते हैं? इसे नष्ट नहीं किया जा सकता है + पक्का मिटाएं? इसे अंडू नहीं किया जा सकता। Confirmation alert message when deleteing something. - संशोधन करें + बदलाव करें - फ़ोल्डर संपादित करें + फोल्डर बदलाव करें ईमेल Short label for an email address. - ई-मेल पता + ईमेल पता Full label for a email address. हमें ईमेल करें - सहायता प्राप्त करने या प्रतिक्रिया छोड़ने के लिए हमें ईमेल करें। + मदद लेने या फीडबैक देने के लिए हमें ईमेल करें। - अपना पिन डालें + अपना पिन कोड डालें। - पसंदीदा + मनपसंद Title for your favorite items in the vault. - बग रिपोर्ट दर्ज करें + बग रिपोर्ट भेजें - हमारे GitHub भंडार में एक मुद्दे को बताएं। + हमारे गिटहब रिपॉज़िटरी में समस्या बताएं। - फिंगरप्रिंट से सत्यापन करें + फिंगरप्रिंट से सत्यापन करें। - फ़ोल्डर + फोल्डर Label for a folder. - नया फ़ोल्डर बनाया गया + नया फोल्डर बनाया गया। - फ़ोल्डर को हटाया + फोल्डर मिटाया गया। - कोई फ़ोल्डर नहीं है + कोई फोल्डर नहीं है Items that have no folder specified go in this special "catch-all" folder. - फ़ोल्डर्स + फोल्डर - फ़ोल्डर अद्यतन हुआ + फोल्डर सेव हुआ - वेबसाइट पर जाएँ + वेबसाइट पर जाएं The button text that allows user to launch the website to their web browser. - सहायता और सुझाव + मदद और फीडबैक - छुपायें + छुपाएं Hide a secret value that is currently shown (password). - जारी रखने से पहले कृपया इंटरनेट से जुड़े। + जारी रखने से पहले इंटरनेट से जुड़ें। Description message for the alert when internet connection is required to continue. - इंटरनेट से जुड़िए। + इंटरनेट कनेक्शन चाहिए Title for the alert when internet connection is required to continue. - मास्टर पासवर्ड गलत है। फिर कोशिश करें। + मुख्य पासवर्ड गलत है। वापस कोशिश करें। - पिन गलत है। फिर कोशिश करें। + पिन गलत है। वापस कोशिश करें। खोलें @@ -269,38 +269,38 @@ Title for login page. (noun) - लॉग आउट + लॉग आउट करें The log out button text (verb). - क्या आप वाकई लॉग आउट करना चाहते हैं? + पक्का लॉग आउट करें? खाता हटाएं - क्या आप वाकई यह खाता हटाना चाहते हैं? + पक्का खाता हटाएं? - Account already added + खाता पहले से जोड़ा गया - Would you like to switch to it now? + अभी खाता इस्तेमाल करें? - मास्टर / मुख्य पासवर्ड + मुख्य पासवर्ड Label for a master password. - अतिरिक्त + और Text to define that there are more options things to see. - मेरी तिजोरी + मेरा तिजोरी The title for the vault page. - Authenticator + सत्यापन करनेवाला Authenticator TOTP feature @@ -311,11 +311,11 @@ नहीं - टिप्पणियाँ + नोट Label for notes. - ठीक + ठीक है Acknowledgement. @@ -323,69 +323,69 @@ Label for a password. - सहेजें + सेव करें Button text for a save operation (verb). - Move + ले जाएं सेव हो रहा है... Message shown when interacting with the server - सेटिंग्स + सेटिंग The title for the settings page. - दिखाएँ + दिखाएं Reveal a hidden value (password). - आइटम हटा दिया गया है। + चीज़ मिटाया गया। Confirmation message after successfully deleting a login. जमा करें - संकालन + सिंक The title for the sync page. - धन्यवाद + शुक्रिया - उपकरण + औज़ार The title for the tools page. - URI + यूआरआई Label for a uri/url. - अंगुलिछाप से खोलें + फिंगरप्रिंट से खोलें - उपयोगकर्ता नाम: + यूज़रनाम Label for a username. - {0} की आश्यकता है। + {0} फील्ड चाहिए। Validation message for when a form field is left blank and is required to be entered. - {0} कॉपी कर लिया गया है। + {0} कॉपी किया Confirmation message after successfully copying a value to the clipboard. - अंगुलिछाप दें + फिंगरप्रिंट सत्यापित करें - मास्टर पासवर्ड बताएं। + मुख्य पासवर्ड सत्यापित करें - पिन बताएं। + पिन सत्यापित करें। संस्करण @@ -394,29 +394,29 @@ देखें - हमारी वेबसाइट पर जाएँ + हमारी वेबसाइट पर जाएं - Visit our website to get help, news, email us, and/or learn more about how to use bitwarden. + मदद लेने, खबर लेने, हमें ईमेल करने, और/या बिटवार्डन के इस्तेमाल के बारे में ज़्यादा जानने के लिए हमारी वेबसाइट पर जाएं। वेबसाइट Label for a website. - हाँ + हां खाता - अपना नया खाता बनाया गया है! अब आप लॉग ऑन कर सकते हैं। + आपका नया खाता बनाया गया! अब आप लॉग इन कर सकते हैं। - आइटम जोड़ें + चीज़ जोड़ें - ऐप का विस्तारण + ऐप एक्सटेंशन Use the bitwarden accessibility service to auto-fill your logins across apps and the web. @@ -776,10 +776,10 @@ सक्षम - Off + बंद - On + चालू स्थिति @@ -1096,16 +1096,16 @@ Scanning will happen automatically. मध्य नाम - Mr + श्री - Mrs + श्रीमती - Ms + श्रीमती - Mx + मैक्स नवंबर @@ -2274,7 +2274,7 @@ Scanning will happen automatically. Vault: {0} - All + सब TOTP @@ -2365,13 +2365,13 @@ select Add TOTP to store the key safely Login denied - Approve login requests + लॉगइन मांग माने Use this device to approve login requests made from other devices. - Allow notifications + सूचना देने दें Receive push notifications for new login requests @@ -2522,99 +2522,99 @@ Do you want to switch to this account? Resend notification - Need another option? + दूसरा ऑप्शन चाहिए? - View all log in options + ऑप्शन में सारे लॉग देखें - This request is no longer valid + ये मांग अब मान्य नहीं है - Pending login requests + लंबित लॉगइन मांगे - Decline all requests + सारे मांग नकारे - Are you sure you want to decline all pending login requests? + सारे लंबित लॉगइन मांग पक्का नकारें? - Requests declined + मांग नकारे गए - No pending requests + कोई लंबित मांग नहीं - Enable camera permission to use the scanner + स्कैनर इस्तेमाल करने के लिए कैमरा अनुमति दें - Language + भाषा - The language has been changed to {0}. Please restart the app to see the change + भाषा {0} में बदली गई। बदलाव देखने के लिए ऐप बंद करके वापस खोलें। - Language change requires app restart + भाषा बदलाव के लिए ऐप बंद करके खोलना पड़ेगा - Default (System) + डिफॉल्ट (सिस्टम) - Important + ज़रूरी - Your master password cannot be recovered if you forget it! {0} characters minimum. + आप अपना मुख्य पासवर्ड भूलने के बाद वापस नहीं ले सकते। {0} अक्षर कम-से-कम। - Weak Master Password + कमज़ोर मुख्य पासवर्ड - Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password? + पासवर्ड कमज़ोर है। अपना खाता महफूज़ रखने के लिए एक ताकतवर पासवर्ड इस्तेमाल करें। कमज़ोर पासवर्ड पक्का इस्तेमाल करें? - Weak + कमज़ोर - Good + अच्छा - Strong + ताकतवर - Check known data breaches for this password + पुराने डाटा लीक में इस पासवर्ड को खोजें - Exposed Master Password + मुख्य पासवर्ड लीक हुआ था - Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password? + पासवर्ड एक डाटा लीक में मिला। अपना खाता महफूज़ रखने के लिए एक खास पासवर्ड इस्तेमाल करें। लीक हुआ पासवर्ड इस्तेमाल करें? - Weak and Exposed Master Password + कमज़ोर और लीक हुआ मुख्य पासवर्ड - Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password? + पासवर्ड कमज़ोर है और एक डाटा लीक में मिला। अपना खाता महफूज़ रखने के लिए एक ताकतवर और खास पासवर्ड इस्तेमाल करें। ये पासवर्ड पक्का इस्तेमाल करें? - Organization SSO identifier required. + संगठन एसएसओ पहचान चाहिए। - Add the key to an existing or new item + चाबी एक मौजूदा या नए चीज़ में जोड़ें - There are no items in your vault that match "{0}" + आपके तिजोरी में ऐसी कोई भी चीज़ नहीं है जो "{0}" से मेल खाती है - Search for an item or add a new item + चीज़ खोजें या नया चीज़ जोड़ें - There are no items that match the search + कोई भी चीज़ खोज शब्द से मेल नहीं खाता - Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour. + आपका मुख्य पासवर्ड आपके संगठन के एक या उससे ज़्यादा नीति को नहीं मानता। तिजोरी एक्सेस करने के लिए आपको अपना मुख्य पासवर्ड अभी बदलना होगा। ये करने से आप अपने चालू सत्र से लॉग आउट हो जाएंगे, जिसके वजह से आपको वापस लॉग इन करना पड़ेगा। दूसरे डिवाइसों पर चालू सत्र एक घंटे तक सक्रिय रह सकते हैं। - Current master password + चालू मुख्य पासवर्ड diff --git a/src/App/Resources/AppResources.resx b/src/App/Resources/AppResources.resx index 5e9c48694..a94cdb2b4 100644 --- a/src/App/Resources/AppResources.resx +++ b/src/App/Resources/AppResources.resx @@ -2496,8 +2496,8 @@ Do you want to switch to this account? Get master password hint - - Logging in as {0} + + Logging in as {0} on {1} Not you? @@ -2610,6 +2610,21 @@ Do you want to switch to this account? There are no items that match the search + + US + + + EU + + + Self-hosted + + + Data region + + + Region + Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour. diff --git a/src/App/Resources/AppResources.ro.resx b/src/App/Resources/AppResources.ro.resx index 8ddbc5cf7..4c9903397 100644 --- a/src/App/Resources/AppResources.ro.resx +++ b/src/App/Resources/AppResources.ro.resx @@ -1753,10 +1753,10 @@ Scanarea se va face automat. Confirmation alert message when soft-deleting a cipher. - Biometric unlock for this account is disabled pending verification of master password. + Deblocarea biometrică pentru acest cont este dezactivată în așteptarea verificării parolei principale. - Autofill biometric unlock for this account is disabled pending verification of master password. + Completarea automată a deblocării biometrice pentru acest cont este dezactivată în așteptarea verificării parolei principale. Activare sincronizare la reîmprospătare diff --git a/src/App/Resources/AppResources.sl.resx b/src/App/Resources/AppResources.sl.resx index 8768c1412..59b2998a0 100644 --- a/src/App/Resources/AppResources.sl.resx +++ b/src/App/Resources/AppResources.sl.resx @@ -269,7 +269,7 @@ Title for login page. (noun) - Izpiši se + Odjavi se The log out button text (verb). @@ -296,7 +296,7 @@ Text to define that there are more options things to see. - Moj sef + Moj trezor The title for the vault page. @@ -342,7 +342,7 @@ Reveal a hidden value (password). - Vnos je bil izbrisan. + Element je bil izbrisan. Confirmation message after successfully deleting a login. @@ -413,7 +413,7 @@ Vas novi račun je bil ustvarjen! Lahko se vpišete. - Dodaj vnos + Dodaj Element Razširitev aplikacije @@ -425,7 +425,7 @@ Storitev samodejnega izpolnjevanja - Izogib dvoumnih znakov + Brez dvoumnih znakov Razširitev aplikacije Bitwarden @@ -468,7 +468,7 @@ Message shown when interacting with the server - Uredi vnos + Uredi element Omogoči samodejno sinhronizacijo @@ -514,13 +514,13 @@ Prstni odtis - Ustvari geslo + Generiraj geslo Pridobi namig za glavno geslo - Uvozi zapise + Uvozi elemente You can bulk import items from the bitwarden.com web vault. Do you want to visit the website now? @@ -566,7 +566,7 @@ Message shown when interacting with the server - Vpišite se ali ustvarite nov račun za dostop do sefa. + Prijavite se ali ustvarite nov račun za dostop do trezorja. Upravljaj @@ -584,7 +584,7 @@ Namig glavnega gesla se vam lahko pomaga spomniti geslo, v kolikor bi ga pozabili. - Master password must be at least {0} characters long. + Glavno geslo mora vsebovati vsaj {0} znakov. Minimalno števil @@ -604,13 +604,13 @@ Nikoli - Nov vnos ustvarjen. + Nov element ustvarjen. - V vašem sefu ni priljubljenih vnosov. + V vašem trezorju ni priljubljenih elementov. - V vašem sefu ni vnosov. + V vašem trezorju ni elementov. There are no items in your vault for this website/app. Tap to add one. @@ -632,7 +632,7 @@ Drugo - Geslo ustvarjeno. + Geslo generirano. Ustvarjalnik gesel @@ -678,24 +678,24 @@ Vnesite 4 mestno PIN številko za odklep aplikacije. - Informacije o vnosu + Informacije o elementu - Vnos je posodobljen. + Element shranjen. Pošiljanje... Message shown when interacting with the server - Sinhronizacija... + Sinhroniziram... Message shown when interacting with the server Sinhronizacija končana. - Sinhronizacija neuspešna. + Sinhronizacija spodletela. Sinhroniziraj trezor zdaj @@ -714,7 +714,7 @@ Odkleni z {0} - Odklepanje s PIN kodo + Odkleni s PIN kodo Preverjanje veljavnosti @@ -724,16 +724,16 @@ Verifikacijska koda - Ogled vnosa + Prikaži element - Bitwarden spletni sef + Spletni trezor Bitwarden Izgubili aplikacijo za avtentikacijo? - Vnosi + Elementi Screen title @@ -746,11 +746,11 @@ Prevodi - Vnosov za {0} + Elementi za {0} This is used for the autofill service. ex. "Logins for twitter.com" - V vašem sefu ni vnosov za {0}. + V vašem trezorju ni elementov za {0}. This is used for the autofill service. ex. "There are no items in your vault for twitter.com". @@ -790,16 +790,16 @@ Samodejno izpolnjevanje - Želite samodejno izpolniti ali videti ta vnos? + Želite samodejno izpolniti ali prikazati ta element? Ali ste prepričani, da želite samodejno izpolniti ta element? Ujemanje ni popolno za "{0}". - Ujemajoči vnosi + Ujemajoči elementi - Možni ujemajoči vnosi + Možni ujemajoči elementi Iskanje @@ -1017,7 +1017,7 @@ Scanning will happen automatically. Prijava - Varni zapisek + Zavarovan zapisek Naslov 1 @@ -1140,10 +1140,10 @@ Scanning will happen automatically. Datum poteka - Show website icons + Prikaži ikone spletnih strani - Show a recognizable image next to each login. + Pri vsaki prijavi prikaži prepoznavno sliko. Ikone URL strežnikov @@ -1161,10 +1161,10 @@ Scanning will happen automatically. Zbirke - Ta zbirka še nima zapisov. + Ta zbirka še nima elementov. - V tej mapi ni zapisov. + V tej mapi ni elementov. Koš je prazen. @@ -1182,7 +1182,7 @@ Scanning will happen automatically. Nastavitve samodejnega izpolnjevanja - Obrazni ID + obraznim ID What Apple calls their facial recognition reader. @@ -1322,7 +1322,7 @@ Scanning will happen automatically. 5. Select "Bitwarden" - Password auto-fill + Samodejno izpolnjevanje gesel The easiest way to add new logins to your vault is by using the Bitwarden Password AutoFill extension. Learn more about using the Bitwarden Password AutoFill extension by navigating to the "Settings" screen. @@ -1340,13 +1340,13 @@ Scanning will happen automatically. Prijave - Varni zapiski + Zavarovani zapiski Vsi elementi - URIs + URI-ji Plural form of a URI @@ -1369,7 +1369,7 @@ Scanning will happen automatically. Vrednost - Zgodovina gesla + Zgodovina gesel Vrste @@ -1378,7 +1378,7 @@ Scanning will happen automatically. Ni gesel za prikazat. - Ni vnosov za prikazat. + Ni elementov za prikaz. Preišči zbirko @@ -1409,7 +1409,7 @@ Scanning will happen automatically. Lastništvo - Kdo je lastnik tega vnosa? + Kdo je lastnik tega elementa? Ni zbirk za prikazat. @@ -1419,7 +1419,7 @@ Scanning will happen automatically. ex: Item moved to Organization. - Vnos je bil deljen. + Element je bil dan v skupno rabo. Izbrati moraš vsaj eno zbirko. @@ -1428,10 +1428,10 @@ Scanning will happen automatically. Deli - Delite vnos + Delite element - Move to Organization + Premakni v organizacijo Ni organizacij za prikazat. @@ -1562,7 +1562,7 @@ Scanning will happen automatically. Kopiraj opombo - Zapri + Izhod Ali res želite zapustiti Bitwarden? @@ -1583,16 +1583,16 @@ Scanning will happen automatically. 'Solarized Dark' is the name of a specific color scheme. It should not be translated. - Auto-fill blocked URIs + URI-ji brez samodejnega izpolnjevanja - Auto-fill will not be offered for blocked URIs. Separate multiple URIs with a comma. For example: "https://twitter.com, androidapp://com.twitter.android". + Za te URI-je Bitwarden ne bo ponujal samodejnega izpolnjevanja. URI-je ločite z vejicami, n.pr.: "https://twitter.com, androidapp://com.twitter.android". - Ask to add login + Ponudi shranjevanje prijav - Ask to add an item if one isn't found in your vault. + Ponudi, da se shrani nova prijava, če je v trezorju še ni. Ob ponovnem zagonu aplikacije @@ -1626,7 +1626,7 @@ Scanning will happen automatically. Biometrična avtentikacija - Biometrično preverjanje + biometričnim preverjanjem Uporabi biometrično preverjanje za odklep @@ -1729,7 +1729,7 @@ Scanning will happen automatically. Message shown when interacting with the server - Vnos je bil obnovljen. + Element je bil obnovljen. Confirmation message after successfully restoring a soft-deleted item @@ -1745,7 +1745,7 @@ Scanning will happen automatically. Confirmation alert message when permanently deleteing a cipher. - Ali res želite povrniti ta vnos? + Ali res želite povrniti ta element? Confirmation alert message when restoring a soft-deleted cipher. @@ -1759,10 +1759,10 @@ Scanning will happen automatically. Autofill biometric unlock for this account is disabled pending verification of master password. - Allow sync on refresh + Dovoli sihnronizacijo ob osvežitvi - Syncing vault with pull down gesture. + Sinhroniziraj ob potegu navzdol Enterprise single sign-on @@ -1829,7 +1829,7 @@ Scanning will happen automatically. Bitwarden needs attention - Turn on "Draw-Over" in "Auto-fill Services" from Bitwarden Settings - Auto-fill services + Storitve samodejnega izpolnjevanja Use inline autofill @@ -1871,7 +1871,7 @@ Scanning will happen automatically. An organization policy is affecting your ownership options. - Pošlji + Pošiljke 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. @@ -1887,23 +1887,23 @@ Scanning will happen automatically. 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - Text + Besedilo - Text + Besedilo - The text you want to send. + Besedilo, ki ga želite poslati When accessing the Send, hide the text by default 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - File + Datoteka - The file you want to send. + Datoteka, ki jo želite poslati File type is selected. @@ -1998,7 +1998,7 @@ Scanning will happen automatically. Deli povezavo - Pošlji povezavo + Povezava pošiljke 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. @@ -2156,22 +2156,22 @@ Scanning will happen automatically. One or more organization policies prevents your from exporting your individual vault. - Add account + Dodaj račun - Unlocked + Odklenjen - Locked + Zaklenjen - Logged out + Odjavljen Switched to next available account - Account locked + Račun je zaklenjen Account logged out successfully @@ -2195,7 +2195,7 @@ Scanning will happen automatically. Vaš račun je bil trajno izbrisan - Invalid verification code + Neveljavna koda za preverjanje Request one-time password @@ -2228,7 +2228,7 @@ Scanning will happen automatically. Enter the verification code that was sent to your email - Submit crash logs + Pošlji zapisnike ob sesutju Help Bitwarden improve app stability by submitting crash reports. @@ -2240,16 +2240,16 @@ Scanning will happen automatically. Options are collapsed, tap to expand. - Uppercase (A to Z) + Velike črke (A-Z) - Lowercase (A to Z) + Male črke (a-z) Numbers (0 to 9) - Special characters (!@#$%^&*) + Posebni znaki (!@#$%^&*) Tap to go back @@ -2264,31 +2264,31 @@ Scanning will happen automatically. Filter items by vault - All vaults + Vsi trezorji - Vaults + Trezorji - Vault: {0} + Trezor: {0} - All + Vsi TOTP - Verification codes + Kode za preverjanje - Premium subscription required + Potrebna je naročnina Premium. Cannot add authenticator key? - Scan QR Code + Skeniraj QR-kodo Cannot scan QR Code? @@ -2319,10 +2319,10 @@ select Add TOTP to store the key safely We were unable to process your request. Please try again or contact us. - Allow screen capture + Dovoli posnetke zaslona - Are you sure you want to turn on screen capture? + Ste prepričani, da želite dovoliti zajemanje zaslona? Login requested @@ -2337,46 +2337,46 @@ select Add TOTP to store the key safely Device type - IP address + IP-naslov - Time + Čas - Near + Blizu - Confirm login + Potrdi prijavo - Deny login + Zavrni prijavo - Just now + Pravkar - {0} minutes ago + Pred {0} minutami - Login confirmed + Prijava potrjena - Login denied + Prijava zavrnjena - Approve login requests + Odobri zahtevke za prijavo - Use this device to approve login requests made from other devices. + S to napravo odobri zahtevke za prijavo, ki pridejo z drugih naprav. - Allow notifications + Dovoli obvestila Receive push notifications for new login requests - No thanks + Ne, hvala Confirm login attempt for {0} @@ -2385,10 +2385,10 @@ select Add TOTP to store the key safely All notifications - Password type + Vrsta gesla - What would you like to generate? + Kaj želite generirati? Username type @@ -2444,7 +2444,7 @@ select Add TOTP to store the key safely Are you sure you want to overwrite the current username? - Generate username + Generiraj uporabniško ime Email Type @@ -2477,13 +2477,13 @@ select Add TOTP to store the key safely Bitwarden uses the Accessibility Service to search for login fields in apps and websites, then establish the appropriate field IDs for entering a username & password when a match for the app or site is found. We do not store any of the information presented to us by the service, nor do we make any attempt to control any on-screen elements beyond text entry of credentials. - Accept + Sprejmi - Decline + Zavrni - Login request has already expired. + Zahtevek za prijavo je že potekel. Login attempt from: @@ -2491,109 +2491,109 @@ select Add TOTP to store the key safely Do you want to switch to this account? - New around here? + Ste novi tukaj? - Get master password hint + Pridobi namig za glavno geslo - Logging in as {0} + Prijavljate se kot {0} - Not you? + To niste vi? - Log in with master password + Prijava z glavnim geslom - Log in with device + Prijava z napravo - Log in initiated + Prijava sprožena - A notification has been sent to your device. + Na vašo napravo smo poslali obvestilo. - Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device. + Prosimo, preverite, da je vaš trezor odklenjem in da se identifikacijski gesli na tej in drugi napravi ujemata. - Resend notification + Ponovno pošlji obvestilo - Need another option? + Potrebujete drugačno možnost? - View all log in options + Prikaži vse možnosti prijave - This request is no longer valid + Ta zahtevek ni več veljaven - Pending login requests + Čakajoči zahtevki za prijavo - Decline all requests + Zavrni vse zahtevke - Are you sure you want to decline all pending login requests? + Ste prepričani, da želite zavrniti vse čakajoče zahtevke za prijavo? - Requests declined + Zahtevki zavrnjeni - No pending requests + Ni zahtevkov - Enable camera permission to use the scanner + Za uporabo skenerja dovolite uporabo kamere - Language + Jezik - The language has been changed to {0}. Please restart the app to see the change + Spremenjeno v jezik {0}. Prosimo, ponovno zaženite aplikacijo za prikaz sprememb. - Language change requires app restart + Za spremembo jezika je potrebno ponovno zagnati aplikacijo. - Default (System) + Privzet (sistemski) - Important + Pomembno - Your master password cannot be recovered if you forget it! {0} characters minimum. + Če pozabite glavno geslo, ga ne bo mogoče obnoviti! Vsaj {0} znakov. - Weak Master Password + Šibko glavno geslo - Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password? + Vaše geslo je šibko. Za zaščito svojega računa potrebujete močno geslo. Ste prepričani, da želite uporabiti šibko geslo? - Weak + Šibko - Good + Dobro - Strong + Močno - Check known data breaches for this password + Preveri, ali je bilo geslo izpostavljeno v krajah podatkov - Exposed Master Password + Izpostavljeno glavno geslo - Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password? + To geslo smo našli med ukradenimi gesli. Za zaščito svojega računa uporabite edinstveno geslo. Ste prepričani, da želite uporabiti izpostavljeno geslo? - Weak and Exposed Master Password + Šibko in izpostavljeno glavno geslo - Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password? + Vaše geslo je šibko, poleg tega smo ga našli med ukradenimi gesli. Za zaščito svojega računa potrebujete močno in edinstveno geslo. Ste prepričani, da želite uporabiti to šibko geslo? Organization SSO identifier required. @@ -2602,18 +2602,18 @@ Do you want to switch to this account? Add the key to an existing or new item - There are no items in your vault that match "{0}" + V vašem trezorju ni elementov, ki bi ustrezali "{0}" - Search for an item or add a new item + Poišči element ali dodaj novega - There are no items that match the search + Ni elementov, ki bi ustrezali iskanju Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour. - Current master password + Trenutno glavno geslo diff --git a/src/App/Resources/AppResources.sr.resx b/src/App/Resources/AppResources.sr.resx index d9cdaa3e2..962f66823 100644 --- a/src/App/Resources/AppResources.sr.resx +++ b/src/App/Resources/AppResources.sr.resx @@ -1753,10 +1753,10 @@ Confirmation alert message when soft-deleting a cipher. - Biometric unlock for this account is disabled pending verification of master password. + Биометријско откључавање је онемогућено до верификације главне лозинке. - Autofill biometric unlock for this account is disabled pending verification of master password. + Биометријско откључавање аутоматског попуњавања за овај налог је онемогућено до верификације главне лозинке. Омогући синхронизацију при освежавању diff --git a/src/App/Resources/AppResources.uk.resx b/src/App/Resources/AppResources.uk.resx index 9a1b37c3a..d02f69588 100644 --- a/src/App/Resources/AppResources.uk.resx +++ b/src/App/Resources/AppResources.uk.resx @@ -1753,10 +1753,10 @@ Confirmation alert message when soft-deleting a cipher. - Biometric unlock for this account is disabled pending verification of master password. + Біометричне розблокування для цього облікового запису вимкнено. Очікується перевірка головного пароля. - Autofill biometric unlock for this account is disabled pending verification of master password. + Біометричне розблокування під час автозаповнення для цього облікового запису вимкнено. Очікується перевірка головного пароля. Дозволити синхронізацію жестом diff --git a/src/App/Resources/AppResources.zh-Hans.resx b/src/App/Resources/AppResources.zh-Hans.resx index 43faf372b..a6260ad31 100644 --- a/src/App/Resources/AppResources.zh-Hans.resx +++ b/src/App/Resources/AppResources.zh-Hans.resx @@ -2610,7 +2610,7 @@ 没有匹配搜索条件的项目 - 您的主密码不符合您的组织策略要求。要访问密码库,必须立即更新您的主密码。继续操作将使您退出当前会话,要求您重新登录。其他设备上的活动会话可能会继续保持活动状态长达一小时。 + 您的主密码不符合某一项或多项组织策略要求。要访问密码库,必须立即更新您的主密码。继续操作将使您退出当前会话,并要求您重新登录。其他设备上的活动会话可能会继续保持活动状态长达一小时。 当前主密码 diff --git a/src/Core/Abstractions/IApiService.cs b/src/Core/Abstractions/IApiService.cs index 2291eae2d..803c280be 100644 --- a/src/Core/Abstractions/IApiService.cs +++ b/src/Core/Abstractions/IApiService.cs @@ -93,5 +93,6 @@ namespace Bit.Core.Abstractions Task GetUsernameFromAsync(ForwardedEmailServiceType service, UsernameGeneratorConfig config); Task GetKnownDeviceAsync(string email, string deviceIdentifier); Task GetOrgDomainSsoDetailsAsync(string email); + Task GetConfigsAsync(); } } diff --git a/src/Core/Abstractions/IConfigService.cs b/src/Core/Abstractions/IConfigService.cs new file mode 100644 index 000000000..285288d2f --- /dev/null +++ b/src/Core/Abstractions/IConfigService.cs @@ -0,0 +1,15 @@ +using System; +using System.Threading.Tasks; +using Bit.Core.Models.Response; + +namespace Bit.Core.Abstractions +{ + public interface IConfigService + { + Task GetAsync(bool forceRefresh = false); + Task GetFeatureFlagBoolAsync(string key, bool forceRefresh = false, bool defaultValue = false); + Task GetFeatureFlagStringAsync(string key, bool forceRefresh = false, string defaultValue = null); + Task GetFeatureFlagIntAsync(string key, bool forceRefresh = false, int defaultValue = 0); + } +} + diff --git a/src/Core/Abstractions/IPasswordGenerationService.cs b/src/Core/Abstractions/IPasswordGenerationService.cs index 74f46ea7c..25062f2ac 100644 --- a/src/Core/Abstractions/IPasswordGenerationService.cs +++ b/src/Core/Abstractions/IPasswordGenerationService.cs @@ -15,8 +15,6 @@ namespace Bit.Core.Abstractions Task GeneratePasswordAsync(PasswordGenerationOptions options); Task> GetHistoryAsync(); Task<(PasswordGenerationOptions, PasswordGeneratorPolicyOptions)> GetOptionsAsync(); - Task<(PasswordGenerationOptions, PasswordGeneratorPolicyOptions)> - EnforcePasswordGeneratorPoliciesOnOptionsAsync(PasswordGenerationOptions options); Result PasswordStrength(string password, List userInputs = null); Task SaveOptionsAsync(PasswordGenerationOptions options); void NormalizeOptions(PasswordGenerationOptions options, PasswordGeneratorPolicyOptions enforcedPolicyOptions); diff --git a/src/Core/Abstractions/IPolicyService.cs b/src/Core/Abstractions/IPolicyService.cs index 8acca2c9a..75ca6168e 100644 --- a/src/Core/Abstractions/IPolicyService.cs +++ b/src/Core/Abstractions/IPolicyService.cs @@ -19,8 +19,7 @@ namespace Bit.Core.Abstractions Tuple GetResetPasswordPolicyOptions(IEnumerable policies, string orgId); Task PolicyAppliesToUser(PolicyType policyType, Func policyFilter = null, string userId = null); - int? GetPolicyInt(Policy policy, string key); - string GetPolicyString(Policy policy, string key); Task ShouldShowVaultFilterAsync(); + Task GetPasswordGeneratorPolicyOptionsAsync(); } } diff --git a/src/Core/Abstractions/IStateService.cs b/src/Core/Abstractions/IStateService.cs index 4062599af..355acd093 100644 --- a/src/Core/Abstractions/IStateService.cs +++ b/src/Core/Abstractions/IStateService.cs @@ -174,5 +174,7 @@ namespace Bit.Core.Abstractions Task SetPreLoginEmailAsync(string value); string GetLocale(); void SetLocale(string locale); + ConfigResponse GetConfigs(); + void SetConfigs(ConfigResponse value); } } diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs index 0f4b0915c..73863f580 100644 --- a/src/Core/Constants.cs +++ b/src/Core/Constants.cs @@ -41,6 +41,9 @@ public const string NotificationDataType = "Type"; public const string PasswordlessLoginRequestKey = "passwordlessLoginRequest"; public const string PreLoginEmailKey = "preLoginEmailKey"; + public const string ConfigsKey = "configsKey"; + public const string DisplayEuEnvironmentFlag = "display-eu-environment"; + /// /// This key is used to store the value of "ShouldConnectToWatch" of the last user that had logged in /// which is used to handle Apple Watch state logic diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index bb55f7d47..216e148d7 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -28,12 +28,12 @@ - - - + + + - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Core/Models/Data/EnvironmentUrlData.cs b/src/Core/Models/Data/EnvironmentUrlData.cs index 744541e19..ae57f804b 100644 --- a/src/Core/Models/Data/EnvironmentUrlData.cs +++ b/src/Core/Models/Data/EnvironmentUrlData.cs @@ -2,6 +2,9 @@ { public class EnvironmentUrlData { + public static EnvironmentUrlData DefaultUS = new EnvironmentUrlData { Base = "https://vault.bitwarden.com" }; + public static EnvironmentUrlData DefaultEU = new EnvironmentUrlData { Base = "https://vault.bitwarden.eu" }; + public string Base { get; set; } public string Api { get; set; } public string Identity { get; set; } @@ -9,5 +12,13 @@ public string Notifications { get; set; } public string WebVault { get; set; } public string Events { get; set; } + + public bool IsEmpty => string.IsNullOrEmpty(Base) + && string.IsNullOrEmpty(Api) + && string.IsNullOrEmpty(Identity) + && string.IsNullOrEmpty(Icons) + && string.IsNullOrEmpty(Notifications) + && string.IsNullOrEmpty(WebVault) + && string.IsNullOrEmpty(Events); } } diff --git a/src/Core/Models/Domain/PasswordGenerationOptions.cs b/src/Core/Models/Domain/PasswordGenerationOptions.cs index 16afec6bf..bab849661 100644 --- a/src/Core/Models/Domain/PasswordGenerationOptions.cs +++ b/src/Core/Models/Domain/PasswordGenerationOptions.cs @@ -2,29 +2,29 @@ { public class PasswordGenerationOptions { - public PasswordGenerationOptions() { } + public const string TYPE_PASSWORD = "password"; + public const string TYPE_PASSPHRASE = "passphrase"; - public PasswordGenerationOptions(bool defaultOptions) + public static PasswordGenerationOptions CreateDefault => new PasswordGenerationOptions { - if (defaultOptions) - { - Length = 14; - AllowAmbiguousChar = true; - Number = true; - MinNumber = 1; - Uppercase = true; - MinUppercase = 0; - Lowercase = true; - MinLowercase = 0; - Special = false; - MinSpecial = 1; - Type = "password"; - NumWords = 3; - WordSeparator = "-"; - Capitalize = false; - IncludeNumber = false; - } - } + Length = 14, + AllowAmbiguousChar = true, + Number = true, + MinNumber = 1, + Uppercase = true, + MinUppercase = 0, + Lowercase = true, + MinLowercase = 0, + Special = false, + MinSpecial = 1, + Type = TYPE_PASSWORD, + NumWords = 3, + WordSeparator = "-", + Capitalize = false, + IncludeNumber = false + }; + + public PasswordGenerationOptions() { } public int? Length { get; set; } public bool? AllowAmbiguousChar { get; set; } @@ -42,6 +42,12 @@ public bool? Capitalize { get; set; } public bool? IncludeNumber { get; set; } + public PasswordGenerationOptions WithLength(int? length) + { + Length = length; + return this; + } + public void Merge(PasswordGenerationOptions defaults) { Length = Length ?? defaults.Length; @@ -60,5 +66,75 @@ Capitalize = Capitalize ?? defaults.Capitalize; IncludeNumber = IncludeNumber ?? defaults.IncludeNumber; } + + public void EnforcePolicy(PasswordGeneratorPolicyOptions enforcedPolicyOptions) + { + if (enforcedPolicyOptions is null) + { + return; + } + + if (Length < enforcedPolicyOptions.MinLength) + { + Length = enforcedPolicyOptions.MinLength; + } + + if (enforcedPolicyOptions.UseUppercase) + { + Uppercase = true; + } + + if (enforcedPolicyOptions.UseLowercase) + { + Lowercase = true; + } + + if (enforcedPolicyOptions.UseNumbers) + { + Number = true; + } + + if (MinNumber < enforcedPolicyOptions.NumberCount) + { + MinNumber = enforcedPolicyOptions.NumberCount; + } + + if (enforcedPolicyOptions.UseSpecial) + { + Special = true; + } + + if (MinSpecial < enforcedPolicyOptions.SpecialCount) + { + MinSpecial = enforcedPolicyOptions.SpecialCount; + } + + // Must normalize these fields because the receiving call expects all options to pass the current rules + if (MinSpecial + MinNumber > Length) + { + MinSpecial = Length - MinNumber; + } + + if (NumWords < enforcedPolicyOptions.MinNumberOfWords) + { + NumWords = enforcedPolicyOptions.MinNumberOfWords; + } + + if (enforcedPolicyOptions.Capitalize) + { + Capitalize = true; + } + + if (enforcedPolicyOptions.IncludeNumber) + { + IncludeNumber = true; + } + + // Force default type if password/passphrase selected via policy + if (enforcedPolicyOptions.DefaultType == TYPE_PASSWORD || enforcedPolicyOptions.DefaultType == TYPE_PASSPHRASE) + { + Type = enforcedPolicyOptions.DefaultType; + } + } } } diff --git a/src/Core/Models/Domain/Policy.cs b/src/Core/Models/Domain/Policy.cs index a84b095d0..3d58c2fb8 100644 --- a/src/Core/Models/Domain/Policy.cs +++ b/src/Core/Models/Domain/Policy.cs @@ -6,6 +6,11 @@ namespace Bit.Core.Models.Domain { public class Policy : Domain { + public const string MINUTES_KEY = "minutes"; + public const string ACTION_KEY = "action"; + public const string ACTION_LOCK = "lock"; + public const string ACTION_LOGOUT = "logOut"; + public Policy() { } public Policy(PolicyData obj) @@ -22,5 +27,32 @@ namespace Bit.Core.Models.Domain public PolicyType Type { get; set; } public Dictionary Data { get; set; } public bool Enabled { get; set; } + + public int? GetInt(string key) + { + if (Data.TryGetValue(key, out var val) && val != null) + { + return (int)(long)val; + } + return null; + } + + public bool? GetBool(string key) + { + if (Data.TryGetValue(key, out var val) && val != null) + { + return (bool)val; + } + return null; + } + + public string GetString(string key) + { + if (Data.TryGetValue(key, out var val)) + { + return (string)val; + } + return null; + } } } diff --git a/src/Core/Models/Response/ConfigResponse.cs b/src/Core/Models/Response/ConfigResponse.cs new file mode 100644 index 000000000..d171a4bad --- /dev/null +++ b/src/Core/Models/Response/ConfigResponse.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; + +namespace Bit.Core.Models.Response +{ + public class ConfigResponse + { + public string Version { get; set; } + public string GitHash { get; set; } + public ServerConfigResponse Server { get; set; } + public EnvironmentConfigResponse Environment { get; set; } + public IDictionary FeatureStates { get; set; } + public DateTime ExpiresOn { get; set; } + } + + public class ServerConfigResponse + { + public string Name { get; set; } + public string Url { get; set; } + } + + public class EnvironmentConfigResponse + { + public string Vault { get; set; } + public string Api { get; set; } + public string Identity { get; set; } + public string Notifications { get; set; } + public string Sso { get; set; } + } +} + diff --git a/src/Core/Services/ApiService.cs b/src/Core/Services/ApiService.cs index 5aabe4acc..1ca456383 100644 --- a/src/Core/Services/ApiService.cs +++ b/src/Core/Services/ApiService.cs @@ -586,6 +586,16 @@ namespace Bit.Core.Services #endregion + #region Configs + + public async Task GetConfigsAsync() + { + var accessToken = await _tokenService.GetTokenAsync(); + return await SendAsync(HttpMethod.Get, "/config/", null, !string.IsNullOrEmpty(accessToken), true); + } + + #endregion + #region Helpers public async Task GetActiveBearerTokenAsync() diff --git a/src/Core/Services/AuthService.cs b/src/Core/Services/AuthService.cs index 5fa8a2115..92cbadd3b 100644 --- a/src/Core/Services/AuthService.cs +++ b/src/Core/Services/AuthService.cs @@ -605,7 +605,7 @@ namespace Bit.Core.Services var generatedFingerprintPhrase = await _cryptoService.GetFingerprintAsync(email, keyPair.Item1); var fingerprintPhrase = string.Join("-", generatedFingerprintPhrase); var publicB64 = Convert.ToBase64String(keyPair.Item1); - var accessCode = await _passwordGenerationService.GeneratePasswordAsync(new PasswordGenerationOptions(true) { Length = 25 }); + var accessCode = await _passwordGenerationService.GeneratePasswordAsync(PasswordGenerationOptions.CreateDefault.WithLength(25)); var passwordlessCreateLoginRequest = new PasswordlessCreateLoginRequest(email, publicB64, deviceId, accessCode, AuthRequestType.AuthenticateAndUnlock, fingerprintPhrase); var response = await _apiService.PostCreateRequestAsync(passwordlessCreateLoginRequest); diff --git a/src/Core/Services/ConfigService.cs b/src/Core/Services/ConfigService.cs new file mode 100644 index 000000000..360fc4b0f --- /dev/null +++ b/src/Core/Services/ConfigService.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Bit.Core.Abstractions; +using Bit.Core.Exceptions; +using Bit.Core.Models.Domain; +using Bit.Core.Models.Response; +using Bit.Core.Models.View; + +namespace Bit.Core.Services +{ + public class ConfigService : IConfigService + { + private const int UPDATE_INTERVAL_MINS = 60; + private ConfigResponse _configs; + private readonly IApiService _apiService; + private readonly IStateService _stateService; + private readonly ILogger _logger; + + public ConfigService(IApiService apiService, IStateService stateService, ILogger logger) + { + _apiService = apiService; + _stateService = stateService; + _logger = logger; + } + + public async Task GetAsync(bool forceRefresh = false) + { + try + { + _configs = _stateService.GetConfigs(); + if (forceRefresh || _configs?.ExpiresOn is null || _configs.ExpiresOn <= DateTime.UtcNow) + { + _configs = await _apiService.GetConfigsAsync(); + _configs.ExpiresOn = DateTime.UtcNow.AddMinutes(UPDATE_INTERVAL_MINS); + _stateService.SetConfigs(_configs); + } + } + catch (ApiException ex) when (ex.Error.StatusCode == System.Net.HttpStatusCode.BadGateway) + { + // ignore if there is no internet connection and return local configs + } + catch (Exception ex) + { + _logger.Exception(ex); + } + + return _configs; + } + + public async Task GetFeatureFlagBoolAsync(string key, bool forceRefresh = false, bool defaultValue = false) => await GetFeatureFlagAsync(key, forceRefresh, defaultValue); + + public async Task GetFeatureFlagStringAsync(string key, bool forceRefresh = false, string defaultValue = null) => await GetFeatureFlagAsync(key, forceRefresh, defaultValue); + + public async Task GetFeatureFlagIntAsync(string key, bool forceRefresh = false, int defaultValue = 0) => await GetFeatureFlagAsync(key, forceRefresh, defaultValue); + + private async Task GetFeatureFlagAsync(string key, bool forceRefresh = false, T defaultValue = default) + { + await GetAsync(forceRefresh); + if (_configs == null || _configs.FeatureStates == null) + { + return defaultValue; + } + + if (_configs.FeatureStates.TryGetValue(key, out var val) == true + && + val is T actualValue) + { + return actualValue; + } + + return defaultValue; + } + } +} + diff --git a/src/Core/Services/PasswordGenerationService.cs b/src/Core/Services/PasswordGenerationService.cs index e689616c2..3210cccad 100644 --- a/src/Core/Services/PasswordGenerationService.cs +++ b/src/Core/Services/PasswordGenerationService.cs @@ -6,7 +6,6 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Bit.Core.Abstractions; -using Bit.Core.Enums; using Bit.Core.Models.Domain; using Bit.Core.Utilities; using Zxcvbn; @@ -15,17 +14,17 @@ namespace Bit.Core.Services { public class PasswordGenerationService : IPasswordGenerationService { - private const int MaxPasswordsInHistory = 100; - private const string LowercaseCharSet = "abcdefghijkmnopqrstuvwxyz"; - private const string UppercaseCharSet = "ABCDEFGHJKLMNPQRSTUVWXYZ"; - private const string NumberCharSet = "23456789"; - private const string SpecialCharSet = "!@#$%^&*"; + private const int MAX_PASSWORDS_IN_HISTORY = 100; + private const string LOWERCASE_CHAR_SET = "abcdefghijkmnopqrstuvwxyz"; + private const string UPPERCASE_CHAR_SET = "ABCDEFGHJKLMNPQRSTUVWXYZ"; + private const string NUMER_CHAR_SET = "23456789"; + private const string SPECIAL_CHAR_SET = "!@#$%^&*"; private readonly ICryptoService _cryptoService; private readonly IStateService _stateService; private readonly ICryptoFunctionService _cryptoFunctionService; private readonly IPolicyService _policyService; - private PasswordGenerationOptions _defaultOptions = new PasswordGenerationOptions(true); + private PasswordGenerationOptions _defaultOptions = PasswordGenerationOptions.CreateDefault; private PasswordGenerationOptions _optionsCache; private List _history; @@ -45,7 +44,7 @@ namespace Bit.Core.Services { // Overload defaults with given options options.Merge(_defaultOptions); - if (options.Type == "passphrase") + if (options.Type == PasswordGenerationOptions.TYPE_PASSPHRASE) { return await GeneratePassphraseAsync(options); } @@ -54,30 +53,30 @@ namespace Bit.Core.Services SanitizePasswordLength(options, true); var positionsBuilder = new StringBuilder(); - if (options.Lowercase.GetValueOrDefault() && options.MinLowercase.GetValueOrDefault() > 0) + if (options.Lowercase.GetValueOrDefault() && options.MinLowercase > 0) { - for (int i = 0; i < options.MinLowercase.GetValueOrDefault(); i++) + for (int i = 0; i < options.MinLowercase; i++) { positionsBuilder.Append("l"); } } - if (options.Uppercase.GetValueOrDefault() && options.MinUppercase.GetValueOrDefault() > 0) + if (options.Uppercase.GetValueOrDefault() && options.MinUppercase > 0) { - for (int i = 0; i < options.MinUppercase.GetValueOrDefault(); i++) + for (int i = 0; i < options.MinUppercase; i++) { positionsBuilder.Append("u"); } } - if (options.Number.GetValueOrDefault() && options.MinNumber.GetValueOrDefault() > 0) + if (options.Number.GetValueOrDefault() && options.MinNumber > 0) { - for (int i = 0; i < options.MinNumber.GetValueOrDefault(); i++) + for (int i = 0; i < options.MinNumber; i++) { positionsBuilder.Append("n"); } } - if (options.Special.GetValueOrDefault() && options.MinSpecial.GetValueOrDefault() > 0) + if (options.Special.GetValueOrDefault() && options.MinSpecial > 0) { - for (int i = 0; i < options.MinSpecial.GetValueOrDefault(); i++) + for (int i = 0; i < options.MinSpecial; i++) { positionsBuilder.Append("s"); } @@ -92,68 +91,68 @@ namespace Bit.Core.Services .OrderBy(a => _cryptoFunctionService.RandomNumber()).ToArray(); // Build out other character sets - var allCharSet = string.Empty; - var lowercaseCharSet = LowercaseCharSet; + var allCharSet = new StringBuilder(); + + var lowercaseCharSet = LOWERCASE_CHAR_SET; if (options.AllowAmbiguousChar.GetValueOrDefault()) { lowercaseCharSet = string.Concat(lowercaseCharSet, "l"); } if (options.Lowercase.GetValueOrDefault()) { - allCharSet = string.Concat(allCharSet, lowercaseCharSet); + allCharSet.Append(lowercaseCharSet); } - var uppercaseCharSet = UppercaseCharSet; + var uppercaseCharSet = UPPERCASE_CHAR_SET; if (options.AllowAmbiguousChar.GetValueOrDefault()) { uppercaseCharSet = string.Concat(uppercaseCharSet, "IO"); } if (options.Uppercase.GetValueOrDefault()) { - allCharSet = string.Concat(allCharSet, uppercaseCharSet); + allCharSet.Append(uppercaseCharSet); } - var numberCharSet = NumberCharSet; + var numberCharSet = NUMER_CHAR_SET; if (options.AllowAmbiguousChar.GetValueOrDefault()) { numberCharSet = string.Concat(numberCharSet, "01"); } if (options.Number.GetValueOrDefault()) { - allCharSet = string.Concat(allCharSet, numberCharSet); + allCharSet.Append(numberCharSet); } - var specialCharSet = SpecialCharSet; if (options.Special.GetValueOrDefault()) { - allCharSet = string.Concat(allCharSet, specialCharSet); + allCharSet.Append(SPECIAL_CHAR_SET); } var password = new StringBuilder(); for (var i = 0; i < options.Length.GetValueOrDefault(); i++) { - var positionChars = string.Empty; + var charSetOnCurrentPosition = string.Empty; switch (positions[i]) { case 'l': - positionChars = lowercaseCharSet; + charSetOnCurrentPosition = lowercaseCharSet; break; case 'u': - positionChars = uppercaseCharSet; + charSetOnCurrentPosition = uppercaseCharSet; break; case 'n': - positionChars = numberCharSet; + charSetOnCurrentPosition = numberCharSet; break; case 's': - positionChars = specialCharSet; + charSetOnCurrentPosition = SPECIAL_CHAR_SET; break; case 'a': - positionChars = allCharSet; + charSetOnCurrentPosition = allCharSet.ToString(); break; } - var randomCharIndex = await _cryptoService.RandomNumberAsync(0, positionChars.Length - 1); - password.Append(positionChars[randomCharIndex]); + var randomCharIndex = await _cryptoService.RandomNumberAsync(0, charSetOnCurrentPosition.Length - 1); + password.Append(charSetOnCurrentPosition[randomCharIndex]); } return password.ToString(); @@ -168,7 +167,7 @@ namespace Bit.Core.Services public async Task GeneratePassphraseAsync(PasswordGenerationOptions options) { options.Merge(_defaultOptions); - if (options.NumWords.GetValueOrDefault() <= 2) + if (options.NumWords <= 2) { options.NumWords = _defaultOptions.NumWords; } @@ -221,179 +220,10 @@ namespace Bit.Core.Services } } - var (enforcedOptions, enforcedPolicyOptions) = await EnforcePasswordGeneratorPoliciesOnOptionsAsync( - _optionsCache); - _optionsCache = enforcedOptions; - return (_optionsCache, enforcedPolicyOptions); - } + var policyOptions = await _policyService.GetPasswordGeneratorPolicyOptionsAsync(); + _optionsCache.EnforcePolicy(policyOptions); - public async Task<(PasswordGenerationOptions, PasswordGeneratorPolicyOptions)> - EnforcePasswordGeneratorPoliciesOnOptionsAsync(PasswordGenerationOptions options) - { - var enforcedPolicyOptions = await GetPasswordGeneratorPolicyOptions(); - if (enforcedPolicyOptions != null) - { - if (options.Length < enforcedPolicyOptions.MinLength) - { - options.Length = enforcedPolicyOptions.MinLength; - } - - if (enforcedPolicyOptions.UseUppercase) - { - options.Uppercase = true; - } - - if (enforcedPolicyOptions.UseLowercase) - { - options.Lowercase = true; - } - - if (enforcedPolicyOptions.UseNumbers) - { - options.Number = true; - } - - if (options.MinNumber < enforcedPolicyOptions.NumberCount) - { - options.MinNumber = enforcedPolicyOptions.NumberCount; - } - - if (enforcedPolicyOptions.UseSpecial) - { - options.Special = true; - } - - if (options.MinSpecial < enforcedPolicyOptions.SpecialCount) - { - options.MinSpecial = enforcedPolicyOptions.SpecialCount; - } - - // Must normalize these fields because the receiving call expects all options to pass the current rules - if (options.MinSpecial + options.MinNumber > options.Length) - { - options.MinSpecial = options.Length - options.MinNumber; - } - - if (options.NumWords < enforcedPolicyOptions.MinNumberOfWords) - { - options.NumWords = enforcedPolicyOptions.MinNumberOfWords; - } - - if (enforcedPolicyOptions.Capitalize) - { - options.Capitalize = true; - } - - if (enforcedPolicyOptions.IncludeNumber) - { - options.IncludeNumber = true; - } - - // Force default type if password/passphrase selected via policy - if (enforcedPolicyOptions.DefaultType == "password" || enforcedPolicyOptions.DefaultType == "passphrase") - { - options.Type = enforcedPolicyOptions.DefaultType; - } - } - else - { - // UI layer expects an instantiated object to prevent more explicit null checks - enforcedPolicyOptions = new PasswordGeneratorPolicyOptions(); - } - - return (options, enforcedPolicyOptions); - } - - public async Task GetPasswordGeneratorPolicyOptions() - { - var policies = await _policyService.GetAll(PolicyType.PasswordGenerator); - PasswordGeneratorPolicyOptions enforcedOptions = null; - - if (policies == null || !policies.Any()) - { - return enforcedOptions; - } - - foreach (var currentPolicy in policies) - { - if (!currentPolicy.Enabled || currentPolicy.Data == null) - { - continue; - } - - if (enforcedOptions == null) - { - enforcedOptions = new PasswordGeneratorPolicyOptions(); - } - - var defaultType = GetPolicyString(currentPolicy, "defaultType"); - if (defaultType != null && enforcedOptions.DefaultType != "password") - { - enforcedOptions.DefaultType = defaultType; - } - - var minLength = GetPolicyInt(currentPolicy, "minLength"); - if (minLength != null && (int)(long)minLength > enforcedOptions.MinLength) - { - enforcedOptions.MinLength = (int)(long)minLength; - } - - var useUpper = GetPolicyBool(currentPolicy, "useUpper"); - if (useUpper != null && (bool)useUpper) - { - enforcedOptions.UseUppercase = true; - } - - var useLower = GetPolicyBool(currentPolicy, "useLower"); - if (useLower != null && (bool)useLower) - { - enforcedOptions.UseLowercase = true; - } - - var useNumbers = GetPolicyBool(currentPolicy, "useNumbers"); - if (useNumbers != null && (bool)useNumbers) - { - enforcedOptions.UseNumbers = true; - } - - var minNumbers = GetPolicyInt(currentPolicy, "minNumbers"); - if (minNumbers != null && (int)(long)minNumbers > enforcedOptions.NumberCount) - { - enforcedOptions.NumberCount = (int)(long)minNumbers; - } - - var useSpecial = GetPolicyBool(currentPolicy, "useSpecial"); - if (useSpecial != null && (bool)useSpecial) - { - enforcedOptions.UseSpecial = true; - } - - var minSpecial = GetPolicyInt(currentPolicy, "minSpecial"); - if (minSpecial != null && (int)(long)minSpecial > enforcedOptions.SpecialCount) - { - enforcedOptions.SpecialCount = (int)(long)minSpecial; - } - - var minNumberWords = GetPolicyInt(currentPolicy, "minNumberWords"); - if (minNumberWords != null && (int)(long)minNumberWords > enforcedOptions.MinNumberOfWords) - { - enforcedOptions.MinNumberOfWords = (int)(long)minNumberWords; - } - - var capitalize = GetPolicyBool(currentPolicy, "capitalize"); - if (capitalize != null && (bool)capitalize) - { - enforcedOptions.Capitalize = true; - } - - var includeNumber = GetPolicyBool(currentPolicy, "includeNumber"); - if (includeNumber != null && (bool)includeNumber) - { - enforcedOptions.IncludeNumber = true; - } - } - - return enforcedOptions; + return (_optionsCache, policyOptions ?? new PasswordGeneratorPolicyOptions()); } public List GetPasswordStrengthUserInput(string email) @@ -409,45 +239,6 @@ namespace Bit.Core.Services return new List(data); } - private int? GetPolicyInt(Policy policy, string key) - { - if (policy.Data.ContainsKey(key)) - { - var value = policy.Data[key]; - if (value != null) - { - return (int)(long)value; - } - } - return null; - } - - private bool? GetPolicyBool(Policy policy, string key) - { - if (policy.Data.ContainsKey(key)) - { - var value = policy.Data[key]; - if (value != null) - { - return (bool)value; - } - } - return null; - } - - private string GetPolicyString(Policy policy, string key) - { - if (policy.Data.ContainsKey(key)) - { - var value = policy.Data[key]; - if (value != null) - { - return (string)value; - } - } - return null; - } - public async Task SaveOptionsAsync(PasswordGenerationOptions options) { await _stateService.SetPasswordGenerationOptionsAsync(options); @@ -485,7 +276,7 @@ namespace Bit.Core.Services token.ThrowIfCancellationRequested(); currentHistory.Insert(0, new GeneratedPasswordHistory { Password = password, Date = DateTime.UtcNow }); // Remove old items. - if (currentHistory.Count > MaxPasswordsInHistory) + if (currentHistory.Count > MAX_PASSWORDS_IN_HISTORY) { currentHistory.RemoveAt(currentHistory.Count - 1); } diff --git a/src/Core/Services/PolicyService.cs b/src/Core/Services/PolicyService.cs index b6922dd56..9301763ac 100644 --- a/src/Core/Services/PolicyService.cs +++ b/src/Core/Services/PolicyService.cs @@ -17,11 +17,6 @@ namespace Bit.Core.Services private IEnumerable _policyCache; - public const string TIMEOUT_POLICY_MINUTES = "minutes"; - public const string TIMEOUT_POLICY_ACTION = "action"; - public const string TIMEOUT_POLICY_ACTION_LOCK = "lock"; - public const string TIMEOUT_POLICY_ACTION_LOGOUT = "logOut"; - public PolicyService( IStateService stateService, IOrganizationService organizationService) @@ -51,10 +46,8 @@ namespace Bit.Core.Services { return _policyCache.Where(p => p.Type == type).ToList(); } - else - { - return _policyCache; - } + + return _policyCache; } public async Task Replace(Dictionary policies, string userId = null) @@ -77,7 +70,7 @@ namespace Bit.Core.Services public async Task UpdateVaultTimeoutFromPolicyAsync(Policy policy, string userId = null) { - var policyTimeout = GetPolicyInt(policy, PolicyService.TIMEOUT_POLICY_MINUTES); + var policyTimeout = policy.GetInt(Policy.MINUTES_KEY); if (policyTimeout != null) { var vaultTimeout = await _stateService.GetVaultTimeoutAsync(userId); @@ -92,11 +85,11 @@ namespace Bit.Core.Services } } - var policyAction = GetPolicyString(policy, PolicyService.TIMEOUT_POLICY_ACTION); + var policyAction = policy.GetString(Policy.ACTION_KEY); if (!string.IsNullOrEmpty(policyAction)) { var vaultTimeoutAction = await _stateService.GetVaultTimeoutActionAsync(userId); - var action = policyAction == PolicyService.TIMEOUT_POLICY_ACTION_LOCK ? VaultTimeoutAction.Lock : VaultTimeoutAction.Logout; + var action = policyAction == Policy.ACTION_LOCK ? VaultTimeoutAction.Lock : VaultTimeoutAction.Logout; if (vaultTimeoutAction != action) { await _stateService.SetVaultTimeoutActionAsync(action, userId); @@ -107,71 +100,63 @@ namespace Bit.Core.Services public async Task GetMasterPasswordPolicyOptions( IEnumerable policies = null, string userId = null) { - MasterPasswordPolicyOptions enforcedOptions = null; - if (policies == null) { policies = await GetAll(PolicyType.MasterPassword, userId); + if (policies == null) + { + return null; + } } else { policies = policies.Where(p => p.Type == PolicyType.MasterPassword); } - if (policies == null || !policies.Any()) + policies = policies.Where(p => p.Enabled && p.Data != null); + + if (!policies.Any()) { - return enforcedOptions; + return null; } + var enforcedOptions = new MasterPasswordPolicyOptions(); + foreach (var currentPolicy in policies) { - if (!currentPolicy.Enabled || currentPolicy.Data == null) + var minComplexity = currentPolicy.GetInt("minComplexity"); + if (minComplexity > enforcedOptions.MinComplexity) { - continue; + enforcedOptions.MinComplexity = minComplexity.Value; } - if (enforcedOptions == null) + var minLength = currentPolicy.GetInt("minLength"); + if (minLength > enforcedOptions.MinLength) { - enforcedOptions = new MasterPasswordPolicyOptions(); + enforcedOptions.MinLength = minLength.Value; } - var minComplexity = GetPolicyInt(currentPolicy, "minComplexity"); - if (minComplexity != null && (int)(long)minComplexity > enforcedOptions.MinComplexity) - { - enforcedOptions.MinComplexity = (int)(long)minComplexity; - } - - var minLength = GetPolicyInt(currentPolicy, "minLength"); - if (minLength != null && (int)(long)minLength > enforcedOptions.MinLength) - { - enforcedOptions.MinLength = (int)(long)minLength; - } - - var requireUpper = GetPolicyBool(currentPolicy, "requireUpper"); - if (requireUpper == true) + if (currentPolicy.GetBool("requireUpper") == true) { enforcedOptions.RequireUpper = true; } - var requireLower = GetPolicyBool(currentPolicy, "requireLower"); - if (requireLower == true) + if (currentPolicy.GetBool("requireLower") == true) { enforcedOptions.RequireLower = true; } - var requireNumbers = GetPolicyBool(currentPolicy, "requireNumbers"); - if (requireNumbers == true) + if (currentPolicy.GetBool("requireNumbers") == true) { enforcedOptions.RequireNumbers = true; } - var requireSpecial = GetPolicyBool(currentPolicy, "requireSpecial"); - if (requireSpecial == true) + if (currentPolicy.GetBool("requireSpecial") == true) { enforcedOptions.RequireSpecial = true; } - var enforceOnLogin = GetPolicyBool(currentPolicy, "enforceOnLogin"); + var enforceOnLogin = currentPolicy.GetBool("enforceOnLogin"); if (enforceOnLogin == true) { enforcedOptions.EnforceOnLogin = true; @@ -234,7 +219,7 @@ namespace Bit.Core.Services var policy = policies.FirstOrDefault(p => p.OrganizationId == orgId && p.Type == PolicyType.ResetPassword && p.Enabled); - resetPasswordPolicyOptions.AutoEnrollEnabled = GetPolicyBool(policy, "autoEnrollEnabled") ?? false; + resetPasswordPolicyOptions.AutoEnrollEnabled = policy.GetBool("autoEnrollEnabled") ?? false; return new Tuple(resetPasswordPolicyOptions, policy != null); } @@ -280,23 +265,6 @@ namespace Bit.Core.Services return organization.isExemptFromPolicies; } - public int? GetPolicyInt(Policy policy, string key) - { - if (policy.Data.ContainsKey(key)) - { - var value = policy.Data[key]; - if (value != null) - { - return (int)(long)value; - } - } - return null; - } - - public string GetPolicyString(Policy policy, string key) => - policy.Data.TryGetValue(key, out var val) ? val as string : null; - - public async Task ShouldShowVaultFilterAsync() { var personalOwnershipPolicyApplies = await PolicyAppliesToUser(PolicyType.PersonalOwnership); @@ -309,19 +277,86 @@ namespace Bit.Core.Services return organizations?.Any() ?? false; } - private bool? GetPolicyBool(Policy policy, string key) + public async Task GetPasswordGeneratorPolicyOptionsAsync() { - if (policy.Data.ContainsKey(key)) + var policies = await GetAll(PolicyType.PasswordGenerator); + if (policies == null) { - var value = policy.Data[key]; - if (value != null) + return null; + } + + var actualPolicies = policies.Where(p => p.Enabled && p.Data != null); + if (!actualPolicies.Any()) + { + return null; + } + + var enforcedOptions = new PasswordGeneratorPolicyOptions(); + + foreach (var currentPolicy in actualPolicies) + { + var defaultType = currentPolicy.GetString("defaultType"); + if (defaultType != null && enforcedOptions.DefaultType != PasswordGenerationOptions.TYPE_PASSWORD) { - return (bool)value; + enforcedOptions.DefaultType = defaultType; + } + + var minLength = currentPolicy.GetInt("minLength"); + if (minLength > enforcedOptions.MinLength) + { + enforcedOptions.MinLength = minLength.Value; + } + + if (currentPolicy.GetBool("useUpper") == true) + { + enforcedOptions.UseUppercase = true; + } + + if (currentPolicy.GetBool("useLower") == true) + { + enforcedOptions.UseLowercase = true; + } + + if (currentPolicy.GetBool("useNumbers") == true) + { + enforcedOptions.UseNumbers = true; + } + + var minNumbers = currentPolicy.GetInt("minNumbers"); + if (minNumbers > enforcedOptions.NumberCount) + { + enforcedOptions.NumberCount = minNumbers.Value; + } + + if (currentPolicy.GetBool("useSpecial") == true) + { + enforcedOptions.UseSpecial = true; + } + + var minSpecial = currentPolicy.GetInt("minSpecial"); + if (minSpecial > enforcedOptions.SpecialCount) + { + enforcedOptions.SpecialCount = minSpecial.Value; + } + + var minNumberWords = currentPolicy.GetInt("minNumberWords"); + if (minNumberWords > enforcedOptions.MinNumberOfWords) + { + enforcedOptions.MinNumberOfWords = minNumberWords.Value; + } + + if (currentPolicy.GetBool("capitalize") == true) + { + enforcedOptions.Capitalize = true; + } + + if (currentPolicy.GetBool("includeNumber") == true) + { + enforcedOptions.IncludeNumber = true; } } - return null; + + return enforcedOptions; } - - } } diff --git a/src/Core/Services/StateService.cs b/src/Core/Services/StateService.cs index 363c44efb..ae2d62d8e 100644 --- a/src/Core/Services/StateService.cs +++ b/src/Core/Services/StateService.cs @@ -1280,6 +1280,16 @@ namespace Bit.Core.Services await SetValueAsync(Constants.PreLoginEmailKey, value, options); } + public ConfigResponse GetConfigs() + { + return _storageMediatorService.Get(Constants.ConfigsKey); + } + + public void SetConfigs(ConfigResponse value) + { + _storageMediatorService.Save(Constants.ConfigsKey, value); + } + // Helpers [Obsolete("Use IStorageMediatorService instead")] diff --git a/src/Core/Services/VaultTimeoutService.cs b/src/Core/Services/VaultTimeoutService.cs index eb800c984..f5bd7d4bd 100644 --- a/src/Core/Services/VaultTimeoutService.cs +++ b/src/Core/Services/VaultTimeoutService.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Bit.Core.Abstractions; using Bit.Core.Enums; +using Bit.Core.Models.Domain; namespace Bit.Core.Services { diff --git a/src/Core/Utilities/ServiceContainer.cs b/src/Core/Utilities/ServiceContainer.cs index 3f8400497..8cab68547 100644 --- a/src/Core/Utilities/ServiceContainer.cs +++ b/src/Core/Utilities/ServiceContainer.cs @@ -75,8 +75,7 @@ namespace Bit.Core.Utilities messagingService.Send("logout", extras); return Task.CompletedTask; }); - var passwordGenerationService = new PasswordGenerationService(cryptoService, stateService, - cryptoFunctionService, policyService); + var passwordGenerationService = new PasswordGenerationService(cryptoService, stateService, cryptoFunctionService, policyService); var totpService = new TotpService(cryptoFunctionService); var authService = new AuthService(cryptoService, cryptoFunctionService, apiService, stateService, tokenService, appIdService, i18nService, platformUtilsService, messagingService, vaultTimeoutService, @@ -88,6 +87,7 @@ namespace Bit.Core.Utilities var userVerificationService = new UserVerificationService(apiService, platformUtilsService, i18nService, cryptoService); var usernameGenerationService = new UsernameGenerationService(cryptoService, apiService, stateService); + var configService = new ConfigService(apiService, stateService, logger); Register(conditionedRunner); Register("tokenService", tokenService); @@ -113,6 +113,7 @@ namespace Bit.Core.Utilities Register("keyConnectorService", keyConnectorService); Register("userVerificationService", userVerificationService); Register(usernameGenerationService); + Register(configService); } public static void Register(string serviceName, T obj) diff --git a/src/iOS.Autofill/iOS.Autofill.csproj b/src/iOS.Autofill/iOS.Autofill.csproj index ce5fc0b09..2be018c61 100644 --- a/src/iOS.Autofill/iOS.Autofill.csproj +++ b/src/iOS.Autofill/iOS.Autofill.csproj @@ -266,7 +266,7 @@ - 4.5.3 + 5.0.1 diff --git a/src/iOS.Extension/Info.plist b/src/iOS.Extension/Info.plist index 26bd5b749..0d913e4b2 100644 --- a/src/iOS.Extension/Info.plist +++ b/src/iOS.Extension/Info.plist @@ -3,7 +3,7 @@ MinimumOSVersion - 10.0 + 11.0 CFBundleDisplayName Bitwarden CFBundleName diff --git a/src/iOS.Extension/iOS.Extension.csproj b/src/iOS.Extension/iOS.Extension.csproj index 44b0891fc..a0b98f0fb 100644 --- a/src/iOS.Extension/iOS.Extension.csproj +++ b/src/iOS.Extension/iOS.Extension.csproj @@ -242,7 +242,7 @@ - 4.5.3 + 5.0.1 diff --git a/src/iOS.ShareExtension/Info.plist b/src/iOS.ShareExtension/Info.plist index 719ccde84..d86024116 100644 --- a/src/iOS.ShareExtension/Info.plist +++ b/src/iOS.ShareExtension/Info.plist @@ -19,7 +19,7 @@ CFBundleVersion 1 MinimumOSVersion - 10.0 + 11.0 NSExtension NSExtensionMainStoryboard diff --git a/src/iOS.ShareExtension/iOS.ShareExtension.csproj b/src/iOS.ShareExtension/iOS.ShareExtension.csproj index 3beee6f8d..57f079e41 100644 --- a/src/iOS.ShareExtension/iOS.ShareExtension.csproj +++ b/src/iOS.ShareExtension/iOS.ShareExtension.csproj @@ -167,7 +167,7 @@ - 4.5.3 + 5.0.1 diff --git a/src/iOS/Info.plist b/src/iOS/Info.plist index 273ab49b6..256054ab5 100644 --- a/src/iOS/Info.plist +++ b/src/iOS/Info.plist @@ -3,7 +3,7 @@ MinimumOSVersion - 10.0 + 11.0 CFBundleDisplayName Bitwarden CFBundleName diff --git a/src/iOS/iOS.csproj b/src/iOS/iOS.csproj index ba4127910..4a5c7c18e 100644 --- a/src/iOS/iOS.csproj +++ b/src/iOS/iOS.csproj @@ -195,7 +195,7 @@ - 1.7.3 + 1.7.5 diff --git a/src/watchOS/bitwarden/bitwarden WatchKit Extension/Models/Mocks/CipherMock.swift b/src/watchOS/bitwarden/bitwarden WatchKit Extension/Models/Mocks/CipherMock.swift index 543e6a99e..7d22dc39a 100644 --- a/src/watchOS/bitwarden/bitwarden WatchKit Extension/Models/Mocks/CipherMock.swift +++ b/src/watchOS/bitwarden/bitwarden WatchKit Extension/Models/Mocks/CipherMock.swift @@ -2,7 +2,7 @@ import Foundation struct CipherMock { static let ciphers:[Cipher] = [ - Cipher(id: "0", name: "1933", userId: "123123", login: Login(username: "thisisatest@testing.com", totp: "otpauth://account?period=10&secret=LLLLLLLLLLLLLLLL", uris: cipherLoginUris)), + Cipher(id: "0", name: "MySite", userId: "123123", login: Login(username: "test@testing.com", totp: "otpauth://account?period=10&secret=LLLLLLLLLLLLLLLL", uris: cipherLoginUris)), Cipher(id: "1", name: "GitHub", userId: "123123", login: Login(username: "thisisatest@testing.com", totp: "LLLLLLLLLLLLLLLL", uris: cipherLoginUris)), Cipher(id: "2", name: "No user", userId: "123123", login: Login(username: nil, totp: "otpauth://account?period=10&digits=8&algorithm=sha256&secret=LLLLLLLLLLLLLLLL", uris: cipherLoginUris)), Cipher(id: "3", name: "Site 2", userId: "123123", login: Login(username: "longtestemail000000@fastmailasdfasdf.com", totp: "otpauth://account?period=10&digits=7&algorithm=sha512&secret=LLLLLLLLLLLLLLLL", uris: cipherLoginUris)), diff --git a/src/watchOS/bitwarden/bitwarden WatchKit Extension/ViewModels/CipherDetailsViewModel.swift b/src/watchOS/bitwarden/bitwarden WatchKit Extension/ViewModels/CipherDetailsViewModel.swift index bfed0a30b..41663d9dd 100644 --- a/src/watchOS/bitwarden/bitwarden WatchKit Extension/ViewModels/CipherDetailsViewModel.swift +++ b/src/watchOS/bitwarden/bitwarden WatchKit Extension/ViewModels/CipherDetailsViewModel.swift @@ -34,30 +34,34 @@ class CipherDetailsViewModel: ObservableObject{ self.counter = self.period - mod self.progress = Double(self.counter) / Double(self.period) } + if mod == 0 || self.totpFormatted == "" { do { - var totpF = try TotpService.shared.GetCodeAsync(key: self.key) ?? "" - if totpF.count > 4 { - let halfIndex = totpF.index(totpF.startIndex, offsetBy: totpF.count / 2) - totpF = "\(totpF[totpF.startIndex.. 4 { + let halfIndex = totpF.index(totpF.startIndex, offsetBy: totpF.count / 2) + totpF = "\(totpF[totpF.startIndex..System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Bitwarden पासवर्ड मैनेजर + बिटवार्डन पासवर्ड मैनेजर Max 30 characters - Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + बिटवार्डन अंतरराष्ट्रीय कॉरपोरेशन, 8बिट सॉल्यूश्नस एलएलसी की मूल कंपनी है। -NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. +द वर्ज, यूएस न्यूज़ एंड वर्ल्ड रिपोर्ट, सीनेट, और कई दूसरे मीडिया संगठन द्वारा बोला गया दुनिया का सबसे बेहतरीन पासवर्ड मैनेजर। -Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. +अनगिनत पासवर्ड मैनेज, स्टोर, महफूज़, और शेयर करें कही से भी। बिटवार्डन देता है ओपन सोर्स पासवर्ड मैनेजमेंट सुविधा सबको, चाहे वो घर पर हो, दफ्तर पर हो, या घूम रहे हो। -Generate strong, unique, and random passwords based on security requirements for every website you frequent. +आप जिन वेबसाइट पर जाते है उनके लिए बनाएं ताकतवर, खास, और बेतरतीब पासवर्ड उनकी सुरक्षा ज़रूरतो के हिसाब से। -Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. +बिटवार्डन सेंड किसी को भी एन्क्रिप्टेड जानकारी, फाइल और सादा टेक्सट, तुरंत भेजें। -Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. +बिटवार्डन कंपनियों के लिए टीम और बिज़नेस प्लान भी देता है ताकि आप अपने साथ काम करनेवालो के साथ पासवर्ड शेयर करे सुरक्षित होकर। -Why Choose Bitwarden: +बिटवार्डन को क्यों चुनें: -World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +ताकतवर एन्क्रिप्शन +पासवर्ड एडवांस एंड-टू-एंड एन्क्रिप्शन (एईएस-256 बिट, सॉल्टेड हैशटैग, और पीबीकेडीएफ2 शा-256) के साथ सुरक्षित रखा जाता है ताकि आपका डाटा महफूज़ और निजी रहे। -Built-in Password Generator -Generate strong, unique, and random passwords based on security requirements for every website you frequent. +पहले से बना पासवर्ड जेनरेटर +आप जिन वेबसाइट पर जाते है उनके लिए बनाएं ताकतवर, खास, और बेतरतीब पासवर्ड उनकी सुरक्षा ज़रूरतो के हिसाब से। -Global Translations -Bitwarden translations exist in 40 languages and are growing, thanks to our global community. +अंतरराष्ट्रीय अनुवाद +40 से ज़्यादा भाषा में बिटवार्डन इस्तेमाल करें, जिसे लिखा है हमारी अंतरराष्ट्रीय दोस्तो ने। -Cross-Platform Applications -Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. +कई प्लेनफॉर्म पर मौजूद +अपने बिटवार्डन तिजोरी से संवेदनशील डाटा महफूज़ और शेयर करें किसी भी ब्राउज़र, फोन, या डेस्कटॉप जैसे डिवाइसो से। Max 4000 characters - बिटवर्डन, 8 बिट, पासवर्ड, फ्री पासवर्ड मैनेजर, पासवर्ड मैनेजर, लॉगिन मैनेजर + बिटवर्डन, 8 बिट, पासवर्ड, मुफ्त पासवर्ड मैनेजर, पासवर्ड मैनेजर, लॉगइन मैनेजर Max 100 characters - एक सुरक्षित तिजोरी से अपने सभी लॉगिन और पासवर्ड प्रबंधित करें + एक सुरक्षित तिजोरी से अपने सारे लॉगइन और पासवर्ड मैनेज करें - स्वचालित रूप से मजबूत, यादृच्छिक और सुरक्षित पासवर्ड उत्पन्न करते हैं + अपनेआप ताकतवर, बेतरतीब, और महफूज़ पासवर्ड बनाएं - टच आईडी, पिन कोड या मास्टर पासवर्ड से अपनी तिजोरी को सुरक्षित रखें + टच आईडी, पिन कोड, या मुख्य पासवर्ड से अपनी तिजोरी सुरक्षित रखें - सफारी, क्रोम और अन्य सैकड़ों ऐप्स से ऑटो-फिल लॉगिन करें + सफारी, क्रोम, और सैकड़ों दूसरे ऐप से अपनेआप भरकर लॉगइन करें - कई उपकरणों से अपने Vault को सिंक और एक्सेस करें + अपने तिजोरी को अलग-अलग डिवाइसो से सिंक और एक्सेस करें diff --git a/store/apple/sl/copy.resx b/store/apple/sl/copy.resx index b254fa174..59b53710c 100644 --- a/store/apple/sl/copy.resx +++ b/store/apple/sl/copy.resx @@ -122,51 +122,50 @@ Max 30 characters - Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + Bitwarden, Inc. je matično podjetje podjetja 8bit Solutions LLC. -NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. +NAJBOŠJI UPRAVLJALNIK GESEL PO MNEJU THE VERGE, U.S. NEWS & WORLD REPORT, CNET IN DRUGIH. -Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. +Upravljajte, shranjujte, varujte in delite neomejeno število gesel na neomejenem številu naprav, kjerkoli. Bitwarden ponuja odprtokodne rešitve za upravljanje gesel vsem, tako doma kot v službi ali na poti. -Generate strong, unique, and random passwords based on security requirements for every website you frequent. +Za vas ustvari močna, edinstvena in naključna gesla, skladna z varnostnimi zahtevami za vsako spletno mesto, ki ga obiščete. -Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. +S pošiljkami Bitwarden Send hitro prenesite šifrirane informacije --- datoteke in navadno besedilo -- neposredno komurkoli. -Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. +Bitwarden ponuja storitvi za organizacije Teams in Enterprise, s katerima lahko gesla varno souporabljate s sodelavci. -Why Choose Bitwarden: +Zakaj izbrati Bitwarden: -World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +Vrhunsko šifriranje +Gesla so zaščitena z naprednim šifriranjem (AES-256, soljene hash-vrednosti in PBKDF2 SHA-256), tako da vaši podatki ostanejo varni in zasebni. -Built-in Password Generator -Generate strong, unique, and random passwords based on security requirements for every website you frequent. +Vgrajen generator gesel +Ustvarite močna, edinstvena in naključna gesla v skladu z varnostnimi zahtevami za vsako spletno mesto, ki ga obiščete. -Global Translations -Bitwarden translations exist in 40 languages and are growing, thanks to our global community. +Prevodi za ves svet +Bitwarden je preveden že v 40 jezikov, naša globalna skupnost pa ves čas posodabljan in ustvarja nove prevede. -Cross-Platform Applications -Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. - +Deluje na vseh platformah +Varujte in souporabljajte svoje občutljive podatke znotraj vašega Bitwarden trezorja v katerem koli brskalniku, mobilni napravi, namiznem računalniku in drugje. Max 4000 characters - bit warden,8bit,password,free password manager,password manager,login manager + bit warden,8bit,password,free password manager,password manager,login manager,upravljalnik gesel,shranjevalnik gesel,geslo,upravljalnik prijav Max 100 characters - Manage all your logins and passwords from a secure vault + Urejajte vse svoje prijavne podatke in gesla v zavarovanem trezorju - Automatically generate strong, random, and secure passwords + Samodejno ustvari močna, naključna in varna gesla - Protect your vault with Touch ID, PIN code, or master password + Zaščitite svoj trezor s pristnim odtisom, PIN-kodo ali glavnim geslom - Auto-fill logins from Safari, Chrome, and hundreds of other apps + Samodejno izpolnjevanje prijav v aplikacijah Safari, Chrome in stotinah drugih - Sync and access your vault from multiple devices + Sinhronizirajte svoj trezor gesel in dostopajte do njega z več naprav diff --git a/store/google/hi/copy.resx b/store/google/hi/copy.resx index 1d1420e6e..62790245b 100644 --- a/store/google/hi/copy.resx +++ b/store/google/hi/copy.resx @@ -118,61 +118,61 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - bitwarden Password Manager + बिटवार्डन पासवर्ड मैनेजर Max 30 characters - bitwarden is a login and password manager that helps keep you safe while online. + बिटवाडर्न एक लॉगइन और पासवर्ड मैनेजर है जो आपको ऑनलाइन महफूज़ रखता है। Max 80 characters - Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + बिटवार्डन अंतरराष्ट्रीय कॉरपोरेशन, 8बिट सॉल्यूश्नस एलएलसी की मूल कंपनी है। -NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. +द वर्ज, यूएस न्यूज़ एंड वर्ल्ड रिपोर्ट, सीनेट, और कई दूसरे मीडिया संगठन द्वारा बोला गया दुनिया का सबसे बेहतरीन पासवर्ड मैनेजर। -Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. +अनगिनत पासवर्ड मैनेज, स्टोर, महफूज़, और शेयर करें कही से भी। बिटवार्डन देता है ओपन सोर्स पासवर्ड मैनेजमेंट सुविधा सबको, चाहे वो घर पर हो, दफ्तर पर हो, या घूम रहे हो। -Generate strong, unique, and random passwords based on security requirements for every website you frequent. +आप जिन वेबसाइट पर जाते है उनके लिए बनाएं ताकतवर, खास, और बेतरतीब पासवर्ड उनकी सुरक्षा ज़रूरतो के हिसाब से। -Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. +बिटवार्डन सेंड किसी को भी एन्क्रिप्टेड जानकारी, फाइल और सादा टेक्सट, तुरंत भेजें। -Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. +बिटवार्डन कंपनियों के लिए टीम और बिज़नेस प्लान भी देता है ताकि आप अपने साथ काम करनेवालो के साथ पासवर्ड शेयर करे सुरक्षित होकर। -Why Choose Bitwarden: +बिटवार्डन को क्यों चुनें: -World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +ताकतवर एन्क्रिप्शन +पासवर्ड एडवांस एंड-टू-एंड एन्क्रिप्शन (एईएस-256 बिट, सॉल्टेड हैशटैग, और पीबीकेडीएफ2 शा-256) के साथ सुरक्षित रखा जाता है ताकि आपका डाटा महफूज़ और निजी रहे। -Built-in Password Generator -Generate strong, unique, and random passwords based on security requirements for every website you frequent. +पहले से बना पासवर्ड जेनरेटर +आप जिन वेबसाइट पर जाते है उनके लिए बनाएं ताकतवर, खास, और बेतरतीब पासवर्ड उनकी सुरक्षा ज़रूरतो के हिसाब से। -Global Translations -Bitwarden translations exist in 40 languages and are growing, thanks to our global community. +अंतरराष्ट्रीय अनुवाद +40 से ज़्यादा भाषा में बिटवार्डन इस्तेमाल करें, जिसे लिखा है हमारी अंतरराष्ट्रीय दोस्तो ने। -Cross-Platform Applications -Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. +कई प्लेनफॉर्म पर मौजूद +अपने बिटवार्डन तिजोरी से संवेदनशील डाटा महफूज़ और शेयर करें किसी भी ब्राउज़र, फोन, या डेस्कटॉप जैसे डिवाइसो से। Max 4000 characters - आपके सभी उपकरणों के लिए एक सुरक्षित और मुफ्त पासवर्ड प्रबंधक + आपके सारे डिवाइसो के लिए एक सुरक्षित और मुफ्त पासवर्ड मैनेजर - एक सुरक्षित तिजोरी से अपने सभी लॉगिन और पासवर्ड प्रबंधित करें + एक सुरक्षित तिजोरी से अपने सारे लॉगइन और पासवर्ड मैनेज करें - स्वचालित रूप से मजबूत, यादृच्छिक और सुरक्षित पासवर्ड उत्पन्न करते हैं + अपनेआप ताकतवर, बेतरतीब, और महफूज़ पासवर्ड बनाएं - टच आईडी, पिन कोड या मास्टर पासवर्ड से अपनी तिजोरी को सुरक्षित रखें + फिंगरप्रिंट, पिन कोड, या मुख्य पासवर्ड से अपनी तिजोरी सुरक्षित रखें - अपने वेब ब्राउज़र और अन्य एप्लिकेशन के भीतर से जल्दी से लॉगिन करें + अपने वेब ब्राउज़र और दूसरे ऐप से जल्दी लॉगइन करें - कई उपकरणों से अपने वॉल्ट को सिंक और एक्सेस करें + अपने तिजोरी को अलग-अलग डिवाइसों से सिंक और एक्सेस करें -- फ़ोन +- फोन - टैबलेट - डेस्कटॉप - वेब diff --git a/store/google/sl/copy.resx b/store/google/sl/copy.resx index 697db123c..3c10dd542 100644 --- a/store/google/sl/copy.resx +++ b/store/google/sl/copy.resx @@ -118,61 +118,61 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Bitwarden shranjevalnik gesel + Bitwarden - upravitelj gesel Max 30 characters - Bitwarden je shranjevalnik dostopnih podatkov in gesel, ki vam pomaga ostati varen na spletu. + Bitwarden je upravitelj prijavnih podatkov in gesel, ki vam pomaga ohraniti varnost na spletu. Max 80 characters - Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + Bitwarden, Inc. je matično podjetje podjetja 8bit Solutions LLC. -NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. +NAJBOŠJI UPRAVLJALNIK GESEL PO MNEJU THE VERGE, U.S. NEWS & WORLD REPORT, CNET IN DRUGIH. -Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. +Upravljajte, shranjujte, varujte in delite neomejeno število gesel na neomejenem številu naprav, kjerkoli. Bitwarden ponuja odprtokodne rešitve za upravljanje gesel vsem, tako doma kot v službi ali na poti. -Generate strong, unique, and random passwords based on security requirements for every website you frequent. +Za vas ustvari močna, edinstvena in naključna gesla, skladna z varnostnimi zahtevami za vsako spletno mesto, ki ga obiščete. -Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. +S pošiljkami Bitwarden Send hitro prenesite šifrirane informacije --- datoteke in navadno besedilo -- neposredno komurkoli. -Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. +Bitwarden ponuja storitvi za organizacije Teams in Enterprise, s katerima lahko gesla varno souporabljate s sodelavci. -Why Choose Bitwarden: +Zakaj izbrati Bitwarden: -World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +Vrhunsko šifriranje +Gesla so zaščitena z naprednim šifriranjem (AES-256, soljene hash-vrednosti in PBKDF2 SHA-256), tako da vaši podatki ostanejo varni in zasebni. -Built-in Password Generator -Generate strong, unique, and random passwords based on security requirements for every website you frequent. +Vgrajen generator gesel +Ustvarite močna, edinstvena in naključna gesla v skladu z varnostnimi zahtevami za vsako spletno mesto, ki ga obiščete. -Global Translations -Bitwarden translations exist in 40 languages and are growing, thanks to our global community. +Prevodi za ves svet +Bitwarden je preveden že v 40 jezikov, naša globalna skupnost pa ves čas posodabljan in ustvarja nove prevede. -Cross-Platform Applications -Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. - +Deluje na vseh platformah +Varujte in souporabljajte svoje občutljive podatke znotraj vašega Bitwarden trezorja v katerem koli brskalniku, mobilni napravi, namiznem računalniku in drugje. Max 4000 characters - Varen in brezplačen shranjevalnik gesel za vse vaše naprave + Varen in brezplačen upravitelj gesel za vse vaše naprave - Urejate vse svoje dostopne podatke in gesla iz varnega sefa + Urejajte vse svoje prijavne podatke in gesla v zavarovanem trezorju - Samodejni ustvari močna, naključna in varna gesla + Samodejno ustvari močna, naključna in varna gesla - Zaščitite svoj sef s pristnim odtisom, kodo PIN ali glavnim geslom + Zaščitite svoj trezor s pristnim odtisom, PIN-kodo ali glavnim geslom - Hitro vnašanje prijavnih podatkov na spletu in v drugih aplikacijah + Hitro samodejno vnašanje prijavnih podatkov na spletu in v drugih aplikacijah - - Telefon + Dostopajte do svojega sefa z različnih naprav: +- Telefon - Tablica -- Namizje +- Računalnik - Splet diff --git a/test/Common/Common.csproj b/test/Common/Common.csproj index 3912b23c1..bcc5f133d 100644 --- a/test/Common/Common.csproj +++ b/test/Common/Common.csproj @@ -7,15 +7,15 @@ - - + + all runtime; build; native; contentfiles; analyzers - - - + + + diff --git a/test/Core.Test/Core.Test.csproj b/test/Core.Test/Core.Test.csproj index e1e4b96f0..df9d8d74b 100644 --- a/test/Core.Test/Core.Test.csproj +++ b/test/Core.Test/Core.Test.csproj @@ -7,15 +7,15 @@ - - - + + + all runtime; build; native; contentfiles; analyzers - - + + diff --git a/test/Core.Test/Models/Request/SendRequestTests.cs b/test/Core.Test/Models/Request/SendRequestTests.cs index 028dce25a..49c60bed4 100644 --- a/test/Core.Test/Models/Request/SendRequestTests.cs +++ b/test/Core.Test/Models/Request/SendRequestTests.cs @@ -14,7 +14,7 @@ namespace Bit.Core.Test.Models.Request { [Theory] [InlineCustomAutoData(new[] { typeof(TextSendCustomization) }, null)] - [InlineCustomAutoData(new[] { typeof(FileSendCustomization) }, 100)] + [InlineCustomAutoData(new[] { typeof(FileSendCustomization) }, 100L)] public void SendRequest_FromSend_Success(long? fileLength, Send send) { var request = new SendRequest(send, fileLength);