Skip to content

Commit c398fbf

Browse files
committed
Align Core with GUI
1 parent 1102017 commit c398fbf

52 files changed

Lines changed: 2079 additions & 432 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Core/Internal/Models/Account.cs

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
using System.ComponentModel;
2-
using Upsilon.Apps.PassKey.Core.Internal.Utils;
3-
using Upsilon.Apps.PassKey.Core.Public.Enums;
4-
using Upsilon.Apps.PassKey.Core.Public.Interfaces;
2+
using Upsilon.Apps.Passkey.Core.Internal.Utils;
3+
using Upsilon.Apps.Passkey.Core.Public.Enums;
4+
using Upsilon.Apps.Passkey.Core.Public.Interfaces;
55

6-
namespace Upsilon.Apps.PassKey.Core.Internal.Models
6+
namespace Upsilon.Apps.Passkey.Core.Internal.Models
77
{
88
internal sealed class Account : IAccount
99
{
1010
#region IAccount interface explicit Internal
1111

1212
string IItem.ItemId => Database.Get(ItemId);
13+
14+
IDatabase IItem.Database => Database;
15+
1316
IService IAccount.Service => Database.Get(Service);
1417

1518
string IAccount.Label
@@ -20,19 +23,19 @@ string IAccount.Label
2023
fieldName: nameof(Label),
2124
needsReview: false,
2225
oldValue: Label,
23-
value: value,
26+
newValue: value,
2427
readableValue: value);
2528
}
2629

27-
string[] IAccount.Identifiants
30+
string[] IAccount.Identifiers
2831
{
29-
get => Database.Get(Identifiants);
30-
set => Identifiants = Database.AutoSave.UpdateValue(ItemId,
32+
get => Database.Get(Identifiers);
33+
set => Identifiers = Database.AutoSave.UpdateValue(ItemId,
3134
itemName: ToString(),
32-
fieldName: nameof(Identifiants),
35+
fieldName: nameof(Identifiers),
3336
needsReview: true,
34-
oldValue: Identifiants,
35-
value: value,
37+
oldValue: Identifiers,
38+
newValue: value,
3639
readableValue: $"({string.Join(", ", value)})");
3740
}
3841

@@ -49,12 +52,26 @@ string IAccount.Password
4952

5053
if (_service != null)
5154
{
55+
if (Service.User.NumberOfOldPasswordToKeep != 0)
56+
{
57+
DateTime[] datesToRemove = [.. Passwords.Keys
58+
.OrderBy(x => x)
59+
.Take(Passwords.Count > Service.User.NumberOfOldPasswordToKeep
60+
? Passwords.Count - Service.User.NumberOfOldPasswordToKeep
61+
: 0)];
62+
63+
foreach (DateTime dateToRemove in datesToRemove)
64+
{
65+
_ = Passwords.Remove(dateToRemove);
66+
}
67+
}
68+
5269
_ = Database.AutoSave.UpdateValue(ItemId,
5370
itemName: ToString(),
5471
fieldName: nameof(Password),
5572
needsReview: true,
5673
oldValue: oldPasswords,
57-
value: Passwords,
74+
newValue: Passwords,
5875
readableValue: string.Empty);
5976
}
6077
}
@@ -71,7 +88,7 @@ string IAccount.Notes
7188
fieldName: nameof(Notes),
7289
needsReview: false,
7390
oldValue: Notes,
74-
value: value,
91+
newValue: value,
7592
readableValue: value);
7693
}
7794

@@ -83,7 +100,7 @@ int IAccount.PasswordUpdateReminderDelay
83100
fieldName: nameof(PasswordUpdateReminderDelay),
84101
needsReview: false,
85102
oldValue: PasswordUpdateReminderDelay,
86-
value: value,
103+
newValue: value,
87104
readableValue: value.ToString());
88105
}
89106

@@ -95,7 +112,7 @@ AccountOption IAccount.Options
95112
fieldName: nameof(Options),
96113
needsReview: false,
97114
oldValue: Options,
98-
value: value,
115+
newValue: value,
99116
readableValue: value.ToString());
100117
}
101118

@@ -113,7 +130,7 @@ internal Service Service
113130
}
114131

