diff --git a/ModernKeePass.Application/Application.csproj b/ModernKeePass.Application/Application.csproj
index fa6c468..5343467 100644
--- a/ModernKeePass.Application/Application.csproj
+++ b/ModernKeePass.Application/Application.csproj
@@ -94,6 +94,7 @@
+
diff --git a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
index 7683686..b3fd6e0 100644
--- a/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
+++ b/ModernKeePass.Application/Common/Interfaces/IDatabaseProxy.cs
@@ -33,7 +33,7 @@ namespace ModernKeePass.Application.Common.Interfaces
EntryEntity GetEntry(string id);
Task AddEntry(string parentGroupId, string entryId);
Task MoveEntry(string parentGroupId, string entryId, int index);
- void UpdateEntry(string entryId, string fieldName, object fieldValue);
+ void UpdateEntry(string entryId, string fieldName, object fieldValue, bool isProtected);
void DeleteField(string entryId, string fieldName);
Task RemoveEntry(string parentGroupId, string entryId);
EntryEntity CreateEntry(string parentGroupId);
diff --git a/ModernKeePass.Application/Common/Interfaces/IEntityVm.cs b/ModernKeePass.Application/Common/Interfaces/IEntityVm.cs
index c6b12e0..b1a2293 100644
--- a/ModernKeePass.Application/Common/Interfaces/IEntityVm.cs
+++ b/ModernKeePass.Application/Common/Interfaces/IEntityVm.cs
@@ -5,7 +5,6 @@ namespace ModernKeePass.Application.Common.Interfaces
public interface IEntityVm
{
string Id { get; set; }
- string Title { get; set; }
Icon Icon { get; set; }
string ParentGroupId { get; set; }
string ParentGroupName { get; set; }
diff --git a/ModernKeePass.Application/Database/Commands/CreateDatabase/CreateDatabaseCommand.cs b/ModernKeePass.Application/Database/Commands/CreateDatabase/CreateDatabaseCommand.cs
index 7888154..c8cd341 100644
--- a/ModernKeePass.Application/Database/Commands/CreateDatabase/CreateDatabaseCommand.cs
+++ b/ModernKeePass.Application/Database/Commands/CreateDatabase/CreateDatabaseCommand.cs
@@ -64,17 +64,17 @@ namespace ModernKeePass.Application.Database.Commands.CreateDatabase
_database.UpdateGroup(internetGroup);
var sample1 = _database.CreateEntry(_database.RootGroupId);
- _database.UpdateEntry(sample1.Id, EntryFieldName.Title, "Sample Entry" );
- _database.UpdateEntry(sample1.Id, EntryFieldName.UserName, "Username" );
- _database.UpdateEntry(sample1.Id, EntryFieldName.Password, "Password" );
- _database.UpdateEntry(sample1.Id, EntryFieldName.Url, "https://keepass.info/" );
- _database.UpdateEntry(sample1.Id, EntryFieldName.Notes, "You may safely delete this sample" );
+ _database.UpdateEntry(sample1.Id, EntryFieldName.Title, "Sample Entry", true);
+ _database.UpdateEntry(sample1.Id, EntryFieldName.UserName, "Username", true);
+ _database.UpdateEntry(sample1.Id, EntryFieldName.Password, "Password", true);
+ _database.UpdateEntry(sample1.Id, EntryFieldName.Url, "https://keepass.info/", true);
+ _database.UpdateEntry(sample1.Id, EntryFieldName.Notes, "You may safely delete this sample", true);
var sample2 = _database.CreateEntry(_database.RootGroupId);
- _database.UpdateEntry(sample2.Id, EntryFieldName.Title, "Sample Entry #2" );
- _database.UpdateEntry(sample2.Id, EntryFieldName.UserName, "Michael321" );
- _database.UpdateEntry(sample2.Id, EntryFieldName.Password, "12345" );
- _database.UpdateEntry(sample2.Id, EntryFieldName.Url, "https://keepass.info/help/kb/testform.html" );
+ _database.UpdateEntry(sample2.Id, EntryFieldName.Title, "Sample Entry #2", true);
+ _database.UpdateEntry(sample2.Id, EntryFieldName.UserName, "Michael321", true);
+ _database.UpdateEntry(sample2.Id, EntryFieldName.Password, "12345", true);
+ _database.UpdateEntry(sample2.Id, EntryFieldName.Url, "https://keepass.info/help/kb/testform.html", true);
}
}
}
diff --git a/ModernKeePass.Application/Entry/Commands/UpsertField/UpsertFieldCommand.cs b/ModernKeePass.Application/Entry/Commands/UpsertField/UpsertFieldCommand.cs
index 50bb55a..5fcbb0b 100644
--- a/ModernKeePass.Application/Entry/Commands/UpsertField/UpsertFieldCommand.cs
+++ b/ModernKeePass.Application/Entry/Commands/UpsertField/UpsertFieldCommand.cs
@@ -9,6 +9,7 @@ namespace ModernKeePass.Application.Entry.Commands.UpsertField
public string EntryId { get; set; }
public string FieldName { get; set; }
public object FieldValue { get; set; }
+ public bool IsProtected { get; set; } = true;
public class UpsertFieldCommandHandler : IRequestHandler
{
@@ -23,7 +24,7 @@ namespace ModernKeePass.Application.Entry.Commands.UpsertField
{
if (!_database.IsOpen) throw new DatabaseClosedException();
- _database.UpdateEntry(message.EntryId, message.FieldName, message.FieldValue);
+ _database.UpdateEntry(message.EntryId, message.FieldName, message.FieldValue, message.IsProtected);
}
}
}
diff --git a/ModernKeePass.Application/Entry/Models/EntryVm.cs b/ModernKeePass.Application/Entry/Models/EntryVm.cs
index d327f88..281ad3d 100644
--- a/ModernKeePass.Application/Entry/Models/EntryVm.cs
+++ b/ModernKeePass.Application/Entry/Models/EntryVm.cs
@@ -15,13 +15,13 @@ namespace ModernKeePass.Application.Entry.Models
public string ParentGroupId { get; set; }
public string ParentGroupName { get; set; }
public string Id { get; set; }
- public string Title { get; set; }
- public string Username { get; set; }
- public string Password { get; set; }
- public string Notes { get; set; }
- public string Url { get; set; }
- public bool HasUrl => !string.IsNullOrEmpty(Url);
- public Dictionary AdditionalFields { get; set; }
+ public FieldVm Title { get; set; }
+ public FieldVm Username { get; set; }
+ public FieldVm Password { get; set; }
+ public FieldVm Notes { get; set; }
+ public FieldVm Url { get; set; }
+ public bool HasUrl => !string.IsNullOrEmpty(Url.Value);
+ public List AdditionalFields { get; set; }
public List History { get; set; }
public Icon Icon { get; set; }
public Color ForegroundColor { get; set; }
@@ -42,12 +42,18 @@ namespace ModernKeePass.Application.Entry.Models
.ForMember(d => d.ParentGroupId, opts => opts.MapFrom(s => s.ParentId))
.ForMember(d => d.ParentGroupName, opts => opts.MapFrom(s => s.ParentName))
.ForMember(d => d.Id, opts => opts.MapFrom(s => s.Id))
- .ForMember(d => d.Title, opts => opts.MapFrom(s => s.Name))
- .ForMember(d => d.Username, opts => opts.MapFrom(s => s.UserName))
- .ForMember(d => d.Password, opts => opts.MapFrom(s => s.Password))
- .ForMember(d => d.Url, opts => opts.MapFrom(s => s.Url))
- .ForMember(d => d.Notes, opts => opts.MapFrom(s => s.Notes))
- .ForMember(d => d.AdditionalFields, opts => opts.MapFrom(s => s.AdditionalFields))
+ .ForMember(d => d.Title, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f =>
+ f.Name.Equals(EntryFieldName.Title, StringComparison.OrdinalIgnoreCase)) ?? new FieldEntity { Name = EntryFieldName.Title, IsProtected = true } ))
+ .ForMember(d => d.Username, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f =>
+ f.Name.Equals(EntryFieldName.UserName, StringComparison.OrdinalIgnoreCase)) ?? new FieldEntity { Name = EntryFieldName.UserName, IsProtected = true } ))
+ .ForMember(d => d.Password, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f =>
+ f.Name.Equals(EntryFieldName.Password, StringComparison.OrdinalIgnoreCase)) ?? new FieldEntity { Name = EntryFieldName.Password, IsProtected = true } ))
+ .ForMember(d => d.Url, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f =>
+ f.Name.Equals(EntryFieldName.Url, StringComparison.OrdinalIgnoreCase)) ?? new FieldEntity { Name = EntryFieldName.Url, IsProtected = true } ))
+ .ForMember(d => d.Notes, opts => opts.MapFrom(s => s.Fields.FirstOrDefault(f =>
+ f.Name.Equals(EntryFieldName.Notes, StringComparison.OrdinalIgnoreCase)) ?? new FieldEntity { Name = EntryFieldName.Notes, IsProtected = true } ))
+ .ForMember(d => d.AdditionalFields, opts => opts.MapFrom(s =>
+ s.Fields.Where(f => !EntryFieldName.StandardFieldNames.Contains(f.Name, StringComparer.OrdinalIgnoreCase))))
.ForMember(d => d.History, opts => opts.MapFrom(s => s.History.Reverse()))
.ForMember(d => d.HasExpirationDate, opts => opts.MapFrom(s => s.HasExpirationDate))
.ForMember(d => d.ExpirationDate, opts => opts.MapFrom(s => s.ExpirationDate))
diff --git a/ModernKeePass.Application/Entry/Models/FieldVm.cs b/ModernKeePass.Application/Entry/Models/FieldVm.cs
new file mode 100644
index 0000000..3336051
--- /dev/null
+++ b/ModernKeePass.Application/Entry/Models/FieldVm.cs
@@ -0,0 +1,20 @@
+using AutoMapper;
+using ModernKeePass.Application.Common.Mappings;
+using ModernKeePass.Domain.Entities;
+
+namespace ModernKeePass.Application.Entry.Models
+{
+ public class FieldVm: IMapFrom
+ {
+ public string Name { get; set; }
+ public string Value { get; set; }
+ public bool IsProtected { get; set; }
+
+ public override string ToString() => Value;
+
+ public void Mapping(Profile profile)
+ {
+ profile.CreateMap();
+ }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePass.Application/Group/Commands/SortEntries/SortEntriesCommand.cs b/ModernKeePass.Application/Group/Commands/SortEntries/SortEntriesCommand.cs
index d161379..5d17924 100644
--- a/ModernKeePass.Application/Group/Commands/SortEntries/SortEntriesCommand.cs
+++ b/ModernKeePass.Application/Group/Commands/SortEntries/SortEntriesCommand.cs
@@ -24,7 +24,7 @@ namespace ModernKeePass.Application.Group.Commands.SortEntries
if (!_database.IsOpen) throw new DatabaseClosedException();
_database.SortEntries(message.Group.Id);
- message.Group.Entries = message.Group.Entries.OrderBy(e => e.Title).ToList();
+ message.Group.Entries = message.Group.Entries.OrderBy(e => e.Title.Value).ToList();
}
}
}
diff --git a/ModernKeePass.Domain/Domain.csproj b/ModernKeePass.Domain/Domain.csproj
index 1530133..7d5fce7 100644
--- a/ModernKeePass.Domain/Domain.csproj
+++ b/ModernKeePass.Domain/Domain.csproj
@@ -82,6 +82,7 @@
+
diff --git a/ModernKeePass.Domain/Entities/EntryEntity.cs b/ModernKeePass.Domain/Entities/EntryEntity.cs
index 088574c..d47b152 100644
--- a/ModernKeePass.Domain/Entities/EntryEntity.cs
+++ b/ModernKeePass.Domain/Entities/EntryEntity.cs
@@ -7,17 +7,13 @@ namespace ModernKeePass.Domain.Entities
{
public class EntryEntity: BaseEntity
{
- public string UserName { get; set; }
- public string Password { get; set; }
- public string Url { get; set; }
- public string Notes { get; set; }
- public DateTimeOffset ExpirationDate { get; set; }
- public Dictionary AdditionalFields { get; set; } = new Dictionary();
+ public IEnumerable Fields { get; set; } = new List();
public IEnumerable History { get; set; } = new List();
+ public Dictionary Attachments { get; set; } = new Dictionary();
+ public DateTimeOffset ExpirationDate { get; set; }
public Icon Icon { get; set; }
public Color ForegroundColor { get; set; }
public Color BackgroundColor { get; set; }
public bool HasExpirationDate { get; set; }
- public Dictionary Attachments { get; set; } = new Dictionary();
}
}
\ No newline at end of file
diff --git a/ModernKeePass.Domain/Entities/FieldEntity.cs b/ModernKeePass.Domain/Entities/FieldEntity.cs
new file mode 100644
index 0000000..3cd972b
--- /dev/null
+++ b/ModernKeePass.Domain/Entities/FieldEntity.cs
@@ -0,0 +1,9 @@
+namespace ModernKeePass.Domain.Entities
+{
+ public class FieldEntity
+ {
+ public string Name { get; set; }
+ public string Value { get; set; }
+ public bool IsProtected { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/ModernKeePass.Domain/Enums/EntryFieldName.cs b/ModernKeePass.Domain/Enums/EntryFieldName.cs
index e94a425..0c9ed66 100644
--- a/ModernKeePass.Domain/Enums/EntryFieldName.cs
+++ b/ModernKeePass.Domain/Enums/EntryFieldName.cs
@@ -1,4 +1,6 @@
-namespace ModernKeePass.Domain.Enums
+using System.Collections.Generic;
+
+namespace ModernKeePass.Domain.Enums
{
public static class EntryFieldName
{
@@ -12,5 +14,19 @@
public const string HasExpirationDate = nameof(HasExpirationDate);
public const string BackgroundColor = nameof(BackgroundColor);
public const string ForegroundColor = nameof(ForegroundColor);
+
+ public static IEnumerable StandardFieldNames = new[]
+ {
+ Title,
+ UserName,
+ Password,
+ Url,
+ Notes,
+ Icon,
+ ExpirationDate,
+ HasExpirationDate,
+ BackgroundColor,
+ ForegroundColor
+ };
}
}
\ No newline at end of file
diff --git a/ModernKeePass.Infrastructure/Infrastructure.csproj b/ModernKeePass.Infrastructure/Infrastructure.csproj
index bcf0d3d..7e4acc0 100644
--- a/ModernKeePass.Infrastructure/Infrastructure.csproj
+++ b/ModernKeePass.Infrastructure/Infrastructure.csproj
@@ -80,8 +80,7 @@
-
-
+
diff --git a/ModernKeePass.Infrastructure/KeePass/GroupMappingProfile.cs b/ModernKeePass.Infrastructure/KeePass/GroupMappingProfile.cs
deleted file mode 100644
index 973f4f0..0000000
--- a/ModernKeePass.Infrastructure/KeePass/GroupMappingProfile.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using AutoMapper;
-using ModernKeePass.Domain.Entities;
-using ModernKeePassLib;
-
-namespace ModernKeePass.Infrastructure.KeePass
-{
- public class GroupMappingProfile : Profile
- {
- public GroupMappingProfile()
- {
- CreateMap()
- .ForMember(d => d.ParentId, opts => opts.MapFrom(s => s.ParentGroup.Uuid.ToHexString()))
- .ForMember(d => d.ParentName, opts => opts.MapFrom(s => s.ParentGroup.Name))
- .ForMember(d => d.Id, opts => opts.MapFrom(s => s.Uuid.ToHexString()))
- .ForMember(d => d.Name, opts => opts.MapFrom(s => s.Name))
- .ForMember(d => d.Icon, opts => opts.MapFrom(s => IconMapper.MapPwIconToIcon(s.IconId)))
- .ForMember(d => d.LastModificationDate, opts => opts.MapFrom(s => s.LastModificationTime))
- .ForMember(d => d.Entries, opts => opts.MapFrom(s => s.Entries))
- .ForMember(d => d.SubGroups, opts => opts.MapFrom(s => s.Groups))
- .MaxDepth(2);
- }
- }
-}
\ No newline at end of file
diff --git a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
index c91e497..8398d70 100644
--- a/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
+++ b/ModernKeePass.Infrastructure/KeePass/KeePassDatabaseClient.cs
@@ -228,7 +228,7 @@ namespace ModernKeePass.Infrastructure.KeePass
_pwDatabase.DeletedObjects.Add(new PwDeletedObject(BuildIdFromString(entityId), _dateTime.Now));
}
- public void UpdateEntry(string entryId, string fieldName, object fieldValue)
+ public void UpdateEntry(string entryId, string fieldName, object fieldValue, bool isProtected)
{
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
@@ -239,7 +239,7 @@ namespace ModernKeePass.Infrastructure.KeePass
case EntryFieldName.Password:
case EntryFieldName.Notes:
case EntryFieldName.Url:
- pwEntry.Strings.Set(EntryFieldMapper.MapFieldToPwDef(fieldName), new ProtectedString(true, fieldValue.ToString()));
+ pwEntry.Strings.Set(EntryFieldMapper.MapFieldToPwDef(fieldName), new ProtectedString(isProtected, fieldValue.ToString()));
break;
case EntryFieldName.HasExpirationDate:
pwEntry.Expires = (bool)fieldValue;
@@ -257,7 +257,7 @@ namespace ModernKeePass.Infrastructure.KeePass
pwEntry.ForegroundColor = (Color)fieldValue;
break;
default:
- pwEntry.Strings.Set(fieldName, new ProtectedString(true, fieldValue.ToString()));
+ pwEntry.Strings.Set(fieldName, new ProtectedString(isProtected, fieldValue.ToString()));
break;
}
}
diff --git a/ModernKeePass.Infrastructure/KeePass/EntryMappingProfile.cs b/ModernKeePass.Infrastructure/KeePass/MappingProfiles.cs
similarity index 53%
rename from ModernKeePass.Infrastructure/KeePass/EntryMappingProfile.cs
rename to ModernKeePass.Infrastructure/KeePass/MappingProfiles.cs
index 5c99915..592d09c 100644
--- a/ModernKeePass.Infrastructure/KeePass/EntryMappingProfile.cs
+++ b/ModernKeePass.Infrastructure/KeePass/MappingProfiles.cs
@@ -4,34 +4,42 @@ using System.Linq;
using AutoMapper;
using ModernKeePass.Domain.Entities;
using ModernKeePassLib;
+using ModernKeePassLib.Security;
namespace ModernKeePass.Infrastructure.KeePass
{
- public class EntryMappingProfile: Profile
+ public class MappingProfiles: Profile
{
- public EntryMappingProfile()
+ public MappingProfiles()
{
+ CreateMap, FieldEntity>()
+ .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Key))
+ .ForMember(dest => dest.Value, opt => opt.MapFrom(src => src.Value.ReadString()))
+ .ForMember(dest => dest.IsProtected, opt => opt.MapFrom(src => src.Value.IsProtected));
+
CreateMap()
.ForMember(dest => dest.ParentId, opt => opt.MapFrom(src => src.ParentGroup.Uuid.ToHexString()))
.ForMember(dest => dest.ParentName, opt => opt.MapFrom(src => src.ParentGroup.Name))
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Uuid.ToHexString()))
- .ForMember(dest => dest.Name, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.TitleField)))
- .ForMember(dest => dest.UserName, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.UserNameField)))
- .ForMember(dest => dest.Password, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.PasswordField)))
- .ForMember(dest => dest.Url, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.UrlField)))
- .ForMember(dest => dest.Notes, opt => opt.MapFrom(src => GetEntryValue(src, PwDefs.NotesField)))
+ .ForMember(dest => dest.Fields, opt => opt.MapFrom(src => src.Strings))
.ForMember(dest => dest.ForegroundColor, opt => opt.MapFrom(src => src.ForegroundColor))
.ForMember(dest => dest.BackgroundColor, opt => opt.MapFrom(src => src.BackgroundColor))
.ForMember(dest => dest.ExpirationDate, opt => opt.MapFrom(src => new DateTimeOffset(src.ExpiryTime)))
.ForMember(dest => dest.HasExpirationDate, opt => opt.MapFrom(src => src.Expires))
.ForMember(dest => dest.Icon, opt => opt.MapFrom(src => IconMapper.MapPwIconToIcon(src.IconId)))
- .ForMember(dest => dest.AdditionalFields, opt => opt.MapFrom(src =>
- src.Strings.Where(s => !PwDefs.GetStandardFields().Contains(s.Key))
- .ToDictionary(s => s.Key, s => GetEntryValue(src, s.Key))))
.ForMember(dest => dest.LastModificationDate, opt => opt.MapFrom(src => new DateTimeOffset(src.LastModificationTime)))
.ForMember(dest => dest.Attachments, opt => opt.MapFrom(src => src.Binaries.Select(b => new KeyValuePair (b.Key, b.Value.ReadData()) )));
+
+ CreateMap()
+ .ForMember(d => d.ParentId, opts => opts.MapFrom(s => s.ParentGroup.Uuid.ToHexString()))
+ .ForMember(d => d.ParentName, opts => opts.MapFrom(s => s.ParentGroup.Name))
+ .ForMember(d => d.Id, opts => opts.MapFrom(s => s.Uuid.ToHexString()))
+ .ForMember(d => d.Name, opts => opts.MapFrom(s => s.Name))
+ .ForMember(d => d.Icon, opts => opts.MapFrom(s => IconMapper.MapPwIconToIcon(s.IconId)))
+ .ForMember(d => d.LastModificationDate, opts => opts.MapFrom(s => s.LastModificationTime))
+ .ForMember(d => d.Entries, opts => opts.MapFrom(s => s.Entries))
+ .ForMember(d => d.SubGroups, opts => opts.MapFrom(s => s.Groups))
+ .MaxDepth(2);
}
-
- private string GetEntryValue(PwEntry entry, string key) => entry.Strings.GetSafe(key).ReadString();
}
}
\ No newline at end of file
diff --git a/ModernKeePass.Infrastructure/project.json b/ModernKeePass.Infrastructure/project.json
index fdab3b7..52c35b1 100644
--- a/ModernKeePass.Infrastructure/project.json
+++ b/ModernKeePass.Infrastructure/project.json
@@ -3,7 +3,7 @@
"dependencies": {
"AutoMapper": "5.2.0",
"Microsoft.NETCore.Portable.Compatibility": "1.0.1",
- "ModernKeePassLib": "2.44.3",
+ "ModernKeePassLib": "2.45.1",
"NETStandard.Library": "2.0.3"
},
"frameworks": {
diff --git a/ModernKeePass/Strings/en-US/CodeBehind.resw b/ModernKeePass/Strings/en-US/CodeBehind.resw
index a533d92..3b04d80 100644
--- a/ModernKeePass/Strings/en-US/CodeBehind.resw
+++ b/ModernKeePass/Strings/en-US/CodeBehind.resw
@@ -276,4 +276,10 @@
Key
+
+ Database size is too big for auto-save on suspend. Please save your changes before closing the app !
+
+
+ Attention
+
\ No newline at end of file
diff --git a/ModernKeePass/Strings/en-US/Resources.resw b/ModernKeePass/Strings/en-US/Resources.resw
index e0ed937..715bc93 100644
--- a/ModernKeePass/Strings/en-US/Resources.resw
+++ b/ModernKeePass/Strings/en-US/Resources.resw
@@ -376,7 +376,7 @@
New group
- Navigation
+ Groups
History
@@ -546,4 +546,16 @@
Invalid field name
+
+ Enable protection ?
+
+
+ No
+
+
+ Yes
+
+
+ Restore
+
\ No newline at end of file
diff --git a/ModernKeePass/Strings/fr-FR/CodeBehind.resw b/ModernKeePass/Strings/fr-FR/CodeBehind.resw
index c8e960a..41e78b6 100644
--- a/ModernKeePass/Strings/fr-FR/CodeBehind.resw
+++ b/ModernKeePass/Strings/fr-FR/CodeBehind.resw
@@ -279,4 +279,10 @@
Ajouter un champ
+
+ La base de données est trop grosse pour sauvegarder automatiquement lors de la suspension. Pensez à bien sauvegarder vos changements avant de fermer l'app !
+
+
+ Attention
+
\ No newline at end of file
diff --git a/ModernKeePass/Strings/fr-FR/Resources.resw b/ModernKeePass/Strings/fr-FR/Resources.resw
index 74a1271..d38b04e 100644
--- a/ModernKeePass/Strings/fr-FR/Resources.resw
+++ b/ModernKeePass/Strings/fr-FR/Resources.resw
@@ -379,7 +379,7 @@
Nouveau groupe
- Navigation
+ Groupes
Historique
@@ -543,4 +543,16 @@
Nom de champ invalide
+
+ Activer la protection ?
+
+
+ Non
+
+
+ Oui
+
+
+ Restaurer
+
\ No newline at end of file
diff --git a/ModernKeePass/ViewModels/EntryDetailVm.cs b/ModernKeePass/ViewModels/EntryDetailVm.cs
index 1470c4c..18a320c 100644
--- a/ModernKeePass/ViewModels/EntryDetailVm.cs
+++ b/ModernKeePass/ViewModels/EntryDetailVm.cs
@@ -68,7 +68,7 @@ namespace ModernKeePass.ViewModels
}
public ObservableCollection History { get; private set; }
- public ObservableCollection AdditionalFields { get; private set; }
+ public ObservableCollection AdditionalFields { get; private set; }
public ObservableCollection Attachments { get; private set; }
///
@@ -85,8 +85,8 @@ namespace ModernKeePass.ViewModels
if (value != null)
{
AdditionalFields =
- new ObservableCollection(
- SelectedItem.AdditionalFields.Select(f => new FieldVm(f.Key, f.Value)));
+ new ObservableCollection(
+ SelectedItem.AdditionalFields.Select(f => new EntryFieldVm(f.Name, f.Value, f.IsProtected)));
Attachments = new ObservableCollection(SelectedItem.Attachments.Select(f => new Attachment
{
Name = f.Key,
@@ -131,32 +131,32 @@ namespace ModernKeePass.ViewModels
public string Title
{
- get { return SelectedItem.Title; }
+ get { return SelectedItem.Title.Value; }
set
{
- SelectedItem.Title = value;
- SetFieldValue(nameof(Title), value).Wait();
+ SelectedItem.Title.Value = value;
+ SetFieldValue(nameof(Title), value, true).Wait();
}
}
public string UserName
{
- get { return SelectedItem.Username; }
+ get { return SelectedItem.Username.Value; }
set
{
- SelectedItem.Username = value;
- SetFieldValue(nameof(UserName), value).Wait();
+ SelectedItem.Username.Value = value;
+ SetFieldValue(nameof(UserName), value, true).Wait();
RaisePropertyChanged(nameof(UserName));
}
}
public string Password
{
- get { return SelectedItem.Password; }
+ get { return SelectedItem.Password.Value; }
set
{
- SelectedItem.Password = value;
- SetFieldValue(nameof(Password), value).Wait();
+ SelectedItem.Password.Value = value;
+ SetFieldValue(nameof(Password), value, true).Wait();
RaisePropertyChanged(nameof(Password));
RaisePropertyChanged(nameof(PasswordComplexityIndicator));
}
@@ -164,22 +164,22 @@ namespace ModernKeePass.ViewModels
public string Url
{
- get { return SelectedItem.Url; }
+ get { return SelectedItem.Url.Value; }
set
{
- SelectedItem.Url = value;
- SetFieldValue(nameof(Url), value).Wait();
+ SelectedItem.Url.Value = value;
+ SetFieldValue(nameof(Url), value, true).Wait();
RaisePropertyChanged(nameof(Url));
}
}
public string Notes
{
- get { return SelectedItem.Notes; }
+ get { return SelectedItem.Notes.Value; }
set
{
- SelectedItem.Notes = value;
- SetFieldValue(nameof(Notes), value).Wait();
+ SelectedItem.Notes.Value = value;
+ SetFieldValue(nameof(Notes), value, true).Wait();
}
}
@@ -189,7 +189,7 @@ namespace ModernKeePass.ViewModels
set
{
SelectedItem.Icon = (Icon)Enum.Parse(typeof(Icon), value.ToString());
- SetFieldValue(nameof(Icon), SelectedItem.Icon).Wait();
+ SetFieldValue(nameof(Icon), SelectedItem.Icon, true).Wait();
}
}
@@ -201,7 +201,7 @@ namespace ModernKeePass.ViewModels
if (!HasExpirationDate) return;
SelectedItem.ExpirationDate = value.Date;
- SetFieldValue("ExpirationDate", SelectedItem.ExpirationDate).Wait();
+ SetFieldValue("ExpirationDate", SelectedItem.ExpirationDate, true).Wait();
}
}
@@ -213,7 +213,7 @@ namespace ModernKeePass.ViewModels
if (!HasExpirationDate) return;
SelectedItem.ExpirationDate = SelectedItem.ExpirationDate.Date.Add(value);
- SetFieldValue("ExpirationDate", SelectedItem.ExpirationDate).Wait();
+ SetFieldValue("ExpirationDate", SelectedItem.ExpirationDate, true).Wait();
}
}
@@ -223,7 +223,7 @@ namespace ModernKeePass.ViewModels
set
{
SelectedItem.HasExpirationDate = value;
- SetFieldValue(nameof(HasExpirationDate), value).Wait();
+ SetFieldValue(nameof(HasExpirationDate), value, true).Wait();
RaisePropertyChanged(nameof(HasExpirationDate));
}
}
@@ -234,7 +234,7 @@ namespace ModernKeePass.ViewModels
set
{
SelectedItem.BackgroundColor = value.ToColor();
- SetFieldValue(nameof(BackgroundColor), SelectedItem.BackgroundColor).Wait();
+ SetFieldValue(nameof(BackgroundColor), SelectedItem.BackgroundColor, true).Wait();
}
}
@@ -244,7 +244,7 @@ namespace ModernKeePass.ViewModels
set
{
SelectedItem.ForegroundColor = value.ToColor();
- SetFieldValue(nameof(ForegroundColor), SelectedItem.ForegroundColor).Wait();
+ SetFieldValue(nameof(ForegroundColor), SelectedItem.ForegroundColor, true).Wait();
}
}
@@ -269,7 +269,7 @@ namespace ModernKeePass.ViewModels
public RelayCommand GoBackCommand { get; }
public RelayCommand GoToParentCommand { get; set; }
public RelayCommand AddAdditionalField { get; set; }
- public RelayCommand DeleteAdditionalField { get; set; }
+ public RelayCommand DeleteAdditionalField { get; set; }
public RelayCommand OpenAttachmentCommand { get; set; }
public RelayCommand AddAttachmentCommand { get; set; }
public RelayCommand DeleteAttachmentCommand { get; set; }
@@ -308,14 +308,14 @@ namespace ModernKeePass.ViewModels
GoBackCommand = new RelayCommand(() => _navigation.GoBack());
GoToParentCommand = new RelayCommand(() => GoToGroup(_parent.Id));
AddAdditionalField = new RelayCommand(AddField, () => IsCurrentEntry);
- DeleteAdditionalField = new RelayCommand(async field => await DeleteField(field), field => field != null && IsCurrentEntry);
+ DeleteAdditionalField = new RelayCommand(async field => await DeleteField(field), field => field != null && IsCurrentEntry);
OpenAttachmentCommand = new RelayCommand(async attachment => await OpenAttachment(attachment));
AddAttachmentCommand = new RelayCommand(async () => await AddAttachment(), () => IsCurrentEntry);
DeleteAttachmentCommand = new RelayCommand(async attachment => await DeleteAttachment(attachment), _ => IsCurrentEntry);
MessengerInstance.Register(this, _ => SaveCommand.RaiseCanExecuteChanged());
- MessengerInstance.Register(this, async message => await SetFieldValue(message.FieldName, message.FieldValue));
- MessengerInstance.Register(this, async message => await UpdateFieldName(message.OldName, message.NewName, message.Value));
+ MessengerInstance.Register(this, async message => await SetFieldValue(message.FieldName, message.FieldValue, message.IsProtected));
+ MessengerInstance.Register(this, async message => await UpdateFieldName(message.OldName, message.NewName, message.Value, message.IsProtected));
}
public async Task Initialize(string entryId)
@@ -348,6 +348,7 @@ namespace ModernKeePass.ViewModels
});
RaisePropertyChanged(nameof(IsRevealPasswordEnabled));
}
+
public async Task AddHistory()
{
if (_isDirty) await _mediator.Send(new AddHistoryCommand { Entry = History[0] });
@@ -365,26 +366,26 @@ namespace ModernKeePass.ViewModels
GoToGroup(destination);
}
- private async Task SetFieldValue(string fieldName, object value)
+ private async Task SetFieldValue(string fieldName, object value, bool isProtected)
{
- await _mediator.Send(new UpsertFieldCommand { EntryId = Id, FieldName = fieldName, FieldValue = value });
+ await _mediator.Send(new UpsertFieldCommand { EntryId = Id, FieldName = fieldName, FieldValue = value, IsProtected = isProtected});
SaveCommand.RaiseCanExecuteChanged();
_isDirty = true;
}
- private async Task UpdateFieldName(string oldName, string newName, string value)
+ private async Task UpdateFieldName(string oldName, string newName, string value, bool isProtected)
{
if (!string.IsNullOrEmpty(oldName)) await _mediator.Send(new DeleteFieldCommand { EntryId = Id, FieldName = oldName });
- await SetFieldValue(newName, value);
+ await SetFieldValue(newName, value, isProtected);
}
private void AddField()
{
- AdditionalFields.Add(new FieldVm(string.Empty, string.Empty));
+ AdditionalFields.Add(new EntryFieldVm(string.Empty, string.Empty, false));
AdditionalFieldSelectedIndex = AdditionalFields.Count - 1;
}
- private async Task DeleteField(FieldVm field)
+ private async Task DeleteField(EntryFieldVm field)
{
AdditionalFields.Remove(field);
if (!string.IsNullOrEmpty(field.Name))
diff --git a/ModernKeePass/ViewModels/GroupDetailVm.cs b/ModernKeePass/ViewModels/GroupDetailVm.cs
index c57d3d3..e156a96 100644
--- a/ModernKeePass/ViewModels/GroupDetailVm.cs
+++ b/ModernKeePass/ViewModels/GroupDetailVm.cs
@@ -43,7 +43,7 @@ namespace ModernKeePass.ViewModels
public bool IsNotRoot => Database.RootGroupId != _group.Id;
public IOrderedEnumerable> EntriesZoomedOut => from e in Entries
- group e by e.Title.ToUpper().FirstOrDefault() into grp
+ group e by e.Title.Name.ToUpper().FirstOrDefault() into grp
orderby grp.Key
select grp;
diff --git a/ModernKeePass/Views/EntryDetailPage.xaml b/ModernKeePass/Views/EntryDetailPage.xaml
index cd1cf3f..29ef1d4 100644
--- a/ModernKeePass/Views/EntryDetailPage.xaml
+++ b/ModernKeePass/Views/EntryDetailPage.xaml
@@ -441,8 +441,8 @@
-
-
+
+
@@ -481,40 +481,51 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs b/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs
index 06f75c6..7136519 100644
--- a/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs
+++ b/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs
@@ -221,7 +221,7 @@ namespace ModernKeePass.Views.UserControls
var results = (await Model.Search(args.QueryText)).Take(5);
foreach (var result in results)
{
- args.Request.SearchSuggestionCollection.AppendResultSuggestion(result.Title, result.ParentGroupName, result.Id, imageUri, string.Empty);
+ args.Request.SearchSuggestionCollection.AppendResultSuggestion(result.Title.Value, result.ParentGroupName, result.Id, imageUri, string.Empty);
}
}
diff --git a/ModernKeePass/Win81App.csproj b/ModernKeePass/Win81App.csproj
index ba6de60..7056d04 100644
--- a/ModernKeePass/Win81App.csproj
+++ b/ModernKeePass/Win81App.csproj
@@ -372,8 +372,8 @@
..\packages\HockeySDK.WINRT.4.1.6\lib\portable-win81\Microsoft.HockeyApp.Kit.dll
True
-
- ..\packages\ModernKeePassLib.2.44.3\lib\netstandard1.2\ModernKeePassLib.dll
+
+ ..\packages\ModernKeePassLib.2.45.1\lib\netstandard1.2\ModernKeePassLib.dll
True
diff --git a/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt b/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt
index 37a923b..0171f7a 100644
--- a/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt
+++ b/ModernKeePass/appMetadata/en-us/baselisting/releaseNotes.txt
@@ -1,4 +1,5 @@
Support for additional fields
Support for attachments
Ability to manually reorder groups
-Design changes
\ No newline at end of file
+Design changes
+Update to KeePassLib version 2.45
\ No newline at end of file
diff --git a/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt b/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt
index ab65482..3123833 100644
--- a/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt
+++ b/ModernKeePass/appMetadata/fr-fr/baselisting/releaseNotes.txt
@@ -1,4 +1,5 @@
Ajout des champs additionnels
Ajout des pièces-jointes
Possibilite de reorganiser les groupes manuellement
-Quelques changements de design
\ No newline at end of file
+Quelques changements de design
+Mise a jour de la KeePassLib version 2.45
\ No newline at end of file
diff --git a/ModernKeePass/packages.config b/ModernKeePass/packages.config
index 82c56c4..d53ea22 100644
--- a/ModernKeePass/packages.config
+++ b/ModernKeePass/packages.config
@@ -14,7 +14,7 @@
-
+
diff --git a/WinAppCommon/Messages/EntryFieldNameChangedMessage.cs b/WinAppCommon/Messages/EntryFieldNameChangedMessage.cs
index 348dcf2..ca1c883 100644
--- a/WinAppCommon/Messages/EntryFieldNameChangedMessage.cs
+++ b/WinAppCommon/Messages/EntryFieldNameChangedMessage.cs
@@ -5,5 +5,6 @@
public string OldName { get; set; }
public string NewName { get; set; }
public string Value { get; set; }
+ public bool IsProtected { get; set; }
}
}
\ No newline at end of file
diff --git a/WinAppCommon/Messages/EntryFieldValueChangedMessage.cs b/WinAppCommon/Messages/EntryFieldValueChangedMessage.cs
index 841517f..bdd9b5c 100644
--- a/WinAppCommon/Messages/EntryFieldValueChangedMessage.cs
+++ b/WinAppCommon/Messages/EntryFieldValueChangedMessage.cs
@@ -4,5 +4,6 @@
{
public string FieldName { get; set; }
public string FieldValue { get; set; }
+ public bool IsProtected { get; set; }
}
}
\ No newline at end of file
diff --git a/WinAppCommon/ViewModels/Items/EntryFieldVm.cs b/WinAppCommon/ViewModels/Items/EntryFieldVm.cs
new file mode 100644
index 0000000..dbc0041
--- /dev/null
+++ b/WinAppCommon/ViewModels/Items/EntryFieldVm.cs
@@ -0,0 +1,51 @@
+using System.Linq;
+using GalaSoft.MvvmLight;
+using Messages;
+using ModernKeePass.Domain.Enums;
+
+namespace ModernKeePass.ViewModels.ListItems
+{
+ public class EntryFieldVm: ViewModelBase
+ {
+ private string _name;
+ private string _value;
+ private bool _isProtected;
+
+ public string Name
+ {
+ get { return _name; }
+ set
+ {
+ var newName = EntryFieldName.StandardFieldNames.Contains(value) ? $"{value}_1" : value;
+ MessengerInstance.Send(new EntryFieldNameChangedMessage { OldName = Name, NewName = newName, Value = Value, IsProtected = IsProtected});
+ Set(nameof(Name), ref _name, newName);
+ }
+ }
+
+ public string Value
+ {
+ get { return _value; }
+ set
+ {
+ MessengerInstance.Send(new EntryFieldValueChangedMessage { FieldName = Name, FieldValue = value, IsProtected = IsProtected });
+ Set(nameof(Value), ref _value, value);
+ }
+ }
+ public bool IsProtected
+ {
+ get { return _isProtected; }
+ set
+ {
+ MessengerInstance.Send(new EntryFieldValueChangedMessage { FieldName = Name, FieldValue = Value, IsProtected = value });
+ Set(nameof(IsProtected), ref _isProtected, value);
+ }
+ }
+
+ public EntryFieldVm(string fieldName, string fieldValue, bool isProtected)
+ {
+ _name = fieldName;
+ _value = fieldValue;
+ _isProtected = isProtected;
+ }
+ }
+}
\ No newline at end of file
diff --git a/WinAppCommon/ViewModels/UserControls/OpenDatabaseControlVm.cs b/WinAppCommon/ViewModels/UserControls/OpenDatabaseControlVm.cs
index d50e635..5bbcac6 100644
--- a/WinAppCommon/ViewModels/UserControls/OpenDatabaseControlVm.cs
+++ b/WinAppCommon/ViewModels/UserControls/OpenDatabaseControlVm.cs
@@ -4,6 +4,7 @@ using System.Text;
using System.Threading.Tasks;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
+using GalaSoft.MvvmLight.Views;
using MediatR;
using Messages;
using ModernKeePass.Application.Common.Interfaces;
@@ -93,6 +94,7 @@ namespace ModernKeePass.ViewModels
private readonly IResourceProxy _resource;
private readonly INotificationService _notification;
private readonly IFileProxy _file;
+ private readonly IDialogService _dialog;
private bool _hasPassword;
private bool _hasKeyFile;
private bool _isOpening;
@@ -102,12 +104,13 @@ namespace ModernKeePass.ViewModels
private string _keyFileText;
private bool _isError;
- public OpenDatabaseControlVm(IMediator mediator, IResourceProxy resource, INotificationService notification, IFileProxy file)
+ public OpenDatabaseControlVm(IMediator mediator, IResourceProxy resource, INotificationService notification, IFileProxy file, IDialogService dialog)
{
_mediator = mediator;
_resource = resource;
_notification = notification;
_file = file;
+ _dialog = dialog;
OpenKeyFileCommand = new RelayCommand(async () => await OpenKeyFile());
OpenDatabaseCommand = new RelayCommand(async databaseFilePath => await TryOpenDatabase(databaseFilePath), _ => IsValid);
_keyFileText = _resource.GetResourceValue("CompositeKeyDefaultKeyFile");
@@ -130,7 +133,7 @@ namespace ModernKeePass.ViewModels
if (database.IsDirty)
{
MessengerInstance.Register(this, async message => await OpenDatabase(message.Parameter as string));
- MessengerInstance.Send(new DatabaseAlreadyOpenedMessage {Parameter = databaseFilePath});
+ MessengerInstance.Send(new DatabaseAlreadyOpenedMessage { Parameter = databaseFilePath });
}
else await OpenDatabase(databaseFilePath);
}
@@ -146,9 +149,11 @@ namespace ModernKeePass.ViewModels
KeyFilePath = HasKeyFile ? KeyFilePath : null,
Password = HasPassword ? Password : null,
});
- var rootGroupId = (await _mediator.Send(new GetDatabaseQuery())).RootGroupId;
+ var database = await _mediator.Send(new GetDatabaseQuery());
- MessengerInstance.Send(new DatabaseOpenedMessage { RootGroupId = rootGroupId });
+ if (database.Size > Common.Constants.File.OneMegaByte)
+ await _dialog.ShowMessage(_resource.GetResourceValue("DatabaseTooBigDescription"), _resource.GetResourceValue("DatabaseTooBigTitle"));
+ MessengerInstance.Send(new DatabaseOpenedMessage { RootGroupId = database.RootGroupId });
}
catch (ArgumentException)
{
diff --git a/WinAppCommon/WinAppCommon.projitems b/WinAppCommon/WinAppCommon.projitems
index 57b5a0a..a8bc241 100644
--- a/WinAppCommon/WinAppCommon.projitems
+++ b/WinAppCommon/WinAppCommon.projitems
@@ -42,7 +42,7 @@
-
+