From 2f1e9716fee14437bd6bf1de99e235df4cb46233 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 30 Jun 2024 18:19:00 +0200 Subject: [PATCH] big big update --- .../Exceptions/LoginException.cs | 2 +- OwnChar/Api/ICharacterManager.cs | 11 ++ OwnChar/Api/IDataManager.cs | 33 +++++ OwnChar/{Data => Api}/IDataProvider.cs | 15 ++- OwnChar/Api/IGroupsManager.cs | 12 ++ OwnChar/Api/IOwnCharManager.cs | 17 +++ OwnChar/Api/IUserManager.cs | 10 ++ OwnChar/Data/DataManagerAction.cs | 57 +++++++++ OwnChar/Data/DataManagerActionResult.cs | 6 + OwnChar/Data/DataManagerActionType.cs | 9 ++ OwnChar/Data/DataManagerActions.cs | 23 ++++ OwnChar/Data/IDataManager.cs | 30 ----- OwnChar/Data/Managers/DefaultDataManager.cs | 113 ++++++++++++++++-- ...ataManager.cs => HttpClientDataManager.cs} | 2 +- OwnChar/Data/OnActionEventArgs.cs | 14 +++ OwnChar/Data/OnCallbackEventArgs.cs | 12 ++ .../JsonFile/JsonFileDataProvider.cs | 9 +- .../Manager/{ => Modules}/CharacterManager.cs | 21 ++-- .../Manager/{ => Modules}/GroupsManager.cs | 32 +++-- OwnChar/Manager/{ => Modules}/UserManager.cs | 17 ++- OwnChar/Manager/OwnCharManager.cs | 25 ++-- OwnChar/Manager/OwnCharManagerModule.cs | 6 + OwnChar/Model/Character.cs | 3 +- OwnChar/Model/Group.cs | 2 +- OwnChar/Model/IOwnCharObject.cs | 5 - OwnChar/Model/OwnCharObject.cs | 6 + OwnChar/Model/Property.cs | 2 +- OwnChar/Model/PropertyCategory.cs | 2 +- OwnChar/Model/UserAccount.cs | 2 +- OwnChar/Model/UserProfile.cs | 2 +- 30 files changed, 388 insertions(+), 112 deletions(-) rename OwnChar/{Manager => Api}/Exceptions/LoginException.cs (63%) create mode 100644 OwnChar/Api/ICharacterManager.cs create mode 100644 OwnChar/Api/IDataManager.cs rename OwnChar/{Data => Api}/IDataProvider.cs (74%) create mode 100644 OwnChar/Api/IGroupsManager.cs create mode 100644 OwnChar/Api/IOwnCharManager.cs create mode 100644 OwnChar/Api/IUserManager.cs create mode 100644 OwnChar/Data/DataManagerAction.cs create mode 100644 OwnChar/Data/DataManagerActionResult.cs create mode 100644 OwnChar/Data/DataManagerActionType.cs create mode 100644 OwnChar/Data/DataManagerActions.cs delete mode 100644 OwnChar/Data/IDataManager.cs rename OwnChar/Data/Managers/{ClientDataManager.cs => HttpClientDataManager.cs} (53%) create mode 100644 OwnChar/Data/OnActionEventArgs.cs create mode 100644 OwnChar/Data/OnCallbackEventArgs.cs rename OwnChar/Manager/{ => Modules}/CharacterManager.cs (59%) rename OwnChar/Manager/{ => Modules}/GroupsManager.cs (51%) rename OwnChar/Manager/{ => Modules}/UserManager.cs (53%) create mode 100644 OwnChar/Manager/OwnCharManagerModule.cs delete mode 100644 OwnChar/Model/IOwnCharObject.cs create mode 100644 OwnChar/Model/OwnCharObject.cs diff --git a/OwnChar/Manager/Exceptions/LoginException.cs b/OwnChar/Api/Exceptions/LoginException.cs similarity index 63% rename from OwnChar/Manager/Exceptions/LoginException.cs rename to OwnChar/Api/Exceptions/LoginException.cs index f6b2803..a5c8ec2 100644 --- a/OwnChar/Manager/Exceptions/LoginException.cs +++ b/OwnChar/Api/Exceptions/LoginException.cs @@ -1,4 +1,4 @@ -namespace OwnChar.Manager.Exceptions; +namespace OwnChar.Api.Exceptions; public class LoginException(string message) : Exception(message) { diff --git a/OwnChar/Api/ICharacterManager.cs b/OwnChar/Api/ICharacterManager.cs new file mode 100644 index 0000000..d69968c --- /dev/null +++ b/OwnChar/Api/ICharacterManager.cs @@ -0,0 +1,11 @@ +using OwnChar.Model; + +namespace OwnChar.Api; +public interface ICharacterManager +{ + Character? CreateCharacter(string? name); + Character? CreateCharacter(string? name, Group? destination); + bool DeleteCharacter(Character? character); + IEnumerable? GetCharacters(Group? group); + IEnumerable? GetCharacters(UserProfile? profile); +} \ No newline at end of file diff --git a/OwnChar/Api/IDataManager.cs b/OwnChar/Api/IDataManager.cs new file mode 100644 index 0000000..6656d07 --- /dev/null +++ b/OwnChar/Api/IDataManager.cs @@ -0,0 +1,33 @@ +using OwnChar.Data; +using OwnChar.Model; + +namespace OwnChar.Api; + +public interface IDataManager +{ + public delegate void OnActionEventHandler(object sender, OnActionEventArgs e); + public delegate void OnCallbackEventHandler(object sender, OnCallbackEventArgs e); + + event OnActionEventHandler? OnAction; + event OnCallbackEventHandler? OnCallback; + // Login + UserAccount? Login(string username, string password); + bool Logout(UserAccount? account); + + // Action + DataManagerActionResult ExecuteAction(DataManagerAction action, DataManagerActionType actionType, UserAccount currentUser, OwnCharObject? obj, params object?[] parameters); + + //// User management + //UserProfile? GetUserProfile(UserAccount account); + + //// Group management + //UserProfile? GetOwner(UserAccount account, Group group); + //IEnumerable? GetMembers(UserAccount account, Group group); + //bool AddMember(UserAccount account, Group group, UserProfile user); + //bool RemoveMember(UserAccount account, Group group, UserProfile user); + + //// Character management + //UserProfile? GetOwner(UserAccount account, Character group); + //IEnumerable? GetCharacters(UserAccount account, Group group); + //IEnumerable? GetCharacters(UserAccount account, UserProfile profile); +} diff --git a/OwnChar/Data/IDataProvider.cs b/OwnChar/Api/IDataProvider.cs similarity index 74% rename from OwnChar/Data/IDataProvider.cs rename to OwnChar/Api/IDataProvider.cs index f7141bc..1457d1a 100644 --- a/OwnChar/Data/IDataProvider.cs +++ b/OwnChar/Api/IDataProvider.cs @@ -1,18 +1,17 @@ using OwnChar.Model; -namespace OwnChar.Data; +namespace OwnChar.Api; public interface IDataProvider { - // General - abstract bool IsInitialized(); - abstract void SetInitialized(); - abstract bool SaveDatabase(); + bool IsInitialized(); + void SetInitialized(); + bool SaveDatabase(); // Model - abstract T? Create() where T : class, IOwnCharObject; - abstract bool Save(T obj) where T : class, IOwnCharObject; - abstract bool Delete(T obj) where T : class, IOwnCharObject; + abstract T? Create() where T : OwnCharObject; + abstract bool Save(T obj) where T : OwnCharObject; + abstract bool Delete(T obj) where T : OwnCharObject; // Hierarchy abstract bool SetParent(UserProfile profile, UserAccount parent); diff --git a/OwnChar/Api/IGroupsManager.cs b/OwnChar/Api/IGroupsManager.cs new file mode 100644 index 0000000..5ed33ae --- /dev/null +++ b/OwnChar/Api/IGroupsManager.cs @@ -0,0 +1,12 @@ +using OwnChar.Model; + +namespace OwnChar.Api; +public interface IGroupsManager +{ + bool AddMember(UserProfile? profile, Group? group); + Group? CreateGroup(string? name); + bool DeleteGroup(Group? group); + bool DeleteMember(UserProfile? profile, Group? group); + IEnumerable? GetMembers(Group? group); + UserProfile? GetOwner(Group? group); +} \ No newline at end of file diff --git a/OwnChar/Api/IOwnCharManager.cs b/OwnChar/Api/IOwnCharManager.cs new file mode 100644 index 0000000..b919611 --- /dev/null +++ b/OwnChar/Api/IOwnCharManager.cs @@ -0,0 +1,17 @@ +using OwnChar.Model; +using Pilz.Cryptography; + +namespace OwnChar.Api; +public interface IOwnCharManager +{ + IDataManager? DataManager { get; set; } + UserAccount? CurrentUser { get; } + bool IsLoggedIn { get; } + + IUserManager Users { get; } + IGroupsManager Groups { get; } + ICharacterManager Characters { get; } + + bool Login(IDataManager? proxy, string? username, SecureString? password); + bool Logout(); +} \ No newline at end of file diff --git a/OwnChar/Api/IUserManager.cs b/OwnChar/Api/IUserManager.cs new file mode 100644 index 0000000..8db650d --- /dev/null +++ b/OwnChar/Api/IUserManager.cs @@ -0,0 +1,10 @@ +using OwnChar.Model; +using Pilz.Cryptography; + +namespace OwnChar.Api; +public interface IUserManager +{ + UserAccount? CreateUserAccount(string? username, SecureString? password); + bool DeleteUserAccount(UserAccount? account); + UserProfile? GetOwnUserProfile(); +} \ No newline at end of file diff --git a/OwnChar/Data/DataManagerAction.cs b/OwnChar/Data/DataManagerAction.cs new file mode 100644 index 0000000..bdf25e7 --- /dev/null +++ b/OwnChar/Data/DataManagerAction.cs @@ -0,0 +1,57 @@ +namespace OwnChar.Data; + +public class DataManagerAction(string id) +{ + public DataManagerAction? BaseAction { get; } + + public string ActionId + { + get + { + if (BaseAction != null) + return $"{BaseAction.ActionId}.{id}"; + return id; + } + } + + public DataManagerAction(DataManagerAction baseAction, string id) : this(id) + { + BaseAction = baseAction; + } + + public static bool operator ==(DataManagerAction? a, DataManagerAction? b) + { + if (a is null || b is null) + return false; + + if (a.ActionId == b.ActionId) + return true; + + if (a.BaseAction != null && a.BaseAction.ActionId == b.ActionId) + return true; + + if (b.BaseAction != null && a.ActionId == b.BaseAction.ActionId) + return true; + + return false; + } + + public static bool operator !=(DataManagerAction? a, DataManagerAction? b) + { + return !(a == b); + } + + public override bool Equals(object? obj) + { + if (ReferenceEquals(this, obj)) + return true; + if (obj is not DataManagerAction action) + return false; + return action == this; + } + + public override int GetHashCode() + { + return ActionId.GetHashCode(); + } +} diff --git a/OwnChar/Data/DataManagerActionResult.cs b/OwnChar/Data/DataManagerActionResult.cs new file mode 100644 index 0000000..924dab2 --- /dev/null +++ b/OwnChar/Data/DataManagerActionResult.cs @@ -0,0 +1,6 @@ +namespace OwnChar.Data; + +public record class DataManagerActionResult(bool HasSuccess, object? Result) +{ + public static DataManagerActionResult NonSuccess { get; } = new(false, null); +} diff --git a/OwnChar/Data/DataManagerActionType.cs b/OwnChar/Data/DataManagerActionType.cs new file mode 100644 index 0000000..18c6716 --- /dev/null +++ b/OwnChar/Data/DataManagerActionType.cs @@ -0,0 +1,9 @@ +namespace OwnChar.Data; + +public enum DataManagerActionType +{ + Default, + Get, + Set, + Delete, +} diff --git a/OwnChar/Data/DataManagerActions.cs b/OwnChar/Data/DataManagerActions.cs new file mode 100644 index 0000000..131f0ca --- /dev/null +++ b/OwnChar/Data/DataManagerActions.cs @@ -0,0 +1,23 @@ +namespace OwnChar.Data; + +public static class DataManagerActions +{ + public static DataManagerAction Create { get; } = new("create"); + public static DataManagerAction Save { get; } = new("save"); + public static DataManagerAction Delete { get; } = new("delete"); + public static DataManagerAction Associate { get; } = new("associate"); + + public static class Creation + { + public static DataManagerAction UserAccount { get; } = new(Create, "useraccount"); + public static DataManagerAction Group { get; } = new(Create, "group"); + public static DataManagerAction Character { get; } = new(Create, "character"); + } + + public static class Association + { + public static DataManagerAction Owner { get; } = new(Associate, "owner"); + public static DataManagerAction Parent { get; } = new(Associate, "parent"); + public static DataManagerAction Members { get; } = new(Associate, "members"); + } +} \ No newline at end of file diff --git a/OwnChar/Data/IDataManager.cs b/OwnChar/Data/IDataManager.cs deleted file mode 100644 index 0e38ceb..0000000 --- a/OwnChar/Data/IDataManager.cs +++ /dev/null @@ -1,30 +0,0 @@ -using OwnChar.Model; - -namespace OwnChar.Data; - -public interface IDataManager -{ - // Login - abstract UserAccount? Login(string username, string password); - abstract bool Logout(UserAccount? account); - - // User management - abstract UserAccount? CreateUserAccount(UserAccount account, string username, string password); - abstract UserProfile? GetUserProfile(UserAccount account); - abstract bool DeleteUserAccount(UserAccount account); - - // Group management - abstract UserProfile? GetOwner(UserAccount account, Group group); - abstract IEnumerable? GetMembers(UserAccount account, Group group); - abstract bool AddMember(UserAccount account, Group group, UserProfile user); - abstract bool RemoveMember(UserAccount account, Group group, UserProfile user); - abstract Group? CreateGroup(UserAccount account, string name); - abstract bool DeleteGroup(UserAccount account, Group group); - - // Character management - abstract UserProfile? GetOwner(UserAccount account, Character group); - abstract IEnumerable? GetCharacters(UserAccount account, Group group); - abstract IEnumerable? GetCharacters(UserAccount account, UserProfile profile); - abstract Character? CreateCharacter(UserAccount account, string name, Group? group); - abstract bool DeleteCharacter(UserAccount account, Character character); -} diff --git a/OwnChar/Data/Managers/DefaultDataManager.cs b/OwnChar/Data/Managers/DefaultDataManager.cs index 426fb02..5c1ec3d 100644 --- a/OwnChar/Data/Managers/DefaultDataManager.cs +++ b/OwnChar/Data/Managers/DefaultDataManager.cs @@ -1,9 +1,13 @@ -using OwnChar.Model; +using OwnChar.Api; +using OwnChar.Model; namespace OwnChar.Data.Managers; public class DefaultDataManager : IDataManager { + public event IDataManager.OnActionEventHandler? OnAction; + public event IDataManager.OnCallbackEventHandler? OnCallback; + private const string defaultUsername = "admin"; private const string defaultPassword = "admin"; @@ -15,6 +19,101 @@ public class DefaultDataManager : IDataManager Initialize(false); } + public virtual DataManagerActionResult ExecuteAction(DataManagerAction action, DataManagerActionType actionType, UserAccount currentUser, OwnCharObject? obj, params object?[] parameters) + { + var success = false; + var e = new OnActionEventArgs(action, actionType, currentUser, obj, parameters); + OnAction?.Invoke(this, e); + + if (e.IsHandled) + return new(true, e.Result); + + if (HandleCreate(e) + || HandleDelete(e) + || HandleSave(e) + || HandleAssociation(e)) + success = true; + + OnCallback?.Invoke(this, new(action, actionType, success, e.Result)); + + return new(success, e.Result); + } + + protected virtual bool HandleCreate(OnActionEventArgs e) + { + if (e.Action != DataManagerActions.Create) + return false; + + // Character + if (e.Action == DataManagerActions.Creation.Character) + { + if (e.Object is not Group group || e.Parameters.Length < 1 || e.Parameters[0] is not string name) + return false; + e.Result = CreateCharacter(e.CurrentUser, name, group); + return e.Result != null; + } + + // Group + if (e.Action == DataManagerActions.Creation.Group) + { + if (e.Parameters.Length < 1 || e.Parameters[0] is not string name) + return false; + e.Result = CreateGroup(e.CurrentUser, name); + return e.Result != null; + } + + // User + if (e.Action == DataManagerActions.Creation.UserAccount) + { + if (e.Parameters.Length < 2 || e.Parameters[0] is not string username || e.Parameters[1] is not string password) + return false; + e.Result = CreateUserAccount(username, password); + return e.Result != null; + } + + return false; + } + + protected virtual bool HandleSave(OnActionEventArgs e) + { + if (e.Action != DataManagerActions.Save) + return false; + + // ... + + return false; + } + + protected virtual bool HandleDelete(OnActionEventArgs e) + { + if (e.Action != DataManagerActions.Delete) + return false; + + // Character + if (e.Object is Character character) + return DeleteCharacter(e.CurrentUser, character); + + // Group + if (e.Object is Group group) + return DeleteGroup(e.CurrentUser, group); + + // User + if (e.Object is UserAccount userAccount) + return DeleteUserAccount(userAccount); + + return false; + } + + protected virtual bool HandleAssociation(OnActionEventArgs e) + { + if (e.Action != DataManagerActions.Associate) + return false; + + // ... + + return false; + } + public IEnumerable? GetMembers(UserAccount account, Group group) { if (!account.HasPermission(UserType.Guest)) @@ -67,7 +166,7 @@ public class DefaultDataManager : IDataManager return result; } - public UserAccount? CreateUserAccount(string username, string password) + protected virtual UserAccount? CreateUserAccount(string username, string password) { var account = DataProvider.Create(); var profile = DataProvider.Create(); @@ -93,7 +192,7 @@ public class DefaultDataManager : IDataManager return account; } - public bool DeleteUserAccount(UserAccount account) + protected virtual bool DeleteUserAccount(UserAccount account) { if (!string.IsNullOrWhiteSpace(account.Username) && DataProvider.GetUserProfile(account.Username) is UserProfile userProfile) userProfile.Name = "Deleted user"; @@ -129,7 +228,7 @@ public class DefaultDataManager : IDataManager return DataProvider.RemoveMember(group, user); } - public Group? CreateGroup(UserAccount account, string name) + protected virtual Group? CreateGroup(UserAccount account, string name) { if (!account.HasPermission(UserType.User) || GetUserProfile(account) is not UserProfile profile || DataProvider.Create() is not Group group) return null; @@ -143,14 +242,14 @@ public class DefaultDataManager : IDataManager return group; } - public bool DeleteGroup(UserAccount account, Group group) + protected virtual bool DeleteGroup(UserAccount account, Group group) { if (GetUserProfile(account) is not UserProfile profile || DataProvider.GetOwner(group) is not UserProfile owner || !account.HasPermission(profile == owner ? UserType.User : UserType.Admin)) return false; return DataProvider.Delete(group); } - public Character? CreateCharacter(UserAccount account, string name, Group? group) + protected virtual Character? CreateCharacter(UserAccount account, string name, Group? group) { if (!account.HasPermission(UserType.User) || GetUserProfile(account) is not UserProfile profile || DataProvider.Create() is not Character character) return null; @@ -167,7 +266,7 @@ public class DefaultDataManager : IDataManager return character; } - public bool DeleteCharacter(UserAccount account, Character character) + protected virtual bool DeleteCharacter(UserAccount account, Character character) { if (GetUserProfile(account) is not UserProfile profile || DataProvider.GetOwner(character) is not UserProfile owner || !account.HasPermission(profile == owner ? UserType.User : UserType.Admin)) return false; diff --git a/OwnChar/Data/Managers/ClientDataManager.cs b/OwnChar/Data/Managers/HttpClientDataManager.cs similarity index 53% rename from OwnChar/Data/Managers/ClientDataManager.cs rename to OwnChar/Data/Managers/HttpClientDataManager.cs index 2f97ae4..990a9d6 100644 --- a/OwnChar/Data/Managers/ClientDataManager.cs +++ b/OwnChar/Data/Managers/HttpClientDataManager.cs @@ -1,5 +1,5 @@ namespace OwnChar.Data.Managers; -public class ClientDataManager +public class HttpClientDataManager { } diff --git a/OwnChar/Data/OnActionEventArgs.cs b/OwnChar/Data/OnActionEventArgs.cs new file mode 100644 index 0000000..27c3eb8 --- /dev/null +++ b/OwnChar/Data/OnActionEventArgs.cs @@ -0,0 +1,14 @@ +using OwnChar.Model; + +namespace OwnChar.Data; + +public class OnActionEventArgs(DataManagerAction action, DataManagerActionType actionType, UserAccount currentUser, OwnCharObject obj, object?[] parameters) : EventArgs +{ + public DataManagerAction Action { get; } = action; + public DataManagerActionType ActionType { get; } = actionType; + public UserAccount CurrentUser { get; } = currentUser; + public OwnCharObject Object { get; } = obj; + public object?[] Parameters { get; } = parameters; + public bool IsHandled { get; set; } + public object? Result { get; set; } +} diff --git a/OwnChar/Data/OnCallbackEventArgs.cs b/OwnChar/Data/OnCallbackEventArgs.cs new file mode 100644 index 0000000..53accb1 --- /dev/null +++ b/OwnChar/Data/OnCallbackEventArgs.cs @@ -0,0 +1,12 @@ +using OwnChar.Model; +using System; + +namespace OwnChar.Data; + +public class OnCallbackEventArgs(DataManagerAction action, DataManagerActionType actionType, bool success, object? result) : EventArgs +{ + public DataManagerAction Action { get; } = action; + public DataManagerActionType ActionType { get; } = actionType; + public bool Success { get; } = success; + public object? Result { get; } = result; +} diff --git a/OwnChar/Data/Providers/JsonFile/JsonFileDataProvider.cs b/OwnChar/Data/Providers/JsonFile/JsonFileDataProvider.cs index 780baeb..1c1ac1a 100644 --- a/OwnChar/Data/Providers/JsonFile/JsonFileDataProvider.cs +++ b/OwnChar/Data/Providers/JsonFile/JsonFileDataProvider.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using OwnChar.Api; using OwnChar.Data.Providers.JsonFile.Model; using OwnChar.Model; @@ -41,10 +42,10 @@ public class JsonFileDataProvider : IDataProvider Formatting = Formatting.Indented, }; } - public T? Create() where T : class, IOwnCharObject + public T? Create() where T : class, OwnCharObject { var t = typeof(T); - IOwnCharObject? obj; + OwnCharObject? obj; if (t == typeof(Property)) obj = new JsonProp(); @@ -64,7 +65,7 @@ public class JsonFileDataProvider : IDataProvider return obj as T; } - public bool Save(T obj) where T : class, IOwnCharObject + public bool Save(T obj) where T : class, OwnCharObject { if (obj is JsonCharacter character) { @@ -95,7 +96,7 @@ public class JsonFileDataProvider : IDataProvider JsonFile.IsInitialized = true; } - public bool Delete(T obj) where T : class, IOwnCharObject + public bool Delete(T obj) where T : class, OwnCharObject { if (obj is JsonCharacter character) { diff --git a/OwnChar/Manager/CharacterManager.cs b/OwnChar/Manager/Modules/CharacterManager.cs similarity index 59% rename from OwnChar/Manager/CharacterManager.cs rename to OwnChar/Manager/Modules/CharacterManager.cs index 8470d1f..780bda8 100644 --- a/OwnChar/Manager/CharacterManager.cs +++ b/OwnChar/Manager/Modules/CharacterManager.cs @@ -1,17 +1,16 @@ -using OwnChar.Model; +using OwnChar.Api; +using OwnChar.Model; -namespace OwnChar.Manager; +namespace OwnChar.Manager.Modules; -public class CharacterManager(OwnCharManager manager) +public class CharacterManager(OwnCharManager manager) : OwnCharManagerModule(manager), ICharacterManager { - public OwnCharManager Manager { get; } = manager; - public IEnumerable? GetCharacters(Group? group) { Manager.CheckLogin(); if (group != null) - return Manager.DataManager.GetCharacters(Manager.CurrentUser, group); + return Manager.DataManager?.GetCharacters(Manager.CurrentUser!, group); return null; } @@ -21,7 +20,7 @@ public class CharacterManager(OwnCharManager manager) Manager.CheckLogin(); if (profile != null) - return Manager.DataManager.GetCharacters(Manager.CurrentUser, profile); + return Manager.DataManager?.GetCharacters(Manager.CurrentUser!, profile); return null; } @@ -34,14 +33,18 @@ public class CharacterManager(OwnCharManager manager) public Character? CreateCharacter(string? name, Group? destination) { ArgumentException.ThrowIfNullOrWhiteSpace(name, nameof(name)); + Manager.CheckLogin(); - return Manager.DataManager.CreateCharacter(Manager.CurrentUser, name, destination); + + return Manager.DataManager?.CreateCharacter(Manager.CurrentUser!, name, destination); } public bool DeleteCharacter(Character? character) { ArgumentNullException.ThrowIfNull(character, nameof(character)); + Manager.CheckLogin(); - return Manager.DataManager.DeleteCharacter(Manager.CurrentUser, character); + + return Manager.DataManager?.DeleteCharacter(Manager.CurrentUser!, character) ?? false; } } diff --git a/OwnChar/Manager/GroupsManager.cs b/OwnChar/Manager/Modules/GroupsManager.cs similarity index 51% rename from OwnChar/Manager/GroupsManager.cs rename to OwnChar/Manager/Modules/GroupsManager.cs index 301ea44..b79e4a8 100644 --- a/OwnChar/Manager/GroupsManager.cs +++ b/OwnChar/Manager/Modules/GroupsManager.cs @@ -1,52 +1,50 @@ -using OwnChar.Model; +using OwnChar.Api; +using OwnChar.Data; +using OwnChar.Model; -namespace OwnChar.Manager; +namespace OwnChar.Manager.Modules; -public class GroupsManager(OwnCharManager manager) +public class GroupsManager(OwnCharManager manager) : OwnCharManagerModule(manager), IGroupsManager { - public OwnCharManager Manager { get; } = manager; - public UserProfile? GetOwner(Group? group) { ArgumentNullException.ThrowIfNull(group, nameof(group)); - Manager.CheckLogin(); - return Manager.DataManager.GetOwner(Manager.CurrentUser, group); + return Manager.DataManager?.GetOwner(Manager.CurrentUser!, group); } public IEnumerable? GetMembers(Group? group) { ArgumentNullException.ThrowIfNull(group, nameof(group)); - Manager.CheckLogin(); - return Manager.DataManager.GetMembers(Manager.CurrentUser, group); + return Manager.DataManager?.GetMembers(Manager.CurrentUser!, group); } public bool AddMember(UserProfile? profile, Group? group) { + Manager.CheckLogin(); ArgumentNullException.ThrowIfNull(profile, nameof(profile)); ArgumentNullException.ThrowIfNull(group, nameof(group)); - Manager.CheckLogin(); - return Manager.DataManager.AddMember(Manager.CurrentUser, group, profile); + return Manager.DataManager.ExecuteAction(DataManagerActions.Association.Members, DataManagerActionType.Set, Manager.CurrentUser!, profile, group).HasSuccess; } public bool DeleteMember(UserProfile? profile, Group? group) { + Manager.CheckLogin(); ArgumentNullException.ThrowIfNull(profile, nameof(profile)); ArgumentNullException.ThrowIfNull(group, nameof(group)); - Manager.CheckLogin(); - return Manager.DataManager.RemoveMember(Manager.CurrentUser, group, profile); + return Manager.DataManager.ExecuteAction(DataManagerActions.Association.Members, DataManagerActionType.Delete, Manager.CurrentUser!, profile, group).HasSuccess; } public Group? CreateGroup(string? name) { - ArgumentException.ThrowIfNullOrWhiteSpace(name, nameof(name)); Manager.CheckLogin(); - return Manager.DataManager.CreateGroup(Manager.CurrentUser, name); + ArgumentException.ThrowIfNullOrWhiteSpace(name, nameof(name)); + return Manager.DataManager.ExecuteAction(DataManagerActions.Creation.Group, DataManagerActionType.Default, Manager.CurrentUser!, null, name).Result as Group; } public bool DeleteGroup(Group? group) { - ArgumentNullException.ThrowIfNull(group, nameof(group)); Manager.CheckLogin(); - return Manager.DataManager.DeleteGroup(Manager.CurrentUser, group); + ArgumentNullException.ThrowIfNull(group, nameof(group)); + return Manager.DataManager.ExecuteAction(DataManagerActions.Delete, DataManagerActionType.Default, Manager.CurrentUser!, group).HasSuccess; } } diff --git a/OwnChar/Manager/UserManager.cs b/OwnChar/Manager/Modules/UserManager.cs similarity index 53% rename from OwnChar/Manager/UserManager.cs rename to OwnChar/Manager/Modules/UserManager.cs index 39580b7..2806b41 100644 --- a/OwnChar/Manager/UserManager.cs +++ b/OwnChar/Manager/Modules/UserManager.cs @@ -1,31 +1,28 @@ -using OwnChar.Model; +using OwnChar.Api; +using OwnChar.Model; using Pilz.Cryptography; -namespace OwnChar.Manager; +namespace OwnChar.Manager.Modules; -public class UserManager(OwnCharManager manager) +public class UserManager(OwnCharManager manager) : OwnCharManagerModule(manager), IUserManager { - public OwnCharManager Manager { get; } = manager; - public UserProfile? GetOwnUserProfile() { Manager.CheckLogin(); - return Manager.DataManager.GetUserProfile(Manager.CurrentUser); + return Manager.DataManager!.GetUserProfile(Manager.CurrentUser!); } public UserAccount? CreateUserAccount(string? username, SecureString? password) { ArgumentException.ThrowIfNullOrWhiteSpace(username, nameof(username)); ArgumentException.ThrowIfNullOrWhiteSpace(password, nameof(password)); - Manager.CheckLogin(); username = username.Trim().ToLower(); - return Manager.DataManager.CreateUserAccount(Manager.CurrentUser, username, Utils.HashPassword(username, password)); + return Manager.DataManager?.CreateUserAccount(username, Utils.HashPassword(username, password)); } public bool DeleteUserAccount(UserAccount? account) { ArgumentNullException.ThrowIfNull(account, nameof(account)); - Manager.CheckLogin(); - return Manager.DataManager.DeleteUserAccount(account); + return Manager.DataManager?.DeleteUserAccount(account) ?? false; } } diff --git a/OwnChar/Manager/OwnCharManager.cs b/OwnChar/Manager/OwnCharManager.cs index f275111..04f6f88 100644 --- a/OwnChar/Manager/OwnCharManager.cs +++ b/OwnChar/Manager/OwnCharManager.cs @@ -1,37 +1,37 @@ -using OwnChar.Data; -using OwnChar.Manager.Exceptions; +using OwnChar.Api; +using OwnChar.Api.Exceptions; +using OwnChar.Manager.Modules; using OwnChar.Model; using Pilz.Cryptography; using System.Diagnostics.CodeAnalysis; namespace OwnChar.Manager; -public class OwnCharManager +public class OwnCharManager : IOwnCharManager { // User - [MemberNotNullWhen(true, nameof(CurrentUser), nameof(DataManager))] - public bool IsLoggedIn => CurrentUser != null && DataManager != null; + public bool IsLoggedIn => CurrentUser != null; public UserAccount? CurrentUser { get; private set; } // Data Provider public IDataManager? DataManager { get; set; } // Manager - public UserManager Users { get; } - public GroupsManager Groups { get; } - public CharacterManager Characters { get; } + public IUserManager Users { get; } + public IGroupsManager Groups { get; } + public ICharacterManager Characters { get; } public OwnCharManager() { - Users = new(this); - Groups = new(this); - Characters = new(this); + Users = new UserManager(this); + Groups = new GroupsManager(this); + Characters = new CharacterManager(this); } [MemberNotNull(nameof(CurrentUser), nameof(DataManager))] internal protected void CheckLogin() { - if (!IsLoggedIn) + if (!IsLoggedIn || DataManager == null) throw new LoginException("You are already logged in!"); } @@ -39,7 +39,6 @@ public class OwnCharManager /// Tries to login on the given data provider. /// /// Returns if the login was successfull and if not. - [MemberNotNullWhen(true, nameof(CurrentUser), nameof(DataManager))] public bool Login(IDataManager? proxy, string? username, SecureString? password) { ArgumentNullException.ThrowIfNull(proxy, nameof(proxy)); diff --git a/OwnChar/Manager/OwnCharManagerModule.cs b/OwnChar/Manager/OwnCharManagerModule.cs new file mode 100644 index 0000000..3a72c7c --- /dev/null +++ b/OwnChar/Manager/OwnCharManagerModule.cs @@ -0,0 +1,6 @@ +namespace OwnChar.Manager; + +public abstract class OwnCharManagerModule(OwnCharManager manager) +{ + public OwnCharManager Manager { get; } = manager; +} diff --git a/OwnChar/Model/Character.cs b/OwnChar/Model/Character.cs index ea1d026..de937a9 100644 --- a/OwnChar/Model/Character.cs +++ b/OwnChar/Model/Character.cs @@ -1,8 +1,7 @@ namespace OwnChar.Model; -public abstract class Character : IOwnCharObject +public abstract class Character : OwnCharObject { public virtual string? Name { get; set; } public virtual string? Fandom { get; set; } - public virtual UserProfile? Owner { get; set; } } diff --git a/OwnChar/Model/Group.cs b/OwnChar/Model/Group.cs index f29dbb1..1cfa775 100644 --- a/OwnChar/Model/Group.cs +++ b/OwnChar/Model/Group.cs @@ -1,6 +1,6 @@ namespace OwnChar.Model; -public abstract class Group : IOwnCharObject +public abstract class Group : OwnCharObject { public virtual string? Name { get; set; } public virtual string? Fandom { get; set; } diff --git a/OwnChar/Model/IOwnCharObject.cs b/OwnChar/Model/IOwnCharObject.cs deleted file mode 100644 index 30078e9..0000000 --- a/OwnChar/Model/IOwnCharObject.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace OwnChar.Model; - -public interface IOwnCharObject -{ -} diff --git a/OwnChar/Model/OwnCharObject.cs b/OwnChar/Model/OwnCharObject.cs new file mode 100644 index 0000000..caa20de --- /dev/null +++ b/OwnChar/Model/OwnCharObject.cs @@ -0,0 +1,6 @@ +namespace OwnChar.Model; + +public class OwnCharObject +{ + public virtual int Id { get; set; } +} diff --git a/OwnChar/Model/Property.cs b/OwnChar/Model/Property.cs index b16f31f..5dd73bc 100644 --- a/OwnChar/Model/Property.cs +++ b/OwnChar/Model/Property.cs @@ -1,6 +1,6 @@ namespace OwnChar.Model; -public abstract class Property : IOwnCharObject +public abstract class Property : OwnCharObject { public virtual string? Name { get; set; } public virtual object? Value { get; set; } diff --git a/OwnChar/Model/PropertyCategory.cs b/OwnChar/Model/PropertyCategory.cs index c3ff4b9..6f59169 100644 --- a/OwnChar/Model/PropertyCategory.cs +++ b/OwnChar/Model/PropertyCategory.cs @@ -1,6 +1,6 @@ namespace OwnChar.Model; -public abstract class PropertyCategory : IOwnCharObject +public abstract class PropertyCategory : OwnCharObject { public virtual string? Name { get; set; } } diff --git a/OwnChar/Model/UserAccount.cs b/OwnChar/Model/UserAccount.cs index 8b38ec9..541547f 100644 --- a/OwnChar/Model/UserAccount.cs +++ b/OwnChar/Model/UserAccount.cs @@ -1,6 +1,6 @@ namespace OwnChar.Model; -public abstract class UserAccount : IOwnCharObject +public abstract class UserAccount : OwnCharObject { public virtual string? Username { get; set; } public virtual string? Password { get; set; } diff --git a/OwnChar/Model/UserProfile.cs b/OwnChar/Model/UserProfile.cs index 99ac413..6457a3b 100644 --- a/OwnChar/Model/UserProfile.cs +++ b/OwnChar/Model/UserProfile.cs @@ -1,6 +1,6 @@ namespace OwnChar.Model; -public abstract class UserProfile : IOwnCharObject +public abstract class UserProfile : OwnCharObject { public virtual string? Name { get; set; } }