diff --git a/ModernKeePass.Application/Application.csproj b/ModernKeePass.Application/Application.csproj
index 813b769..2415ebe 100644
--- a/ModernKeePass.Application/Application.csproj
+++ b/ModernKeePass.Application/Application.csproj
@@ -54,6 +54,9 @@
+
+
+
@@ -71,6 +74,7 @@
+
@@ -78,6 +82,7 @@
+
@@ -102,9 +107,6 @@
-
-
-
diff --git a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
index 61cd1f0..748f0d1 100644
--- a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
+++ b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
@@ -25,8 +25,9 @@ namespace ModernKeePass.Application.Common.Interfaces
void CloseDatabase();
Task AddEntry(string parentGroupId, string entryId);
+ Task InsertEntry(string parentGroupId, string entryId, int messageIndex);
Task AddGroup(string parentGroupId, string groupId);
- void UpdateEntry(string entryId, string fieldName, string fieldValue);
+ void UpdateEntry(string entryId, string fieldName, object fieldValue);
void UpdateGroup(string groupId);
Task RemoveEntry(string parentGroupId, string entryId);
Task RemoveGroup(string parentGroupId, string groupId);
diff --git a/ModernKeePass.Application/Cryptography/Commands/SetCipher/SetCipherCommand.cs b/ModernKeePass.Application/Cryptography/Commands/SetCipher/SetCipherCommand.cs
new file mode 100644
index 0000000..1a5a8fd
--- /dev/null
+++ b/ModernKeePass.Application/Cryptography/Commands/SetCipher/SetCipherCommand.cs
@@ -0,0 +1,27 @@
+using MediatR;
+using ModernKeePass.Application.Common.Interfaces;
+using ModernKeePass.Domain.Exceptions;
+
+namespace ModernKeePass.Application.Cryptography.Commands.SetCipher
+{
+ public class SetCipherCommand : IRequest
+ {
+ public string CipherId { get; set; }
+
+ public class SetCipherCommandHandler : IRequestHandler
+ {
+ private readonly IDatabaseProxy _database;
+
+ public SetCipherCommandHandler(IDatabaseProxy database)
+ {
+ _database = database;
+ }
+
+ public void Handle(SetCipherCommand message)
+ {
+ if (_database.IsOpen) _database.CipherId = message.CipherId;
+ else throw new DatabaseClosedException();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePass.Application/Cryptography/Commands/SetCompression/SetCompressionCommand.cs b/ModernKeePass.Application/Cryptography/Commands/SetCompression/SetCompressionCommand.cs
new file mode 100644
index 0000000..7a95564
--- /dev/null
+++ b/ModernKeePass.Application/Cryptography/Commands/SetCompression/SetCompressionCommand.cs
@@ -0,0 +1,27 @@
+using MediatR;
+using ModernKeePass.Application.Common.Interfaces;
+using ModernKeePass.Domain.Exceptions;
+
+namespace ModernKeePass.Application.Cryptography.Commands.SetCompression
+{
+ public class SetCompressionCommand : IRequest
+ {
+ public string Compression { get; set; }
+
+ public class SetCompressionCommandHandler : IRequestHandler
+ {
+ private readonly IDatabaseProxy _database;
+
+ public SetCompressionCommandHandler(IDatabaseProxy database)
+ {
+ _database = database;
+ }
+
+ public void Handle(SetCompressionCommand message)
+ {
+ if (_database.IsOpen) _database.Compression = message.Compression;
+ else throw new DatabaseClosedException();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePass.Application/Cryptography/Commands/SetKeyDerivation/SetKeyDerivationCommand.cs b/ModernKeePass.Application/Cryptography/Commands/SetKeyDerivation/SetKeyDerivationCommand.cs
new file mode 100644
index 0000000..cbeb949
--- /dev/null
+++ b/ModernKeePass.Application/Cryptography/Commands/SetKeyDerivation/SetKeyDerivationCommand.cs
@@ -0,0 +1,27 @@
+using MediatR;
+using ModernKeePass.Application.Common.Interfaces;
+using ModernKeePass.Domain.Exceptions;
+
+namespace ModernKeePass.Application.Cryptography.Commands.SetKeyDerivation
+{
+ public class SetKeyDerivationCommand : IRequest
+ {
+ public string KeyDerivationId { get; set; }
+
+ public class SetKeyDerivationCommandHandler : IRequestHandler
+ {
+ private readonly IDatabaseProxy _database;
+
+ public SetKeyDerivationCommandHandler(IDatabaseProxy database)
+ {
+ _database = database;
+ }
+
+ public void Handle(SetKeyDerivationCommand message)
+ {
+ if (_database.IsOpen) _database.KeyDerivationId = message.KeyDerivationId;
+ else throw new DatabaseClosedException();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePass.Application/Database/Commands/UpdateCredentials/UpdateCredentialsCommand.cs b/ModernKeePass.Application/Database/Commands/UpdateCredentials/UpdateCredentialsCommand.cs
index b565c0c..beb1314 100644
--- a/ModernKeePass.Application/Database/Commands/UpdateCredentials/UpdateCredentialsCommand.cs
+++ b/ModernKeePass.Application/Database/Commands/UpdateCredentials/UpdateCredentialsCommand.cs
@@ -14,7 +14,7 @@ namespace ModernKeePass.Application.Database.Commands.UpdateCredentials
{
private readonly IDatabaseProxy _database;
- public UpdateCredentialsCommandHandler(IDatabaseProxy database, IMediator mediator)
+ public UpdateCredentialsCommandHandler(IDatabaseProxy database)
{
_database = database;
}
diff --git a/ModernKeePass.Application/DependencyInjection.cs b/ModernKeePass.Application/DependencyInjection.cs
index 0b9a065..4e0ebd1 100644
--- a/ModernKeePass.Application/DependencyInjection.cs
+++ b/ModernKeePass.Application/DependencyInjection.cs
@@ -13,7 +13,7 @@ namespace ModernKeePass.Application
var assembly = typeof(DependencyInjection).GetTypeInfo().Assembly;
services.AddAutoMapper(assembly);
services.AddMediatR(assembly);
- //services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());
+ //services.AddValidatorsFromAssembly(assembly);
return services;
}
diff --git a/ModernKeePass.Application/Entry/Commands/SetFieldValue/SetFieldValueCommand.cs b/ModernKeePass.Application/Entry/Commands/SetFieldValue/SetFieldValueCommand.cs
index c9379c5..32176ec 100644
--- a/ModernKeePass.Application/Entry/Commands/SetFieldValue/SetFieldValueCommand.cs
+++ b/ModernKeePass.Application/Entry/Commands/SetFieldValue/SetFieldValueCommand.cs
@@ -8,7 +8,7 @@ namespace ModernKeePass.Application.Entry.Commands.SetFieldValue
{
public string EntryId { get; set; }
public string FieldName { get; set; }
- public string FieldValue { get; set; }
+ public object FieldValue { get; set; }
public class SetFieldValueCommandHandler : IRequestHandler
{
diff --git a/ModernKeePass.Application/Entry/Commands/SetFieldValue/SetFieldValueCommandValidator.cs b/ModernKeePass.Application/Entry/Commands/SetFieldValue/SetFieldValueCommandValidator.cs
new file mode 100644
index 0000000..c2f20d1
--- /dev/null
+++ b/ModernKeePass.Application/Entry/Commands/SetFieldValue/SetFieldValueCommandValidator.cs
@@ -0,0 +1,17 @@
+using FluentValidation;
+
+namespace ModernKeePass.Application.Entry.Commands.SetFieldValue
+{
+ public class SetFieldValueCommandValidator: AbstractValidator
+ {
+ public SetFieldValueCommandValidator()
+ {
+ RuleFor(v => v.EntryId)
+ .NotNull()
+ .NotEmpty();
+ RuleFor(v => v.FieldName)
+ .NotNull()
+ .NotEmpty();
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePass.Application/Entry/Models/EntryVm.cs b/ModernKeePass.Application/Entry/Models/EntryVm.cs
index ea13b79..f218bd0 100644
--- a/ModernKeePass.Application/Entry/Models/EntryVm.cs
+++ b/ModernKeePass.Application/Entry/Models/EntryVm.cs
@@ -17,7 +17,7 @@ namespace ModernKeePass.Application.Entry.Models
public string Notes { get; set; }
public Uri Url { get; set; }
public Dictionary AdditionalFields { get; set; }
- public IEnumerable History { get; set; }
+ public IEnumerable History { get; set; }
public Icon Icon { get; set; }
public Color ForegroundColor { get; set; }
public Color BackgroundColor { get; set; }
diff --git a/ModernKeePass.Application/Group/Commands/InsertEntry/InsertEntryCommand.cs b/ModernKeePass.Application/Group/Commands/InsertEntry/InsertEntryCommand.cs
new file mode 100644
index 0000000..db3e417
--- /dev/null
+++ b/ModernKeePass.Application/Group/Commands/InsertEntry/InsertEntryCommand.cs
@@ -0,0 +1,34 @@
+using System.Threading.Tasks;
+using MediatR;
+using ModernKeePass.Application.Common.Interfaces;
+using ModernKeePass.Application.Entry.Models;
+using ModernKeePass.Application.Group.Models;
+using ModernKeePass.Domain.Exceptions;
+
+namespace ModernKeePass.Application.Group.Commands.InsertEntry
+{
+ public class InsertEntryCommand : IRequest
+ {
+ public GroupVm ParentGroup { get; set; }
+ public EntryVm Entry { get; set; }
+ public int Index { get; set; }
+
+ public class InsertEntryCommandHandler : IAsyncRequestHandler
+ {
+ private readonly IDatabaseProxy _database;
+
+ public InsertEntryCommandHandler(IDatabaseProxy database)
+ {
+ _database = database;
+ }
+
+ public async Task Handle(InsertEntryCommand message)
+ {
+ if (!_database.IsOpen) throw new DatabaseClosedException();
+
+ await _database.InsertEntry(message.ParentGroup.Id, message.Entry.Id, message.Index);
+ message.ParentGroup.Entries.Insert(message.Index, message.Entry);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
index daf6d2a..bcdb38f 100644
--- a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
+++ b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
@@ -5,6 +5,7 @@ using AutoMapper;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Dtos;
using ModernKeePass.Domain.Entities;
+using ModernKeePass.Domain.Enums;
using ModernKeePass.Domain.Exceptions;
using ModernKeePassLib;
using ModernKeePassLib.Cryptography.KeyDerivation;
@@ -45,6 +46,7 @@ namespace ModernKeePass.Infrastructure.KeePass
}
set { _pwDatabase.RecycleBinUuid = BuildIdFromString(value); }
}
+
public string CipherId
{
get { return _pwDatabase.DataCipherUuid.ToHexString(); }
@@ -168,6 +170,17 @@ namespace ModernKeePass.Infrastructure.KeePass
parentPwGroup.AddEntry(pwEntry, true);
});
}
+
+ public async Task InsertEntry(string parentGroupId, string entryId, int index)
+ {
+ await Task.Run(() =>
+ {
+ var parentPwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(parentGroupId), true);
+ var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
+ parentPwGroup.Entries.Insert((uint)index, pwEntry);
+ });
+ }
+
public async Task AddGroup(string parentGroupId, string groupId)
{
await Task.Run(() =>
@@ -197,15 +210,34 @@ namespace ModernKeePass.Infrastructure.KeePass
});
}
- public void UpdateEntry(string entryId, string fieldName, string fieldValue)
+ public void UpdateEntry(string entryId, string fieldName, object fieldValue)
{
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
pwEntry.Touch(true);
pwEntry.CreateBackup(null);
- pwEntry.Strings.Set(EntryFieldMapper.MapFieldToPwDef(fieldName), new ProtectedString(true, fieldValue));
+
+ switch (fieldName)
+ {
+ case EntryFieldName.Title:
+ case EntryFieldName.UserName:
+ case EntryFieldName.Password:
+ case EntryFieldName.Notes:
+ case EntryFieldName.Url:
+ pwEntry.Strings.Set(EntryFieldMapper.MapFieldToPwDef(fieldName), new ProtectedString(true, fieldValue.ToString()));
+ break;
+ case EntryFieldName.HasExpirationDate:
+ pwEntry.Expires = (bool)fieldValue;
+ break;
+ case EntryFieldName.ExpirationDate:
+ pwEntry.ExpiryTime = (DateTime)fieldValue;
+ break;
+ case EntryFieldName.Icon:
+ pwEntry.IconId = IconMapper.MapIconToPwIcon((Icon)fieldValue);
+ break;
+ }
}
- public void UpdateGroup(string group)
+ public void UpdateGroup(string groupId)
{
throw new NotImplementedException();
}
@@ -237,7 +269,7 @@ namespace ModernKeePass.Infrastructure.KeePass
var id = pwEntry.Uuid;
pwEntry.ParentGroup.Entries.Remove(pwEntry);
- if (_pwDatabase.RecycleBinEnabled)
+ if (!_pwDatabase.RecycleBinEnabled || pwEntry.ParentGroup.Uuid.Equals(_pwDatabase.RecycleBinUuid))
{
_pwDatabase.DeletedObjects.Add(new PwDeletedObject(id, DateTime.UtcNow));
}
@@ -252,7 +284,7 @@ namespace ModernKeePass.Infrastructure.KeePass
var id = pwGroup.Uuid;
pwGroup.ParentGroup.Groups.Remove(pwGroup);
- if (_pwDatabase.RecycleBinEnabled)
+ if (!_pwDatabase.RecycleBinEnabled || pwGroup.ParentGroup.Uuid.Equals(_pwDatabase.RecycleBinUuid))
{
_pwDatabase.DeletedObjects.Add(new PwDeletedObject(id, DateTime.UtcNow));
}
diff --git a/ModernKeePass/Actions/DeleteEntityAction.cs b/ModernKeePass/Actions/DeleteEntityAction.cs
index cc08709..ba23276 100644
--- a/ModernKeePass/Actions/DeleteEntityAction.cs
+++ b/ModernKeePass/Actions/DeleteEntityAction.cs
@@ -1,9 +1,9 @@
using System.Windows.Input;
using Windows.UI.Xaml;
using Microsoft.Xaml.Interactivity;
+using ModernKeePass.Application.Resources.Queries;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
-using ModernKeePass.Services;
using ModernKeePass.ViewModels;
namespace ModernKeePass.Actions
@@ -32,19 +32,23 @@ namespace ModernKeePass.Actions
public object Execute(object sender, object parameter)
{
- var resource = new ResourcesService();
+ var mediator = App.Mediator;
var type = Entity is GroupVm ? "Group" : "Entry";
var message = Entity.IsRecycleOnDelete
- ? resource.GetResourceValue($"{type}RecyclingConfirmation")
- : resource.GetResourceValue($"{type}DeletingConfirmation");
- var text = Entity.IsRecycleOnDelete ? resource.GetResourceValue($"{type}Recycled") : resource.GetResourceValue($"{type}Deleted");
- MessageDialogHelper.ShowActionDialog(resource.GetResourceValue("EntityDeleteTitle"), message,
- resource.GetResourceValue("EntityDeleteActionButton"),
- resource.GetResourceValue("EntityDeleteCancelButton"), a =>
+ ? mediator.Send(new GetResourceQuery { Key = $"{type}RecyclingConfirmation" })
+ : mediator.Send(new GetResourceQuery { Key = $"{type}DeletingConfirmation" });
+ var text = Entity.IsRecycleOnDelete ?
+ mediator.Send(new GetResourceQuery { Key = $"{type}Recycled" }) :
+ mediator.Send(new GetResourceQuery { Key = $"{type}Deleted" });
+ MessageDialogHelper.ShowActionDialog(
+ mediator.Send(new GetResourceQuery { Key = "EntityDeleteTitle" }).GetAwaiter().GetResult(),
+ message.GetAwaiter().GetResult(),
+ mediator.Send(new GetResourceQuery { Key = "EntityDeleteActionButton" }).GetAwaiter().GetResult(),
+ mediator.Send(new GetResourceQuery { Key = "EntityDeleteCancelButton" }).GetAwaiter().GetResult(), async a =>
{
- ToastNotificationHelper.ShowMovedToast(Entity, resource.GetResourceValue("EntityDeleting"), text);
- Entity.MarkForDelete(resource.GetResourceValue("RecycleBinTitle"));
+ ToastNotificationHelper.ShowMovedToast(Entity, await mediator.Send(new GetResourceQuery { Key = "EntityDeleting" }), await text);
+ await Entity.MarkForDelete(await mediator.Send(new GetResourceQuery { Key = "RecycleBinTitle"}));
Command.Execute(null);
}, null).GetAwaiter();
diff --git a/ModernKeePass/Common/ToastNotificationHelper.cs b/ModernKeePass/Common/ToastNotificationHelper.cs
index 1dd88c8..9b2592e 100644
--- a/ModernKeePass/Common/ToastNotificationHelper.cs
+++ b/ModernKeePass/Common/ToastNotificationHelper.cs
@@ -13,7 +13,7 @@ namespace ModernKeePass.Common
{
var notificationXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
var toastElements = notificationXml.GetElementsByTagName("text");
- toastElements[0].AppendChild(notificationXml.CreateTextNode($"{action} {entity.Name}"));
+ toastElements[0].AppendChild(notificationXml.CreateTextNode($"{action} {entity.Title}"));
toastElements[1].AppendChild(notificationXml.CreateTextNode(text));
var toastNode = notificationXml.SelectSingleNode("/toast");
diff --git a/ModernKeePass/Interfaces/IVmEntity.cs b/ModernKeePass/Interfaces/IVmEntity.cs
index 093ae64..7bd1203 100644
--- a/ModernKeePass/Interfaces/IVmEntity.cs
+++ b/ModernKeePass/Interfaces/IVmEntity.cs
@@ -9,9 +9,9 @@ namespace ModernKeePass.Interfaces
{
GroupVm ParentGroup { get; }
GroupVm PreviousGroup { get; }
- int IconId { get; }
+ int Icon { get; }
string Id { get; }
- string Name { get; set; }
+ string Title { get; set; }
IEnumerable BreadCrumb { get; }
bool IsEditMode { get; }
bool IsRecycleOnDelete { get; }
diff --git a/ModernKeePass/Services/ImportService.cs b/ModernKeePass/Services/ImportService.cs
index e339abc..baa718f 100644
--- a/ModernKeePass/Services/ImportService.cs
+++ b/ModernKeePass/Services/ImportService.cs
@@ -14,7 +14,7 @@ namespace ModernKeePass.Services
foreach (var entity in data)
{
var entry = group.AddNewEntry();
- entry.Name = entity["0"];
+ entry.Title = entity["0"];
entry.UserName = entity["1"];
entry.Password = entity["2"];
if (entity.Count > 3) entry.Url = entity["3"];
diff --git a/ModernKeePass/ViewModels/EntryVm.cs b/ModernKeePass/ViewModels/EntryVm.cs
index 02994af..1adb5eb 100644
--- a/ModernKeePass/ViewModels/EntryVm.cs
+++ b/ModernKeePass/ViewModels/EntryVm.cs
@@ -1,25 +1,27 @@
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using System.Drawing;
+using System.Threading.Tasks;
using System.Windows.Input;
+using MediatR;
+using ModernKeePass.Application.Database.Commands.SaveDatabase;
+using ModernKeePass.Application.Entry.Commands.SetFieldValue;
+using ModernKeePass.Application.Group.Commands.DeleteEntry;
+using ModernKeePass.Application.Resources.Queries;
+using ModernKeePass.Application.Security.Commands.GeneratePassword;
+using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
-using ModernKeePass.Services;
-using ModernKeePassLib;
-using ModernKeePassLib.Cryptography.PasswordGenerator;
-using ModernKeePassLib.Security;
-using ModernKeePassLib.Cryptography;
namespace ModernKeePass.ViewModels
{
- public class EntryVm : INotifyPropertyChanged, IVmEntity, ISelectableModel
+ public class EntryVm : NotifyPropertyChangedBase, IVmEntity, ISelectableModel
{
public GroupVm ParentGroup { get; private set; }
public GroupVm PreviousGroup { get; private set; }
public bool IsRevealPasswordEnabled => !string.IsNullOrEmpty(Password);
- public bool HasExpired => HasExpirationDate && _pwEntry.ExpiryTime < DateTime.Now;
- public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password?.ToCharArray());
+ public bool HasExpired => HasExpirationDate && ExpiryDate < DateTime.Now;
+ public double PasswordComplexityIndicator => _mediator.Send(new EstimatePasswordComplexityQuery {Password = Password}).GetAwaiter().GetResult();
public bool UpperCasePatternSelected { get; set; } = true;
public bool LowerCasePatternSelected { get; set; } = true;
public bool DigitsPatternSelected { get; set; } = true;
@@ -29,8 +31,7 @@ namespace ModernKeePass.ViewModels
public bool SpecialPatternSelected { get; set; }
public bool BracketsPatternSelected { get; set; }
public string CustomChars { get; set; } = string.Empty;
- public PwUuid IdUuid => _pwEntry?.Uuid;
- public string Id => _pwEntry?.Uuid.ToHexString();
+ public string Id => _entry.Id;
public bool IsRecycleOnDelete => _database.RecycleBinEnabled && !ParentGroup.IsSelected;
public IEnumerable BreadCrumb => new List(ParentGroup.BreadCrumb) {ParentGroup};
///
@@ -44,80 +45,73 @@ namespace ModernKeePass.ViewModels
set
{
_passwordLength = value;
- NotifyPropertyChanged("PasswordLength");
+ OnPropertyChanged();
}
}
- public string Name
+ public string Title
{
- get { return GetEntryValue(PwDefs.TitleField); }
- set { SetEntryValue(PwDefs.TitleField, new ProtectedString(true, value)); }
+ get { return _entry.Title; }
+ set { _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Title), FieldValue = value}); }
}
public string UserName
{
- get { return GetEntryValue(PwDefs.UserNameField); }
- set { SetEntryValue(PwDefs.UserNameField, new ProtectedString(true, value)); }
+ get { return _entry.Username; }
+ set { _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(UserName), FieldValue = value }); }
}
public string Password
{
- get { return GetEntryValue(PwDefs.PasswordField); }
+ get { return _entry.Password; }
set
{
- SetEntryValue(PwDefs.PasswordField, new ProtectedString(true, value));
- NotifyPropertyChanged("Password");
- NotifyPropertyChanged("PasswordComplexityIndicator");
+ _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Password), FieldValue = value });
+ OnPropertyChanged();
+ OnPropertyChanged(nameof(PasswordComplexityIndicator));
}
}
public string Url
{
- get { return GetEntryValue(PwDefs.UrlField); }
- set { SetEntryValue(PwDefs.UrlField, new ProtectedString(true, value)); }
+ get { return _entry.Url.ToString();}
+ set { _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Url), FieldValue = value }); }
}
public string Notes
{
- get { return GetEntryValue(PwDefs.NotesField); }
- set { SetEntryValue(PwDefs.NotesField, new ProtectedString(true, value)); }
+ get { return _entry.Notes; }
+ set { _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Notes), FieldValue = value }); }
}
- public int IconId
+ public int Icon
{
get
{
- if (HasExpired) return (int) PwIcon.Expired;
- if (_pwEntry?.IconId != null) return (int) _pwEntry?.IconId;
- return -1;
- }
- set
- {
- HandleBackup();
- _pwEntry.IconId = (PwIcon)value;
+ if (HasExpired) return (int)Domain.Enums.Icon.ReportHacked;
+ return (int) _entry.Icon;
}
+ set { _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = nameof(Icon), FieldValue = value }); }
}
public DateTimeOffset ExpiryDate
{
- get { return new DateTimeOffset(_pwEntry.ExpiryTime.Date); }
+ get { return _entry.ExpirationDate; }
set
{
if (!HasExpirationDate) return;
- HandleBackup();
- _pwEntry.ExpiryTime = value.DateTime;
+ _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = "ExpirationDate", FieldValue = value.Date });
}
}
public TimeSpan ExpiryTime
{
- get { return _pwEntry.ExpiryTime.TimeOfDay; }
+ get { return _entry.ExpirationDate.TimeOfDay; }
set
{
if (!HasExpirationDate) return;
- HandleBackup();
- _pwEntry.ExpiryTime = _pwEntry.ExpiryTime.Date.Add(value);
+ _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = "ExpirationDate", FieldValue = ExpiryDate.Date.Add(value) });
}
}
@@ -127,7 +121,7 @@ namespace ModernKeePass.ViewModels
set
{
_isEditMode = value;
- NotifyPropertyChanged("IsEditMode");
+ OnPropertyChanged();
}
}
@@ -137,7 +131,7 @@ namespace ModernKeePass.ViewModels
set
{
_isVisible = value;
- NotifyPropertyChanged("IsVisible");
+ OnPropertyChanged();
}
}
@@ -147,16 +141,16 @@ namespace ModernKeePass.ViewModels
set
{
_isRevealPassword = value;
- NotifyPropertyChanged("IsRevealPassword");
+ OnPropertyChanged();
}
}
public bool HasExpirationDate
{
- get { return _pwEntry.Expires; }
+ get { return _entry.HasExpirationDate; }
set
{
- _pwEntry.Expires = value;
- NotifyPropertyChanged("HasExpirationDate");
+ _mediator.Send(new SetFieldValueCommand {EntryId = Id, FieldName = nameof(HasExpirationDate), FieldValue = value});
+ OnPropertyChanged();
}
}
@@ -165,7 +159,7 @@ namespace ModernKeePass.ViewModels
get
{
var history = new Stack();
- foreach (var historyEntry in _pwEntry.History)
+ foreach (var historyEntry in _entry.History)
{
history.Push(new EntryVm(historyEntry, ParentGroup) {IsSelected = false});
}
@@ -178,89 +172,68 @@ namespace ModernKeePass.ViewModels
public Color? BackgroundColor
{
- get { return _pwEntry?.BackgroundColor; }
+ get { return _entry?.BackgroundColor; }
set
{
- if (value != null) _pwEntry.BackgroundColor = (Color) value;
+ if (value != null) _entry.BackgroundColor = (Color) value;
}
}
public Color? ForegroundColor
{
- get { return _pwEntry?.ForegroundColor; }
+ get { return _entry?.ForegroundColor; }
set
{
- if (value != null) _pwEntry.ForegroundColor = (Color)value;
+ if (value != null) _entry.ForegroundColor = (Color)value;
}
}
public ICommand SaveCommand { get; }
public ICommand GeneratePasswordCommand { get; }
public ICommand UndoDeleteCommand { get; }
-
- public event PropertyChangedEventHandler PropertyChanged;
-
- private readonly PwEntry _pwEntry;
- private readonly IDatabaseService _database;
- private readonly IResourceService _resource;
+
+ private readonly Application.Entry.Models.EntryVm _entry;
+ private readonly IMediator _mediator;
private bool _isEditMode;
- private bool _isDirty = true;
private bool _isRevealPassword;
private double _passwordLength = 25;
private bool _isVisible = true;
-
- private void NotifyPropertyChanged(string propertyName)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
-
+
public EntryVm() { }
- internal EntryVm(PwEntry entry, GroupVm parent) : this(entry, parent, DatabaseService.Instance, new ResourcesService()) { }
+ internal EntryVm(Application.Entry.Models.EntryVm entry, GroupVm parent) : this(entry, parent, App.Mediator) { }
- public EntryVm(PwEntry entry, GroupVm parent, IDatabaseService database, IResourceService resource)
+ public EntryVm(Application.Entry.Models.EntryVm entry, GroupVm parent, IMediator mediator)
{
- _database = database;
- _resource = resource;
- _pwEntry = entry;
+ _entry = entry;
+ _mediator = mediator;
ParentGroup = parent;
- SaveCommand = new RelayCommand(() => _database.Save());
- GeneratePasswordCommand = new RelayCommand(GeneratePassword);
+ SaveCommand = new RelayCommand(() => _mediator.Send(new SaveDatabaseCommand()));
+ GeneratePasswordCommand = new RelayCommand(async () => await GeneratePassword());
UndoDeleteCommand = new RelayCommand(() => Move(PreviousGroup), () => PreviousGroup != null);
}
- public void GeneratePassword()
+ public async Task GeneratePassword()
{
- var pwProfile = new PwProfile
+ Password = await _mediator.Send(new GeneratePasswordCommand
{
- GeneratorType = PasswordGeneratorType.CharSet,
- Length = (uint)PasswordLength,
- CharSet = new PwCharSet()
- };
-
- if (UpperCasePatternSelected) pwProfile.CharSet.Add(PwCharSet.UpperCase);
- if (LowerCasePatternSelected) pwProfile.CharSet.Add(PwCharSet.LowerCase);
- if (DigitsPatternSelected) pwProfile.CharSet.Add(PwCharSet.Digits);
- if (SpecialPatternSelected) pwProfile.CharSet.Add(PwCharSet.Special);
- if (MinusPatternSelected) pwProfile.CharSet.Add('-');
- if (UnderscorePatternSelected) pwProfile.CharSet.Add('_');
- if (SpacePatternSelected) pwProfile.CharSet.Add(' ');
- if (BracketsPatternSelected) pwProfile.CharSet.Add(PwCharSet.Brackets);
-
- pwProfile.CharSet.Add(CustomChars);
-
- ProtectedString password;
- PwGenerator.Generate(out password, pwProfile, null, new CustomPwGeneratorPool());
-
- SetEntryValue(PwDefs.PasswordField, password);
- NotifyPropertyChanged("Password");
- NotifyPropertyChanged("IsRevealPasswordEnabled");
- NotifyPropertyChanged("PasswordComplexityIndicator");
+ BracketsPatternSelected = BracketsPatternSelected,
+ CustomChars = CustomChars,
+ DigitsPatternSelected = DigitsPatternSelected,
+ LowerCasePatternSelected = LowerCasePatternSelected,
+ MinusPatternSelected = MinusPatternSelected,
+ PasswordLength = (int)PasswordLength,
+ SpacePatternSelected = SpacePatternSelected,
+ SpecialPatternSelected = SpecialPatternSelected,
+ UnderscorePatternSelected = UnderscorePatternSelected,
+ UpperCasePatternSelected = UpperCasePatternSelected
+ });
+ OnPropertyChanged(nameof(IsRevealPasswordEnabled));
}
- public void MarkForDelete(string recycleBinTitle)
+ public Task MarkForDelete(string recycleBinTitle)
{
if (_database.RecycleBinEnabled && _database.RecycleBin?.IdUuid == null)
_database.CreateRecycleBin(recycleBinTitle);
@@ -280,43 +253,21 @@ namespace ModernKeePass.ViewModels
ParentGroup.Entries.Add(this);
}
- public void CommitDelete()
+ public async Task CommitDelete()
{
- _pwEntry.ParentGroup.Entries.Remove(_pwEntry);
- if (!_database.RecycleBinEnabled || PreviousGroup.IsSelected) _database.AddDeletedItem(IdUuid);
+ await _mediator.Send(new DeleteEntryCommand {Entry = _entry});
}
- public PwEntry GetPwEntry()
+ public Application.Entry.Models.EntryVm GetEntry()
{
- return _pwEntry;
- }
- public void Reset()
- {
- _isDirty = false;
+ return _entry;
}
public override string ToString()
{
- return IsSelected ? _resource.GetResourceValue("EntryCurrent") : _pwEntry.LastModificationTime.ToString("g");
- }
-
- private void HandleBackup()
- {
- if (_isDirty) return;
- _pwEntry?.Touch(true);
- _pwEntry?.CreateBackup(null);
- _isDirty = true;
- }
-
- private string GetEntryValue(string key)
- {
- return _pwEntry?.Strings.GetSafe(key).ReadString();
- }
-
- private void SetEntryValue(string key, ProtectedString newValue)
- {
- HandleBackup();
- _pwEntry?.Strings.Set(key, newValue);
+ return IsSelected ?
+ _mediator.Send(new GetResourceQuery{Key = "EntryCurrent"}).GetAwaiter().GetResult() :
+ _entry.ModificationDate.ToString("g");
}
}
}
diff --git a/ModernKeePass/ViewModels/GroupVm.cs b/ModernKeePass/ViewModels/GroupVm.cs
index 264ef85..35bafcb 100644
--- a/ModernKeePass/ViewModels/GroupVm.cs
+++ b/ModernKeePass/ViewModels/GroupVm.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
@@ -8,10 +7,17 @@ using System.Windows.Input;
using MediatR;
using ModernKeePass.Application.Database.Commands.SaveDatabase;
using ModernKeePass.Application.Database.Queries.GetDatabase;
+using ModernKeePass.Application.Group.Commands.AddEntry;
+using ModernKeePass.Application.Group.Commands.CreateEntry;
+using ModernKeePass.Application.Group.Commands.CreateGroup;
+using ModernKeePass.Application.Group.Commands.DeleteGroup;
+using ModernKeePass.Application.Group.Commands.InsertEntry;
+using ModernKeePass.Application.Group.Commands.RemoveEntry;
+using ModernKeePass.Application.Group.Commands.SortEntries;
+using ModernKeePass.Application.Group.Commands.SortGroups;
using ModernKeePass.Common;
using ModernKeePass.Domain.Enums;
using ModernKeePass.Interfaces;
-using ModernKeePassLib;
namespace ModernKeePass.ViewModels
{
@@ -63,17 +69,17 @@ namespace ModernKeePass.ViewModels
}
public IOrderedEnumerable> EntriesZoomedOut => from e in Entries
- group e by e.Name.ToUpper().FirstOrDefault() into grp
+ group e by e.Title.ToUpper().FirstOrDefault() into grp
orderby grp.Key
select grp;
- public string Name
+ public string Title
{
get { return _group == null ? string.Empty : _group.Title; }
set { _group.Title = value; }
}
- public int IconId
+ public int Icon
{
get
{
@@ -152,38 +158,44 @@ namespace ModernKeePass.ViewModels
Groups = new ObservableCollection(group.SubGroups.Select(g => new GroupVm(g, this, recycleBinId)));
}
- private void Entries_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private async void Entries_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
- var oldIndex = (uint) e.OldStartingIndex;
- _reorderedEntry = _group.Entries.GetAt(oldIndex);
- _group.Entries.RemoveAt(oldIndex);
+ var oldIndex = e.OldStartingIndex;
+ _reorderedEntry = _group.Entries[oldIndex];
+ await _mediator.Send(new RemoveEntryCommand {Entry = _reorderedEntry, ParentGroup = _group});
break;
case NotifyCollectionChangedAction.Add:
- if (_reorderedEntry == null) _group.AddEntry(((EntryVm) e.NewItems[0]).GetPwEntry(), true);
- else _group.Entries.Insert((uint)e.NewStartingIndex, _reorderedEntry);
+ if (_reorderedEntry == null)
+ {
+ var entry = ((EntryVm) e.NewItems[0]).GetEntry();
+ await _mediator.Send(new AddEntryCommand {Entry = entry, ParentGroup = _group});
+ }
+ else
+ {
+ await _mediator.Send(new InsertEntryCommand {Entry = _reorderedEntry, ParentGroup = _group, Index = e.NewStartingIndex});
+ }
break;
}
}
- public GroupVm AddNewGroup(string name = "")
+ public async Task AddNewGroup(string name = "")
{
- var pwGroup = new PwGroup(true, true, name, PwIcon.Folder);
- _group.AddGroup(pwGroup, true);
- var newGroup = new GroupVm(pwGroup, this) {Name = name, IsEditMode = string.IsNullOrEmpty(name)};
- Groups.Add(newGroup);
- return newGroup;
+ var newGroup = await _mediator.Send(new CreateGroupCommand {Name = name, ParentGroup = _group});
+ var newGroupVm = new GroupVm(newGroup, this) {Title = name, IsEditMode = string.IsNullOrEmpty(name)};
+ Groups.Add(newGroupVm);
+ return newGroupVm;
}
- public EntryVm AddNewEntry()
+ public async Task AddNewEntry()
{
- var pwEntry = new PwEntry(true, true);
- var newEntry = new EntryVm(pwEntry, this) {IsEditMode = true};
- newEntry.GeneratePassword();
- Entries.Add(newEntry);
- return newEntry;
+ var newEntry = await _mediator.Send(new CreateEntryCommand { ParentGroup = _group });
+ var newEntryVm = new EntryVm(newEntry, this) {IsEditMode = true};
+ await newEntryVm.GeneratePassword();
+ Entries.Add(newEntryVm);
+ return newEntryVm;
}
public async Task MarkForDelete(string recycleBinTitle)
@@ -217,42 +229,26 @@ namespace ModernKeePass.ViewModels
public async Task CommitDelete()
{
- _group.ParentGroup.Groups.Remove(_group);
- if (await IsRecycleBinEnabled() && !PreviousGroup.IsSelected) _database.RecycleBin._group.AddGroup(_group, true);
- else _database.AddDeletedItem(IdUuid);
+ await _mediator.Send(new DeleteGroupCommand { Group = _group });
}
public override string ToString()
{
- return Name;
+ return Title;
}
private async Task SortEntriesAsync()
{
- var comparer = new PwEntryComparer(PwDefs.TitleField, true, false);
- try
- {
- _group.Entries.Sort(comparer);
- Entries = new ObservableCollection(Entries.OrderBy(e => e.Name));
- }
- catch (Exception e)
- {
- await MessageDialogHelper.ShowErrorDialog(e);
- }
+ await _mediator.Send(new SortEntriesCommand {Group = _group});
+ Entries = new ObservableCollection(Entries.OrderBy(e => e.Title));
}
private async Task SortGroupsAsync()
{
- try
- {
- _group.SortSubGroups(false);
- Groups = new ObservableCollection(Groups.OrderBy(g => g.Name).ThenBy(g => g._group == null));
- OnPropertyChanged("Groups");
- }
- catch (Exception e)
- {
- await MessageDialogHelper.ShowErrorDialog(e);
- }
+ await _mediator.Send(new SortGroupsCommand {Group = _group});
+ Groups = new ObservableCollection(Groups.OrderBy(g => g.Title).ThenBy(g => g._group == null));
+ // TODO: should not be needed
+ OnPropertyChanged(nameof(Groups));
}
private async Task IsRecycleBinEnabled()
diff --git a/ModernKeePass/ViewModels/NewVm.cs b/ModernKeePass/ViewModels/NewVm.cs
index 01ff1d5..9d92a4d 100644
--- a/ModernKeePass/ViewModels/NewVm.cs
+++ b/ModernKeePass/ViewModels/NewVm.cs
@@ -41,23 +41,23 @@ namespace ModernKeePass.ViewModels
var converter = new IntToSymbolConverter();
var bankingGroup = group.AddNewGroup("Banking");
- bankingGroup.IconId = (int)converter.ConvertBack(Symbol.Calculator, null, null, string.Empty);
+ bankingGroup.Icon = (int)converter.ConvertBack(Symbol.Calculator, null, null, string.Empty);
var emailGroup = group.AddNewGroup("Email");
- emailGroup.IconId = (int)converter.ConvertBack(Symbol.Mail, null, null, string.Empty);
+ emailGroup.Icon = (int)converter.ConvertBack(Symbol.Mail, null, null, string.Empty);
var internetGroup = group.AddNewGroup("Internet");
- internetGroup.IconId = (int)converter.ConvertBack(Symbol.World, null, null, string.Empty);
+ internetGroup.Icon = (int)converter.ConvertBack(Symbol.World, null, null, string.Empty);
var sample1 = group.AddNewEntry();
- sample1.Name = "Sample Entry";
+ sample1.Title = "Sample Entry";
sample1.UserName = "Username";
sample1.Url = PwDefs.HomepageUrl;
sample1.Password = "Password";
sample1.Notes = "You may safely delete this sample";
var sample2 = group.AddNewEntry();
- sample2.Name = "Sample Entry #2";
+ sample2.Title = "Sample Entry #2";
sample2.UserName = "Michael321";
sample2.Url = PwDefs.HelpUrl + "kb/testform.html";
sample2.Password = "12345";
diff --git a/ModernKeePass/Views/EntryDetailPage.xaml b/ModernKeePass/Views/EntryDetailPage.xaml
index 50cfe11..cbbed2a 100644
--- a/ModernKeePass/Views/EntryDetailPage.xaml
+++ b/ModernKeePass/Views/EntryDetailPage.xaml
@@ -415,7 +415,7 @@
-
+
@@ -425,7 +425,7 @@
-
+
@@ -498,13 +498,13 @@
-
+
-
+
-
+
diff --git a/ModernKeePass/Views/EntryDetailPage.xaml.cs b/ModernKeePass/Views/EntryDetailPage.xaml.cs
index 65abfff..e3e85c5 100644
--- a/ModernKeePass/Views/EntryDetailPage.xaml.cs
+++ b/ModernKeePass/Views/EntryDetailPage.xaml.cs
@@ -49,7 +49,6 @@ namespace ModernKeePass.Views
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
NavigationHelper.OnNavigatedFrom(e);
- Model.Reset();
}
#endregion
diff --git a/ModernKeePass/Views/GroupDetailPage.xaml b/ModernKeePass/Views/GroupDetailPage.xaml
index 68266bb..ce6f446 100644
--- a/ModernKeePass/Views/GroupDetailPage.xaml
+++ b/ModernKeePass/Views/GroupDetailPage.xaml
@@ -105,11 +105,11 @@
-
+
-
+
@@ -122,7 +122,7 @@
-
+
@@ -130,7 +130,7 @@
-
+
@@ -138,7 +138,7 @@
-
+
@@ -159,7 +159,7 @@
-
+
@@ -207,14 +207,14 @@
-
+
-
+
-
+
diff --git a/ModernKeePass/Views/GroupDetailPage.xaml.cs b/ModernKeePass/Views/GroupDetailPage.xaml.cs
index cd8d3a2..f10e2d3 100644
--- a/ModernKeePass/Views/GroupDetailPage.xaml.cs
+++ b/ModernKeePass/Views/GroupDetailPage.xaml.cs
@@ -122,10 +122,10 @@ namespace ModernKeePass.Views
private void SearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args)
{
var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appdata://Assets/ModernKeePass-SmallLogo.scale-80.png"));
- var results = Model.SubEntries.Where(e => e.Name.IndexOf(args.QueryText, StringComparison.OrdinalIgnoreCase) >= 0).Take(5);
+ var results = Model.SubEntries.Where(e => e.Title.IndexOf(args.QueryText, StringComparison.OrdinalIgnoreCase) >= 0).Take(5);
foreach (var result in results)
{
- args.Request.SearchSuggestionCollection.AppendResultSuggestion(result.Name, result.ParentGroup.Name, result.Id, imageUri, string.Empty);
+ args.Request.SearchSuggestionCollection.AppendResultSuggestion(result.Title, result.ParentGroup.Title, result.Id, imageUri, string.Empty);
}
}
diff --git a/ModernKeePassApp.Test/ViewModelsTests.cs b/ModernKeePassApp.Test/ViewModelsTests.cs
index d01d31d..ce5635a 100644
--- a/ModernKeePassApp.Test/ViewModelsTests.cs
+++ b/ModernKeePassApp.Test/ViewModelsTests.cs
@@ -118,7 +118,7 @@ namespace ModernKeePassApp.Test
var database = new DatabaseServiceMock();
var entryVm = new EntryVm(new PwEntry(true, true), new GroupVm(), database, _resource)
{
- Name = "Test",
+ Title = "Test",
UserName = "login",
Password = "password"
};
@@ -130,7 +130,7 @@ namespace ModernKeePassApp.Test
var database = new DatabaseServiceMock();
var entryVm = new GroupVm(new PwGroup(true, true), new GroupVm(), database)
{
- Name = "Test"
+ Title = "Test"
};
}
}