2019-05-13 19:13:23 +03:00
|
|
|
|
using Bit.App.Resources;
|
2019-05-14 15:32:07 +03:00
|
|
|
|
using Bit.App.Utilities;
|
2019-05-13 19:13:23 +03:00
|
|
|
|
using Bit.Core.Abstractions;
|
|
|
|
|
using Bit.Core.Models.Domain;
|
|
|
|
|
using Bit.Core.Utilities;
|
2019-03-29 06:52:33 +03:00
|
|
|
|
using System.Collections.Generic;
|
2019-05-13 19:13:23 +03:00
|
|
|
|
using System.Threading.Tasks;
|
2019-05-14 15:32:07 +03:00
|
|
|
|
using Xamarin.Forms;
|
2019-03-29 06:52:33 +03:00
|
|
|
|
|
|
|
|
|
namespace Bit.App.Pages
|
|
|
|
|
{
|
|
|
|
|
public class GeneratorPageViewModel : BaseViewModel
|
|
|
|
|
{
|
2019-05-13 19:13:23 +03:00
|
|
|
|
private readonly IPasswordGenerationService _passwordGenerationService;
|
|
|
|
|
private readonly IPlatformUtilsService _platformUtilsService;
|
|
|
|
|
|
|
|
|
|
private PasswordGenerationOptions _options;
|
2020-02-28 03:53:02 +03:00
|
|
|
|
private PasswordGeneratorPolicyOptions _enforcedPolicyOptions;
|
2019-05-13 19:13:23 +03:00
|
|
|
|
private string _password;
|
|
|
|
|
private bool _isPassword;
|
2019-05-13 21:43:23 +03:00
|
|
|
|
private bool _uppercase;
|
|
|
|
|
private bool _lowercase;
|
|
|
|
|
private bool _number;
|
|
|
|
|
private bool _special;
|
|
|
|
|
private bool _avoidAmbiguous;
|
|
|
|
|
private int _minNumber;
|
|
|
|
|
private int _minSpecial;
|
2019-05-13 23:06:56 +03:00
|
|
|
|
private int _length = 5;
|
|
|
|
|
private int _numWords = 3;
|
2019-05-13 21:43:23 +03:00
|
|
|
|
private string _wordSeparator;
|
2019-07-01 22:35:26 +03:00
|
|
|
|
private bool _capitalize;
|
|
|
|
|
private bool _includeNumber;
|
2019-05-13 19:13:23 +03:00
|
|
|
|
private int _typeSelectedIndex;
|
2019-05-13 21:43:23 +03:00
|
|
|
|
private bool _doneIniting;
|
2019-05-13 19:13:23 +03:00
|
|
|
|
|
2019-03-29 06:52:33 +03:00
|
|
|
|
public GeneratorPageViewModel()
|
|
|
|
|
{
|
2019-05-13 19:13:23 +03:00
|
|
|
|
_passwordGenerationService = ServiceContainer.Resolve<IPasswordGenerationService>(
|
|
|
|
|
"passwordGenerationService");
|
|
|
|
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
|
|
|
|
PageTitle = AppResources.PasswordGenerator;
|
|
|
|
|
TypeOptions = new List<string> { AppResources.Password, AppResources.Passphrase };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<string> TypeOptions { get; set; }
|
|
|
|
|
|
|
|
|
|
public string Password
|
|
|
|
|
{
|
|
|
|
|
get => _password;
|
2019-05-14 15:32:07 +03:00
|
|
|
|
set => SetProperty(ref _password, value,
|
|
|
|
|
additionalPropertyNames: new string[]
|
|
|
|
|
{
|
|
|
|
|
nameof(ColoredPassword)
|
|
|
|
|
});
|
2019-05-13 19:13:23 +03:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-03 22:56:55 +03:00
|
|
|
|
public string ColoredPassword => PasswordFormatter.FormatPassword(Password);
|
2019-05-14 15:32:07 +03:00
|
|
|
|
|
2019-05-13 19:13:23 +03:00
|
|
|
|
public bool IsPassword
|
|
|
|
|
{
|
|
|
|
|
get => _isPassword;
|
|
|
|
|
set => SetProperty(ref _isPassword, value);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-13 21:43:23 +03:00
|
|
|
|
public int Length
|
2019-05-13 19:13:23 +03:00
|
|
|
|
{
|
2019-05-13 21:43:23 +03:00
|
|
|
|
get => _length;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(SetProperty(ref _length, value))
|
|
|
|
|
{
|
|
|
|
|
_options.Length = value;
|
2019-05-31 18:13:46 +03:00
|
|
|
|
var task = SliderInputAsync();
|
2019-05-13 21:43:23 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool Uppercase
|
|
|
|
|
{
|
|
|
|
|
get => _uppercase;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(SetProperty(ref _uppercase, value))
|
|
|
|
|
{
|
|
|
|
|
_options.Uppercase = value;
|
|
|
|
|
var task = SaveOptionsAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool Lowercase
|
|
|
|
|
{
|
|
|
|
|
get => _lowercase;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(SetProperty(ref _lowercase, value))
|
|
|
|
|
{
|
|
|
|
|
_options.Lowercase = value;
|
|
|
|
|
var task = SaveOptionsAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool Number
|
|
|
|
|
{
|
|
|
|
|
get => _number;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(SetProperty(ref _number, value))
|
|
|
|
|
{
|
|
|
|
|
_options.Number = value;
|
|
|
|
|
var task = SaveOptionsAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool Special
|
|
|
|
|
{
|
|
|
|
|
get => _special;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(SetProperty(ref _special, value))
|
|
|
|
|
{
|
|
|
|
|
_options.Special = value;
|
|
|
|
|
var task = SaveOptionsAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool AvoidAmbiguous
|
|
|
|
|
{
|
|
|
|
|
get => _avoidAmbiguous;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(SetProperty(ref _avoidAmbiguous, value))
|
|
|
|
|
{
|
|
|
|
|
_options.Ambiguous = !value;
|
|
|
|
|
var task = SaveOptionsAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int MinNumber
|
|
|
|
|
{
|
|
|
|
|
get => _minNumber;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(SetProperty(ref _minNumber, value))
|
|
|
|
|
{
|
|
|
|
|
_options.MinNumber = value;
|
|
|
|
|
var task = SaveOptionsAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int MinSpecial
|
|
|
|
|
{
|
|
|
|
|
get => _minSpecial;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(SetProperty(ref _minSpecial, value))
|
|
|
|
|
{
|
|
|
|
|
_options.MinSpecial = value;
|
|
|
|
|
var task = SaveOptionsAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int NumWords
|
|
|
|
|
{
|
|
|
|
|
get => _numWords;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(SetProperty(ref _numWords, value))
|
|
|
|
|
{
|
|
|
|
|
_options.NumWords = value;
|
|
|
|
|
var task = SaveOptionsAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string WordSeparator
|
|
|
|
|
{
|
|
|
|
|
get => _wordSeparator;
|
|
|
|
|
set
|
|
|
|
|
{
|
2019-06-03 21:32:43 +03:00
|
|
|
|
if(value == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-05-13 23:06:56 +03:00
|
|
|
|
var val = value.Trim();
|
|
|
|
|
if(SetProperty(ref _wordSeparator, val))
|
2019-05-13 21:43:23 +03:00
|
|
|
|
{
|
2019-05-13 23:06:56 +03:00
|
|
|
|
_options.WordSeparator = val;
|
2019-05-13 21:43:23 +03:00
|
|
|
|
var task = SaveOptionsAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-05-13 19:13:23 +03:00
|
|
|
|
}
|
|
|
|
|
|
2019-07-01 22:35:26 +03:00
|
|
|
|
public bool Capitalize
|
|
|
|
|
{
|
|
|
|
|
get => _capitalize;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(SetProperty(ref _capitalize, value))
|
|
|
|
|
{
|
|
|
|
|
_options.Capitalize = value;
|
|
|
|
|
var task = SaveOptionsAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IncludeNumber
|
|
|
|
|
{
|
|
|
|
|
get => _includeNumber;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(SetProperty(ref _includeNumber, value))
|
|
|
|
|
{
|
|
|
|
|
_options.Number = value;
|
|
|
|
|
var task = SaveOptionsAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-28 03:53:02 +03:00
|
|
|
|
|
|
|
|
|
public PasswordGeneratorPolicyOptions EnforcedPolicyOptions
|
|
|
|
|
{
|
|
|
|
|
get => _enforcedPolicyOptions;
|
|
|
|
|
set => SetProperty(ref _enforcedPolicyOptions, value,
|
|
|
|
|
additionalPropertyNames: new[]
|
|
|
|
|
{
|
2020-02-28 07:14:26 +03:00
|
|
|
|
nameof(IsPolicyInEffect)
|
2020-02-28 03:53:02 +03:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-14 07:02:38 +03:00
|
|
|
|
public bool IsPolicyInEffect => _enforcedPolicyOptions.InEffect();
|
2020-02-28 03:53:02 +03:00
|
|
|
|
|
2019-05-13 19:13:23 +03:00
|
|
|
|
public int TypeSelectedIndex
|
|
|
|
|
{
|
|
|
|
|
get => _typeSelectedIndex;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if(SetProperty(ref _typeSelectedIndex, value))
|
|
|
|
|
{
|
2019-05-13 21:43:23 +03:00
|
|
|
|
IsPassword = value == 0;
|
|
|
|
|
var task = SaveOptionsAsync();
|
2019-05-13 19:13:23 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task InitAsync()
|
|
|
|
|
{
|
2020-02-28 03:53:02 +03:00
|
|
|
|
(_options, EnforcedPolicyOptions) = await _passwordGenerationService.GetOptionsAsync();
|
2019-05-13 21:43:23 +03:00
|
|
|
|
LoadFromOptions();
|
2019-05-31 16:09:32 +03:00
|
|
|
|
await RegenerateAsync();
|
2019-05-13 21:43:23 +03:00
|
|
|
|
_doneIniting = true;
|
2019-05-13 19:13:23 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task RegenerateAsync()
|
|
|
|
|
{
|
2019-05-13 21:43:23 +03:00
|
|
|
|
Password = await _passwordGenerationService.GeneratePasswordAsync(_options);
|
2019-05-13 19:13:23 +03:00
|
|
|
|
await _passwordGenerationService.AddHistoryAsync(Password);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task SaveOptionsAsync(bool regenerate = true)
|
|
|
|
|
{
|
2019-05-13 21:43:23 +03:00
|
|
|
|
if(!_doneIniting)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
SetOptions();
|
2020-02-28 03:53:02 +03:00
|
|
|
|
_passwordGenerationService.NormalizeOptions(_options, _enforcedPolicyOptions);
|
2019-05-13 21:43:23 +03:00
|
|
|
|
await _passwordGenerationService.SaveOptionsAsync(_options);
|
|
|
|
|
LoadFromOptions();
|
2019-05-13 19:13:23 +03:00
|
|
|
|
if(regenerate)
|
|
|
|
|
{
|
|
|
|
|
await RegenerateAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-31 18:13:46 +03:00
|
|
|
|
public async Task SliderChangedAsync()
|
|
|
|
|
{
|
|
|
|
|
await SaveOptionsAsync(false);
|
|
|
|
|
await _passwordGenerationService.AddHistoryAsync(Password);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task SliderInputAsync()
|
2019-05-31 16:09:32 +03:00
|
|
|
|
{
|
|
|
|
|
SetOptions();
|
2020-02-28 03:53:02 +03:00
|
|
|
|
_passwordGenerationService.NormalizeOptions(_options, _enforcedPolicyOptions);
|
2019-05-31 16:09:32 +03:00
|
|
|
|
Password = await _passwordGenerationService.GeneratePasswordAsync(_options);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-13 19:13:23 +03:00
|
|
|
|
public async Task CopyAsync()
|
|
|
|
|
{
|
|
|
|
|
await _platformUtilsService.CopyToClipboardAsync(Password);
|
2019-06-04 16:48:08 +03:00
|
|
|
|
_platformUtilsService.ShowToast("success", null,
|
|
|
|
|
string.Format(AppResources.ValueHasBeenCopied, AppResources.Password));
|
2019-05-13 19:13:23 +03:00
|
|
|
|
}
|
|
|
|
|
|
2019-05-13 21:43:23 +03:00
|
|
|
|
private void LoadFromOptions()
|
2019-05-13 19:13:23 +03:00
|
|
|
|
{
|
2019-05-13 21:43:23 +03:00
|
|
|
|
AvoidAmbiguous = !_options.Ambiguous.GetValueOrDefault();
|
|
|
|
|
TypeSelectedIndex = _options.Type == "passphrase" ? 1 : 0;
|
2019-05-13 19:13:23 +03:00
|
|
|
|
IsPassword = TypeSelectedIndex == 0;
|
2019-05-13 21:43:23 +03:00
|
|
|
|
MinNumber = _options.MinNumber.GetValueOrDefault();
|
|
|
|
|
MinSpecial = _options.MinSpecial.GetValueOrDefault();
|
|
|
|
|
Special = _options.Special.GetValueOrDefault();
|
|
|
|
|
Number = _options.Number.GetValueOrDefault();
|
|
|
|
|
NumWords = _options.NumWords.GetValueOrDefault();
|
|
|
|
|
WordSeparator = _options.WordSeparator;
|
|
|
|
|
Uppercase = _options.Uppercase.GetValueOrDefault();
|
|
|
|
|
Lowercase = _options.Lowercase.GetValueOrDefault();
|
2019-05-13 23:06:56 +03:00
|
|
|
|
Length = _options.Length.GetValueOrDefault(5);
|
2019-07-01 22:35:26 +03:00
|
|
|
|
Capitalize = _options.Capitalize.GetValueOrDefault();
|
|
|
|
|
IncludeNumber = _options.IncludeNumber.GetValueOrDefault();
|
2019-05-13 21:43:23 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetOptions()
|
|
|
|
|
{
|
|
|
|
|
_options.Ambiguous = !AvoidAmbiguous;
|
|
|
|
|
_options.Type = TypeSelectedIndex == 1 ? "passphrase" : "password";
|
|
|
|
|
_options.MinNumber = MinNumber;
|
|
|
|
|
_options.MinSpecial = MinSpecial;
|
|
|
|
|
_options.Special = Special;
|
|
|
|
|
_options.NumWords = NumWords;
|
|
|
|
|
_options.Number = Number;
|
|
|
|
|
_options.WordSeparator = WordSeparator;
|
|
|
|
|
_options.Uppercase = Uppercase;
|
|
|
|
|
_options.Lowercase = Lowercase;
|
2019-05-13 23:06:56 +03:00
|
|
|
|
_options.Length = Length;
|
2019-07-01 22:35:26 +03:00
|
|
|
|
_options.Capitalize = Capitalize;
|
|
|
|
|
_options.IncludeNumber = IncludeNumber;
|
2019-03-29 06:52:33 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|