115132
public string Label { get; set; } = string.Empty;
116-
public string[] Identifiants { get; set; } = [];
133+
public string[] Identifiers { get; set; } = [];
117134
public string Password { get; set; } = string.Empty;
118135
public Dictionary<DateTime, string> Passwords { get; set; } = [];
119136
public string Notes { get; set; } = string.Empty;
@@ -144,23 +161,23 @@ public void Apply(Change change)
144161
switch (change.FieldName)
145162
{
146163
case nameof(Label):
147-
Label = Database.SerializationCenter.Deserialize<string>(change.Value);
164+
Label = change.NewValue.DeserializeTo<string>(Database.SerializationCenter);
148165
break;
149-
case nameof(Identifiants):
150-
Identifiants = Database.SerializationCenter.Deserialize<string[]>(change.Value);
166+
case nameof(Identifiers):
167+
Identifiers = change.NewValue.DeserializeTo<string[]>(Database.SerializationCenter);
151168
break;
152169
case nameof(Notes):
153-
Notes = Database.SerializationCenter.Deserialize<string>(change.Value);
170+
Notes = change.NewValue.DeserializeTo<string>(Database.SerializationCenter);
154171
break;
155172
case nameof(Password):
156-
Passwords = Database.SerializationCenter.Deserialize<Dictionary<DateTime, string>>(change.Value);
173+
Passwords = change.NewValue.DeserializeTo<Dictionary<DateTime, string>>(Database.SerializationCenter);
157174
Password = Passwords.Count != 0 ? Passwords[Passwords.Keys.Max()] : string.Empty;
158175
break;
159176
case nameof(PasswordUpdateReminderDelay):
160-
PasswordUpdateReminderDelay = Database.SerializationCenter.Deserialize<int>(change.Value);
177+
PasswordUpdateReminderDelay = change.NewValue.DeserializeTo<int>(Database.SerializationCenter);
161178
break;
162179
case nameof(Options):
163-
Options = Database.SerializationCenter.Deserialize<AccountOption>(change.Value);
180+
Options = change.NewValue.DeserializeTo<AccountOption>(Database.SerializationCenter);
164181
break;
165182
default:
166183
throw new InvalidDataException("FieldName not valid");
@@ -180,7 +197,7 @@ public override string ToString()
180197
account += $"{Label} ";
181198
}
182199

183-
return account + $"({string.Join(", ", Identifiants)})";
200+
return account + $"({string.Join(", ", Identifiers)})";
184201
}
185202
}
186203
}

Core/Internal/Models/AutoSave.cs

Lines changed: 120 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,111 @@
1-
using Upsilon.Apps.PassKey.Core.Internal.Utils;
2-
using Upsilon.Apps.PassKey.Core.Public.Interfaces;
1+
using Upsilon.Apps.Passkey.Core.Internal.Utils;
2+
using Upsilon.Apps.Passkey.Core.Public.Interfaces;
33

