diff --git a/Core/Models/Account.cs b/Core/Models/Account.cs index 72b1dec..7af4567 100644 --- a/Core/Models/Account.cs +++ b/Core/Models/Account.cs @@ -141,17 +141,17 @@ internal bool PasswordExpired DateTime lastPassword = Passwords.Keys.Max(); int delay = ((DateTime.Now.Year - lastPassword.Year) * 12) + DateTime.Now.Month - lastPassword.Month; - return delay >= PasswordUpdateReminderDelay; + return delay > PasswordUpdateReminderDelay; } } - internal bool PasswordLeaked => Options.ContainsFlag(AccountOption.WarnIfPasswordLeaked) && Database.PasswordFactory.PasswordLeaked(Password); + internal bool PasswordLeaked { get; set; } = false; - public void Apply(Change change) + internal void Apply(Change change) { switch (change.ActionType) { - case LogEventType.ItemUpdated: + case ActivityEventType.ItemUpdated: switch (change.FieldName) { case nameof(Label): @@ -178,7 +178,7 @@ public void Apply(Change change) } break; default: - throw new InvalidEnumArgumentException(nameof(change.ActionType), (int)change.ActionType, typeof(LogEventType)); + throw new InvalidEnumArgumentException(nameof(change.ActionType), (int)change.ActionType, typeof(ActivityEventType)); } } @@ -193,5 +193,7 @@ public override string ToString() return account + $"({string.Join(", ", Identifiers)})"; } + + public bool HasChanged() => Database.HasChanged(ItemId); } } \ No newline at end of file diff --git a/Core/Models/Activity.cs b/Core/Models/Activity.cs new file mode 100644 index 0000000..902eb12 --- /dev/null +++ b/Core/Models/Activity.cs @@ -0,0 +1,114 @@ +using Upsilon.Apps.Passkey.Core.Utils; +using Upsilon.Apps.Passkey.Interfaces.Enums; +using Upsilon.Apps.Passkey.Interfaces.Models; + +namespace Upsilon.Apps.Passkey.Core.Models +{ + internal class Activity : IActivity + { + #region IActivity interface + + public DateTime DateTime => new(DateTimeTicks); + + public string ItemId { get; } = string.Empty; + + public ActivityEventType EventType { get; set; } = ActivityEventType.None; + + public bool NeedsReview { get; set; } = true; + + public string Message => _buildMessage(); + + #endregion + + public long DateTimeTicks { get; set; } + public string[] Data { get; set; } = []; + + public Activity(long dateTimeTicks, string itemId, ActivityEventType eventType, string[] data, bool needsReview) + { + DateTimeTicks = dateTimeTicks; + ItemId = itemId; + EventType = eventType; + Data = data; + NeedsReview = needsReview; + } + + public Activity(string activity) + { + string[] info = activity.Split('|'); + + if (info.Length > 0) + { + DateTimeTicks = Convert.ToInt64(info[0], 16); + } + + if (info.Length > 1) + { + ItemId = info[1]; + } + + if (info.Length > 2 + && byte.TryParse(info[2], out byte eventType)) + { + EventType = (ActivityEventType)eventType; + } + + if (info.Length > 3) + { + NeedsReview = !string.IsNullOrEmpty(info[3]); + } + + if (info.Length > 4) + { + activity = string.Join("|", info[4..]) + .Replace("|", "/|") + .Replace("\\/|", "\\|"); + info = activity.Split("/|"); + Data = [.. info.Select(x => x.Replace("\\|", "|"))]; + } + } + + public override string ToString() + { + string activity = $"{DateTimeTicks:X}|{ItemId}|{(int)EventType}|{(NeedsReview ? "1" : "")}"; + + string[] data = [.. Data.Select(x => x.Replace("|", "\\|"))]; + if (data.Length != 0) + { + activity += $"|{string.Join("|", data)}"; + } + + return activity; + } + + private string _buildMessage() + { + string message = EventType switch + { + ActivityEventType.MergeAndSaveThenRemoveAutoSaveFile => $"User {Data[0]}'s autosave merged and saved", + ActivityEventType.MergeWithoutSavingAndKeepAutoSaveFile => $"User {Data[0]}'s autosave merged without saving", + ActivityEventType.DontMergeAndRemoveAutoSaveFile => $"User {Data[0]}'s autosave not merged and removed", + ActivityEventType.DontMergeAndKeepAutoSaveFile => $"User {Data[0]}'s autosave not merged and keeped", + ActivityEventType.DatabaseCreated => $"User {Data[0]}'s database created", + ActivityEventType.DatabaseOpened => $"User {Data[0]}'s database opened", + ActivityEventType.DatabaseSaved => $"User {Data[0]}'s database saved", + ActivityEventType.DatabaseClosed => $"User {Data[0]}'s database closed", + ActivityEventType.LoginSessionTimeoutReached => $"User {Data[0]}'s login session timeout reached", + ActivityEventType.LoginFailed => $"User {Data[0]} login failed at level {Data[1]}", + ActivityEventType.UserLoggedIn => $"User {Data[0]} logged in", + ActivityEventType.UserLoggedOut => $"User {Data[0]} logged out {(!string.IsNullOrEmpty(Data[1]) ? "without saving" : "")}", + ActivityEventType.ImportingDataStarted => $"Importing data from file : '{Data[0]}'", + ActivityEventType.ImportingDataSucceded => $"Import completed successfully", + ActivityEventType.ImportingDataFailed => $"Import failed because {Data[0]}", + ActivityEventType.ExportingDataStarted => $"Exporting data to file : '{Data[0]}'", + ActivityEventType.ExportingDataSucceded => $"Export completed successfully", + ActivityEventType.ExportingDataFailed => $"Export failed because {Data[0]}", + ActivityEventType.ItemUpdated => $"{(Data.Length > 3 ? $"{Data[3]}'s " : "")}{Data[0]}'s {Data[1].ToSentenceCase().ToLower()} has been {(string.IsNullOrWhiteSpace(Data[2]) ? $"updated" : $"set to {Data[2]}")}", + ActivityEventType.ItemAdded => $"{Data[2]} has been added to {Data[0]}", + ActivityEventType.ItemDeleted => $"{Data[2]} has been removed from {Data[0]}", + _ => ToString(), + }; + + return message.Trim(); + } + } +} diff --git a/Core/Models/AutoSave.cs b/Core/Models/AutoSave.cs index 646844a..d13edcc 100644 --- a/Core/Models/AutoSave.cs +++ b/Core/Models/AutoSave.cs @@ -28,7 +28,7 @@ internal T UpdateValue(string itemId, newValue.SerializeWith(Database.SerializationCenter), readableValue, needsReview, - LogEventType.ItemUpdated); + ActivityEventType.ItemUpdated); } return newValue; @@ -39,7 +39,7 @@ internal T AddValue(string itemId, bool needsReview, T value) where T : notnull { - _addChange(itemId, string.Empty, value.SerializeWith(Database.SerializationCenter), readableValue, needsReview, LogEventType.ItemAdded); + _addChange(itemId, string.Empty, value.SerializeWith(Database.SerializationCenter), readableValue, needsReview, ActivityEventType.ItemAdded); return value; } @@ -49,7 +49,7 @@ internal T DeleteValue(string itemId, bool needsReview, T value) where T : notnull { - _addChange(itemId, string.Empty, value.SerializeWith(Database.SerializationCenter), readableValue, needsReview, LogEventType.ItemDeleted); + _addChange(itemId, string.Empty, value.SerializeWith(Database.SerializationCenter), readableValue, needsReview, ActivityEventType.ItemDeleted); return value; } @@ -59,7 +59,7 @@ private void _addChange(string itemId, string newValue, string readableValue, bool needsReview, - LogEventType action) + ActivityEventType action) { _addChange(itemId, fieldName, @@ -76,7 +76,7 @@ private void _addChange(string itemId, string newValue, string readableValue, bool needsReview, - LogEventType action) + ActivityEventType action) { string changeKey = $"{itemId}\t{fieldName}"; if (!Changes.ContainsKey(changeKey)) @@ -97,12 +97,14 @@ private void _addChange(string itemId, _mergeChanges(changeKey, currentChange); Database.FileLocker.Save(this, Database.AutoSaveFileEntry, Database.Passkeys); + string itemName = string.Empty; + string parentName = string.Empty; if (itemId == Database.User?.ItemId) { if (Database.User is not null) { - itemId = Database.User.ToString(); + itemName = Database.User.ToString(); } } else if (itemId.StartsWith('S')) @@ -111,7 +113,7 @@ private void _addChange(string itemId, if (s is not null) { - itemId = s.ToString(); + itemName = s.ToString(); } } else if (itemId.StartsWith('A')) @@ -120,20 +122,33 @@ private void _addChange(string itemId, if (a is not null) { - itemId = a.ToString(); + itemName = a.ToString(); + + if (action == ActivityEventType.ItemUpdated) + { + parentName = a.Service.ToString(); + } } } - Database.Logs.AddLog(data: [itemId, fieldName, readableValue], + string[] data = [itemName, fieldName, readableValue]; + + if (!string.IsNullOrEmpty(parentName)) + { + data = [.. data, parentName]; + } + + Database.ActivityCenter.AddActivity(itemId: itemId, eventType: action, + data, needsReview); } private void _mergeChanges(string changeKey, Change currentChange) { - Change? lastUpdate = Changes[changeKey].LastOrDefault(x => x.ActionType == LogEventType.ItemUpdated); + Change? lastUpdate = Changes[changeKey].LastOrDefault(x => x.ActionType == ActivityEventType.ItemUpdated); - if (currentChange.ActionType != LogEventType.ItemUpdated + if (currentChange.ActionType != ActivityEventType.ItemUpdated || lastUpdate is null) { Changes[changeKey].Add(currentChange); diff --git a/Core/Models/Change.cs b/Core/Models/Change.cs index 429a3dc..81d34e8 100644 --- a/Core/Models/Change.cs +++ b/Core/Models/Change.cs @@ -5,7 +5,7 @@ namespace Upsilon.Apps.Passkey.Core.Models internal sealed class Change { public long Index { get; set; } = long.MaxValue; - public LogEventType ActionType { get; set; } = LogEventType.None; + public ActivityEventType ActionType { get; set; } = ActivityEventType.None; public string ItemId { get; set; } = string.Empty; public string FieldName { get; set; } = string.Empty; public string? OldValue { get; set; } = null; diff --git a/Core/Models/Database.cs b/Core/Models/Database.cs index a11dcf7..f36286e 100644 --- a/Core/Models/Database.cs +++ b/Core/Models/Database.cs @@ -12,10 +12,10 @@ public sealed class Database : IDatabase public string DatabaseFile { get; set; } - IUser? IDatabase.User => Get(User); + IUser? IDatabase.User => User; int? IDatabase.SessionLeftTime => User?.SessionLeftTime; - ILog[]? IDatabase.Logs => Get(Logs.Logs.OrderByDescending(x => x.DateTime).ToArray()); + IActivity[]? IDatabase.Activities => Get(ActivityCenter.Activities.OrderByDescending(x => x.DateTime).ToArray()); IWarning[]? IDatabase.Warnings => Get(User is not null ? Warnings : null); @@ -54,8 +54,9 @@ public void Delete() { if (ex is WrongPasswordException passwordException) { - Logs.AddLog(data: [Username, passwordException.PasswordLevel.ToString()], - eventType: LogEventType.LoginFailed, + ActivityCenter.AddActivity(itemId: string.Empty, + eventType: ActivityEventType.LoginFailed, + data: [Username, passwordException.PasswordLevel.ToString()], needsReview: true); } } @@ -64,9 +65,10 @@ public void Delete() { User.Database = this; - Logs.LoadStringLogs(); - Logs.AddLog(data: [Username], - eventType: LogEventType.UserLoggedIn, + ActivityCenter.LoadStringActivities(); + ActivityCenter.AddActivity(itemId: string.Empty, + eventType: ActivityEventType.UserLoggedIn, + data: [Username], needsReview: false); if (FileLocker.Exists(AutoSaveFileEntry)) @@ -89,17 +91,22 @@ public void Delete() public void Close() => Dispose(); - public bool HasChanged() => User is not null && HasChanged(User.ItemId); - public bool HasChanged(string itemId) => AutoSave.Any(itemId); public bool HasChanged(string itemId, string fieldName) => AutoSave.Any(itemId, fieldName); public bool ImportFromFile(string filePath) { - _save(logSaveEvent: true); - Logs.AddLog(data: [filePath], - eventType: LogEventType.ImportingDataStarted, + if (User is null) throw new NullReferenceException(nameof(User)); + + if (User.HasChanged()) + { + _save(logSaveEvent: true); + } + + ActivityCenter.AddActivity(itemId: string.Empty, + eventType: ActivityEventType.ImportingDataStarted, + data: [filePath], needsReview: true); string importContent = string.Empty; @@ -128,15 +135,17 @@ public bool ImportFromFile(string filePath) if (string.IsNullOrWhiteSpace(errorLog)) { - Logs.AddLog(data: [], - eventType: LogEventType.ImportingDataSucceded, + ActivityCenter.AddActivity(itemId: string.Empty, + eventType: ActivityEventType.ImportingDataSucceded, + data: [], needsReview: true); _save(logSaveEvent: true); } else { - Logs.AddLog(data: [errorLog], - eventType: LogEventType.ImportingDataFailed, + ActivityCenter.AddActivity(itemId: string.Empty, + eventType: ActivityEventType.ImportingDataFailed, + data: [errorLog], needsReview: true); } @@ -145,9 +154,16 @@ public bool ImportFromFile(string filePath) public bool ExportToFile(string filePath) { - _save(logSaveEvent: true); - Logs.AddLog(data: [filePath], - eventType: LogEventType.ExportingDataStarted, + if (User is null) throw new NullReferenceException(nameof(User)); + + if (User.HasChanged()) + { + _save(logSaveEvent: true); + } + + ActivityCenter.AddActivity(itemId: string.Empty, + eventType: ActivityEventType.ExportingDataStarted, + data: [filePath], needsReview: true); string errorLog = string.Empty; @@ -171,14 +187,16 @@ public bool ExportToFile(string filePath) if (string.IsNullOrWhiteSpace(errorLog)) { - Logs.AddLog(data: [], - eventType: LogEventType.ExportingDataSucceded, + ActivityCenter.AddActivity(itemId: string.Empty, + eventType: ActivityEventType.ExportingDataSucceded, + data: [], needsReview: true); } else { - Logs.AddLog(data: [errorLog], - eventType: LogEventType.ExportingDataFailed, + ActivityCenter.AddActivity(itemId: string.Empty, + eventType: ActivityEventType.ExportingDataFailed, + data: [errorLog], needsReview: true); } @@ -189,7 +207,7 @@ public bool ExportToFile(string filePath) internal User? User; internal AutoSave AutoSave; - internal LogCenter Logs; + internal ActivityCenter ActivityCenter; internal Warning[]? Warnings; internal string Username { get; private set; } @@ -197,7 +215,7 @@ public bool ExportToFile(string filePath) internal readonly string DatabaseFileEntry = "database"; internal readonly string AutoSaveFileEntry = "autosave"; - internal readonly string LogFileEntry = "log"; + internal readonly string ActivityFileEntry = "activity"; internal FileLocker FileLocker; private Database(ICryptographyCenter cryptographicCenter, @@ -232,15 +250,15 @@ private Database(ICryptographyCenter cryptographicCenter, FileLocker = new(cryptographicCenter, serializationCenter, databaseFile, fileMode); - Logs = fileMode == FileMode.Create + ActivityCenter = fileMode == FileMode.Create ? new() { Username = username, PublicKey = publicKey, } - : FileLocker.Open(LogFileEntry); + : FileLocker.Open(ActivityFileEntry); - Logs.Database = this; + ActivityCenter.Database = this; } public static IDatabase Create(ICryptographyCenter cryptographicCenter, @@ -284,8 +302,9 @@ public static IDatabase Create(ICryptographyCenter cryptographicCenter, Passkeys = [.. passkeys], }; - database.Logs.AddLog(data: [username], - eventType: LogEventType.DatabaseCreated, + database.ActivityCenter.AddActivity(itemId: string.Empty, + eventType: ActivityEventType.DatabaseCreated, + data: [username], needsReview: false); database._save(logSaveEvent: false); @@ -308,8 +327,9 @@ public static IDatabase Open(ICryptographyCenter cryptographicCenter, FileMode.Open, username); - database.Logs.AddLog(data: [username], - eventType: LogEventType.DatabaseOpened, + database.ActivityCenter.AddActivity(itemId: string.Empty, + eventType: ActivityEventType.DatabaseOpened, + data: [username], needsReview: false); return database; @@ -324,7 +344,7 @@ internal T Get(T value) private void _save(bool logSaveEvent) { - _saveLogs(); + _saveActivities(rebuildStringActivities: true); _saveDatabase(logSaveEvent); } @@ -338,24 +358,27 @@ private void _saveDatabase(bool logSaveEvent) if (logSaveEvent) { - Logs.AddLog(data: [Username], - eventType: LogEventType.DatabaseSaved, + ActivityCenter.AddActivity(itemId: string.Empty, + eventType: ActivityEventType.DatabaseSaved, + data: [Username], needsReview: false); } AutoSave.Clear(deleteFile: true); + _ = Task.Run(_lookAtWarnings); + User.ResetTimer(); DatabaseSaved?.Invoke(this, EventArgs.Empty); } - private void _saveLogs() + private void _saveActivities(bool rebuildStringActivities) { if (User is null) throw new NullReferenceException(nameof(User)); - Logs.Username = User.Username; - FileLocker.Save(Logs, LogFileEntry, [CryptographyCenter.GetHash(User.Username)]); + ActivityCenter.Username = User.Username; + ActivityCenter.Save(rebuildStringActivities); } internal void Close(bool logCloseEvent, bool loginTimeoutReached) @@ -371,13 +394,15 @@ internal void Close(bool logCloseEvent, bool loginTimeoutReached) AutoSave.Clear(deleteFile: true); } - Logs.AddLog(data: [Username, needsReview ? "1" : string.Empty], - eventType: LogEventType.UserLoggedOut, + ActivityCenter.AddActivity(itemId: string.Empty, + eventType: ActivityEventType.UserLoggedOut, + data: [Username, needsReview ? "1" : string.Empty], needsReview); } - Logs.AddLog(data: [Username], - eventType: LogEventType.DatabaseClosed, + ActivityCenter.AddActivity(itemId: string.Empty, + eventType: ActivityEventType.DatabaseClosed, + data: [Username], needsReview: false); } @@ -408,7 +433,7 @@ private void _handleAutoSave(AutoSaveMergeBehavior mergeAutoSave) break; case AutoSaveMergeBehavior.MergeWithoutSavingAndKeepAutoSaveFile: AutoSave.ApplyChanges(deleteFile: false); - _saveLogs(); + _saveActivities(rebuildStringActivities: false); break; case AutoSaveMergeBehavior.DontMergeAndRemoveAutoSaveFile: AutoSave.Clear(deleteFile: true); @@ -418,8 +443,9 @@ private void _handleAutoSave(AutoSaveMergeBehavior mergeAutoSave) break; } - Logs.AddLog(data: [Username], - eventType: (LogEventType)mergeAutoSave, + ActivityCenter.AddActivity(itemId: string.Empty, + eventType: (ActivityEventType)mergeAutoSave, + data: [Username], needsReview: true); } @@ -429,31 +455,33 @@ private void _lookAtWarnings() try { - Warning[] logWarnings = _lookAtLogWarnings(); + Warning[] activityWarnings = _lookAtActivityWarnings(); Warning[] passwordUpdateReminderWarnings = _lookAtPasswordUpdateReminderWarnings(); Warning[] passwordLeakedWarnings = _lookAtPasswordLeakedWarnings(); Warning[] duplicatedPasswordsWarnings = _lookAtDuplicatedPasswordsWarnings(); - Warnings = [..logWarnings, + Warnings = [..activityWarnings, ..passwordUpdateReminderWarnings, ..passwordLeakedWarnings, ..duplicatedPasswordsWarnings]; - WarningDetected?.Invoke(this, new WarningDetectedEventArgs( - [..User.WarningsToNotify.ContainsFlag(WarningType.LogReviewWarning) ? logWarnings : [], - ..User.WarningsToNotify.ContainsFlag(WarningType.PasswordUpdateReminderWarning) ? passwordUpdateReminderWarnings : [], - ..User.WarningsToNotify.ContainsFlag(WarningType.PasswordLeakedWarning) ? passwordLeakedWarnings : [], - ..User.WarningsToNotify.ContainsFlag(WarningType.DuplicatedPasswordsWarning) ? duplicatedPasswordsWarnings : []])); + IWarning[] warnings = [.. Warnings?.Where(x => User is not null && User.WarningsToNotify.HasFlag(x.WarningType)) ?? []]; + + if (warnings.Length != 0) + { + WarningDetected?.Invoke(this, new WarningDetectedEventArgs(warnings)); + } } catch { } } - private Warning[] _lookAtLogWarnings() + private Warning[] _lookAtActivityWarnings() { - if (User is null) throw new NullReferenceException(nameof(User)); - if (Logs.Logs is null) throw new NullReferenceException(nameof(Logs.Logs)); - - return [new Warning([.. Logs.Logs.Where(x => x.NeedsReview).Cast()])]; + return User is null + ? throw new NullReferenceException(nameof(User)) + : ActivityCenter.Activities is null + ? throw new NullReferenceException(nameof(ActivityCenter.Activities)) + : [new Warning([.. ActivityCenter.Activities.Where(x => x.NeedsReview).Cast()])]; } private Warning[] _lookAtPasswordUpdateReminderWarnings() @@ -471,9 +499,23 @@ private Warning[] _lookAtPasswordLeakedWarnings() { if (User is null) return []; + string[] leakedPasswords = [.. User.Services + .SelectMany(x => x.Accounts) + .Where(x => x.Options.HasFlag(AccountOption.WarnIfPasswordLeaked)) + .Select(x => x.Password) + .Distinct() + .AsParallel() + .Where(PasswordFactory.PasswordLeaked)]; + Account[] accounts = [.. User.Services .SelectMany(x => x.Accounts) - .Where(x => x.PasswordLeaked)]; + .Where(x => x.Options.HasFlag(AccountOption.WarnIfPasswordLeaked) + && leakedPasswords.Contains(x.Password))]; + + foreach (Account account in accounts) + { + account.PasswordLeaked = true; + } return accounts.Length != 0 ? [new Warning(WarningType.PasswordLeakedWarning, accounts)] : []; } @@ -491,7 +533,10 @@ private Warning[] _lookAtDuplicatedPasswordsWarnings() foreach (IGrouping accounts in duplicatedPasswords) { - warnings.Add(new(WarningType.DuplicatedPasswordsWarning, [.. accounts.Cast()])); + if (accounts.Any(x => x.Options.HasFlag(AccountOption.WarnIfDuplicatedPassword))) + { + warnings.Add(new(WarningType.DuplicatedPasswordsWarning, [.. accounts.Cast()])); + } } return [.. warnings]; diff --git a/Core/Models/Log.cs b/Core/Models/Log.cs deleted file mode 100644 index 773e6ba..0000000 --- a/Core/Models/Log.cs +++ /dev/null @@ -1,94 +0,0 @@ -using Upsilon.Apps.Passkey.Core.Utils; -using Upsilon.Apps.Passkey.Interfaces.Enums; -using Upsilon.Apps.Passkey.Interfaces.Models; - -namespace Upsilon.Apps.Passkey.Core.Models -{ - internal class Log : ILog - { - #region ILog interface - - public DateTime DateTime => new(DateTimeTicks); - - public LogEventType EventType { get; set; } = LogEventType.None; - - public bool NeedsReview { get; set; } = true; - - public string[] Data { get; set; } = []; - - public string Message => _buildMessage(); - - #endregion - - public long DateTimeTicks { get; set; } - - private readonly Database? _database; - - public Log() { } - - public Log(Database database, string log) - { - _database = database; - - string[] info = log.Split('|'); - - if (info.Length > 0 - && long.TryParse(info[0], out long ticks)) - { - DateTimeTicks = ticks; - } - - if (info.Length > 1 - && byte.TryParse(info[1], out byte eventType)) - { - EventType = (LogEventType)eventType; - } - - if (info.Length > 2) - { - NeedsReview = !string.IsNullOrEmpty(info[2]); - } - - if (info.Length > 3) - { - Data = info[3..]; - } - } - - public override string ToString() - { - return $"{DateTimeTicks}|{(int)EventType}|{(NeedsReview ? "1" : "")}|{string.Join("|", Data)}"; - } - - private string _buildMessage() - { - string message = EventType switch - { - LogEventType.MergeAndSaveThenRemoveAutoSaveFile => $"User {Data[0]}'s autosave merged and saved", - LogEventType.MergeWithoutSavingAndKeepAutoSaveFile => $"User {Data[0]}'s autosave merged without saving", - LogEventType.DontMergeAndRemoveAutoSaveFile => $"User {Data[0]}'s autosave not merged and removed", - LogEventType.DontMergeAndKeepAutoSaveFile => $"User {Data[0]}'s autosave not merged and keeped", - LogEventType.DatabaseCreated => $"User {Data[0]}'s database created", - LogEventType.DatabaseOpened => $"User {Data[0]}'s database opened", - LogEventType.DatabaseSaved => $"User {Data[0]}'s database saved", - LogEventType.DatabaseClosed => $"User {Data[0]}'s database closed", - LogEventType.LoginSessionTimeoutReached => $"User {Data[0]}'s login session timeout reached", - LogEventType.LoginFailed => $"User {Data[0]} login failed at level {Data[1]}", - LogEventType.UserLoggedIn => $"User {Data[0]} logged in", - LogEventType.UserLoggedOut => $"User {Data[0]} logged out {(!string.IsNullOrEmpty(Data[1]) ? "without saving" : "")}", - LogEventType.ImportingDataStarted => $"Importing data from file : '{Data[0]}'", - LogEventType.ImportingDataSucceded => $"Import completed successfully", - LogEventType.ImportingDataFailed => $"Import failed because {Data[0]}", - LogEventType.ExportingDataStarted => $"Exporting data to file : '{Data[0]}'", - LogEventType.ExportingDataSucceded => $"Export completed successfully", - LogEventType.ExportingDataFailed => $"Export failed because {Data[0]}", - LogEventType.ItemUpdated => $"{Data[0]}'s {Data[1].ToSentenceCase().ToLower()} has been {(string.IsNullOrWhiteSpace(Data[2]) ? $"updated" : $"set to {Data[2]}")}", - LogEventType.ItemAdded => $"{Data[2]} has been added to {Data[0]}", - LogEventType.ItemDeleted => $"{Data[2]} has been removed from {Data[0]}", - _ => ToString(), - }; - - return message.Trim(); - } - } -} diff --git a/Core/Models/Service.cs b/Core/Models/Service.cs index 02b86ef..c45e9f4 100644 --- a/Core/Models/Service.cs +++ b/Core/Models/Service.cs @@ -54,7 +54,7 @@ public IAccount AddAccount(string label, IEnumerable identifiers, string Account account = new() { Service = this, - ItemId = "A" + Database.CryptographyCenter.GetHash(label + string.Join(string.Empty, identifiers)), + ItemId = "A" + Database.CryptographyCenter.GetHash(ItemId + label + string.Join(string.Empty, identifiers)), Label = label, Identifiers = [.. identifiers], Password = password, @@ -121,11 +121,11 @@ internal User User public string Url { get; set; } = string.Empty; public string Notes { get; set; } = string.Empty; - public void Apply(Change change) + internal void Apply(Change change) { switch (change.ActionType) { - case LogEventType.ItemUpdated: + case ActivityEventType.ItemUpdated: switch (change.FieldName) { case nameof(ServiceName): @@ -141,20 +141,22 @@ public void Apply(Change change) throw new InvalidDataException("FieldName not valid"); } break; - case LogEventType.ItemAdded: + case ActivityEventType.ItemAdded: Account accountToAdd = change.NewValue.DeserializeTo(Database.SerializationCenter); accountToAdd.Service = this; Accounts.Add(accountToAdd); break; - case LogEventType.ItemDeleted: + case ActivityEventType.ItemDeleted: Account accountToDelete = change.NewValue.DeserializeTo(Database.SerializationCenter); _ = Accounts.RemoveAll(x => x.ItemId == accountToDelete.ItemId); break; default: - throw new InvalidEnumArgumentException(nameof(change.ActionType), (int)change.ActionType, typeof(LogEventType)); + throw new InvalidEnumArgumentException(nameof(change.ActionType), (int)change.ActionType, typeof(ActivityEventType)); } } public override string ToString() => $"Service {ServiceName}"; + + public bool HasChanged() => Database.HasChanged(ItemId) || Accounts.Any(x => x.HasChanged()); } } \ No newline at end of file diff --git a/Core/Models/User.cs b/Core/Models/User.cs index 109ea17..2cee777 100644 --- a/Core/Models/User.cs +++ b/Core/Models/User.cs @@ -110,6 +110,22 @@ int IUser.NumberOfOldPasswordToKeep } } + int IUser.NumberOfMonthActivitiesToKeep + { + get => Database.Get(NumberOfMonthActivitiesToKeep); + set + { + NumberOfMonthActivitiesToKeep = Database.AutoSave.UpdateValue(ItemId, + fieldName: nameof(NumberOfMonthActivitiesToKeep), + needsReview: true, + oldValue: NumberOfMonthActivitiesToKeep, + newValue: value, + readableValue: value.ToString()); + + Database.ActivityCenter.Save(rebuildStringActivities: true); + } + } + WarningType IUser.WarningsToNotify { get => Database.Get(WarningsToNotify); @@ -126,7 +142,7 @@ IService IUser.AddService(string serviceName) Service service = new() { User = this, - ItemId = "S" + Database.CryptographyCenter.GetHash(serviceName), + ItemId = "S" + Database.CryptographyCenter.GetHash(ItemId + serviceName), ServiceName = serviceName }; @@ -171,8 +187,9 @@ internal Database Database public int CleaningClipboardTimeout { get; set; } = 0; public int ShowPasswordDelay { get; set; } = 0; public int NumberOfOldPasswordToKeep { get; set; } = 0; + public int NumberOfMonthActivitiesToKeep { get; set; } = 0; public WarningType WarningsToNotify { get; set; } - = WarningType.LogReviewWarning + = WarningType.ActivityReviewWarning | WarningType.PasswordUpdateReminderWarning | WarningType.DuplicatedPasswordsWarning | WarningType.PasswordLeakedWarning; @@ -200,8 +217,9 @@ private void _timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e) if (SessionLeftTime == 0) { - Database.Logs.AddLog(data: [Username], - eventType: LogEventType.LoginSessionTimeoutReached, + Database.ActivityCenter.AddActivity(itemId: ItemId, + eventType: ActivityEventType.LoginSessionTimeoutReached, + data: [Username], needsReview: true); Database.Close(logCloseEvent: true, loginTimeoutReached: true); @@ -228,7 +246,7 @@ public void ResetTimer() _clipboardLeftTime = CleaningClipboardTimeout; } - public void Apply(Change change) + internal void Apply(Change change) { switch (change.ItemId[0]) { @@ -256,7 +274,7 @@ private void _apply(Change change) { switch (change.ActionType) { - case LogEventType.ItemUpdated: + case ActivityEventType.ItemUpdated: switch (change.FieldName) { case nameof(Username): @@ -280,20 +298,22 @@ private void _apply(Change change) throw new InvalidDataException("FieldName not valid"); } break; - case LogEventType.ItemAdded: + case ActivityEventType.ItemAdded: Service serviceToAdd = change.NewValue.DeserializeTo(Database.SerializationCenter); serviceToAdd.User = this; Services.Add(serviceToAdd); break; - case LogEventType.ItemDeleted: + case ActivityEventType.ItemDeleted: Service serviceToDelete = change.NewValue.DeserializeTo(Database.SerializationCenter); _ = Services.RemoveAll(x => x.ItemId == serviceToDelete.ItemId); break; default: - throw new InvalidEnumArgumentException(nameof(change.ActionType), (int)change.ActionType, typeof(LogEventType)); + throw new InvalidEnumArgumentException(nameof(change.ActionType), (int)change.ActionType, typeof(ActivityEventType)); } } public override string ToString() => $"User {Database.Username}"; + + public bool HasChanged() => Database.HasChanged(ItemId) || Services.Any(x => x.HasChanged()); } } \ No newline at end of file diff --git a/Core/Models/Warning.cs b/Core/Models/Warning.cs index 3acbe2d..10172cc 100644 --- a/Core/Models/Warning.cs +++ b/Core/Models/Warning.cs @@ -7,14 +7,14 @@ internal class Warning : IWarning { public WarningType WarningType { get; set; } - public ILog[]? Logs { get; set; } + public IActivity[]? Activities { get; set; } public IAccount[]? Accounts { get; set; } - public Warning(ILog[] logs) + public Warning(IActivity[] activities) { - WarningType = WarningType.LogReviewWarning; - Logs = logs; + WarningType = WarningType.ActivityReviewWarning; + Activities = activities; } public Warning(WarningType warningType, IAccount[] accounts) diff --git a/Core/Utils/ActivityCenter.cs b/Core/Utils/ActivityCenter.cs new file mode 100644 index 0000000..ed4e6c7 --- /dev/null +++ b/Core/Utils/ActivityCenter.cs @@ -0,0 +1,73 @@ +using Upsilon.Apps.Passkey.Core.Models; +using Upsilon.Apps.Passkey.Interfaces.Enums; +using Upsilon.Apps.Passkey.Interfaces.Models; + +namespace Upsilon.Apps.Passkey.Core.Utils +{ + internal class ActivityCenter + { + internal Database Database + { + get => field ?? throw new NullReferenceException(nameof(Database)); + set; + } + + internal List Activities = []; + + public List ActivityList { get; set; } = []; + + public string Username { get; set; } = string.Empty; + + public string PublicKey { get; set; } = string.Empty; + + internal void AddActivity(string itemId, ActivityEventType eventType, string[] data, bool needsReview) + { + Activity activity = new(DateTime.Now.Ticks, itemId, eventType, data, needsReview); + + Activities.Insert(0, activity); + ActivityList.Insert(0, Database.CryptographyCenter.EncryptAsymmetrically(activity.ToString(), PublicKey)); + + Save(rebuildStringActivities: false); + } + + internal void LoadStringActivities() + { + Activities.Clear(); + + if (Database.User is null) return; + + Activities = [.. ActivityList.AsParallel() + .Select(x => new Activity(Database.CryptographyCenter.DecryptAsymmetrically(x, Database.User.PrivateKey))) + .OrderByDescending(x => x.DateTime)]; + } + + internal void Save(bool rebuildStringActivities) + { + if (rebuildStringActivities) + { + _removeOldActivities(); + + ActivityList.Clear(); + ActivityList.AddRange(Activities + .OrderByDescending(x => x.DateTime) + .Select(x => ((Activity)x).ToString()) + .Distinct() + .Select(x => Database.CryptographyCenter.EncryptAsymmetrically(x, PublicKey))); + } + + Database.FileLocker.Save(this, Database.ActivityFileEntry); + } + + private void _removeOldActivities() + { + if (Database.User is null + || Database.User.NumberOfMonthActivitiesToKeep == 0) + { + return; + } + + DateTime limitDate = DateTime.Now.AddMonths(-Database.User.NumberOfMonthActivitiesToKeep).Date.AddDays(-DateTime.Now.Day + 1); + Activities = [.. Activities.Where(x => x.DateTime >= limitDate || x.NeedsReview)]; + } + } +} diff --git a/Core/Utils/FileLocker.cs b/Core/Utils/FileLocker.cs index d31768e..dc8b410 100644 --- a/Core/Utils/FileLocker.cs +++ b/Core/Utils/FileLocker.cs @@ -25,7 +25,7 @@ internal void Lock() { Unlock(); - _stream = new FileStream(FilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None); + _stream = new FileStream(FilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Inheritable); } internal void Unlock() @@ -165,9 +165,13 @@ private void _writeContent(string content, string fileEntry, string[] passkeys) using StreamWriter writer = new(stream, Encoding.UTF8); if (passkeys.Length != 0) + { writer.Write(_compressString(_cryptographicCenter.EncryptSymmetrically(content, passkeys))); + } else + { writer.Write(_compressString(content)); + } } Lock(); diff --git a/Core/Utils/LogCenter.cs b/Core/Utils/LogCenter.cs deleted file mode 100644 index 6990bd0..0000000 --- a/Core/Utils/LogCenter.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Upsilon.Apps.Passkey.Core.Models; -using Upsilon.Apps.Passkey.Interfaces.Enums; -using Upsilon.Apps.Passkey.Interfaces.Models; - -namespace Upsilon.Apps.Passkey.Core.Utils -{ - internal class LogCenter - { - internal Database Database - { - get => field ?? throw new NullReferenceException(nameof(Database)); - set; - } - - internal List Logs = []; - - public List LogList { get; set; } = []; - - public string Username { get; set; } = string.Empty; - - public string PublicKey { get; set; } = string.Empty; - - public void AddLog(string[] data, LogEventType eventType, bool needsReview) - { - Log log = new() - { - DateTimeTicks = DateTime.Now.Ticks, - Data = data, - EventType = eventType, - NeedsReview = needsReview, - }; - - Logs.Add(log); - LogList.Add(Database.CryptographyCenter.EncryptAsymmetrically(log.ToString(), PublicKey)); - - _save(); - } - - internal void LoadStringLogs() - { - Logs.Clear(); - - if (Database.User is null) return; - - foreach (string log in LogList) - { - Logs.Add(new Log(Database, Database.CryptographyCenter.DecryptAsymmetrically(log, Database.User.PrivateKey))); - } - } - - private void _save() - { - Database.FileLocker.Save(this, Database.LogFileEntry); - } - } -} diff --git a/Core/Utils/PasswordFactory.cs b/Core/Utils/PasswordFactory.cs index 91d6b1b..f8277cc 100644 --- a/Core/Utils/PasswordFactory.cs +++ b/Core/Utils/PasswordFactory.cs @@ -20,9 +20,11 @@ public string GeneratePassword(int length, string alphabet, bool checkIfLeaked = StringBuilder stringBuilder = new(); Random random = new((int)DateTime.Now.Ticks); + byte iteration = 0; do { + iteration++; _ = stringBuilder.Clear(); for (int i = 0; i < length; i++) @@ -30,9 +32,9 @@ public string GeneratePassword(int length, string alphabet, bool checkIfLeaked = _ = stringBuilder.Append(alphabet[random.Next(alphabet.Length)]); } } - while (checkIfLeaked && PasswordLeaked(stringBuilder.ToString())); + while (iteration < length && checkIfLeaked && PasswordLeaked(stringBuilder.ToString())); - return stringBuilder.ToString(); + return iteration == length ? string.Empty : stringBuilder.ToString(); } public bool PasswordLeaked(string password) diff --git a/Core/Utils/StaticMethods.cs b/Core/Utils/StaticMethods.cs index 57c814f..274e6ba 100644 --- a/Core/Utils/StaticMethods.cs +++ b/Core/Utils/StaticMethods.cs @@ -7,18 +7,6 @@ public static class StaticMethods { public static string ToSentenceCase(this string str) => Regex.Replace(str, "[a-z][A-Z]", m => $"{m.Value[0]} {char.ToLower(m.Value[1])}"); - public static bool ContainsFlag(this T value, T lookingForFlag) where T : Enum - { - if (!typeof(T).IsEnum) - { - throw new ArgumentException("T must be an enumerated type"); - } - - int intValue = (int)(object)value; - int intLookingForFlag = (int)(object)lookingForFlag; - return (intValue & intLookingForFlag) == intLookingForFlag; - } - public static string SerializeWith(this T obj, ISerializationCenter serializationCenter) where T : notnull => serializationCenter.Serialize(obj); diff --git a/Interfaces/Enums/AccountOption.cs b/Interfaces/Enums/AccountOption.cs index 0677387..df3deb6 100644 --- a/Interfaces/Enums/AccountOption.cs +++ b/Interfaces/Enums/AccountOption.cs @@ -13,6 +13,10 @@ public enum AccountOption /// /// Warn if the password leaked. /// - WarnIfPasswordLeaked = 0b0010, + WarnIfPasswordLeaked = 0b0001, + /// + /// Warn if the password is same as another account's password. + /// + WarnIfDuplicatedPassword = 0b0010, } } \ No newline at end of file diff --git a/Interfaces/Enums/LogEventType.cs b/Interfaces/Enums/ActivityEventType.cs similarity index 98% rename from Interfaces/Enums/LogEventType.cs rename to Interfaces/Enums/ActivityEventType.cs index 4f0f4df..53ac8d2 100644 --- a/Interfaces/Enums/LogEventType.cs +++ b/Interfaces/Enums/ActivityEventType.cs @@ -3,7 +3,7 @@ /// /// Represent the event type. /// - public enum LogEventType + public enum ActivityEventType { /// /// No event type. diff --git a/Interfaces/Enums/WarningType.cs b/Interfaces/Enums/WarningType.cs index 587de34..2bfbc2c 100644 --- a/Interfaces/Enums/WarningType.cs +++ b/Interfaces/Enums/WarningType.cs @@ -7,11 +7,11 @@ public enum WarningType { /// - /// A set of logs needs to be reviewed. + /// A set of activities needs to be reviewed. /// - LogReviewWarning = 0b0001, + ActivityReviewWarning = 0b0001, /// - /// A set of accounts password expired and need to be updated. + /// A set of accounts password expired. /// PasswordUpdateReminderWarning = 0b0010, /// @@ -19,7 +19,7 @@ public enum WarningType /// DuplicatedPasswordsWarning = 0b0100, /// - /// Some passwords leaked and found on the ';--have i been pwned? database + /// Some passwords leaked. /// PasswordLeakedWarning = 0b1000, } diff --git a/Interfaces/Interfaces.cd b/Interfaces/Interfaces.cd deleted file mode 100644 index acb986d..0000000 --- a/Interfaces/Interfaces.cd +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - AAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAA= - Events\AutoSaveDetectedEventArgs.cs - - - - - - - - - AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Events\WarningDetectedEventArgs.cs - - - - - - AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Events\LogoutEventArgs.cs - - - - - - AAAgAAAAEAAAAAAAAAAAAAAAAAAAQAACAAAAAAJAAAA= - IAccount.cs - - - - - - - - - - AAACAAAAAAAAABAAAMAAAAAAAAAAAAASAAAAAABABAE= - ICryptographyCenter.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - AgABAIgQAAAAgAAAYAAACCAggAGEAQAAEAARAACABAA= - IDatabase.cs - - - - - - - - - - - - - - - - - AAAAAAAAAEAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAA= - IItem.cs - - - - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAIAIAAAAAA= - ILog.cs - - - - - - AAAAAAAAAAAAAAAAAAAAAAAAACBAAAAAAAAAAAAAAAA= - ISerializationCenter.cs - - - - - - AAAhAAAAAAAAAAAAAAAAAAAAAAAAAACACAACAQAABAA= - IService.cs - - - - - - - - - - - - gABAAAEAAAAAAAAAAQAAAAAAAAAACAAIAAkAECAAAAA= - IUser.cs - - - - - - - - - - - - - - - - - AAAAAAAQgAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAA= - IWarning.cs - - - - - - - - - - - - - AAAAAQAAAAAAAAAAAAAAAAACAAAAAAQAgABAAAAAAAA= - IPasswordFactory.cs - - - - - - AAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - IClipboardManager.cs - - - - - - AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAA= - Enums\AccountOption.cs - - - - - - AAAAQAAAAABgAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= - Enums\WarningType.cs - - - - - - AAAAIBAgAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAA= - Enums\AutoSaveMergeBehavior.cs - - - - \ No newline at end of file diff --git a/Interfaces/Models/ILog.cs b/Interfaces/Models/IActivity.cs similarity index 77% rename from Interfaces/Models/ILog.cs rename to Interfaces/Models/IActivity.cs index 99ec7e1..a255e2d 100644 --- a/Interfaces/Models/ILog.cs +++ b/Interfaces/Models/IActivity.cs @@ -3,9 +3,9 @@ namespace Upsilon.Apps.Passkey.Interfaces.Models { /// - /// Represent an event log. + /// Represent an event activity. /// - public interface ILog + public interface IActivity { /// /// The date and time the event occured. @@ -13,19 +13,19 @@ public interface ILog DateTime DateTime { get; } /// - /// The event type. + /// The item id rizing the event. /// - LogEventType EventType { get; } + string ItemId { get; } /// - /// Indicate if the current log needs review. + /// The event type. /// - bool NeedsReview { get; set; } + ActivityEventType EventType { get; } /// - /// The raw event data. + /// Indicate if the current log needs review. /// - string[] Data { get; } + bool NeedsReview { get; set; } /// /// The event message. diff --git a/Interfaces/Models/IDatabase.cs b/Interfaces/Models/IDatabase.cs index 7e8d627..1f5687d 100644 --- a/Interfaces/Models/IDatabase.cs +++ b/Interfaces/Models/IDatabase.cs @@ -24,9 +24,9 @@ public interface IDatabase : IDisposable int? SessionLeftTime { get; } /// - /// The logs. + /// The activities. /// - ILog[]? Logs { get; } + IActivity[]? Activities { get; } /// /// The warnings detected. @@ -97,12 +97,6 @@ public interface IDatabase : IDisposable /// void Close(); - /// - /// Check if the database has changed. - /// - /// True if the database changed, False else. - bool HasChanged(); - /// /// Check if the given item has changed. /// diff --git a/Interfaces/Models/IItem.cs b/Interfaces/Models/IItem.cs index 9e03bf9..dbd7ba9 100644 --- a/Interfaces/Models/IItem.cs +++ b/Interfaces/Models/IItem.cs @@ -14,5 +14,11 @@ public interface IItem /// The database that contains the item. /// IDatabase Database { get; } + + /// + /// Check if the current item has changed. + /// + /// True if the current item has changed, False else. + bool HasChanged(); } } diff --git a/Interfaces/Models/IUser.cs b/Interfaces/Models/IUser.cs index dd4263a..7117686 100644 --- a/Interfaces/Models/IUser.cs +++ b/Interfaces/Models/IUser.cs @@ -37,6 +37,11 @@ public interface IUser : IItem /// int NumberOfOldPasswordToKeep { get; set; } + /// + /// The number of months activities to keep. + /// + int NumberOfMonthActivitiesToKeep { get; set; } + /// /// The warnings types which will be notified if detected. /// diff --git a/Interfaces/Models/IWarning.cs b/Interfaces/Models/IWarning.cs index 0b512bb..e454b9d 100644 --- a/Interfaces/Models/IWarning.cs +++ b/Interfaces/Models/IWarning.cs @@ -13,9 +13,9 @@ public interface IWarning WarningType WarningType { get; } /// - /// The logs concerned to the warning, if exists. + /// The activities concerned to the warning, if exists. /// - ILog[]? Logs { get; } + IActivity[]? Activities { get; } /// /// The accounts concerned to the warning, if exists. diff --git a/Interfaces/Utils/StaticMethods.cs b/Interfaces/Utils/StaticMethods.cs index 11d4d8c..36348c0 100644 --- a/Interfaces/Utils/StaticMethods.cs +++ b/Interfaces/Utils/StaticMethods.cs @@ -4,11 +4,6 @@ namespace Upsilon.Apps.Passkey.Interfaces.Utils { public static class StaticMethods { - public static bool HasChanged(this IItem item) - { - return item.Database.HasChanged(item.ItemId); - } - public static bool HasChanged(this IItem item, string fieldName) { return item.Database.HasChanged(item.ItemId, fieldName); diff --git a/README.md b/README.md index 2b68428..32aabe0 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ classDiagram <> +ItemId : string +Database : IDatabase + +HasChanged(void) bool } class IAccount { @@ -136,7 +137,6 @@ classDiagram +Save(void) void +Delete(void) void +Close(void) void - +HasChanged(void) bool +HasChanged(in itemId string) bool +HasChanged(in itemId string, in fieldName string) bool +ImportFromFile(in filePath string) bool @@ -146,6 +146,7 @@ classDiagram class ILog { <> +DateTime : DateTime + +ItemId : string +Message : string +NeedsReview : bool } @@ -164,6 +165,7 @@ classDiagram <> None WarnIfPasswordLeaked + WarnIfDuplicatedPassword } class WarningType { diff --git a/UnitTests/Models/AccountUnitTests.cs b/UnitTests/Models/AccountUnitTests.cs index 6fed204..00e8823 100644 --- a/UnitTests/Models/AccountUnitTests.cs +++ b/UnitTests/Models/AccountUnitTests.cs @@ -32,14 +32,14 @@ public void Case01_AddAccountUpdateSaved() string notes = UnitTestsHelper.GetRandomString(); int passwordUpdateReminderDelay = UnitTestsHelper.GetRandomInt(12); AccountOption options = AccountOption.None; - Stack expectedLogs = new(); + Stack expectedActivities = new(); Stack expectedLogWarnings = new(); // When IAccount account = service.AddAccount(oldAccountLabel, oldIdentifiers, oldPassword); - expectedLogs.Push($"Information : {account} has been added to Service {service.ServiceName}"); - expectedLogs.Push($"Warning : {account}'s password has been updated"); - expectedLogWarnings.Push($"Warning : {account}'s password has been updated"); + expectedActivities.Push($"Information : {account} has been added to Service {service.ServiceName}"); + expectedActivities.Push($"Warning : {service}'s {account}'s password has been updated"); + expectedLogWarnings.Push($"Warning : {service}'s {account}'s password has been updated"); // Then databaseCreated.User.HasChanged().Should().BeTrue(); @@ -54,23 +54,23 @@ public void Case01_AddAccountUpdateSaved() // When account.Label = newAccountLabel; account.Label = newAccountLabel; - expectedLogs.Push($"Information : Account {oldAccountLabel} ({string.Join(", ", oldIdentifiers)})'s label has been set to {newAccountLabel}"); + expectedActivities.Push($"Information : {service}'s Account {oldAccountLabel} ({string.Join(", ", oldIdentifiers)})'s label has been set to {newAccountLabel}"); account.Identifiers = newIdentifiers; account.Identifiers = newIdentifiers; - expectedLogs.Push($"Warning : Account {newAccountLabel} ({string.Join(", ", oldIdentifiers)})'s identifiers has been set to ({string.Join(", ", newIdentifiers)})"); - expectedLogWarnings.Push($"Warning : Account {newAccountLabel} ({string.Join(", ", oldIdentifiers)})'s identifiers has been set to ({string.Join(", ", newIdentifiers)})"); + expectedActivities.Push($"Warning : {service}'s Account {newAccountLabel} ({string.Join(", ", oldIdentifiers)})'s identifiers has been set to ({string.Join(", ", newIdentifiers)})"); + expectedLogWarnings.Push($"Warning : {service}'s Account {newAccountLabel} ({string.Join(", ", oldIdentifiers)})'s identifiers has been set to ({string.Join(", ", newIdentifiers)})"); account.Password = newPassword; account.Password = newPassword; - expectedLogs.Push($"Warning : {account}'s password has been updated"); - expectedLogWarnings.Push($"Warning : {account}'s password has been updated"); + expectedActivities.Push($"Warning : {service}'s {account}'s password has been updated"); + expectedLogWarnings.Push($"Warning : {service}'s {account}'s password has been updated"); account.Notes = notes; account.Notes = notes; - expectedLogs.Push($"Information : {account}'s notes has been set to {notes}"); + expectedActivities.Push($"Information : {service}'s {account}'s notes has been set to {notes}"); account.PasswordUpdateReminderDelay = passwordUpdateReminderDelay; - expectedLogs.Push($"Information : {account}'s password update reminder delay has been set to {passwordUpdateReminderDelay}"); + expectedActivities.Push($"Information : {service}'s {account}'s password update reminder delay has been set to {passwordUpdateReminderDelay}"); account.Options = options; account.Options = options; - expectedLogs.Push($"Information : {account}'s options has been set to {options}"); + expectedActivities.Push($"Information : {service}'s {account}'s options has been set to {options}"); // Then databaseCreated.User.HasChanged().Should().BeTrue(); @@ -86,14 +86,14 @@ public void Case01_AddAccountUpdateSaved() // When databaseCreated.Save(); - expectedLogs.Push($"Information : User {username}'s database saved"); + expectedActivities.Push($"Information : User {username}'s database saved"); databaseCreated.Close(); - expectedLogs.Push($"Information : User {username} logged out"); - expectedLogs.Push($"Information : User {username}'s database closed"); + expectedActivities.Push($"Information : User {username} logged out"); + expectedActivities.Push($"Information : User {username}'s database closed"); IDatabase databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _); - expectedLogs.Push($"Information : User {username}'s database opened"); - expectedLogs.Push($"Information : User {username} logged in"); + expectedActivities.Push($"Information : User {username}'s database opened"); + expectedActivities.Push($"Information : User {username} logged in"); IService serviceLoaded = databaseLoaded.User.Services.First(); // Then @@ -111,8 +111,8 @@ public void Case01_AddAccountUpdateSaved() _ = account.PasswordUpdateReminderDelay.Should().Be(passwordUpdateReminderDelay); _ = account.Options.Should().Be(options); - UnitTestsHelper.LastLogsShouldMatch(databaseLoaded, [.. expectedLogs]); - UnitTestsHelper.LastLogWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); + UnitTestsHelper.LastActivitiesShouldMatch(databaseLoaded, [.. expectedActivities]); + UnitTestsHelper.LastActivityWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); // Finaly databaseLoaded.Close(); @@ -142,14 +142,14 @@ public void Case02_AddAccountUpdateAutoSave() string notes = UnitTestsHelper.GetRandomString(); int passwordUpdateReminderDelay = UnitTestsHelper.GetRandomInt(12); AccountOption options = AccountOption.None; - Stack expectedLogs = new(); + Stack expectedActivities = new(); Stack expectedLogWarnings = new(); // When IAccount account = service.AddAccount(oldAccountLabel, oldIdentifiers, oldPassword); - expectedLogs.Push($"Information : {account} has been added to Service {service.ServiceName}"); - expectedLogs.Push($"Warning : {account}'s password has been updated"); - expectedLogWarnings.Push($"Warning : {account}'s password has been updated"); + expectedActivities.Push($"Information : {account} has been added to Service {service.ServiceName}"); + expectedActivities.Push($"Warning : {service}'s {account}'s password has been updated"); + expectedLogWarnings.Push($"Warning : {service}'s {account}'s password has been updated"); // Then _ = service.Accounts.Length.Should().Be(1); @@ -161,33 +161,33 @@ public void Case02_AddAccountUpdateAutoSave() // When account.Label = newAccountLabel; account.Label = newAccountLabel; - expectedLogs.Push($"Information : Account {oldAccountLabel} ({string.Join(", ", oldIdentifiers)})'s label has been set to {newAccountLabel}"); + expectedActivities.Push($"Information : {service}'s Account {oldAccountLabel} ({string.Join(", ", oldIdentifiers)})'s label has been set to {newAccountLabel}"); account.Identifiers = newIdentifiers; account.Identifiers = newIdentifiers; - expectedLogs.Push($"Warning : Account {newAccountLabel} ({string.Join(", ", oldIdentifiers)})'s identifiers has been set to ({string.Join(", ", newIdentifiers)})"); - expectedLogWarnings.Push($"Warning : Account {newAccountLabel} ({string.Join(", ", oldIdentifiers)})'s identifiers has been set to ({string.Join(", ", newIdentifiers)})"); + expectedActivities.Push($"Warning : {service}'s Account {newAccountLabel} ({string.Join(", ", oldIdentifiers)})'s identifiers has been set to ({string.Join(", ", newIdentifiers)})"); + expectedLogWarnings.Push($"Warning : {service}'s Account {newAccountLabel} ({string.Join(", ", oldIdentifiers)})'s identifiers has been set to ({string.Join(", ", newIdentifiers)})"); account.Password = newPassword; account.Password = newPassword; - expectedLogs.Push($"Warning : {account}'s password has been updated"); - expectedLogWarnings.Push($"Warning : {account}'s password has been updated"); + expectedActivities.Push($"Warning : {service}'s {account}'s password has been updated"); + expectedLogWarnings.Push($"Warning : {service}'s {account}'s password has been updated"); account.Notes = notes; account.Notes = notes; - expectedLogs.Push($"Information : {account}'s notes has been set to {notes}"); + expectedActivities.Push($"Information : {service}'s {account}'s notes has been set to {notes}"); account.PasswordUpdateReminderDelay = passwordUpdateReminderDelay; - expectedLogs.Push($"Information : {account}'s password update reminder delay has been set to {passwordUpdateReminderDelay}"); + expectedActivities.Push($"Information : {service}'s {account}'s password update reminder delay has been set to {passwordUpdateReminderDelay}"); account.Options = options; account.Options = options; - expectedLogs.Push($"Information : {account}'s options has been set to {options}"); + expectedActivities.Push($"Information : {service}'s {account}'s options has been set to {options}"); databaseCreated.Close(); - expectedLogs.Push($"Warning : User {username} logged out without saving"); + expectedActivities.Push($"Warning : User {username} logged out without saving"); expectedLogWarnings.Push($"Warning : User {username} logged out without saving"); - expectedLogs.Push($"Information : User {username}'s database closed"); + expectedActivities.Push($"Information : User {username}'s database closed"); IDatabase databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _, AutoSaveMergeBehavior.MergeAndSaveThenRemoveAutoSaveFile); - expectedLogs.Push($"Information : User {username}'s database opened"); - expectedLogs.Push($"Information : User {username} logged in"); - expectedLogs.Push($"Warning : User {username}'s autosave merged and saved"); + expectedActivities.Push($"Information : User {username}'s database opened"); + expectedActivities.Push($"Information : User {username} logged in"); + expectedActivities.Push($"Warning : User {username}'s autosave merged and saved"); expectedLogWarnings.Push($"Warning : User {username}'s autosave merged and saved"); IService serviceLoaded = databaseLoaded.User.Services.First(); @@ -206,8 +206,8 @@ public void Case02_AddAccountUpdateAutoSave() _ = account.PasswordUpdateReminderDelay.Should().Be(passwordUpdateReminderDelay); _ = account.Options.Should().Be(options); - UnitTestsHelper.LastLogsShouldMatch(databaseLoaded, [.. expectedLogs]); - UnitTestsHelper.LastLogWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); + UnitTestsHelper.LastActivitiesShouldMatch(databaseLoaded, [.. expectedActivities]); + UnitTestsHelper.LastActivityWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); // Finaly databaseLoaded.Close(); @@ -233,7 +233,7 @@ public void Case03_DeleteAccountUpdateSaved() _ = service.AddAccount(accountLabel, identifiers, password); databaseCreated.Save(); databaseCreated.Close(); - Stack expectedLogs = new(); + Stack expectedActivities = new(); Stack expectedLogWarnings = new(); IDatabase databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _); @@ -242,7 +242,7 @@ public void Case03_DeleteAccountUpdateSaved() // When serviceLoaded.DeleteAccount(accountLoaded); - expectedLogs.Push($"Warning : Account {accountLabel} ({string.Join(", ", identifiers)}) has been removed from Service {service.ServiceName}"); + expectedActivities.Push($"Warning : Account {accountLabel} ({string.Join(", ", identifiers)}) has been removed from Service {service.ServiceName}"); expectedLogWarnings.Push($"Warning : Account {accountLabel} ({string.Join(", ", identifiers)}) has been removed from Service {service.ServiceName}"); // Then @@ -250,22 +250,22 @@ public void Case03_DeleteAccountUpdateSaved() // When databaseLoaded.Save(); - expectedLogs.Push($"Information : User {username}'s database saved"); + expectedActivities.Push($"Information : User {username}'s database saved"); databaseLoaded.Close(); - expectedLogs.Push($"Information : User {username} logged out"); - expectedLogs.Push($"Information : User {username}'s database closed"); + expectedActivities.Push($"Information : User {username} logged out"); + expectedActivities.Push($"Information : User {username}'s database closed"); databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _); - expectedLogs.Push($"Information : User {username}'s database opened"); - expectedLogs.Push($"Information : User {username} logged in"); + expectedActivities.Push($"Information : User {username}'s database opened"); + expectedActivities.Push($"Information : User {username} logged in"); serviceLoaded = databaseLoaded.User.Services.First(); // Then _ = serviceLoaded.Accounts.Length.Should().Be(0); - UnitTestsHelper.LastLogsShouldMatch(databaseLoaded, [.. expectedLogs]); - UnitTestsHelper.LastLogWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); + UnitTestsHelper.LastActivitiesShouldMatch(databaseLoaded, [.. expectedActivities]); + UnitTestsHelper.LastActivityWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); // Finaly databaseLoaded.Close(); @@ -291,7 +291,7 @@ public void Case04_DeleteAccountUpdateAutoSave() _ = service.AddAccount(accountLabel, identifiers, password); databaseCreated.Save(); databaseCreated.Close(); - Stack expectedLogs = new(); + Stack expectedActivities = new(); Stack expectedLogWarnings = new(); IDatabase databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _); @@ -300,7 +300,7 @@ public void Case04_DeleteAccountUpdateAutoSave() // When serviceLoaded.DeleteAccount(accountLoaded); - expectedLogs.Push($"Warning : Account {accountLabel} ({string.Join(", ", identifiers)}) has been removed from Service {service.ServiceName}"); + expectedActivities.Push($"Warning : Account {accountLabel} ({string.Join(", ", identifiers)}) has been removed from Service {service.ServiceName}"); expectedLogWarnings.Push($"Warning : Account {accountLabel} ({string.Join(", ", identifiers)}) has been removed from Service {service.ServiceName}"); // Then @@ -308,14 +308,14 @@ public void Case04_DeleteAccountUpdateAutoSave() // When databaseLoaded.Close(); - expectedLogs.Push($"Warning : User {username} logged out without saving"); + expectedActivities.Push($"Warning : User {username} logged out without saving"); expectedLogWarnings.Push($"Warning : User {username} logged out without saving"); - expectedLogs.Push($"Information : User {username}'s database closed"); + expectedActivities.Push($"Information : User {username}'s database closed"); databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _, AutoSaveMergeBehavior.MergeAndSaveThenRemoveAutoSaveFile); - expectedLogs.Push($"Information : User {username}'s database opened"); - expectedLogs.Push($"Information : User {username} logged in"); - expectedLogs.Push($"Warning : User {username}'s autosave merged and saved"); + expectedActivities.Push($"Information : User {username}'s database opened"); + expectedActivities.Push($"Information : User {username} logged in"); + expectedActivities.Push($"Warning : User {username}'s autosave merged and saved"); expectedLogWarnings.Push($"Warning : User {username}'s autosave merged and saved"); serviceLoaded = databaseLoaded.User.Services.First(); @@ -323,8 +323,8 @@ public void Case04_DeleteAccountUpdateAutoSave() // Then _ = serviceLoaded.Accounts.Length.Should().Be(0); - UnitTestsHelper.LastLogsShouldMatch(databaseLoaded, [.. expectedLogs]); - UnitTestsHelper.LastLogWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); + UnitTestsHelper.LastActivitiesShouldMatch(databaseLoaded, [.. expectedActivities]); + UnitTestsHelper.LastActivityWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); // Finaly databaseLoaded.Close(); diff --git a/UnitTests/Models/DatabaseUnitTests.cs b/UnitTests/Models/DatabaseUnitTests.cs index 2946eb8..1dee623 100644 --- a/UnitTests/Models/DatabaseUnitTests.cs +++ b/UnitTests/Models/DatabaseUnitTests.cs @@ -12,13 +12,15 @@ public sealed class DatabaseUnitTests [TestMethod, Ignore] public void Case00_GenerateNewDatabase() { - IDatabase database = UnitTestsHelper.CreateTestDatabase(["a", "b"], "_"); + UnitTestsHelper.ClearTestEnvironment("_"); + + IDatabase database = UnitTestsHelper.CreateTestDatabase(["a", "b", "c"], "_"); IUser user = database.User; user.LogoutTimeout = 10; user.CleaningClipboardTimeout = 15; user.WarningsToNotify = (WarningType)0; - for (int i = 0; i < 50; i++) + for (int i = 0; i < 100; i++) { IService service = user.AddService($"Service{i} ({UnitTestsHelper.GetRandomString(min: 10, max: 15)})"); service.Url = $"www.service{i}.xyz"; @@ -32,6 +34,7 @@ public void Case00_GenerateNewDatabase() random = UnitTestsHelper.GetRandomInt(10) + 1; IAccount account; + string password = UnitTestsHelper.GetRandomString(min: 20, max: 25); switch (random % 4) { case 1: @@ -40,7 +43,7 @@ public void Case00_GenerateNewDatabase() break; case 2: account = service.AddAccount(identifiers: UnitTestsHelper.GetRandomStringArray(random / 2).Select(x => x + "@test.te"), - password: UnitTestsHelper.GetRandomString(min: 20, max: 25)); + password: password); break; case 3: account = service.AddAccount(identifiers: UnitTestsHelper.GetRandomStringArray(random / 2).Select(x => x + "@test.te")); @@ -48,14 +51,14 @@ public void Case00_GenerateNewDatabase() default: account = service.AddAccount(label: $"Account{j}", identifiers: UnitTestsHelper.GetRandomStringArray(random / 2).Select(x => x + "@test.te"), - password: UnitTestsHelper.GetRandomString(min: 20, max: 25)); + password: password); break; } random = UnitTestsHelper.GetRandomInt(100); account.Notes = random % 10 == 0 ? $"Service{i}'s Account{j} notes : \n{UnitTestsHelper.GetRandomString(min: 10, max: 150)}" : ""; account.PasswordUpdateReminderDelay = random < 10 ? random : 0; - account.Options = random % 2 == 0 ? AccountOption.WarnIfPasswordLeaked : AccountOption.None; + account.Options = (!string.IsNullOrEmpty(account.Password) && random % 2 == 0) ? AccountOption.WarnIfPasswordLeaked : AccountOption.None; } } @@ -76,13 +79,13 @@ public void Case01_DatabaseCreationOpenDelete() string username = UnitTestsHelper.GetUsername(); string[] passkeys = UnitTestsHelper.GetRandomStringArray(); string databaseFile = UnitTestsHelper.ComputeDatabaseFilePath(); - Stack expectedLogs = new(); + Stack expectedActivities = new(); UnitTestsHelper.ClearTestEnvironment(); // When IDatabase databaseCreated = UnitTestsHelper.CreateTestDatabase(passkeys); - expectedLogs.Push($"Information : {databaseCreated.User}'s database created"); + expectedActivities.Push($"Information : {databaseCreated.User}'s database created"); // Then _ = databaseCreated.DatabaseFile.Should().Be(databaseFile); @@ -96,8 +99,8 @@ public void Case01_DatabaseCreationOpenDelete() // When databaseCreated.Close(); - expectedLogs.Push($"Information : User {username} logged out"); - expectedLogs.Push($"Information : User {username}'s database closed"); + expectedActivities.Push($"Information : User {username} logged out"); + expectedActivities.Push($"Information : User {username}'s database closed"); // Then _ = databaseCreated.User.Should().BeNull(); @@ -105,8 +108,8 @@ public void Case01_DatabaseCreationOpenDelete() // When IDatabase databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _); - expectedLogs.Push($"Information : {databaseLoaded.User}'s database opened"); - expectedLogs.Push($"Information : {databaseLoaded.User} logged in"); + expectedActivities.Push($"Information : {databaseLoaded.User}'s database opened"); + expectedActivities.Push($"Information : {databaseLoaded.User} logged in"); // Then _ = databaseLoaded.Should().NotBeNull(); @@ -119,7 +122,7 @@ public void Case01_DatabaseCreationOpenDelete() _ = databaseLoaded.User.LogoutTimeout.Should().Be(0); _ = databaseLoaded.User.CleaningClipboardTimeout.Should().Be(0); - UnitTestsHelper.LastLogsShouldMatch(databaseLoaded, [.. expectedLogs]); + UnitTestsHelper.LastActivitiesShouldMatch(databaseLoaded, [.. expectedActivities]); // When databaseLoaded.Delete(); @@ -243,7 +246,7 @@ public void Case04_DatabaseOpenButWrongPasskeysProvided() string[] wrongPasskeys = [.. passkeys]; int wrongKeyIndex = UnitTestsHelper.GetRandomInt(passkeys.Length); wrongPasskeys[wrongKeyIndex] = UnitTestsHelper.GetRandomString(); - Stack expectedLogs = new(); + Stack expectedActivities = new(); Stack expectedLogWarnings = new(); UnitTestsHelper.ClearTestEnvironment(); @@ -252,10 +255,10 @@ public void Case04_DatabaseOpenButWrongPasskeysProvided() // When IDatabase databaseLoaded = UnitTestsHelper.OpenTestDatabase(wrongPasskeys, out _); - expectedLogs.Push($"Information : User {username}'s database opened"); + expectedActivities.Push($"Information : User {username}'s database opened"); for (int i = wrongKeyIndex; i < wrongPasskeys.Length; i++) { - expectedLogs.Push($"Warning : User {username} login failed at level {wrongKeyIndex + 1}"); + expectedActivities.Push($"Warning : User {username} login failed at level {wrongKeyIndex + 1}"); expectedLogWarnings.Push($"Warning : User {username} login failed at level {wrongKeyIndex + 1}"); } @@ -264,14 +267,14 @@ public void Case04_DatabaseOpenButWrongPasskeysProvided() // When databaseLoaded.Close(); - expectedLogs.Push($"Information : User {username}'s database closed"); + expectedActivities.Push($"Information : User {username}'s database closed"); databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _); - expectedLogs.Push($"Information : User {username}'s database opened"); - expectedLogs.Push($"Information : User {username} logged in"); + expectedActivities.Push($"Information : User {username}'s database opened"); + expectedActivities.Push($"Information : User {username} logged in"); // Then - UnitTestsHelper.LastLogsShouldMatch(databaseLoaded, [.. expectedLogs]); - UnitTestsHelper.LastLogWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); + UnitTestsHelper.LastActivitiesShouldMatch(databaseLoaded, [.. expectedActivities]); + UnitTestsHelper.LastActivityWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); // Finaly databaseLoaded.Close(); @@ -289,7 +292,7 @@ public void Case05_DatabaseAutoLogout() string username = UnitTestsHelper.GetUsername(); string[] passkeys = UnitTestsHelper.GetRandomStringArray(); bool closedDueToTimeout = false; - Stack expectedLogs = new(); + Stack expectedActivities = new(); Stack expectedLogWarnings = new(); UnitTestsHelper.ClearTestEnvironment(); @@ -320,7 +323,7 @@ public void Case05_DatabaseAutoLogout() database = UnitTestsHelper.OpenTestDatabase(passkeys, out _); // Then - _ = database.Logs.FirstOrDefault(x => x.Message == $"User {username}'s login session timeout reached" && x.NeedsReview).Should().NotBeNull(); + _ = database.Activities.FirstOrDefault(x => x.Message == $"User {username}'s login session timeout reached" && x.NeedsReview).Should().NotBeNull(); // Finaly database.Close(); diff --git a/UnitTests/Models/ImportExportUnitTests.cs b/UnitTests/Models/ImportExportUnitTests.cs index fd3b981..2bdce14 100644 --- a/UnitTests/Models/ImportExportUnitTests.cs +++ b/UnitTests/Models/ImportExportUnitTests.cs @@ -24,19 +24,18 @@ public void Case01_Import_MissingFile() string[] passkeys = UnitTestsHelper.GetRandomStringArray(); string importFile = UnitTestsHelper.GetTestFilePath("missing_import.csv"); IDatabase database = UnitTestsHelper.CreateTestDatabase(passkeys); - Stack expectedLogs = new(); + Stack expectedActivities = new(); // When database.ImportFromFile(importFile); - expectedLogs.Push($"Information : User {username}'s database saved"); - expectedLogs.Push($"Warning : Importing data from file : '{importFile}'"); - expectedLogs.Push($"Warning : Import failed because import file is not accessible"); + expectedActivities.Push($"Warning : Importing data from file : '{importFile}'"); + expectedActivities.Push($"Warning : Import failed because import file is not accessible"); // Then database.User.Services.Should().BeEmpty(); - UnitTestsHelper.LastLogsShouldMatch(database, [.. expectedLogs]); + UnitTestsHelper.LastActivitiesShouldMatch(database, [.. expectedActivities]); // Finaly database.Close(); @@ -53,19 +52,18 @@ public void Case02_Import_WrongExtention() string[] passkeys = UnitTestsHelper.GetRandomStringArray(); string importFile = UnitTestsHelper.GetTestFilePath($"{username}/import.txt", createIfNotExists: true); IDatabase database = UnitTestsHelper.CreateTestDatabase(passkeys); - Stack expectedLogs = new(); + Stack expectedActivities = new(); // When database.ImportFromFile(importFile); - expectedLogs.Push($"Information : User {username}'s database saved"); - expectedLogs.Push($"Warning : Importing data from file : '{importFile}'"); - expectedLogs.Push($"Warning : Import failed because '.txt' extention type is not handled"); + expectedActivities.Push($"Warning : Importing data from file : '{importFile}'"); + expectedActivities.Push($"Warning : Import failed because '.txt' extention type is not handled"); // Then database.User.Services.Should().BeEmpty(); - UnitTestsHelper.LastLogsShouldMatch(database, [.. expectedLogs]); + UnitTestsHelper.LastActivitiesShouldMatch(database, [.. expectedActivities]); // Finaly database.Close(); @@ -82,19 +80,18 @@ public void Case03_Import_NoData() string[] passkeys = UnitTestsHelper.GetRandomStringArray(); string importFile = UnitTestsHelper.GetTestFilePath($"import_noData.csv"); IDatabase database = UnitTestsHelper.CreateTestDatabase(passkeys); - Stack expectedLogs = new(); + Stack expectedActivities = new(); // When database.ImportFromFile(importFile); - expectedLogs.Push($"Information : User {username}'s database saved"); - expectedLogs.Push($"Warning : Importing data from file : '{importFile}'"); - expectedLogs.Push($"Warning : Import failed because there is no data to import"); + expectedActivities.Push($"Warning : Importing data from file : '{importFile}'"); + expectedActivities.Push($"Warning : Import failed because there is no data to import"); // Then database.User.Services.Should().BeEmpty(); - UnitTestsHelper.LastLogsShouldMatch(database, [.. expectedLogs]); + UnitTestsHelper.LastActivitiesShouldMatch(database, [.. expectedActivities]); // Finaly database.Close(); @@ -111,21 +108,21 @@ public void Case04_Import_ServiceAlreadyExists() string[] passkeys = UnitTestsHelper.GetRandomStringArray(); string importFile = UnitTestsHelper.GetTestFilePath($"import.csv"); IDatabase database = UnitTestsHelper.CreateTestDatabase(passkeys); - Stack expectedLogs = new(); + Stack expectedActivities = new(); database.User.AddService("Service1"); // When database.ImportFromFile(importFile); - expectedLogs.Push($"Information : User {username}'s database saved"); - expectedLogs.Push($"Warning : Importing data from file : '{importFile}'"); - expectedLogs.Push($"Warning : Import failed because service 'Service1' already exists"); + expectedActivities.Push($"Information : User {username}'s database saved"); + expectedActivities.Push($"Warning : Importing data from file : '{importFile}'"); + expectedActivities.Push($"Warning : Import failed because service 'Service1' already exists"); // Then database.User.Services.Length.Should().Be(1); database.User.Services[0].Url.Should().BeEmpty(); - UnitTestsHelper.LastLogsShouldMatch(database, [.. expectedLogs]); + UnitTestsHelper.LastActivitiesShouldMatch(database, [.. expectedActivities]); // Finaly database.Close(); @@ -142,19 +139,18 @@ public void Case05_ImportBlanckService() string[] passkeys = UnitTestsHelper.GetRandomStringArray(); string importFile = UnitTestsHelper.GetTestFilePath($"import_blanckService.csv"); IDatabase database = UnitTestsHelper.CreateTestDatabase(passkeys); - Stack expectedLogs = new(); + Stack expectedActivities = new(); // When database.ImportFromFile(importFile); - expectedLogs.Push($"Information : User {username}'s database saved"); - expectedLogs.Push($"Warning : Importing data from file : '{importFile}'"); - expectedLogs.Push($"Warning : Import failed because service name cannot be blank"); + expectedActivities.Push($"Warning : Importing data from file : '{importFile}'"); + expectedActivities.Push($"Warning : Import failed because service name cannot be blank"); // Then database.User.Services.Should().BeEmpty(); - UnitTestsHelper.LastLogsShouldMatch(database, [.. expectedLogs]); + UnitTestsHelper.LastActivitiesShouldMatch(database, [.. expectedActivities]); // Finaly database.Close(); @@ -172,48 +168,47 @@ public void Case06_ImportCSV_OK() string importFile = UnitTestsHelper.GetTestFilePath("import.csv"); string exportFile = UnitTestsHelper.GetTestFilePath($"{username}/export.csv"); IDatabase database = UnitTestsHelper.CreateTestDatabase(passkeys); - Stack expectedLogs = new(); + Stack expectedActivities = new(); // When database.ImportFromFile(importFile); - expectedLogs.Push($"Information : User {username}'s database saved"); - expectedLogs.Push($"Warning : Importing data from file : '{importFile}'"); + expectedActivities.Push($"Warning : Importing data from file : '{importFile}'"); - expectedLogs.Push($"Information : Service Service0 has been added to User {username}"); - expectedLogs.Push($"Information : Service Service0's url has been set to www.service0.xyz"); - expectedLogs.Push($"Information : Service Service0's notes has been set to Service0's notes"); + expectedActivities.Push($"Information : Service Service0 has been added to User {username}"); + expectedActivities.Push($"Information : Service Service0's url has been set to www.service0.xyz"); + expectedActivities.Push($"Information : Service Service0's notes has been set to Service0's notes"); - expectedLogs.Push($"Information : Account Account0 (account0@service0.xyz, account0_backup@service0.xyz) has been added to Service Service0"); - expectedLogs.Push($"Warning : Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s password has been updated"); - expectedLogs.Push($"Information : Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s notes has been set to Service0's Account0's notes"); - expectedLogs.Push($"Information : Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s options has been set to None"); - expectedLogs.Push($"Information : Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s password update reminder delay has been set to 3"); + expectedActivities.Push($"Information : Account Account0 (account0@service0.xyz, account0_backup@service0.xyz) has been added to Service Service0"); + expectedActivities.Push($"Warning : Service Service0's Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s password has been updated"); + expectedActivities.Push($"Information : Service Service0's Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s notes has been set to Service0's Account0's notes"); + expectedActivities.Push($"Information : Service Service0's Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s options has been set to None"); + expectedActivities.Push($"Information : Service Service0's Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s password update reminder delay has been set to 3"); - expectedLogs.Push($"Information : Account Account1 (account1@service0.xyz, account1_backup@service0.xyz) has been added to Service Service0"); - expectedLogs.Push($"Warning : Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s password has been updated"); - expectedLogs.Push($"Information : Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s notes has been set to Service0's Account1's notes"); - expectedLogs.Push($"Information : Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s options has been set to None"); - expectedLogs.Push($"Information : Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s password update reminder delay has been set to 3"); + expectedActivities.Push($"Information : Account Account1 (account1@service0.xyz, account1_backup@service0.xyz) has been added to Service Service0"); + expectedActivities.Push($"Warning : Service Service0's Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s password has been updated"); + expectedActivities.Push($"Information : Service Service0's Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s notes has been set to Service0's Account1's notes"); + expectedActivities.Push($"Information : Service Service0's Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s options has been set to None"); + expectedActivities.Push($"Information : Service Service0's Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s password update reminder delay has been set to 3"); - expectedLogs.Push($"Information : Service Service1 has been added to User {username}"); - expectedLogs.Push($"Information : Service Service1's url has been set to www.service1.xyz"); - expectedLogs.Push($"Information : Service Service1's notes has been set to Service1's notes"); + expectedActivities.Push($"Information : Service Service1 has been added to User {username}"); + expectedActivities.Push($"Information : Service Service1's url has been set to www.service1.xyz"); + expectedActivities.Push($"Information : Service Service1's notes has been set to Service1's notes"); - expectedLogs.Push($"Information : Account Account0 (account0@service1.xyz, account0_backup@service1.xyz) has been added to Service Service1"); - expectedLogs.Push($"Warning : Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s password has been updated"); - expectedLogs.Push($"Information : Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s notes has been set to Service1's Account0's notes"); - expectedLogs.Push($"Information : Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s options has been set to None"); - expectedLogs.Push($"Information : Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s password update reminder delay has been set to 3"); + expectedActivities.Push($"Information : Account Account0 (account0@service1.xyz, account0_backup@service1.xyz) has been added to Service Service1"); + expectedActivities.Push($"Warning : Service Service1's Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s password has been updated"); + expectedActivities.Push($"Information : Service Service1's Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s notes has been set to Service1's Account0's notes"); + expectedActivities.Push($"Information : Service Service1's Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s options has been set to None"); + expectedActivities.Push($"Information : Service Service1's Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s password update reminder delay has been set to 3"); - expectedLogs.Push($"Information : Account Account1 (account1@service1.xyz, account1_backup@service1.xyz) has been added to Service Service1"); - expectedLogs.Push($"Warning : Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s password has been updated"); - expectedLogs.Push($"Information : Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s notes has been set to Service1's Account1's notes"); - expectedLogs.Push($"Information : Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s options has been set to None"); - expectedLogs.Push($"Information : Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s password update reminder delay has been set to 3"); + expectedActivities.Push($"Information : Account Account1 (account1@service1.xyz, account1_backup@service1.xyz) has been added to Service Service1"); + expectedActivities.Push($"Warning : Service Service1's Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s password has been updated"); + expectedActivities.Push($"Information : Service Service1's Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s notes has been set to Service1's Account1's notes"); + expectedActivities.Push($"Information : Service Service1's Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s options has been set to None"); + expectedActivities.Push($"Information : Service Service1's Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s password update reminder delay has been set to 3"); - expectedLogs.Push($"Warning : Import completed successfully"); - expectedLogs.Push($"Information : User {username}'s database saved"); + expectedActivities.Push($"Warning : Import completed successfully"); + expectedActivities.Push($"Information : User {username}'s database saved"); // Then database.User.Services.Length.Should().Be(2); @@ -260,14 +255,13 @@ public void Case06_ImportCSV_OK() // When database.ExportToFile(exportFile); - expectedLogs.Push($"Information : User {username}'s database saved"); - expectedLogs.Push($"Warning : Exporting data to file : '{exportFile}'"); - expectedLogs.Push($"Warning : Export completed successfully"); + expectedActivities.Push($"Warning : Exporting data to file : '{exportFile}'"); + expectedActivities.Push($"Warning : Export completed successfully"); // Then File.ReadAllText(importFile).Replace("\r", "").Should().Be(File.ReadAllText(exportFile).Replace("\r", "")); - UnitTestsHelper.LastLogsShouldMatch(database, [.. expectedLogs]); + UnitTestsHelper.LastActivitiesShouldMatch(database, [.. expectedActivities]); // Finaly database.Close(); @@ -284,19 +278,18 @@ public void Case07_ImportCSV_MissingHeader() string[] passkeys = UnitTestsHelper.GetRandomStringArray(); string importFile = UnitTestsHelper.GetTestFilePath($"import_MissingHearder.csv"); IDatabase database = UnitTestsHelper.CreateTestDatabase(passkeys); - Stack expectedLogs = new(); + Stack expectedActivities = new(); // When database.ImportFromFile(importFile); - expectedLogs.Push($"Information : User {username}'s database saved"); - expectedLogs.Push($"Warning : Importing data from file : '{importFile}'"); - expectedLogs.Push($"Warning : Import failed because the CSV headers should be : 'ServiceName', 'ServiceUrl', 'ServiceNotes', 'AccountLabel', 'Identifiers', 'Password', 'AccountNotes', 'AccountOptions', 'PasswordUpdateReminderDelay'"); + expectedActivities.Push($"Warning : Importing data from file : '{importFile}'"); + expectedActivities.Push($"Warning : Import failed because the CSV headers should be : 'ServiceName', 'ServiceUrl', 'ServiceNotes', 'AccountLabel', 'Identifiers', 'Password', 'AccountNotes', 'AccountOptions', 'PasswordUpdateReminderDelay'"); // Then database.User.Services.Should().BeEmpty(); - UnitTestsHelper.LastLogsShouldMatch(database, [.. expectedLogs]); + UnitTestsHelper.LastActivitiesShouldMatch(database, [.. expectedActivities]); // Finaly database.Close(); @@ -313,19 +306,18 @@ public void Case08_ImportCSV_MissingCollumn() string[] passkeys = UnitTestsHelper.GetRandomStringArray(); string importFile = UnitTestsHelper.GetTestFilePath($"import_MissingCollumn.csv"); IDatabase database = UnitTestsHelper.CreateTestDatabase(passkeys); - Stack expectedLogs = new(); + Stack expectedActivities = new(); // When database.ImportFromFile(importFile); - expectedLogs.Push($"Information : User {username}'s database saved"); - expectedLogs.Push($"Warning : Importing data from file : '{importFile}'"); - expectedLogs.Push($"Warning : Import failed because the CSV data format is incorrect"); + expectedActivities.Push($"Warning : Importing data from file : '{importFile}'"); + expectedActivities.Push($"Warning : Import failed because the CSV data format is incorrect"); // Then database.User.Services.Should().BeEmpty(); - UnitTestsHelper.LastLogsShouldMatch(database, [.. expectedLogs]); + UnitTestsHelper.LastActivitiesShouldMatch(database, [.. expectedActivities]); // Finaly database.Close(); @@ -342,48 +334,47 @@ public void Case09_ImportJson_OK() string[] passkeys = UnitTestsHelper.GetRandomStringArray(); string importFile = UnitTestsHelper.GetTestFilePath("import.json"); IDatabase database = UnitTestsHelper.CreateTestDatabase(passkeys); - Stack expectedLogs = new(); + Stack expectedActivities = new(); // When database.ImportFromFile(importFile); - expectedLogs.Push($"Information : User {username}'s database saved"); - expectedLogs.Push($"Warning : Importing data from file : '{importFile}'"); + expectedActivities.Push($"Warning : Importing data from file : '{importFile}'"); - expectedLogs.Push($"Information : Service Service0 has been added to User {username}"); - expectedLogs.Push($"Information : Service Service0's url has been set to www.service0.xyz"); - expectedLogs.Push($"Information : Service Service0's notes has been set to Service0's notes"); + expectedActivities.Push($"Information : Service Service0 has been added to User {username}"); + expectedActivities.Push($"Information : Service Service0's url has been set to www.service0.xyz"); + expectedActivities.Push($"Information : Service Service0's notes has been set to Service0's notes"); - expectedLogs.Push($"Information : Account Account0 (account0@service0.xyz, account0_backup@service0.xyz) has been added to Service Service0"); - expectedLogs.Push($"Warning : Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s password has been updated"); - expectedLogs.Push($"Information : Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s notes has been set to Service0's Account0's notes"); - expectedLogs.Push($"Information : Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s options has been set to None"); - expectedLogs.Push($"Information : Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s password update reminder delay has been set to 3"); + expectedActivities.Push($"Information : Account Account0 (account0@service0.xyz, account0_backup@service0.xyz) has been added to Service Service0"); + expectedActivities.Push($"Warning : Service Service0's Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s password has been updated"); + expectedActivities.Push($"Information : Service Service0's Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s notes has been set to Service0's Account0's notes"); + expectedActivities.Push($"Information : Service Service0's Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s options has been set to None"); + expectedActivities.Push($"Information : Service Service0's Account Account0 (account0@service0.xyz, account0_backup@service0.xyz)'s password update reminder delay has been set to 3"); - expectedLogs.Push($"Information : Account Account1 (account1@service0.xyz, account1_backup@service0.xyz) has been added to Service Service0"); - expectedLogs.Push($"Warning : Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s password has been updated"); - expectedLogs.Push($"Information : Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s notes has been set to Service0's Account1's notes"); - expectedLogs.Push($"Information : Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s options has been set to None"); - expectedLogs.Push($"Information : Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s password update reminder delay has been set to 3"); + expectedActivities.Push($"Information : Account Account1 (account1@service0.xyz, account1_backup@service0.xyz) has been added to Service Service0"); + expectedActivities.Push($"Warning : Service Service0's Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s password has been updated"); + expectedActivities.Push($"Information : Service Service0's Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s notes has been set to Service0's Account1's notes"); + expectedActivities.Push($"Information : Service Service0's Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s options has been set to None"); + expectedActivities.Push($"Information : Service Service0's Account Account1 (account1@service0.xyz, account1_backup@service0.xyz)'s password update reminder delay has been set to 3"); - expectedLogs.Push($"Information : Service Service1 has been added to User {username}"); - expectedLogs.Push($"Information : Service Service1's url has been set to www.service1.xyz"); - expectedLogs.Push($"Information : Service Service1's notes has been set to Service1's notes"); + expectedActivities.Push($"Information : Service Service1 has been added to User {username}"); + expectedActivities.Push($"Information : Service Service1's url has been set to www.service1.xyz"); + expectedActivities.Push($"Information : Service Service1's notes has been set to Service1's notes"); - expectedLogs.Push($"Information : Account Account0 (account0@service1.xyz, account0_backup@service1.xyz) has been added to Service Service1"); - expectedLogs.Push($"Warning : Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s password has been updated"); - expectedLogs.Push($"Information : Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s notes has been set to Service1's Account0's notes"); - expectedLogs.Push($"Information : Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s options has been set to None"); - expectedLogs.Push($"Information : Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s password update reminder delay has been set to 3"); + expectedActivities.Push($"Information : Account Account0 (account0@service1.xyz, account0_backup@service1.xyz) has been added to Service Service1"); + expectedActivities.Push($"Warning : Service Service1's Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s password has been updated"); + expectedActivities.Push($"Information : Service Service1's Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s notes has been set to Service1's Account0's notes"); + expectedActivities.Push($"Information : Service Service1's Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s options has been set to None"); + expectedActivities.Push($"Information : Service Service1's Account Account0 (account0@service1.xyz, account0_backup@service1.xyz)'s password update reminder delay has been set to 3"); - expectedLogs.Push($"Information : Account Account1 (account1@service1.xyz, account1_backup@service1.xyz) has been added to Service Service1"); - expectedLogs.Push($"Warning : Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s password has been updated"); - expectedLogs.Push($"Information : Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s notes has been set to Service1's Account1's notes"); - expectedLogs.Push($"Information : Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s options has been set to None"); - expectedLogs.Push($"Information : Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s password update reminder delay has been set to 3"); + expectedActivities.Push($"Information : Account Account1 (account1@service1.xyz, account1_backup@service1.xyz) has been added to Service Service1"); + expectedActivities.Push($"Warning : Service Service1's Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s password has been updated"); + expectedActivities.Push($"Information : Service Service1's Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s notes has been set to Service1's Account1's notes"); + expectedActivities.Push($"Information : Service Service1's Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s options has been set to None"); + expectedActivities.Push($"Information : Service Service1's Account Account1 (account1@service1.xyz, account1_backup@service1.xyz)'s password update reminder delay has been set to 3"); - expectedLogs.Push($"Warning : Import completed successfully"); - expectedLogs.Push($"Information : User {username}'s database saved"); + expectedActivities.Push($"Warning : Import completed successfully"); + expectedActivities.Push($"Information : User {username}'s database saved"); // Then database.User.Services.Length.Should().Be(2); @@ -428,7 +419,7 @@ public void Case09_ImportJson_OK() database.User.Services[1].Accounts[1].Options.Should().Be(AccountOption.None); database.User.Services[1].Accounts[1].PasswordUpdateReminderDelay.Should().Be(3); - UnitTestsHelper.LastLogsShouldMatch(database, [.. expectedLogs]); + UnitTestsHelper.LastActivitiesShouldMatch(database, [.. expectedActivities]); // Finaly database.Close(); @@ -445,19 +436,18 @@ public void Case10_ImportJson_WrongFormat() string[] passkeys = UnitTestsHelper.GetRandomStringArray(); string importFile = UnitTestsHelper.GetTestFilePath($"import_WrongFormat.json"); IDatabase database = UnitTestsHelper.CreateTestDatabase(passkeys); - Stack expectedLogs = new(); + Stack expectedActivities = new(); // When database.ImportFromFile(importFile); - expectedLogs.Push($"Information : User {username}'s database saved"); - expectedLogs.Push($"Warning : Importing data from file : '{importFile}'"); - expectedLogs.Push($"Warning : Import failed because import file deserialization failed"); + expectedActivities.Push($"Warning : Importing data from file : '{importFile}'"); + expectedActivities.Push($"Warning : Import failed because import file deserialization failed"); // Then database.User.Services.Should().BeEmpty(); - UnitTestsHelper.LastLogsShouldMatch(database, [.. expectedLogs]); + UnitTestsHelper.LastActivitiesShouldMatch(database, [.. expectedActivities]); // Finaly database.Close(); @@ -476,20 +466,20 @@ public void Case11_Export_FileAlreadyExists() string importFile = UnitTestsHelper.GetTestFilePath($"import.json"); string exportFile = UnitTestsHelper.GetTestFilePath($"{username}/export.json", createIfNotExists: true); IDatabase database = UnitTestsHelper.CreateTestDatabase(passkeys); - Stack expectedLogs = new(); + Stack expectedActivities = new(); database.ImportFromFile(importFile); // When database.ExportToFile(exportFile); - expectedLogs.Push($"Information : User {username}'s database saved"); - expectedLogs.Push($"Warning : Exporting data to file : '{exportFile}'"); - expectedLogs.Push($"Warning : Export failed because export file already exists"); + expectedActivities.Push($"Information : User {username}'s database saved"); + expectedActivities.Push($"Warning : Exporting data to file : '{exportFile}'"); + expectedActivities.Push($"Warning : Export failed because export file already exists"); // Then File.Exists(exportFile).Should().BeTrue(); - UnitTestsHelper.LastLogsShouldMatch(database, [.. expectedLogs]); + UnitTestsHelper.LastActivitiesShouldMatch(database, [.. expectedActivities]); // Finaly database.Close(); @@ -508,20 +498,20 @@ public void Case12_Export_FileExtensionNotHandled() string importFile = UnitTestsHelper.GetTestFilePath($"import.json"); string exportFile = UnitTestsHelper.GetTestFilePath($"{username}/export.txt"); IDatabase database = UnitTestsHelper.CreateTestDatabase(passkeys); - Stack expectedLogs = new(); + Stack expectedActivities = new(); database.ImportFromFile(importFile); // When database.ExportToFile(exportFile); - expectedLogs.Push($"Information : User {username}'s database saved"); - expectedLogs.Push($"Warning : Exporting data to file : '{exportFile}'"); - expectedLogs.Push($"Warning : Export failed because '.txt' extention type is not handled"); + expectedActivities.Push($"Information : User {username}'s database saved"); + expectedActivities.Push($"Warning : Exporting data to file : '{exportFile}'"); + expectedActivities.Push($"Warning : Export failed because '.txt' extention type is not handled"); // Then File.Exists(exportFile).Should().BeFalse(); - UnitTestsHelper.LastLogsShouldMatch(database, [.. expectedLogs]); + UnitTestsHelper.LastActivitiesShouldMatch(database, [.. expectedActivities]); // Finaly database.Close(); diff --git a/UnitTests/Models/ServiceUnitTests.cs b/UnitTests/Models/ServiceUnitTests.cs index 2f6f6dc..80c98db 100644 --- a/UnitTests/Models/ServiceUnitTests.cs +++ b/UnitTests/Models/ServiceUnitTests.cs @@ -26,12 +26,12 @@ public void Case01_AddServiceUpdateSaved() string newServiceName = "new_" + oldServiceName; string url = UnitTestsHelper.GetRandomString(); string notes = UnitTestsHelper.GetRandomString(); - Stack expectedLogs = new(); + Stack expectedActivities = new(); Stack expectedLogWarnings = new(); // When IService service = databaseCreated.User.AddService(oldServiceName); - expectedLogs.Push($"Information : {service} has been added to User {username}"); + expectedActivities.Push($"Information : {service} has been added to User {username}"); // Then databaseCreated.User.HasChanged().Should().BeTrue(); @@ -41,14 +41,14 @@ public void Case01_AddServiceUpdateSaved() // When service.ServiceName = newServiceName; service.ServiceName = newServiceName; - expectedLogs.Push($"Warning : Service {oldServiceName}'s service name has been set to {newServiceName}"); + expectedActivities.Push($"Warning : Service {oldServiceName}'s service name has been set to {newServiceName}"); expectedLogWarnings.Push($"Warning : Service {oldServiceName}'s service name has been set to {newServiceName}"); service.Url = url; service.Url = url; - expectedLogs.Push($"Information : {service}'s url has been set to {url}"); + expectedActivities.Push($"Information : {service}'s url has been set to {url}"); service.Notes = notes; service.Notes = notes; - expectedLogs.Push($"Information : {service}'s notes has been set to {notes}"); + expectedActivities.Push($"Information : {service}'s notes has been set to {notes}"); // Then databaseCreated.User.HasChanged().Should().BeTrue(); @@ -59,14 +59,14 @@ public void Case01_AddServiceUpdateSaved() // When databaseCreated.Save(); - expectedLogs.Push($"Information : User {username}'s database saved"); + expectedActivities.Push($"Information : User {username}'s database saved"); databaseCreated.Close(); - expectedLogs.Push($"Information : User {username} logged out"); - expectedLogs.Push($"Information : User {username}'s database closed"); + expectedActivities.Push($"Information : User {username} logged out"); + expectedActivities.Push($"Information : User {username}'s database closed"); IDatabase databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _); - expectedLogs.Push($"Information : User {username}'s database opened"); - expectedLogs.Push($"Information : User {username} logged in"); + expectedActivities.Push($"Information : User {username}'s database opened"); + expectedActivities.Push($"Information : User {username} logged in"); // Then _ = databaseLoaded.User.Services.Length.Should().Be(1); @@ -79,8 +79,8 @@ public void Case01_AddServiceUpdateSaved() _ = serviceLoaded.Url.Should().Be(url); _ = serviceLoaded.Notes.Should().Be(notes); - UnitTestsHelper.LastLogsShouldMatch(databaseLoaded, [.. expectedLogs]); - UnitTestsHelper.LastLogWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); + UnitTestsHelper.LastActivitiesShouldMatch(databaseLoaded, [.. expectedActivities]); + UnitTestsHelper.LastActivityWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); // Finaly databaseLoaded.Close(); @@ -104,12 +104,12 @@ public void Case02_AddServiceUpdateAutoSave() string newServiceName = "new_" + oldServiceName; string url = UnitTestsHelper.GetRandomString(); string notes = UnitTestsHelper.GetRandomString(); - Stack expectedLogs = new(); + Stack expectedActivities = new(); Stack expectedLogWarnings = new(); // When IService service = databaseCreated.User.AddService(oldServiceName); - expectedLogs.Push($"Information : {service} has been added to User {username}"); + expectedActivities.Push($"Information : {service} has been added to User {username}"); // Then _ = databaseCreated.User.Services.Length.Should().Be(1); @@ -117,24 +117,24 @@ public void Case02_AddServiceUpdateAutoSave() // When service.ServiceName = newServiceName; service.ServiceName = newServiceName; - expectedLogs.Push($"Warning : Service {oldServiceName}'s service name has been set to {newServiceName}"); + expectedActivities.Push($"Warning : Service {oldServiceName}'s service name has been set to {newServiceName}"); expectedLogWarnings.Push($"Warning : Service {oldServiceName}'s service name has been set to {newServiceName}"); service.Url = url; service.Url = url; - expectedLogs.Push($"Information : {service}'s url has been set to {url}"); + expectedActivities.Push($"Information : {service}'s url has been set to {url}"); service.Notes = notes; service.Notes = notes; - expectedLogs.Push($"Information : {service}'s notes has been set to {notes}"); + expectedActivities.Push($"Information : {service}'s notes has been set to {notes}"); databaseCreated.Close(); - expectedLogs.Push($"Warning : User {username} logged out without saving"); + expectedActivities.Push($"Warning : User {username} logged out without saving"); expectedLogWarnings.Push($"Warning : User {username} logged out without saving"); - expectedLogs.Push($"Information : User {username}'s database closed"); + expectedActivities.Push($"Information : User {username}'s database closed"); IDatabase databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _, AutoSaveMergeBehavior.MergeAndSaveThenRemoveAutoSaveFile); - expectedLogs.Push($"Information : User {username}'s database opened"); - expectedLogs.Push($"Information : User {username} logged in"); - expectedLogs.Push($"Warning : User {username}'s autosave merged and saved"); + expectedActivities.Push($"Information : User {username}'s database opened"); + expectedActivities.Push($"Information : User {username} logged in"); + expectedActivities.Push($"Warning : User {username}'s autosave merged and saved"); expectedLogWarnings.Push($"Warning : User {username}'s autosave merged and saved"); // Then @@ -148,8 +148,8 @@ public void Case02_AddServiceUpdateAutoSave() _ = serviceLoaded.Url.Should().Be(url); _ = serviceLoaded.Notes.Should().Be(notes); - UnitTestsHelper.LastLogsShouldMatch(databaseLoaded, [.. expectedLogs]); - UnitTestsHelper.LastLogWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); + UnitTestsHelper.LastActivitiesShouldMatch(databaseLoaded, [.. expectedActivities]); + UnitTestsHelper.LastActivityWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); // Finaly databaseLoaded.Close(); @@ -172,7 +172,7 @@ public void Case03_DeleteServiceUpdateSaved() _ = databaseCreated.User.AddService(serviceName); databaseCreated.Save(); databaseCreated.Close(); - Stack expectedLogs = new(); + Stack expectedActivities = new(); Stack expectedLogWarnings = new(); IDatabase databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _); @@ -180,7 +180,7 @@ public void Case03_DeleteServiceUpdateSaved() // When databaseLoaded.User.DeleteService(serviceLoaded); - expectedLogs.Push($"Warning : Service {serviceName} has been removed from User {username}"); + expectedActivities.Push($"Warning : Service {serviceName} has been removed from User {username}"); expectedLogWarnings.Push($"Warning : Service {serviceName} has been removed from User {username}"); // Then @@ -188,20 +188,20 @@ public void Case03_DeleteServiceUpdateSaved() // When databaseLoaded.Save(); - expectedLogs.Push($"Information : User {username}'s database saved"); + expectedActivities.Push($"Information : User {username}'s database saved"); databaseLoaded.Close(); - expectedLogs.Push($"Information : User {username} logged out"); - expectedLogs.Push($"Information : User {username}'s database closed"); + expectedActivities.Push($"Information : User {username} logged out"); + expectedActivities.Push($"Information : User {username}'s database closed"); databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _); - expectedLogs.Push($"Information : User {username}'s database opened"); - expectedLogs.Push($"Information : User {username} logged in"); + expectedActivities.Push($"Information : User {username}'s database opened"); + expectedActivities.Push($"Information : User {username} logged in"); // Then _ = databaseLoaded.User.Services.Length.Should().Be(0); - UnitTestsHelper.LastLogsShouldMatch(databaseLoaded, [.. expectedLogs]); - UnitTestsHelper.LastLogWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); + UnitTestsHelper.LastActivitiesShouldMatch(databaseLoaded, [.. expectedActivities]); + UnitTestsHelper.LastActivityWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); // Finaly databaseLoaded.Close(); @@ -223,7 +223,7 @@ public void Case04_DeleteServiceUpdateAutoSave() string serviceName = "Service_" + UnitTestsHelper.GetUsername(); _ = databaseCreated.User.AddService(serviceName); databaseCreated.Close(); - Stack expectedLogs = new(); + Stack expectedActivities = new(); Stack expectedLogWarnings = new(); IDatabase databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _, AutoSaveMergeBehavior.MergeAndSaveThenRemoveAutoSaveFile); @@ -231,7 +231,7 @@ public void Case04_DeleteServiceUpdateAutoSave() // When databaseLoaded.User.DeleteService(serviceLoaded); - expectedLogs.Push($"Warning : Service {serviceName} has been removed from User {username}"); + expectedActivities.Push($"Warning : Service {serviceName} has been removed from User {username}"); expectedLogWarnings.Push($"Warning : Service {serviceName} has been removed from User {username}"); // Then @@ -239,21 +239,21 @@ public void Case04_DeleteServiceUpdateAutoSave() // When databaseLoaded.Close(); - expectedLogs.Push($"Warning : User {username} logged out without saving"); + expectedActivities.Push($"Warning : User {username} logged out without saving"); expectedLogWarnings.Push($"Warning : User {username} logged out without saving"); - expectedLogs.Push($"Information : User {username}'s database closed"); + expectedActivities.Push($"Information : User {username}'s database closed"); databaseLoaded = UnitTestsHelper.OpenTestDatabase(passkeys, out _, AutoSaveMergeBehavior.MergeAndSaveThenRemoveAutoSaveFile); - expectedLogs.Push($"Information : User {username}'s database opened"); - expectedLogs.Push($"Information : User {username} logged in"); - expectedLogs.Push($"Warning : User {username}'s autosave merged and saved"); + expectedActivities.Push($"Information : User {username}'s database opened"); + expectedActivities.Push($"Information : User {username} logged in"); + expectedActivities.Push($"Warning : User {username}'s autosave merged and saved"); expectedLogWarnings.Push($"Warning : User {username}'s autosave merged and saved"); // Then _ = databaseLoaded.User.Services.Length.Should().Be(0); - UnitTestsHelper.LastLogsShouldMatch(databaseLoaded, [.. expectedLogs]); - UnitTestsHelper.LastLogWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); + UnitTestsHelper.LastActivitiesShouldMatch(databaseLoaded, [.. expectedActivities]); + UnitTestsHelper.LastActivityWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); // Finaly databaseLoaded.Close(); diff --git a/UnitTests/Models/UserUnitTests.cs b/UnitTests/Models/UserUnitTests.cs index 7563e4e..bbc4810 100644 --- a/UnitTests/Models/UserUnitTests.cs +++ b/UnitTests/Models/UserUnitTests.cs @@ -70,45 +70,45 @@ public void Case02_UserUpdateThenSaved() string[] newPasskeys = UnitTestsHelper.GetRandomStringArray(); int logoutTimeout = UnitTestsHelper.GetRandomInt(1, 60); int cleaningClipboardTimeout = UnitTestsHelper.GetRandomInt(1, 60); - Stack expectedLogs = new(); + Stack expectedActivities = new(); Stack expectedLogWarnings = new(); // When databaseCreated.User.Username = newUsername; databaseCreated.User.Username = newUsername; - expectedLogs.Push($"Warning : {databaseCreated.User}'s username has been set to {newUsername}"); + expectedActivities.Push($"Warning : {databaseCreated.User}'s username has been set to {newUsername}"); expectedLogWarnings.Push($"Warning : {databaseCreated.User}'s username has been set to {newUsername}"); databaseCreated.User.Passkeys = newPasskeys; databaseCreated.User.Passkeys = newPasskeys; - expectedLogs.Push($"Warning : {databaseCreated.User}'s passkeys has been updated"); + expectedActivities.Push($"Warning : {databaseCreated.User}'s passkeys has been updated"); expectedLogWarnings.Push($"Warning : {databaseCreated.User}'s passkeys has been updated"); databaseCreated.User.LogoutTimeout = logoutTimeout; databaseCreated.User.LogoutTimeout = logoutTimeout; - expectedLogs.Push($"Information : {databaseCreated.User}'s logout timeout has been set to {logoutTimeout}"); + expectedActivities.Push($"Information : {databaseCreated.User}'s logout timeout has been set to {logoutTimeout}"); databaseCreated.User.CleaningClipboardTimeout = cleaningClipboardTimeout; databaseCreated.User.CleaningClipboardTimeout = cleaningClipboardTimeout; - expectedLogs.Push($"Information : {databaseCreated.User}'s cleaning clipboard timeout has been set to {cleaningClipboardTimeout}"); + expectedActivities.Push($"Information : {databaseCreated.User}'s cleaning clipboard timeout has been set to {cleaningClipboardTimeout}"); databaseCreated.User.WarningsToNotify = WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning; databaseCreated.User.WarningsToNotify = WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning; - expectedLogs.Push($"Warning : {databaseCreated.User}'s warnings to notify has been set to {WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning}"); + expectedActivities.Push($"Warning : {databaseCreated.User}'s warnings to notify has been set to {WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning}"); expectedLogWarnings.Push($"Warning : {databaseCreated.User}'s warnings to notify has been set to {WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning}"); databaseCreated.Save(); - expectedLogs.Push($"Information : {databaseCreated.User}'s database saved"); + expectedActivities.Push($"Information : {databaseCreated.User}'s database saved"); databaseCreated.Close(); - expectedLogs.Push($"Information : User {newUsername} logged out"); - expectedLogs.Push($"Information : User {newUsername}'s database closed"); + expectedActivities.Push($"Information : User {newUsername} logged out"); + expectedActivities.Push($"Information : User {newUsername}'s database closed"); IDatabase databaseLoaded = Database.Open(UnitTestsHelper.CryptographicCenter, UnitTestsHelper.SerializationCenter, UnitTestsHelper.PasswordFactory, UnitTestsHelper.ClipboardManager, databaseFile, newUsername); - expectedLogs.Push($"Information : User {newUsername}'s database opened"); + expectedActivities.Push($"Information : User {newUsername}'s database opened"); foreach (string passkey in newPasskeys) { _ = databaseLoaded.Login(passkey); } - expectedLogs.Push($"Information : {databaseLoaded.User} logged in"); + expectedActivities.Push($"Information : {databaseLoaded.User} logged in"); // Then _ = databaseLoaded.User.Should().NotBeNull(); @@ -116,8 +116,8 @@ public void Case02_UserUpdateThenSaved() _ = databaseLoaded.User.LogoutTimeout.Should().Be(logoutTimeout); _ = databaseLoaded.User.CleaningClipboardTimeout.Should().Be(cleaningClipboardTimeout); - UnitTestsHelper.LastLogsShouldMatch(databaseLoaded, [.. expectedLogs]); - UnitTestsHelper.LastLogWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); + UnitTestsHelper.LastActivitiesShouldMatch(databaseLoaded, [.. expectedActivities]); + UnitTestsHelper.LastActivityWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); _ = databaseLoaded.Warnings.Should().NotBeEmpty(); @@ -145,37 +145,37 @@ public void Case03_UserUpdateButNotSaved_CaseMergeAndSave() string[] newPasskeys = UnitTestsHelper.GetRandomStringArray(); int logoutTimeout = UnitTestsHelper.GetRandomInt(1, 60); int cleaningClipboardTimeout = UnitTestsHelper.GetRandomInt(1, 60); - Stack expectedLogs = new(); + Stack expectedActivities = new(); Stack expectedLogWarnings = new(); // When databaseCreated.User.Username = newUsername; databaseCreated.User.Username = newUsername; - expectedLogs.Push($"Warning : {databaseCreated.User}'s username has been set to {newUsername}"); + expectedActivities.Push($"Warning : {databaseCreated.User}'s username has been set to {newUsername}"); expectedLogWarnings.Push($"Warning : {databaseCreated.User}'s username has been set to {newUsername}"); databaseCreated.User.Passkeys = newPasskeys; databaseCreated.User.Passkeys = newPasskeys; - expectedLogs.Push($"Warning : {databaseCreated.User}'s passkeys has been updated"); + expectedActivities.Push($"Warning : {databaseCreated.User}'s passkeys has been updated"); expectedLogWarnings.Push($"Warning : {databaseCreated.User}'s passkeys has been updated"); databaseCreated.User.LogoutTimeout = logoutTimeout; databaseCreated.User.LogoutTimeout = logoutTimeout; - expectedLogs.Push($"Information : {databaseCreated.User}'s logout timeout has been set to {logoutTimeout}"); + expectedActivities.Push($"Information : {databaseCreated.User}'s logout timeout has been set to {logoutTimeout}"); databaseCreated.User.CleaningClipboardTimeout = cleaningClipboardTimeout; databaseCreated.User.CleaningClipboardTimeout = cleaningClipboardTimeout; - expectedLogs.Push($"Information : {databaseCreated.User}'s cleaning clipboard timeout has been set to {cleaningClipboardTimeout}"); + expectedActivities.Push($"Information : {databaseCreated.User}'s cleaning clipboard timeout has been set to {cleaningClipboardTimeout}"); databaseCreated.User.WarningsToNotify = WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning; databaseCreated.User.WarningsToNotify = WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning; - expectedLogs.Push($"Warning : {databaseCreated.User}'s warnings to notify has been set to {WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning}"); + expectedActivities.Push($"Warning : {databaseCreated.User}'s warnings to notify has been set to {WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning}"); expectedLogWarnings.Push($"Warning : {databaseCreated.User}'s warnings to notify has been set to {WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning}"); databaseCreated.Close(); - expectedLogs.Push($"Warning : User {oldUsername} logged out without saving"); + expectedActivities.Push($"Warning : User {oldUsername} logged out without saving"); expectedLogWarnings.Push($"Warning : User {oldUsername} logged out without saving"); - expectedLogs.Push($"Information : User {oldUsername}'s database closed"); + expectedActivities.Push($"Information : User {oldUsername}'s database closed"); IDatabase databaseLoaded = UnitTestsHelper.OpenTestDatabase(oldPasskeys, out IWarning[] warnings, AutoSaveMergeBehavior.MergeAndSaveThenRemoveAutoSaveFile); - expectedLogs.Push($"Information : User {oldUsername}'s database opened"); - expectedLogs.Push($"Information : User {oldUsername} logged in"); - expectedLogs.Push($"Warning : {databaseLoaded.User}'s autosave merged and saved"); + expectedActivities.Push($"Information : User {oldUsername}'s database opened"); + expectedActivities.Push($"Information : User {oldUsername} logged in"); + expectedActivities.Push($"Warning : {databaseLoaded.User}'s autosave merged and saved"); expectedLogWarnings.Push($"Warning : {databaseLoaded.User}'s autosave merged and saved"); // Then @@ -189,8 +189,8 @@ public void Case03_UserUpdateButNotSaved_CaseMergeAndSave() // When databaseLoaded.Close(); - expectedLogs.Push($"Information : User {newUsername} logged out"); - expectedLogs.Push($"Information : User {newUsername}'s database closed"); + expectedActivities.Push($"Information : User {newUsername} logged out"); + expectedActivities.Push($"Information : User {newUsername}'s database closed"); databaseLoaded = Database.Open(UnitTestsHelper.CryptographicCenter, UnitTestsHelper.SerializationCenter, @@ -198,12 +198,12 @@ public void Case03_UserUpdateButNotSaved_CaseMergeAndSave() UnitTestsHelper.ClipboardManager, databaseFile, newUsername); - expectedLogs.Push($"Information : User {newUsername}'s database opened"); + expectedActivities.Push($"Information : User {newUsername}'s database opened"); foreach (string passkey in newPasskeys) { _ = databaseLoaded.Login(passkey); } - expectedLogs.Push($"Information : {databaseLoaded.User} logged in"); + expectedActivities.Push($"Information : {databaseLoaded.User} logged in"); // Then _ = databaseLoaded.User.Username.Should().Be(newUsername); @@ -211,8 +211,8 @@ public void Case03_UserUpdateButNotSaved_CaseMergeAndSave() _ = databaseLoaded.User.LogoutTimeout.Should().Be(logoutTimeout); _ = databaseLoaded.User.CleaningClipboardTimeout.Should().Be(cleaningClipboardTimeout); - UnitTestsHelper.LastLogsShouldMatch(databaseLoaded, [.. expectedLogs]); - UnitTestsHelper.LastLogWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); + UnitTestsHelper.LastActivitiesShouldMatch(databaseLoaded, [.. expectedActivities]); + UnitTestsHelper.LastActivityWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); _ = databaseLoaded.Warnings.Should().NotBeEmpty(); @@ -240,37 +240,37 @@ public void Case04_UserUpdateButNotSaved_CaseMergeWithoutSaving() string[] newPasskeys = UnitTestsHelper.GetRandomStringArray(); int logoutTimeout = UnitTestsHelper.GetRandomInt(1, 60); int cleaningClipboardTimeout = UnitTestsHelper.GetRandomInt(1, 60); - Stack expectedLogs = new(); + Stack expectedActivities = new(); Stack expectedLogWarnings = new(); // When databaseCreated.User.Username = newUsername; databaseCreated.User.Username = newUsername; - expectedLogs.Push($"Warning : {databaseCreated.User}'s username has been set to {newUsername}"); + expectedActivities.Push($"Warning : {databaseCreated.User}'s username has been set to {newUsername}"); expectedLogWarnings.Push($"Warning : {databaseCreated.User}'s username has been set to {newUsername}"); databaseCreated.User.Passkeys = newPasskeys; databaseCreated.User.Passkeys = newPasskeys; - expectedLogs.Push($"Warning : {databaseCreated.User}'s passkeys has been updated"); + expectedActivities.Push($"Warning : {databaseCreated.User}'s passkeys has been updated"); expectedLogWarnings.Push($"Warning : {databaseCreated.User}'s passkeys has been updated"); databaseCreated.User.LogoutTimeout = logoutTimeout; databaseCreated.User.LogoutTimeout = logoutTimeout; - expectedLogs.Push($"Information : {databaseCreated.User}'s logout timeout has been set to {logoutTimeout}"); + expectedActivities.Push($"Information : {databaseCreated.User}'s logout timeout has been set to {logoutTimeout}"); databaseCreated.User.CleaningClipboardTimeout = cleaningClipboardTimeout; databaseCreated.User.CleaningClipboardTimeout = cleaningClipboardTimeout; - expectedLogs.Push($"Information : {databaseCreated.User}'s cleaning clipboard timeout has been set to {cleaningClipboardTimeout}"); + expectedActivities.Push($"Information : {databaseCreated.User}'s cleaning clipboard timeout has been set to {cleaningClipboardTimeout}"); databaseCreated.User.WarningsToNotify = WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning; databaseCreated.User.WarningsToNotify = WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning; - expectedLogs.Push($"Warning : {databaseCreated.User}'s warnings to notify has been set to {WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning}"); + expectedActivities.Push($"Warning : {databaseCreated.User}'s warnings to notify has been set to {WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning}"); expectedLogWarnings.Push($"Warning : {databaseCreated.User}'s warnings to notify has been set to {WarningType.DuplicatedPasswordsWarning | WarningType.PasswordUpdateReminderWarning}"); databaseCreated.Close(); - expectedLogs.Push($"Warning : User {oldUsername} logged out without saving"); + expectedActivities.Push($"Warning : User {oldUsername} logged out without saving"); expectedLogWarnings.Push($"Warning : User {oldUsername} logged out without saving"); - expectedLogs.Push($"Information : User {oldUsername}'s database closed"); + expectedActivities.Push($"Information : User {oldUsername}'s database closed"); IDatabase databaseLoaded = UnitTestsHelper.OpenTestDatabase(oldPasskeys, out IWarning[] warnings, AutoSaveMergeBehavior.MergeWithoutSavingAndKeepAutoSaveFile); - expectedLogs.Push($"Information : User {oldUsername}'s database opened"); - expectedLogs.Push($"Information : User {oldUsername} logged in"); - expectedLogs.Push($"Warning : {databaseLoaded.User}'s autosave merged without saving"); + expectedActivities.Push($"Information : User {oldUsername}'s database opened"); + expectedActivities.Push($"Information : User {oldUsername} logged in"); + expectedActivities.Push($"Warning : {databaseLoaded.User}'s autosave merged without saving"); expectedLogWarnings.Push($"Warning : {databaseLoaded.User}'s autosave merged without saving"); // Then @@ -288,10 +288,10 @@ public void Case04_UserUpdateButNotSaved_CaseMergeWithoutSaving() // When databaseLoaded.Save(); - expectedLogs.Push($"Information : {databaseLoaded.User}'s database saved"); + expectedActivities.Push($"Information : {databaseLoaded.User}'s database saved"); databaseLoaded.Close(); - expectedLogs.Push($"Information : User {newUsername} logged out"); - expectedLogs.Push($"Information : User {newUsername}'s database closed"); + expectedActivities.Push($"Information : User {newUsername} logged out"); + expectedActivities.Push($"Information : User {newUsername}'s database closed"); databaseLoaded = Database.Open(UnitTestsHelper.CryptographicCenter, UnitTestsHelper.SerializationCenter, @@ -299,12 +299,12 @@ public void Case04_UserUpdateButNotSaved_CaseMergeWithoutSaving() UnitTestsHelper.ClipboardManager, databaseFile, newUsername); - expectedLogs.Push($"Information : User {newUsername}'s database opened"); + expectedActivities.Push($"Information : User {newUsername}'s database opened"); foreach (string passkey in newPasskeys) { _ = databaseLoaded.Login(passkey); } - expectedLogs.Push($"Information : {databaseLoaded.User} logged in"); + expectedActivities.Push($"Information : {databaseLoaded.User} logged in"); // Then _ = databaseLoaded.User.Username.Should().Be(newUsername); @@ -312,8 +312,8 @@ public void Case04_UserUpdateButNotSaved_CaseMergeWithoutSaving() _ = databaseLoaded.User.LogoutTimeout.Should().Be(logoutTimeout); _ = databaseLoaded.User.CleaningClipboardTimeout.Should().Be(cleaningClipboardTimeout); - UnitTestsHelper.LastLogsShouldMatch(databaseLoaded, [.. expectedLogs]); - UnitTestsHelper.LastLogWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); + UnitTestsHelper.LastActivitiesShouldMatch(databaseLoaded, [.. expectedActivities]); + UnitTestsHelper.LastActivityWarningsShouldMatch(databaseLoaded, [.. expectedLogWarnings]); _ = databaseLoaded.Warnings.Should().NotBeEmpty(); diff --git a/UnitTests/TestFiles/import_blanckIdentifier.json b/UnitTests/TestFiles/import_blanckIdentifier.json new file mode 100644 index 0000000..0773473 --- /dev/null +++ b/UnitTests/TestFiles/import_blanckIdentifier.json @@ -0,0 +1,52 @@ +[ + { + "ServiceName": "Service0", + "Url": "www.service0.xyz", + "Notes": "Service0\u0027s notes", + "Accounts": [ + { + "Label": "Account0", + "Identifiers": [ "account0@service0.xyz", "account0_backup@service0.xyz" ], + "Password": "0000", + "Passwords": { "2025-11-26T21:33:12.4829309+03:00": "0000" }, + "Notes": "Service0\u0027s Account0\u0027s notes", + "PasswordUpdateReminderDelay": 3, + "Options": "None" + }, + { + "Label": "Account1", + "Identifiers": [ "account1@service0.xyz", "account1_backup@service0.xyz" ], + "Password": "1111", + "Passwords": { "2025-11-26T21:33:12.7380781+03:00": "1111" }, + "Notes": "Service0\u0027s Account1\u0027s notes", + "PasswordUpdateReminderDelay": 3, + "Options": "None" + } + ] + }, + { + "ServiceName": "Service1", + "Url": "www.service1.xyz", + "Notes": "Service1\u0027s notes", + "Accounts": [ + { + "Label": "Account0", + "Identifiers": [ "account0@service1.xyz", "account0_backup@service1.xyz" ], + "Password": "AAAA", + "Passwords": { "2025-11-26T21:33:13.1589472+03:00": "AAAA" }, + "Notes": "Service1\u0027s Account0\u0027s notes", + "PasswordUpdateReminderDelay": 3, + "Options": "None" + }, + { + "Label": "Account1", + "Identifiers": [ "account1@service1.xyz", "" ], + "Password": "BBBB", + "Passwords": { "2025-11-26T21:33:13.4643103+03:00": "BBBB" }, + "Notes": "Service1\u0027s Account1\u0027s notes", + "PasswordUpdateReminderDelay": 3, + "Options": "None" + } + ] + } +] \ No newline at end of file diff --git a/UnitTests/UnitTestsHelper.cs b/UnitTests/UnitTestsHelper.cs index 457427d..a793abf 100644 --- a/UnitTests/UnitTestsHelper.cs +++ b/UnitTests/UnitTestsHelper.cs @@ -160,34 +160,34 @@ public static int GetRandomInt(int min, int max) return (int)value; } - public static void LastLogsShouldMatch(IDatabase database, string[] expectedLogs) + public static void LastActivitiesShouldMatch(IDatabase database, string[] expectedActivities) { - string[] actualLogs = database.Logs.Select(x => $"{(x.NeedsReview ? "Warning" : "Information")} : {x.Message}").ToArray(); + string[] actualActivities = database.Activities.Select(x => $"{(x.NeedsReview ? "Warning" : "Information")} : {x.Message}").ToArray(); - _lastLogsShouldMatch(actualLogs, expectedLogs); + _lastActivitiesShouldMatch(actualActivities, expectedActivities); } - public static void LastLogWarningsShouldMatch(IDatabase database, string[] expectedLogs) + public static void LastActivityWarningsShouldMatch(IDatabase database, string[] expectedActivities) { while (database.Warnings is null) { Thread.Sleep(200); } - IWarning logWarning = database.Warnings.First(x => x.WarningType == WarningType.LogReviewWarning); + IWarning activityWarning = database.Warnings.First(x => x.WarningType == WarningType.ActivityReviewWarning); - string[] actualLogs = logWarning.Logs + string[] actualActivities = activityWarning.Activities .OrderByDescending(x => x.DateTime) .Select(x => $"{(x.NeedsReview ? "Warning" : "Information")} : {x.Message}").ToArray(); - _lastLogsShouldMatch(actualLogs, expectedLogs); + _lastActivitiesShouldMatch(actualActivities, expectedActivities); } - private static void _lastLogsShouldMatch(string[] actualLogs, string[] expectedLogs) + private static void _lastActivitiesShouldMatch(string[] actualActivities, string[] expectedActivities) { - for (int i = expectedLogs.Length - 1; i >= 0; i--) + for (int i = expectedActivities.Length - 1; i >= 0; i--) { - _ = actualLogs[i].Should().Be(expectedLogs[i]); + _ = actualActivities[i].Should().Be(expectedActivities[i]); } } }