2017-11-23 19:02:49 +01:00
|
|
|
|
using System;
|
|
|
|
|
using System.Text;
|
2017-11-24 18:21:06 +01:00
|
|
|
|
using System.Threading.Tasks;
|
2017-11-13 11:28:14 +01:00
|
|
|
|
using Windows.Storage;
|
2020-03-24 19:14:34 +01:00
|
|
|
|
using Windows.Storage.AccessCache;
|
|
|
|
|
using MediatR;
|
|
|
|
|
using ModernKeePass.Application.Database.Commands.UpdateCredentials;
|
|
|
|
|
using ModernKeePass.Application.Database.Queries.OpenDatabase;
|
2020-03-27 18:45:13 +01:00
|
|
|
|
using ModernKeePass.Application.Security.Commands.GenerateKeyFile;
|
|
|
|
|
using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity;
|
2017-11-07 18:45:35 +01:00
|
|
|
|
using ModernKeePass.Common;
|
2017-11-22 18:54:03 +01:00
|
|
|
|
using ModernKeePass.Interfaces;
|
2017-11-29 19:13:38 +01:00
|
|
|
|
using ModernKeePass.Services;
|
2017-11-07 18:45:35 +01:00
|
|
|
|
|
|
|
|
|
namespace ModernKeePass.ViewModels
|
|
|
|
|
{
|
|
|
|
|
public class CompositeKeyVm: NotifyPropertyChangedBase
|
|
|
|
|
{
|
|
|
|
|
public enum StatusTypes
|
|
|
|
|
{
|
|
|
|
|
Normal = 0,
|
|
|
|
|
Error = 1,
|
|
|
|
|
Warning = 3,
|
|
|
|
|
Success = 5
|
|
|
|
|
}
|
2020-03-24 19:14:34 +01:00
|
|
|
|
|
2017-11-07 18:45:35 +01:00
|
|
|
|
public bool HasPassword
|
|
|
|
|
{
|
|
|
|
|
get { return _hasPassword; }
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
SetProperty(ref _hasPassword, value);
|
|
|
|
|
OnPropertyChanged("IsValid");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool HasKeyFile
|
|
|
|
|
{
|
|
|
|
|
get { return _hasKeyFile; }
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
SetProperty(ref _hasKeyFile, value);
|
|
|
|
|
OnPropertyChanged("IsValid");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-20 18:49:11 +01:00
|
|
|
|
public bool HasUserAccount
|
|
|
|
|
{
|
|
|
|
|
get { return _hasUserAccount; }
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
SetProperty(ref _hasUserAccount, value);
|
|
|
|
|
OnPropertyChanged("IsValid");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IsValid => !_isOpening && (HasPassword || HasKeyFile && KeyFile != null || HasUserAccount);
|
2017-11-07 18:45:35 +01:00
|
|
|
|
|
|
|
|
|
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("PasswordComplexityIndicator");
|
|
|
|
|
StatusType = (int)StatusTypes.Normal;
|
2017-11-24 18:21:06 +01:00
|
|
|
|
Status = string.Empty;
|
2017-11-07 18:45:35 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public StorageFile KeyFile
|
|
|
|
|
{
|
|
|
|
|
get { return _keyFile; }
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
_keyFile = value;
|
2017-11-13 11:28:14 +01:00
|
|
|
|
KeyFileText = value?.Name;
|
|
|
|
|
OnPropertyChanged("IsValid");
|
2017-11-07 18:45:35 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-13 11:28:14 +01:00
|
|
|
|
public string KeyFileText
|
|
|
|
|
{
|
|
|
|
|
get { return _keyFileText; }
|
|
|
|
|
set { SetProperty(ref _keyFileText, value); }
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-26 12:25:22 +01:00
|
|
|
|
public Application.Group.Models.GroupVm RootGroup { get; set; }
|
2017-11-22 18:54:03 +01:00
|
|
|
|
|
2020-03-27 18:45:13 +01:00
|
|
|
|
public double PasswordComplexityIndicator => _mediator.Send(new EstimatePasswordComplexityQuery { Password = Password }).GetAwaiter().GetResult();
|
|
|
|
|
|
2017-12-04 10:46:01 +01:00
|
|
|
|
private bool _hasPassword;
|
|
|
|
|
private bool _hasKeyFile;
|
2017-12-20 18:49:11 +01:00
|
|
|
|
private bool _hasUserAccount;
|
2017-12-04 10:46:01 +01:00
|
|
|
|
private bool _isOpening;
|
|
|
|
|
private string _password = string.Empty;
|
|
|
|
|
private string _status;
|
|
|
|
|
private StatusTypes _statusType;
|
|
|
|
|
private StorageFile _keyFile;
|
|
|
|
|
private string _keyFileText;
|
2020-03-24 19:14:34 +01:00
|
|
|
|
private readonly IMediator _mediator;
|
2018-02-23 18:09:21 +01:00
|
|
|
|
private readonly IResourceService _resource;
|
2017-12-04 10:46:01 +01:00
|
|
|
|
|
2020-03-24 19:14:34 +01:00
|
|
|
|
public CompositeKeyVm() : this(App.Mediator, new ResourcesService()) { }
|
2017-11-22 18:54:03 +01:00
|
|
|
|
|
2020-03-24 19:14:34 +01:00
|
|
|
|
public CompositeKeyVm(IMediator mediator, IResourceService resource)
|
2017-11-22 18:54:03 +01:00
|
|
|
|
{
|
2020-03-24 19:14:34 +01:00
|
|
|
|
_mediator = mediator;
|
2017-12-01 17:59:38 +01:00
|
|
|
|
_resource = resource;
|
|
|
|
|
_keyFileText = _resource.GetResourceValue("CompositeKeyDefaultKeyFile");
|
2017-11-22 18:54:03 +01:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-19 18:47:37 +02:00
|
|
|
|
public async Task<bool> OpenDatabase(StorageFile databaseFile, bool createNew)
|
2017-11-07 18:45:35 +01:00
|
|
|
|
{
|
2017-11-23 19:02:49 +01:00
|
|
|
|
try
|
|
|
|
|
{
|
2017-12-04 10:46:01 +01:00
|
|
|
|
_isOpening = true;
|
2020-03-27 18:45:13 +01:00
|
|
|
|
OnPropertyChanged(nameof(IsValid));
|
|
|
|
|
|
|
|
|
|
RootGroup = await _mediator.Send(new OpenDatabaseQuery {
|
|
|
|
|
FilePath = StorageApplicationPermissions.FutureAccessList.Add(databaseFile),
|
|
|
|
|
KeyFilePath = HasKeyFile && KeyFile != null ? StorageApplicationPermissions.FutureAccessList.Add(KeyFile) : null,
|
|
|
|
|
Password = Password = HasPassword ? Password : null,
|
|
|
|
|
});
|
2018-01-08 18:52:03 +01:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
catch (ArgumentException)
|
|
|
|
|
{
|
2018-06-05 18:40:23 +02:00
|
|
|
|
var errorMessage = new StringBuilder($"{_resource.GetResourceValue("CompositeKeyErrorOpen")}\n");
|
|
|
|
|
if (HasPassword) errorMessage.AppendLine(_resource.GetResourceValue("CompositeKeyErrorUserPassword"));
|
|
|
|
|
if (HasKeyFile) errorMessage.AppendLine(_resource.GetResourceValue("CompositeKeyErrorUserKeyFile"));
|
|
|
|
|
if (HasUserAccount) errorMessage.AppendLine(_resource.GetResourceValue("CompositeKeyErrorUserAccount"));
|
2018-01-08 18:52:03 +01:00
|
|
|
|
UpdateStatus(errorMessage.ToString(), StatusTypes.Error);
|
2017-11-23 19:02:49 +01:00
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
2018-06-05 18:40:23 +02:00
|
|
|
|
var error = $"{_resource.GetResourceValue("CompositeKeyErrorOpen")}{e.Message}";
|
2018-01-08 18:52:03 +01:00
|
|
|
|
UpdateStatus(error, StatusTypes.Error);
|
2017-11-23 19:02:49 +01:00
|
|
|
|
}
|
2017-12-04 10:46:01 +01:00
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
_isOpening = false;
|
2018-07-25 18:08:59 +02:00
|
|
|
|
OnPropertyChanged("IsValid");
|
2017-12-04 10:46:01 +01:00
|
|
|
|
}
|
2017-11-13 11:28:14 +01:00
|
|
|
|
return false;
|
2017-11-07 18:45:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-24 13:01:14 +01:00
|
|
|
|
public async Task UpdateKey()
|
2017-11-07 18:45:35 +01:00
|
|
|
|
{
|
2020-03-27 18:45:13 +01:00
|
|
|
|
await _mediator.Send(new UpdateCredentialsCommand
|
|
|
|
|
{
|
|
|
|
|
KeyFilePath = HasKeyFile && KeyFile != null ? StorageApplicationPermissions.FutureAccessList.Add(KeyFile) : null,
|
|
|
|
|
Password = Password = HasPassword ? Password : null,
|
|
|
|
|
});
|
2017-12-01 17:59:38 +01:00
|
|
|
|
UpdateStatus(_resource.GetResourceValue("CompositeKeyUpdated"), StatusTypes.Success);
|
2017-11-07 18:45:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-24 13:01:14 +01:00
|
|
|
|
public async Task CreateKeyFile(StorageFile file)
|
2017-11-17 10:20:54 +01:00
|
|
|
|
{
|
2020-03-27 18:45:13 +01:00
|
|
|
|
var token = StorageApplicationPermissions.FutureAccessList.Add(file);
|
2017-11-17 10:20:54 +01:00
|
|
|
|
// TODO: implement entropy generator
|
2020-03-27 18:45:13 +01:00
|
|
|
|
await _mediator.Send(new GenerateKeyFileCommand {KeyFilePath = token});
|
2017-11-17 10:20:54 +01:00
|
|
|
|
KeyFile = file;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-07 18:45:35 +01:00
|
|
|
|
private void UpdateStatus(string text, StatusTypes type)
|
|
|
|
|
{
|
|
|
|
|
Status = text;
|
|
|
|
|
StatusType = (int)type;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|