diff --git a/src/App/Pages/Generator/GeneratorPage.xaml b/src/App/Pages/Generator/GeneratorPage.xaml index e4630f1cf..200991294 100644 --- a/src/App/Pages/Generator/GeneratorPage.xaml +++ b/src/App/Pages/Generator/GeneratorPage.xaml @@ -132,6 +132,8 @@ HorizontalOptions="StartAndExpand" /> @@ -143,6 +145,8 @@ HorizontalOptions="StartAndExpand" /> diff --git a/src/App/Pages/Generator/GeneratorPageViewModel.cs b/src/App/Pages/Generator/GeneratorPageViewModel.cs index b0af77a78..2b3db6f18 100644 --- a/src/App/Pages/Generator/GeneratorPageViewModel.cs +++ b/src/App/Pages/Generator/GeneratorPageViewModel.cs @@ -233,10 +233,7 @@ namespace Bit.App.Pages }); } - public bool IsPolicyInEffect => _enforcedPolicyOptions.MinLength > 0 || _enforcedPolicyOptions.UseUppercase || - _enforcedPolicyOptions.UseLowercase || _enforcedPolicyOptions.UseNumbers || - _enforcedPolicyOptions.NumberCount > 0 || _enforcedPolicyOptions.UseSpecial || - _enforcedPolicyOptions.SpecialCount > 0; + public bool IsPolicyInEffect => _enforcedPolicyOptions.InEffect(); public int TypeSelectedIndex { diff --git a/src/Core/Models/Domain/PasswordGeneratorPolicyOptions.cs b/src/Core/Models/Domain/PasswordGeneratorPolicyOptions.cs index 62a78756e..b163f67a7 100644 --- a/src/Core/Models/Domain/PasswordGeneratorPolicyOptions.cs +++ b/src/Core/Models/Domain/PasswordGeneratorPolicyOptions.cs @@ -2,6 +2,7 @@ { public class PasswordGeneratorPolicyOptions { + public string DefaultType { get; set; } public int MinLength { get; set; } public bool UseUppercase { get; set; } public bool UseLowercase { get; set; } @@ -9,5 +10,23 @@ public int NumberCount { get; set; } public bool UseSpecial { get; set; } public int SpecialCount { get; set; } + public int MinNumberOfWords { get; set; } + public bool Capitalize { get; set; } + public bool IncludeNumber { get; set; } + + public bool InEffect() + { + return DefaultType != "" || + MinLength > 0 || + NumberCount > 0 || + SpecialCount > 0 || + UseUppercase || + UseLowercase || + UseNumbers || + UseSpecial || + MinNumberOfWords > 0 || + Capitalize || + IncludeNumber; + } } } diff --git a/src/Core/Services/PasswordGenerationService.cs b/src/Core/Services/PasswordGenerationService.cs index a3289b2cd..34854e6ab 100644 --- a/src/Core/Services/PasswordGenerationService.cs +++ b/src/Core/Services/PasswordGenerationService.cs @@ -312,6 +312,27 @@ namespace Bit.Core.Services { 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 { @@ -344,6 +365,12 @@ namespace Bit.Core.Services 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) { @@ -385,6 +412,24 @@ namespace Bit.Core.Services { 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; @@ -415,6 +460,19 @@ namespace Bit.Core.Services } 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) { @@ -550,6 +608,11 @@ namespace Bit.Core.Services options.NumWords = 20; } + if(options.NumWords < enforcedPolicyOptions.MinNumberOfWords) + { + options.NumWords = enforcedPolicyOptions.MinNumberOfWords; + } + if(options.WordSeparator != null && options.WordSeparator.Length > 1) { options.WordSeparator = options.WordSeparator[0].ToString();