mirror of
https://github.com/wismna/ModernKeePass.git
synced 2025-10-03 15:40:18 -04:00
Removed database status in favor of much cleaner code
Implemented (but deactivated) anti corruption mechanism WIP detect changes and save them if opening another database
This commit is contained in:
@@ -46,9 +46,16 @@ namespace ModernKeePass
|
|||||||
? exception.InnerException
|
? exception.InnerException
|
||||||
: exception;
|
: exception;
|
||||||
|
|
||||||
if (!(realException is SaveException)) return;
|
if (realException is SaveException)
|
||||||
unhandledExceptionEventArgs.Handled = true;
|
{
|
||||||
MessageDialogHelper.SaveErrorDialog(realException as SaveException, Database);
|
unhandledExceptionEventArgs.Handled = true;
|
||||||
|
MessageDialogHelper.SaveErrorDialog(realException as SaveException, Database);
|
||||||
|
}
|
||||||
|
else if (realException is DatabaseOpenedException)
|
||||||
|
{
|
||||||
|
unhandledExceptionEventArgs.Handled = true;
|
||||||
|
MessageDialogHelper.SaveUnchangedDialog(realException as DatabaseOpenedException, Database);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Windows.Storage.Pickers;
|
using Windows.Storage.Pickers;
|
||||||
using Windows.UI.Popups;
|
using Windows.UI.Popups;
|
||||||
using Windows.UI.Xaml.Media.Animation;
|
|
||||||
using ModernKeePass.Exceptions;
|
using ModernKeePass.Exceptions;
|
||||||
using ModernKeePass.Interfaces;
|
using ModernKeePass.Interfaces;
|
||||||
|
|
||||||
@@ -10,13 +9,16 @@ namespace ModernKeePass.Common
|
|||||||
{
|
{
|
||||||
public static class MessageDialogHelper
|
public static class MessageDialogHelper
|
||||||
{
|
{
|
||||||
public static async void ShowActionDialog(string title, string contentText, string actionButtonText, string cancelButtonText, UICommandInvokedHandler action)
|
// TODO: include resources
|
||||||
|
public static async void ShowActionDialog(string title, string contentText, string actionButtonText, string cancelButtonText, UICommandInvokedHandler actionCommand, UICommandInvokedHandler cancelCommand)
|
||||||
{
|
{
|
||||||
// Create the message dialog and set its content
|
// Create the message dialog and set its content
|
||||||
var messageDialog = CreateBasicDialog(title, contentText, cancelButtonText);
|
var messageDialog = CreateBasicDialog(title, contentText, cancelButtonText);
|
||||||
|
|
||||||
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
|
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
|
||||||
messageDialog.Commands.Add(new UICommand(actionButtonText, action));
|
messageDialog.Commands.Add(new UICommand(actionButtonText, actionCommand));
|
||||||
|
// TODO: correct this
|
||||||
|
//messageDialog.Commands.Add(new UICommand(cancelButtonText, cancelCommand));
|
||||||
|
|
||||||
// Show the message dialog
|
// Show the message dialog
|
||||||
await messageDialog.ShowAsync();
|
await messageDialog.ShowAsync();
|
||||||
@@ -35,6 +37,19 @@ namespace ModernKeePass.Common
|
|||||||
|
|
||||||
var file = await savePicker.PickSaveFileAsync();
|
var file = await savePicker.PickSaveFileAsync();
|
||||||
if (file != null) database.Save(file);
|
if (file != null) database.Save(file);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SaveUnchangedDialog(DatabaseOpenedException exception, IDatabase database)
|
||||||
|
{
|
||||||
|
ShowActionDialog("Opened database", $"Database {database.Name} is currently opened. What to you wish to do?", "Save changes", "Discard", command =>
|
||||||
|
{
|
||||||
|
database.Save();
|
||||||
|
database.Close();
|
||||||
|
},
|
||||||
|
command =>
|
||||||
|
{
|
||||||
|
database.Close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
9
ModernKeePass/Exceptions/DatabaseOpenedException.cs
Normal file
9
ModernKeePass/Exceptions/DatabaseOpenedException.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Exceptions
|
||||||
|
{
|
||||||
|
public class DatabaseOpenedException: Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
using Windows.Storage;
|
using System.Threading.Tasks;
|
||||||
|
using Windows.Storage;
|
||||||
using ModernKeePass.ViewModels;
|
using ModernKeePass.ViewModels;
|
||||||
using ModernKeePassLib;
|
using ModernKeePassLib;
|
||||||
using ModernKeePassLib.Cryptography.KeyDerivation;
|
using ModernKeePassLib.Cryptography.KeyDerivation;
|
||||||
@@ -10,20 +11,23 @@ namespace ModernKeePass.Interfaces
|
|||||||
{
|
{
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
bool RecycleBinEnabled { get; set; }
|
bool RecycleBinEnabled { get; set; }
|
||||||
int Status { get; set; }
|
//int Status { get; set; }
|
||||||
GroupVm RootGroup { get; set; }
|
GroupVm RootGroup { get; set; }
|
||||||
GroupVm RecycleBin { get; set; }
|
GroupVm RecycleBin { get; set; }
|
||||||
StorageFile DatabaseFile { get; set; }
|
StorageFile DatabaseFile { get; set; }
|
||||||
PwUuid DataCipher { get; set; }
|
PwUuid DataCipher { get; set; }
|
||||||
PwCompressionAlgorithm CompressionAlgorithm { get; set; }
|
PwCompressionAlgorithm CompressionAlgorithm { get; set; }
|
||||||
KdfParameters KeyDerivation { get; set; }
|
KdfParameters KeyDerivation { get; set; }
|
||||||
|
bool IsOpen { get; }
|
||||||
|
bool IsFileOpen { get; }
|
||||||
|
bool IsClosed { get; }
|
||||||
|
|
||||||
void Open(CompositeKey key, bool createNew);
|
Task Open(CompositeKey key, bool createNew);
|
||||||
void UpdateCompositeKey(CompositeKey key);
|
void UpdateCompositeKey(CompositeKey key);
|
||||||
void Save();
|
void Save();
|
||||||
void Save(StorageFile file);
|
void Save(StorageFile file);
|
||||||
void CreateRecycleBin();
|
void CreateRecycleBin();
|
||||||
void AddDeletedItem(PwUuid id);
|
void AddDeletedItem(PwUuid id);
|
||||||
void Close();
|
Task Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -114,6 +114,7 @@
|
|||||||
<Compile Include="App.xaml.cs">
|
<Compile Include="App.xaml.cs">
|
||||||
<DependentUpon>App.xaml</DependentUpon>
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Exceptions\DatabaseOpenedException.cs" />
|
||||||
<Compile Include="Interfaces\ILicenseService.cs" />
|
<Compile Include="Interfaces\ILicenseService.cs" />
|
||||||
<Compile Include="Interfaces\IRecent.cs" />
|
<Compile Include="Interfaces\IRecent.cs" />
|
||||||
<Compile Include="Interfaces\IRecentItem.cs" />
|
<Compile Include="Interfaces\IRecentItem.cs" />
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Windows.Storage;
|
using Windows.Storage;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using ModernKeePass.Exceptions;
|
using ModernKeePass.Exceptions;
|
||||||
@@ -16,7 +17,7 @@ namespace ModernKeePass.Services
|
|||||||
{
|
{
|
||||||
public class DatabaseService: IDatabase
|
public class DatabaseService: IDatabase
|
||||||
{
|
{
|
||||||
public enum DatabaseStatus
|
/*public enum DatabaseStatus
|
||||||
{
|
{
|
||||||
Error = -3,
|
Error = -3,
|
||||||
NoCompositeKey = -2,
|
NoCompositeKey = -2,
|
||||||
@@ -24,9 +25,10 @@ namespace ModernKeePass.Services
|
|||||||
Closed = 0,
|
Closed = 0,
|
||||||
Opening = 1,
|
Opening = 1,
|
||||||
Opened = 2
|
Opened = 2
|
||||||
}
|
}*/
|
||||||
private readonly PwDatabase _pwDatabase = new PwDatabase();
|
private readonly PwDatabase _pwDatabase = new PwDatabase();
|
||||||
private readonly ISettings _settings;
|
private readonly ISettings _settings;
|
||||||
|
private StorageFile _realDatabaseFile;
|
||||||
private StorageFile _databaseFile;
|
private StorageFile _databaseFile;
|
||||||
private GroupVm _recycleBin;
|
private GroupVm _recycleBin;
|
||||||
|
|
||||||
@@ -42,7 +44,7 @@ namespace ModernKeePass.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Status { get; set; } = (int)DatabaseStatus.Closed;
|
//public int Status { get; set; } = (int)DatabaseStatus.Closed;
|
||||||
public string Name => DatabaseFile?.Name;
|
public string Name => DatabaseFile?.Name;
|
||||||
|
|
||||||
public bool RecycleBinEnabled
|
public bool RecycleBinEnabled
|
||||||
@@ -56,8 +58,28 @@ namespace ModernKeePass.Services
|
|||||||
get { return _databaseFile; }
|
get { return _databaseFile; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
// No file, database is closed
|
||||||
|
/*if (value == null)
|
||||||
|
Status = (int) DatabaseStatus.Closed;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There already is an opened file
|
||||||
|
if (Status == (int) DatabaseStatus.Opened)
|
||||||
|
{
|
||||||
|
if (_pwDatabase.Modified)
|
||||||
|
throw new DatabaseOpenedException();
|
||||||
|
Close().GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
_databaseFile = value;
|
||||||
|
Status = (int) DatabaseStatus.Opening;
|
||||||
|
}*/
|
||||||
|
if (IsOpen)
|
||||||
|
{
|
||||||
|
//if (_pwDatabase.Modified)
|
||||||
|
throw new DatabaseOpenedException();
|
||||||
|
//Close().GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
_databaseFile = value;
|
_databaseFile = value;
|
||||||
Status = (int)DatabaseStatus.Opening;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +101,10 @@ namespace ModernKeePass.Services
|
|||||||
set { _pwDatabase.KdfParameters = value; }
|
set { _pwDatabase.KdfParameters = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsOpen => _pwDatabase.IsOpen;
|
||||||
|
public bool IsFileOpen => !_pwDatabase.IsOpen && _databaseFile != null;
|
||||||
|
public bool IsClosed => _databaseFile == null;
|
||||||
|
|
||||||
public DatabaseService() : this(new SettingsService())
|
public DatabaseService() : this(new SettingsService())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@@ -93,14 +119,16 @@ namespace ModernKeePass.Services
|
|||||||
/// <param name="key">The database composite key</param>
|
/// <param name="key">The database composite key</param>
|
||||||
/// <param name="createNew">True to create a new database before opening it</param>
|
/// <param name="createNew">True to create a new database before opening it</param>
|
||||||
/// <returns>An error message, if any</returns>
|
/// <returns>An error message, if any</returns>
|
||||||
public void Open(CompositeKey key, bool createNew = false)
|
public async Task Open(CompositeKey key, bool createNew = false)
|
||||||
{
|
{
|
||||||
|
// TODO: Check if there is an existing backup file
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (key == null)
|
if (key == null)
|
||||||
{
|
{
|
||||||
Status = (int)DatabaseStatus.NoCompositeKey;
|
//Status = (int)DatabaseStatus.NoCompositeKey;
|
||||||
return;
|
//return;
|
||||||
|
throw new ArgumentNullException(nameof(key));
|
||||||
}
|
}
|
||||||
var ioConnection = IOConnectionInfo.FromFile(DatabaseFile);
|
var ioConnection = IOConnectionInfo.FromFile(DatabaseFile);
|
||||||
if (createNew)
|
if (createNew)
|
||||||
@@ -120,17 +148,51 @@ namespace ModernKeePass.Services
|
|||||||
else _pwDatabase.Open(ioConnection, key, new NullStatusLogger());
|
else _pwDatabase.Open(ioConnection, key, new NullStatusLogger());
|
||||||
|
|
||||||
if (!_pwDatabase.IsOpen) return;
|
if (!_pwDatabase.IsOpen) return;
|
||||||
Status = (int)DatabaseStatus.Opened;
|
|
||||||
|
// Copy database in temp directory and use this file for operations
|
||||||
|
if (_settings.GetSetting<bool>("AntiCorruption"))
|
||||||
|
{
|
||||||
|
_realDatabaseFile = _databaseFile;
|
||||||
|
var backupFile =
|
||||||
|
await ApplicationData.Current.RoamingFolder.CreateFileAsync(Name,
|
||||||
|
CreationCollisionOption.FailIfExists);
|
||||||
|
Save(backupFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Status = (int)DatabaseStatus.Opened;
|
||||||
RootGroup = new GroupVm(_pwDatabase.RootGroup, null, RecycleBinEnabled ? _pwDatabase.RecycleBinUuid : null);
|
RootGroup = new GroupVm(_pwDatabase.RootGroup, null, RecycleBinEnabled ? _pwDatabase.RecycleBinUuid : null);
|
||||||
}
|
}
|
||||||
catch (InvalidCompositeKeyException)
|
catch (InvalidCompositeKeyException ex)
|
||||||
{
|
{
|
||||||
Status = (int)DatabaseStatus.CompositeKeyError;
|
//Status = (int)DatabaseStatus.CompositeKeyError;
|
||||||
|
throw new ArgumentException(ex.Message, ex);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
/*catch (Exception)
|
||||||
{
|
{
|
||||||
Status = (int)DatabaseStatus.Error;
|
//Status = (int)DatabaseStatus.Error;
|
||||||
throw;
|
throw;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Commit the changes to the currently opened database to file
|
||||||
|
/// </summary>
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
if (!_pwDatabase.IsOpen) return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_pwDatabase.Save(new NullStatusLogger());
|
||||||
|
|
||||||
|
// Test if save worked correctly
|
||||||
|
if (_settings.GetSetting<bool>("AntiCorruption"))
|
||||||
|
{
|
||||||
|
_pwDatabase.Open(_pwDatabase.IOConnectionInfo, _pwDatabase.MasterKey, new NullStatusLogger());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new SaveException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,35 +213,28 @@ namespace ModernKeePass.Services
|
|||||||
DatabaseFile = oldFile;
|
DatabaseFile = oldFile;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
finally
|
/*finally
|
||||||
{
|
{
|
||||||
Status = (int)DatabaseStatus.Opened;
|
Status = (int)DatabaseStatus.Opened;
|
||||||
}
|
}*/
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Commit the changes to the currently opened database to file
|
|
||||||
/// </summary>
|
|
||||||
public void Save()
|
|
||||||
{
|
|
||||||
if (_pwDatabase == null || !_pwDatabase.IsOpen) return;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_pwDatabase.Save(new NullStatusLogger());
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new SaveException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Close the currently opened database
|
/// Close the currently opened database
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Close()
|
public async Task Close()
|
||||||
{
|
{
|
||||||
_pwDatabase?.Close();
|
_pwDatabase?.Close();
|
||||||
Status = (int)DatabaseStatus.Closed;
|
|
||||||
|
// Restore the backup DB to the original one
|
||||||
|
if (_settings.GetSetting<bool>("AntiCorruption"))
|
||||||
|
{
|
||||||
|
if (_pwDatabase.Modified)
|
||||||
|
Save(_realDatabaseFile);
|
||||||
|
await DatabaseFile.DeleteAsync();
|
||||||
|
}
|
||||||
|
DatabaseFile = null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddDeletedItem(PwUuid id)
|
public void AddDeletedItem(PwUuid id)
|
||||||
|
@@ -124,37 +124,31 @@ namespace ModernKeePass.ViewModels
|
|||||||
|
|
||||||
public async Task<bool> OpenDatabase(bool createNew)
|
public async Task<bool> OpenDatabase(bool createNew)
|
||||||
{
|
{
|
||||||
var error = string.Empty;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_isOpening = true;
|
_isOpening = true;
|
||||||
Database.Open(CreateCompositeKey(), createNew);
|
await Database.Open(CreateCompositeKey(), createNew);
|
||||||
|
await Task.Run(() => RootGroup = Database.RootGroup);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
var errorMessage = new StringBuilder(_resource.GetResourceValue("CompositeKeyErrorUserStart"));
|
||||||
|
if (HasPassword) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserPassword"));
|
||||||
|
if (HasPassword && HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserOr"));
|
||||||
|
if (HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserKeyFile"));
|
||||||
|
if (HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserAccount"));
|
||||||
|
UpdateStatus(errorMessage.ToString(), StatusTypes.Error);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
error = $"{_resource.GetResourceValue("CompositeKeyErrorOpen")}: {e.Message}";
|
var error = $"{_resource.GetResourceValue("CompositeKeyErrorOpen")}: {e.Message}";
|
||||||
|
UpdateStatus(error, StatusTypes.Error);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
_isOpening = false;
|
_isOpening = false;
|
||||||
}
|
}
|
||||||
switch ((DatabaseService.DatabaseStatus)Database.Status)
|
|
||||||
{
|
|
||||||
case DatabaseService.DatabaseStatus.Opened:
|
|
||||||
await Task.Run(() => RootGroup = Database.RootGroup);
|
|
||||||
return true;
|
|
||||||
case DatabaseService.DatabaseStatus.CompositeKeyError:
|
|
||||||
var errorMessage = new StringBuilder(_resource.GetResourceValue("CompositeKeyErrorUserStart"));
|
|
||||||
if (HasPassword) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserPassword"));
|
|
||||||
if (HasPassword && HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserOr"));
|
|
||||||
if (HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserKeyFile"));
|
|
||||||
if (HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserAccount"));
|
|
||||||
UpdateStatus(errorMessage.ToString(), StatusTypes.Error);
|
|
||||||
break;
|
|
||||||
case DatabaseService.DatabaseStatus.Error:
|
|
||||||
UpdateStatus(error, StatusTypes.Error);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -51,7 +51,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
|
|
||||||
public MainVm(Frame referenceFrame, Frame destinationFrame, IDatabase database, IResource resource, IRecent recent)
|
public MainVm(Frame referenceFrame, Frame destinationFrame, IDatabase database, IResource resource, IRecent recent)
|
||||||
{
|
{
|
||||||
var isDatabaseOpen = database != null && database.Status == (int) DatabaseService.DatabaseStatus.Opened;
|
var isDatabaseOpen = database != null && database.IsOpen;
|
||||||
|
|
||||||
var mainMenuItems = new ObservableCollection<MainMenuItemVm>
|
var mainMenuItems = new ObservableCollection<MainMenuItemVm>
|
||||||
{
|
{
|
||||||
@@ -62,7 +62,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
Destination = destinationFrame,
|
Destination = destinationFrame,
|
||||||
Parameter = referenceFrame,
|
Parameter = referenceFrame,
|
||||||
SymbolIcon = Symbol.Page2,
|
SymbolIcon = Symbol.Page2,
|
||||||
IsSelected = database != null && database.Status == (int) DatabaseService.DatabaseStatus.Opening
|
IsSelected = database != null && database.IsFileOpen
|
||||||
},
|
},
|
||||||
new MainMenuItemVm
|
new MainMenuItemVm
|
||||||
{
|
{
|
||||||
@@ -90,7 +90,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
Parameter = referenceFrame,
|
Parameter = referenceFrame,
|
||||||
SymbolIcon = Symbol.Copy,
|
SymbolIcon = Symbol.Copy,
|
||||||
IsSelected =
|
IsSelected =
|
||||||
(database == null || database.Status == (int) DatabaseService.DatabaseStatus.Closed) &&
|
(database == null || database.IsClosed) &&
|
||||||
recent.EntryCount > 0,
|
recent.EntryCount > 0,
|
||||||
IsEnabled = recent.EntryCount > 0
|
IsEnabled = recent.EntryCount > 0
|
||||||
},
|
},
|
||||||
@@ -120,7 +120,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
SelectedItem = mainMenuItems.FirstOrDefault(m => m.IsSelected);
|
SelectedItem = mainMenuItems.FirstOrDefault(m => m.IsSelected);
|
||||||
|
|
||||||
// Add currently opened database to the menu
|
// Add currently opened database to the menu
|
||||||
if (database != null && database.Status == (int) DatabaseService.DatabaseStatus.Opened)
|
if (database != null && database.IsOpen)
|
||||||
mainMenuItems.Add(new MainMenuItemVm
|
mainMenuItems.Add(new MainMenuItemVm
|
||||||
{
|
{
|
||||||
Title = database.Name,
|
Title = database.Name,
|
||||||
|
@@ -8,7 +8,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
{
|
{
|
||||||
public class OpenVm: NotifyPropertyChangedBase
|
public class OpenVm: NotifyPropertyChangedBase
|
||||||
{
|
{
|
||||||
public bool ShowPasswordBox => _database?.Status == (int) DatabaseService.DatabaseStatus.Opening;
|
public bool ShowPasswordBox => _database.IsFileOpen;
|
||||||
|
|
||||||
public string Name => _database?.Name;
|
public string Name => _database?.Name;
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
public OpenVm(IDatabase database)
|
public OpenVm(IDatabase database)
|
||||||
{
|
{
|
||||||
_database = database;
|
_database = database;
|
||||||
if (database == null || database.Status != (int) DatabaseService.DatabaseStatus.Opening) return;
|
if (database == null || !database.IsFileOpen) return;
|
||||||
OpenFile(database.DatabaseFile);
|
OpenFile(database.DatabaseFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using Windows.Storage;
|
using System.Threading.Tasks;
|
||||||
|
using Windows.Storage;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using ModernKeePass.Interfaces;
|
using ModernKeePass.Interfaces;
|
||||||
|
|
||||||
@@ -14,10 +15,11 @@ namespace ModernKeePass.ViewModels
|
|||||||
_database = database;
|
_database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save(bool close = true)
|
public async Task Save(bool close = true)
|
||||||
{
|
{
|
||||||
_database.Save();
|
_database.Save();
|
||||||
if (close) _database.Close();
|
if (close)
|
||||||
|
await _database.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save(StorageFile file)
|
public void Save(StorageFile file)
|
||||||
|
@@ -61,7 +61,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
Group = resource.GetResourceValue("SettingsMenuGroupDatabase"),
|
Group = resource.GetResourceValue("SettingsMenuGroupDatabase"),
|
||||||
SymbolIcon = Symbol.Setting,
|
SymbolIcon = Symbol.Setting,
|
||||||
PageType = typeof(SettingsDatabasePage),
|
PageType = typeof(SettingsDatabasePage),
|
||||||
IsEnabled = database?.Status == 2
|
IsEnabled = database.IsOpen
|
||||||
},
|
},
|
||||||
new ListMenuItemVm
|
new ListMenuItemVm
|
||||||
{
|
{
|
||||||
@@ -69,7 +69,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
Group = resource.GetResourceValue("SettingsMenuGroupDatabase"),
|
Group = resource.GetResourceValue("SettingsMenuGroupDatabase"),
|
||||||
SymbolIcon = Symbol.Permissions,
|
SymbolIcon = Symbol.Permissions,
|
||||||
PageType = typeof(SettingsSecurityPage),
|
PageType = typeof(SettingsSecurityPage),
|
||||||
IsEnabled = database?.Status == 2
|
IsEnabled = database.IsOpen
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
SelectedItem = menuItems.FirstOrDefault(m => m.IsSelected);
|
SelectedItem = menuItems.FirstOrDefault(m => m.IsSelected);
|
||||||
|
@@ -83,7 +83,7 @@ namespace ModernKeePass.Views
|
|||||||
ToastNotificationHelper.ShowMovedToast(Model, resource.GetResourceValue("EntityDeleting"), text);
|
ToastNotificationHelper.ShowMovedToast(Model, resource.GetResourceValue("EntityDeleting"), text);
|
||||||
Model.MarkForDelete();
|
Model.MarkForDelete();
|
||||||
if (Frame.CanGoBack) Frame.GoBack();
|
if (Frame.CanGoBack) Frame.GoBack();
|
||||||
});
|
}, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RestoreButton_Click(object sender, RoutedEventArgs e)
|
private void RestoreButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
@@ -119,7 +119,7 @@ namespace ModernKeePass.Views
|
|||||||
ToastNotificationHelper.ShowMovedToast(Model, resource.GetResourceValue("EntityDeleting"), text);
|
ToastNotificationHelper.ShowMovedToast(Model, resource.GetResourceValue("EntityDeleting"), text);
|
||||||
Model.MarkForDelete();
|
Model.MarkForDelete();
|
||||||
if (Frame.CanGoBack) Frame.GoBack();
|
if (Frame.CanGoBack) Frame.GoBack();
|
||||||
});
|
}, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RestoreButton_Click(object sender, RoutedEventArgs e)
|
private void RestoreButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
@@ -28,10 +28,10 @@ namespace ModernKeePass.Views
|
|||||||
_mainFrame = e.Parameter as Frame;
|
_mainFrame = e.Parameter as Frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveButton_OnClick(object sender, RoutedEventArgs e)
|
private async void SaveButton_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Model.Save();
|
await Model.Save();
|
||||||
_mainFrame.Navigate(typeof(Views.MainPage));
|
_mainFrame.Navigate(typeof(MainPage));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SaveAsButton_OnClick(object sender, RoutedEventArgs e)
|
private async void SaveAsButton_OnClick(object sender, RoutedEventArgs e)
|
||||||
@@ -47,7 +47,7 @@ namespace ModernKeePass.Views
|
|||||||
if (file == null) return;
|
if (file == null) return;
|
||||||
Model.Save(file);
|
Model.Save(file);
|
||||||
|
|
||||||
_mainFrame.Navigate(typeof(Views.MainPage));
|
_mainFrame.Navigate(typeof(MainPage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -90,7 +90,12 @@ namespace ModernKeePass.Views.UserControls
|
|||||||
|
|
||||||
private void PasswordBox_KeyDown(object sender, KeyRoutedEventArgs e)
|
private void PasswordBox_KeyDown(object sender, KeyRoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Key == VirtualKey.Enter && Model.IsValid) OpenButton_OnClick(null, null);
|
if (e.Key == VirtualKey.Enter && Model.IsValid)
|
||||||
|
{
|
||||||
|
OpenButton_OnClick(sender, e);
|
||||||
|
// Stop the event from triggering twice
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void KeyFileButton_Click(object sender, RoutedEventArgs e)
|
private async void KeyFileButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
@@ -16,20 +16,20 @@ namespace ModernKeePassApp.Test
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestCreate()
|
public void TestCreate()
|
||||||
{
|
{
|
||||||
Assert.AreEqual((int) DatabaseService.DatabaseStatus.Closed, _database.Status);
|
Assert.IsTrue(_database.IsClosed);
|
||||||
_database.DatabaseFile = ApplicationData.Current.TemporaryFolder.CreateFileAsync("NewDatabase.kdbx").GetAwaiter().GetResult();
|
_database.DatabaseFile = ApplicationData.Current.TemporaryFolder.CreateFileAsync("NewDatabase.kdbx").GetAwaiter().GetResult();
|
||||||
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Opening, _database.Status);
|
Assert.IsTrue(_database.IsFileOpen);
|
||||||
OpenOrCreateDatabase(true);
|
OpenOrCreateDatabase(true);
|
||||||
_database.Close();
|
_database.Close().GetAwaiter().GetResult();
|
||||||
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Closed, _database.Status);
|
Assert.IsTrue(_database.IsClosed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestOpen()
|
public void TestOpen()
|
||||||
{
|
{
|
||||||
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Closed, _database.Status);
|
Assert.IsTrue(_database.IsClosed);
|
||||||
_database.DatabaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Data\TestDatabase.kdbx").GetAwaiter().GetResult();
|
_database.DatabaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Data\TestDatabase.kdbx").GetAwaiter().GetResult();
|
||||||
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Opening, _database.Status);
|
Assert.IsTrue(_database.IsFileOpen);
|
||||||
OpenOrCreateDatabase(false);
|
OpenOrCreateDatabase(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,23 +38,23 @@ namespace ModernKeePassApp.Test
|
|||||||
{
|
{
|
||||||
TestOpen();
|
TestOpen();
|
||||||
_database.Save(ApplicationData.Current.TemporaryFolder.CreateFileAsync("SaveDatabase.kdbx").GetAwaiter().GetResult());
|
_database.Save(ApplicationData.Current.TemporaryFolder.CreateFileAsync("SaveDatabase.kdbx").GetAwaiter().GetResult());
|
||||||
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Opened, _database.Status);
|
Assert.IsTrue(_database.IsOpen);
|
||||||
_database.Close();
|
_database.Close().GetAwaiter().GetResult();
|
||||||
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Closed, _database.Status);
|
Assert.IsTrue(_database.IsClosed);
|
||||||
TestOpen();
|
TestOpen();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OpenOrCreateDatabase(bool createNew)
|
private void OpenOrCreateDatabase(bool createNew)
|
||||||
{
|
{
|
||||||
_database.Open(null, createNew);
|
Assert.ThrowsException<ArgumentNullException>(
|
||||||
Assert.AreEqual((int)DatabaseService.DatabaseStatus.NoCompositeKey, _database.Status);
|
() => _database.Open(null, createNew).GetAwaiter().GetResult());
|
||||||
var compositeKey = new CompositeKeyVm(_database, new ResourceServiceMock())
|
var compositeKey = new CompositeKeyVm(_database, new ResourceServiceMock())
|
||||||
{
|
{
|
||||||
HasPassword = true,
|
HasPassword = true,
|
||||||
Password = "test"
|
Password = "test"
|
||||||
};
|
};
|
||||||
compositeKey.OpenDatabase(createNew).GetAwaiter().GetResult();
|
compositeKey.OpenDatabase(createNew).GetAwaiter().GetResult();
|
||||||
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Opened, _database.Status);
|
Assert.IsTrue(_database.IsOpen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using ModernKeePass.Interfaces;
|
using ModernKeePass.Interfaces;
|
||||||
using ModernKeePass.ViewModels;
|
using ModernKeePass.ViewModels;
|
||||||
using ModernKeePassLib;
|
using ModernKeePassLib;
|
||||||
@@ -10,6 +11,11 @@ namespace ModernKeePassApp.Test.Mock
|
|||||||
{
|
{
|
||||||
public class DatabaseServiceMock : IDatabase
|
public class DatabaseServiceMock : IDatabase
|
||||||
{
|
{
|
||||||
|
private bool _isOpen;
|
||||||
|
private bool _isFileOpen;
|
||||||
|
private bool _isClosed;
|
||||||
|
|
||||||
|
|
||||||
public PwCompressionAlgorithm CompressionAlgorithm { get; set; }
|
public PwCompressionAlgorithm CompressionAlgorithm { get; set; }
|
||||||
|
|
||||||
public StorageFile DatabaseFile { get; set; }
|
public StorageFile DatabaseFile { get; set; }
|
||||||
@@ -18,6 +24,21 @@ namespace ModernKeePassApp.Test.Mock
|
|||||||
|
|
||||||
public KdfParameters KeyDerivation { get; set; }
|
public KdfParameters KeyDerivation { get; set; }
|
||||||
|
|
||||||
|
public bool IsOpen
|
||||||
|
{
|
||||||
|
get { return _isOpen; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsFileOpen
|
||||||
|
{
|
||||||
|
get { return _isFileOpen; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsClosed
|
||||||
|
{
|
||||||
|
get { return _isClosed; }
|
||||||
|
}
|
||||||
|
|
||||||
public string Name => "MockDatabase";
|
public string Name => "MockDatabase";
|
||||||
|
|
||||||
public GroupVm RecycleBin { get; set; }
|
public GroupVm RecycleBin { get; set; }
|
||||||
@@ -25,17 +46,19 @@ namespace ModernKeePassApp.Test.Mock
|
|||||||
public bool RecycleBinEnabled { get; set; }
|
public bool RecycleBinEnabled { get; set; }
|
||||||
|
|
||||||
public GroupVm RootGroup { get; set; }
|
public GroupVm RootGroup { get; set; }
|
||||||
|
|
||||||
public int Status { get; set; }
|
|
||||||
|
|
||||||
public void AddDeletedItem(PwUuid id)
|
public void AddDeletedItem(PwUuid id)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public Task Close()
|
||||||
{
|
{
|
||||||
Status = 0;
|
return Task.Run(() =>
|
||||||
|
{
|
||||||
|
_isClosed = true;
|
||||||
|
_isOpen = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateRecycleBin()
|
public void CreateRecycleBin()
|
||||||
@@ -43,9 +66,13 @@ namespace ModernKeePassApp.Test.Mock
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Open(CompositeKey key, bool createNew)
|
public Task Open(CompositeKey key, bool createNew)
|
||||||
{
|
{
|
||||||
Status = 2;
|
return Task.Run(() =>
|
||||||
|
{
|
||||||
|
_isOpen = true;
|
||||||
|
_isClosed = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save()
|
public void Save()
|
||||||
@@ -57,7 +84,7 @@ namespace ModernKeePassApp.Test.Mock
|
|||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateCompositeKey(CompositeKey key)
|
public void UpdateCompositeKey(CompositeKey key)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
Reference in New Issue
Block a user