4-
namespace Upsilon.Apps.PassKey.Core.Internal.Models
4+
namespace Upsilon.Apps.Passkey.Core.Internal.Models
55
{
66
internal sealed class AutoSave
77
{
8-
private Database? _database;
98
internal Database Database
109
{
11-
get => _database ?? throw new NullReferenceException(nameof(Database));
12-
set => _database = value;
10+
get => field ?? throw new NullReferenceException(nameof(Database));
11+
set;
1312
}
1413

15-
public Queue<Change> Changes { get; set; } = new();
14+
public Dictionary<string, List<Change>> Changes { get; set; } = [];
1615

17-
internal T UpdateValue<T>(string itemId, string itemName, string fieldName, bool needsReview, T oldValue, T value, string readableValue) where T : notnull
16+
internal T UpdateValue<T>(string itemId,
17+
string itemName,
18+
string fieldName,
19+
bool needsReview,
20+
T oldValue,
21+
T newValue,
22+
string readableValue) where T : notnull
1823
{
19-
if (ISerializationCenter.AreDifferent(Database.SerializationCenter, oldValue, value))
24+
if (ISerializationCenter.AreDifferent(Database.SerializationCenter, oldValue, newValue))
2025
{
21-
_addChange(itemId, itemName, string.Empty, fieldName, Database.SerializationCenter.Serialize(value), readableValue, needsReview, Change.Type.Update);
26+
_addChange(itemId,
27+
itemName,
28+
string.Empty,
29+
fieldName,
30+
oldValue.SerializeWith(Database.SerializationCenter),
31+
newValue.SerializeWith(Database.SerializationCenter),
32+
readableValue,
33+
needsReview,
34+
Change.Type.Update);
2235
}
2336

24-
return value;
37+
return newValue;
2538
}
2639

27-
internal T AddValue<T>(string itemId, string itemName, string containerName, bool needsReview, T value) where T : notnull
40+
internal T AddValue<T>(string itemId,
41+
string itemName,
42+
string containerName,
43+
bool needsReview,
44+
T value) where T : notnull
2845
{
29-
_addChange(itemId, itemName, containerName, string.Empty, Database.SerializationCenter.Serialize(value), string.Empty, needsReview, Change.Type.Add);
46+
_addChange(itemId, itemName, containerName, string.Empty, value.SerializeWith(Database.SerializationCenter), string.Empty, needsReview, Change.Type.Add);
3047

3148
return value;
3249
}
3350

34-
internal T DeleteValue<T>(string itemId, string itemName, string containerName, bool needsReview, T value) where T : notnull
51+
internal T DeleteValue<T>(string itemId,
52+
string itemName,
53+
string containerName,
54+
bool needsReview,
55+
T value) where T : notnull
3556
{
36-
_addChange(itemId, itemName, containerName, string.Empty, Database.SerializationCenter.Serialize(value), string.Empty, needsReview, Change.Type.Delete);
57+
_addChange(itemId, itemName, containerName, string.Empty, value.SerializeWith(Database.SerializationCenter), string.Empty, needsReview, Change.Type.Delete);
3758

3859
return value;
3960
}
4061

41-
private void _addChange(string itemId, string itemName, string containerName, string fieldName, string value, string readableValue, bool needsReview, Change.Type action)
62+
private void _addChange(string itemId,
63+
string itemName,
64+
string containerName,
65+
string fieldName,
66+
string newValue,
67+
string readableValue,
68+
bool needsReview,
69+
Change.Type action)
70+
{
71+
_addChange(itemId,
72+
itemName,
73+
containerName,
74+
fieldName,
75+
null,
76+
newValue,
77+
readableValue,
78+
needsReview,
79+
action);
80+
}
81+
82+
private void _addChange(string itemId,
83+
string itemName,
84+
string containerName,
85+
string fieldName,
86+
string? oldValue,
87+
string newValue,
88+
string readableValue,
89+
bool needsReview,
90+
Change.Type action)
4291
{
43-
Changes.Enqueue(new Change
92+
string changeKey = $"{itemId}\t{fieldName}";
93+
if (!Changes.ContainsKey(changeKey))
94+
{
95+
Changes[changeKey] = [];
96+
}
97+
98+
Change currentChange = new()
4499
{
100+
Index = DateTime.Now.Ticks,
45101
ActionType = action,
46102
ItemId = itemId,
47103
FieldName = fieldName,
48-
Value = value,
49-
});
104+
OldValue = oldValue,
105+
NewValue = newValue,
106+
};
107+
108+
_mergeChanges(changeKey, currentChange);
50109

51110
if (Database.AutoSaveFileLocker == null)
52111
{
@@ -63,24 +122,60 @@ private void _addChange(string itemId, string itemName, string containerName, st
63122
Database.Logs.AddLog(logMessage, needsReview);
64123
}
65124

66-
internal void MergeChange()
125+
private void _mergeChanges(string changeKey, Change currentChange)
67126
{
68-
while (Changes.Count != 0)
127+
Change? lastUpdate = Changes[changeKey].LastOrDefault(x => x.ActionType == Change.Type.Update);
128+
129+
if (currentChange.ActionType != Change.Type.Update
130+
|| lastUpdate is null)
69131
{
70-
Database.User?.Apply(Changes.Dequeue());
132+
Changes[changeKey].Add(currentChange);
133+
return;
71134
}
72135

73-
Clear();
136+
_ = Changes[changeKey].Remove(lastUpdate);
137+
currentChange.OldValue = lastUpdate.OldValue;
138+
139+
if (currentChange.OldValue != currentChange.NewValue)
140+
{
141+
Changes[changeKey].Add(currentChange);
142+
}
143+
else if (Changes[changeKey].Count == 0)
144+
{
145+
_ = Changes.Remove(changeKey);
146+
}
74147
}
75148

76-
internal void Clear()
149+
internal void ApplyChanges(bool deleteFile)
150+
{
151+
List<Change> changes = Changes.Values.SelectMany(x => x).OrderBy(x => x.Index).ToList();
152+
153+
foreach (Change change in changes)
154+
{
155+
Database.User?.Apply(change);
156+
}
157+
158+
if (deleteFile)
159+
{
160+
Clear(deleteFile: true);
161+
}
162+
}
163+
164+
internal bool Any() => Any(string.Empty);
165+
166+
internal bool Any(string itemId) => Changes.Any(x => x.Key.StartsWith(itemId));
167+
168+
internal bool Any(string itemId, string fieldName) => Changes.Any(x => x.Key == $"{itemId}\t{fieldName}");
169+
170+
internal void Clear(bool deleteFile)
77171
{
78172
Changes.Clear();
79173

80174
Database.AutoSaveFileLocker?.Dispose();
81175
Database.AutoSaveFileLocker = null;
82176

83-
if (File.Exists(Database.AutoSaveFile))
177+
if (deleteFile
178+
&& File.Exists(Database.AutoSaveFile))
84179
{
85180
File.Delete(Database.AutoSaveFile);
86181
}

Core/Internal/Models/Change.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace Upsilon.Apps.PassKey.Core.Internal.Models
1+
namespace Upsilon.Apps.Passkey.Core.Internal.Models
22
{
33
internal sealed class Change
44
{
@@ -10,9 +10,11 @@ public enum Type
1010
Delete = 3,
1111
}
1212

13+
public long Index { get; set; } = long.MaxValue;
1314
public Type ActionType { get; set; } = Type.None;
1415
public string ItemId { get; set; } = string.Empty;
1516
public string FieldName { get; set; } = string.Empty;
16-
public string Value { get; set; } = string.Empty;
17+
public string? OldValue { get; set; } = null;
18+
public string NewValue { get; set; } = string.Empty;
1719
}
1820
}

0 commit comments

Comments
 (0)