WIP Split composite key user control

Some refactoring
This commit is contained in:
Geoffroy BONNEVILLE
2020-04-20 20:02:43 +02:00
parent 73670e8689
commit 310bd777b2
54 changed files with 849 additions and 1200 deletions

View File

@@ -10,6 +10,8 @@
public class Settings
{
public static string SaveSuspend => nameof(SaveSuspend);
public static string Sample => nameof(Sample);
public static string DefaultFileFormat => nameof(DefaultFileFormat);
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
using Windows.UI.Xaml.Controls;
using ModernKeePass.Domain.AOP;
using ModernKeePass.Domain.Interfaces;
namespace ModernKeePass.ViewModels.ListItems
{
public class ListMenuItemVm : NotifyPropertyChangedBase, IIsEnabled, ISelectableModel
{
private bool _isSelected;
public string Title { get; set; }
public string Group { get; set; } = "_";
public Type PageType { get; set; }
public Symbol SymbolIcon { get; set; }
public bool IsEnabled { get; set; } = true;
public bool IsSelected
{
get { return _isSelected; }
set { SetProperty(ref _isSelected, value); }
}
public override string ToString()
{
return Title;
}
}
}

View File

@@ -0,0 +1,10 @@
using Windows.UI.Xaml.Controls;
namespace ModernKeePass.ViewModels.ListItems
{
public class MainMenuItemVm: ListMenuItemVm
{
public object Parameter { get; set; }
public Frame Destination { get; set; }
}
}

View File

@@ -0,0 +1,56 @@
using Microsoft.Extensions.DependencyInjection;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.AOP;
using ModernKeePass.Domain.Dtos;
using ModernKeePass.Domain.Interfaces;
namespace ModernKeePass.ViewModels.ListItems
{
public class RecentItemVm: NotifyPropertyChangedBase, ISelectableModel
{
private readonly IRecentProxy _recent;
private bool _isSelected;
private string _name;
private string _token;
private string _path;
public string Token
{
get { return _token; }
set { SetProperty(ref _token, value); }
}
public string Name
{
get { return _name; }
set { SetProperty(ref _name, value); }
}
public string Path
{
get { return _path; }
set { SetProperty(ref _path, value); }
}
public bool IsSelected
{
get { return _isSelected; }
set { SetProperty(ref _isSelected, value); }
}
public RecentItemVm(FileInfo file): this(App.Services.GetRequiredService<IRecentProxy>(), file) {}
public RecentItemVm(IRecentProxy recent, FileInfo file)
{
_recent = recent;
Token = file.Id;
Name = file.Name;
Path = file.Path;
}
// Called from XAML
public void UpdateAccessTime()
{
_recent.Get(Token, true).Wait();
}
}
}

View File

@@ -0,0 +1,94 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Database.Models;
using ModernKeePass.Application.Database.Queries.GetDatabase;
using ModernKeePass.Application.Group.Queries.GetGroup;
using ModernKeePass.Application.Parameters.Commands.SetCipher;
using ModernKeePass.Application.Parameters.Commands.SetCompression;
using ModernKeePass.Application.Parameters.Commands.SetHasRecycleBin;
using ModernKeePass.Application.Parameters.Commands.SetKeyDerivation;
using ModernKeePass.Application.Parameters.Commands.SetRecycleBin;
using ModernKeePass.Application.Parameters.Models;
using ModernKeePass.Application.Parameters.Queries.GetCiphers;
using ModernKeePass.Application.Parameters.Queries.GetCompressions;
using ModernKeePass.Application.Parameters.Queries.GetKeyDerivations;
using ModernKeePass.Domain.AOP;
namespace ModernKeePass.ViewModels.ListItems
{
// TODO: implement Kdf settings
public class SettingsDatabaseVm: NotifyPropertyChangedBase
{
private readonly IMediator _mediator;
private readonly DatabaseVm _database;
public bool HasRecycleBin
{
get { return _database.IsRecycleBinEnabled; }
set
{
_mediator.Send(new SetHasRecycleBinCommand {HasRecycleBin = value}).Wait();
OnPropertyChanged(nameof(HasRecycleBin));
}
}
public bool IsNewRecycleBin
{
get { return string.IsNullOrEmpty(_database.RecycleBinId); }
set
{
if (value) _mediator.Send(new SetRecycleBinCommand { RecycleBinId = null }).Wait();
}
}
public ObservableCollection<IEntityVm> Groups { get; }
public ObservableCollection<CipherVm> Ciphers { get; }
public IEnumerable<string> Compressions => _mediator.Send(new GetCompressionsQuery()).GetAwaiter().GetResult();
public ObservableCollection<KeyDerivationVm> KeyDerivations { get; }
public CipherVm SelectedCipher
{
get { return Ciphers.FirstOrDefault(c => c.Id == _database.CipherId); }
set { _mediator.Send(new SetCipherCommand {CipherId = value.Id}).Wait(); }
}
public string SelectedCompression
{
get { return Compressions.FirstOrDefault(c => c == _database.Compression); }
set { _mediator.Send(new SetCompressionCommand {Compression = value}).Wait(); }
}
public KeyDerivationVm SelectedKeyDerivation
{
get { return KeyDerivations.FirstOrDefault(c => c.Id == _database.KeyDerivationId); }
set { _mediator.Send(new SetKeyDerivationCommand {KeyDerivationId = value.Id}).Wait(); }
}
public IEntityVm SelectedRecycleBin
{
get { return Groups.FirstOrDefault(g => g.Id == _database.RecycleBinId); }
set
{
if (!IsNewRecycleBin) _mediator.Send(new SetRecycleBinCommand { RecycleBinId = value.Id}).Wait();
}
}
public SettingsDatabaseVm() : this(App.Services.GetRequiredService<IMediator>()) { }
public SettingsDatabaseVm(IMediator mediator)
{
_mediator = mediator;
_database = _mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
var rootGroup = _mediator.Send(new GetGroupQuery { Id = _database.RootGroupId }).GetAwaiter().GetResult();
Groups = new ObservableCollection<IEntityVm>(rootGroup.SubGroups);
var ciphers = _mediator.Send(new GetCiphersQuery()).GetAwaiter().GetResult();
Ciphers = new ObservableCollection<CipherVm>(ciphers);
var keyDerivations = _mediator.Send(new GetKeyDerivationsQuery()).GetAwaiter().GetResult();
KeyDerivations = new ObservableCollection<KeyDerivationVm>(keyDerivations);
}
}
}

View File

@@ -0,0 +1,34 @@
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Common;
namespace ModernKeePass.ViewModels.ListItems
{
public class SettingsNewVm
{
private readonly ISettingsProxy _settings;
public SettingsNewVm() : this(App.Services.GetRequiredService<ISettingsProxy>())
{ }
public SettingsNewVm(ISettingsProxy settings)
{
_settings = settings;
}
public bool IsCreateSample
{
get { return _settings.GetSetting<bool>(Constants.Settings.Sample); }
set { _settings.PutSetting(Constants.Settings.Sample, value); }
}
public IEnumerable<string> FileFormats => new []{"2", "4"};
public string FileFormatVersion
{
get { return _settings.GetSetting<string>(Constants.Settings.DefaultFileFormat); }
set { _settings.PutSetting(Constants.Settings.DefaultFileFormat, value); }
}
}
}

View File

@@ -0,0 +1,25 @@
using Microsoft.Extensions.DependencyInjection;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Common;
namespace ModernKeePass.ViewModels.ListItems
{
public class SettingsSaveVm
{
private readonly ISettingsProxy _settings;
public SettingsSaveVm() : this(App.Services.GetRequiredService<ISettingsProxy>())
{ }
public SettingsSaveVm(ISettingsProxy settings)
{
_settings = settings;
}
public bool IsSaveSuspend
{
get { return _settings.GetSetting(Constants.Settings.SaveSuspend, true); }
set { _settings.PutSetting(Constants.Settings.SaveSuspend, value); }
}
}
}

View File

@@ -0,0 +1,175 @@
using System;
using System.Text;
using System.Threading.Tasks;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Database.Commands.CreateDatabase;
using ModernKeePass.Application.Database.Commands.UpdateCredentials;
using ModernKeePass.Application.Database.Queries.GetDatabase;
using ModernKeePass.Application.Database.Queries.OpenDatabase;
using ModernKeePass.Application.Security.Commands.GenerateKeyFile;
using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity;
using ModernKeePass.Domain.AOP;
using ModernKeePass.Domain.Dtos;
namespace ModernKeePass.ViewModels
{
public class CompositeKeyVm : NotifyPropertyChangedBase
{
public enum StatusTypes
{
Normal = 0,
Error = 1,
Warning = 3,
Success = 5
}
public bool HasPassword
{
get { return _hasPassword; }
set
{
SetProperty(ref _hasPassword, value);
OnPropertyChanged(nameof(IsValid));
}
}
public bool HasKeyFile
{
get { return _hasKeyFile; }
set
{
SetProperty(ref _hasKeyFile, value);
OnPropertyChanged(nameof(IsValid));
}
}
public bool IsValid => !_isOpening && (HasPassword || HasKeyFile && KeyFilePath != null);
public string Status
{
get { return _status; }
set { SetProperty(ref _status, value); }
}
public int StatusType
{
get { return (int)_statusType; }
set { SetProperty(ref _statusType, (StatusTypes)value); }
}
public string Password
{
get { return _password; }
set
{
_password = value;
OnPropertyChanged(nameof(PasswordComplexityIndicator));
StatusType = (int)StatusTypes.Normal;
Status = string.Empty;
}
}
public string KeyFilePath
{
get { return _keyFilePath; }
set
{
_keyFilePath = value;
OnPropertyChanged(nameof(IsValid));
}
}
public string KeyFileText
{
get { return _keyFileText; }
set { SetProperty(ref _keyFileText, value); }
}
public string RootGroupId { get; set; }
public double PasswordComplexityIndicator => _mediator.Send(new EstimatePasswordComplexityQuery { Password = Password }).GetAwaiter().GetResult();
private bool _hasPassword;
private bool _hasKeyFile;
private bool _isOpening;
private string _password = string.Empty;
private string _status;
private StatusTypes _statusType;
private string _keyFilePath;
private string _keyFileText;
private readonly IMediator _mediator;
private readonly ISettingsProxy _settings;
private readonly IResourceProxy _resource;
public CompositeKeyVm() : this(
App.Services.GetRequiredService<IMediator>(),
App.Services.GetRequiredService<ISettingsProxy>(),
App.Services.GetRequiredService<IResourceProxy>())
{ }
public CompositeKeyVm(IMediator mediator, ISettingsProxy settings, IResourceProxy resource)
{
_mediator = mediator;
_settings = settings;
_resource = resource;
_keyFileText = _resource.GetResourceValue("CompositeKeyDefaultKeyFile");
}
public async Task<bool> OpenDatabase(string databaseFilePath, bool createNew)
{
try
{
_isOpening = true;
OnPropertyChanged(nameof(IsValid));
if (createNew)
{
await _mediator.Send(new CreateDatabaseCommand
{
FilePath = databaseFilePath,
KeyFilePath = HasKeyFile ? KeyFilePath : null,
Password = HasPassword ? Password : null,
Name = "New Database",
CreateSampleData = _settings.GetSetting<bool>("Sample")
});
}
else
{
await _mediator.Send(new OpenDatabaseQuery
{
FilePath = databaseFilePath,
KeyFilePath = HasKeyFile ? KeyFilePath : null,
Password = HasPassword ? Password : null,
});
}
RootGroupId = (await _mediator.Send(new GetDatabaseQuery())).RootGroupId;
return true;
}
catch (ArgumentException)
{
var errorMessage = new StringBuilder($"{_resource.GetResourceValue("CompositeKeyErrorOpen")}\n");
if (HasPassword) errorMessage.AppendLine(_resource.GetResourceValue("CompositeKeyErrorUserPassword"));
if (HasKeyFile) errorMessage.AppendLine(_resource.GetResourceValue("CompositeKeyErrorUserKeyFile"));
UpdateStatus(errorMessage.ToString(), StatusTypes.Error);
}
catch (Exception e)
{
var error = $"{_resource.GetResourceValue("CompositeKeyErrorOpen")}{e.Message}";
UpdateStatus(error, StatusTypes.Error);
}
finally
{
_isOpening = false;
OnPropertyChanged(nameof(IsValid));
}
return false;
}
private void UpdateStatus(string text, StatusTypes type)
{
Status = text;
StatusType = (int)type;
}
}
}

View File

@@ -0,0 +1,153 @@
using System;
using System.Text;
using System.Threading.Tasks;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Database.Queries.GetDatabase;
using ModernKeePass.Application.Database.Queries.OpenDatabase;
using ModernKeePass.Common;
using ModernKeePass.Domain.AOP;
namespace ModernKeePass.ViewModels
{
public class OpenDatabaseControlVm : NotifyPropertyChangedBase
{
public enum StatusTypes
{
Normal = 0,
Error = 1,
Warning = 3,
Success = 5
}
public bool HasPassword
{
get { return _hasPassword; }
set
{
SetProperty(ref _hasPassword, value);
OnPropertyChanged(nameof(IsValid));
}
}
public bool HasKeyFile
{
get { return _hasKeyFile; }
set
{
SetProperty(ref _hasKeyFile, value);
OnPropertyChanged(nameof(IsValid));
}
}
public bool IsValid => !_isOpening && (HasPassword || HasKeyFile && KeyFilePath != null);
public string Status
{
get { return _status; }
set { SetProperty(ref _status, value); }
}
public int StatusType
{
get { return (int)_statusType; }
set { SetProperty(ref _statusType, (StatusTypes)value); }
}
public string Password
{
get { return _password; }
set
{
_password = value;
StatusType = (int)StatusTypes.Normal;
Status = string.Empty;
}
}
public string KeyFilePath
{
get { return _keyFilePath; }
set
{
_keyFilePath = value;
OnPropertyChanged(nameof(IsValid));
}
}
public string KeyFileText
{
get { return _keyFileText; }
set { SetProperty(ref _keyFileText, value); }
}
public string RootGroupId { get; set; }
protected readonly IMediator Mediator;
private readonly IResourceProxy _resource;
private bool _hasPassword;
private bool _hasKeyFile;
private bool _isOpening;
private string _password = string.Empty;
private string _status;
private StatusTypes _statusType;
private string _keyFilePath;
private string _keyFileText;
public OpenDatabaseControlVm() : this(
App.Services.GetRequiredService<IMediator>(),
App.Services.GetRequiredService<IResourceProxy>())
{ }
public OpenDatabaseControlVm(IMediator mediator, IResourceProxy resource)
{
Mediator = mediator;
_resource = resource;
_keyFileText = _resource.GetResourceValue("CompositeKeyDefaultKeyFile");
}
public async Task<bool> OpenDatabase(string databaseFilePath)
{
try
{
_isOpening = true;
OnPropertyChanged(nameof(IsValid));
await Mediator.Send(new OpenDatabaseQuery
{
FilePath = databaseFilePath,
KeyFilePath = HasKeyFile ? KeyFilePath : null,
Password = HasPassword ? Password : null,
});
RootGroupId = (await Mediator.Send(new GetDatabaseQuery())).RootGroupId;
return true;
}
catch (ArgumentException)
{
var errorMessage = new StringBuilder($"{_resource.GetResourceValue("CompositeKeyErrorOpen")}\n");
if (HasPassword) errorMessage.AppendLine(_resource.GetResourceValue("CompositeKeyErrorUserPassword"));
if (HasKeyFile) errorMessage.AppendLine(_resource.GetResourceValue("CompositeKeyErrorUserKeyFile"));
UpdateStatus(errorMessage.ToString(), StatusTypes.Error);
}
catch (Exception e)
{
var error = $"{_resource.GetResourceValue("CompositeKeyErrorOpen")}{e.Message}";
UpdateStatus(error, StatusTypes.Error);
}
finally
{
_isOpening = false;
OnPropertyChanged(nameof(IsValid));
}
return false;
}
private void UpdateStatus(string text, StatusTypes type)
{
Status = text;
StatusType = (int)type;
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Database.Commands.CreateDatabase;
using ModernKeePass.Common;
using ModernKeePass.Domain.Dtos;
namespace ModernKeePass.ViewModels
{
public class UpdateCredentialsViewModel : OpenDatabaseControlVm
{
private readonly ICredentialsProxy _credentials;
private readonly ISettingsProxy _settings;
private string _confirmPassword;
public string ConfirmPassword
{
get { return _confirmPassword; }
set { SetProperty(ref _confirmPassword, value); }
}
public double PasswordComplexityIndicator => _credentials.EstimatePasswordComplexity(Password);
public new bool IsValid => HasPassword && Password == ConfirmPassword || HasKeyFile && KeyFilePath != string.Empty;
public UpdateCredentialsViewModel(): this(App.Services.GetRequiredService<ICredentialsProxy>(), App.Services.GetRequiredService<ISettingsProxy>()) { }
public UpdateCredentialsViewModel(ICredentialsProxy credentials, ISettingsProxy settings)
{
_credentials = credentials;
_settings = settings;
}
public async Task CreateDatabase(FileInfo fileInfo)
{
await Mediator.Send(new CreateDatabaseCommand
{
FilePath = fileInfo.Path,
KeyFilePath = HasKeyFile ? KeyFilePath : null,
Password = HasPassword ? Password : null,
Name = "New Database",
CreateSampleData = _settings.GetSetting<bool>(Constants.Settings.Sample)
});
}
}
}

View File

@@ -38,5 +38,13 @@
<Compile Include="$(MSBuildThisFileDirectory)Extensions\DispatcherTaskExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TemplateSelectors\FirstItemDataTemplateSelector.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TemplateSelectors\SelectableDataTemplateSelector.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\ListMenuItemVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\MainMenuItemVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\RecentItemVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\SettingsDatabaseVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\SettingsNewVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\SettingsSaveVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\OpenDatabaseControlVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\UpdateCredentialsViewModel.cs" />
</ItemGroup>
</Project>