From 37f1a7087e251750c1094cb04a8d69d637a40e5f Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Wed, 10 May 2023 16:59:49 +0200 Subject: [PATCH 1/4] [PM-1748] Fix Watch TOTP details on Always On Display (#2515) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * PM-1748 Fix watchOS issue where the TOTP code wasn't being regenerated after always on display. Also, blurred totp code and timer value when entering in Always On Display * Fixed PR labeler for WatchOS changes * PM-1748 watchOS made username privacy sensitive for always on display * Revert "Fixed PR labeler for WatchOS changes" This reverts commit 3c55f380696ee0d6a6a363bcf4603bdae59c7d19. --------- Co-authored-by: Álison Fernandes --- .../Models/Mocks/CipherMock.swift | 2 +- .../ViewModels/CipherDetailsViewModel.swift | 24 +++++++++++-------- .../Views/CipherDetailsView.swift | 9 +++++++ .../Views/CipherItemView.swift | 1 + .../Views/CipherListView.swift | 1 + 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/watchOS/bitwarden/bitwarden WatchKit Extension/Models/Mocks/CipherMock.swift b/src/watchOS/bitwarden/bitwarden WatchKit Extension/Models/Mocks/CipherMock.swift index 543e6a99e..7d22dc39a 100644 --- a/src/watchOS/bitwarden/bitwarden WatchKit Extension/Models/Mocks/CipherMock.swift +++ b/src/watchOS/bitwarden/bitwarden WatchKit Extension/Models/Mocks/CipherMock.swift @@ -2,7 +2,7 @@ import Foundation struct CipherMock { static let ciphers:[Cipher] = [ - Cipher(id: "0", name: "1933", userId: "123123", login: Login(username: "thisisatest@testing.com", totp: "otpauth://account?period=10&secret=LLLLLLLLLLLLLLLL", uris: cipherLoginUris)), + Cipher(id: "0", name: "MySite", userId: "123123", login: Login(username: "test@testing.com", totp: "otpauth://account?period=10&secret=LLLLLLLLLLLLLLLL", uris: cipherLoginUris)), Cipher(id: "1", name: "GitHub", userId: "123123", login: Login(username: "thisisatest@testing.com", totp: "LLLLLLLLLLLLLLLL", uris: cipherLoginUris)), Cipher(id: "2", name: "No user", userId: "123123", login: Login(username: nil, totp: "otpauth://account?period=10&digits=8&algorithm=sha256&secret=LLLLLLLLLLLLLLLL", uris: cipherLoginUris)), Cipher(id: "3", name: "Site 2", userId: "123123", login: Login(username: "longtestemail000000@fastmailasdfasdf.com", totp: "otpauth://account?period=10&digits=7&algorithm=sha512&secret=LLLLLLLLLLLLLLLL", uris: cipherLoginUris)), diff --git a/src/watchOS/bitwarden/bitwarden WatchKit Extension/ViewModels/CipherDetailsViewModel.swift b/src/watchOS/bitwarden/bitwarden WatchKit Extension/ViewModels/CipherDetailsViewModel.swift index bfed0a30b..41663d9dd 100644 --- a/src/watchOS/bitwarden/bitwarden WatchKit Extension/ViewModels/CipherDetailsViewModel.swift +++ b/src/watchOS/bitwarden/bitwarden WatchKit Extension/ViewModels/CipherDetailsViewModel.swift @@ -34,30 +34,34 @@ class CipherDetailsViewModel: ObservableObject{ self.counter = self.period - mod self.progress = Double(self.counter) / Double(self.period) } + if mod == 0 || self.totpFormatted == "" { do { - var totpF = try TotpService.shared.GetCodeAsync(key: self.key) ?? "" - if totpF.count > 4 { - let halfIndex = totpF.index(totpF.startIndex, offsetBy: totpF.count / 2) - totpF = "\(totpF[totpF.startIndex.. 4 { + let halfIndex = totpF.index(totpF.startIndex, offsetBy: totpF.count / 2) + totpF = "\(totpF[totpF.startIndex.. Date: Thu, 11 May 2023 11:13:30 -0400 Subject: [PATCH 2/4] Dependency Updates (#2517) --- src/Android/Android.csproj | 17 ++++++++--------- src/App/App.csproj | 8 ++++---- src/Core/Core.csproj | 8 ++++---- src/iOS.Autofill/iOS.Autofill.csproj | 2 +- src/iOS.Extension/Info.plist | 2 +- src/iOS.Extension/iOS.Extension.csproj | 2 +- src/iOS.ShareExtension/Info.plist | 2 +- .../iOS.ShareExtension.csproj | 2 +- src/iOS/Info.plist | 2 +- src/iOS/iOS.csproj | 2 +- test/Common/Common.csproj | 10 +++++----- test/Core.Test/Core.Test.csproj | 10 +++++----- .../Models/Request/SendRequestTests.cs | 2 +- 13 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/Android/Android.csproj b/src/Android/Android.csproj index c285cad13..4b42db250 100644 --- a/src/Android/Android.csproj +++ b/src/Android/Android.csproj @@ -78,21 +78,20 @@ 1.9.0 - - - - + + + - 1.7.3 + 1.7.5 - 123.0.8 + 123.1.1.1 - - + + - 118.0.1.2 + 118.0.1.3 diff --git a/src/App/App.csproj b/src/App/App.csproj index 7901bcca6..83e1ee879 100644 --- a/src/App/App.csproj +++ b/src/App/App.csproj @@ -14,11 +14,11 @@ - - - + + + - + diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index bb55f7d47..216e148d7 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -28,12 +28,12 @@ - - - + + + - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/iOS.Autofill/iOS.Autofill.csproj b/src/iOS.Autofill/iOS.Autofill.csproj index ce5fc0b09..2be018c61 100644 --- a/src/iOS.Autofill/iOS.Autofill.csproj +++ b/src/iOS.Autofill/iOS.Autofill.csproj @@ -266,7 +266,7 @@ - 4.5.3 + 5.0.1 diff --git a/src/iOS.Extension/Info.plist b/src/iOS.Extension/Info.plist index 26bd5b749..0d913e4b2 100644 --- a/src/iOS.Extension/Info.plist +++ b/src/iOS.Extension/Info.plist @@ -3,7 +3,7 @@ MinimumOSVersion - 10.0 + 11.0 CFBundleDisplayName Bitwarden CFBundleName diff --git a/src/iOS.Extension/iOS.Extension.csproj b/src/iOS.Extension/iOS.Extension.csproj index 44b0891fc..a0b98f0fb 100644 --- a/src/iOS.Extension/iOS.Extension.csproj +++ b/src/iOS.Extension/iOS.Extension.csproj @@ -242,7 +242,7 @@ - 4.5.3 + 5.0.1 diff --git a/src/iOS.ShareExtension/Info.plist b/src/iOS.ShareExtension/Info.plist index 719ccde84..d86024116 100644 --- a/src/iOS.ShareExtension/Info.plist +++ b/src/iOS.ShareExtension/Info.plist @@ -19,7 +19,7 @@ CFBundleVersion 1 MinimumOSVersion - 10.0 + 11.0 NSExtension NSExtensionMainStoryboard diff --git a/src/iOS.ShareExtension/iOS.ShareExtension.csproj b/src/iOS.ShareExtension/iOS.ShareExtension.csproj index 3beee6f8d..57f079e41 100644 --- a/src/iOS.ShareExtension/iOS.ShareExtension.csproj +++ b/src/iOS.ShareExtension/iOS.ShareExtension.csproj @@ -167,7 +167,7 @@ - 4.5.3 + 5.0.1 diff --git a/src/iOS/Info.plist b/src/iOS/Info.plist index 273ab49b6..256054ab5 100644 --- a/src/iOS/Info.plist +++ b/src/iOS/Info.plist @@ -3,7 +3,7 @@ MinimumOSVersion - 10.0 + 11.0 CFBundleDisplayName Bitwarden CFBundleName diff --git a/src/iOS/iOS.csproj b/src/iOS/iOS.csproj index ba4127910..4a5c7c18e 100644 --- a/src/iOS/iOS.csproj +++ b/src/iOS/iOS.csproj @@ -195,7 +195,7 @@ - 1.7.3 + 1.7.5 diff --git a/test/Common/Common.csproj b/test/Common/Common.csproj index 3912b23c1..bcc5f133d 100644 --- a/test/Common/Common.csproj +++ b/test/Common/Common.csproj @@ -7,15 +7,15 @@ - - + + all runtime; build; native; contentfiles; analyzers - - - + + + diff --git a/test/Core.Test/Core.Test.csproj b/test/Core.Test/Core.Test.csproj index e1e4b96f0..df9d8d74b 100644 --- a/test/Core.Test/Core.Test.csproj +++ b/test/Core.Test/Core.Test.csproj @@ -7,15 +7,15 @@ - - - + + + all runtime; build; native; contentfiles; analyzers - - + + diff --git a/test/Core.Test/Models/Request/SendRequestTests.cs b/test/Core.Test/Models/Request/SendRequestTests.cs index 028dce25a..49c60bed4 100644 --- a/test/Core.Test/Models/Request/SendRequestTests.cs +++ b/test/Core.Test/Models/Request/SendRequestTests.cs @@ -14,7 +14,7 @@ namespace Bit.Core.Test.Models.Request { [Theory] [InlineCustomAutoData(new[] { typeof(TextSendCustomization) }, null)] - [InlineCustomAutoData(new[] { typeof(FileSendCustomization) }, 100)] + [InlineCustomAutoData(new[] { typeof(FileSendCustomization) }, 100L)] public void SendRequest_FromSend_Success(long? fileLength, Send send) { var request = new SendRequest(send, fileLength); From 1c8328f62dd4f1a29a00ce4b025a162487642596 Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Thu, 11 May 2023 18:41:32 +0200 Subject: [PATCH 3/4] [PM-1402] Refactor PasswordGenerationService alongside PolicyService (#2443) * PM-1402 Refactor pass generation service alongside policyservice * PM-1402 Refactor PasswordGenerationService and PolicyService to have a simpler code and more specific to each class * PM-1402 Fix format * PM-1402 Moved policy consts from PolicyService to Policy * PM-1402 fix crash due to lack of null checking * PM-1402 fix format * PM-1402 removed GetValueOrDefault() given that it was not needed and was changing the behavior --- .../Pages/Accounts/LoginSsoPageViewModel.cs | 5 +- .../Pages/Generator/GeneratorPageViewModel.cs | 2 +- .../SettingsPage/SettingsPageViewModel.cs | 14 +- .../IPasswordGenerationService.cs | 2 - src/Core/Abstractions/IPolicyService.cs | 3 +- .../Domain/PasswordGenerationOptions.cs | 118 ++++++-- src/Core/Models/Domain/Policy.cs | 32 ++ src/Core/Services/AuthService.cs | 2 +- .../Services/PasswordGenerationService.cs | 283 +++--------------- src/Core/Services/PolicyService.cs | 169 ++++++----- src/Core/Services/VaultTimeoutService.cs | 1 + src/Core/Utilities/ServiceContainer.cs | 3 +- 12 files changed, 282 insertions(+), 352 deletions(-) diff --git a/src/App/Pages/Accounts/LoginSsoPageViewModel.cs b/src/App/Pages/Accounts/LoginSsoPageViewModel.cs index c6da63df8..fbf9bf4f2 100644 --- a/src/App/Pages/Accounts/LoginSsoPageViewModel.cs +++ b/src/App/Pages/Accounts/LoginSsoPageViewModel.cs @@ -121,9 +121,8 @@ namespace Bit.App.Pages var ssoToken = response.Token; - - var passwordOptions = new PasswordGenerationOptions(true); - passwordOptions.Length = 64; + var passwordOptions = PasswordGenerationOptions.CreateDefault + .WithLength(64); var codeVerifier = await _passwordGenerationService.GeneratePasswordAsync(passwordOptions); var codeVerifierHash = await _cryptoFunctionService.HashAsync(codeVerifier, CryptoHashAlgorithm.Sha256); diff --git a/src/App/Pages/Generator/GeneratorPageViewModel.cs b/src/App/Pages/Generator/GeneratorPageViewModel.cs index 8af5548c5..78436352b 100644 --- a/src/App/Pages/Generator/GeneratorPageViewModel.cs +++ b/src/App/Pages/Generator/GeneratorPageViewModel.cs @@ -827,7 +827,7 @@ namespace Bit.App.Pages private void SetOptions() { _options.AllowAmbiguousChar = AllowAmbiguousChars; - _options.Type = PasswordTypeSelectedIndex == 1 ? "passphrase" : "password"; + _options.Type = PasswordTypeSelectedIndex == 1 ? PasswordGenerationOptions.TYPE_PASSPHRASE : PasswordGenerationOptions.TYPE_PASSWORD; _options.MinNumber = MinNumber; _options.MinSpecial = MinSpecial; _options.Special = Special; diff --git a/src/App/Pages/Settings/SettingsPage/SettingsPageViewModel.cs b/src/App/Pages/Settings/SettingsPage/SettingsPageViewModel.cs index d71bef46e..99e509373 100644 --- a/src/App/Pages/Settings/SettingsPage/SettingsPageViewModel.cs +++ b/src/App/Pages/Settings/SettingsPage/SettingsPageViewModel.cs @@ -131,7 +131,7 @@ namespace Bit.App.Pages { // if we have a vault timeout policy, we need to filter the timeout options _vaultTimeoutPolicy = (await _policyService.GetAll(PolicyType.MaximumVaultTimeout)).First(); - var policyMinutes = _policyService.GetPolicyInt(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_MINUTES); + var policyMinutes = _vaultTimeoutPolicy.GetInt(Policy.MINUTES_KEY); _vaultTimeoutOptions = _vaultTimeoutOptions.Where(t => t.Value <= policyMinutes && (t.Value > 0 || t.Value == CustomVaultTimeoutValue) && @@ -302,7 +302,7 @@ namespace Bit.App.Pages if (_vaultTimeoutPolicy != null) { - var maximumTimeout = _policyService.GetPolicyInt(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_MINUTES); + var maximumTimeout = _vaultTimeoutPolicy.GetInt(Policy.MINUTES_KEY); if (newTimeout > maximumTimeout) { @@ -382,7 +382,7 @@ namespace Bit.App.Pages public async Task VaultTimeoutActionAsync() { if (_vaultTimeoutPolicy != null && - !string.IsNullOrEmpty(_policyService.GetPolicyString(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_ACTION))) + !string.IsNullOrEmpty(_vaultTimeoutPolicy.GetString(Policy.MINUTES_KEY))) { // do nothing if we have a policy set return; @@ -610,8 +610,8 @@ namespace Bit.App.Pages } if (_vaultTimeoutPolicy != null) { - var policyMinutes = _policyService.GetPolicyInt(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_MINUTES); - var policyAction = _policyService.GetPolicyString(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_ACTION); + var policyMinutes = _vaultTimeoutPolicy.GetInt(Policy.MINUTES_KEY); + var policyAction = _vaultTimeoutPolicy.GetString(Policy.ACTION_KEY); if (policyMinutes.HasValue || !string.IsNullOrWhiteSpace(policyAction)) { @@ -625,14 +625,14 @@ namespace Bit.App.Pages else if (!policyMinutes.HasValue && !string.IsNullOrWhiteSpace(policyAction)) { policyAlert = string.Format(AppResources.VaultTimeoutActionPolicyInEffect, - policyAction == PolicyService.TIMEOUT_POLICY_ACTION_LOCK ? AppResources.Lock : AppResources.LogOut); + policyAction == Policy.ACTION_LOCK ? AppResources.Lock : AppResources.LogOut); } else { policyAlert = string.Format(AppResources.VaultTimeoutPolicyWithActionInEffect, Math.Floor((float)policyMinutes / 60), policyMinutes % 60, - policyAction == PolicyService.TIMEOUT_POLICY_ACTION_LOCK ? AppResources.Lock : AppResources.LogOut); + policyAction == Policy.ACTION_LOCK ? AppResources.Lock : AppResources.LogOut); } securityItems.Insert(0, new SettingsPageListItem { diff --git a/src/Core/Abstractions/IPasswordGenerationService.cs b/src/Core/Abstractions/IPasswordGenerationService.cs index 74f46ea7c..25062f2ac 100644 --- a/src/Core/Abstractions/IPasswordGenerationService.cs +++ b/src/Core/Abstractions/IPasswordGenerationService.cs @@ -15,8 +15,6 @@ namespace Bit.Core.Abstractions Task GeneratePasswordAsync(PasswordGenerationOptions options); Task> GetHistoryAsync(); Task<(PasswordGenerationOptions, PasswordGeneratorPolicyOptions)> GetOptionsAsync(); - Task<(PasswordGenerationOptions, PasswordGeneratorPolicyOptions)> - EnforcePasswordGeneratorPoliciesOnOptionsAsync(PasswordGenerationOptions options); Result PasswordStrength(string password, List userInputs = null); Task SaveOptionsAsync(PasswordGenerationOptions options); void NormalizeOptions(PasswordGenerationOptions options, PasswordGeneratorPolicyOptions enforcedPolicyOptions); diff --git a/src/Core/Abstractions/IPolicyService.cs b/src/Core/Abstractions/IPolicyService.cs index 8acca2c9a..75ca6168e 100644 --- a/src/Core/Abstractions/IPolicyService.cs +++ b/src/Core/Abstractions/IPolicyService.cs @@ -19,8 +19,7 @@ namespace Bit.Core.Abstractions Tuple GetResetPasswordPolicyOptions(IEnumerable policies, string orgId); Task PolicyAppliesToUser(PolicyType policyType, Func policyFilter = null, string userId = null); - int? GetPolicyInt(Policy policy, string key); - string GetPolicyString(Policy policy, string key); Task ShouldShowVaultFilterAsync(); + Task GetPasswordGeneratorPolicyOptionsAsync(); } } diff --git a/src/Core/Models/Domain/PasswordGenerationOptions.cs b/src/Core/Models/Domain/PasswordGenerationOptions.cs index 16afec6bf..bab849661 100644 --- a/src/Core/Models/Domain/PasswordGenerationOptions.cs +++ b/src/Core/Models/Domain/PasswordGenerationOptions.cs @@ -2,29 +2,29 @@ { public class PasswordGenerationOptions { - public PasswordGenerationOptions() { } + public const string TYPE_PASSWORD = "password"; + public const string TYPE_PASSPHRASE = "passphrase"; - public PasswordGenerationOptions(bool defaultOptions) + public static PasswordGenerationOptions CreateDefault => new PasswordGenerationOptions { - if (defaultOptions) - { - Length = 14; - AllowAmbiguousChar = true; - Number = true; - MinNumber = 1; - Uppercase = true; - MinUppercase = 0; - Lowercase = true; - MinLowercase = 0; - Special = false; - MinSpecial = 1; - Type = "password"; - NumWords = 3; - WordSeparator = "-"; - Capitalize = false; - IncludeNumber = false; - } - } + Length = 14, + AllowAmbiguousChar = true, + Number = true, + MinNumber = 1, + Uppercase = true, + MinUppercase = 0, + Lowercase = true, + MinLowercase = 0, + Special = false, + MinSpecial = 1, + Type = TYPE_PASSWORD, + NumWords = 3, + WordSeparator = "-", + Capitalize = false, + IncludeNumber = false + }; + + public PasswordGenerationOptions() { } public int? Length { get; set; } public bool? AllowAmbiguousChar { get; set; } @@ -42,6 +42,12 @@ public bool? Capitalize { get; set; } public bool? IncludeNumber { get; set; } + public PasswordGenerationOptions WithLength(int? length) + { + Length = length; + return this; + } + public void Merge(PasswordGenerationOptions defaults) { Length = Length ?? defaults.Length; @@ -60,5 +66,75 @@ Capitalize = Capitalize ?? defaults.Capitalize; IncludeNumber = IncludeNumber ?? defaults.IncludeNumber; } + + public void EnforcePolicy(PasswordGeneratorPolicyOptions enforcedPolicyOptions) + { + if (enforcedPolicyOptions is null) + { + return; + } + + if (Length < enforcedPolicyOptions.MinLength) + { + Length = enforcedPolicyOptions.MinLength; + } + + if (enforcedPolicyOptions.UseUppercase) + { + Uppercase = true; + } + + if (enforcedPolicyOptions.UseLowercase) + { + Lowercase = true; + } + + if (enforcedPolicyOptions.UseNumbers) + { + Number = true; + } + + if (MinNumber < enforcedPolicyOptions.NumberCount) + { + MinNumber = enforcedPolicyOptions.NumberCount; + } + + if (enforcedPolicyOptions.UseSpecial) + { + Special = true; + } + + if (MinSpecial < enforcedPolicyOptions.SpecialCount) + { + MinSpecial = enforcedPolicyOptions.SpecialCount; + } + + // Must normalize these fields because the receiving call expects all options to pass the current rules + if (MinSpecial + MinNumber > Length) + { + MinSpecial = Length - MinNumber; + } + + if (NumWords < enforcedPolicyOptions.MinNumberOfWords) + { + NumWords = enforcedPolicyOptions.MinNumberOfWords; + } + + if (enforcedPolicyOptions.Capitalize) + { + Capitalize = true; + } + + if (enforcedPolicyOptions.IncludeNumber) + { + IncludeNumber = true; + } + + // Force default type if password/passphrase selected via policy + if (enforcedPolicyOptions.DefaultType == TYPE_PASSWORD || enforcedPolicyOptions.DefaultType == TYPE_PASSPHRASE) + { + Type = enforcedPolicyOptions.DefaultType; + } + } } } diff --git a/src/Core/Models/Domain/Policy.cs b/src/Core/Models/Domain/Policy.cs index a84b095d0..3d58c2fb8 100644 --- a/src/Core/Models/Domain/Policy.cs +++ b/src/Core/Models/Domain/Policy.cs @@ -6,6 +6,11 @@ namespace Bit.Core.Models.Domain { public class Policy : Domain { + public const string MINUTES_KEY = "minutes"; + public const string ACTION_KEY = "action"; + public const string ACTION_LOCK = "lock"; + public const string ACTION_LOGOUT = "logOut"; + public Policy() { } public Policy(PolicyData obj) @@ -22,5 +27,32 @@ namespace Bit.Core.Models.Domain public PolicyType Type { get; set; } public Dictionary Data { get; set; } public bool Enabled { get; set; } + + public int? GetInt(string key) + { + if (Data.TryGetValue(key, out var val) && val != null) + { + return (int)(long)val; + } + return null; + } + + public bool? GetBool(string key) + { + if (Data.TryGetValue(key, out var val) && val != null) + { + return (bool)val; + } + return null; + } + + public string GetString(string key) + { + if (Data.TryGetValue(key, out var val)) + { + return (string)val; + } + return null; + } } } diff --git a/src/Core/Services/AuthService.cs b/src/Core/Services/AuthService.cs index 5fa8a2115..92cbadd3b 100644 --- a/src/Core/Services/AuthService.cs +++ b/src/Core/Services/AuthService.cs @@ -605,7 +605,7 @@ namespace Bit.Core.Services var generatedFingerprintPhrase = await _cryptoService.GetFingerprintAsync(email, keyPair.Item1); var fingerprintPhrase = string.Join("-", generatedFingerprintPhrase); var publicB64 = Convert.ToBase64String(keyPair.Item1); - var accessCode = await _passwordGenerationService.GeneratePasswordAsync(new PasswordGenerationOptions(true) { Length = 25 }); + var accessCode = await _passwordGenerationService.GeneratePasswordAsync(PasswordGenerationOptions.CreateDefault.WithLength(25)); var passwordlessCreateLoginRequest = new PasswordlessCreateLoginRequest(email, publicB64, deviceId, accessCode, AuthRequestType.AuthenticateAndUnlock, fingerprintPhrase); var response = await _apiService.PostCreateRequestAsync(passwordlessCreateLoginRequest); diff --git a/src/Core/Services/PasswordGenerationService.cs b/src/Core/Services/PasswordGenerationService.cs index e689616c2..3210cccad 100644 --- a/src/Core/Services/PasswordGenerationService.cs +++ b/src/Core/Services/PasswordGenerationService.cs @@ -6,7 +6,6 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Bit.Core.Abstractions; -using Bit.Core.Enums; using Bit.Core.Models.Domain; using Bit.Core.Utilities; using Zxcvbn; @@ -15,17 +14,17 @@ namespace Bit.Core.Services { public class PasswordGenerationService : IPasswordGenerationService { - private const int MaxPasswordsInHistory = 100; - private const string LowercaseCharSet = "abcdefghijkmnopqrstuvwxyz"; - private const string UppercaseCharSet = "ABCDEFGHJKLMNPQRSTUVWXYZ"; - private const string NumberCharSet = "23456789"; - private const string SpecialCharSet = "!@#$%^&*"; + private const int MAX_PASSWORDS_IN_HISTORY = 100; + private const string LOWERCASE_CHAR_SET = "abcdefghijkmnopqrstuvwxyz"; + private const string UPPERCASE_CHAR_SET = "ABCDEFGHJKLMNPQRSTUVWXYZ"; + private const string NUMER_CHAR_SET = "23456789"; + private const string SPECIAL_CHAR_SET = "!@#$%^&*"; private readonly ICryptoService _cryptoService; private readonly IStateService _stateService; private readonly ICryptoFunctionService _cryptoFunctionService; private readonly IPolicyService _policyService; - private PasswordGenerationOptions _defaultOptions = new PasswordGenerationOptions(true); + private PasswordGenerationOptions _defaultOptions = PasswordGenerationOptions.CreateDefault; private PasswordGenerationOptions _optionsCache; private List _history; @@ -45,7 +44,7 @@ namespace Bit.Core.Services { // Overload defaults with given options options.Merge(_defaultOptions); - if (options.Type == "passphrase") + if (options.Type == PasswordGenerationOptions.TYPE_PASSPHRASE) { return await GeneratePassphraseAsync(options); } @@ -54,30 +53,30 @@ namespace Bit.Core.Services SanitizePasswordLength(options, true); var positionsBuilder = new StringBuilder(); - if (options.Lowercase.GetValueOrDefault() && options.MinLowercase.GetValueOrDefault() > 0) + if (options.Lowercase.GetValueOrDefault() && options.MinLowercase > 0) { - for (int i = 0; i < options.MinLowercase.GetValueOrDefault(); i++) + for (int i = 0; i < options.MinLowercase; i++) { positionsBuilder.Append("l"); } } - if (options.Uppercase.GetValueOrDefault() && options.MinUppercase.GetValueOrDefault() > 0) + if (options.Uppercase.GetValueOrDefault() && options.MinUppercase > 0) { - for (int i = 0; i < options.MinUppercase.GetValueOrDefault(); i++) + for (int i = 0; i < options.MinUppercase; i++) { positionsBuilder.Append("u"); } } - if (options.Number.GetValueOrDefault() && options.MinNumber.GetValueOrDefault() > 0) + if (options.Number.GetValueOrDefault() && options.MinNumber > 0) { - for (int i = 0; i < options.MinNumber.GetValueOrDefault(); i++) + for (int i = 0; i < options.MinNumber; i++) { positionsBuilder.Append("n"); } } - if (options.Special.GetValueOrDefault() && options.MinSpecial.GetValueOrDefault() > 0) + if (options.Special.GetValueOrDefault() && options.MinSpecial > 0) { - for (int i = 0; i < options.MinSpecial.GetValueOrDefault(); i++) + for (int i = 0; i < options.MinSpecial; i++) { positionsBuilder.Append("s"); } @@ -92,68 +91,68 @@ namespace Bit.Core.Services .OrderBy(a => _cryptoFunctionService.RandomNumber()).ToArray(); // Build out other character sets - var allCharSet = string.Empty; - var lowercaseCharSet = LowercaseCharSet; + var allCharSet = new StringBuilder(); + + var lowercaseCharSet = LOWERCASE_CHAR_SET; if (options.AllowAmbiguousChar.GetValueOrDefault()) { lowercaseCharSet = string.Concat(lowercaseCharSet, "l"); } if (options.Lowercase.GetValueOrDefault()) { - allCharSet = string.Concat(allCharSet, lowercaseCharSet); + allCharSet.Append(lowercaseCharSet); } - var uppercaseCharSet = UppercaseCharSet; + var uppercaseCharSet = UPPERCASE_CHAR_SET; if (options.AllowAmbiguousChar.GetValueOrDefault()) { uppercaseCharSet = string.Concat(uppercaseCharSet, "IO"); } if (options.Uppercase.GetValueOrDefault()) { - allCharSet = string.Concat(allCharSet, uppercaseCharSet); + allCharSet.Append(uppercaseCharSet); } - var numberCharSet = NumberCharSet; + var numberCharSet = NUMER_CHAR_SET; if (options.AllowAmbiguousChar.GetValueOrDefault()) { numberCharSet = string.Concat(numberCharSet, "01"); } if (options.Number.GetValueOrDefault()) { - allCharSet = string.Concat(allCharSet, numberCharSet); + allCharSet.Append(numberCharSet); } - var specialCharSet = SpecialCharSet; if (options.Special.GetValueOrDefault()) { - allCharSet = string.Concat(allCharSet, specialCharSet); + allCharSet.Append(SPECIAL_CHAR_SET); } var password = new StringBuilder(); for (var i = 0; i < options.Length.GetValueOrDefault(); i++) { - var positionChars = string.Empty; + var charSetOnCurrentPosition = string.Empty; switch (positions[i]) { case 'l': - positionChars = lowercaseCharSet; + charSetOnCurrentPosition = lowercaseCharSet; break; case 'u': - positionChars = uppercaseCharSet; + charSetOnCurrentPosition = uppercaseCharSet; break; case 'n': - positionChars = numberCharSet; + charSetOnCurrentPosition = numberCharSet; break; case 's': - positionChars = specialCharSet; + charSetOnCurrentPosition = SPECIAL_CHAR_SET; break; case 'a': - positionChars = allCharSet; + charSetOnCurrentPosition = allCharSet.ToString(); break; } - var randomCharIndex = await _cryptoService.RandomNumberAsync(0, positionChars.Length - 1); - password.Append(positionChars[randomCharIndex]); + var randomCharIndex = await _cryptoService.RandomNumberAsync(0, charSetOnCurrentPosition.Length - 1); + password.Append(charSetOnCurrentPosition[randomCharIndex]); } return password.ToString(); @@ -168,7 +167,7 @@ namespace Bit.Core.Services public async Task GeneratePassphraseAsync(PasswordGenerationOptions options) { options.Merge(_defaultOptions); - if (options.NumWords.GetValueOrDefault() <= 2) + if (options.NumWords <= 2) { options.NumWords = _defaultOptions.NumWords; } @@ -221,179 +220,10 @@ namespace Bit.Core.Services } } - var (enforcedOptions, enforcedPolicyOptions) = await EnforcePasswordGeneratorPoliciesOnOptionsAsync( - _optionsCache); - _optionsCache = enforcedOptions; - return (_optionsCache, enforcedPolicyOptions); - } + var policyOptions = await _policyService.GetPasswordGeneratorPolicyOptionsAsync(); + _optionsCache.EnforcePolicy(policyOptions); - public async Task<(PasswordGenerationOptions, PasswordGeneratorPolicyOptions)> - EnforcePasswordGeneratorPoliciesOnOptionsAsync(PasswordGenerationOptions options) - { - var enforcedPolicyOptions = await GetPasswordGeneratorPolicyOptions(); - if (enforcedPolicyOptions != null) - { - if (options.Length < enforcedPolicyOptions.MinLength) - { - options.Length = enforcedPolicyOptions.MinLength; - } - - if (enforcedPolicyOptions.UseUppercase) - { - options.Uppercase = true; - } - - if (enforcedPolicyOptions.UseLowercase) - { - options.Lowercase = true; - } - - if (enforcedPolicyOptions.UseNumbers) - { - options.Number = true; - } - - if (options.MinNumber < enforcedPolicyOptions.NumberCount) - { - options.MinNumber = enforcedPolicyOptions.NumberCount; - } - - if (enforcedPolicyOptions.UseSpecial) - { - options.Special = true; - } - - if (options.MinSpecial < enforcedPolicyOptions.SpecialCount) - { - options.MinSpecial = enforcedPolicyOptions.SpecialCount; - } - - // Must normalize these fields because the receiving call expects all options to pass the current rules - if (options.MinSpecial + options.MinNumber > options.Length) - { - options.MinSpecial = options.Length - options.MinNumber; - } - - if (options.NumWords < enforcedPolicyOptions.MinNumberOfWords) - { - options.NumWords = enforcedPolicyOptions.MinNumberOfWords; - } - - if (enforcedPolicyOptions.Capitalize) - { - options.Capitalize = true; - } - - if (enforcedPolicyOptions.IncludeNumber) - { - options.IncludeNumber = true; - } - - // Force default type if password/passphrase selected via policy - if (enforcedPolicyOptions.DefaultType == "password" || enforcedPolicyOptions.DefaultType == "passphrase") - { - options.Type = enforcedPolicyOptions.DefaultType; - } - } - else - { - // UI layer expects an instantiated object to prevent more explicit null checks - enforcedPolicyOptions = new PasswordGeneratorPolicyOptions(); - } - - return (options, enforcedPolicyOptions); - } - - public async Task GetPasswordGeneratorPolicyOptions() - { - var policies = await _policyService.GetAll(PolicyType.PasswordGenerator); - PasswordGeneratorPolicyOptions enforcedOptions = null; - - if (policies == null || !policies.Any()) - { - return enforcedOptions; - } - - foreach (var currentPolicy in policies) - { - if (!currentPolicy.Enabled || currentPolicy.Data == null) - { - continue; - } - - if (enforcedOptions == null) - { - enforcedOptions = new PasswordGeneratorPolicyOptions(); - } - - var defaultType = GetPolicyString(currentPolicy, "defaultType"); - if (defaultType != null && enforcedOptions.DefaultType != "password") - { - enforcedOptions.DefaultType = defaultType; - } - - var minLength = GetPolicyInt(currentPolicy, "minLength"); - if (minLength != null && (int)(long)minLength > enforcedOptions.MinLength) - { - enforcedOptions.MinLength = (int)(long)minLength; - } - - var useUpper = GetPolicyBool(currentPolicy, "useUpper"); - if (useUpper != null && (bool)useUpper) - { - enforcedOptions.UseUppercase = true; - } - - var useLower = GetPolicyBool(currentPolicy, "useLower"); - if (useLower != null && (bool)useLower) - { - enforcedOptions.UseLowercase = true; - } - - var useNumbers = GetPolicyBool(currentPolicy, "useNumbers"); - if (useNumbers != null && (bool)useNumbers) - { - enforcedOptions.UseNumbers = true; - } - - var minNumbers = GetPolicyInt(currentPolicy, "minNumbers"); - if (minNumbers != null && (int)(long)minNumbers > enforcedOptions.NumberCount) - { - enforcedOptions.NumberCount = (int)(long)minNumbers; - } - - var useSpecial = GetPolicyBool(currentPolicy, "useSpecial"); - if (useSpecial != null && (bool)useSpecial) - { - enforcedOptions.UseSpecial = true; - } - - var minSpecial = GetPolicyInt(currentPolicy, "minSpecial"); - if (minSpecial != null && (int)(long)minSpecial > enforcedOptions.SpecialCount) - { - enforcedOptions.SpecialCount = (int)(long)minSpecial; - } - - var minNumberWords = GetPolicyInt(currentPolicy, "minNumberWords"); - if (minNumberWords != null && (int)(long)minNumberWords > enforcedOptions.MinNumberOfWords) - { - enforcedOptions.MinNumberOfWords = (int)(long)minNumberWords; - } - - var capitalize = GetPolicyBool(currentPolicy, "capitalize"); - if (capitalize != null && (bool)capitalize) - { - enforcedOptions.Capitalize = true; - } - - var includeNumber = GetPolicyBool(currentPolicy, "includeNumber"); - if (includeNumber != null && (bool)includeNumber) - { - enforcedOptions.IncludeNumber = true; - } - } - - return enforcedOptions; + return (_optionsCache, policyOptions ?? new PasswordGeneratorPolicyOptions()); } public List GetPasswordStrengthUserInput(string email) @@ -409,45 +239,6 @@ namespace Bit.Core.Services return new List(data); } - private int? GetPolicyInt(Policy policy, string key) - { - if (policy.Data.ContainsKey(key)) - { - var value = policy.Data[key]; - if (value != null) - { - return (int)(long)value; - } - } - return null; - } - - private bool? GetPolicyBool(Policy policy, string key) - { - if (policy.Data.ContainsKey(key)) - { - var value = policy.Data[key]; - if (value != null) - { - return (bool)value; - } - } - return null; - } - - private string GetPolicyString(Policy policy, string key) - { - if (policy.Data.ContainsKey(key)) - { - var value = policy.Data[key]; - if (value != null) - { - return (string)value; - } - } - return null; - } - public async Task SaveOptionsAsync(PasswordGenerationOptions options) { await _stateService.SetPasswordGenerationOptionsAsync(options); @@ -485,7 +276,7 @@ namespace Bit.Core.Services token.ThrowIfCancellationRequested(); currentHistory.Insert(0, new GeneratedPasswordHistory { Password = password, Date = DateTime.UtcNow }); // Remove old items. - if (currentHistory.Count > MaxPasswordsInHistory) + if (currentHistory.Count > MAX_PASSWORDS_IN_HISTORY) { currentHistory.RemoveAt(currentHistory.Count - 1); } diff --git a/src/Core/Services/PolicyService.cs b/src/Core/Services/PolicyService.cs index b6922dd56..9301763ac 100644 --- a/src/Core/Services/PolicyService.cs +++ b/src/Core/Services/PolicyService.cs @@ -17,11 +17,6 @@ namespace Bit.Core.Services private IEnumerable _policyCache; - public const string TIMEOUT_POLICY_MINUTES = "minutes"; - public const string TIMEOUT_POLICY_ACTION = "action"; - public const string TIMEOUT_POLICY_ACTION_LOCK = "lock"; - public const string TIMEOUT_POLICY_ACTION_LOGOUT = "logOut"; - public PolicyService( IStateService stateService, IOrganizationService organizationService) @@ -51,10 +46,8 @@ namespace Bit.Core.Services { return _policyCache.Where(p => p.Type == type).ToList(); } - else - { - return _policyCache; - } + + return _policyCache; } public async Task Replace(Dictionary policies, string userId = null) @@ -77,7 +70,7 @@ namespace Bit.Core.Services public async Task UpdateVaultTimeoutFromPolicyAsync(Policy policy, string userId = null) { - var policyTimeout = GetPolicyInt(policy, PolicyService.TIMEOUT_POLICY_MINUTES); + var policyTimeout = policy.GetInt(Policy.MINUTES_KEY); if (policyTimeout != null) { var vaultTimeout = await _stateService.GetVaultTimeoutAsync(userId); @@ -92,11 +85,11 @@ namespace Bit.Core.Services } } - var policyAction = GetPolicyString(policy, PolicyService.TIMEOUT_POLICY_ACTION); + var policyAction = policy.GetString(Policy.ACTION_KEY); if (!string.IsNullOrEmpty(policyAction)) { var vaultTimeoutAction = await _stateService.GetVaultTimeoutActionAsync(userId); - var action = policyAction == PolicyService.TIMEOUT_POLICY_ACTION_LOCK ? VaultTimeoutAction.Lock : VaultTimeoutAction.Logout; + var action = policyAction == Policy.ACTION_LOCK ? VaultTimeoutAction.Lock : VaultTimeoutAction.Logout; if (vaultTimeoutAction != action) { await _stateService.SetVaultTimeoutActionAsync(action, userId); @@ -107,71 +100,63 @@ namespace Bit.Core.Services public async Task GetMasterPasswordPolicyOptions( IEnumerable policies = null, string userId = null) { - MasterPasswordPolicyOptions enforcedOptions = null; - if (policies == null) { policies = await GetAll(PolicyType.MasterPassword, userId); + if (policies == null) + { + return null; + } } else { policies = policies.Where(p => p.Type == PolicyType.MasterPassword); } - if (policies == null || !policies.Any()) + policies = policies.Where(p => p.Enabled && p.Data != null); + + if (!policies.Any()) { - return enforcedOptions; + return null; } + var enforcedOptions = new MasterPasswordPolicyOptions(); + foreach (var currentPolicy in policies) { - if (!currentPolicy.Enabled || currentPolicy.Data == null) + var minComplexity = currentPolicy.GetInt("minComplexity"); + if (minComplexity > enforcedOptions.MinComplexity) { - continue; + enforcedOptions.MinComplexity = minComplexity.Value; } - if (enforcedOptions == null) + var minLength = currentPolicy.GetInt("minLength"); + if (minLength > enforcedOptions.MinLength) { - enforcedOptions = new MasterPasswordPolicyOptions(); + enforcedOptions.MinLength = minLength.Value; } - var minComplexity = GetPolicyInt(currentPolicy, "minComplexity"); - if (minComplexity != null && (int)(long)minComplexity > enforcedOptions.MinComplexity) - { - enforcedOptions.MinComplexity = (int)(long)minComplexity; - } - - var minLength = GetPolicyInt(currentPolicy, "minLength"); - if (minLength != null && (int)(long)minLength > enforcedOptions.MinLength) - { - enforcedOptions.MinLength = (int)(long)minLength; - } - - var requireUpper = GetPolicyBool(currentPolicy, "requireUpper"); - if (requireUpper == true) + if (currentPolicy.GetBool("requireUpper") == true) { enforcedOptions.RequireUpper = true; } - var requireLower = GetPolicyBool(currentPolicy, "requireLower"); - if (requireLower == true) + if (currentPolicy.GetBool("requireLower") == true) { enforcedOptions.RequireLower = true; } - var requireNumbers = GetPolicyBool(currentPolicy, "requireNumbers"); - if (requireNumbers == true) + if (currentPolicy.GetBool("requireNumbers") == true) { enforcedOptions.RequireNumbers = true; } - var requireSpecial = GetPolicyBool(currentPolicy, "requireSpecial"); - if (requireSpecial == true) + if (currentPolicy.GetBool("requireSpecial") == true) { enforcedOptions.RequireSpecial = true; } - var enforceOnLogin = GetPolicyBool(currentPolicy, "enforceOnLogin"); + var enforceOnLogin = currentPolicy.GetBool("enforceOnLogin"); if (enforceOnLogin == true) { enforcedOptions.EnforceOnLogin = true; @@ -234,7 +219,7 @@ namespace Bit.Core.Services var policy = policies.FirstOrDefault(p => p.OrganizationId == orgId && p.Type == PolicyType.ResetPassword && p.Enabled); - resetPasswordPolicyOptions.AutoEnrollEnabled = GetPolicyBool(policy, "autoEnrollEnabled") ?? false; + resetPasswordPolicyOptions.AutoEnrollEnabled = policy.GetBool("autoEnrollEnabled") ?? false; return new Tuple(resetPasswordPolicyOptions, policy != null); } @@ -280,23 +265,6 @@ namespace Bit.Core.Services return organization.isExemptFromPolicies; } - public int? GetPolicyInt(Policy policy, string key) - { - if (policy.Data.ContainsKey(key)) - { - var value = policy.Data[key]; - if (value != null) - { - return (int)(long)value; - } - } - return null; - } - - public string GetPolicyString(Policy policy, string key) => - policy.Data.TryGetValue(key, out var val) ? val as string : null; - - public async Task ShouldShowVaultFilterAsync() { var personalOwnershipPolicyApplies = await PolicyAppliesToUser(PolicyType.PersonalOwnership); @@ -309,19 +277,86 @@ namespace Bit.Core.Services return organizations?.Any() ?? false; } - private bool? GetPolicyBool(Policy policy, string key) + public async Task GetPasswordGeneratorPolicyOptionsAsync() { - if (policy.Data.ContainsKey(key)) + var policies = await GetAll(PolicyType.PasswordGenerator); + if (policies == null) { - var value = policy.Data[key]; - if (value != null) + return null; + } + + var actualPolicies = policies.Where(p => p.Enabled && p.Data != null); + if (!actualPolicies.Any()) + { + return null; + } + + var enforcedOptions = new PasswordGeneratorPolicyOptions(); + + foreach (var currentPolicy in actualPolicies) + { + var defaultType = currentPolicy.GetString("defaultType"); + if (defaultType != null && enforcedOptions.DefaultType != PasswordGenerationOptions.TYPE_PASSWORD) { - return (bool)value; + enforcedOptions.DefaultType = defaultType; + } + + var minLength = currentPolicy.GetInt("minLength"); + if (minLength > enforcedOptions.MinLength) + { + enforcedOptions.MinLength = minLength.Value; + } + + if (currentPolicy.GetBool("useUpper") == true) + { + enforcedOptions.UseUppercase = true; + } + + if (currentPolicy.GetBool("useLower") == true) + { + enforcedOptions.UseLowercase = true; + } + + if (currentPolicy.GetBool("useNumbers") == true) + { + enforcedOptions.UseNumbers = true; + } + + var minNumbers = currentPolicy.GetInt("minNumbers"); + if (minNumbers > enforcedOptions.NumberCount) + { + enforcedOptions.NumberCount = minNumbers.Value; + } + + if (currentPolicy.GetBool("useSpecial") == true) + { + enforcedOptions.UseSpecial = true; + } + + var minSpecial = currentPolicy.GetInt("minSpecial"); + if (minSpecial > enforcedOptions.SpecialCount) + { + enforcedOptions.SpecialCount = minSpecial.Value; + } + + var minNumberWords = currentPolicy.GetInt("minNumberWords"); + if (minNumberWords > enforcedOptions.MinNumberOfWords) + { + enforcedOptions.MinNumberOfWords = minNumberWords.Value; + } + + if (currentPolicy.GetBool("capitalize") == true) + { + enforcedOptions.Capitalize = true; + } + + if (currentPolicy.GetBool("includeNumber") == true) + { + enforcedOptions.IncludeNumber = true; } } - return null; + + return enforcedOptions; } - - } } diff --git a/src/Core/Services/VaultTimeoutService.cs b/src/Core/Services/VaultTimeoutService.cs index eb800c984..f5bd7d4bd 100644 --- a/src/Core/Services/VaultTimeoutService.cs +++ b/src/Core/Services/VaultTimeoutService.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Bit.Core.Abstractions; using Bit.Core.Enums; +using Bit.Core.Models.Domain; namespace Bit.Core.Services { diff --git a/src/Core/Utilities/ServiceContainer.cs b/src/Core/Utilities/ServiceContainer.cs index 3f8400497..c3b6bbd65 100644 --- a/src/Core/Utilities/ServiceContainer.cs +++ b/src/Core/Utilities/ServiceContainer.cs @@ -75,8 +75,7 @@ namespace Bit.Core.Utilities messagingService.Send("logout", extras); return Task.CompletedTask; }); - var passwordGenerationService = new PasswordGenerationService(cryptoService, stateService, - cryptoFunctionService, policyService); + var passwordGenerationService = new PasswordGenerationService(cryptoService, stateService, cryptoFunctionService, policyService); var totpService = new TotpService(cryptoFunctionService); var authService = new AuthService(cryptoService, cryptoFunctionService, apiService, stateService, tokenService, appIdService, i18nService, platformUtilsService, messagingService, vaultTimeoutService, From 9d6b938ba9048227492a3cb73249f84f00c193fd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 11 May 2023 19:42:27 +0200 Subject: [PATCH 4/4] Autosync the updated translations (#2519) Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- src/App/Resources/AppResources.bn.resx | 174 ++++++------- src/App/Resources/AppResources.de.resx | 2 +- src/App/Resources/AppResources.el.resx | 12 +- src/App/Resources/AppResources.fi.resx | 6 +- src/App/Resources/AppResources.fr.resx | 4 +- src/App/Resources/AppResources.ro.resx | 4 +- src/App/Resources/AppResources.sl.resx | 274 ++++++++++---------- src/App/Resources/AppResources.sr.resx | 4 +- src/App/Resources/AppResources.zh-Hans.resx | 2 +- store/apple/sl/copy.resx | 43 ++- store/google/sl/copy.resx | 50 ++-- 11 files changed, 287 insertions(+), 288 deletions(-) diff --git a/src/App/Resources/AppResources.bn.resx b/src/App/Resources/AppResources.bn.resx index da4c6489e..c7c2ff9fb 100644 --- a/src/App/Resources/AppResources.bn.resx +++ b/src/App/Resources/AppResources.bn.resx @@ -160,7 +160,7 @@ The button text that allows a user to copy the login's username to their clipboard. - Credits + কৃতিত্ব Title for page that we use to give credit to resources that we use. @@ -168,11 +168,11 @@ Delete an entity (verb). - Deleting... + মোছা হচ্ছে... Message shown when interacting with the server - Do you really want to delete? This cannot be undone. + আপনি কি সত্যিই মুছে ফেলতে চান? এটিকে পূর্বের মত করা যাবে না।. Confirmation alert message when deleteing something. @@ -190,16 +190,16 @@ Full label for a email address. - Email us + আমাদের ইমেইল করুন - Email us directly to get help or leave feedback. + সাহায্য পেতে বা মতামত দিতে সরাসরি আমাদের ইমেল করুন। - Enter your PIN code. + আপনার পিন কোডটি প্রবেশ করান - Favorites + পছন্দসমূহ Title for your favorite items in the vault. @@ -216,7 +216,7 @@ Label for a folder. - New folder created. + নতুন ফোল্ডার তৈরি হয়েছে। Folder deleted. @@ -276,7 +276,7 @@ আপনি লগ আউট করতে চান? - Remove account + অ্যাকাউন্ট অপসারণ করুন Are you sure you want to remove this account? @@ -315,30 +315,30 @@ Label for notes. - Ok + ঠিক আছে Acknowledgement. - Password + পাসওয়ার্ড Label for a password. - Save + সংরক্ষণ করুন Button text for a save operation (verb). - Move + স্থানান্তর করুন Saving... Message shown when interacting with the server - Settings + সেটিংস The title for the settings page. - Show + দেখান Reveal a hidden value (password). @@ -353,7 +353,7 @@ The title for the sync page. - Thank you + ধন্যবাদ Tools @@ -388,29 +388,29 @@ Verify PIN - Version + সংস্করণ View - Visit our website + আমাদের ওয়েবসাইটে ঢু মেরে আসুন Visit our website to get help, news, email us, and/or learn more about how to use Bitwarden. - Website + ওয়েবসাইট Label for a website. - Yes + হ্যাঁ - Account + অ্যাকাউন্ট - Your new account has been created! You may now log in. + আপনার নতুন অ্যাকাউন্ট তৈরি করা হয়েছে! আপনি এখন লগইন করতে পারবেন। Add an Item @@ -425,7 +425,7 @@ Auto-fill service - Avoid ambiguous characters + অস্পষ্ট বর্ণগুলি বাদ দিয়ে যান Bitwarden app extension @@ -443,7 +443,7 @@ Use the Bitwarden accessibility service to auto-fill your logins. - Change email + ইমেইল পরিবর্তন করুন You can change your email address on the bitwarden.com web vault. Do you want to visit the website now? @@ -455,7 +455,7 @@ আপনি bitwarden.com ওয়েব ভল্ট থেকে প্রধান পাসওয়ার্ডটি পরিবর্তন করতে পারেন। আপনি কি এখনই ওয়েবসাইটটি দেখতে চান? - Close + বন্ধ করুন অবিরত @@ -480,7 +480,7 @@ Reactivate app extension - Almost done! + প্রায় হয়ে গেছে! Activate app extension @@ -493,7 +493,7 @@ Get instant access to your passwords! - You're ready to log in! + আপনি লগইন করার জন্য একদম তৈরি! Your logins are now easily accessible from Safari, Chrome, and other supported apps. @@ -651,7 +651,7 @@ Push notifications for apple products - Rate the app + অ্যাপ্লিকেশনটকে রেট দিন দয়া করে একটি ভাল পর্যালোচনার মাধ্যমে সাহায্য করতে আমাদের বিবেচনা করুন! @@ -701,7 +701,7 @@ Sync vault now - Touch ID + টাচ আইডি What Apple calls their fingerprint reader. @@ -721,13 +721,13 @@ Message shown when interacting with the server - Verification code + যাচাইকরণ কোড View item - Bitwarden web vault + বিটওয়ার্ডেন ওয়েব ভল্ট Lost authenticator app? @@ -740,10 +740,10 @@ Extension activated! - Icons + আইকন - Translations + অনুবাদসমূহ Items for {0} @@ -769,19 +769,19 @@ 2. Switch on the toggle and press OK to accept. - Disabled + নিষ্ক্রিয় - Enabled + সক্রিয় - Off + বন্ধ - On + চালু - Status + অবস্থা The easiest way to add new logins to your vault is from the Bitwarden Auto-fill Service. Learn more about using the Bitwarden Auto-fill Service by navigating to the "Settings" screen. @@ -904,13 +904,13 @@ Scanning will happen automatically. - Scan QR Code + QR কোড স্ক্যান করুন - Camera + ক্যামেরা - Photos + ছবিসমূহ Copy TOTP @@ -934,7 +934,7 @@ Scanning will happen automatically. Choose file - File + ফাইল No file chosen @@ -1080,7 +1080,7 @@ Scanning will happen automatically. নামের শেষাংশ - Full name + পুরো নাম লাইসেন্স নম্বর @@ -1107,34 +1107,34 @@ Scanning will happen automatically. Mx - November + নভেম্বর - October + অক্টোবর - Passport number + পাসপোর্ট নম্বর - Phone + ফোন - September + সেপ্টেম্বর - Social Security number + সামাজিক সুরক্ষা নম্বর - State / Province + রাজ্য / প্রদেশ - Title + শিরোনাম - Zip / Postal code + জিপ / পোস্টকোড - Address + ঠিকানা Expiration @@ -1204,7 +1204,7 @@ Scanning will happen automatically. Custom field name - Boolean + বুলিয়ান Hidden @@ -1225,7 +1225,7 @@ Scanning will happen automatically. Remove - New URI + নতুন URI URI {0} @@ -1272,7 +1272,7 @@ Scanning will happen automatically. Hold your Yubikey near the top of the device. - Try again + আবার চেষ্টা করুন To continue, hold your YubiKey NEO against the back of the device. @@ -1440,16 +1440,16 @@ Scanning will happen automatically. Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved. - Number of words + শব্দসংখ্যা - Passphrase + গুপ্ত-বাক্যাংশ - Word separator + শব্দ বিভাজক - Clear + পরিষ্কার করুন To clear something out. example: To clear browser history. @@ -1474,42 +1474,42 @@ Scanning will happen automatically. Export vault - Lock now + এখনই লক করুন - PIN + পিন - Unlock + আনলক করুন Unlock vault - 30 minutes + ৩০ মিনিট - Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application. + Bitwarden আনলক করার জন্য আপনার পিন কোডটি সেট করুন। আপনি যদি অ্যাপ্লিকেশনটি থেকে পুরোপুরি লগ আউট করেন তবে আপনার পিন সেটিংস রিসেট করা হবে। - Logged in as {0} on {1}. + {1}-এ {0} হিসেবে লগইন করা হয়েছে। ex: Logged in as user@example.com on bitwarden.com. আপনার ভল্ট লক করা আছে। চালিয়ে যেতে আপনার প্রধান পাসওয়ার্ডটি যাচাই করান। - Your vault is locked. Verify your PIN code to continue. + আপনার ভল্ট লক করা আছে। চালিয়ে যেতে আপনার পিন কোড যাচাই করান। - Your vault is locked. Verify your identity to continue. + আপনার ভল্ট লক করা আছে। চালিয়ে যেতে আপনার পরিচয় যাচাই করান। - Dark + গাঢ় A dark color - Light + উজ্জ্বল A light color @@ -1887,10 +1887,10 @@ Scanning will happen automatically. 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - Text + লেখা - Text + লেখা The text you want to send. @@ -1900,7 +1900,7 @@ Scanning will happen automatically. 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - File + ফাইল The file you want to send. @@ -1918,7 +1918,7 @@ Scanning will happen automatically. Text type is not selected, tap to select. - Deletion date + মুছে ফেলার তারিখ Deletion time @@ -1957,7 +1957,7 @@ Scanning will happen automatically. Current access count - New password + নতুন পাসওয়ার্ড Optionally require a password for users to access this Send. @@ -2030,19 +2030,19 @@ Scanning will happen automatically. 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - 1 day + ১ দিন - 2 days + ২ দিন 3 days - 7 days + ৭ দিন - 30 days + ৩০ দিন Custom @@ -2240,16 +2240,16 @@ Scanning will happen automatically. Options are collapsed, tap to expand. - Uppercase (A to Z) + বড় হাতের অক্ষর (A-Z) Lowercase (A to Z) - Numbers (0 to 9) + সংখ্যা (0-9) - Special characters (!@#$%^&*) + বিশেষ অক্ষর (!@#$%^&*) Tap to go back @@ -2352,10 +2352,10 @@ select Add TOTP to store the key safely Deny login - Just now + এইমাত্র - {0} minutes ago + {0} মিনিট আগে Login confirmed @@ -2548,7 +2548,7 @@ Do you want to switch to this account? Enable camera permission to use the scanner - Language + ভাষা The language has been changed to {0}. Please restart the app to see the change @@ -2575,10 +2575,10 @@ Do you want to switch to this account? Weak - Good + ভালো - Strong + শক্তিশালী Check known data breaches for this password diff --git a/src/App/Resources/AppResources.de.resx b/src/App/Resources/AppResources.de.resx index b53a2c827..f8868282a 100644 --- a/src/App/Resources/AppResources.de.resx +++ b/src/App/Resources/AppResources.de.resx @@ -1753,7 +1753,7 @@ Das Scannen erfolgt automatisch. Confirmation alert message when soft-deleting a cipher. - Biometrie zum Entsperren ist für dieses Konto deaktiviert, bis das Master-Passwort verifiziert wurde. + Das Entsperren über Biometrie ist für dieses Konto deaktiviert, bis das Master-Passwort verifiziert wurde. Das Entsperren von Auto-Ausfüllen über Biometrie ist für dieses Konto deaktiviert, bis das Master-Passwort verifiziert wurde. diff --git a/src/App/Resources/AppResources.el.resx b/src/App/Resources/AppResources.el.resx index e961c0f38..67e71da38 100644 --- a/src/App/Resources/AppResources.el.resx +++ b/src/App/Resources/AppResources.el.resx @@ -1753,10 +1753,10 @@ Confirmation alert message when soft-deleting a cipher. - Biometric unlock for this account is disabled pending verification of master password. + Το βιομετρικό ξεκλείδωμα για αυτόν τον λογαριασμό είναι απενεργοποιημένο εν αναμονή της επαλήθευσης του κύριου κωδικού πρόσβασης. - Autofill biometric unlock for this account is disabled pending verification of master password. + Το βιομετρικό ξεκλείδωμα αυτόματης συμπλήρωσης για αυτό το λογαριασμό είναι απενεργοποιημένο εν αναμονή της επαλήθευσης του κύριου κωδικού πρόσβασης. Ενεργοποίηση συγχρονισμού κατά την ανανέωση @@ -2143,10 +2143,10 @@ Οι πολιτικές του οργανισμού σας επηρεάζουν το χρονικό όριο vault σας. Το μέγιστο επιτρεπόμενο Χρονικό όριο Vault είναι {0} ώρα(ες) και {1} λεπτό(ά) - Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is {0} hour(s) and {1} minute(s). Your vault timeout action is set to {2}. + Οι πολιτικές του οργανισμού σας επηρεάζουν το χρονικό όριο του vault σας. Το μέγιστο επιτρεπόμενο χρονικό όριο vault είναι {0} ώρα(ες) και {1} λεπτό(ά). Το χρονικό όριο του vault σας έχει οριστεί σε {2}. - Your organization policies have set your vault timeout action to {0}. + Οι πολιτικές του οργανισμού σας έχουν ορίσει την ενέργεια χρονικού ορίου vault σε {0}. Το χρονικό όριο του vault σας υπερβαίνει τους περιορισμούς που έχει ορίσει ο οργανισμός σας. @@ -2610,9 +2610,9 @@ Δεν υπάρχουν στοιχεία που να ταιριάζουν με την αναζήτηση - Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour. + Ο κύριος κωδικός πρόσβασής σας δεν πληροί μία ή περισσότερες πολιτικές του οργανισμού σας. Για να αποκτήσετε πρόσβαση στο Vault σας, πρέπει να ενημερώσετε τον κύριο κωδικό πρόσβασής σας τώρα. Η διαδικασία θα σας αποσυνδέσει από την τρέχουσα συνεδρία σας, απαιτώντας από εσάς να συνδεθείτε ξανά. Οι ενεργές συνεδρίες σε άλλες συσκευές ενδέχεται να συνεχίσουν να είναι ενεργές εώς και μία ώρα. - Current master password + Τρέχων κύριος κωδικός diff --git a/src/App/Resources/AppResources.fi.resx b/src/App/Resources/AppResources.fi.resx index a756bf557..c02d56df2 100644 --- a/src/App/Resources/AppResources.fi.resx +++ b/src/App/Resources/AppResources.fi.resx @@ -1753,10 +1753,10 @@ Koodi luetaan automaattisesti. Confirmation alert message when soft-deleting a cipher. - Biometric unlock for this account is disabled pending verification of master password. + Biometrinen avaus on poistettu käytöstä tältä tililtä, kunnes pääsalasana on vahvistettu. - Autofill biometric unlock for this account is disabled pending verification of master password. + Automaattisen täytön biometrinen avaus on poistettu käytöstä tältä tililtä, kunnes pääsalasana on vahvistettu. Synkronoi holvi päivityksen yhteydessä @@ -2602,7 +2602,7 @@ Haluatko vaihtaa tähän tiliin? Lisää avain olemassa olevaan tai uuteen kohteeseen - Holvissasi ei ole kohteita osoitteelle "{0}" + Holvissasi ei ole kohdetta "{0}" vastavia tietoja Etsi kohdetta tai lisää uusi kohde diff --git a/src/App/Resources/AppResources.fr.resx b/src/App/Resources/AppResources.fr.resx index 59451de96..519235ea5 100644 --- a/src/App/Resources/AppResources.fr.resx +++ b/src/App/Resources/AppResources.fr.resx @@ -1753,10 +1753,10 @@ La numérisation se fera automatiquement. Confirmation alert message when soft-deleting a cipher. - Biometric unlock for this account is disabled pending verification of master password. + Le déverrouillage biométrique pour ce compte est désactivé en attente de vérification du mot de passe maître. - Autofill biometric unlock for this account is disabled pending verification of master password. + Le déverrouillage biométrique de saisie automatique pour ce compte est désactivé en attente de vérification du mot de passe maître. Autoriser la synchronisation au rafraîchissement diff --git a/src/App/Resources/AppResources.ro.resx b/src/App/Resources/AppResources.ro.resx index 8ddbc5cf7..4c9903397 100644 --- a/src/App/Resources/AppResources.ro.resx +++ b/src/App/Resources/AppResources.ro.resx @@ -1753,10 +1753,10 @@ Scanarea se va face automat. Confirmation alert message when soft-deleting a cipher. - Biometric unlock for this account is disabled pending verification of master password. + Deblocarea biometrică pentru acest cont este dezactivată în așteptarea verificării parolei principale. - Autofill biometric unlock for this account is disabled pending verification of master password. + Completarea automată a deblocării biometrice pentru acest cont este dezactivată în așteptarea verificării parolei principale. Activare sincronizare la reîmprospătare diff --git a/src/App/Resources/AppResources.sl.resx b/src/App/Resources/AppResources.sl.resx index 8768c1412..59b2998a0 100644 --- a/src/App/Resources/AppResources.sl.resx +++ b/src/App/Resources/AppResources.sl.resx @@ -269,7 +269,7 @@ Title for login page. (noun) - Izpiši se + Odjavi se The log out button text (verb). @@ -296,7 +296,7 @@ Text to define that there are more options things to see. - Moj sef + Moj trezor The title for the vault page. @@ -342,7 +342,7 @@ Reveal a hidden value (password). - Vnos je bil izbrisan. + Element je bil izbrisan. Confirmation message after successfully deleting a login. @@ -413,7 +413,7 @@ Vas novi račun je bil ustvarjen! Lahko se vpišete. - Dodaj vnos + Dodaj Element Razširitev aplikacije @@ -425,7 +425,7 @@ Storitev samodejnega izpolnjevanja - Izogib dvoumnih znakov + Brez dvoumnih znakov Razširitev aplikacije Bitwarden @@ -468,7 +468,7 @@ Message shown when interacting with the server - Uredi vnos + Uredi element Omogoči samodejno sinhronizacijo @@ -514,13 +514,13 @@ Prstni odtis - Ustvari geslo + Generiraj geslo Pridobi namig za glavno geslo - Uvozi zapise + Uvozi elemente You can bulk import items from the bitwarden.com web vault. Do you want to visit the website now? @@ -566,7 +566,7 @@ Message shown when interacting with the server - Vpišite se ali ustvarite nov račun za dostop do sefa. + Prijavite se ali ustvarite nov račun za dostop do trezorja. Upravljaj @@ -584,7 +584,7 @@ Namig glavnega gesla se vam lahko pomaga spomniti geslo, v kolikor bi ga pozabili. - Master password must be at least {0} characters long. + Glavno geslo mora vsebovati vsaj {0} znakov. Minimalno števil @@ -604,13 +604,13 @@ Nikoli - Nov vnos ustvarjen. + Nov element ustvarjen. - V vašem sefu ni priljubljenih vnosov. + V vašem trezorju ni priljubljenih elementov. - V vašem sefu ni vnosov. + V vašem trezorju ni elementov. There are no items in your vault for this website/app. Tap to add one. @@ -632,7 +632,7 @@ Drugo - Geslo ustvarjeno. + Geslo generirano. Ustvarjalnik gesel @@ -678,24 +678,24 @@ Vnesite 4 mestno PIN številko za odklep aplikacije. - Informacije o vnosu + Informacije o elementu - Vnos je posodobljen. + Element shranjen. Pošiljanje... Message shown when interacting with the server - Sinhronizacija... + Sinhroniziram... Message shown when interacting with the server Sinhronizacija končana. - Sinhronizacija neuspešna. + Sinhronizacija spodletela. Sinhroniziraj trezor zdaj @@ -714,7 +714,7 @@ Odkleni z {0} - Odklepanje s PIN kodo + Odkleni s PIN kodo Preverjanje veljavnosti @@ -724,16 +724,16 @@ Verifikacijska koda - Ogled vnosa + Prikaži element - Bitwarden spletni sef + Spletni trezor Bitwarden Izgubili aplikacijo za avtentikacijo? - Vnosi + Elementi Screen title @@ -746,11 +746,11 @@ Prevodi - Vnosov za {0} + Elementi za {0} This is used for the autofill service. ex. "Logins for twitter.com" - V vašem sefu ni vnosov za {0}. + V vašem trezorju ni elementov za {0}. This is used for the autofill service. ex. "There are no items in your vault for twitter.com". @@ -790,16 +790,16 @@ Samodejno izpolnjevanje - Želite samodejno izpolniti ali videti ta vnos? + Želite samodejno izpolniti ali prikazati ta element? Ali ste prepričani, da želite samodejno izpolniti ta element? Ujemanje ni popolno za "{0}". - Ujemajoči vnosi + Ujemajoči elementi - Možni ujemajoči vnosi + Možni ujemajoči elementi Iskanje @@ -1017,7 +1017,7 @@ Scanning will happen automatically. Prijava - Varni zapisek + Zavarovan zapisek Naslov 1 @@ -1140,10 +1140,10 @@ Scanning will happen automatically. Datum poteka - Show website icons + Prikaži ikone spletnih strani - Show a recognizable image next to each login. + Pri vsaki prijavi prikaži prepoznavno sliko. Ikone URL strežnikov @@ -1161,10 +1161,10 @@ Scanning will happen automatically. Zbirke - Ta zbirka še nima zapisov. + Ta zbirka še nima elementov. - V tej mapi ni zapisov. + V tej mapi ni elementov. Koš je prazen. @@ -1182,7 +1182,7 @@ Scanning will happen automatically. Nastavitve samodejnega izpolnjevanja - Obrazni ID + obraznim ID What Apple calls their facial recognition reader. @@ -1322,7 +1322,7 @@ Scanning will happen automatically. 5. Select "Bitwarden" - Password auto-fill + Samodejno izpolnjevanje gesel The easiest way to add new logins to your vault is by using the Bitwarden Password AutoFill extension. Learn more about using the Bitwarden Password AutoFill extension by navigating to the "Settings" screen. @@ -1340,13 +1340,13 @@ Scanning will happen automatically. Prijave - Varni zapiski + Zavarovani zapiski Vsi elementi - URIs + URI-ji Plural form of a URI @@ -1369,7 +1369,7 @@ Scanning will happen automatically. Vrednost - Zgodovina gesla + Zgodovina gesel Vrste @@ -1378,7 +1378,7 @@ Scanning will happen automatically. Ni gesel za prikazat. - Ni vnosov za prikazat. + Ni elementov za prikaz. Preišči zbirko @@ -1409,7 +1409,7 @@ Scanning will happen automatically. Lastništvo - Kdo je lastnik tega vnosa? + Kdo je lastnik tega elementa? Ni zbirk za prikazat. @@ -1419,7 +1419,7 @@ Scanning will happen automatically. ex: Item moved to Organization. - Vnos je bil deljen. + Element je bil dan v skupno rabo. Izbrati moraš vsaj eno zbirko. @@ -1428,10 +1428,10 @@ Scanning will happen automatically. Deli - Delite vnos + Delite element - Move to Organization + Premakni v organizacijo Ni organizacij za prikazat. @@ -1562,7 +1562,7 @@ Scanning will happen automatically. Kopiraj opombo - Zapri + Izhod Ali res želite zapustiti Bitwarden? @@ -1583,16 +1583,16 @@ Scanning will happen automatically. 'Solarized Dark' is the name of a specific color scheme. It should not be translated. - Auto-fill blocked URIs + URI-ji brez samodejnega izpolnjevanja - Auto-fill will not be offered for blocked URIs. Separate multiple URIs with a comma. For example: "https://twitter.com, androidapp://com.twitter.android". + Za te URI-je Bitwarden ne bo ponujal samodejnega izpolnjevanja. URI-je ločite z vejicami, n.pr.: "https://twitter.com, androidapp://com.twitter.android". - Ask to add login + Ponudi shranjevanje prijav - Ask to add an item if one isn't found in your vault. + Ponudi, da se shrani nova prijava, če je v trezorju še ni. Ob ponovnem zagonu aplikacije @@ -1626,7 +1626,7 @@ Scanning will happen automatically. Biometrična avtentikacija - Biometrično preverjanje + biometričnim preverjanjem Uporabi biometrično preverjanje za odklep @@ -1729,7 +1729,7 @@ Scanning will happen automatically. Message shown when interacting with the server - Vnos je bil obnovljen. + Element je bil obnovljen. Confirmation message after successfully restoring a soft-deleted item @@ -1745,7 +1745,7 @@ Scanning will happen automatically. Confirmation alert message when permanently deleteing a cipher. - Ali res želite povrniti ta vnos? + Ali res želite povrniti ta element? Confirmation alert message when restoring a soft-deleted cipher. @@ -1759,10 +1759,10 @@ Scanning will happen automatically. Autofill biometric unlock for this account is disabled pending verification of master password. - Allow sync on refresh + Dovoli sihnronizacijo ob osvežitvi - Syncing vault with pull down gesture. + Sinhroniziraj ob potegu navzdol Enterprise single sign-on @@ -1829,7 +1829,7 @@ Scanning will happen automatically. Bitwarden needs attention - Turn on "Draw-Over" in "Auto-fill Services" from Bitwarden Settings - Auto-fill services + Storitve samodejnega izpolnjevanja Use inline autofill @@ -1871,7 +1871,7 @@ Scanning will happen automatically. An organization policy is affecting your ownership options. - Pošlji + Pošiljke 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. @@ -1887,23 +1887,23 @@ Scanning will happen automatically. 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - Text + Besedilo - Text + Besedilo - The text you want to send. + Besedilo, ki ga želite poslati When accessing the Send, hide the text by default 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - File + Datoteka - The file you want to send. + Datoteka, ki jo želite poslati File type is selected. @@ -1998,7 +1998,7 @@ Scanning will happen automatically. Deli povezavo - Pošlji povezavo + Povezava pošiljke 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. @@ -2156,22 +2156,22 @@ Scanning will happen automatically. One or more organization policies prevents your from exporting your individual vault. - Add account + Dodaj račun - Unlocked + Odklenjen - Locked + Zaklenjen - Logged out + Odjavljen Switched to next available account - Account locked + Račun je zaklenjen Account logged out successfully @@ -2195,7 +2195,7 @@ Scanning will happen automatically. Vaš račun je bil trajno izbrisan - Invalid verification code + Neveljavna koda za preverjanje Request one-time password @@ -2228,7 +2228,7 @@ Scanning will happen automatically. Enter the verification code that was sent to your email - Submit crash logs + Pošlji zapisnike ob sesutju Help Bitwarden improve app stability by submitting crash reports. @@ -2240,16 +2240,16 @@ Scanning will happen automatically. Options are collapsed, tap to expand. - Uppercase (A to Z) + Velike črke (A-Z) - Lowercase (A to Z) + Male črke (a-z) Numbers (0 to 9) - Special characters (!@#$%^&*) + Posebni znaki (!@#$%^&*) Tap to go back @@ -2264,31 +2264,31 @@ Scanning will happen automatically. Filter items by vault - All vaults + Vsi trezorji - Vaults + Trezorji - Vault: {0} + Trezor: {0} - All + Vsi TOTP - Verification codes + Kode za preverjanje - Premium subscription required + Potrebna je naročnina Premium. Cannot add authenticator key? - Scan QR Code + Skeniraj QR-kodo Cannot scan QR Code? @@ -2319,10 +2319,10 @@ select Add TOTP to store the key safely We were unable to process your request. Please try again or contact us. - Allow screen capture + Dovoli posnetke zaslona - Are you sure you want to turn on screen capture? + Ste prepričani, da želite dovoliti zajemanje zaslona? Login requested @@ -2337,46 +2337,46 @@ select Add TOTP to store the key safely Device type - IP address + IP-naslov - Time + Čas - Near + Blizu - Confirm login + Potrdi prijavo - Deny login + Zavrni prijavo - Just now + Pravkar - {0} minutes ago + Pred {0} minutami - Login confirmed + Prijava potrjena - Login denied + Prijava zavrnjena - Approve login requests + Odobri zahtevke za prijavo - Use this device to approve login requests made from other devices. + S to napravo odobri zahtevke za prijavo, ki pridejo z drugih naprav. - Allow notifications + Dovoli obvestila Receive push notifications for new login requests - No thanks + Ne, hvala Confirm login attempt for {0} @@ -2385,10 +2385,10 @@ select Add TOTP to store the key safely All notifications - Password type + Vrsta gesla - What would you like to generate? + Kaj želite generirati? Username type @@ -2444,7 +2444,7 @@ select Add TOTP to store the key safely Are you sure you want to overwrite the current username? - Generate username + Generiraj uporabniško ime Email Type @@ -2477,13 +2477,13 @@ select Add TOTP to store the key safely Bitwarden uses the Accessibility Service to search for login fields in apps and websites, then establish the appropriate field IDs for entering a username & password when a match for the app or site is found. We do not store any of the information presented to us by the service, nor do we make any attempt to control any on-screen elements beyond text entry of credentials. - Accept + Sprejmi - Decline + Zavrni - Login request has already expired. + Zahtevek za prijavo je že potekel. Login attempt from: @@ -2491,109 +2491,109 @@ select Add TOTP to store the key safely Do you want to switch to this account? - New around here? + Ste novi tukaj? - Get master password hint + Pridobi namig za glavno geslo - Logging in as {0} + Prijavljate se kot {0} - Not you? + To niste vi? - Log in with master password + Prijava z glavnim geslom - Log in with device + Prijava z napravo - Log in initiated + Prijava sprožena - A notification has been sent to your device. + Na vašo napravo smo poslali obvestilo. - Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device. + Prosimo, preverite, da je vaš trezor odklenjem in da se identifikacijski gesli na tej in drugi napravi ujemata. - Resend notification + Ponovno pošlji obvestilo - Need another option? + Potrebujete drugačno možnost? - View all log in options + Prikaži vse možnosti prijave - This request is no longer valid + Ta zahtevek ni več veljaven - Pending login requests + Čakajoči zahtevki za prijavo - Decline all requests + Zavrni vse zahtevke - Are you sure you want to decline all pending login requests? + Ste prepričani, da želite zavrniti vse čakajoče zahtevke za prijavo? - Requests declined + Zahtevki zavrnjeni - No pending requests + Ni zahtevkov - Enable camera permission to use the scanner + Za uporabo skenerja dovolite uporabo kamere - Language + Jezik - The language has been changed to {0}. Please restart the app to see the change + Spremenjeno v jezik {0}. Prosimo, ponovno zaženite aplikacijo za prikaz sprememb. - Language change requires app restart + Za spremembo jezika je potrebno ponovno zagnati aplikacijo. - Default (System) + Privzet (sistemski) - Important + Pomembno - Your master password cannot be recovered if you forget it! {0} characters minimum. + Če pozabite glavno geslo, ga ne bo mogoče obnoviti! Vsaj {0} znakov. - Weak Master Password + Šibko glavno geslo - Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password? + Vaše geslo je šibko. Za zaščito svojega računa potrebujete močno geslo. Ste prepričani, da želite uporabiti šibko geslo? - Weak + Šibko - Good + Dobro - Strong + Močno - Check known data breaches for this password + Preveri, ali je bilo geslo izpostavljeno v krajah podatkov - Exposed Master Password + Izpostavljeno glavno geslo - Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password? + To geslo smo našli med ukradenimi gesli. Za zaščito svojega računa uporabite edinstveno geslo. Ste prepričani, da želite uporabiti izpostavljeno geslo? - Weak and Exposed Master Password + Šibko in izpostavljeno glavno geslo - Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password? + Vaše geslo je šibko, poleg tega smo ga našli med ukradenimi gesli. Za zaščito svojega računa potrebujete močno in edinstveno geslo. Ste prepričani, da želite uporabiti to šibko geslo? Organization SSO identifier required. @@ -2602,18 +2602,18 @@ Do you want to switch to this account? Add the key to an existing or new item - There are no items in your vault that match "{0}" + V vašem trezorju ni elementov, ki bi ustrezali "{0}" - Search for an item or add a new item + Poišči element ali dodaj novega - There are no items that match the search + Ni elementov, ki bi ustrezali iskanju Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour. - Current master password + Trenutno glavno geslo diff --git a/src/App/Resources/AppResources.sr.resx b/src/App/Resources/AppResources.sr.resx index d9cdaa3e2..962f66823 100644 --- a/src/App/Resources/AppResources.sr.resx +++ b/src/App/Resources/AppResources.sr.resx @@ -1753,10 +1753,10 @@ Confirmation alert message when soft-deleting a cipher. - Biometric unlock for this account is disabled pending verification of master password. + Биометријско откључавање је онемогућено до верификације главне лозинке. - Autofill biometric unlock for this account is disabled pending verification of master password. + Биометријско откључавање аутоматског попуњавања за овај налог је онемогућено до верификације главне лозинке. Омогући синхронизацију при освежавању diff --git a/src/App/Resources/AppResources.zh-Hans.resx b/src/App/Resources/AppResources.zh-Hans.resx index 43faf372b..a6260ad31 100644 --- a/src/App/Resources/AppResources.zh-Hans.resx +++ b/src/App/Resources/AppResources.zh-Hans.resx @@ -2610,7 +2610,7 @@ 没有匹配搜索条件的项目 - 您的主密码不符合您的组织策略要求。要访问密码库,必须立即更新您的主密码。继续操作将使您退出当前会话,要求您重新登录。其他设备上的活动会话可能会继续保持活动状态长达一小时。 + 您的主密码不符合某一项或多项组织策略要求。要访问密码库,必须立即更新您的主密码。继续操作将使您退出当前会话,并要求您重新登录。其他设备上的活动会话可能会继续保持活动状态长达一小时。 当前主密码 diff --git a/store/apple/sl/copy.resx b/store/apple/sl/copy.resx index b254fa174..59b53710c 100644 --- a/store/apple/sl/copy.resx +++ b/store/apple/sl/copy.resx @@ -122,51 +122,50 @@ Max 30 characters - Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + Bitwarden, Inc. je matično podjetje podjetja 8bit Solutions LLC. -NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. +NAJBOŠJI UPRAVLJALNIK GESEL PO MNEJU THE VERGE, U.S. NEWS & WORLD REPORT, CNET IN DRUGIH. -Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. +Upravljajte, shranjujte, varujte in delite neomejeno število gesel na neomejenem številu naprav, kjerkoli. Bitwarden ponuja odprtokodne rešitve za upravljanje gesel vsem, tako doma kot v službi ali na poti. -Generate strong, unique, and random passwords based on security requirements for every website you frequent. +Za vas ustvari močna, edinstvena in naključna gesla, skladna z varnostnimi zahtevami za vsako spletno mesto, ki ga obiščete. -Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. +S pošiljkami Bitwarden Send hitro prenesite šifrirane informacije --- datoteke in navadno besedilo -- neposredno komurkoli. -Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. +Bitwarden ponuja storitvi za organizacije Teams in Enterprise, s katerima lahko gesla varno souporabljate s sodelavci. -Why Choose Bitwarden: +Zakaj izbrati Bitwarden: -World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +Vrhunsko šifriranje +Gesla so zaščitena z naprednim šifriranjem (AES-256, soljene hash-vrednosti in PBKDF2 SHA-256), tako da vaši podatki ostanejo varni in zasebni. -Built-in Password Generator -Generate strong, unique, and random passwords based on security requirements for every website you frequent. +Vgrajen generator gesel +Ustvarite močna, edinstvena in naključna gesla v skladu z varnostnimi zahtevami za vsako spletno mesto, ki ga obiščete. -Global Translations -Bitwarden translations exist in 40 languages and are growing, thanks to our global community. +Prevodi za ves svet +Bitwarden je preveden že v 40 jezikov, naša globalna skupnost pa ves čas posodabljan in ustvarja nove prevede. -Cross-Platform Applications -Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. - +Deluje na vseh platformah +Varujte in souporabljajte svoje občutljive podatke znotraj vašega Bitwarden trezorja v katerem koli brskalniku, mobilni napravi, namiznem računalniku in drugje. Max 4000 characters - bit warden,8bit,password,free password manager,password manager,login manager + bit warden,8bit,password,free password manager,password manager,login manager,upravljalnik gesel,shranjevalnik gesel,geslo,upravljalnik prijav Max 100 characters - Manage all your logins and passwords from a secure vault + Urejajte vse svoje prijavne podatke in gesla v zavarovanem trezorju - Automatically generate strong, random, and secure passwords + Samodejno ustvari močna, naključna in varna gesla - Protect your vault with Touch ID, PIN code, or master password + Zaščitite svoj trezor s pristnim odtisom, PIN-kodo ali glavnim geslom - Auto-fill logins from Safari, Chrome, and hundreds of other apps + Samodejno izpolnjevanje prijav v aplikacijah Safari, Chrome in stotinah drugih - Sync and access your vault from multiple devices + Sinhronizirajte svoj trezor gesel in dostopajte do njega z več naprav diff --git a/store/google/sl/copy.resx b/store/google/sl/copy.resx index 697db123c..3c10dd542 100644 --- a/store/google/sl/copy.resx +++ b/store/google/sl/copy.resx @@ -118,61 +118,61 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Bitwarden shranjevalnik gesel + Bitwarden - upravitelj gesel Max 30 characters - Bitwarden je shranjevalnik dostopnih podatkov in gesel, ki vam pomaga ostati varen na spletu. + Bitwarden je upravitelj prijavnih podatkov in gesel, ki vam pomaga ohraniti varnost na spletu. Max 80 characters - Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + Bitwarden, Inc. je matično podjetje podjetja 8bit Solutions LLC. -NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. +NAJBOŠJI UPRAVLJALNIK GESEL PO MNEJU THE VERGE, U.S. NEWS & WORLD REPORT, CNET IN DRUGIH. -Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. +Upravljajte, shranjujte, varujte in delite neomejeno število gesel na neomejenem številu naprav, kjerkoli. Bitwarden ponuja odprtokodne rešitve za upravljanje gesel vsem, tako doma kot v službi ali na poti. -Generate strong, unique, and random passwords based on security requirements for every website you frequent. +Za vas ustvari močna, edinstvena in naključna gesla, skladna z varnostnimi zahtevami za vsako spletno mesto, ki ga obiščete. -Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. +S pošiljkami Bitwarden Send hitro prenesite šifrirane informacije --- datoteke in navadno besedilo -- neposredno komurkoli. -Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. +Bitwarden ponuja storitvi za organizacije Teams in Enterprise, s katerima lahko gesla varno souporabljate s sodelavci. -Why Choose Bitwarden: +Zakaj izbrati Bitwarden: -World-Class Encryption -Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. +Vrhunsko šifriranje +Gesla so zaščitena z naprednim šifriranjem (AES-256, soljene hash-vrednosti in PBKDF2 SHA-256), tako da vaši podatki ostanejo varni in zasebni. -Built-in Password Generator -Generate strong, unique, and random passwords based on security requirements for every website you frequent. +Vgrajen generator gesel +Ustvarite močna, edinstvena in naključna gesla v skladu z varnostnimi zahtevami za vsako spletno mesto, ki ga obiščete. -Global Translations -Bitwarden translations exist in 40 languages and are growing, thanks to our global community. +Prevodi za ves svet +Bitwarden je preveden že v 40 jezikov, naša globalna skupnost pa ves čas posodabljan in ustvarja nove prevede. -Cross-Platform Applications -Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. - +Deluje na vseh platformah +Varujte in souporabljajte svoje občutljive podatke znotraj vašega Bitwarden trezorja v katerem koli brskalniku, mobilni napravi, namiznem računalniku in drugje. Max 4000 characters - Varen in brezplačen shranjevalnik gesel za vse vaše naprave + Varen in brezplačen upravitelj gesel za vse vaše naprave - Urejate vse svoje dostopne podatke in gesla iz varnega sefa + Urejajte vse svoje prijavne podatke in gesla v zavarovanem trezorju - Samodejni ustvari močna, naključna in varna gesla + Samodejno ustvari močna, naključna in varna gesla - Zaščitite svoj sef s pristnim odtisom, kodo PIN ali glavnim geslom + Zaščitite svoj trezor s pristnim odtisom, PIN-kodo ali glavnim geslom - Hitro vnašanje prijavnih podatkov na spletu in v drugih aplikacijah + Hitro samodejno vnašanje prijavnih podatkov na spletu in v drugih aplikacijah - - Telefon + Dostopajte do svojega sefa z različnih naprav: +- Telefon - Tablica -- Namizje +- Računalnik - Splet