mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 23:25:45 +03:00
Password generator policy enforcement (#741)
* Password generator policy enforcement * Formatting * Changed to simple cast (double unboxing for int64/long) * Added ui indication of active policy on password generator page and fixed issue with switch enable logic
This commit is contained in:
parent
02cffa01e2
commit
f78f303a79
9 changed files with 231 additions and 12 deletions
|
@ -39,6 +39,29 @@
|
||||||
<ScrollView Padding="0, 0, 0, 20">
|
<ScrollView Padding="0, 0, 0, 20">
|
||||||
<StackLayout Spacing="0" Padding="0">
|
<StackLayout Spacing="0" Padding="0">
|
||||||
<StackLayout StyleClass="box">
|
<StackLayout StyleClass="box">
|
||||||
|
<Grid IsVisible="{Binding IsPolicyInEffect}"
|
||||||
|
Margin="0, 12, 0, 0"
|
||||||
|
RowSpacing="0"
|
||||||
|
ColumnSpacing="0">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Frame Padding="10"
|
||||||
|
Margin="0"
|
||||||
|
HasShadow="False"
|
||||||
|
BackgroundColor="Transparent"
|
||||||
|
BorderColor="Accent">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n PasswordGeneratorPolicyInEffect}"
|
||||||
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
|
HorizontalTextAlignment="Center" />
|
||||||
|
</Frame>
|
||||||
|
</Grid>
|
||||||
<controls:MonoLabel
|
<controls:MonoLabel
|
||||||
Text="{Binding ColoredPassword, Mode=OneWay}"
|
Text="{Binding ColoredPassword, Mode=OneWay}"
|
||||||
TextType="Html"
|
TextType="Html"
|
||||||
|
@ -152,6 +175,7 @@
|
||||||
HorizontalOptions="StartAndExpand" />
|
HorizontalOptions="StartAndExpand" />
|
||||||
<Switch
|
<Switch
|
||||||
IsToggled="{Binding Uppercase}"
|
IsToggled="{Binding Uppercase}"
|
||||||
|
IsEnabled="{Binding IsUppercaseSwitchEnabled}"
|
||||||
StyleClass="box-value"
|
StyleClass="box-value"
|
||||||
HorizontalOptions="End" />
|
HorizontalOptions="End" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
@ -163,6 +187,7 @@
|
||||||
HorizontalOptions="StartAndExpand" />
|
HorizontalOptions="StartAndExpand" />
|
||||||
<Switch
|
<Switch
|
||||||
IsToggled="{Binding Lowercase}"
|
IsToggled="{Binding Lowercase}"
|
||||||
|
IsEnabled="{Binding IsLowercaseSwitchEnabled}"
|
||||||
StyleClass="box-value"
|
StyleClass="box-value"
|
||||||
HorizontalOptions="End" />
|
HorizontalOptions="End" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
@ -174,6 +199,7 @@
|
||||||
HorizontalOptions="StartAndExpand" />
|
HorizontalOptions="StartAndExpand" />
|
||||||
<Switch
|
<Switch
|
||||||
IsToggled="{Binding Number}"
|
IsToggled="{Binding Number}"
|
||||||
|
IsEnabled="{Binding IsNumberSwitchEnabled}"
|
||||||
StyleClass="box-value"
|
StyleClass="box-value"
|
||||||
HorizontalOptions="End" />
|
HorizontalOptions="End" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
@ -185,6 +211,7 @@
|
||||||
HorizontalOptions="StartAndExpand" />
|
HorizontalOptions="StartAndExpand" />
|
||||||
<Switch
|
<Switch
|
||||||
IsToggled="{Binding Special}"
|
IsToggled="{Binding Special}"
|
||||||
|
IsEnabled="{Binding IsSpecialSwitchEnabled}"
|
||||||
StyleClass="box-value"
|
StyleClass="box-value"
|
||||||
HorizontalOptions="End" />
|
HorizontalOptions="End" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace Bit.App.Pages
|
||||||
private readonly IPlatformUtilsService _platformUtilsService;
|
private readonly IPlatformUtilsService _platformUtilsService;
|
||||||
|
|
||||||
private PasswordGenerationOptions _options;
|
private PasswordGenerationOptions _options;
|
||||||
|
private PasswordGeneratorPolicyOptions _enforcedPolicyOptions;
|
||||||
private string _password;
|
private string _password;
|
||||||
private bool _isPassword;
|
private bool _isPassword;
|
||||||
private bool _uppercase;
|
private bool _uppercase;
|
||||||
|
@ -221,7 +222,34 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PasswordGeneratorPolicyOptions EnforcedPolicyOptions
|
||||||
|
{
|
||||||
|
get => _enforcedPolicyOptions;
|
||||||
|
set => SetProperty(ref _enforcedPolicyOptions, value,
|
||||||
|
additionalPropertyNames: new[]
|
||||||
|
{
|
||||||
|
nameof(IsPolicyInEffect),
|
||||||
|
nameof(IsUppercaseSwitchEnabled),
|
||||||
|
nameof(IsLowercaseSwitchEnabled),
|
||||||
|
nameof(IsNumberSwitchEnabled),
|
||||||
|
nameof(IsSpecialSwitchEnabled)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsPolicyInEffect => _enforcedPolicyOptions.MinLength > 0 || _enforcedPolicyOptions.UseUppercase ||
|
||||||
|
_enforcedPolicyOptions.UseLowercase || _enforcedPolicyOptions.UseNumbers ||
|
||||||
|
_enforcedPolicyOptions.NumberCount > 0 || _enforcedPolicyOptions.UseSpecial ||
|
||||||
|
_enforcedPolicyOptions.SpecialCount > 0;
|
||||||
|
|
||||||
|
public bool IsUppercaseSwitchEnabled => !IsPolicyInEffect || !EnforcedPolicyOptions.UseUppercase;
|
||||||
|
|
||||||
|
public bool IsLowercaseSwitchEnabled => !IsPolicyInEffect || !EnforcedPolicyOptions.UseLowercase;
|
||||||
|
|
||||||
|
public bool IsNumberSwitchEnabled => !IsPolicyInEffect || !EnforcedPolicyOptions.UseNumbers;
|
||||||
|
|
||||||
|
public bool IsSpecialSwitchEnabled => !IsPolicyInEffect || !EnforcedPolicyOptions.UseSpecial;
|
||||||
|
|
||||||
public int TypeSelectedIndex
|
public int TypeSelectedIndex
|
||||||
{
|
{
|
||||||
get => _typeSelectedIndex;
|
get => _typeSelectedIndex;
|
||||||
|
@ -237,7 +265,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public async Task InitAsync()
|
public async Task InitAsync()
|
||||||
{
|
{
|
||||||
_options = await _passwordGenerationService.GetOptionsAsync();
|
(_options, EnforcedPolicyOptions) = await _passwordGenerationService.GetOptionsAsync();
|
||||||
LoadFromOptions();
|
LoadFromOptions();
|
||||||
await RegenerateAsync();
|
await RegenerateAsync();
|
||||||
_doneIniting = true;
|
_doneIniting = true;
|
||||||
|
@ -256,7 +284,7 @@ namespace Bit.App.Pages
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SetOptions();
|
SetOptions();
|
||||||
_passwordGenerationService.NormalizeOptions(_options);
|
_passwordGenerationService.NormalizeOptions(_options, _enforcedPolicyOptions);
|
||||||
await _passwordGenerationService.SaveOptionsAsync(_options);
|
await _passwordGenerationService.SaveOptionsAsync(_options);
|
||||||
LoadFromOptions();
|
LoadFromOptions();
|
||||||
if(regenerate)
|
if(regenerate)
|
||||||
|
@ -274,7 +302,7 @@ namespace Bit.App.Pages
|
||||||
public async Task SliderInputAsync()
|
public async Task SliderInputAsync()
|
||||||
{
|
{
|
||||||
SetOptions();
|
SetOptions();
|
||||||
_passwordGenerationService.NormalizeOptions(_options);
|
_passwordGenerationService.NormalizeOptions(_options, _enforcedPolicyOptions);
|
||||||
Password = await _passwordGenerationService.GeneratePasswordAsync(_options);
|
Password = await _passwordGenerationService.GeneratePasswordAsync(_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
src/App/Resources/AppResources.Designer.cs
generated
6
src/App/Resources/AppResources.Designer.cs
generated
|
@ -2835,5 +2835,11 @@ namespace Bit.App.Resources {
|
||||||
return ResourceManager.GetString("Clone", resourceCulture);
|
return ResourceManager.GetString("Clone", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string PasswordGeneratorPolicyInEffect {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("PasswordGeneratorPolicyInEffect", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1612,4 +1612,7 @@
|
||||||
<value>Clone</value>
|
<value>Clone</value>
|
||||||
<comment>Clone an entity (verb).</comment>
|
<comment>Clone an entity (verb).</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PasswordGeneratorPolicyInEffect" xml:space="preserve">
|
||||||
|
<value>One or more organization policies are affecting your generator settings</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -12,9 +12,9 @@ namespace Bit.Core.Abstractions
|
||||||
Task<string> GeneratePassphraseAsync(PasswordGenerationOptions options);
|
Task<string> GeneratePassphraseAsync(PasswordGenerationOptions options);
|
||||||
Task<string> GeneratePasswordAsync(PasswordGenerationOptions options);
|
Task<string> GeneratePasswordAsync(PasswordGenerationOptions options);
|
||||||
Task<List<GeneratedPasswordHistory>> GetHistoryAsync();
|
Task<List<GeneratedPasswordHistory>> GetHistoryAsync();
|
||||||
Task<PasswordGenerationOptions> GetOptionsAsync();
|
Task<(PasswordGenerationOptions, PasswordGeneratorPolicyOptions)> GetOptionsAsync();
|
||||||
Task<object> PasswordStrength(string password, List<string> userInputs = null);
|
Task<object> PasswordStrength(string password, List<string> userInputs = null);
|
||||||
Task SaveOptionsAsync(PasswordGenerationOptions options);
|
Task SaveOptionsAsync(PasswordGenerationOptions options);
|
||||||
void NormalizeOptions(PasswordGenerationOptions options);
|
void NormalizeOptions(PasswordGenerationOptions options, PasswordGeneratorPolicyOptions enforcedPolicyOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
src/Core/Models/Domain/PasswordGeneratorPolicyOptions.cs
Normal file
13
src/Core/Models/Domain/PasswordGeneratorPolicyOptions.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
namespace Bit.Core.Models.Domain
|
||||||
|
{
|
||||||
|
public class PasswordGeneratorPolicyOptions
|
||||||
|
{
|
||||||
|
public int MinLength { get; set; }
|
||||||
|
public bool UseUppercase { get; set; }
|
||||||
|
public bool UseLowercase { get; set; }
|
||||||
|
public bool UseNumbers { get; set; }
|
||||||
|
public int NumberCount { get; set; }
|
||||||
|
public bool UseSpecial { get; set; }
|
||||||
|
public int SpecialCount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
|
||||||
namespace Bit.Core.Services
|
namespace Bit.Core.Services
|
||||||
{
|
{
|
||||||
|
@ -23,6 +24,7 @@ namespace Bit.Core.Services
|
||||||
private readonly ICryptoService _cryptoService;
|
private readonly ICryptoService _cryptoService;
|
||||||
private readonly IStorageService _storageService;
|
private readonly IStorageService _storageService;
|
||||||
private readonly ICryptoFunctionService _cryptoFunctionService;
|
private readonly ICryptoFunctionService _cryptoFunctionService;
|
||||||
|
private readonly IPolicyService _policyService;
|
||||||
private PasswordGenerationOptions _defaultOptions = new PasswordGenerationOptions(true);
|
private PasswordGenerationOptions _defaultOptions = new PasswordGenerationOptions(true);
|
||||||
private PasswordGenerationOptions _optionsCache;
|
private PasswordGenerationOptions _optionsCache;
|
||||||
private List<GeneratedPasswordHistory> _history;
|
private List<GeneratedPasswordHistory> _history;
|
||||||
|
@ -30,11 +32,13 @@ namespace Bit.Core.Services
|
||||||
public PasswordGenerationService(
|
public PasswordGenerationService(
|
||||||
ICryptoService cryptoService,
|
ICryptoService cryptoService,
|
||||||
IStorageService storageService,
|
IStorageService storageService,
|
||||||
ICryptoFunctionService cryptoFunctionService)
|
ICryptoFunctionService cryptoFunctionService,
|
||||||
|
IPolicyService policyService)
|
||||||
{
|
{
|
||||||
_cryptoService = cryptoService;
|
_cryptoService = cryptoService;
|
||||||
_storageService = storageService;
|
_storageService = storageService;
|
||||||
_cryptoFunctionService = cryptoFunctionService;
|
_cryptoFunctionService = cryptoFunctionService;
|
||||||
|
_policyService = policyService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GeneratePasswordAsync(PasswordGenerationOptions options)
|
public async Task<string> GeneratePasswordAsync(PasswordGenerationOptions options)
|
||||||
|
@ -240,7 +244,7 @@ namespace Bit.Core.Services
|
||||||
return string.Join(options.WordSeparator, wordList);
|
return string.Join(options.WordSeparator, wordList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<PasswordGenerationOptions> GetOptionsAsync()
|
public async Task<(PasswordGenerationOptions,PasswordGeneratorPolicyOptions)> GetOptionsAsync()
|
||||||
{
|
{
|
||||||
if(_optionsCache == null)
|
if(_optionsCache == null)
|
||||||
{
|
{
|
||||||
|
@ -255,7 +259,129 @@ namespace Bit.Core.Services
|
||||||
_optionsCache = options;
|
_optionsCache = options;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _optionsCache;
|
|
||||||
|
var enforcedPolicyOptions = await GetPasswordGeneratorPolicyOptions();
|
||||||
|
if(enforcedPolicyOptions != null)
|
||||||
|
{
|
||||||
|
if(_optionsCache.Length < enforcedPolicyOptions.MinLength)
|
||||||
|
{
|
||||||
|
_optionsCache.Length = enforcedPolicyOptions.MinLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(enforcedPolicyOptions.UseUppercase)
|
||||||
|
{
|
||||||
|
_optionsCache.Uppercase = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(enforcedPolicyOptions.UseLowercase)
|
||||||
|
{
|
||||||
|
_optionsCache.Lowercase = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(enforcedPolicyOptions.UseNumbers)
|
||||||
|
{
|
||||||
|
_optionsCache.Number = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_optionsCache.MinNumber < enforcedPolicyOptions.NumberCount)
|
||||||
|
{
|
||||||
|
_optionsCache.MinNumber = enforcedPolicyOptions.NumberCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(enforcedPolicyOptions.UseSpecial)
|
||||||
|
{
|
||||||
|
_optionsCache.Special = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_optionsCache.MinSpecial < enforcedPolicyOptions.SpecialCount)
|
||||||
|
{
|
||||||
|
_optionsCache.MinSpecial = enforcedPolicyOptions.SpecialCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must normalize these fields because the receiving call expects all options to pass the current rules
|
||||||
|
if(_optionsCache.MinSpecial + _optionsCache.MinNumber > _optionsCache.Length)
|
||||||
|
{
|
||||||
|
_optionsCache.MinSpecial = _optionsCache.Length - _optionsCache.MinNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// UI layer expects an instantiated object to prevent more explicit null checks
|
||||||
|
enforcedPolicyOptions = new PasswordGeneratorPolicyOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (_optionsCache, enforcedPolicyOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PasswordGeneratorPolicyOptions> 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 currentPolicyMinLength = currentPolicy.Data["minLength"];
|
||||||
|
if(currentPolicyMinLength != null &&
|
||||||
|
(int)(long)currentPolicyMinLength > enforcedOptions.MinLength)
|
||||||
|
{
|
||||||
|
enforcedOptions.MinLength = (int)(long)currentPolicyMinLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentPolicyUseUpper = currentPolicy.Data["useUpper"];
|
||||||
|
if(currentPolicyUseUpper != null && (bool)currentPolicyUseUpper)
|
||||||
|
{
|
||||||
|
enforcedOptions.UseUppercase = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentPolicyUseLower = currentPolicy.Data["useLower"];
|
||||||
|
if(currentPolicyUseLower != null && (bool)currentPolicyUseLower)
|
||||||
|
{
|
||||||
|
enforcedOptions.UseLowercase = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentPolicyUseNumbers = currentPolicy.Data["useNumbers"];
|
||||||
|
if(currentPolicyUseNumbers != null && (bool)currentPolicyUseNumbers)
|
||||||
|
{
|
||||||
|
enforcedOptions.UseNumbers = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentPolicyMinNumbers = currentPolicy.Data["minNumbers"];
|
||||||
|
if(currentPolicyMinNumbers != null &&
|
||||||
|
(int)(long)currentPolicyMinNumbers > enforcedOptions.NumberCount)
|
||||||
|
{
|
||||||
|
enforcedOptions.NumberCount = (int)(long)currentPolicyMinNumbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentPolicyUseSpecial = currentPolicy.Data["useSpecial"];
|
||||||
|
if(currentPolicyUseSpecial != null && (bool)currentPolicyUseSpecial)
|
||||||
|
{
|
||||||
|
enforcedOptions.UseSpecial = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentPolicyMinSpecial = currentPolicy.Data["minSpecial"];
|
||||||
|
if(currentPolicyMinSpecial != null &&
|
||||||
|
(int)(long)currentPolicyMinSpecial > enforcedOptions.SpecialCount)
|
||||||
|
{
|
||||||
|
enforcedOptions.SpecialCount = (int)(long)currentPolicyMinSpecial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enforcedOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SaveOptionsAsync(PasswordGenerationOptions options)
|
public async Task SaveOptionsAsync(PasswordGenerationOptions options)
|
||||||
|
@ -315,7 +441,8 @@ namespace Bit.Core.Services
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void NormalizeOptions(PasswordGenerationOptions options)
|
public void NormalizeOptions(PasswordGenerationOptions options,
|
||||||
|
PasswordGeneratorPolicyOptions enforcedPolicyOptions)
|
||||||
{
|
{
|
||||||
options.MinLowercase = 0;
|
options.MinLowercase = 0;
|
||||||
options.MinUppercase = 0;
|
options.MinUppercase = 0;
|
||||||
|
@ -336,6 +463,11 @@ namespace Bit.Core.Services
|
||||||
options.Length = 128;
|
options.Length = 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(options.Length < enforcedPolicyOptions.MinLength)
|
||||||
|
{
|
||||||
|
options.Length = enforcedPolicyOptions.MinLength;
|
||||||
|
}
|
||||||
|
|
||||||
if(options.MinNumber == null)
|
if(options.MinNumber == null)
|
||||||
{
|
{
|
||||||
options.MinNumber = 0;
|
options.MinNumber = 0;
|
||||||
|
@ -348,6 +480,11 @@ namespace Bit.Core.Services
|
||||||
{
|
{
|
||||||
options.MinNumber = 9;
|
options.MinNumber = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(options.MinNumber < enforcedPolicyOptions.NumberCount)
|
||||||
|
{
|
||||||
|
options.MinNumber = enforcedPolicyOptions.NumberCount;
|
||||||
|
}
|
||||||
|
|
||||||
if(options.MinSpecial == null)
|
if(options.MinSpecial == null)
|
||||||
{
|
{
|
||||||
|
@ -362,6 +499,11 @@ namespace Bit.Core.Services
|
||||||
options.MinSpecial = 9;
|
options.MinSpecial = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(options.MinSpecial < enforcedPolicyOptions.SpecialCount)
|
||||||
|
{
|
||||||
|
options.MinSpecial = enforcedPolicyOptions.SpecialCount;
|
||||||
|
}
|
||||||
|
|
||||||
if(options.MinSpecial + options.MinNumber > options.Length)
|
if(options.MinSpecial + options.MinNumber > options.Length)
|
||||||
{
|
{
|
||||||
options.MinSpecial = options.Length - options.MinNumber;
|
options.MinSpecial = options.Length - options.MinNumber;
|
||||||
|
|
|
@ -56,7 +56,7 @@ namespace Bit.Core.Utilities
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
});
|
});
|
||||||
var passwordGenerationService = new PasswordGenerationService(cryptoService, storageService,
|
var passwordGenerationService = new PasswordGenerationService(cryptoService, storageService,
|
||||||
cryptoFunctionService);
|
cryptoFunctionService, policyService);
|
||||||
var totpService = new TotpService(storageService, cryptoFunctionService);
|
var totpService = new TotpService(storageService, cryptoFunctionService);
|
||||||
var authService = new AuthService(cryptoService, apiService, userService, tokenService, appIdService,
|
var authService = new AuthService(cryptoService, apiService, userService, tokenService, appIdService,
|
||||||
i18nService, platformUtilsService, messagingService, lockService);
|
i18nService, platformUtilsService, messagingService, lockService);
|
||||||
|
|
|
@ -71,7 +71,7 @@ namespace Bit.iOS.Core.Controllers
|
||||||
OptionsTableViewController.TableView.SeparatorColor = ThemeHelpers.SeparatorColor;
|
OptionsTableViewController.TableView.SeparatorColor = ThemeHelpers.SeparatorColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
var options = await _passwordGenerationService.GetOptionsAsync();
|
var (options, enforcedPolicyOptions) = await _passwordGenerationService.GetOptionsAsync();
|
||||||
UppercaseCell.Switch.On = options.Uppercase.GetValueOrDefault();
|
UppercaseCell.Switch.On = options.Uppercase.GetValueOrDefault();
|
||||||
LowercaseCell.Switch.On = options.Lowercase.GetValueOrDefault(true);
|
LowercaseCell.Switch.On = options.Lowercase.GetValueOrDefault(true);
|
||||||
SpecialCell.Switch.On = options.Special.GetValueOrDefault();
|
SpecialCell.Switch.On = options.Special.GetValueOrDefault();
|
||||||
|
|
Loading…
Reference in a new issue