1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-05 23:53:33 +00:00

Compare commits

..

3 Commits

Author SHA1 Message Date
Andre Rosado
ef62bd4199 Reverted AnonAddy to AddyIo refactor, keeping text and url changes 2023-09-05 17:41:11 +01:00
Will Browning
9c633dc720 Update AnonAddy references 2023-08-21 14:38:12 +01:00
Will Browning
2e8948cb79 Update AppResources.af.resx 2023-08-21 14:11:08 +01:00
76 changed files with 8764 additions and 8072 deletions

View File

@@ -525,7 +525,7 @@ jobs:
submodules: 'true'
- name: Login to Azure - CI Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.6
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
@@ -667,22 +667,6 @@ jobs:
$configuration = "AppStore";
$platform = "iPhone";
Write-Output "########################################"
Write-Output "##### Archive $configuration Configuration for $platform Platform"
Write-Output "########################################"
msbuild "$($env:GITHUB_WORKSPACE + "/src/iOS/iOS.csproj")" "/p:Platform=$platform" `
"/p:Configuration=$configuration" "/p:ArchiveOnBuild=true" "/t:`"Build`""
Write-Output "########################################"
Write-Output "##### Done"
Write-Output "########################################"
shell: pwsh
- name: Archive Build for Mobile Automation
run: |
$configuration = "Release";
$platform = "iPhoneSimulator";
Write-Output "########################################"
Write-Output "##### Archive $configuration Configuration for $platform Platform"
Write-Output "########################################"
@@ -705,15 +689,6 @@ jobs:
-exportOptionsPlist $EXPORT_OPTIONS_PATH
shell: bash
- name: Export .app for Automation CI
run: |
ARCHIVE_PATH="./src/iOS/bin/iPhoneSimulator/Release/BitwardeniOS.app"
EXPORT_PATH="./bitwarden-export"
zip -r -q BitwardeniOS.app.zip $ARCHIVE_PATH
mv BitwardeniOS.app.zip $EXPORT_PATH
shell: bash
- name: Copy all dSYMs files to upload
run: |
ARCHIVE_DSYMS_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive/dSYMs"
@@ -736,13 +711,6 @@ jobs:
./bitwarden-export/dSYMs/*.*
if-no-files-found: error
- name: Upload .app file for Automation CI
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
with:
name: BitwardeniOS.app.zip
path: ./bitwarden-export/BitwardeniOS.app.zip
if-no-files-found: error
- name: Install AppCenter CLI
if: |
(github.ref == 'refs/heads/master'
@@ -811,7 +779,7 @@ jobs:
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Login to Azure - CI Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.6
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
@@ -877,7 +845,7 @@ jobs:
fi
- name: Login to Azure - CI Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.6
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
if: failure()
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}

View File

@@ -18,13 +18,13 @@ jobs:
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Login to Azure - CI Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.6
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@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
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"

View File

@@ -12,6 +12,6 @@ jobs:
pull-requests: write
runs-on: ubuntu-20.04
steps:
- uses: actions/labeler@ac9175f8a1f3625fd0d4fb234536d26811351594 # v4.3.0
- uses: actions/labeler@ba790c862c380240c6d5e7427be5ace9a05c754b # v4.0.3
with:
sync-labels: true

View File

@@ -38,11 +38,11 @@ jobs:
fi
- name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Check Release Version
id: version
uses: bitwarden/gh-actions/release-version-check@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
uses: bitwarden/gh-actions/release-version-check@34ecb67b2a357795dc893549df0795e7383ff50f
with:
release-type: ${{ github.event.inputs.release_type }}
project-type: xamarin
@@ -87,7 +87,7 @@ jobs:
- name: Create release
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@6c75be85e571768fa31b40abf38de58ba0397db5 # v1.13.0
uses: ncipollo/release-action@40bb172bd05f266cf9ba4ff965cb61e9ee5f6d01 # v1.9.0
with:
artifacts: "./com.x8bit.bitwarden.aab/com.x8bit.bitwarden.aab,
./com.x8bit.bitwarden.apk/com.x8bit.bitwarden.apk,
@@ -126,7 +126,7 @@ jobs:
if: inputs.fdroid_publish
steps:
- name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Download F-Droid .apk artifact
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
@@ -147,9 +147,9 @@ jobs:
name: com.x8bit.bitwarden-fdroid.apk
- name: Set up Node
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561 # v2.5.1
with:
node-version: '16.x'
node-version: '10.x'
- name: Set up F-Droid server
run: |

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: 'Run stale action'
uses: actions/stale@f7176fd3007623b69d27091f9b9d4ab7995f0a06 # v5.2.1
uses: actions/stale@3cc123766321e9f15a6676375c154ccffb12a358 # v5.0.0
with:
stale-issue-label: 'needs-reply'
stale-pr-label: 'needs-changes'

View File

@@ -14,7 +14,7 @@ jobs:
version_number: ${{ steps.version.outputs.new-version }}
steps:
- name: Checkout Branch
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Calculate bumped version
id: version
@@ -35,5 +35,7 @@ jobs:
name: Bump version to ${{ needs.setup.outputs.version_number }}
needs: setup
uses: ./.github/workflows/version-bump.yml
secrets:
AZURE_PROD_KV_CREDENTIALS: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
with:
version_number: ${{ needs.setup.outputs.version_number }}

View File

@@ -12,6 +12,9 @@ on:
version_number:
required: true
type: string
secrets:
AZURE_PROD_KV_CREDENTIALS:
required: true
jobs:
bump_version:
@@ -19,22 +22,22 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout Branch
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
- name: Login to Azure - CI Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7
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@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
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@d6f3f49f3345e29369fe57596a3ca8f94c4d2ca7 # v5.4.0
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 }}
@@ -45,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@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
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@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
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@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
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@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
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@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
uses: bitwarden/gh-actions/version-bump@34ecb67b2a357795dc893549df0795e7383ff50f
with:
version: ${{ github.event.inputs.version_number }}
file_path: "./src/iOS/Info.plist"

View File

@@ -8,4 +8,4 @@ on:
jobs:
call-workflow:
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@34ecb67b2a357795dc893549df0795e7383ff50f

View File

@@ -159,7 +159,7 @@ namespace Bit.Droid
var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService);
var cryptoService = new CryptoService(stateService, cryptoFunctionService);
var biometricService = new BiometricService(stateService, cryptoService);
var passwordRepromptService = new MobilePasswordRepromptService(platformUtilsService, cryptoService, stateService);
var passwordRepromptService = new MobilePasswordRepromptService(platformUtilsService, cryptoService);
ServiceContainer.Register<ISynchronousStorageService>(preferencesStorage);
ServiceContainer.Register<IBroadcasterService>("broadcasterService", broadcasterService);

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2023.9.1" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2023.7.1" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" />

View File

@@ -7,7 +7,6 @@ using Bit.App.Utilities;
using Bit.Core;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Models.Domain;
using Bit.Core.Models.Request;
using Bit.Core.Services;
@@ -73,12 +72,11 @@ namespace Bit.App.Pages
TogglePasswordCommand = new Command(TogglePassword);
SubmitCommand = new Command(async () => await SubmitAsync());
AccountSwitchingOverlayViewModel =
new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger)
{
AllowAddAccountRow = true,
AllowActiveAccountSelection = true
};
AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger)
{
AllowAddAccountRow = true,
AllowActiveAccountSelection = true
};
}
public string MasterPassword
@@ -157,12 +155,8 @@ namespace Bit.App.Pages
public Command SubmitCommand { get; }
public Command TogglePasswordCommand { get; }
public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
public string PasswordVisibilityAccessibilityText => ShowPassword
? AppResources.PasswordIsVisibleTapToHide
: AppResources.PasswordIsNotVisibleTapToShow;
public string PasswordVisibilityAccessibilityText => ShowPassword ? AppResources.PasswordIsVisibleTapToHide : AppResources.PasswordIsNotVisibleTapToShow;
public Action UnlockedAction { get; set; }
public event Action<int?> FocusSecretEntry
{
@@ -184,9 +178,8 @@ namespace Bit.App.Pages
var ephemeralPinSet = await _stateService.GetPinKeyEncryptedUserKeyEphemeralAsync()
?? await _stateService.GetPinProtectedKeyAsync();
PinEnabled = (_pinStatus == PinLockType.Transient && ephemeralPinSet != null) ||
_pinStatus == PinLockType.Persistent;
BiometricEnabled = await IsBiometricsEnabledAsync();
_pinStatus == PinLockType.Persistent;
BiometricEnabled = await _vaultTimeoutService.IsBiometricLockSetAsync() && await _biometricService.CanUseBiometricsUnlockAsync();
// Users without MP and without biometric or pin has no MP to unlock with
_hasMasterPassword = await _userVerificationService.HasMasterPasswordAsync();
@@ -221,9 +214,7 @@ namespace Bit.App.Pages
else
{
PageTitle = _hasMasterPassword ? AppResources.VerifyMasterPassword : AppResources.UnlockVault;
LockedVerifyText = _hasMasterPassword
? AppResources.VaultLockedMasterPassword
: AppResources.VaultLockedIdentity;
LockedVerifyText = _hasMasterPassword ? AppResources.VaultLockedMasterPassword : AppResources.VaultLockedIdentity;
}
if (BiometricEnabled)
@@ -242,32 +233,11 @@ namespace Bit.App.Pages
BiometricButtonText = supportsFace ? AppResources.UseFaceIDToUnlock :
AppResources.UseFingerprintToUnlock;
}
}
}
public async Task SubmitAsync()
{
ShowPassword = false;
try
{
var kdfConfig = await _stateService.GetActiveUserCustomDataAsync(a => new KdfConfig(a?.Profile));
if (PinEnabled)
{
await UnlockWithPinAsync(kdfConfig);
}
else
{
await UnlockWithMasterPasswordAsync(kdfConfig);
}
}
catch (LegacyUserException)
{
await HandleLegacyUserAsync();
}
}
private async Task UnlockWithPinAsync(KdfConfig kdfConfig)
{
if (PinEnabled && string.IsNullOrWhiteSpace(Pin))
{
@@ -276,84 +246,6 @@ namespace Bit.App.Pages
AppResources.Ok);
return;
}
var failed = true;
try
{
EncString userKeyPin;
EncString oldPinProtected;
switch (_pinStatus)
{
case PinLockType.Persistent:
{
userKeyPin = await _stateService.GetPinKeyEncryptedUserKeyAsync();
var oldEncryptedKey = await _stateService.GetPinProtectedAsync();
oldPinProtected = oldEncryptedKey != null ? new EncString(oldEncryptedKey) : null;
break;
}
case PinLockType.Transient:
userKeyPin = await _stateService.GetPinKeyEncryptedUserKeyEphemeralAsync();
oldPinProtected = await _stateService.GetPinProtectedKeyAsync();
break;
case PinLockType.Disabled:
default:
throw new Exception("Pin is disabled");
}
UserKey userKey;
if (oldPinProtected != null)
{
userKey = await _cryptoService.DecryptAndMigrateOldPinKeyAsync(
_pinStatus == PinLockType.Transient,
Pin,
_email,
kdfConfig,
oldPinProtected
);
}
else
{
userKey = await _cryptoService.DecryptUserKeyWithPinAsync(
Pin,
_email,
kdfConfig,
userKeyPin
);
}
var protectedPin = await _stateService.GetProtectedPinAsync();
var decryptedPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), userKey);
failed = decryptedPin != Pin;
if (!failed)
{
Pin = string.Empty;
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
await SetUserKeyAndContinueAsync(userKey);
}
}
catch (LegacyUserException)
{
throw;
}
catch
{
failed = true;
}
if (failed)
{
var invalidUnlockAttempts = await AppHelpers.IncrementInvalidUnlockAttemptsAsync();
if (invalidUnlockAttempts >= 5)
{
_messagingService.Send("logout");
return;
}
await _platformUtilsService.ShowDialogAsync(AppResources.InvalidPIN,
AppResources.AnErrorHasOccurred);
}
}
private async Task UnlockWithMasterPasswordAsync(KdfConfig kdfConfig)
{
if (!PinEnabled && string.IsNullOrWhiteSpace(MasterPassword))
{
await Page.DisplayAlert(AppResources.AnErrorHasOccurred,
@@ -362,78 +254,142 @@ namespace Bit.App.Pages
return;
}
var masterKey = await _cryptoService.MakeMasterKeyAsync(MasterPassword, _email, kdfConfig);
if (await _cryptoService.IsLegacyUserAsync(masterKey))
{
throw new LegacyUserException();
}
ShowPassword = false;
var kdfConfig = await _stateService.GetActiveUserCustomDataAsync(a => new KdfConfig(a?.Profile));
var storedKeyHash = await _cryptoService.GetMasterKeyHashAsync();
var passwordValid = false;
MasterPasswordPolicyOptions enforcedMasterPasswordOptions = null;
if (storedKeyHash != null)
if (PinEnabled)
{
// Offline unlock possible
passwordValid = await _cryptoService.CompareAndUpdateKeyHashAsync(MasterPassword, masterKey);
}
else
{
// Online unlock required
await _deviceActionService.ShowLoadingAsync(AppResources.Loading);
var keyHash = await _cryptoService.HashMasterKeyAsync(MasterPassword, masterKey,
HashPurpose.ServerAuthorization);
var request = new PasswordVerificationRequest();
request.MasterPasswordHash = keyHash;
var failed = true;
try
{
var response = await _apiService.PostAccountVerifyPasswordAsync(request);
enforcedMasterPasswordOptions = response.MasterPasswordPolicy;
passwordValid = true;
var localKeyHash = await _cryptoService.HashMasterKeyAsync(MasterPassword, masterKey,
HashPurpose.LocalAuthorization);
await _cryptoService.SetMasterKeyHashAsync(localKeyHash);
EncString userKeyPin = null;
EncString oldPinProtected = null;
if (_pinStatus == PinLockType.Persistent)
{
userKeyPin = await _stateService.GetPinKeyEncryptedUserKeyAsync();
var oldEncryptedKey = await _stateService.GetPinProtectedAsync();
oldPinProtected = oldEncryptedKey != null ? new EncString(oldEncryptedKey) : null;
}
else if (_pinStatus == PinLockType.Transient)
{
userKeyPin = await _stateService.GetPinKeyEncryptedUserKeyEphemeralAsync();
oldPinProtected = await _stateService.GetPinProtectedKeyAsync();
}
UserKey userKey;
if (oldPinProtected != null)
{
userKey = await _cryptoService.DecryptAndMigrateOldPinKeyAsync(
_pinStatus == PinLockType.Transient,
Pin,
_email,
kdfConfig,
oldPinProtected
);
}
else
{
userKey = await _cryptoService.DecryptUserKeyWithPinAsync(
Pin,
_email,
kdfConfig,
userKeyPin
);
}
var protectedPin = await _stateService.GetProtectedPinAsync();
var decryptedPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), userKey);
failed = decryptedPin != Pin;
if (!failed)
{
Pin = string.Empty;
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
await SetUserKeyAndContinueAsync(userKey);
}
}
catch (Exception e)
catch
{
System.Diagnostics.Debug.WriteLine(">>> {0}: {1}", e.GetType(), e.StackTrace);
failed = true;
}
await _deviceActionService.HideLoadingAsync();
}
if (passwordValid)
{
if (await RequirePasswordChangeAsync(enforcedMasterPasswordOptions))
if (failed)
{
// Save the ForcePasswordResetReason to force a password reset after unlock
await _stateService.SetForcePasswordResetReasonAsync(
ForcePasswordResetReason.WeakMasterPasswordOnLogin);
}
MasterPassword = string.Empty;
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
var userKey = await _cryptoService.DecryptUserKeyWithMasterKeyAsync(masterKey);
await _cryptoService.SetMasterKeyAsync(masterKey);
await SetUserKeyAndContinueAsync(userKey);
// Re-enable biometrics
if (BiometricEnabled & !BiometricIntegrityValid)
{
await _biometricService.SetupBiometricAsync();
var invalidUnlockAttempts = await AppHelpers.IncrementInvalidUnlockAttemptsAsync();
if (invalidUnlockAttempts >= 5)
{
_messagingService.Send("logout");
return;
}
await _platformUtilsService.ShowDialogAsync(AppResources.InvalidPIN,
AppResources.AnErrorHasOccurred);
}
}
else
{
var invalidUnlockAttempts = await AppHelpers.IncrementInvalidUnlockAttemptsAsync();
if (invalidUnlockAttempts >= 5)
var masterKey = await _cryptoService.MakeMasterKeyAsync(MasterPassword, _email, kdfConfig);
var storedKeyHash = await _cryptoService.GetMasterKeyHashAsync();
var passwordValid = false;
MasterPasswordPolicyOptions enforcedMasterPasswordOptions = null;
if (storedKeyHash != null)
{
_messagingService.Send("logout");
return;
// Offline unlock possible
passwordValid = await _cryptoService.CompareAndUpdateKeyHashAsync(MasterPassword, masterKey);
}
else
{
// Online unlock required
await _deviceActionService.ShowLoadingAsync(AppResources.Loading);
var keyHash = await _cryptoService.HashMasterKeyAsync(MasterPassword, masterKey, HashPurpose.ServerAuthorization);
var request = new PasswordVerificationRequest();
request.MasterPasswordHash = keyHash;
try
{
var response = await _apiService.PostAccountVerifyPasswordAsync(request);
enforcedMasterPasswordOptions = response.MasterPasswordPolicy;
passwordValid = true;
var localKeyHash = await _cryptoService.HashMasterKeyAsync(MasterPassword, masterKey, HashPurpose.LocalAuthorization);
await _cryptoService.SetMasterKeyHashAsync(localKeyHash);
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(">>> {0}: {1}", e.GetType(), e.StackTrace);
}
await _deviceActionService.HideLoadingAsync();
}
if (passwordValid)
{
if (await RequirePasswordChangeAsync(enforcedMasterPasswordOptions))
{
// Save the ForcePasswordResetReason to force a password reset after unlock
await _stateService.SetForcePasswordResetReasonAsync(
ForcePasswordResetReason.WeakMasterPasswordOnLogin);
}
MasterPassword = string.Empty;
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
var userKey = await _cryptoService.DecryptUserKeyWithMasterKeyAsync(masterKey);
await _cryptoService.SetMasterKeyAsync(masterKey);
await SetUserKeyAndContinueAsync(userKey);
// Re-enable biometrics
if (BiometricEnabled & !BiometricIntegrityValid)
{
await _biometricService.SetupBiometricAsync();
}
}
else
{
var invalidUnlockAttempts = await AppHelpers.IncrementInvalidUnlockAttemptsAsync();
if (invalidUnlockAttempts >= 5)
{
_messagingService.Send("logout");
return;
}
await _platformUtilsService.ShowDialogAsync(AppResources.InvalidMasterPassword,
AppResources.AnErrorHasOccurred);
}
await _platformUtilsService.ShowDialogAsync(AppResources.InvalidMasterPassword,
AppResources.AnErrorHasOccurred);
}
}
@@ -496,34 +452,25 @@ namespace Bit.App.Pages
{
ShowPassword = !ShowPassword;
var secret = PinEnabled ? Pin : MasterPassword;
_secretEntryFocusWeakEventManager.RaiseEvent(string.IsNullOrEmpty(secret) ? 0 : secret.Length,
nameof(FocusSecretEntry));
_secretEntryFocusWeakEventManager.RaiseEvent(string.IsNullOrEmpty(secret) ? 0 : secret.Length, nameof(FocusSecretEntry));
}
public async Task PromptBiometricAsync()
{
try
BiometricIntegrityValid = await _platformUtilsService.IsBiometricIntegrityValidAsync();
BiometricButtonVisible = BiometricIntegrityValid;
if (!BiometricEnabled || !BiometricIntegrityValid)
{
BiometricIntegrityValid = await _platformUtilsService.IsBiometricIntegrityValidAsync();
BiometricButtonVisible = BiometricIntegrityValid;
if (!BiometricEnabled || !BiometricIntegrityValid)
{
return;
}
var success = await _platformUtilsService.AuthenticateBiometricAsync(null,
PinEnabled ? AppResources.PIN : AppResources.MasterPassword,
() => _secretEntryFocusWeakEventManager.RaiseEvent((int?)null, nameof(FocusSecretEntry)));
await _stateService.SetBiometricLockedAsync(!success);
if (success)
{
var userKey = await _cryptoService.GetBiometricUnlockKeyAsync();
await SetUserKeyAndContinueAsync(userKey);
}
return;
}
catch (LegacyUserException)
var success = await _platformUtilsService.AuthenticateBiometricAsync(null,
PinEnabled ? AppResources.PIN : AppResources.MasterPassword,
() => _secretEntryFocusWeakEventManager.RaiseEvent((int?)null, nameof(FocusSecretEntry)));
await _stateService.SetBiometricLockedAsync(!success);
if (success)
{
await HandleLegacyUserAsync();
var userKey = await _cryptoService.GetBiometricUnlockKeyAsync();
await SetUserKeyAndContinueAsync(userKey);
}
}
@@ -546,29 +493,5 @@ namespace Bit.App.Pages
_messagingService.Send("unlocked");
UnlockedAction?.Invoke();
}
private async Task<bool> IsBiometricsEnabledAsync()
{
try
{
return await _vaultTimeoutService.IsBiometricLockSetAsync() &&
await _biometricService.CanUseBiometricsUnlockAsync();
}
catch (LegacyUserException)
{
await HandleLegacyUserAsync();
}
return false;
}
private async Task HandleLegacyUserAsync()
{
// Legacy users must migrate on web vault.
await _platformUtilsService.ShowDialogAsync(AppResources.EncryptionKeyMigrationRequiredDescriptionLong,
AppResources.AnErrorHasOccurred,
AppResources.Ok);
await _vaultTimeoutService.LogOutAsync();
}
}
}

View File

@@ -248,14 +248,6 @@ namespace Bit.App.Pages
await _deviceActionService.HideLoadingAsync();
if (response.RequiresEncryptionKeyMigration)
{
// Legacy users must migrate on web vault.
await _platformUtilsService.ShowDialogAsync(AppResources.EncryptionKeyMigrationRequiredDescriptionLong, AppResources.AnErrorHasOccurred,
AppResources.Ok);
return;
}
if (response.TwoFactor)
{
StartTwoFactorAction?.Invoke();

View File

@@ -34,7 +34,6 @@ namespace Bit.App.Pages
private readonly ICryptoService _cryptoService;
private string _orgIdentifier;
private bool _useEphemeralWebBrowserSession;
public LoginSsoPageViewModel()
{
@@ -146,12 +145,9 @@ namespace Bit.App.Pages
"ssoToken=" + Uri.EscapeDataString(ssoToken);
WebAuthenticatorResult authResult = null;
authResult = await WebAuthenticator.AuthenticateAsync(new WebAuthenticatorOptions()
{
CallbackUrl = new Uri(REDIRECT_URI),
Url = new Uri(url),
PrefersEphemeralWebBrowserSession = _useEphemeralWebBrowserSession,
});
authResult = await WebAuthenticator.AuthenticateAsync(new Uri(url),
new Uri(REDIRECT_URI));
var code = GetResultCode(authResult, state);
if (!string.IsNullOrEmpty(code))
@@ -176,8 +172,6 @@ namespace Bit.App.Pages
{
// user canceled
await _deviceActionService.HideLoadingAsync();
// Workaroung for cached expired sso token PM-3551
_useEphemeralWebBrowserSession = true;
}
catch (Exception ex)
{

View File

@@ -51,8 +51,7 @@
<Label
Text="{u:I18n ResetPasswordAutoEnrollInviteWarning}"
StyleClass="text-muted, text-sm, text-bold"
HorizontalTextAlignment="Start"
AutomationId="ResetPasswordAutoEnrollInviteWarningLabel" />
HorizontalTextAlignment="Start" />
</Frame>
</Grid>
<Grid IsVisible="{Binding IsPolicyInEffect}"
@@ -74,8 +73,7 @@
<Label
Text="{Binding PolicySummary}"
StyleClass="text-muted, text-sm, text-bold"
HorizontalTextAlignment="Start"
AutomationId="PolicyInEffectLabel" />
HorizontalTextAlignment="Start" />
</Frame>
</Grid>
<Grid StyleClass="box-row">
@@ -100,8 +98,7 @@
IsTextPredictionEnabled="False"
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
Grid.Row="1"
Grid.Column="0"
AutomationId="MasterPasswordField" />
Grid.Column="0" />
<controls:IconButton
StyleClass="box-row-button, box-row-button-platform"
Text="{Binding ShowPasswordIcon}"
@@ -111,8 +108,7 @@
Grid.RowSpan="2"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n ToggleVisibility}"
AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}"
AutomationId="ToggleMasterPasswordVisibilityButton" />
AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}" />
</Grid>
<Label
Text="{u:I18n MasterPasswordDescription}"
@@ -141,8 +137,7 @@
IsTextPredictionEnabled="False"
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
Grid.Row="1"
Grid.Column="0"
AutomationId="RetypePasswordField" />
Grid.Column="0" />
<controls:IconButton
StyleClass="box-row-button, box-row-button-platform"
Text="{Binding ShowPasswordIcon}"
@@ -152,8 +147,7 @@
Grid.RowSpan="2"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n ToggleVisibility}"
AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}"
AutomationId="ToggleRetypePasswordVisibilityButton" />
AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}" />
</Grid>
<StackLayout StyleClass="box-row">
<Label
@@ -164,8 +158,7 @@
Text="{Binding Hint}"
StyleClass="box-value"
ReturnType="Go"
ReturnCommand="{Binding SubmitCommand}"
AutomationId="MasterPasswordHintLabel" />
ReturnCommand="{Binding SubmitCommand}" />
</StackLayout>
<Label
Text="{u:I18n MasterPasswordHintDescription}"

View File

@@ -466,8 +466,7 @@ namespace Bit.App.Pages
{
Email = _authService.Email,
MasterPasswordHash = _authService.MasterPasswordHash,
DeviceIdentifier = await _appIdService.GetAppIdAsync(),
SsoEmail2FaSessionToken = _authService.SsoEmail2FaSessionToken
DeviceIdentifier = await _appIdService.GetAppIdAsync()
};
await _apiService.PostTwoFactorEmailAsync(request);
if (showLoading)

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8" ?>
<pages:BaseContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
@@ -48,8 +48,7 @@
<Label
Text="{Binding UpdateMasterPasswordWarningText }"
StyleClass="text-muted, text-sm, text-bold"
HorizontalTextAlignment="Center"
AutomationId="UpdatePasswordWarningLabel" />
HorizontalTextAlignment="Center" />
</Frame>
</Grid>
<Grid IsVisible="{Binding IsPolicyInEffect}"
@@ -72,8 +71,7 @@
<Label
Text="{Binding PolicySummary}"
StyleClass="text-muted, text-sm, text-bold"
HorizontalTextAlignment="Start"
AutomationId="PolicySummaryLabel" />
HorizontalTextAlignment="Start" />
</Frame>
</Grid>
<Grid StyleClass="box-row" IsVisible="{Binding RequireCurrentPassword }">
@@ -98,8 +96,7 @@
IsTextPredictionEnabled="False"
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
Grid.Row="1"
Grid.Column="0"
AutomationId="MasterPasswordField" />
Grid.Column="0" />
<controls:IconButton
StyleClass="box-row-button, box-row-button-platform"
Text="{Binding ShowPasswordIcon}"
@@ -109,8 +106,7 @@
Grid.RowSpan="2"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n ToggleVisibility}"
AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}"
AutomationId="ToggleMasterPasswordVisibilityButton" />
AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}" />
</Grid>
<Grid StyleClass="box-row">
<Grid.RowDefinitions>
@@ -134,8 +130,7 @@
IsTextPredictionEnabled="False"
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
Grid.Row="1"
Grid.Column="0"
AutomationId="NewPasswordField" />
Grid.Column="0" />
<controls:IconButton
StyleClass="box-row-button, box-row-button-platform"
Text="{Binding ShowPasswordIcon}"
@@ -145,8 +140,7 @@
Grid.RowSpan="2"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n ToggleVisibility}"
AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}"
AutomationId="NewPasswordVisibilityButton" />
AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}" />
</Grid>
</StackLayout>
<StackLayout StyleClass="box">
@@ -172,8 +166,7 @@
IsTextPredictionEnabled="False"
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
Grid.Row="1"
Grid.Column="0"
AutomationId="RetypePasswordField" />
Grid.Column="0" />
<controls:IconButton
StyleClass="box-row-button, box-row-button-platform"
Text="{Binding ShowPasswordIcon}"
@@ -183,8 +176,7 @@
Grid.RowSpan="2"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n ToggleVisibility}"
AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}"
AutomationId="ToggleRetypePasswordVisibilityButton" />
AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}" />
</Grid>
<StackLayout StyleClass="box-row">
<Label
@@ -195,8 +187,7 @@
Text="{Binding Hint}"
StyleClass="box-value"
ReturnType="Go"
ReturnCommand="{Binding SubmitCommand}"
AutomationId="MasterPasswordHintLabel" />
ReturnCommand="{Binding SubmitCommand}" />
</StackLayout>
<Label
Text="{u:I18n MasterPasswordHintDescription}"

View File

@@ -150,12 +150,6 @@ namespace Bit.App.Pages
private async Task SaveActivityAsync()
{
SetServices();
if (await _stateService.GetActiveUserIdAsync() == null)
{
// Fresh install and/or all users logged out won't have an active user, skip saving last active time
return;
}
await _stateService.SetLastActiveTimeAsync(_deviceActionService.GetActiveTime());
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -125,14 +125,14 @@
<comment>Add/create a new entity (verb).</comment>
</data>
<data name="AddFolder" xml:space="preserve">
<value>إضافة مجلّد</value>
<value>مجلد مضاف</value>
</data>
<data name="AddItem" xml:space="preserve">
<value>إضافة عنصر</value>
<value>تمت إضافة العنصر</value>
<comment>The title for the add item page.</comment>
</data>
<data name="AnErrorHasOccurred" xml:space="preserve">
<value>لقد حدث خطأ.</value>
<value>كان هناك خطأ.</value>
<comment>Alert title when something goes wrong.</comment>
</data>
<data name="Back" xml:space="preserve">
@@ -140,7 +140,7 @@
<comment>Navigate back to the previous screen.</comment>
</data>
<data name="Bitwarden" xml:space="preserve">
<value>Bitwarden</value>
<value>bitwarden</value>
<comment>App name. Shouldn't ever change.</comment>
</data>
<data name="Cancel" xml:space="preserve">
@@ -156,11 +156,11 @@
<comment>The button text that allows a user to copy the login's password to their clipboard.</comment>
</data>
<data name="CopyUsername" xml:space="preserve">
<value>انسخ اسم المستخدم</value>
<value>المصادقة باستخدام FIDO2 WebAuthn، يمكنك المصادقة باستخدام مفتاح أمان خارجي.</value>
<comment>The button text that allows a user to copy the login's username to their clipboard.</comment>
</data>
<data name="Credits" xml:space="preserve">
<value>شكر وتقدير</value>
<value>شكر</value>
<comment>Title for page that we use to give credit to resources that we use.</comment>
</data>
<data name="Delete" xml:space="preserve">
@@ -168,42 +168,42 @@
<comment>Delete an entity (verb).</comment>
</data>
<data name="Deleting" xml:space="preserve">
<value>جارِ الحذف...</value>
<value>حذف ...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="DoYouReallyWantToDelete" xml:space="preserve">
<value>هل تريد حقا أن تحذف؟ هذا لا يمكن التراجع عنها.</value>
<value>هل أنت متأكد من أنك تريد الحذف؟ لا يمكن إلغاؤه</value>
<comment>Confirmation alert message when deleteing something.</comment>
</data>
<data name="Edit" xml:space="preserve">
<value>تعديل</value>
</data>
<data name="EditFolder" xml:space="preserve">
<value>تحرير المجلد</value>
<value>تعديل مجلد</value>
</data>
<data name="Email" xml:space="preserve">
<value>بريد الكتروني</value>
<comment>Short label for an email address.</comment>
</data>
<data name="EmailAddress" xml:space="preserve">
<value>عنوان البريد الإلكتروني</value>
<value>عنوان بريد الكتروني</value>
<comment>Full label for a email address.</comment>
</data>
<data name="EmailUs" xml:space="preserve">
<value>راسلنا عبر البريد الإلكتروني</value>
<value>اكتب إلينا</value>
</data>
<data name="EmailUsDescription" xml:space="preserve">
<value>أرسل لنا رسالة مباشرة للحصول على المساعدة أو ترك ملاحظات.</value>
<value>اتصل بنا مباشرة للحصول على المساعدة أو التعليق.</value>
</data>
<data name="EnterPIN" xml:space="preserve">
<value>أدخل رَقم تعريفك الشخصي.</value>
<value>أدخل رقم التعريف الشخصي الخاص بك.</value>
</data>
<data name="Favorites" xml:space="preserve">
<value>المفضلات</value>
<comment>Title for your favorite items in the vault.</comment>
</data>
<data name="FileBugReport" xml:space="preserve">
<value>إرسال تقرير عن خطأ</value>
<value>إرسال تقرير خطأ</value>
</data>
<data name="FileBugReportDescription" xml:space="preserve">
<value>افتح تذكرة في مستودع Github لدينا.</value>
@@ -212,42 +212,42 @@
<value>استخدم بصمة إصبعك للتعريف بنفسك.</value>
</data>
<data name="Folder" xml:space="preserve">
<value>المجلد</value>
<value>مجلد</value>
<comment>Label for a folder.</comment>
</data>
<data name="FolderCreated" xml:space="preserve">
<value>نشأ مجلد جديد.</value>
<value>مجلد جديد أنشئ</value>
</data>
<data name="FolderDeleted" xml:space="preserve">
<value>حذفت المجلد.</value>
<value>مجلد محذوف</value>
</data>
<data name="FolderNone" xml:space="preserve">
<value>لا مجلد</value>
<comment>Items that have no folder specified go in this special "catch-all" folder.</comment>
</data>
<data name="Folders" xml:space="preserve">
<value>المجلدات</value>
<value>مجلدات</value>
</data>
<data name="FolderUpdated" xml:space="preserve">
<value>حُفظ المجلد</value>
<value>مجلد محدّث</value>
</data>
<data name="GoToWebsite" xml:space="preserve">
<value>الذهاب إلى الموقع الالكتروني</value>
<value>زر الموقع الالكتروني</value>
<comment>The button text that allows user to launch the website to their web browser.</comment>
</data>
<data name="HelpAndFeedback" xml:space="preserve">
<value>المساعدة و الملاحظات</value>
<value>مساعدة ورجوع</value>
</data>
<data name="Hide" xml:space="preserve">
<value>إخفاء</value>
<comment>Hide a secret value that is currently shown (password).</comment>
</data>
<data name="InternetConnectionRequiredMessage" xml:space="preserve">
<value>عليك الاتصال بالإنترنت قبل المواصلة.</value>
<value>عليك الاتصال بالانترنت قبل المواصلة</value>
<comment>Description message for the alert when internet connection is required to continue.</comment>
</data>
<data name="InternetConnectionRequiredTitle" xml:space="preserve">
<value>الاتصال بالإنترنت مطلوب</value>
<value>اتصال بالانترنت مطلوب</value>
<comment>Title for the alert when internet connection is required to continue.</comment>
</data>
<data name="InvalidMasterPassword" xml:space="preserve">
@@ -261,11 +261,11 @@
<comment>The button text that allows user to launch the website to their web browser.</comment>
</data>
<data name="LogIn" xml:space="preserve">
<value>تسجيل الدخول</value>
<value>تعريف</value>
<comment>The login button text (verb).</comment>
</data>
<data name="LogInNoun" xml:space="preserve">
<value>تسجيل الدخول</value>
<value>اسم المستخدم</value>
<comment>Title for login page. (noun)</comment>
</data>
<data name="LogOut" xml:space="preserve">
@@ -330,11 +330,11 @@
<value>نقل</value>
</data>
<data name="Saving" xml:space="preserve">
<value>جارِ حفظ...</value>
<value>حفظ...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="Settings" xml:space="preserve">
<value>الإعدادات</value>
<value>إعدادات</value>
<comment>The title for the settings page.</comment>
</data>
<data name="Show" xml:space="preserve">
@@ -360,7 +360,7 @@
<comment>The title for the tools page.</comment>
</data>
<data name="URI" xml:space="preserve">
<value>عنوان الـ URI</value>
<value>الرابط</value>
<comment>Label for a uri/url.</comment>
</data>
<data name="UseFingerprintToUnlock" xml:space="preserve">
@@ -464,7 +464,7 @@
<value>إنشاء حساب</value>
</data>
<data name="CreatingAccount" xml:space="preserve">
<value>جارِ إنشاء الحساب...</value>
<value>إنشاء الحساب...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="EditItem" xml:space="preserve">
@@ -493,16 +493,16 @@
<value>احصل على إمكانية الوصول الفوري إلى كلمات المرور الخاصة بك!</value>
</data>
<data name="ExtensionReady" xml:space="preserve">
<value>أنت مستعد لتسجيل الدخول!</value>
<value>أنت مستعد للتعريف بنفسك!</value>
</data>
<data name="ExtensionSetup" xml:space="preserve">
<value>يمكن الآن الوصول إلى المعرفات الخاصة بك بسهولة من Safari وChrome والتطبيقات الأخرى المدعومة.</value>
</data>
<data name="ExtensionSetup2" xml:space="preserve">
<value>في Safari و Chrome، ابحث عن bitwarden باستخدام أيقونة المشاركة (المساعدة: انتقل إلى اليمين في السطر السفلي من القائمة).</value>
<value>في Safari و Chrome، ابحث عن bitwarden باستخدام رمز المشاركة (المساعدة: انتقل إلى اليمين في السطر السفلي من القائمة).</value>
</data>
<data name="ExtensionTapIcon" xml:space="preserve">
<value>اضغط على أيقونة Bitwarden في القائمة لإطلاق الملحق.</value>
<value>اضغط على رمز bitwarden في القائمة لإطلاق الملحق.</value>
</data>
<data name="ExtensionTurnOn" xml:space="preserve">
<value>لتنشيط bitwarden على Safari والتطبيقات الأخرى، اضغط على رمز "المزيد" على السطر السفلي من القائمة.</value>
@@ -514,10 +514,10 @@
<value>البصمة</value>
</data>
<data name="GeneratePassword" xml:space="preserve">
<value>توليد كلمة مرور</value>
<value>إنشاء كلمة مرور</value>
</data>
<data name="GetPasswordHint" xml:space="preserve">
<value>احصل على تلميح لكلمة مرورك الرئيسية</value>
<value>الحصول على دليل كلمة المرور الرئيسية</value>
</data>
<data name="ImportItems" xml:space="preserve">
<value>استيراد العناصر</value>
@@ -532,7 +532,7 @@
<value>آخر مزامنة:</value>
</data>
<data name="Length" xml:space="preserve">
<value>الطول</value>
<value>طول</value>
</data>
<data name="Lock" xml:space="preserve">
<value>قفل</value>
@@ -562,11 +562,11 @@
<value>سيؤدي تسجيل الخروج إلى إزالة جميع الوصول إلى الخزنة الخاصة بك ويتطلب المصادقة عبر الإنترنت بعد انتهاء المهلة. هل أنت متأكد من أنك تريد استخدام هذا الإعداد؟</value>
</data>
<data name="LoggingIn" xml:space="preserve">
<value>جارِ تسجيل الدخول...</value>
<value>تعريف...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="LoginOrCreateNewAccount" xml:space="preserve">
<value>قم بتسجيل الدخول أو إنشاء حساب جديد للوصول إلى خزنتك الآمنة.</value>
<value>قم بالتسجيل أو إنشاء حساب جديد للوصول إلى خزنتك الآمنة.</value>
</data>
<data name="Manage" xml:space="preserve">
<value>إدارة</value>
@@ -598,7 +598,7 @@
<value>المزيد من الإعدادات</value>
</data>
<data name="MustLogInMainApp" xml:space="preserve">
<value>يجب عليك تسجيل الدخول إلى تطبيق Bitwarden الرئيسي قبل استخدام الامتداد.</value>
<value>تحتاج إلى التعريف بنفسك على التطبيق bitwarden الرئيسي قبل استخدام الامتداد.</value>
</data>
<data name="Never" xml:space="preserve">
<value>أبداً</value>
@@ -623,25 +623,25 @@
<comment>Confirmation, like "Ok, I understand it"</comment>
</data>
<data name="OptionDefaults" xml:space="preserve">
<value>يتم تعيين الخيارات الافتراضية من أداة إنشاء كلمة المرور في تطبيق Bitwarden الرئيسي.</value>
<value>يتم تعيين الخيارات الافتراضية من أداة إنشاء كلمة المرور في تطبيق bitwarden الرئيسي.</value>
</data>
<data name="Options" xml:space="preserve">
<value>الخيارات</value>
<value>خيارات</value>
</data>
<data name="Other" xml:space="preserve">
<value>الأخرى</value>
</data>
<data name="PasswordGenerated" xml:space="preserve">
<value>كلمة المرور المولدة</value>
<value>كلمة المرور التي تم إنشاؤها.</value>
</data>
<data name="PasswordGenerator" xml:space="preserve">
<value>مولد كلمة المرور</value>
</data>
<data name="PasswordHint" xml:space="preserve">
<value>تلميح كلمة المرور</value>
<value>فهرس كلمة المرور</value>
</data>
<data name="PasswordHintAlert" xml:space="preserve">
<value>لقد أرسلنا لك رسالة بريد إلكتروني تحتوي على تلميح لكلمة مرورك الرئيسية.</value>
<value>أرسلنا بريدًا إلكترونيًا مع دليل كلمة المرور الخاص بك.</value>
</data>
<data name="PasswordOverrideAlert" xml:space="preserve">
<value>هل أنت متأكد من أنك تريد سحق كلمة المرور الموجودة؟</value>
@@ -657,7 +657,7 @@
<value>شكرا على مساعدتنا من خلال كتابة تعليق إيجابي!</value>
</data>
<data name="RegeneratePassword" xml:space="preserve">
<value>إعادة توليد كلمة المرور</value>
<value>إعادة إنشاء كلمة مرور</value>
</data>
<data name="RetypeMasterPassword" xml:space="preserve">
<value>إعادة إدخال كلمة المرور الرئيسية</value>
@@ -684,11 +684,11 @@
<value>تم تحديث العنصر</value>
</data>
<data name="Submitting" xml:space="preserve">
<value>جارِ الإرسال...</value>
<value>تقديم...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="Syncing" xml:space="preserve">
<value>جارِ المزامنة...</value>
<value>المزامنة...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="SyncingComplete" xml:space="preserve">
@@ -701,14 +701,14 @@
<value>مزامنة الخزنة الآن</value>
</data>
<data name="TouchID" xml:space="preserve">
<value>Touch ID معرف اتصال البصمة</value>
<value>Touch ID معرف اتصال</value>
<comment>What Apple calls their fingerprint reader.</comment>
</data>
<data name="TwoStepLogin" xml:space="preserve">
<value>تحديد المصادقة الثنائية</value>
</data>
<data name="TwoStepLoginConfirmation" xml:space="preserve">
<value>تجعل المصادقة الثنائية المعامل حسابك أكثر أمانًا من خلال طلب إدخال رمز أمان مع كل معرف من تطبيق المصادقة. يمكن تنشيط تعريف العامل المزدوج في خزنة الويب في bitwarden.com هل تريد زيارة الموقع الآن؟</value>
<value>تجعل المصادقة الثنائية المعامل حسابك أكثر أمانًا من خلال طلب إدخال رمز أمان مع كل معرف من تطبيق المصادقة. يمكن تنشيط تعريف العامل المزدوج في خزنة الويب في bitwarden.com. هل تريد زيارة الموقع الآن؟</value>
</data>
<data name="UnlockWith" xml:space="preserve">
<value>فتح مع {0}</value>
@@ -879,7 +879,7 @@
<value>لا يمكن لجهازك فتح هذا النوع من الملفات.</value>
</data>
<data name="Downloading" xml:space="preserve">
<value>جارِ التحميل...</value>
<value>تحميل...</value>
<comment>Message shown when downloading a file</comment>
</data>
<data name="AttachmentLargeWarning" xml:space="preserve">
@@ -1035,7 +1035,7 @@
<value>أغسطس</value>
</data>
<data name="Brand" xml:space="preserve">
<value>العلامة التجارية</value>
<value>العلامة</value>
</data>
<data name="CardholderName" xml:space="preserve">
<value>اسم حامل البطاقة</value>
@@ -1077,7 +1077,7 @@
<value>يونيو</value>
</data>
<data name="LastName" xml:space="preserve">
<value>الأسم الأخير</value>
<value>اسم العائلة</value>
</data>
<data name="FullName" xml:space="preserve">
<value>الاسم الكامل</value>
@@ -1337,7 +1337,7 @@
<value>الهويات</value>
</data>
<data name="Logins" xml:space="preserve">
<value>تسجيلات الدخول</value>
<value>معرفات</value>
</data>
<data name="SecureNotes" xml:space="preserve">
<value>ملاحظات آمنة</value>
@@ -1492,7 +1492,7 @@
<value>تعيين رمز PIN الخاص بك لإلغاء قفل Bitwarden. سيتم إعادة تعيين إعدادات PIN الخاصة بك إذا قمت بتسجيل الخروج بالكامل من التطبيق.</value>
</data>
<data name="LoggedInAsOn" xml:space="preserve">
<value>مسجل الدخول كـ {0} على {1}.</value>
<value>تم تسجيل الدخول كـ {0} في {1}.</value>
<comment>ex: Logged in as user@example.com on bitwarden.com.</comment>
</data>
<data name="VaultLockedMasterPassword" xml:space="preserve">
@@ -1617,7 +1617,7 @@
<value>إظهار / إخفاء</value>
</data>
<data name="LoginExpired" xml:space="preserve">
<value>انتهت صَلاحِيَة جَلسة تسجيل دخولك.</value>
<value>انتهت صلاحية جلسة تسجيل الدخول الخاصة بك.</value>
</data>
<data name="BiometricsDirection" xml:space="preserve">
<value>المصادقة البيومترية</value>
@@ -2328,7 +2328,7 @@
<value>هل تحاول تسجيل الدخول؟</value>
</data>
<data name="LogInAttemptByXOnY" xml:space="preserve">
<value>محاولة تسجيل الدخول بواسطة {0} على {1}</value>
<value>محاولة تسجيل الدخول بواسطة {0} في {1}</value>
</data>
<data name="DeviceType" xml:space="preserve">
<value>نوع الجهاز</value>
@@ -2629,22 +2629,22 @@
<value>كلمة المرور الرئيسية الحالية</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>سجلت دخولك!</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>الموافقة بجهازي الآخر</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>طلب موافقة المسؤول</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>الموافقة بكلمة مرور رئيسية</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>أوقف باستخدام جهاز عمومي</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>تذكر هذا الجهاز</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>مفتاح المرور</value>
@@ -2678,7 +2678,7 @@
<value>مساعدة إعادة طلب كلمة المرور الرئيسية</value>
</data>
<data name="UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve" xml:space="preserve">
<value>قد يفشل إلغاء القُفْل بسبب عدم كفاية الذاكرة. قم بتقليل إعدادات ذاكرة KDF أو قم بإعداد إلغاء القُفْل البيومتري لحل المشكلة.</value>
<value>Unlocking may fail due to insufficient memory. Decrease your KDF memory settings or set up biometric unlock to resolve.</value>
</data>
<data name="InvalidAPIKey" xml:space="preserve">
<value>مفتاح API غير صالح</value>
@@ -2687,22 +2687,22 @@
<value>رمز API غير صالح</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>طلبت موافقة المسؤول</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>أرسلت طلبك إلى مسؤولك.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>سيتم إخطارك بمجرد الموافقة عليها. </value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>مشكلة في تسجيل الدخول؟</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>تسجيل الدخول كـ {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>تَغيير إجراء مهلة المخزن لتسجيل الخروج</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>لا يمكن مشاركة هذا العنصر مع المؤسسة لأنه يوجد بالفعل واحد مع نفس مفتاح المرور.</value>
@@ -2751,13 +2751,13 @@
<value>لا يمكن تعديل العديد من عناوين URIs في وقت واحد</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>تمت الموافقة على تسجيل الدخول</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>يجب إعداد تسجيل الدخول باستخدام الجهاز في إعدادات تطبيق Bitwarden. هل تحتاج إلى خِيار آخر؟</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>تسجيل الدخول بالجهاز</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>جارٍ تسجيل الدخول</value>

View File

@@ -2627,22 +2627,22 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Hazırkı ana parol</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>Giriş edildi!</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>Digər cihazımla təsdiqlə</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>Admin təsdiqini tələb et</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Ana parolla təsdiqlə</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Hər kəsə açıq bir cihaz istifadə edərək söndür</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Bu cihazı xatırla</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Passkey</value>
@@ -2685,22 +2685,22 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Yararsız API tokeni</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>Admin təsdiqi tələb olunur</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>Tələbiniz admininizə göndərildi.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>Təsdiqləndikdən sonra məlumatlandırılacaqsınız. </value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Girişdə problem var?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>{0} olaraq giriş edilir</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Anbar vaxt bitməsi əməliyyatııxış et" olaraq dəyişdirildi</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>This item cannot be shared with the organization because there is one already with the same passkey.</value>
@@ -2749,13 +2749,13 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Bir dəfəyə bir neçə URI-a düzəliş etmək mümkün deyil</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>Giriş təsdiqləndi</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>Cihazla giriş etmə, Bitwarden tətbiqinin tənzimləmələrində quraşdırılmalıdır. Başqa bir seçimə ehtiyacınız var?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Cihazla giriş et</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Giriş edilir</value>

View File

@@ -2628,22 +2628,22 @@ select Add TOTP to store the key safely</value>
<value>Текуща главна парола</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>Вписахте се!</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>Одобряване с другото ми устройство</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>Подаване на заявка за одобрение от администратор</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Одобряване с главната парола</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Изключване на използването на публично устройство</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Запомняне на това устройство</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Passkey</value>
@@ -2677,7 +2677,7 @@ select Add TOTP to store the key safely</value>
<value>Помощ за повторното запитване за главната парола</value>
</data>
<data name="UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve" xml:space="preserve">
<value>Отключването може да бъде неуспешно заради недостатъчно памет. Намалете настройките на паметта за KDF или настройте отключването чрез биометрични данни, за да разрешите проблема.</value>
<value>Unlocking may fail due to insufficient memory. Decrease your KDF memory settings or set up biometric unlock to resolve.</value>
</data>
<data name="InvalidAPIKey" xml:space="preserve">
<value>Неправилен ключ за ППИ</value>
@@ -2686,22 +2686,22 @@ select Add TOTP to store the key safely</value>
<value>Неправилен идентификатор за ППИ</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>Заявено е одобрение от администратор</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>Вашата заявка беше изпратена до администратора Ви.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>Ще получите известие, когато тя бъде одобрена. </value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Имате проблем с вписването?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Вписване като {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Действието при изтичане на времето за достъп до трезора е променено на отписване</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>This item cannot be shared with the organization because there is one already with the same passkey.</value>
@@ -2750,13 +2750,13 @@ select Add TOTP to store the key safely</value>
<value>Не може да редактирате повече от един адрес едновременно</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>Вписването е одобрено</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>Вписването с устройство трябва да е включено в настройките на приложението на Битуорден. Друга настройка ли търсите?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Вписване с устройство</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Вписване в</value>

View File

@@ -2628,22 +2628,22 @@ Voleu canviar a aquest compte?</value>
<value>Contrasenya mestra actual</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>Connectat!</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>Aproveu des d'un altre dispositiu vostre</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>Sol·liciteu l'aprovació de l'administrador</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Aprova amb contrasenya mestra</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Apagueu amb un dispositiu públic</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Recorda aquest dispositiu</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Clau de pas</value>
@@ -2677,7 +2677,7 @@ Voleu canviar a aquest compte?</value>
<value>Ajuda per tornar a demanar la contrasenya mestra</value>
</data>
<data name="UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve" xml:space="preserve">
<value>El desbloqueig pot fallar a causa de memòria insuficient. Disminueix la configuració de memòria KDF per resoldre-ho.</value>
<value>Unlocking may fail due to insufficient memory. Decrease your KDF memory settings or set up biometric unlock to resolve.</value>
</data>
<data name="InvalidAPIKey" xml:space="preserve">
<value>Clau API no vàlida</value>
@@ -2686,22 +2686,22 @@ Voleu canviar a aquest compte?</value>
<value>Token API no vàlid</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>S'ha sol·licitat l'aprovació de l'administrador</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>La vostra sol·licitud s'ha enviat a l'administrador.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>Se us notificarà una vegada aprovat. </value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Teniu problemes per iniciar la sessió?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Connectat com {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>L'acció de temps d'espera de la caixa forta ha canviat per tancar la sessió</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>Aquest element no es pot compartir amb l'organització perquè ja n'hi ha un amb la mateixa clau de pas.</value>
@@ -2750,13 +2750,13 @@ Voleu canviar a aquest compte?</value>
<value>No es poden editar diversos URI alhora</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>S'ha aprovat l'inici de sessió</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>L'inici de sessió amb el dispositiu ha d'estar activat a la configuració de l'aplicació Bitwarden. Necessiteu una altra opció?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Inici de sessió amb dispositiu</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Inici de sessió en</value>

View File

@@ -505,7 +505,7 @@
<value>Pro spuštění rozšíření klepněte na ikonu Bitwardenu v menu.</value>
</data>
<data name="ExtensionTurnOn" xml:space="preserve">
<value>Pro zapnutí Bitwardenu v prohlížeči Safari a dalších aplikacích klepněte na ikonu „Další“ v dolní části menu.</value>
<value>Pro zapnutí Bitwardenu v prohlížeči Safari a dalších aplikacích klepněte na ikonu "Více" v dolní části menu.</value>
</data>
<data name="Favorite" xml:space="preserve">
<value>Oblíbené</value>
@@ -1304,22 +1304,22 @@ Načtení proběhne automaticky.</value>
<value>Přistupujte k Vašemu trezoru přímo z Vaší klávesnice pro rychlejší automatické vyplnění hesel.</value>
</data>
<data name="AutofillTurnOn" xml:space="preserve">
<value>Pokyny pro zapnutí automatického vyplňování hesel na vašem zařízení:</value>
<value>Pokyny pro zapnutí automatického vyplňování hesel na Vašem zařízení:</value>
</data>
<data name="AutofillTurnOn1" xml:space="preserve">
<value>1. Přejděte do aplikace "Nastavení" v iOS</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Klepněte na Hesla > Volby hesla</value>
<value>2. Klepněte na "Hesla" > "Volby hesla"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Povolte „Automatické vyplnění hesel</value>
<value>3. Zapněte přepínač u položky "Automatické vyplnění hesel"</value>
</data>
<data name="AutofillTurnOn4" xml:space="preserve">
<value>4. Najděte sekci Povolit vyplňování z</value>
<value>4. Najděte sekci "Povolit vyplňování z:"</value>
</data>
<data name="AutofillTurnOn5" xml:space="preserve">
<value>5. Zvolte Bitwarden</value>
<value>5. Zvolte "Bitwarden"</value>
</data>
<data name="PasswordAutofill" xml:space="preserve">
<value>Automatické vyplňování hesel</value>
@@ -2627,22 +2627,22 @@ Chcete se přepnout na tento účet?</value>
<value>Aktuální hlavní heslo</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>Přihlášeno!</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>Schválit s mým dalším zařízením</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>Žádost o schválení správcem</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Schválit hlavním heslem</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Vypnout pomocí veřejného zařízení</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Zapamatovat toto zařízení</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Přístupový klíč</value>
@@ -2676,7 +2676,7 @@ Chcete se přepnout na tento účet?</value>
<value>Nápověda pro znovuzeptání se na hlavní heslo</value>
</data>
<data name="UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve" xml:space="preserve">
<value>Odemknutí může selhat z důvodu nedostatku paměti. Snižte nastavení KDF paměti nebo nastavte odemykání pomocí biometrie.</value>
<value>Unlocking may fail due to insufficient memory. Decrease your KDF memory settings or set up biometric unlock to resolve.</value>
</data>
<data name="InvalidAPIKey" xml:space="preserve">
<value>Neplatný klíč API</value>
@@ -2685,22 +2685,22 @@ Chcete se přepnout na tento účet?</value>
<value>Neplatný token API</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>Bylo vyžádáno schválení správcem</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>Váš požadavek byl odeslán Vašemu správci.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>Po schválení budete upozorněni. </value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Potíže s přihlášením?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Přihlášování jako {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Akce časového limitu trezoru byla změněna na odhlášení</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>Tuto položku nelze sdílet s organizací, protože již existuje jedna se stejným přístupovým klíčem.</value>
@@ -2749,13 +2749,13 @@ Chcete se přepnout na tento účet?</value>
<value>Najednou nelze upravovat více URI</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>Přihlášení bylo schváleno</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>Přihlášení zařízením musí být nastaveno v aplikaci Bitwarden. Potřebujete další volby?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Přihlásit se zařízením</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Přihlašování na</value>

View File

@@ -2627,22 +2627,22 @@ Möchtest du zu diesem Konto wechseln?</value>
<value>Aktuelles Master-Passwort</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>Angemeldet!</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>Mit meinem anderen Gerät genehmigen</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>Admin-Genehmigung anfordern</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Mit Master-Passwort genehmigen</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Mit einem öffentlichen Gerät ausschalten</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Dieses Gerät merken</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Passkey</value>
@@ -2685,19 +2685,19 @@ Möchtest du zu diesem Konto wechseln?</value>
<value>Ungültiger API-Token</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>Admin-Genehmigung angefordert</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>Deine Anfrage wurde an deinen Administrator gesendet.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>Du wirst benachrichtigt, sobald sie genehmigt wurde.</value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Probleme beim Einloggen?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Anmelden als {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Vault timeout action changed to log out</value>
@@ -2749,13 +2749,13 @@ Möchtest du zu diesem Konto wechseln?</value>
<value>Es können nicht mehrere URIs auf einmal bearbeitet werden</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>Login genehmigt</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>Die Anmeldung über ein Gerät muss in den Einstellungen der Bitwarden App eingerichtet werden. Benötigst du eine andere Option?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Mit Gerät anmelden</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Anmelden bei</value>

View File

@@ -701,7 +701,7 @@
<value>Synkronoi holvi nyt</value>
</data>
<data name="TouchID" xml:space="preserve">
<value>Touch ID:llä</value>
<value>Touch ID</value>
<comment>What Apple calls their fingerprint reader.</comment>
</data>
<data name="TwoStepLogin" xml:space="preserve">
@@ -711,7 +711,7 @@
<value>Kaksivaiheinen kirjautuminen parantaa tilisi suojausta vaatimalla kirjautumisen vahvistuksen salasanan lisäksi todennuslaitteen, sovelluksen, tekstiviestin, puhelun tai sähköpostin avulla. Voit ottaa kaksivaiheisen kirjautumisen käyttöön bitwarden.comverkkoholvissa. Haluatko avata sen nyt?</value>
</data>
<data name="UnlockWith" xml:space="preserve">
<value>Avaus {0}</value>
<value>Avaustapa: {0}</value>
</data>
<data name="UnlockWithPIN" xml:space="preserve">
<value>Avaus PIN-koodilla</value>
@@ -766,7 +766,7 @@
<value>1. Valitse esteettömyysasetusten "Palvelut" -otsikon alta ”Bitwarden”.</value>
</data>
<data name="BitwardenAutofillServiceStep2" xml:space="preserve">
<value>2. Kytke asetus käyttöön ja hyväksy painanalla "OK".</value>
<value>2. Laita asetus päälle ja paina OK-painiketta hyväksyäksesi.</value>
</data>
<data name="Disabled" xml:space="preserve">
<value>Poistettu käytöstä</value>
@@ -802,7 +802,7 @@
<value>Mahdollisesti tunnistetut kohteet</value>
</data>
<data name="Search" xml:space="preserve">
<value>Etsi</value>
<value>Hae</value>
</data>
<data name="BitwardenAutofillServiceSearch" xml:space="preserve">
<value>Etsit automaattisesti täytettävää kohdetta osoitteelle ”{0}”.</value>
@@ -860,7 +860,7 @@
<comment>For 2FA</comment>
</data>
<data name="YubiKeyInstruction" xml:space="preserve">
<value>Jatka asettamalla YubiKey NEO -todennuslaite laitteen taustaa vasten tai kytke YubiKey-todennuslaite laitteen USB-porttiin ja paina sen painiketta.</value>
<value>Jatka asettamalla YubiKey NEO -todenuslaite laitteen takapuolta vasten tai kytke YubiKey-todennuslaite laitteen USB-porttiin ja paina sen painiketta.</value>
</data>
<data name="YubiKeyTitle" xml:space="preserve">
<value>YubiKey-todennuslaite</value>
@@ -916,10 +916,10 @@ Koodi luetaan automaattisesti.</value>
<value>Kopioi TOTP-todennuskoodi</value>
</data>
<data name="CopyTotpAutomaticallyDescription" xml:space="preserve">
<value>TOTP-todennuskoodi kopioidaan automaattisesti leikepöydälle automaattisen täytön yhteydessä, jos kirjautumistieto sisältää kaksivaiheisen todennusmenetelmän avaimen.</value>
<value>Jos kirjautumistieto sisältää kaksivaiheisen todennusmenetelmän avaimen, kopioidaan TOTP-todennuskoodi leikepöydälle kohteen automaattisen täytön yhteydessä.</value>
</data>
<data name="CopyTotpAutomatically" xml:space="preserve">
<value>TOTP-koodin kopiointi</value>
<value>Kopioi TOTP-koodi automaattisesti</value>
</data>
<data name="PremiumRequired" xml:space="preserve">
<value>Käyttääksesi tätä toimintoa tarvitset Premium-jäsenyyden.</value>
@@ -1140,7 +1140,7 @@ Koodi luetaan automaattisesti.</value>
<value>Erääntymisaika</value>
</data>
<data name="ShowWebsiteIcons" xml:space="preserve">
<value>Näytä sivustokuvakkeet</value>
<value>Näytä verkkosivustojen kuvakkeet</value>
</data>
<data name="ShowWebsiteIconsDescription" xml:space="preserve">
<value>Näytä tunnistettava kuva jokaiselle kirjautumistiedolle.</value>
@@ -1182,7 +1182,7 @@ Koodi luetaan automaattisesti.</value>
<value>Avaa "Automaattinen täyttö -palvelu" -asetukset</value>
</data>
<data name="FaceID" xml:space="preserve">
<value>Face ID:llä</value>
<value>Face ID</value>
<comment>What Apple calls their facial recognition reader.</comment>
</data>
<data name="FaceIDDirection" xml:space="preserve">
@@ -1269,13 +1269,13 @@ Koodi luetaan automaattisesti.</value>
<comment>An entity of multiple related people (ex. a team or business organization).</comment>
</data>
<data name="HoldYubikeyNearTop" xml:space="preserve">
<value>Pidä YubiKey-todennuslaittettasi lähellä laitteen yläosaa.</value>
<value>Pidä YubiKey-todenuslaittettasi lähellä laitteen yläosaa.</value>
</data>
<data name="TryAgain" xml:space="preserve">
<value>Yritä uudelleen</value>
</data>
<data name="YubiKeyInstructionIos" xml:space="preserve">
<value>Jatka pitämällä YubiKey NEO -todennuslaitetta laitteen taustaa vasten.</value>
<value>Jatka pitämällä YubiKey NEO -todenuslaitetta laitteen takapuolta vasten.</value>
</data>
<data name="BitwardenAutofillAccessibilityServiceDescription2" xml:space="preserve">
<value>Esteettömyyspalvelu voi olla hyödyllinen sellaisten sovellusten kanssa, jotka eivät tue tavallista automaattisen täytön palvelua.</value>
@@ -1381,7 +1381,7 @@ Koodi luetaan automaattisesti.</value>
<value>Ei näytettäviä kohteita.</value>
</data>
<data name="SearchCollection" xml:space="preserve">
<value>Etsi kokoelmasta</value>
<value>Hae kokoelmasta</value>
</data>
<data name="SearchFileSends" xml:space="preserve">
<value>Etsi tiedosto-Sendeistä</value>
@@ -1556,7 +1556,7 @@ Koodi luetaan automaattisesti.</value>
<value>Oletusarvoinen tumma teema</value>
</data>
<data name="DefaultDarkThemeDescription" xml:space="preserve">
<value>Valitse "Oletus (järjestelmä)" -asetuksen oletusarvoinen tumma teema, jota käytetään laitteen tumman tilan ollessa käytössä.</value>
<value>Valitse Oletus (järjestelmä) -asetuksen oletusarvoinen tumma teema, jota käytetään laitteen tumman tilan ollessa käytössä.</value>
</data>
<data name="CopyNotes" xml:space="preserve">
<value>Kopioi merkinnät</value>
@@ -1623,7 +1623,7 @@ Koodi luetaan automaattisesti.</value>
<value>Biometrinen todennus</value>
</data>
<data name="Biometrics" xml:space="preserve">
<value>biometrialla</value>
<value>Biometria</value>
</data>
<data name="UseBiometricsToUnlock" xml:space="preserve">
<value>Avaa biometrialla</value>
@@ -1734,7 +1734,7 @@ Koodi luetaan automaattisesti.</value>
<comment>(noun) Location of deleted items which have not yet been permanently deleted</comment>
</data>
<data name="SearchTrash" xml:space="preserve">
<value>Etsi roskakorista</value>
<value>Hae roskakorista</value>
<comment>(action prompt) Label for the search text field when viewing the trash folder</comment>
</data>
<data name="DoYouReallyWantToPermanentlyDeleteCipher" xml:space="preserve">
@@ -1999,7 +1999,7 @@ Koodi luetaan automaattisesti.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SearchSends" xml:space="preserve">
<value>Etsi Sendeistä</value>
<value>Hae Sendeistä</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="EditSend" xml:space="preserve">
@@ -2629,22 +2629,22 @@ Haluatko vaihtaa tähän tiliin?</value>
<value>Nykyinen pääsalasana</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>Kirjautuminen onnistui!</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>Hyväksy muilta laitteiltasi</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>Pyydä hyväksyntää ylläpidolta</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Hyväksy pääsalasanalla</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Poista käytöstä julkisilla laitteilla</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Muista tämä laite</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Suojausavain</value>
@@ -2666,7 +2666,7 @@ Haluatko vaihtaa tähän tiliin?</value>
<value>Suojausavainta ei kopioida</value>
</data>
<data name="ThePasskeyWillNotBeCopiedToTheClonedItemDoYouWantToContinueCloningThisItem" xml:space="preserve">
<value>Suojausavain ei kopioidu kloonattuun kohteeseen. Haluatko jatkaa kloonausta?</value>
<value>Suojausavainta ei kopioida kloonattuun kohteeseen. Haluatko jatkaa kloonausta?</value>
</data>
<data name="CopyApplication" xml:space="preserve">
<value>Kopioi sovellus</value>
@@ -2678,7 +2678,7 @@ Haluatko vaihtaa tähän tiliin?</value>
<value>Pääsalasanan uudelleenkyselyn ohje</value>
</data>
<data name="UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve" xml:space="preserve">
<value>Lukituksen avaus voi epäonnistua riittämättömän keskusmuistin vuoksi. Korjaa madaltamalla KDF-muistiasetuksiasi.</value>
<value>Unlocking may fail due to insufficient memory. Decrease your KDF memory settings or set up biometric unlock to resolve.</value>
</data>
<data name="InvalidAPIKey" xml:space="preserve">
<value>Virheellinen API-avain</value>
@@ -2687,22 +2687,22 @@ Haluatko vaihtaa tähän tiliin?</value>
<value>Virheellinen API-tunniste</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>Hyväksyntää pyydetty ylläpidolta</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>Pyyntösi on välitetty ylläpidollesi.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>Saat ilmoituksen heti kun se on hyväksytty.</value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Ongelmia kirjautumisessa?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Kirjaudutaan tunnuksella {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Holvin aikakatkaisutoiminnoksi vaihdettiin uloskirjaus</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>Kohdetta ei voida jakaa organisaatiolle, koska siellä on jo samaa suojausavainta käyttävä kohde.</value>
@@ -2751,13 +2751,13 @@ Haluatko vaihtaa tähän tiliin?</value>
<value>Useita URI-osoitteita ei ole mahdollista muokata samanaikaisesti</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>Kirjautuminen hyväksyttiin</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>Laitteella kirjautuminen on määritettävä Bitwarden-sovelluksen asetuksista. Tarvitsetko eri vaihtoehdon?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Laitteella kirjautuminen</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Kirjaudutaan sijaintiin</value>

View File

@@ -2627,22 +2627,22 @@ Szeretnénk átváltani erre a fiókra?</value>
<value>Jelenlegi mesterjelszó</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>Megtörtént a bejelentkezés.</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>Jóváhagyás másik eszközzel</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>Adminisztrátori jóváhagyás kérés</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Jóváhagyás mesterjelszóval</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Kikapcsolás nyilvános eszközzel</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Eszköz megjegyzése</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Hozzáférési kulcs</value>
@@ -2685,22 +2685,22 @@ Szeretnénk átváltani erre a fiókra?</value>
<value>Érvénytelen API vezérjel</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>Adminisztrátori jóváhagyás kérés történt</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>A kérés elküldésre került az adminisztrátornak.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>A jóváhagyás után értesítés érkezik.</value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Probléma van a bejelentkezéssel?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Bejelentkezés mint {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>A széf időkifutási művelete kijelentkezésre módosult.</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>Ez az elem nem osztható meg a szervezettel, mert már van egy ugyanezzel a hozzáférési kulccsal.</value>
@@ -2749,13 +2749,13 @@ Szeretnénk átváltani erre a fiókra?</value>
<value>Nem szerkeszthető több URI egyszerre.</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>A bejelentkezés jóváhagyásra került.</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>Az eszközzel történő bejelentkezést be kell állítani a Bitwarden alkalmazás beállításaiban. Más opcióra van szükség?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Bejelentkezés eszközzel</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Bejelentkezés:</value>

View File

@@ -2505,7 +2505,7 @@ Vuoi passare a questo account?</value>
<value>Accedi con dispositivo</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Accesso avviato</value>
<value>Login avviato</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Una notifica è stata inviata al tuo dispositivo.</value>
@@ -2637,10 +2637,10 @@ Vuoi passare a questo account?</value>
<value>Richiedi approvazione dell'amministratore</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Approva con password principale</value>
<value>Approva con la password principale</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Deseleziona se stai usando un dispositivo pubblico</value>
<value>Disattiva quando usi un dispositivo pubblico</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Ricorda questo dispositivo</value>
@@ -2692,16 +2692,16 @@ Vuoi passare a questo account?</value>
<value>La tua richiesta è stata inviata al tuo amministratore.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>Riceverai una notifica una volta approvato. </value>
<value>Riceverai una notifica al momento dell'approvazione. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Problemi ad accedere?</value>
<value>Problemi nell'effettuare l'accesso?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Accedendo come {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Azione timeout cassaforte impostata su uscire</value>
<value>Azione timeout cassaforte cambiata per uscire</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>Questo elemento non può essere condiviso con l'organizzazione perché ne esiste già uno con la stessa passkey.</value>
@@ -2753,10 +2753,10 @@ Vuoi passare a questo account?</value>
<value>Accesso approvato</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>L'accesso con dispositivo deve essere abilitato nelle impostazioni dell'app Bitwarden. Ti serve un'altra opzione?</value>
<value>Accesso con dispositivo deve essere impostato nelle impostazioni dell'app Bitwarden. Hai bisogno di un'altra opzione?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Accedi con dispositivo</value>
<value>Accesso con dispositivo</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Accedendo su</value>

View File

@@ -1384,10 +1384,10 @@ Nolasīšana notiks automātiski.</value>
<value>Meklēt krājumā</value>
</data>
<data name="SearchFileSends" xml:space="preserve">
<value>Meklēt datņu Send</value>
<value>Meklēt datņu Sūtījumus</value>
</data>
<data name="SearchTextSends" xml:space="preserve">
<value>Meklēt teksta Send</value>
<value>Meklēt teksta Sūtījumus</value>
</data>
<data name="SearchGroup" xml:space="preserve">
<value>Meklēt {0}</value>
@@ -1496,13 +1496,13 @@ Nolasīšana notiks automātiski.</value>
<comment>ex: Logged in as user@example.com on bitwarden.com.</comment>
</data>
<data name="VaultLockedMasterPassword" xml:space="preserve">
<value>Glabātava ir aizslēgta. Nepieciešams norādīt galveno paroli, lai turpinātu.</value>
<value>Glabātava ir slēgta. Nepieciešams norādīt galveno paroli, lai turpinātu.</value>
</data>
<data name="VaultLockedPIN" xml:space="preserve">
<value>Glabātava ir aizslēgta. Nepieciešams norādīt PIN kodu, lai turpinātu.</value>
<value>Glabātava ir slēgta. Nepieciešams norādīt PIN kodu, lai turpinātu.</value>
</data>
<data name="VaultLockedIdentity" xml:space="preserve">
<value>Glabātava ir aizslēgta. Jāapstiprina identitāte, lai turpinātu.</value>
<value>Glabātava ir slēgta. Jāapstiprina identitāte, lai turpinātu.</value>
</data>
<data name="Dark" xml:space="preserve">
<value>Tumšs</value>
@@ -1662,7 +1662,7 @@ Nolasīšana notiks automātiski.</value>
<value>Kods nosūtīts</value>
</data>
<data name="ConfirmYourIdentity" xml:space="preserve">
<value>apstiprina identitāte, lai turpinātu.</value>
<value>Lai turpinātu, apstipriniet savu identitāti.</value>
</data>
<data name="ExportVaultWarning" xml:space="preserve">
<value>Šī izguve satur glabātavas datus nešifrētā veidā. Izdoto datni nevajadzētu glabāt vai sūtīt nedrošos veidos (piemēram, e-pastā). Izdzēst to uzreiz pēc izmantošanas.</value>
@@ -1746,7 +1746,7 @@ Nolasīšana notiks automātiski.</value>
<comment>Confirmation alert message when restoring a soft-deleted cipher.</comment>
</data>
<data name="DoYouReallyWantToSoftDeleteCipher" xml:space="preserve">
<value>Vai tiešām pārvietot uz atkritni?</value>
<value>Vai tiešām vēlaties sūtīt uz atkritni?</value>
<comment>Confirmation alert message when soft-deleting a cipher.</comment>
</data>
<data name="AccountBiometricInvalidated" xml:space="preserve">
@@ -1867,19 +1867,19 @@ Nolasīšana notiks automātiski.</value>
<value>Apvienības nosacījumi ietekmē Tavas īpašumtiesību iespējas.</value>
</data>
<data name="Send" xml:space="preserve">
<value>Send</value>
<value>Sūtīt</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="AllSends" xml:space="preserve">
<value>Visi Send</value>
<value>Visi Sūtījumi</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="Sends" xml:space="preserve">
<value>Send vienumi</value>
<value>Sūtījumi</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="NameInfo" xml:space="preserve">
<value>Lasāms nosaukums, kas apraksta šo Send.</value>
<value>Draudzīgs nosaukums, lai raksturotu šo Sūtījumu.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="Text" xml:space="preserve">
@@ -1920,7 +1920,7 @@ Nolasīšana notiks automātiski.</value>
<value>Dzēšanas laiks</value>
</data>
<data name="DeletionDateInfo" xml:space="preserve">
<value>Send tiks neatgriezeniski izdzēsts norādītajā datumā un laikā.</value>
<value>Sūtījums tiks neatgriezeniski dzēsts norādītajā datumā un laikā.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="PendingDelete" xml:space="preserve">
@@ -1933,21 +1933,21 @@ Nolasīšana notiks automātiski.</value>
<value>Derīguma beigu laiks</value>
</data>
<data name="ExpirationDateInfo" xml:space="preserve">
<value>Ja iestatīts, piekļuve šim Send beigsies norādītajā datumā un laikā.</value>
<value>Ja tas ir iestatīts, piekļuve šim Sūtījumam beigsies norādītajā datumā un laikā.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="Expired" xml:space="preserve">
<value>Beidzies izmantošanas laiks</value>
</data>
<data name="MaximumAccessCount" xml:space="preserve">
<value>Lielākais pieļaujamais piekļuves reižu skaits</value>
<value>Lielākais pieļaujamais piekļuvju skaits</value>
</data>
<data name="MaximumAccessCountInfo" xml:space="preserve">
<value>Ja iestatīts, lietotāji nevarēs piekļūt šim Send, kad tiks sasniegts lielākais pieļaujamais piekļūšanas reižu skaits.</value>
<value>Ja tas ir iestatīts, lietotāji vairs nevarēs piekļūt šim Sūtījumam, tiklīdz būs sasniegts maksimālais piekļuves skaits.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="MaximumAccessCountReached" xml:space="preserve">
<value>Sasniegts lielākais pieļaujamais piekļuves reižu skaits</value>
<value>Sasniegts lielākais pieļaujamais piekļuvju skaits</value>
</data>
<data name="CurrentAccessCount" xml:space="preserve">
<value>Pašreizējais piekļuvju skaits</value>
@@ -1956,14 +1956,14 @@ Nolasīšana notiks automātiski.</value>
<value>Jauna parole</value>
</data>
<data name="PasswordInfo" xml:space="preserve">
<value>Pēc izvēles pieprasīt paroli, lai lietotāji varētu piekļūt šim Send.</value>
<value>Pēc izvēles pieprasīt paroli, lai lietotāji varētu piekļūt šim Sūtījumam.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="RemovePassword" xml:space="preserve">
<value>Noņemt paroli</value>
</data>
<data name="AreYouSureRemoveSendPassword" xml:space="preserve">
<value>Vai tiešām noņemt paroli?</value>
<value>Vai tiešām vēlaties noņemt paroli?</value>
</data>
<data name="RemovingSendPassword" xml:space="preserve">
<value>Noņem paroli</value>
@@ -1972,19 +1972,19 @@ Nolasīšana notiks automātiski.</value>
<value>Parole ir noņemta</value>
</data>
<data name="NotesInfo" xml:space="preserve">
<value>Personīgas piezīmes par šo Send.</value>
<value>Privātas piezīmes par šo Sūtījumu.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="DisableSend" xml:space="preserve">
<value>Izslēgt šo Send, lai neviens tam nevarētu piekļūt</value>
<value>Deaktivizēt šo Sūtījumu, lai neviens tam nevarētu piekļūt</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="NoSends" xml:space="preserve">
<value>Kontā nav neviena Send.</value>
<value>Jūsu kontā nav neviena Sūtījuma.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="AddASend" xml:space="preserve">
<value>Pievienot Send</value>
<value>Pievienot Sūtījumu</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="CopyLink" xml:space="preserve">
@@ -1994,35 +1994,35 @@ Nolasīšana notiks automātiski.</value>
<value>Kopīgot saiti</value>
</data>
<data name="SendLink" xml:space="preserve">
<value>Send saite</value>
<value>Sūtījuma saite</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SearchSends" xml:space="preserve">
<value>Meklēt Send</value>
<value>Meklēt Sūtījumus</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="EditSend" xml:space="preserve">
<value>Labot Send</value>
<value>Labot Sūtījumu</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="AddSend" xml:space="preserve">
<value>Jauns Send</value>
<value>Jauns Sūtījums</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="AreYouSureDeleteSend" xml:space="preserve">
<value>Vai tiešām izdzēst šo Send?</value>
<value>Vai tiešām vēlaties dzēst šo Sūtījumu?</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SendDeleted" xml:space="preserve">
<value>Send izdzēsts</value>
<value>Sūtījums dzēsts</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SendUpdated" xml:space="preserve">
<value>Send saglabāts</value>
<value>Sūtījums saglabāts</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="NewSendCreated" xml:space="preserve">
<value>Send izveidots</value>
<value>Sūtījums izveidots</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="OneDay" xml:space="preserve">
@@ -2044,30 +2044,30 @@ Nolasīšana notiks automātiski.</value>
<value>Pielāgots</value>
</data>
<data name="ShareOnSave" xml:space="preserve">
<value>Kopīgot šo Send pēc saglabāšanas</value>
<value>Kopīgojiet šo Sūtījumu pēc saglabāšanas</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SendDisabledWarning" xml:space="preserve">
<value>Uzņēmuma nosacījumu dēļ ir iespējams dzēst tikai esošu Send.</value>
<value>Organizācijas politikas dēļ jūs varat dzēst tikai esošu Sūtījumu.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="AboutSend" xml:space="preserve">
<value>Par Send</value>
<value>Par Sūtījumu</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="HideEmail" xml:space="preserve">
<value>Slēpt e-pasta adresi no saņēmējiem.</value>
</data>
<data name="SendOptionsPolicyInEffect" xml:space="preserve">
<value>Viens vai vairāki apvienības nosacījumi ietekmē Send iespējas.</value>
<value>Viena vai vairākas organizācijas politikas ietekmē jūsu Sūtījuma opcijas.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SendFilePremiumRequired" xml:space="preserve">
<value>Ar bezmaksas kontu ir iespējams kopīgot tikai tekstu. Ir nepieciešama Premium dalība, lai Send izmantotu datnes.</value>
<value>Bezmaksas kontos var kopīgot tikai tekstu. Lai izmantotu failus ar Sūtījumu, ir nepieciešama Premium dalība.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SendFileEmailVerificationRequired" xml:space="preserve">
<value>Ir jāapstiprina e-pasta adrese, lai izmantotu datnes ar Send. E-pasta edresi var apstiprināt tīmekļa glabātavā.</value>
<value>Jums ir jāapstiprina savs e-pasts, lai izmantotu failus ar Sūtījumu. Jūs varat verificēt savu e-pastu tīmekļa glabātuvē.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="PasswordPrompt" xml:space="preserve">
@@ -2203,7 +2203,7 @@ Nolasīšana notiks automātiski.</value>
<value>Sūta</value>
</data>
<data name="CopySendLinkOnSave" xml:space="preserve">
<value>Saglabāšanas laikā ievietot Send saiti starpliktuvē</value>
<value>Kopēt Sūtījuma saiti saglabāšanas laikā</value>
</data>
<data name="SendingCode" xml:space="preserve">
<value>Sūta kodu</value>
@@ -2212,13 +2212,13 @@ Nolasīšana notiks automātiski.</value>
<value>Pārbauda</value>
</data>
<data name="ResendCode" xml:space="preserve">
<value>Atkārtoti nosūtīt kodu</value>
<value>Nosūtīt kodu vēlreiz</value>
</data>
<data name="AVerificationCodeWasSentToYourEmail" xml:space="preserve">
<value>Pārbaudes kods tika nosūtīts e-pastā</value>
</data>
<data name="AnErrorOccurredWhileSendingAVerificationCodeToYourEmailPleaseTryAgain" xml:space="preserve">
<value>Atgadījās kļūda, kad apliecinājuma kods tika sūtīts uz e-pastu. Lūgums mēģināt vēlreiz</value>
<value>Nosūtot verifikācijas kodu uz jūsu e-pastu, radās kļūda. Lūdzu mēģiniet vēlreiz</value>
</data>
<data name="EnterTheVerificationCodeThatWasSentToYourEmail" xml:space="preserve">
<value>Ievadīt pārbaudes kodu, kas tika nosūtīts e-pastā</value>
@@ -2511,7 +2511,7 @@ Vai pārslēgties uz šo kontu?</value>
<value>Uz ierīci ir nosūtīts paziņojums.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Lūgums pārliecināties, ka glabātava ir atslēgta un atpazīšanas vārdkopa ir tāda pati arī citā ierīcē.</value>
<value>pārliecinās, ka glabātava ir atslēgta un atpazīšanas vārdkopa ir tāda pati arī citā ierīcē.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Atkārtoti nosūtīt paziņojumu</value>
@@ -2628,22 +2628,22 @@ Vai pārslēgties uz šo kontu?</value>
<value>Pašreizējā galvenā parole</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>Pieteicies.</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>Apstiprināt ar citu savu ierīci</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>Pieprasīt pārvaldītāja apstiprinājumu</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Apstiprināt ar galveno paroli</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Izslēgt izmantojot publisku ierīci</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Atcerēties šo ierīci</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Paroļatslēga</value>
@@ -2686,22 +2686,22 @@ Vai pārslēgties uz šo kontu?</value>
<value>Nederīga API pilnvara</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>Pieprasīts pārvaldītāja apstiprinājums</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>Pieprasījums tika nosūtīts pārvaldītājam.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>Tiks saņemts paziņojums, tiklīdz būs apstiprināts. </value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Neizdodas pieteikties?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Piesakās kā {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Glabātavas noildzes darbība nomainīta uz atteikšanos</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>Šo vienumu nevar kopīgot ar apvienību, jo tur jau ir tāds ar to pašu paroļatslēgu.</value>
@@ -2750,13 +2750,13 @@ Vai pārslēgties uz šo kontu?</value>
<value>Nevar labot vairākus URI vienlaicīgi</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>Pieteikšanās apstiprināta</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>Ir jāuzstāda pieteikšanās ar ierīci Bitwarden lietotnes iestatījumos. Nepieciešama cita iespēja?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Pieteikties ar ierīci</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Piesakās</value>

View File

@@ -514,7 +514,7 @@
<value>अंगुलिमुद्रा</value>
</data>
<data name="GeneratePassword" xml:space="preserve">
<value>पासवर्ड निर्माण करा</value>
<value>Generate password</value>
</data>
<data name="GetPasswordHint" xml:space="preserve">
<value>Get your master password hint</value>
@@ -587,11 +587,11 @@
<value>Master password must be at least {0} characters long.</value>
</data>
<data name="MinNumbers" xml:space="preserve">
<value>किमान अंक</value>
<value>Minimum numbers</value>
<comment>Minimum numeric characters for password generator settings</comment>
</data>
<data name="MinSpecial" xml:space="preserve">
<value>किमान विशेष</value>
<value>Minimum special</value>
<comment>Minimum special characters for password generator settings</comment>
</data>
<data name="MoreSettings" xml:space="preserve">
@@ -632,10 +632,10 @@
<value>Other</value>
</data>
<data name="PasswordGenerated" xml:space="preserve">
<value>पासवर्ड निर्माण झाला</value>
<value>Password generated</value>
</data>
<data name="PasswordGenerator" xml:space="preserve">
<value>पासवर्ड जनित्र</value>
<value>Password generator</value>
</data>
<data name="PasswordHint" xml:space="preserve">
<value>Password hint</value>
@@ -657,7 +657,7 @@
<value>Please consider helping us out with a good review!</value>
</data>
<data name="RegeneratePassword" xml:space="preserve">
<value>पासवर्ड पुनर्जनित करा</value>
<value>Regenerate password</value>
</data>
<data name="RetypeMasterPassword" xml:space="preserve">
<value>Re-type master password</value>
@@ -1008,16 +1008,16 @@ Scanning will happen automatically.</value>
<value>Security code</value>
</data>
<data name="TypeCard" xml:space="preserve">
<value>कार्ड</value>
<value>Card</value>
</data>
<data name="TypeIdentity" xml:space="preserve">
<value>ओळख</value>
<value>Identity</value>
</data>
<data name="TypeLogin" xml:space="preserve">
<value>प्रवेश</value>
<value>Login</value>
</data>
<data name="TypeSecureNote" xml:space="preserve">
<value>संरक्षित चिठ्ठी</value>
<value>Secure note</value>
</data>
<data name="Address1" xml:space="preserve">
<value>Address 1</value>
@@ -1038,7 +1038,7 @@ Scanning will happen automatically.</value>
<value>Brand</value>
</data>
<data name="CardholderName" xml:space="preserve">
<value>कार्डधारकाचे नाव</value>
<value>Cardholder name</value>
</data>
<data name="CityTown" xml:space="preserve">
<value>City / Town</value>
@@ -1158,16 +1158,16 @@ Scanning will happen automatically.</value>
<value>Go to my vault</value>
</data>
<data name="Collections" xml:space="preserve">
<value>संग्रह</value>
<value>Collections</value>
</data>
<data name="NoItemsCollection" xml:space="preserve">
<value>ह्या संग्रहात एकही वस्तू नाही.</value>
<value>There are no items in this collection.</value>
</data>
<data name="NoItemsFolder" xml:space="preserve">
<value>There are no items in this folder.</value>
</data>
<data name="NoItemsTrash" xml:space="preserve">
<value>कचराकुंडी रिकामी आहे.</value>
<value>There are no items in the trash.</value>
</data>
<data name="AutofillAccessibilityService" xml:space="preserve">
<value>Auto-fill Accessibility Service</value>
@@ -1331,7 +1331,7 @@ Scanning will happen automatically.</value>
<value>Invalid email address.</value>
</data>
<data name="Cards" xml:space="preserve">
<value>कार्ड</value>
<value>Cards</value>
</data>
<data name="Identities" xml:space="preserve">
<value>Identities</value>
@@ -1340,7 +1340,7 @@ Scanning will happen automatically.</value>
<value>Logins</value>
</data>
<data name="SecureNotes" xml:space="preserve">
<value>संरक्षित चिठ्ठ्या</value>
<value>Secure notes</value>
</data>
<data name="AllItems" xml:space="preserve">
<value>All items</value>
@@ -1372,7 +1372,7 @@ Scanning will happen automatically.</value>
<value>Password history</value>
</data>
<data name="Types" xml:space="preserve">
<value>प्रकार</value>
<value>Types</value>
</data>
<data name="NoPasswordsToList" xml:space="preserve">
<value>No passwords to list.</value>
@@ -1381,7 +1381,7 @@ Scanning will happen automatically.</value>
<value>There are no items to list.</value>
</data>
<data name="SearchCollection" xml:space="preserve">
<value>संग्रहात शोधा</value>
<value>Search collection</value>
</data>
<data name="SearchFileSends" xml:space="preserve">
<value>Search file Sends</value>
@@ -1422,7 +1422,7 @@ Scanning will happen automatically.</value>
<value>Item has been shared.</value>
</data>
<data name="SelectOneCollection" xml:space="preserve">
<value>किमान एक संग्रह तरी निवडला पाहिजे.</value>
<value>You must select at least one collection.</value>
</data>
<data name="Share" xml:space="preserve">
<value>Share</value>
@@ -1440,7 +1440,7 @@ Scanning will happen automatically.</value>
<value>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.</value>
</data>
<data name="NumberOfWords" xml:space="preserve">
<value>शब्दांची संख्या</value>
<value>Number of words</value>
</data>
<data name="Passphrase" xml:space="preserve">
<value>Passphrase</value>
@@ -1453,7 +1453,7 @@ Scanning will happen automatically.</value>
<comment>To clear something out. example: To clear browser history.</comment>
</data>
<data name="Generator" xml:space="preserve">
<value>जनित्र</value>
<value>Generator</value>
<comment>Short for "Password Generator"</comment>
</data>
<data name="NoFoldersToList" xml:space="preserve">
@@ -1601,11 +1601,11 @@ Scanning will happen automatically.</value>
<value>Your theme changes will apply when the app is restarted.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>पहिले अक्षर मोठे करा</value>
<value>Capitalize</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>अंक समविष्ट करा</value>
<value>Include number</value>
</data>
<data name="Download" xml:space="preserve">
<value>Download</value>
@@ -1684,7 +1684,7 @@ Scanning will happen automatically.</value>
<value>There was a problem exporting your vault. If the problem persists, you'll need to export from the web vault.</value>
</data>
<data name="ExportVaultSuccess" xml:space="preserve">
<value>तिजोरी निर्यात यशस्वी</value>
<value>Vault exported successfully</value>
</data>
<data name="Clone" xml:space="preserve">
<value>Clone</value>
@@ -1730,7 +1730,7 @@ Scanning will happen automatically.</value>
<comment>Confirmation message after successfully restoring a soft-deleted item</comment>
</data>
<data name="Trash" xml:space="preserve">
<value>कचराकुंडी</value>
<value>Trash</value>
<comment>(noun) Location of deleted items which have not yet been permanently deleted</comment>
</data>
<data name="SearchTrash" xml:space="preserve">
@@ -1868,15 +1868,15 @@ Scanning will happen automatically.</value>
<value>An organization policy is affecting your ownership options.</value>
</data>
<data name="Send" xml:space="preserve">
<value>पाठवणी</value>
<value>Send</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="AllSends" xml:space="preserve">
<value>सर्व पाठवण्या</value>
<value>All Sends</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="Sends" xml:space="preserve">
<value>पाठवण्या</value>
<value>Sends</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="NameInfo" xml:space="preserve">
@@ -1985,7 +1985,7 @@ Scanning will happen automatically.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="AddASend" xml:space="preserve">
<value>पाठवणी जोडा</value>
<value>Add a Send</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="CopyLink" xml:space="preserve">
@@ -2261,10 +2261,10 @@ Scanning will happen automatically.</value>
<value>Filter items by vault</value>
</data>
<data name="AllVaults" xml:space="preserve">
<value>सर्व तिजोऱ्या</value>
<value>All vaults</value>
</data>
<data name="Vaults" xml:space="preserve">
<value>तिजोऱ्या</value>
<value>Vaults</value>
</data>
<data name="VaultFilterDescription" xml:space="preserve">
<value>Vault: {0}</value>
@@ -2385,7 +2385,7 @@ select Add TOTP to store the key safely</value>
<value>Password type</value>
</data>
<data name="WhatWouldYouLikeToGenerate" xml:space="preserve">
<value>काय निर्माण करायचे?</value>
<value>What would you like to generate?</value>
</data>
<data name="UsernameType" xml:space="preserve">
<value>Username type</value>
@@ -2441,7 +2441,7 @@ select Add TOTP to store the key safely</value>
<value>Are you sure you want to overwrite the current username?</value>
</data>
<data name="GenerateUsername" xml:space="preserve">
<value>वापरकर्ता नाव निर्माण करा</value>
<value>Generate username</value>
</data>
<data name="EmailType" xml:space="preserve">
<value>Email Type</value>

View File

@@ -156,7 +156,7 @@
<comment>The button text that allows a user to copy the login's password to their clipboard.</comment>
</data>
<data name="CopyUsername" xml:space="preserve">
<value>Copiar o nome de usuário</value>
<value>Copiar o Nome de Usuário</value>
<comment>The button text that allows a user to copy the login's username to their clipboard.</comment>
</data>
<data name="Credits" xml:space="preserve">
@@ -179,7 +179,7 @@
<value>Editar</value>
</data>
<data name="EditFolder" xml:space="preserve">
<value>Editar pasta</value>
<value>Editar Pasta</value>
</data>
<data name="Email" xml:space="preserve">
<value>E-Mail</value>
@@ -229,14 +229,14 @@
<value>Pastas</value>
</data>
<data name="FolderUpdated" xml:space="preserve">
<value>Pasta salva</value>
<value>Pasta atualizada.</value>
</data>
<data name="GoToWebsite" xml:space="preserve">
<value>Ir para o Site</value>
<value>Ir para o website</value>
<comment>The button text that allows user to launch the website to their web browser.</comment>
</data>
<data name="HelpAndFeedback" xml:space="preserve">
<value>Ajuda e feedback</value>
<value>Ajuda e Feedback</value>
</data>
<data name="Hide" xml:space="preserve">
<value>Ocultar</value>
@@ -269,7 +269,7 @@
<comment>Title for login page. (noun)</comment>
</data>
<data name="LogOut" xml:space="preserve">
<value>Encerrar sessão</value>
<value>Encerrar Sessão</value>
<comment>The log out button text (verb).</comment>
</data>
<data name="LogoutConfirmation" xml:space="preserve">
@@ -288,7 +288,7 @@
<value>Você gostaria de mudar para ela agora?</value>
</data>
<data name="MasterPassword" xml:space="preserve">
<value>Senha mestra</value>
<value>Senha Mestra</value>
<comment>Label for a master password.</comment>
</data>
<data name="More" xml:space="preserve">
@@ -296,7 +296,7 @@
<comment>Text to define that there are more options things to see.</comment>
</data>
<data name="MyVault" xml:space="preserve">
<value>Meu cofre</value>
<value>Meu Cofre</value>
<comment>The title for the vault page.</comment>
</data>
<data name="Authenticator" xml:space="preserve">
@@ -342,7 +342,7 @@
<comment>Reveal a hidden value (password).</comment>
</data>
<data name="ItemDeleted" xml:space="preserve">
<value>Item excluído</value>
<value>O item foi apagado.</value>
<comment>Confirmation message after successfully deleting a login.</comment>
</data>
<data name="Submit" xml:space="preserve">
@@ -422,7 +422,7 @@
<value>Utilize o serviço de acessibilidade do Bitwarden para autopreencher as suas credenciais entre aplicativos e a web.</value>
</data>
<data name="AutofillService" xml:space="preserve">
<value>Serviço de autopreenchimento</value>
<value>Serviço de Autopreenchimento</value>
</data>
<data name="AvoidAmbiguousCharacters" xml:space="preserve">
<value>Evitar Caracteres Ambíguos</value>
@@ -468,7 +468,7 @@
<comment>Message shown when interacting with the server</comment>
</data>
<data name="EditItem" xml:space="preserve">
<value>Editar item</value>
<value>Editar Item</value>
</data>
<data name="EnableAutomaticSyncing" xml:space="preserve">
<value>Ativar Sincronização Automática</value>
@@ -587,7 +587,7 @@
<value>A senha mestra deve ter pelo menos {0} caracteres.</value>
</data>
<data name="MinNumbers" xml:space="preserve">
<value>Números mínimos</value>
<value>Números Mínimos</value>
<comment>Minimum numeric characters for password generator settings</comment>
</data>
<data name="MinSpecial" xml:space="preserve">
@@ -651,19 +651,19 @@
<comment>Push notifications for apple products</comment>
</data>
<data name="RateTheApp" xml:space="preserve">
<value>Avalie o aplicativo</value>
<value>Avalie o Aplicativo</value>
</data>
<data name="RateTheAppDescription" xml:space="preserve">
<value>Por favor considere ajudar-nos com uma boa avaliação!</value>
</data>
<data name="RegeneratePassword" xml:space="preserve">
<value>Gerar nova senha</value>
<value>Gerar Nova Senha</value>
</data>
<data name="RetypeMasterPassword" xml:space="preserve">
<value>Digite novamente a Senha Mestra</value>
</data>
<data name="SearchVault" xml:space="preserve">
<value>Pesquisar cofre</value>
<value>Pesquisar Cofre</value>
</data>
<data name="Security" xml:space="preserve">
<value>Segurança</value>
@@ -681,7 +681,7 @@
<value>Informação do Item</value>
</data>
<data name="ItemUpdated" xml:space="preserve">
<value>Item salvo</value>
<value>Item atualizado.</value>
</data>
<data name="Submitting" xml:space="preserve">
<value>Enviando...</value>
@@ -799,7 +799,7 @@
<value>Itens Correspondentes</value>
</data>
<data name="PossibleMatchingItems" xml:space="preserve">
<value>Itens correspondentes possíveis</value>
<value>Itens Correspondentes Possíveis</value>
</data>
<data name="Search" xml:space="preserve">
<value>Pesquisar</value>
@@ -867,7 +867,7 @@
<comment>"YubiKey" is the product name and should not be translated.</comment>
</data>
<data name="AddNewAttachment" xml:space="preserve">
<value>Adicionar novo anexo</value>
<value>Adicionar Novo Anexo</value>
</data>
<data name="Attachments" xml:space="preserve">
<value>Anexos</value>
@@ -961,7 +961,7 @@ A leitura será feita automaticamente.</value>
<value>URL do Servidor da API</value>
</data>
<data name="CustomEnvironment" xml:space="preserve">
<value>Ambiente personalizado</value>
<value>Ambiente Personalizado</value>
</data>
<data name="CustomEnvironmentFooter" xml:space="preserve">
<value>Para usuários avançados. Você pode especificar a URL de base de cada serviço independentemente.</value>
@@ -978,7 +978,7 @@ A leitura será feita automaticamente.</value>
<comment>"Identity" refers to an identity server. See more context here https://en.wikipedia.org/wiki/Identity_management</comment>
</data>
<data name="SelfHostedEnvironment" xml:space="preserve">
<value>Ambiente auto-hospedado</value>
<value>Ambiente Auto-hospedado</value>
</data>
<data name="SelfHostedEnvironmentFooter" xml:space="preserve">
<value>Especifique a URL de base da sua instalação local do Bitwarden.</value>
@@ -987,25 +987,25 @@ A leitura será feita automaticamente.</value>
<value>URL do Servidor</value>
</data>
<data name="WebVaultUrl" xml:space="preserve">
<value>URL do servidor do Cofre Web</value>
<value>URL do Servidor do Cofre Web</value>
</data>
<data name="BitwardenAutofillServiceNotificationContentOld" xml:space="preserve">
<value>Toque nesta notificação para visualizar as credenciais do seu cofre.</value>
</data>
<data name="CustomFields" xml:space="preserve">
<value>Campos personalizados</value>
<value>Campos Personalizados</value>
</data>
<data name="CopyNumber" xml:space="preserve">
<value>Copiar Número</value>
</data>
<data name="CopySecurityCode" xml:space="preserve">
<value>Copiar código de segurança</value>
<value>Copiar Código de Segurança</value>
</data>
<data name="Number" xml:space="preserve">
<value>Número</value>
</data>
<data name="SecurityCode" xml:space="preserve">
<value>Código de segurança</value>
<value>Código de Segurança</value>
</data>
<data name="TypeCard" xml:space="preserve">
<value>Cartão</value>
@@ -1017,7 +1017,7 @@ A leitura será feita automaticamente.</value>
<value>Credencial</value>
</data>
<data name="TypeSecureNote" xml:space="preserve">
<value>Nota segura</value>
<value>Nota Segura</value>
</data>
<data name="Address1" xml:space="preserve">
<value>Endereço 1</value>
@@ -1038,7 +1038,7 @@ A leitura será feita automaticamente.</value>
<value>Bandeira</value>
</data>
<data name="CardholderName" xml:space="preserve">
<value>Titular do cartão</value>
<value>Titular do Cartão</value>
</data>
<data name="CityTown" xml:space="preserve">
<value>Cidade / Localidade</value>
@@ -1056,10 +1056,10 @@ A leitura será feita automaticamente.</value>
<value>Dr</value>
</data>
<data name="ExpirationMonth" xml:space="preserve">
<value>Mês de vencimento</value>
<value>Mês de Vencimento</value>
</data>
<data name="ExpirationYear" xml:space="preserve">
<value>Ano de vencimento</value>
<value>Ano de Vencimento</value>
</data>
<data name="February" xml:space="preserve">
<value>Fevereiro</value>
@@ -1384,10 +1384,10 @@ A leitura será feita automaticamente.</value>
<value>Pesquisar coleção</value>
</data>
<data name="SearchFileSends" xml:space="preserve">
<value>Pesquisar arquivo do Sends</value>
<value>Pesquisar Sends de Arquivo</value>
</data>
<data name="SearchTextSends" xml:space="preserve">
<value>Pesquisar texto do Sends</value>
<value>Pesquisar Sends de Texto</value>
</data>
<data name="SearchGroup" xml:space="preserve">
<value>Pesquisar {0}</value>
@@ -1471,10 +1471,10 @@ A leitura será feita automaticamente.</value>
<value>O Bitwarden permite que você compartilhe os itens do seu cofre com outros ao usar uma conta da organização. Você gostaria de visitar o site bitwarden.com para saber mais?</value>
</data>
<data name="ExportVault" xml:space="preserve">
<value>Exportar cofre</value>
<value>Exportar Cofre</value>
</data>
<data name="LockNow" xml:space="preserve">
<value>Bloquear agora</value>
<value>Bloquear Agora</value>
</data>
<data name="PIN" xml:space="preserve">
<value>PIN</value>
@@ -1483,7 +1483,7 @@ A leitura será feita automaticamente.</value>
<value>Desbloquear</value>
</data>
<data name="UnlockVault" xml:space="preserve">
<value>Desbloquear cofre</value>
<value>Desbloquear Cofre</value>
</data>
<data name="ThirtyMinutes" xml:space="preserve">
<value>30 minutos</value>
@@ -1592,7 +1592,7 @@ A leitura será feita automaticamente.</value>
<value>Pedir para adicionar um item se um não for encontrado no seu cofre.</value>
</data>
<data name="OnRestart" xml:space="preserve">
<value>Ao reiniciar o App</value>
<value>Ao Reiniciar o App</value>
</data>
<data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>O autopreenchimento facilita o acesso seguro ao seu cofre Bitwarden a partir de outros sites e aplicativos. Parece que você não ativou um serviço de autopreenchimento para o Bitwarden. Ative o autopreenchimento para o Bitwarden na tela "Configurações".</value>
@@ -1614,7 +1614,7 @@ A leitura será feita automaticamente.</value>
<value>Compartilhado</value>
</data>
<data name="ToggleVisibility" xml:space="preserve">
<value>Alternar visibilidade</value>
<value>Alterar Visiblidade</value>
</data>
<data name="LoginExpired" xml:space="preserve">
<value>A sua sessão expirou.</value>
@@ -1650,7 +1650,7 @@ A leitura será feita automaticamente.</value>
<value>Concedido</value>
</data>
<data name="FileFormat" xml:space="preserve">
<value>Formato do arquivo</value>
<value>Formato do Arquivo</value>
</data>
<data name="ExportVaultMasterPasswordDescription" xml:space="preserve">
<value>Digite sua senha mestra para exportar os dados do seu cofre.</value>
@@ -1768,7 +1768,7 @@ A leitura será feita automaticamente.</value>
<value>Faça o login rapidamente usando o portal de login único da sua organização. Por favor, insira o identificador da sua organização para começar.</value>
</data>
<data name="OrgIdentifier" xml:space="preserve">
<value>Identificador da organização</value>
<value>Identificador da Organização</value>
</data>
<data name="LoginSsoError" xml:space="preserve">
<value>Atualmente incapaz de acessar com SSO</value>
@@ -1826,7 +1826,7 @@ A leitura será feita automaticamente.</value>
<value>O Bitwarden precisa de atenção - Ative "Sobrepor a" em "Serviços de Autopreenchimento" nas Configurações do Bitwarden</value>
</data>
<data name="AutofillServices" xml:space="preserve">
<value>Serviços de autopreenchimento</value>
<value>Serviços de Autopreenchimento</value>
</data>
<data name="InlineAutofill" xml:space="preserve">
<value>Usar Autopreenchimento em Linha</value>
@@ -1835,7 +1835,7 @@ A leitura será feita automaticamente.</value>
<value>Usar autopreenchimento nativo se o IME selecionado (teclado) o suporta. Se sua configuração não for suportada (ou esta opção estiver desativada), será usada a sobreposição de Autopreenchimento padrão.</value>
</data>
<data name="Accessibility" xml:space="preserve">
<value>Usar acessibilidade</value>
<value>Usar Acessibilidade</value>
</data>
<data name="AccessibilityDescription" xml:space="preserve">
<value>Utilize o Serviço de Acessibilidade do Bitwarden para autopreencher as suas credenciais entre aplicativos e a web. Quando ativado, exibiremos um pop-up quando os campos de credenciais forem selecionados.</value>
@@ -1853,13 +1853,13 @@ A leitura será feita automaticamente.</value>
<value>Usar Sobrepor a</value>
</data>
<data name="DrawOverDescription" xml:space="preserve">
<value>Quando ativado, permite que o Serviço de Acessibilidade do Bitwarden exiba uma janela quando os campos de "login" são selecionados.</value>
<value>Quando ativado, permite que o Serviço de Acessibilidade do Bitwarden exiba uma janela quando os campos de login forem selecionados.</value>
</data>
<data name="DrawOverDescription2" xml:space="preserve">
<value>Se ativado, o Serviço de Acessibilidade do Bitwarden exibirá um "pop-up" quando os campos de "login" são selecionados para ajudar a preencher automaticamente suas credenciais.</value>
<value>Se ativado, o Serviço de Acessibilidade do Bitwarden exibirá um pop-up quando os campos de login forem selecionados para ajudar a preencher automaticamente suas credenciais.</value>
</data>
<data name="DrawOverDescription3" xml:space="preserve">
<value>Se ativado, a acessibilidade mostrará um "pop-up" para aumentar o Serviço de Autopreenchimento para aplicativos mais antigos que não suportam a Estrutura de Autopreenchimento do Android.</value>
<value>Se ativado, a acessibilidade mostrará um pop-up para aumentar o Serviço de Autopreenchimento para aplicativos mais antigos que não suportam a Estrutura de Autopreenchimento do Android.</value>
</data>
<data name="PersonalOwnershipSubmitError" xml:space="preserve">
<value>Devido a uma Política Empresarial, você está restrito de salvar itens para seu cofre pessoal. Altere a opção de propriedade para uma organização e escolha entre Coleções disponíveis.</value>
@@ -1915,10 +1915,10 @@ A leitura será feita automaticamente.</value>
<value>O tipo de texto não está selecionado, toque para selecionar.</value>
</data>
<data name="DeletionDate" xml:space="preserve">
<value>Data de exclusão</value>
<value>Data de Exclusão</value>
</data>
<data name="DeletionTime" xml:space="preserve">
<value>Hora da exclusão</value>
<value>Hora da Exclusão</value>
</data>
<data name="DeletionDateInfo" xml:space="preserve">
<value>O envio será eliminado permanentemente na data e hora especificadas.</value>
@@ -1928,7 +1928,7 @@ A leitura será feita automaticamente.</value>
<value>Exclusão pendente</value>
</data>
<data name="ExpirationDate" xml:space="preserve">
<value>Data de validade</value>
<value>Data de Validade</value>
</data>
<data name="ExpirationTime" xml:space="preserve">
<value>Hora da Expiração</value>
@@ -1954,14 +1954,14 @@ A leitura será feita automaticamente.</value>
<value>Contagem Atual de Acessos</value>
</data>
<data name="NewPassword" xml:space="preserve">
<value>Nova senha</value>
<value>Nova Senha</value>
</data>
<data name="PasswordInfo" xml:space="preserve">
<value>Exigir opcionalmente uma senha para os usuários acessarem este Send.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="RemovePassword" xml:space="preserve">
<value>Remover senha</value>
<value>Remover Senha</value>
</data>
<data name="AreYouSureRemoveSendPassword" xml:space="preserve">
<value>Você tem certeza que deseja remover a senha?</value>
@@ -1989,10 +1989,10 @@ A leitura será feita automaticamente.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="CopyLink" xml:space="preserve">
<value>Copiar link</value>
<value>Copiar Link</value>
</data>
<data name="ShareLink" xml:space="preserve">
<value>Compartilhar link</value>
<value>Compartilhar Link</value>
</data>
<data name="SendLink" xml:space="preserve">
<value>Link do Send</value>
@@ -2015,15 +2015,15 @@ A leitura será feita automaticamente.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SendDeleted" xml:space="preserve">
<value>Send excluído</value>
<value>O Send foi excluído.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SendUpdated" xml:space="preserve">
<value>Send atualizado</value>
<value>Send atualizado.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="NewSendCreated" xml:space="preserve">
<value>Send criado</value>
<value>Novo Send criado.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="OneDay" xml:space="preserve">
@@ -2081,28 +2081,28 @@ A leitura será feita automaticamente.</value>
<value>Esta ação é protegida, para continuar por favor reinsira a sua senha mestra para verificar a sua identidade.</value>
</data>
<data name="CaptchaRequired" xml:space="preserve">
<value>Captcha obrigatório</value>
<value>Captcha Obrigatório</value>
</data>
<data name="CaptchaFailed" xml:space="preserve">
<value>Captcha falhou. Por favor, tente novamente.</value>
<value>Captcha Errado. Por favor, tente novamente.</value>
</data>
<data name="UpdatedMasterPassword" xml:space="preserve">
<value>Senha mestra atualizada</value>
<value>Senha Mestra Atualizada</value>
</data>
<data name="UpdateMasterPassword" xml:space="preserve">
<value>Atualizar senha mestra</value>
<value>Atualizar Senha Mestra</value>
</data>
<data name="UpdateMasterPasswordWarning" xml:space="preserve">
<value>A sua senha mestra foi alterada recentemente por um administrador na sua organização. Para acessar o cofre, você precisa atualizar sua senha mestra agora. O processo desconectará você da sessão atual, exigindo que você inicie a sessão novamente. Sessões ativas em outros dispositivos podem continuar ativas por até uma hora.</value>
<value>Sua Senha Mestra foi alterada recentemente por um administrador de sua organização. Para acessar o cofre, você precisa atualizar sua Senha Mestra agora. O processo desconectará você da sessão atual, exigindo que você inicie a sessão novamente. Sessões ativas em outros dispositivos podem continuar ativas por até uma hora.</value>
</data>
<data name="UpdatingPassword" xml:space="preserve">
<value>Atualizando senha</value>
<value>Atualizando Senha</value>
</data>
<data name="UpdatePasswordError" xml:space="preserve">
<value>No momento não é possível atualizar a senha</value>
</data>
<data name="RemoveMasterPassword" xml:space="preserve">
<value>Remover senha mestra</value>
<value>Remover Senha Mestra</value>
</data>
<data name="RemoveMasterPasswordWarning" xml:space="preserve">
<value>{0} está usando o SSO com criptografia gerenciada pelo cliente. Ao continuar, isso removerá sua Senha Mestra da sua conta e exigirá o SSO para acessar.</value>
@@ -2111,7 +2111,7 @@ A leitura será feita automaticamente.</value>
<value>Se não quiser remover sua Senha Mestra, você pode sair desta organização.</value>
</data>
<data name="LeaveOrganization" xml:space="preserve">
<value>Sair da organização</value>
<value>Sair da Organização</value>
</data>
<data name="LeaveOrganizationName" xml:space="preserve">
<value>Sair de {0}?</value>
@@ -2168,7 +2168,7 @@ A leitura será feita automaticamente.</value>
<value>Alterada para a próxima conta disponível</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Conta bloqueada</value>
<value>Conta Bloqueada</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Conta desconectada com sucesso</value>
@@ -2213,7 +2213,7 @@ A leitura será feita automaticamente.</value>
<value>Verificando</value>
</data>
<data name="ResendCode" xml:space="preserve">
<value>Reenviar código</value>
<value>Reenviar Código</value>
</data>
<data name="AVerificationCodeWasSentToYourEmail" xml:space="preserve">
<value>Um código de verificação foi enviado para o seu e-mail</value>
@@ -2316,7 +2316,7 @@ selecione Adicionar TOTP para armazenar a chave de forma segura</value>
<value>Não foi possível processar o seu pedido. Por favor, tente novamente ou entre em contato conosco.</value>
</data>
<data name="AllowScreenCapture" xml:space="preserve">
<value>Permitir captura de tela</value>
<value>Permitir Captura de Tela</value>
</data>
<data name="AreYouSureYouWantToEnableScreenCapture" xml:space="preserve">
<value>Tem certeza de que deseja ativar a Captura de Tela?</value>
@@ -2471,7 +2471,7 @@ selecione Adicionar TOTP para armazenar a chave de forma segura</value>
<value>Aviso sobre o Serviço de Acessibilidade</value>
</data>
<data name="AccessibilityDisclosureText" xml:space="preserve">
<value>O Bitwarden utiliza o Serviço de Acessibilidade para procurar campos de login em aplicativos e sites, então estabelece os IDs de campo apropriados para digitar um nome de usuário e senha quando uma correspondência para o aplicativo ou site for encontrada. Não armazenamos nenhuma das informações que nos são apresentadas pelo serviço, nem fazemos qualquer tentativa de controlar quaisquer elementos na tela além da entrada de credenciais em texto.</value>
<value>O Bitwarden utiliza o Serviço de Acessibilidade para procurar campos de login em aplicativos e sites, então estabelecer os IDs de campo apropriados para digitar um nome de usuário e senha quando uma correspondência para o aplicativo ou site for encontrada. Não armazenamos nenhuma das informações que nos são apresentadas pelo serviço nem fazemos qualquer tentativa de controlar quaisquer elementos na tela além da entrada de credenciais em texto.</value>
</data>
<data name="Accept" xml:space="preserve">
<value>Aceitar</value>
@@ -2629,22 +2629,22 @@ Você deseja mudar para esta conta?</value>
<value>Senha mestra atual</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>Conectado!</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>Aprovar com meu outro dispositivo</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>Solicitar aprovação do administrador</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Aprovar com senha mestra</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Desativar usando um dispositivo público</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Lembrar deste dispositivo</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Chave de acesso</value>
@@ -2687,22 +2687,22 @@ Você deseja mudar para esta conta?</value>
<value>Token de API inválido</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>Aprovação do administrador necessária</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>Seu pedido foi enviado para seu administrador.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>Será notificado assim que for aprovado. </value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Problemas para acessar?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Entrando como {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>A ação ao acabar o tempo do Cofre mudada para encerrar a sessão</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>Este item não pode ser compartilhado com a organização porque já existe um com a mesma senha.</value>
@@ -2751,13 +2751,13 @@ Você deseja mudar para esta conta?</value>
<value>Não é possível editar várias URIs de uma vez</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>Login aprovado</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>Fazer login com o dispositivo deve ser configurado nas configurações do aplicativo Bitwarden. Precisa de outra opção?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Fazer login com dispositivo</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Entrando em</value>

View File

@@ -954,9 +954,6 @@ Scanning will happen automatically.</value>
<data name="UpdateKey" xml:space="preserve">
<value>You cannot use this feature until you update your encryption key.</value>
</data>
<data name="EncryptionKeyMigrationRequiredDescriptionLong" xml:space="preserve">
<value>Encryption key migration required. Please login through the web vault to update your encryption key.</value>
</data>
<data name="LearnMore" xml:space="preserve">
<value>Learn more</value>
</data>

View File

@@ -1471,7 +1471,7 @@
<value>Bitwarden позволяет делиться элементами вашего хранилища с другими пользователями, используя аккаунт организации. Хотите посетить сайт bitwarden.com, чтобы узнать больше?</value>
</data>
<data name="ExportVault" xml:space="preserve">
<value>Экспорт хранилища</value>
<value>Экспортировать хранилище</value>
</data>
<data name="LockNow" xml:space="preserve">
<value>Заблокировать</value>
@@ -2511,7 +2511,7 @@
<value>На ваше устройство отправлено уведомление.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Убедитесь, что ваше хранилище разблокировано и фраза отпечатка совпадает на другом устройстве.</value>
<value>Убедитесь, что ваше хранилище разблокировано и фраза отпечатка пальца совпадает на другом устройстве.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Отправить уведомление повторно</value>
@@ -2577,7 +2577,7 @@
<value>Сильный</value>
</data>
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
<value>Проверять известные случаи утечки данных для этого пароля</value>
<value>Проверьте известные случаи утечки данных для этого пароля</value>
</data>
<data name="ExposedMasterPassword" xml:space="preserve">
<value>Мастер-пароль скомпрометирован</value>
@@ -2622,7 +2622,7 @@
<value>Регион</value>
</data>
<data name="UpdateWeakMasterPasswordWarning" xml:space="preserve">
<value>Ваш мастер-пароль не соответствует требованиям политики вашей организации. Для доступа к хранилищу вы должны обновить свой мастер-пароль прямо сейчас. При этом текущий сеанс будет завершен и потребуется повторная авторизация. Сеансы на других устройствах могут оставаться активными в течение часа.</value>
<value>Ваш мастер-пароль не соответствует требованиям политики вашей организации. Для доступа к хранилищу вы должны обновить свой мастер-пароль прямо сейчас. При этом текущая сессия будет завершена и потребуется повторная авторизация. Сессии на других устройствах могут оставаться активными в течение часа.</value>
</data>
<data name="CurrentMasterPassword" xml:space="preserve">
<value>Текущий мастер-пароль</value>
@@ -2677,7 +2677,7 @@
<value>Помощь по повторному запросу мастер-пароля</value>
</data>
<data name="UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve" xml:space="preserve">
<value>Разблокировка может завершиться ошибкой из-за нехватки памяти. Уменьшите настройки памяти KDF или настройте биометрическую разблокировку для решения этой проблемы.</value>
<value>Unlocking may fail due to insufficient memory. Decrease your KDF memory settings or set up biometric unlock to resolve.</value>
</data>
<data name="InvalidAPIKey" xml:space="preserve">
<value>Некорректный ключ API</value>
@@ -2756,7 +2756,7 @@
<value>Вход с устройства должен быть настроен в мобильном приложении Bitwarden. Нужен другой вариант?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Войти с помощью устройства</value>
<value>Войти с устройства</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Войти на</value>

View File

@@ -2628,22 +2628,22 @@ Chcete prepnúť na toto konto?</value>
<value>Súčasné hlavné heslo</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>Prihlásený!</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>Schváliť pomocou môjho druhého zariadenia</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>Žiadosť o schválenie správcom</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Schváliť pomocou hlavného hesla</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Vypnúť pomocou verejného zariadenia</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Zapamätať si toto zariadenie</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Prístupový kľúč</value>
@@ -2686,22 +2686,22 @@ Chcete prepnúť na toto konto?</value>
<value>Neplatný token API</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>Vyžaduje sa schválenie správcom</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>Vaša žiadosť bola odoslaná správcovi.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>Po schválení budete informovaný. </value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Máte problémy s prihlásením?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Prihlasujete sa ako {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Akcia pri vypršaní času pre trezor zmenená na odhlásenie</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>Túto položku nemožno zdieľať s organizáciou, pretože už existuje jedna s rovnakým prístupovým kľúčom.</value>
@@ -2750,13 +2750,13 @@ Chcete prepnúť na toto konto?</value>
<value>Nie je možné upravovať viacero URI naraz</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>Schválené prihlásenie</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>Prihlásenie pomocou zariadenia musí byť nastavené v nastaveniach aplikácie Bitwarden. Potrebujete inú možnosť?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Prihlásiť pomocou zariadenia</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Prihlásenie na</value>

View File

@@ -2630,22 +2630,22 @@
<value>Тренутна главна лозинка</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>Пријављено!</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>Одобри са мојим другим уређајем</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>Затражити одобрење администратора</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Одобрити са главном лозинком</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Искључите ако се користи јавни уређај</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Запамти овај уређај</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Passkey</value>
@@ -2688,22 +2688,22 @@
<value>Неисправан API токен</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>Захтевано је одобрење администратора</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>Ваш захтев је послат вашем администратору.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>Бићете обавештени када буде одобрено. </value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Имате проблема са пријављивањем?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Пријављивање као {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Радња временског ограничења сефа је промењена за одјављивање</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>This item cannot be shared with the organization because there is one already with the same passkey.</value>
@@ -2752,13 +2752,13 @@
<value>Не може да се уреди истовремено више адресе</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>Пријава је одобрена</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>Пријава помоћу уређаја мора бити подешена у подешавањима Bitwarden апликације. Потребна је друга опција?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Пријавите се са уређајем</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Logging in on</value>

View File

@@ -2642,10 +2642,10 @@ Vill du byta till detta konto?</value>
<value>Godkänn med huvudlösenord</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Stäng av med en offentlig enhet</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Kom ihåg denna enhet</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Passkey</value>
@@ -2697,7 +2697,7 @@ Vill du byta till detta konto?</value>
<value>Du kommer att meddelas vid godkännande. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Problem med att logga in?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Loggar in som {0}</value>

View File

@@ -2693,13 +2693,13 @@
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>ஏற்கப்பட்ட பின் அறிவிக்கப்படுவீர். </value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>{0} ஆக உள்நுழைகிறது</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Vault timeout action changed to log out</value>
@@ -2751,13 +2751,13 @@
<value>பல உரலிகளை ஒரே நேரத்தில் திருத்த முடியாது</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>உள்நுழைவு ஏற்கப்பட்டது</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>சாதனத்துடன் உள்நுழை</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>இதில் உள்நுழைகிறது</value>

View File

@@ -2627,22 +2627,22 @@ Bu hesaba geçmek ister misiniz?</value>
<value>Mevcut ana parola</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>Oturum açıldı!</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>Diğer cihazımla onayla</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>Yönetici onayı iste</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Ana parola ile onayla</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Herkese açık bir cihaz kullanarak kapat</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Bu cihazı hatırla</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Şifre anahtarı</value>
@@ -2685,22 +2685,22 @@ Bu hesaba geçmek ister misiniz?</value>
<value>Geçersiz API token'ı</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>Yönetici onayı istendi</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>İsteğiniz yöneticinize gönderildi.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>Onaylandıktan sonra bilgilendirileceksiniz. </value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Giriş yaparken sorun mu yaşıyorsunuz?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>{0} olarak oturum açılıyor</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Kasa zaman aşımı eylemi oturumu kapatmak için değiştirildi</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>Aynı şifre anahtarına sahip başka bir kayıt olduğu için bu kaydı kuruluşunuzla paylaşamazsınız.</value>
@@ -2749,13 +2749,13 @@ Bu hesaba geçmek ister misiniz?</value>
<value>Aynı anda birden fazla URl düzenlenemez</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>Giriş onaylandı</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>Cihazla oturum aç, Bitwarden uygulamasının ayarlarında ayarlanmalıdır. Başka bir seçeneğe mi ihtiyacınız var?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Cihazla giriş yap</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Logging in on</value>

View File

@@ -724,7 +724,7 @@
<value>Код підтвердження</value>
</data>
<data name="ViewItem" xml:space="preserve">
<value>Переглянути запис</value>
<value>Перегляд запису</value>
</data>
<data name="WebVault" xml:space="preserve">
<value>Веб сховище Bitwarden</value>
@@ -790,7 +790,7 @@
<value>Автозаповнення</value>
</data>
<data name="AutofillOrView" xml:space="preserve">
<value>Автоматично заповнити чи переглянути запис?</value>
<value>Автоматичне заповнення чи перегляд запису?</value>
</data>
<data name="BitwardenAutofillServiceMatchConfirm" xml:space="preserve">
<value>Ви дійсно хочете використати цей запис для автоматичного заповнення? Він не повністю відповідає "{0}".</value>
@@ -2628,22 +2628,22 @@
<value>Поточний головний пароль</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>Ви увійшли!</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>Затвердити з моїм іншим пристроєм</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>Запит підтвердження адміністратора</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>Затвердити з головним паролем</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>Вимкнути використання загальнодоступного пристрою</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>Запам'ятати цей пристрій</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>Ключ доступу</value>
@@ -2686,22 +2686,22 @@
<value>Недійсний токен API</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>Запитано затвердження адміністратором</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>Ваш запит відправлено адміністратору.</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>Ви отримаєте сповіщення після затвердження. </value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>Проблема під час входу?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Вхід у систему як {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Час очікування сховища змінено на вихід</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>Цей запис не можна поширити для організації, оскільки там вже є запис із таким самим ключем доступу.</value>
@@ -2750,13 +2750,13 @@
<value>Неможливо редагувати кілька URI одночасно</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>Вхід затверджено</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>Потрібно увімкнути схвалення запитів на вхід у налаштуваннях програми Bitwarden. Потрібен інший варіант?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>Увійти з пристроєм</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>Увійти на</value>

View File

@@ -2628,22 +2628,22 @@
<value>当前主密码</value>
</data>
<data name="LoggedIn" xml:space="preserve">
<value>已登录!</value>
<value>Logged in!</value>
</data>
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
<value>通过我的其他设备批准</value>
<value>Approve with my other device</value>
</data>
<data name="RequestAdminApproval" xml:space="preserve">
<value>请求管理员批准</value>
<value>Request admin approval</value>
</data>
<data name="ApproveWithMasterPassword" xml:space="preserve">
<value>使用主密码批准</value>
<value>Approve with master password</value>
</data>
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
<value>不允许使用公共设备</value>
<value>Turn off using a public device</value>
</data>
<data name="RememberThisDevice" xml:space="preserve">
<value>记住此设备</value>
<value>Remember this device</value>
</data>
<data name="Passkey" xml:space="preserve">
<value>通行密钥</value>
@@ -2659,13 +2659,13 @@
<value>应用</value>
</data>
<data name="YouCannotEditPasskeyApplicationBecauseItWouldInvalidateThePasskey" xml:space="preserve">
<value>您不能编辑通行密钥应用程序,因为这会使通行密钥失效</value>
<value>您不能编辑通行密钥应用程序,这会使通行密钥失效</value>
</data>
<data name="PasskeyWillNotBeCopied" xml:space="preserve">
<value>通行密钥不会被复制</value>
</data>
<data name="ThePasskeyWillNotBeCopiedToTheClonedItemDoYouWantToContinueCloningThisItem" xml:space="preserve">
<value>通行密钥将不会复制到克隆的项目。要继续克隆这个项目吗?</value>
<value>通行密钥将不会复制到克隆的项目。要继续克隆这个项目吗?</value>
</data>
<data name="CopyApplication" xml:space="preserve">
<value>复制应用</value>
@@ -2677,7 +2677,7 @@
<value>主密码重新询问帮助</value>
</data>
<data name="UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve" xml:space="preserve">
<value>由于内存不足,解锁可能会失败。请减少您的 KDF 内存设置或设置生物识别解锁来解决此问题。</value>
<value>Unlocking may fail due to insufficient memory. Decrease your KDF memory settings or set up biometric unlock to resolve.</value>
</data>
<data name="InvalidAPIKey" xml:space="preserve">
<value>无效的 API 密钥</value>
@@ -2686,22 +2686,22 @@
<value>无效的 API 令牌</value>
</data>
<data name="AdminApprovalRequested" xml:space="preserve">
<value>已请求管理员批准</value>
<value>Admin approval requested</value>
</data>
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
<value>您的请求已发送给您的管理员。</value>
<value>Your request has been sent to your admin.</value>
</data>
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
<value>批准后,您将收到通知。 </value>
<value>You will be notified once approved. </value>
</data>
<data name="TroubleLoggingIn" xml:space="preserve">
<value>登录遇到问题?</value>
<value>Trouble logging in?</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>正登录为 {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>密码库超时动作已更改为注销</value>
<value>Vault timeout action changed to log out</value>
</data>
<data name="ThisItemCannotBeSharedWithTheOrganizationBecauseThereIsOneAlreadyWithTheSamePasskey" xml:space="preserve">
<value>无法与组织共享此项目,因为已经有一个项目具有相同的通行密钥。</value>
@@ -2750,13 +2750,13 @@
<value>一次不能编辑多个 URI</value>
</data>
<data name="LoginApproved" xml:space="preserve">
<value>登录已批准</value>
<value>Login approved</value>
</data>
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
<value>设备登录必须在 Bitwarden 应用程序的设置中启用。需要其他登录选项吗?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data>
<data name="LogInWithDevice" xml:space="preserve">
<value>设备登录</value>
<value>Log in with device</value>
</data>
<data name="LoggingInOn" xml:space="preserve">
<value>登录到</value>

View File

@@ -2656,7 +2656,7 @@
<comment>To state the date in which the cipher was created: Created 03/21/2023</comment>
</data>
<data name="Application" xml:space="preserve">
<value>應用程式</value>
<value>Application</value>
</data>
<data name="YouCannotEditPasskeyApplicationBecauseItWouldInvalidateThePasskey" xml:space="preserve">
<value>You cannot edit passkey application because it would invalidate the passkey</value>

View File

@@ -1,7 +1,6 @@
using System.Threading.Tasks;
using Bit.App.Abstractions;
using Bit.App.Resources;
using Bit.App.Utilities;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
@@ -11,13 +10,11 @@ namespace Bit.App.Services
{
private readonly IPlatformUtilsService _platformUtilsService;
private readonly ICryptoService _cryptoService;
private readonly IStateService _stateService;
public MobilePasswordRepromptService(IPlatformUtilsService platformUtilsService, ICryptoService cryptoService, IStateService stateService)
public MobilePasswordRepromptService(IPlatformUtilsService platformUtilsService, ICryptoService cryptoService)
{
_platformUtilsService = platformUtilsService;
_cryptoService = cryptoService;
_stateService = stateService;
}
public string[] ProtectedFields { get; } = { "LoginTotp", "LoginPassword", "H_FieldValue", "CardNumber", "CardCode" };
@@ -45,22 +42,7 @@ namespace Bit.App.Services
return false;
};
var masterKey = await _cryptoService.GetOrDeriveMasterKeyAsync(password);
var passwordValid = await _cryptoService.CompareAndUpdateKeyHashAsync(password, masterKey);
if (passwordValid)
{
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
var userKey = await _cryptoService.DecryptUserKeyWithMasterKeyAsync(masterKey);
await _cryptoService.SetMasterKeyAsync(masterKey);
var hasKey = await _cryptoService.HasUserKeyAsync();
if (!hasKey)
{
await _cryptoService.SetUserKeyAsync(userKey);
}
}
return passwordValid;
return await _cryptoService.CompareAndUpdateKeyHashAsync(password, null);
}
private async Task<bool> ShouldByPassMasterPasswordRepromptAsync()

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bit.Core;
using Bit.Core.Abstractions;
@@ -12,16 +11,27 @@ namespace Bit.App.Services
private readonly IStorageService _preferencesStorageService;
private readonly IStorageService _liteDbStorageService;
private readonly HashSet<string> _liteDbStorageKeys = new HashSet<string>
private readonly HashSet<string> _preferenceStorageKeys = new HashSet<string>
{
Constants.EventCollectionKey,
Constants.CiphersKey(""),
Constants.FoldersKey(""),
Constants.CollectionsKey(""),
Constants.CiphersLocalDataKey(""),
Constants.SendsKey(""),
Constants.PassGenHistoryKey(""),
Constants.SettingsKey(""),
Constants.StateVersionKey,
Constants.PreAuthEnvironmentUrlsKey,
Constants.AutofillTileAdded,
Constants.AddSitePromptShownKey,
Constants.PushInitialPromptShownKey,
Constants.LastFileCacheClearKey,
Constants.PushRegisteredTokenKey,
Constants.LastBuildKey,
Constants.ClearCiphersCacheKey,
Constants.BiometricIntegritySourceKey,
Constants.iOSExtensionActiveUserIdKey,
Constants.iOSAutoFillClearCiphersCacheKey,
Constants.iOSAutoFillBiometricIntegritySourceKey,
Constants.iOSExtensionClearCiphersCacheKey,
Constants.iOSExtensionBiometricIntegritySourceKey,
Constants.iOSShareExtensionClearCiphersCacheKey,
Constants.iOSShareExtensionBiometricIntegritySourceKey,
Constants.RememberedEmailKey,
Constants.RememberedOrgIdentifierKey
};
public MobileStorageService(
@@ -34,30 +44,29 @@ namespace Bit.App.Services
public async Task<T> GetAsync<T>(string key)
{
if (IsLiteDbKey(key))
if (_preferenceStorageKeys.Contains(key))
{
return await _liteDbStorageService.GetAsync<T>(key);
return await _preferencesStorageService.GetAsync<T>(key);
}
return await _preferencesStorageService.GetAsync<T>(key) ?? await TryMigrateLiteDbToPrefsAsync<T>(key);
return await _liteDbStorageService.GetAsync<T>(key);
}
public Task SaveAsync<T>(string key, T obj)
{
if (IsLiteDbKey(key))
if (_preferenceStorageKeys.Contains(key))
{
return _liteDbStorageService.SaveAsync(key, obj);
return _preferencesStorageService.SaveAsync(key, obj);
}
return _preferencesStorageService.SaveAsync(key, obj);
return _liteDbStorageService.SaveAsync(key, obj);
}
public Task RemoveAsync(string key)
{
if (IsLiteDbKey(key))
if (_preferenceStorageKeys.Contains(key))
{
return _liteDbStorageService.RemoveAsync(key);
return _preferencesStorageService.RemoveAsync(key);
}
return _preferencesStorageService.RemoveAsync(key);
return _liteDbStorageService.RemoveAsync(key);
}
public void Dispose()
@@ -71,25 +80,5 @@ namespace Bit.App.Services
disposablePrefService.Dispose();
}
}
// Helpers
private bool IsLiteDbKey(string key)
{
return _liteDbStorageKeys.Any(key.StartsWith) ||
_liteDbStorageKeys.Contains(key);
}
private async Task<T> TryMigrateLiteDbToPrefsAsync<T>(string key)
{
var currentValue = await _liteDbStorageService.GetAsync<T>(key);
if (currentValue != null)
{
await _preferencesStorageService.SaveAsync(key, currentValue);
await _liteDbStorageService.RemoveAsync(key);
}
return currentValue;
}
}
}

View File

@@ -5,5 +5,6 @@ namespace Bit.Core.Abstractions
public interface IAppIdService
{
Task<string> GetAppIdAsync();
Task<string> GetAnonymousAppIdAsync();
}
}

View File

@@ -15,7 +15,6 @@ namespace Bit.Core.Abstractions
string Code { get; set; }
string CodeVerifier { get; set; }
string SsoRedirectUrl { get; set; }
string SsoEmail2FaSessionToken { get; set; }
TwoFactorProviderType? SelectedTwoFactorProviderType { get; set; }
Dictionary<TwoFactorProviderType, TwoFactorProvider> TwoFactorProviders { get; set; }
Dictionary<TwoFactorProviderType, Dictionary<string, object>> TwoFactorProvidersData { get; set; }

View File

@@ -35,6 +35,7 @@ namespace Bit.Core.Abstractions
Task ReplaceAsync(Dictionary<string, CipherData> ciphers);
Task<Cipher> SaveAttachmentRawWithServerAsync(Cipher cipher, string filename, byte[] data);
Task SaveCollectionsWithServerAsync(Cipher cipher);
Task SaveNeverDomainAsync(string domain);
Task SaveWithServerAsync(Cipher cipher);
Task<ShareWithServerError> ShareWithServerAsync(CipherView cipher, string organizationId, HashSet<string> collectionIds);
Task UpdateLastUsedDateAsync(string id);

View File

@@ -13,7 +13,6 @@ namespace Bit.Core.Abstractions
Task RefreshKeysAsync();
Task SetUserKeyAsync(UserKey userKey, string userId = null);
Task<UserKey> GetUserKeyAsync(string userId = null);
Task<bool> IsLegacyUserAsync(MasterKey masterKey = null, string userId = null);
Task<UserKey> GetUserKeyWithLegacySupportAsync(string userId = null);
Task<bool> HasUserKeyAsync(string userId = null);
Task<bool> HasEncryptedUserKeyAsync(string userId = null);
@@ -61,6 +60,5 @@ namespace Bit.Core.Abstractions
Task<EncString> EncryptAsync(string plainValue, SymmetricCryptoKey key = null);
Task<EncByteArray> EncryptToBytesAsync(byte[] plainValue, SymmetricCryptoKey key = null);
Task<UserKey> DecryptAndMigrateOldPinKeyAsync(bool masterPasswordOnRestart, string pin, string email, KdfConfig kdfConfig, EncString oldPinKey);
Task<MasterKey> GetOrDeriveMasterKeyAsync(string password, string userId = null);
}
}

View File

@@ -92,12 +92,14 @@ namespace Bit.Core.Abstractions
Task SetInlineAutofillEnabledAsync(bool? value, string userId = null);
Task<bool?> GetAutofillDisableSavePromptAsync(string userId = null);
Task SetAutofillDisableSavePromptAsync(bool? value, string userId = null);
Task<Dictionary<string, Dictionary<string, object>>> GetCiphersLocalDataAsync(string userId = null);
Task SetCiphersLocalDataAsync(Dictionary<string, Dictionary<string, object>> value, string userId = null);
Task<Dictionary<string, Dictionary<string, object>>> GetLocalDataAsync(string userId = null);
Task SetLocalDataAsync(Dictionary<string, Dictionary<string, object>> value, string userId = null);
Task<Dictionary<string, CipherData>> GetEncryptedCiphersAsync(string userId = null);
Task SetEncryptedCiphersAsync(Dictionary<string, CipherData> value, string userId = null);
Task<int?> GetDefaultUriMatchAsync(string userId = null);
Task SetDefaultUriMatchAsync(int? value, string userId = null);
Task<HashSet<string>> GetNeverDomainsAsync(string userId = null);
Task SetNeverDomainsAsync(HashSet<string> value, string userId = null);
Task<int?> GetClearClipboardAsync(string userId = null);
Task SetClearClipboardAsync(int? value, string userId = null);
Task<Dictionary<string, CollectionData>> GetEncryptedCollectionsAsync(string userId = null);

View File

@@ -9,12 +9,11 @@ namespace Bit.Core
public const string AndroidAppProtocol = "androidapp://";
public const string iOSAppProtocol = "iosapp://";
public const string DefaultUsernameGenerated = "-";
public const string AppIdKey = "appId";
public const string StateVersionKey = "stateVersion";
public const string StateKey = "state";
public const string PreAuthEnvironmentUrlsKey = "preAuthEnvironmentUrls";
public const string LastFileCacheClearKey = "lastFileCacheClear";
public const string AutofillTileAddedKey = "autofillTileAdded";
public const string AutofillTileAdded = "autofillTileAdded";
public const string PushRegisteredTokenKey = "pushRegisteredToken";
public const string PushInitialPromptShownKey = "pushInitialPromptShown";
public const string PushInstallationRegistrationErrorKey = "pushInstallationRegistrationError";
@@ -87,13 +86,14 @@ namespace Bit.Core
public static string VaultTimeoutKey(string userId) => $"vaultTimeout_{userId}";
public static string VaultTimeoutActionKey(string userId) => $"vaultTimeoutAction_{userId}";
public static string MasterKeyEncryptedUserKeyKey(string userId) => $"masterKeyEncryptedUserKey_{userId}";
public static string UserKeyAutoUnlockKey(string userId) => $"userKeyAutoUnlock_{userId}";
public static string UserKeyBiometricUnlockKey(string userId) => $"userKeyBiometricUnlock_{userId}";
public static string UserKeyAutoUnlockKey(string userId) => $"autoUnlock_{userId}";
public static string UserKeyBiometricUnlockKey(string userId) => $"biometricUnlock_{userId}";
public static string CiphersKey(string userId) => $"ciphers_{userId}";
public static string FoldersKey(string userId) => $"folders_{userId}";
public static string CollectionsKey(string userId) => $"collections_{userId}";
public static string OrganizationsKey(string userId) => $"organizations_{userId}";
public static string CiphersLocalDataKey(string userId) => $"ciphersLocalData_{userId}";
public static string LocalDataKey(string userId) => $"ciphersLocalData_{userId}";
public static string NeverDomainsKey(string userId) => $"neverDomains_{userId}";
public static string SendsKey(string userId) => $"sends_{userId}";
public static string PoliciesKey(string userId) => $"policies_{userId}";
public static string EncOrgKeysKey(string userId) => $"encOrgKeys_{userId}";

View File

@@ -1,11 +0,0 @@
using System;
namespace Bit.Core.Exceptions
{
public class LegacyUserException : Exception
{
public LegacyUserException()
: base("Legacy users must migrate on web vault.")
{
}
}
}

View File

@@ -13,7 +13,6 @@ namespace Bit.Core.Models.Domain
[Obsolete("Use AccountDecryptionOptions to determine if the user does not have a MP")]
public bool ResetMasterPassword { get; set; }
public bool ForcePasswordReset { get; set; }
public bool RequiresEncryptionKeyMigration { get; set; }
public Dictionary<TwoFactorProviderType, Dictionary<string, object>> TwoFactorProviders { get; set; }
}
}

View File

@@ -5,6 +5,5 @@
public string Email { get; set; }
public string MasterPasswordHash { get; set; }
public string DeviceIdentifier { get; set; }
public string SsoEmail2FaSessionToken { get; set; }
}
}

View File

@@ -12,7 +12,5 @@ namespace Bit.Core.Models.Response
public MasterPasswordPolicyOptions MasterPasswordPolicy { get; set; }
[JsonProperty("CaptchaBypassToken")]
public string CaptchaToken { get; set; }
public string SsoEmail2faSessionToken { get; set; }
public string Email { get; set; }
}
}

View File

@@ -15,7 +15,12 @@ namespace Bit.Core.Services
public Task<string> GetAppIdAsync()
{
return MakeAndGetAppIdAsync(Constants.AppIdKey);
return MakeAndGetAppIdAsync("appId");
}
public Task<string> GetAnonymousAppIdAsync()
{
return MakeAndGetAppIdAsync("anonymousAppId");
}
private async Task<string> MakeAndGetAppIdAsync(string key)

View File

@@ -124,7 +124,6 @@ namespace Bit.Core.Services
public string Code { get; set; }
public string CodeVerifier { get; set; }
public string SsoRedirectUrl { get; set; }
public string SsoEmail2FaSessionToken { get; set; }
public Dictionary<TwoFactorProviderType, TwoFactorProvider> TwoFactorProviders { get; set; }
public Dictionary<TwoFactorProviderType, Dictionary<string, object>> TwoFactorProvidersData { get; set; }
public TwoFactorProviderType? SelectedTwoFactorProviderType { get; set; }
@@ -458,36 +457,24 @@ namespace Bit.Core.Services
if (result.TwoFactor)
{
// Two factor required.
Email = response.TwoFactorResponse.Email ?? email;
Email = email;
MasterPasswordHash = hashedPassword;
LocalMasterPasswordHash = localHashedPassword;
AuthRequestId = authRequestId;
Code = code;
CodeVerifier = codeVerifier;
SsoRedirectUrl = redirectUrl;
SsoEmail2FaSessionToken = response.TwoFactorResponse.SsoEmail2faSessionToken;
_masterKey = _setCryptoKeys ? masterKey : null;
_userKey = userKey2FA;
TwoFactorProvidersData = response.TwoFactorResponse.TwoFactorProviders2;
result.TwoFactorProviders = response.TwoFactorResponse.TwoFactorProviders2;
CaptchaToken = response.TwoFactorResponse.CaptchaToken;
_masterPasswordPolicy = response.TwoFactorResponse.MasterPasswordPolicy;
await _tokenService.ClearTwoFactorTokenAsync(Email);
await _tokenService.ClearTwoFactorTokenAsync(email);
return result;
}
var tokenResponse = response.TokenResponse;
if (localHashedPassword != null && tokenResponse.Key == null)
{
// Only check for legacy if there is no key on token
if (await _cryptoService.IsLegacyUserAsync(masterKey))
{
// Legacy users must migrate on web vault;
result.RequiresEncryptionKeyMigration = true;
return result;
}
}
result.ResetMasterPassword = tokenResponse.ResetMasterPassword;
result.ForcePasswordReset = tokenResponse.ForcePasswordReset;
_masterPasswordPolicy = tokenResponse.MasterPasswordPolicy;

View File

@@ -208,7 +208,7 @@ namespace Bit.Core.Services
public async Task<Cipher> GetAsync(string id)
{
var localData = await _stateService.GetCiphersLocalDataAsync();
var localData = await _stateService.GetLocalDataAsync();
var ciphers = await _stateService.GetEncryptedCiphersAsync();
if (!ciphers?.ContainsKey(id) ?? true)
{
@@ -220,7 +220,7 @@ namespace Bit.Core.Services
public async Task<List<Cipher>> GetAllAsync()
{
var localData = await _stateService.GetCiphersLocalDataAsync();
var localData = await _stateService.GetLocalDataAsync();
var ciphers = await _stateService.GetEncryptedCiphersAsync();
var response = ciphers?.Select(c => new Cipher(c.Value, false,
localData?.ContainsKey(c.Key) ?? false ? localData[c.Key] : null));
@@ -458,7 +458,7 @@ namespace Bit.Core.Services
public async Task UpdateLastUsedDateAsync(string id)
{
var ciphersLocalData = await _stateService.GetCiphersLocalDataAsync();
var ciphersLocalData = await _stateService.GetLocalDataAsync();
if (ciphersLocalData == null)
{
ciphersLocalData = new Dictionary<string, Dictionary<string, object>>();
@@ -476,7 +476,7 @@ namespace Bit.Core.Services
ciphersLocalData[id].Add("lastUsedDate", DateTime.UtcNow);
}
await _stateService.SetCiphersLocalDataAsync(ciphersLocalData);
await _stateService.SetLocalDataAsync(ciphersLocalData);
// Update cache
if (DecryptedCipherCache == null)
{
@@ -489,6 +489,21 @@ namespace Bit.Core.Services
}
}
public async Task SaveNeverDomainAsync(string domain)
{
if (string.IsNullOrWhiteSpace(domain))
{
return;
}
var domains = await _stateService.GetNeverDomainsAsync();
if (domains == null)
{
domains = new HashSet<string>();
}
domains.Add(domain);
await _stateService.SetNeverDomainsAsync(domains);
}
public async Task SaveWithServerAsync(Cipher cipher)
{
CipherResponse response;

View File

@@ -62,16 +62,6 @@ namespace Bit.Core.Services
return _stateService.GetUserKeyAsync(userId);
}
public async Task<bool> IsLegacyUserAsync(MasterKey masterKey = null, string userId = null)
{
masterKey ??= await GetMasterKeyAsync(userId);
if (masterKey == null)
{
return false;
}
return await ValidateUserKeyAsync(new UserKey(masterKey.Key));
}
public async Task<UserKey> GetUserKeyWithLegacySupportAsync(string userId = null)
{
var userKey = await GetUserKeyAsync(userId);
@@ -710,15 +700,6 @@ namespace Bit.Core.Services
return new EncByteArray(encBytes);
}
public async Task<MasterKey> GetOrDeriveMasterKeyAsync(string password, string userId = null)
{
var masterKey = await GetMasterKeyAsync(userId);
return masterKey ?? await this.MakeMasterKeyAsync(
password,
await _stateService.GetEmailAsync(userId),
await _stateService.GetActiveUserCustomDataAsync(a => new KdfConfig(a?.Profile)));
}
// --HELPER METHODS--
private async Task StoreAdditionalKeysAsync(UserKey userKey, string userId = null)
@@ -1007,31 +988,6 @@ namespace Bit.Core.Services
return keyCreator(key);
}
private async Task<bool> ValidateUserKeyAsync(UserKey key, string userId = null)
{
if (key == null)
{
return false;
}
try
{
var encPrivateKey = await _stateService.GetPrivateKeyEncryptedAsync(userId);
if (encPrivateKey == null)
{
return false;
}
var privateKey = await DecryptToBytesAsync(new EncString(encPrivateKey), key);
await _cryptoFunctionService.RsaExtractPublicKeyAsync(privateKey);
return true;
}
catch
{
return false;
}
}
private class EncryptedObject
{
public byte[] Iv { get; set; }
@@ -1054,15 +1010,7 @@ namespace Bit.Core.Services
// Decrypt
var masterKey = new MasterKey(Convert.FromBase64String(oldKey));
if (await IsLegacyUserAsync(masterKey, userId))
{
throw new LegacyUserException();
}
var encryptedUserKey = await _stateService.GetEncKeyEncryptedAsync(userId);
if (encryptedUserKey == null)
{
return;
}
var userKey = await DecryptUserKeyWithMasterKeyAsync(
masterKey,
new EncString(encryptedUserKey),
@@ -1097,10 +1045,6 @@ namespace Bit.Core.Services
kdfConfig,
oldPinKey
);
if (await IsLegacyUserAsync(masterKey))
{
throw new LegacyUserException();
}
var encUserKey = await _stateService.GetEncKeyEncryptedAsync();
var userKey = await DecryptUserKeyWithMasterKeyAsync(
masterKey,
@@ -1126,11 +1070,8 @@ namespace Bit.Core.Services
var encPin = await EncryptAsync(pin, userKey);
await _stateService.SetProtectedPinAsync(encPin.EncryptedString);
}
// Clear old key only if not needed for bio/auto migration
if (await _stateService.GetKeyEncryptedAsync() != null)
{
await _stateService.SetEncKeyEncryptedAsync(null);
}
// Clear old key
await _stateService.SetEncKeyEncryptedAsync(null);
return userKey;
}

View File

@@ -13,7 +13,7 @@ namespace Bit.Core.Services
{
public class StateMigrationService : IStateMigrationService
{
private const int StateVersion = 6;
private const int StateVersion = 5;
private readonly DeviceType _deviceType;
private readonly IStorageService _preferencesStorageService;
@@ -80,12 +80,9 @@ namespace Bit.Core.Services
goto case 3;
case 3:
await MigrateFrom3To4Async();
goto case 4;
break;
case 4:
await MigrateFrom4To5Async();
goto case 5;
case 5:
await MigrateFrom5To6Async();
break;
}
}
@@ -547,296 +544,6 @@ namespace Bit.Core.Services
#endregion
#region v5 to v6 Migration
private async Task MigrateFrom5To6Async()
{
// global data
await MoveToPrefsAsync<string>(V6Keys.AppIdKey);
await MoveToPrefsAsync<bool?>(V6Keys.DisableFaviconKey);
await MoveToPrefsAsync<string>(V6Keys.ThemeKey);
await MoveToPrefsAsync<string>(V6Keys.AutoDarkThemeKey);
await MoveToPrefsAsync<V6Keys.PasswordlessRequestNotification>(V6Keys.PasswordlessLoginNotificationKey);
await MoveToPrefsAsync<string>(V6Keys.PreLoginEmailKey);
await MoveToPrefsAsync<bool?>(V6Keys.LastUserShouldConnectToWatchKey);
await MoveToPrefsAsync<string>(V6Keys.PushInstallationRegistrationErrorKey);
await MoveToPrefsAsync<bool?>(V6Keys.AutofillNeedsIdentityReplacementKey);
// account data
var state = await GetValueAsync<State>(Storage.LiteDb, Constants.StateKey);
if (state?.Accounts != null)
{
await SetValueAsync(Storage.Prefs, Constants.StateKey, state);
foreach (var account in state.Accounts.Where(a => a.Value?.Profile?.UserId != null))
{
var userId = account.Value.Profile.UserId;
await MoveToPrefsAsync<bool?>(V6Keys.BiometricUnlockKey(userId));
await MoveToPrefsAsync<string>(V6Keys.ProtectedPinKey(userId));
await MoveToPrefsAsync<string>(V6Keys.PinKeyEncryptedUserKeyKey(userId));
await MoveToPrefsAsync<string>(V6Keys.KeyHashKey(userId));
await MoveToPrefsAsync<string>(V6Keys.MasterKeyEncryptedUserKeyKey(userId));
await MoveToPrefsAsync<Dictionary<string, string>>(V6Keys.EncOrgKeysKey(userId));
await MoveToPrefsAsync<string>(V6Keys.EncPrivateKeyKey(userId));
await MoveToPrefsAsync<List<string>>(V6Keys.AutofillBlacklistedUrisKey(userId));
await MoveToPrefsAsync<long?>(V6Keys.LastActiveTimeKey(userId));
await MoveToPrefsAsync<int?>(V6Keys.VaultTimeoutKey(userId));
await MoveToPrefsAsync<V6Keys.VaultTimeoutAction?>(V6Keys.VaultTimeoutActionKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.ScreenCaptureAllowedKey(userId));
await MoveToPrefsAsync<V6Keys.PreviousPageInfo>(V6Keys.PreviousPageKey(userId));
await MoveToPrefsAsync<int>(V6Keys.InvalidUnlockAttemptsKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.DisableAutoTotpCopyKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.InlineAutofillEnabledKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.AutofillDisableSavePromptKey(userId));
await MoveToPrefsAsync<int?>(V6Keys.DefaultUriMatchKey(userId));
await MoveToPrefsAsync<int?>(V6Keys.ClearClipboardKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.PasswordRepromptAutofillKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.PasswordVerifiedAutofillKey(userId));
await MoveToPrefsAsync<DateTime?>(V6Keys.LastSyncKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.SyncOnRefreshKey(userId));
await MoveToPrefsAsync<DateTime?>(V6Keys.PushLastRegistrationDateKey(userId));
await MoveToPrefsAsync<string>(V6Keys.PushCurrentTokenKey(userId));
await MoveToPrefsAsync<Dictionary<string, V6Keys.PolicyData>>(V6Keys.PoliciesKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.UsesKeyConnectorKey(userId));
await MoveToPrefsAsync<Dictionary<string, V6Keys.OrganizationData>>(
V6Keys.OrganizationsKey(userId));
await MoveToPrefsAsync<V6Keys.PasswordGenerationOptions>(V6Keys.PassGenOptionsKey(userId));
await MoveToPrefsAsync<V6Keys.UsernameGenerationOptions>(V6Keys.UsernameGenOptionsKey(userId));
await MoveToPrefsAsync<string>(V6Keys.TwoFactorTokenKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.ApprovePasswordlessLoginsKey(userId));
await MoveToPrefsAsync<bool?>(V6Keys.ShouldConnectToWatchKey(userId));
await MoveToPrefsAsync<string>(V6Keys.DeviceKeyKey(userId));
}
}
await RemoveValueAsync(Storage.LiteDb, Constants.StateKey);
await RemoveValueAsync(Storage.LiteDb, V6Keys.LastActiveTimeKey(""));
// Update stored version
await SetLastStateVersionAsync(6);
}
private class V6Keys
{
// global keys
internal const string AppIdKey = "appId";
internal const string DisableFaviconKey = "disableFavicon";
internal const string ThemeKey = "theme";
internal const string AutoDarkThemeKey = "autoDarkTheme";
internal const string PasswordlessLoginNotificationKey = "passwordlessLoginNotificationKey";
internal const string PreLoginEmailKey = "preLoginEmailKey";
internal const string LastUserShouldConnectToWatchKey = "lastUserShouldConnectToWatch";
internal const string PushInstallationRegistrationErrorKey = "pushInstallationRegistrationError";
internal const string AutofillNeedsIdentityReplacementKey = "autofillNeedsIdentityReplacement";
// account keys
internal static string BiometricUnlockKey(string userId) => $"biometricUnlock_{userId}";
internal static string ProtectedPinKey(string userId) => $"protectedPin_{userId}";
internal static string PinKeyEncryptedUserKeyKey(string userId) => $"pinKeyEncryptedUserKey_{userId}";
internal static string KeyHashKey(string userId) => $"keyHash_{userId}";
internal static string MasterKeyEncryptedUserKeyKey(string userId) => $"masterKeyEncryptedUserKey_{userId}";
internal static string EncOrgKeysKey(string userId) => $"encOrgKeys_{userId}";
internal static string EncPrivateKeyKey(string userId) => $"encPrivateKey_{userId}";
internal static string AutofillBlacklistedUrisKey(string userId) => $"autofillBlacklistedUris_{userId}";
internal static string LastActiveTimeKey(string userId) => $"lastActiveTime_{userId}";
internal static string VaultTimeoutKey(string userId) => $"vaultTimeout_{userId}";
internal static string VaultTimeoutActionKey(string userId) => $"vaultTimeoutAction_{userId}";
internal static string ScreenCaptureAllowedKey(string userId) => $"screenCaptureAllowed_{userId}";
internal static string PreviousPageKey(string userId) => $"previousPage_{userId}";
internal static string InvalidUnlockAttemptsKey(string userId) => $"invalidUnlockAttempts_{userId}";
internal static string DisableAutoTotpCopyKey(string userId) => $"disableAutoTotpCopy_{userId}";
internal static string InlineAutofillEnabledKey(string userId) => $"inlineAutofillEnabled_{userId}";
internal static string AutofillDisableSavePromptKey(string userId) => $"autofillDisableSavePrompt_{userId}";
internal static string DefaultUriMatchKey(string userId) => $"defaultUriMatch_{userId}";
internal static string ClearClipboardKey(string userId) => $"clearClipboard_{userId}";
internal static string PasswordRepromptAutofillKey(string userId) => $"passwordRepromptAutofillKey_{userId}";
internal static string PasswordVerifiedAutofillKey(string userId) => $"passwordVerifiedAutofillKey_{userId}";
internal static string LastSyncKey(string userId) => $"lastSync_{userId}";
internal static string SyncOnRefreshKey(string userId) => $"syncOnRefresh_{userId}";
internal static string PushLastRegistrationDateKey(string userId) => $"pushLastRegistrationDate_{userId}";
internal static string PushCurrentTokenKey(string userId) => $"pushCurrentToken_{userId}";
internal static string PoliciesKey(string userId) => $"policies_{userId}";
internal static string UsesKeyConnectorKey(string userId) => $"usesKeyConnector_{userId}";
internal static string OrganizationsKey(string userId) => $"organizations_{userId}";
internal static string PassGenOptionsKey(string userId) => $"passwordGenerationOptions_{userId}";
internal static string UsernameGenOptionsKey(string userId) => $"usernameGenerationOptions_{userId}";
internal static string TwoFactorTokenKey(string email) => $"twoFactorToken_{email}";
internal static string ApprovePasswordlessLoginsKey(string userId) => $"approvePasswordlessLogins_{userId}";
internal static string ShouldConnectToWatchKey(string userId) => $"shouldConnectToWatch_{userId}";
internal static string DeviceKeyKey(string userId) => $"deviceKey_{userId}";
// objects
internal class PasswordlessRequestNotification
{
public string UserId { get; set; }
public string Id { get; set; }
}
internal enum VaultTimeoutAction
{
Lock = 0,
Logout = 1,
}
internal class PreviousPageInfo
{
public string Page { get; set; }
public string CipherId { get; set; }
public string SendId { get; set; }
public string SearchText { get; set; }
}
internal class PolicyData
{
public string Id { get; set; }
public string OrganizationId { get; set; }
public V6Keys.PolicyType Type { get; set; }
public Dictionary<string, object> Data { get; set; }
public bool Enabled { get; set; }
}
internal enum PolicyType : byte
{
TwoFactorAuthentication = 0,
MasterPassword = 1,
PasswordGenerator = 2,
OnlyOrg = 3,
RequireSso = 4,
PersonalOwnership = 5,
DisableSend = 6,
SendOptions = 7,
ResetPassword = 8,
MaximumVaultTimeout = 9,
DisablePersonalVaultExport = 10,
}
internal class OrganizationData
{
public string Id { get; set; }
public string Name { get; set; }
public V6Keys.OrganizationUserStatusType Status { get; set; }
public V6Keys.OrganizationUserType Type { get; set; }
public bool Enabled { get; set; }
public bool UseGroups { get; set; }
public bool UseDirectory { get; set; }
public bool UseEvents { get; set; }
public bool UseTotp { get; set; }
public bool Use2fa { get; set; }
public bool UseApi { get; set; }
public bool UsePolicies { get; set; }
public bool SelfHost { get; set; }
public bool UsersGetPremium { get; set; }
public int? Seats { get; set; }
public short? MaxCollections { get; set; }
public short? MaxStorageGb { get; set; }
public V6Keys.Permissions Permissions { get; set; } = new Permissions();
public string Identifier { get; set; }
public bool UsesKeyConnector { get; set; }
public string KeyConnectorUrl { get; set; }
}
internal enum OrganizationUserStatusType : byte
{
Invited = 0,
Accepted = 1,
Confirmed = 2
}
internal enum OrganizationUserType : byte
{
Owner = 0,
Admin = 1,
User = 2,
Manager = 3,
Custom = 4,
}
internal class Permissions
{
public bool AccessBusinessPortal { get; set; }
public bool AccessEventLogs { get; set; }
public bool AccessImportExport { get; set; }
public bool AccessReports { get; set; }
public bool EditAssignedCollections { get; set; }
public bool DeleteAssignedCollections { get; set; }
public bool CreateNewCollections { get; set; }
public bool EditAnyCollection { get; set; }
public bool DeleteAnyCollection { get; set; }
public bool ManageGroups { get; set; }
public bool ManagePolicies { get; set; }
public bool ManageSso { get; set; }
public bool ManageUsers { get; set; }
}
internal class PasswordGenerationOptions
{
public int? Length { get; set; }
public bool? AllowAmbiguousChar { get; set; }
public bool? Number { get; set; }
public int? MinNumber { get; set; }
public bool? Uppercase { get; set; }
public int? MinUppercase { get; set; }
public bool? Lowercase { get; set; }
public int? MinLowercase { get; set; }
public bool? Special { get; set; }
public int? MinSpecial { get; set; }
public string Type { get; set; }
public int? NumWords { get; set; }
public string WordSeparator { get; set; }
public bool? Capitalize { get; set; }
public bool? IncludeNumber { get; set; }
}
internal class UsernameGenerationOptions
{
public V6Keys.UsernameType Type { get; set; }
public V6Keys.ForwardedEmailServiceType ServiceType { get; set; }
public V6Keys.UsernameEmailType PlusAddressedEmailType { get; set; }
public V6Keys.UsernameEmailType CatchAllEmailType { get; set; }
public bool CapitalizeRandomWordUsername { get; set; }
public bool IncludeNumberRandomWordUsername { get; set; }
public string PlusAddressedEmail { get; set; }
public string CatchAllEmailDomain { get; set; }
public string FirefoxRelayApiAccessToken { get; set; }
public string SimpleLoginApiKey { get; set; }
public string DuckDuckGoApiKey { get; set; }
public string FastMailApiKey { get; set; }
public string AnonAddyApiAccessToken { get; set; }
public string AnonAddyDomainName { get; set; }
public string EmailWebsite { get; set; }
}
internal enum UsernameType
{
PlusAddressedEmail = 0,
CatchAllEmail = 1,
ForwardedEmailAlias = 2,
RandomWord = 3,
}
internal enum ForwardedEmailServiceType
{
None = -1,
AnonAddy = 0,
FirefoxRelay = 1,
SimpleLogin = 2,
DuckDuckGo = 3,
Fastmail = 4,
}
internal enum UsernameEmailType
{
Random = 0,
Website = 1,
}
}
#endregion
// Helpers
private async Task<int> GetLastStateVersionAsync()
@@ -905,20 +612,5 @@ namespace Bit.Core.Services
return _liteDbStorageService;
}
}
private async Task MoveToPrefsAsync<T>(string key)
{
var value = await GetValueAsync<T>(Storage.LiteDb, key);
if (value == null)
{
return;
}
if (await GetValueAsync<T>(Storage.Prefs, key) == null)
{
await SetValueAsync(Storage.Prefs, key, value);
}
await RemoveValueAsync(Storage.LiteDb, key);
}
}
}

View File

@@ -548,12 +548,12 @@ namespace Bit.Core.Services
public async Task<bool?> GetAutofillTileAddedAsync()
{
return await GetValueAsync<bool?>(Constants.AutofillTileAddedKey, await GetDefaultStorageOptionsAsync());
return await GetValueAsync<bool?>(Constants.AutofillTileAdded, await GetDefaultStorageOptionsAsync());
}
public async Task SetAutofillTileAddedAsync(bool? value)
{
await SetValueAsync(Constants.AutofillTileAddedKey, value, await GetDefaultStorageOptionsAsync());
await SetValueAsync(Constants.AutofillTileAdded, value, await GetDefaultStorageOptionsAsync());
}
public async Task<string> GetEmailAsync(string userId = null)
@@ -751,19 +751,19 @@ namespace Bit.Core.Services
reconciledOptions);
}
public async Task<Dictionary<string, Dictionary<string, object>>> GetCiphersLocalDataAsync(string userId = null)
public async Task<Dictionary<string, Dictionary<string, object>>> GetLocalDataAsync(string userId = null)
{
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
await GetDefaultStorageOptionsAsync());
return await GetValueAsync<Dictionary<string, Dictionary<string, object>>>(
Constants.CiphersLocalDataKey(reconciledOptions.UserId), reconciledOptions);
Constants.LocalDataKey(reconciledOptions.UserId), reconciledOptions);
}
public async Task SetCiphersLocalDataAsync(Dictionary<string, Dictionary<string, object>> value, string userId = null)
public async Task SetLocalDataAsync(Dictionary<string, Dictionary<string, object>> value, string userId = null)
{
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
await GetDefaultStorageOptionsAsync());
await SetValueAsync(Constants.CiphersLocalDataKey(reconciledOptions.UserId), value, reconciledOptions);
await SetValueAsync(Constants.LocalDataKey(reconciledOptions.UserId), value, reconciledOptions);
}
public async Task<Dictionary<string, CipherData>> GetEncryptedCiphersAsync(string userId = null)
@@ -795,6 +795,21 @@ namespace Bit.Core.Services
await SetValueAsync(Constants.DefaultUriMatchKey(reconciledOptions.UserId), value, reconciledOptions);
}
public async Task<HashSet<string>> GetNeverDomainsAsync(string userId = null)
{
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
await GetDefaultStorageOptionsAsync());
return await GetValueAsync<HashSet<string>>(Constants.NeverDomainsKey(reconciledOptions.UserId),
reconciledOptions);
}
public async Task SetNeverDomainsAsync(HashSet<string> value, string userId = null)
{
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
await GetDefaultStorageOptionsAsync());
await SetValueAsync(Constants.NeverDomainsKey(reconciledOptions.UserId), value, reconciledOptions);
}
public async Task<int?> GetClearClipboardAsync(string userId = null)
{
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
@@ -1527,7 +1542,7 @@ namespace Bit.Core.Services
SetLastActiveTimeAsync(null, userId),
SetPreviousPageInfoAsync(null, userId),
SetInvalidUnlockAttemptsAsync(null, userId),
SetCiphersLocalDataAsync(null, userId),
SetLocalDataAsync(null, userId),
SetEncryptedCiphersAsync(null, userId),
SetEncryptedCollectionsAsync(null, userId),
SetLastSyncAsync(null, userId),

View File

@@ -2,8 +2,6 @@
using System.Threading.Tasks;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Models.Domain;
namespace Bit.Core.Services
{
@@ -61,6 +59,13 @@ namespace Bit.Core.Services
public async Task<bool> IsLockedAsync(string userId = null)
{
// When checking if we need to lock inactive account, we don't want to
// set the key, so we only check if the account has an auto unlock key
if (userId != null && await _stateService.GetActiveUserIdAsync() != userId)
{
return await _cryptoService.HasAutoUnlockKeyAsync(userId);
}
var biometricSet = await IsBiometricLockSetAsync(userId);
if (biometricSet && await _stateService.GetBiometricLockedAsync(userId))
{
@@ -69,23 +74,11 @@ namespace Bit.Core.Services
if (!await _cryptoService.HasUserKeyAsync(userId))
{
try
if (!await _cryptoService.HasAutoUnlockKeyAsync(userId))
{
if (!await _cryptoService.HasAutoUnlockKeyAsync(userId))
{
return true;
}
if (userId != null && await _stateService.GetActiveUserIdAsync() != userId)
{
await _cryptoService.SetUserKeyAsync(await _cryptoService.GetAutoUnlockKeyAsync(userId),
userId);
}
return true;
}
catch (LegacyUserException)
{
await LogOutAsync(false, userId);
}
await _cryptoService.SetUserKeyAsync(await _cryptoService.GetAutoUnlockKeyAsync(userId), userId);
}
// Check again to verify auto key was set

View File

@@ -223,7 +223,6 @@ namespace Bit.iOS.Autofill
else if (navController.TopViewController is LockPasswordViewController passwordViewController)
{
passwordViewController.CPViewController = this;
passwordViewController.LaunchHomePage = () => DismissViewController(false, () => LaunchHomePage());
segue.DestinationViewController.PresentationController.Delegate =
new CustomPresentationControllerDelegate(passwordViewController.DismissModalAction);
}

View File

@@ -11,7 +11,7 @@
<key>CFBundleIdentifier</key>
<string>com.8bit.bitwarden.autofill</string>
<key>CFBundleShortVersionString</key>
<string>2023.9.1</string>
<string>2023.7.1</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>CFBundleLocalizations</key>

View File

@@ -7,7 +7,6 @@ using Bit.App.Resources;
using Bit.App.Utilities;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Models.Domain;
using Bit.Core.Services;
using Bit.Core.Utilities;
@@ -55,15 +54,12 @@ namespace Bit.iOS.Core.Controllers
public abstract UIBarButtonItem BaseSubmitButton { get; }
public abstract Action Success { get; }
public abstract Action Cancel { get; }
public Action LaunchHomePage { get; set; }
public FormEntryTableViewCell MasterPasswordCell { get; set; } = new FormEntryTableViewCell(
AppResources.MasterPassword, buttonsConfig: FormEntryTableViewCell.ButtonsConfig.One);
public string BiometricIntegritySourceKey { get; set; }
public bool HasLoginOrUnlockMethod => _hasMasterPassword || _biometricEnabled || _pinEnabled;
public UITableViewCell BiometricCell
{
get
@@ -121,23 +117,12 @@ namespace Bit.iOS.Core.Controllers
_pinEnabled = (_pinStatus == PinLockType.Transient && ephemeralPinSet != null) ||
_pinStatus == PinLockType.Persistent;
_biometricEnabled = await IsBiometricsEnabledAsync();
_biometricEnabled = await _vaultTimeoutService.IsBiometricLockSetAsync()
&& await _cryptoService.HasEncryptedUserKeyAsync();
_biometricIntegrityValid =
await _platformUtilsService.IsBiometricIntegrityValidAsync(BiometricIntegritySourceKey);
_hasMasterPassword = await _userVerificationService.HasMasterPasswordAsync();
_biometricUnlockOnly = !_hasMasterPassword && _biometricEnabled && !_pinEnabled;
if (_biometricUnlockOnly)
{
await EnableBiometricsIfNeeded();
}
_biometricIntegrityValid = await _platformUtilsService.IsBiometricIntegrityValidAsync(BiometricIntegritySourceKey);
}
if (!HasLoginOrUnlockMethod)
{
// user doesn't have a login method
// needs to go to homepage and login again
LaunchHomePage?.Invoke();
return;
}
if (_pinEnabled)
@@ -260,26 +245,99 @@ namespace Bit.iOS.Core.Controllers
&&
kdfConfig.Memory > Constants.MaximumArgon2IdMemoryBeforeExtensionCrashing
&&
!await _platformUtilsService.ShowDialogAsync(
AppResources.UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve,
AppResources.Warning, AppResources.Continue, AppResources.Cancel))
!await _platformUtilsService.ShowDialogAsync(AppResources.UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve, AppResources.Warning, AppResources.Continue, AppResources.Cancel))
{
return;
}
if (_pinEnabled)
{
await UnlockWithPinAsync(inputtedValue, email, kdfConfig);
var failed = true;
try
{
EncString userKeyPin = null;
EncString oldPinProtected = null;
if (_pinStatus == PinLockType.Persistent)
{
userKeyPin = await _stateService.GetPinKeyEncryptedUserKeyAsync();
var oldEncryptedKey = await _stateService.GetPinProtectedAsync();
oldPinProtected = oldEncryptedKey != null ? new EncString(oldEncryptedKey) : null;
}
else if (_pinStatus == PinLockType.Transient)
{
userKeyPin = await _stateService.GetPinKeyEncryptedUserKeyEphemeralAsync();
oldPinProtected = await _stateService.GetPinProtectedKeyAsync();
}
UserKey userKey;
if (oldPinProtected != null)
{
userKey = await _cryptoService.DecryptAndMigrateOldPinKeyAsync(
_pinStatus == PinLockType.Transient,
inputtedValue,
email,
kdfConfig,
oldPinProtected
);
}
else
{
userKey = await _cryptoService.DecryptUserKeyWithPinAsync(
inputtedValue,
email,
kdfConfig,
userKeyPin
);
}
var protectedPin = await _stateService.GetProtectedPinAsync();
var decryptedPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), userKey);
failed = decryptedPin != inputtedValue;
if (!failed)
{
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
await SetKeyAndContinueAsync(userKey);
}
}
catch
{
failed = true;
}
if (failed)
{
await HandleFailedCredentialsAsync();
}
}
else
{
await UnlockWithMasterPasswordAsync(inputtedValue, email, kdfConfig);
var masterKey = await _cryptoService.MakeMasterKeyAsync(inputtedValue, email, kdfConfig);
var storedPasswordHash = await _cryptoService.GetMasterKeyHashAsync();
if (storedPasswordHash == null)
{
var oldKey = await _secureStorageService.GetAsync<string>("oldKey");
if (masterKey.KeyB64 == oldKey)
{
var localPasswordHash = await _cryptoService.HashMasterKeyAsync(inputtedValue, masterKey, HashPurpose.LocalAuthorization);
await _secureStorageService.RemoveAsync("oldKey");
await _cryptoService.SetMasterKeyHashAsync(localPasswordHash);
}
}
var passwordValid = await _cryptoService.CompareAndUpdateKeyHashAsync(inputtedValue, masterKey);
if (passwordValid)
{
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
var userKey = await _cryptoService.DecryptUserKeyWithMasterKeyAsync(masterKey);
await _cryptoService.SetMasterKeyAsync(masterKey);
await SetKeyAndContinueAsync(userKey, true);
}
else
{
await HandleFailedCredentialsAsync();
}
}
}
catch (LegacyUserException)
{
await HandleLegacyUserAsync();
}
finally
{
_checkingPassword = false;
@@ -297,125 +355,19 @@ namespace Bit.iOS.Core.Controllers
InvalidValue();
}
private async Task UnlockWithPinAsync(string inputPin, string email, KdfConfig kdfConfig)
{
var failed = true;
try
{
EncString userKeyPin = null;
EncString oldPinProtected = null;
if (_pinStatus == PinLockType.Persistent)
{
userKeyPin = await _stateService.GetPinKeyEncryptedUserKeyAsync();
var oldEncryptedKey = await _stateService.GetPinProtectedAsync();
oldPinProtected = oldEncryptedKey != null ? new EncString(oldEncryptedKey) : null;
}
else if (_pinStatus == PinLockType.Transient)
{
userKeyPin = await _stateService.GetPinKeyEncryptedUserKeyEphemeralAsync();
oldPinProtected = await _stateService.GetPinProtectedKeyAsync();
}
UserKey userKey;
if (oldPinProtected != null)
{
userKey = await _cryptoService.DecryptAndMigrateOldPinKeyAsync(
_pinStatus == PinLockType.Transient,
inputPin,
email,
kdfConfig,
oldPinProtected
);
}
else
{
userKey = await _cryptoService.DecryptUserKeyWithPinAsync(
inputPin,
email,
kdfConfig,
userKeyPin
);
}
var protectedPin = await _stateService.GetProtectedPinAsync();
var decryptedPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), userKey);
failed = decryptedPin != inputPin;
if (!failed)
{
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
await SetKeyAndContinueAsync(userKey);
}
}
catch
{
failed = true;
}
if (failed)
{
await HandleFailedCredentialsAsync();
}
}
private async Task UnlockWithMasterPasswordAsync(string inputPassword, string email, KdfConfig kdfConfig)
{
var masterKey = await _cryptoService.MakeMasterKeyAsync(inputPassword, email, kdfConfig);
if (await _cryptoService.IsLegacyUserAsync(masterKey))
{
throw new LegacyUserException();
}
var storedPasswordHash = await _cryptoService.GetMasterKeyHashAsync();
if (storedPasswordHash == null)
{
var oldKey = await _secureStorageService.GetAsync<string>("oldKey");
if (masterKey.KeyB64 == oldKey)
{
var localPasswordHash =
await _cryptoService.HashMasterKeyAsync(inputPassword, masterKey,
HashPurpose.LocalAuthorization);
await _secureStorageService.RemoveAsync("oldKey");
await _cryptoService.SetMasterKeyHashAsync(localPasswordHash);
}
}
var passwordValid = await _cryptoService.CompareAndUpdateKeyHashAsync(inputPassword, masterKey);
if (passwordValid)
{
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
var userKey = await _cryptoService.DecryptUserKeyWithMasterKeyAsync(masterKey);
await _cryptoService.SetMasterKeyAsync(masterKey);
await SetKeyAndContinueAsync(userKey, true);
}
else
{
await HandleFailedCredentialsAsync();
}
}
public async Task PromptBiometricAsync()
{
try
if (!_biometricEnabled || !_biometricIntegrityValid)
{
if (!_biometricEnabled || !_biometricIntegrityValid)
{
return;
}
var success = await _platformUtilsService.AuthenticateBiometricAsync(null,
_pinEnabled ? AppResources.PIN : AppResources.MasterPassword,
() => MasterPasswordCell.TextField.BecomeFirstResponder());
await _stateService.SetBiometricLockedAsync(!success);
if (success)
{
var userKey = await _cryptoService.GetBiometricUnlockKeyAsync();
await SetKeyAndContinueAsync(userKey);
}
return;
}
catch (LegacyUserException)
var success = await _platformUtilsService.AuthenticateBiometricAsync(null,
_pinEnabled ? AppResources.PIN : AppResources.MasterPassword,
() => MasterPasswordCell.TextField.BecomeFirstResponder());
await _stateService.SetBiometricLockedAsync(!success);
if (success)
{
await HandleLegacyUserAsync();
DoContinue();
}
}
@@ -468,29 +420,6 @@ namespace Bit.iOS.Core.Controllers
}
}
private async Task<bool> IsBiometricsEnabledAsync()
{
try
{
return await _vaultTimeoutService.IsBiometricLockSetAsync() &&
await _biometricService.CanUseBiometricsUnlockAsync();
}
catch (LegacyUserException)
{
await HandleLegacyUserAsync();
}
return false;
}
private async Task HandleLegacyUserAsync()
{
// Legacy users must migrate on web vault.
await _platformUtilsService.ShowDialogAsync(AppResources.EncryptionKeyMigrationRequiredDescriptionLong,
AppResources.AnErrorHasOccurred,
AppResources.Ok);
await _vaultTimeoutService.LogOutAsync();
}
private void InvalidValue()
{
var alert = Dialogs.CreateAlert(AppResources.AnErrorHasOccurred,

View File

@@ -0,0 +1,512 @@
using System;
using System.Threading.Tasks;
using Bit.App.Abstractions;
using Bit.App.Models;
using Bit.App.Pages;
using Bit.App.Resources;
using Bit.App.Utilities;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Models.Domain;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Bit.iOS.Core.Utilities;
using Bit.iOS.Core.Views;
using Foundation;
using UIKit;
using Xamarin.Forms;
namespace Bit.iOS.Core.Controllers
{
// TODO: Leaving this here until all inheritance is changed to use BaseLockPasswordViewController instead of UITableViewController
[Obsolete("Use BaseLockPasswordViewController instead")]
public abstract class LockPasswordViewController : ExtendedUITableViewController
{
private IVaultTimeoutService _vaultTimeoutService;
private ICryptoService _cryptoService;
private IDeviceActionService _deviceActionService;
private IStateService _stateService;
private IStorageService _secureStorageService;
private IPlatformUtilsService _platformUtilsService;
private IBiometricService _biometricService;
private IUserVerificationService _userVerificationService;
private PinLockType _pinStatus;
private bool _pinEnabled;
private bool _biometricEnabled;
private bool _biometricIntegrityValid = true;
private bool _passwordReprompt = false;
private bool _hasMasterPassword;
private bool _biometricUnlockOnly = false;
protected bool autofillExtension = false;
public LockPasswordViewController(IntPtr handle)
: base(handle)
{ }
public abstract UINavigationItem BaseNavItem { get; }
public abstract UIBarButtonItem BaseCancelButton { get; }
public abstract UIBarButtonItem BaseSubmitButton { get; }
public abstract Action Success { get; }
public abstract Action Cancel { get; }
public FormEntryTableViewCell MasterPasswordCell { get; set; } = new FormEntryTableViewCell(
AppResources.MasterPassword, buttonsConfig: FormEntryTableViewCell.ButtonsConfig.One);
public string BiometricIntegritySourceKey { get; set; }
public UITableViewCell BiometricCell
{
get
{
var cell = new UITableViewCell();
cell.BackgroundColor = ThemeHelpers.BackgroundColor;
if (_biometricIntegrityValid)
{
var biometricButtonText = _deviceActionService.SupportsFaceBiometric() ?
AppResources.UseFaceIDToUnlock : AppResources.UseFingerprintToUnlock;
cell.TextLabel.TextColor = ThemeHelpers.PrimaryColor;
cell.TextLabel.Text = biometricButtonText;
}
else
{
cell.TextLabel.TextColor = ThemeHelpers.DangerColor;
cell.TextLabel.Font = ThemeHelpers.GetDangerFont();
cell.TextLabel.Lines = 0;
cell.TextLabel.LineBreakMode = UILineBreakMode.WordWrap;
cell.TextLabel.Text = AppResources.AccountBiometricInvalidatedExtension;
}
return cell;
}
}
public override async void ViewDidLoad()
{
_vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
_cryptoService = ServiceContainer.Resolve<ICryptoService>("cryptoService");
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
_secureStorageService = ServiceContainer.Resolve<IStorageService>("secureStorageService");
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
_biometricService = ServiceContainer.Resolve<IBiometricService>("biometricService");
_userVerificationService = ServiceContainer.Resolve<IUserVerificationService>();
// We re-use the lock screen for autofill extension to verify master password
// when trying to access protected items.
if (autofillExtension && await _stateService.GetPasswordRepromptAutofillAsync())
{
_passwordReprompt = true;
_pinStatus = PinLockType.Disabled;
_pinEnabled = false;
_biometricEnabled = false;
}
else
{
_pinStatus = await _vaultTimeoutService.GetPinLockTypeAsync();
var ephemeralPinSet = await _stateService.GetPinKeyEncryptedUserKeyEphemeralAsync()
?? await _stateService.GetPinProtectedKeyAsync();
_pinEnabled = (_pinStatus == PinLockType.Transient && ephemeralPinSet != null) ||
_pinStatus == PinLockType.Persistent;
_biometricEnabled = await _vaultTimeoutService.IsBiometricLockSetAsync()
&& await _cryptoService.HasEncryptedUserKeyAsync();
_biometricIntegrityValid =
await _platformUtilsService.IsBiometricIntegrityValidAsync(BiometricIntegritySourceKey);
_hasMasterPassword = await _userVerificationService.HasMasterPasswordAsync();
_biometricUnlockOnly = !_hasMasterPassword && _biometricEnabled && !_pinEnabled;
}
if (_pinEnabled)
{
BaseNavItem.Title = AppResources.VerifyPIN;
}
else if (_hasMasterPassword)
{
BaseNavItem.Title = AppResources.VerifyMasterPassword;
}
else
{
BaseNavItem.Title = AppResources.UnlockVault;
}
BaseCancelButton.Title = AppResources.Cancel;
if (_biometricUnlockOnly)
{
BaseSubmitButton.Title = null;
BaseSubmitButton.Enabled = false;
}
else
{
BaseSubmitButton.Title = AppResources.Submit;
}
var descriptor = UIFontDescriptor.PreferredBody;
if (!_biometricUnlockOnly)
{
MasterPasswordCell.Label.Text = _pinEnabled ? AppResources.PIN : AppResources.MasterPassword;
MasterPasswordCell.TextField.SecureTextEntry = true;
MasterPasswordCell.TextField.ReturnKeyType = UIReturnKeyType.Go;
MasterPasswordCell.TextField.ShouldReturn += (UITextField tf) =>
{
CheckPasswordAsync().GetAwaiter().GetResult();
return true;
};
if (_pinEnabled)
{
MasterPasswordCell.TextField.KeyboardType = UIKeyboardType.NumberPad;
}
MasterPasswordCell.ConfigureToggleSecureTextCell();
}
TableView.RowHeight = UITableView.AutomaticDimension;
TableView.EstimatedRowHeight = 70;
TableView.Source = new TableSource(this);
TableView.AllowsSelection = true;
base.ViewDidLoad();
if (_biometricEnabled)
{
if (!_biometricIntegrityValid)
{
return;
}
var tasks = Task.Run(async () =>
{
await Task.Delay(500);
NSRunLoop.Main.BeginInvokeOnMainThread(async () => await PromptBiometricAsync());
});
}
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
// Users without MP and without biometric or pin need SSO
if (!_hasMasterPassword)
{
if (!(_pinEnabled || _biometricEnabled) ||
(_biometricEnabled && !_biometricIntegrityValid))
{
PromptSSO();
}
}
else if (!_biometricEnabled || !_biometricIntegrityValid)
{
MasterPasswordCell.TextField.BecomeFirstResponder();
}
}
protected async Task CheckPasswordAsync()
{
if (string.IsNullOrWhiteSpace(MasterPasswordCell.TextField.Text))
{
var alert = Dialogs.CreateAlert(AppResources.AnErrorHasOccurred,
string.Format(AppResources.ValidationFieldRequired,
_pinEnabled ? AppResources.PIN : AppResources.MasterPassword),
AppResources.Ok);
PresentViewController(alert, true, null);
return;
}
var email = await _stateService.GetEmailAsync();
var kdfConfig = await _stateService.GetActiveUserCustomDataAsync(a => new KdfConfig(a?.Profile));
var inputtedValue = MasterPasswordCell.TextField.Text;
if (_pinEnabled)
{
var failed = true;
try
{
EncString userKeyPin = null;
EncString oldPinProtected = null;
if (_pinStatus == PinLockType.Persistent)
{
userKeyPin = await _stateService.GetPinKeyEncryptedUserKeyAsync();
var oldEncryptedKey = await _stateService.GetPinProtectedAsync();
oldPinProtected = oldEncryptedKey != null ? new EncString(oldEncryptedKey) : null;
}
else if (_pinStatus == PinLockType.Transient)
{
userKeyPin = await _stateService.GetPinKeyEncryptedUserKeyEphemeralAsync();
oldPinProtected = await _stateService.GetPinProtectedKeyAsync();
}
UserKey userKey;
if (oldPinProtected != null)
{
userKey = await _cryptoService.DecryptAndMigrateOldPinKeyAsync(
_pinStatus == PinLockType.Transient,
inputtedValue,
email,
kdfConfig,
oldPinProtected
);
}
else
{
userKey = await _cryptoService.DecryptUserKeyWithPinAsync(
inputtedValue,
email,
kdfConfig,
userKeyPin
);
}
var protectedPin = await _stateService.GetProtectedPinAsync();
var decryptedPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), userKey);
failed = decryptedPin != inputtedValue;
if (!failed)
{
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
await SetKeyAndContinueAsync(userKey);
}
}
catch
{
failed = true;
}
if (failed)
{
var invalidUnlockAttempts = await AppHelpers.IncrementInvalidUnlockAttemptsAsync();
if (invalidUnlockAttempts >= 5)
{
await LogOutAsync();
return;
}
InvalidValue();
}
}
else
{
var masterKey = await _cryptoService.MakeMasterKeyAsync(inputtedValue, email, kdfConfig);
var storedPasswordHash = await _cryptoService.GetMasterKeyHashAsync();
if (storedPasswordHash == null)
{
var oldKey = await _secureStorageService.GetAsync<string>("oldKey");
if (masterKey.KeyB64 == oldKey)
{
var localPasswordHash = await _cryptoService.HashMasterKeyAsync(inputtedValue, masterKey, HashPurpose.LocalAuthorization);
await _secureStorageService.RemoveAsync("oldKey");
await _cryptoService.SetMasterKeyHashAsync(localPasswordHash);
}
}
var passwordValid = await _cryptoService.CompareAndUpdateKeyHashAsync(inputtedValue, masterKey);
if (passwordValid)
{
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
var userKey = await _cryptoService.DecryptUserKeyWithMasterKeyAsync(masterKey);
await _cryptoService.SetMasterKeyAsync(masterKey);
await SetKeyAndContinueAsync(userKey, true);
}
else
{
var invalidUnlockAttempts = await AppHelpers.IncrementInvalidUnlockAttemptsAsync();
if (invalidUnlockAttempts >= 5)
{
await LogOutAsync();
return;
}
InvalidValue();
}
}
}
public async Task PromptBiometricAsync()
{
if (!_biometricEnabled || !_biometricIntegrityValid)
{
return;
}
var success = await _platformUtilsService.AuthenticateBiometricAsync(null,
_pinEnabled ? AppResources.PIN : AppResources.MasterPassword,
() => MasterPasswordCell.TextField.BecomeFirstResponder());
await _stateService.SetBiometricLockedAsync(!success);
if (success)
{
DoContinue();
}
}
public void PromptSSO()
{
var loginPage = new LoginSsoPage();
var app = new App.App(new AppOptions { IosExtension = true });
ThemeManager.SetTheme(app.Resources);
ThemeManager.ApplyResourcesTo(loginPage);
if (loginPage.BindingContext is LoginSsoPageViewModel vm)
{
vm.SsoAuthSuccessAction = () => DoContinue();
vm.CloseAction = Cancel;
}
var navigationPage = new NavigationPage(loginPage);
var loginController = navigationPage.CreateViewController();
loginController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(loginController, true, null);
}
private async Task SetKeyAndContinueAsync(UserKey userKey, bool masterPassword = false)
{
var hasKey = await _cryptoService.HasUserKeyAsync();
if (!hasKey)
{
await _cryptoService.SetUserKeyAsync(userKey);
}
DoContinue(masterPassword);
}
private async void DoContinue(bool masterPassword = false)
{
if (masterPassword)
{
await _stateService.SetPasswordVerifiedAutofillAsync(true);
}
await EnableBiometricsIfNeeded();
await _stateService.SetBiometricLockedAsync(false);
MasterPasswordCell.TextField.ResignFirstResponder();
Success();
}
private async Task EnableBiometricsIfNeeded()
{
// Re-enable biometrics if initial use
if (_biometricEnabled & !_biometricIntegrityValid)
{
await _biometricService.SetupBiometricAsync(BiometricIntegritySourceKey);
}
}
private void InvalidValue()
{
var alert = Dialogs.CreateAlert(AppResources.AnErrorHasOccurred,
string.Format(null, _pinEnabled ? AppResources.PIN : AppResources.InvalidMasterPassword),
AppResources.Ok, (a) =>
{
MasterPasswordCell.TextField.Text = string.Empty;
MasterPasswordCell.TextField.BecomeFirstResponder();
});
PresentViewController(alert, true, null);
}
private async Task LogOutAsync()
{
await AppHelpers.LogOutAsync(await _stateService.GetActiveUserIdAsync());
var authService = ServiceContainer.Resolve<IAuthService>("authService");
authService.LogOut(() =>
{
Cancel?.Invoke();
});
}
public class TableSource : ExtendedUITableViewSource
{
private LockPasswordViewController _controller;
public TableSource(LockPasswordViewController controller)
{
_controller = controller;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
if (indexPath.Section == 0)
{
if (indexPath.Row == 0)
{
if (_controller._biometricUnlockOnly)
{
return _controller.BiometricCell;
}
else
{
return _controller.MasterPasswordCell;
}
}
}
else if (indexPath.Section == 1)
{
if (indexPath.Row == 0)
{
if (_controller._passwordReprompt)
{
var cell = new ExtendedUITableViewCell();
cell.TextLabel.TextColor = ThemeHelpers.DangerColor;
cell.TextLabel.Font = ThemeHelpers.GetDangerFont();
cell.TextLabel.Lines = 0;
cell.TextLabel.LineBreakMode = UILineBreakMode.WordWrap;
cell.TextLabel.Text = AppResources.PasswordConfirmationDesc;
return cell;
}
else if (!_controller._biometricUnlockOnly)
{
return _controller.BiometricCell;
}
}
}
return new ExtendedUITableViewCell();
}
public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
return UITableView.AutomaticDimension;
}
public override nint NumberOfSections(UITableView tableView)
{
return (!_controller._biometricUnlockOnly && _controller._biometricEnabled) ||
_controller._passwordReprompt
? 2
: 1;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
if (section <= 1)
{
return 1;
}
return 0;
}
public override nfloat GetHeightForHeader(UITableView tableView, nint section)
{
return section == 1 ? 0.00001f : UITableView.AutomaticDimension;
}
public override string TitleForHeader(UITableView tableView, nint section)
{
return null;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
tableView.DeselectRow(indexPath, true);
tableView.EndEditing(true);
if (indexPath.Row == 0 &&
((_controller._biometricUnlockOnly && indexPath.Section == 0) ||
indexPath.Section == 1))
{
var task = _controller.PromptBiometricAsync();
return;
}
var cell = tableView.CellAt(indexPath);
if (cell == null)
{
return;
}
if (cell is ISelectable selectableCell)
{
selectableCell.Select();
}
}
}
}
}

View File

@@ -115,7 +115,7 @@ namespace Bit.iOS.Core.Utilities
var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService);
var cryptoService = new CryptoService(stateService, cryptoFunctionService);
var biometricService = new BiometricService(stateService, cryptoService);
var passwordRepromptService = new MobilePasswordRepromptService(platformUtilsService, cryptoService, stateService);
var passwordRepromptService = new MobilePasswordRepromptService(platformUtilsService, cryptoService);
ServiceContainer.Register<ISynchronousStorageService>(preferencesStorage);
ServiceContainer.Register<IBroadcasterService>("broadcasterService", broadcasterService);

View File

@@ -53,17 +53,6 @@
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
<OutputPath>bin\iPhoneSimulator\Release\</OutputPath>
<DefineConstants>__IOS__;__MOBILE__;__UNIFIED__;</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;VSX1000</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'FDroid|AnyCPU'">
<OutputPath>bin\FDroid\</OutputPath>
<DefineConstants>__IOS__;__MOBILE__;__UNIFIED__;</DefineConstants>
@@ -157,6 +146,7 @@
<Compile Include="Controllers\ExtendedUITableViewCell.cs" />
<Compile Include="Controllers\ExtendedUIViewController.cs" />
<Compile Include="Controllers\ExtendedUITableViewSource.cs" />
<Compile Include="Controllers\LockPasswordViewController.cs" />
<Compile Include="Controllers\LoginAddViewController.cs" />
<Compile Include="Controllers\PasswordGeneratorViewController.cs" />
<Compile Include="Models\AppExtensionContext.cs" />

View File

@@ -11,7 +11,7 @@
<key>CFBundleIdentifier</key>
<string>com.8bit.bitwarden.find-login-action-extension</string>
<key>CFBundleShortVersionString</key>
<string>2023.9.1</string>
<string>2023.7.1</string>
<key>CFBundleLocalizations</key>
<array>
<string>en</string>

View File

@@ -110,7 +110,6 @@ namespace Bit.iOS.Extension
else if (navController.TopViewController is LockPasswordViewController passwordViewController)
{
passwordViewController.LoadingController = this;
passwordViewController.LaunchHomePage = () => DismissViewController(false, () => LaunchHomePage());
segue.DestinationViewController.PresentationController.Delegate =
new CustomPresentationControllerDelegate(passwordViewController.DismissModalAction);
}

View File

@@ -4,14 +4,8 @@ using UIKit;
namespace Bit.iOS.Extension
{
public partial class LockPasswordViewController : Core.Controllers.BaseLockPasswordViewController
public partial class LockPasswordViewController : Core.Controllers.LockPasswordViewController
{
public LockPasswordViewController()
{
BiometricIntegritySourceKey = Bit.Core.Constants.iOSExtensionBiometricIntegritySourceKey;
DismissModalAction = Cancel;
}
public LockPasswordViewController(IntPtr handle)
: base(handle)
{
@@ -26,8 +20,6 @@ namespace Bit.iOS.Extension
public override Action Success => () => LoadingController.DismissLockAndContinue();
public override Action Cancel => () => LoadingController.CompleteRequest(null, null);
public override UITableView TableView => MainTableView;
public override void ViewDidLoad()
{
base.ViewDidLoad();

View File

@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>2023.9.1</string>
<string>2023.7.1</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>MinimumOSVersion</key>

View File

@@ -123,7 +123,6 @@ namespace Bit.iOS.ShareExtension
{
var viewController = _storyboard.Value.InstantiateViewController("lockVC") as LockPasswordViewController;
viewController.LoadingController = this;
viewController.LaunchHomePage = () => DismissViewController(false, () => LaunchHomePage());
viewController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
if (_presentingOnNavigationPage)

View File

@@ -11,7 +11,7 @@
<key>CFBundleIdentifier</key>
<string>com.8bit.bitwarden</string>
<key>CFBundleShortVersionString</key>
<string>2023.9.1</string>
<string>2023.7.1</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>CFBundleIconName</key>

View File

@@ -5,6 +5,6 @@
"SyncingItemsContainingVerificationCodes" = "Vahvistuskoodeja sisältäviä kohteita synkronoidaan.";
"UnlockBitwardenOnYourIPhoneToViewVerificationCodes" = "Näytä vahvistuskoodit avaamalla Bitwarden iPhonessa.";
"SetUpBitwardenToViewItemsContainingVerificationCodes" = "Määritä Bitwarden nähdäksesi vahvistuskoodeja sisältävät kohteet.";
"Search" = "Etsi";
"Search" = "Haku";
"NoItemsFound" = "Kohteita ei löytynyt.";
"SetUpAppleWatchPasscodeInOrderToUseBitwarden" = "Määritä Apple Watch- lukituskoodi Bitwardenn käyttämiseksi.";

View File

@@ -1,10 +1,10 @@
"ThereAreNoItemsToList" = "There are no items to list";
"ToViewVerificationCodesUpgradeToPremium" = "To view verification codes, upgrade to premium";
"Add2FactorAutenticationToAnItemToViewVerificationCodes" = "Add 2 factor authentication to an item to view the verification codes";
"LogInToBitwardenOnYourIPhoneToViewVerificationCodes" = "वेरीफिकेशन कोड देखने के लिए अपने आईफोन पे बिटवार्डन में लॉगइन करें";
"SyncingItemsContainingVerificationCodes" = "वेरीफिकेशन कोड वाले चीज़ें सिंक कर रहे";
"UnlockBitwardenOnYourIPhoneToViewVerificationCodes" = "वेरीफिकेशन कोड देखने के लिए अपने आईफोन पे बिटवार्डन खोलें";
"SetUpBitwardenToViewItemsContainingVerificationCodes" = "वेरीफिकेशन कोड वाले चीज़ें देखने के लिए बिटवार्डन सेट करें";
"Search" = "खोजें";
"NoItemsFound" = "कोई चीज़ नहीं मिला";
"SetUpAppleWatchPasscodeInOrderToUseBitwarden" = "बिटवार्डन इस्तेमाल करने के लिए एप्पल वॉच पासकोड सेट करें";
"LogInToBitwardenOnYourIPhoneToViewVerificationCodes" = "Log in to Bitwarden on your iPhone to view verification codes";
"SyncingItemsContainingVerificationCodes" = "Syncing items containing verification codes";
"UnlockBitwardenOnYourIPhoneToViewVerificationCodes" = "Unlock Bitwarden on your iPhone to view verification codes";
"SetUpBitwardenToViewItemsContainingVerificationCodes" = "Set up Bitwarden to view items containing verification codes";
"Search" = "Search";
"NoItemsFound" = "No items found";
"SetUpAppleWatchPasscodeInOrderToUseBitwarden" = "Set up Apple Watch passcode in order to use Bitwarden";

View File

@@ -2,7 +2,7 @@
"ToViewVerificationCodesUpgradeToPremium" = "Per visualizzare i codici di verifica, passa a Premium";
"Add2FactorAutenticationToAnItemToViewVerificationCodes" = "Aggiungi la verifica in due passaggi a un elemento per visualizzare i codici di verifica";
"LogInToBitwardenOnYourIPhoneToViewVerificationCodes" = "Accedi a Bitwarden sul tuo iPhone per visualizzare i codici di verifica";
"SyncingItemsContainingVerificationCodes" = "Sincronizzazione elementi con codici di verifica in corso...";
"SyncingItemsContainingVerificationCodes" = "Sincronizzando elementi contenenti codici di verifica";
"UnlockBitwardenOnYourIPhoneToViewVerificationCodes" = "Sblocca Bitwarden sul tuo iPhone per visualizzare i codici di verifica";
"SetUpBitwardenToViewItemsContainingVerificationCodes" = "Configura Bitwarden per visualizzare gli elementi contenenti codici di verifica";
"Search" = "Cerca";

View File

@@ -5,6 +5,6 @@
"SyncingItemsContainingVerificationCodes" = "Syncing items containing verification codes";
"UnlockBitwardenOnYourIPhoneToViewVerificationCodes" = "Unlock Bitwarden on your iPhone to view verification codes";
"SetUpBitwardenToViewItemsContainingVerificationCodes" = "Set up Bitwarden to view items containing verification codes";
"Search" = "Ara";
"Search" = "Search";
"NoItemsFound" = "Hiç kayıt bulunamadı";
"SetUpAppleWatchPasscodeInOrderToUseBitwarden" = "Set up Apple Watch passcode in order to use Bitwarden";

View File

@@ -6,5 +6,5 @@
"UnlockBitwardenOnYourIPhoneToViewVerificationCodes" = "解锁您 iPhone 上的 Bitwarden 以查看验证码";
"SetUpBitwardenToViewItemsContainingVerificationCodes" = "设置 Bitwarden 以查看包含验证码的项目";
"Search" = "搜索";
"NoItemsFound" = "未找到任何目";
"NoItemsFound" = "未找到任何目";
"SetUpAppleWatchPasscodeInOrderToUseBitwarden" = "设置 Apple Watch 密码以使用 Bitwarden";