diff --git a/OwnChar/Api/Clients/CharactersApiClient.cs b/OwnChar/Api/Clients/CharactersApiClient.cs index 10832c8..de7fcb1 100644 --- a/OwnChar/Api/Clients/CharactersApiClient.cs +++ b/OwnChar/Api/Clients/CharactersApiClient.cs @@ -1,5 +1,5 @@ namespace OwnChar.Api.Clients; -public class CharactersApiClient(OwnCharApiClient client) +internal class CharactersApiClient(OwnCharApiClient client) : ICharactersApiClient { } diff --git a/OwnChar/Api/Clients/GroupsApiClient.cs b/OwnChar/Api/Clients/GroupsApiClient.cs index fbdc347..f06dc98 100644 --- a/OwnChar/Api/Clients/GroupsApiClient.cs +++ b/OwnChar/Api/Clients/GroupsApiClient.cs @@ -4,40 +4,40 @@ using OwnChar.Data.Model.Client; namespace OwnChar.Api.Clients; -public class GroupsApiClient(OwnCharApiClient client) +internal class GroupsApiClient(IOwnCharApiClient client) : IGroupsApiClient { public async Task GetGroup(long id) { - var result = await client.MakeRequest>("/groups/get/byid", new(id)); - result.EnsureSuccess(); - return result.Result; + var result = await client.SendRequest>("/groups/get/byid", new GetSinlgeObjectRequest(id)); + result.EnsureOk(); + return result.Message.Result; } public async Task> GetGroupsForProfile(long userProfileId) { - var result = await client.MakeRequest("/groups/get", new() + var result = await client.SendRequest("/groups/get", new GetGroupsRequest { ProfileId = userProfileId, UseProfileId = true, }); - result.EnsureSuccess(); - return result.Groups; + result.EnsureOk(); + return result.Message.Groups; } public async Task> GetPublicGroups() { - var result = await client.MakeRequest("/groups/get", new()); - result.EnsureSuccess(); - return result.Groups; + var result = await client.SendRequest("/groups/get", new GetGroupsRequest()); + result.EnsureOk(); + return result.Message.Groups; } public async Task> GetAllGroups() { - var result = await client.MakeRequest("/groups/get", new() + var result = await client.SendRequest("/groups/get", new GetGroupsRequest { IncludeNonPublic = true, }); - result.EnsureSuccess(); - return result.Groups; + result.EnsureOk(); + return result.Message.Groups; } } diff --git a/OwnChar/Api/Clients/ICharactersApiClient.cs b/OwnChar/Api/Clients/ICharactersApiClient.cs new file mode 100644 index 0000000..f94f1ae --- /dev/null +++ b/OwnChar/Api/Clients/ICharactersApiClient.cs @@ -0,0 +1,5 @@ +namespace OwnChar.Api.Clients; + +public interface ICharactersApiClient +{ +} diff --git a/OwnChar/Api/Clients/IGroupsApiClient.cs b/OwnChar/Api/Clients/IGroupsApiClient.cs new file mode 100644 index 0000000..6efd24a --- /dev/null +++ b/OwnChar/Api/Clients/IGroupsApiClient.cs @@ -0,0 +1,10 @@ +using OwnChar.Data.Model.Client; + +namespace OwnChar.Api.Clients; +public interface IGroupsApiClient +{ + Task> GetAllGroups(); + Task GetGroup(long id); + Task> GetGroupsForProfile(long userProfileId); + Task> GetPublicGroups(); +} \ No newline at end of file diff --git a/OwnChar/Api/Clients/ILoginApiClient.cs b/OwnChar/Api/Clients/ILoginApiClient.cs new file mode 100644 index 0000000..8c9ed11 --- /dev/null +++ b/OwnChar/Api/Clients/ILoginApiClient.cs @@ -0,0 +1,9 @@ +using OwnChar.Data.Model.Client; +using Pilz.Cryptography; + +namespace OwnChar.Api.Clients; +public interface ILoginApiClient +{ + Task Login(string username, SecureString password); + Task Logout(); +} \ No newline at end of file diff --git a/OwnChar/Api/Clients/IUsersApiClient.cs b/OwnChar/Api/Clients/IUsersApiClient.cs new file mode 100644 index 0000000..8d06886 --- /dev/null +++ b/OwnChar/Api/Clients/IUsersApiClient.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OwnChar.Api.Clients; + +public interface IUsersApiClient +{ +} diff --git a/OwnChar/Api/Clients/LoginApiClient.cs b/OwnChar/Api/Clients/LoginApiClient.cs index 9bb50bb..237421a 100644 --- a/OwnChar/Api/Clients/LoginApiClient.cs +++ b/OwnChar/Api/Clients/LoginApiClient.cs @@ -1,20 +1,21 @@ -using OwnChar.Api.Packets; -using OwnChar.Api.Packets.General; +using OwnChar.Api.Packets.General; using OwnChar.Data.Model.Client; using Pilz.Cryptography; namespace OwnChar.Api.Clients; -public class LoginApiClient(OwnCharApiClient client) +internal class LoginApiClient(OwnCharApiClient client) : ILoginApiClient { public async Task Login(string username, SecureString password) { - var result = await client.MakeRequest("/auth/login", new(username, password)); + var result = await client.SendRequest("/auth/login", new LoginRequest(username, password)); + result.EnsureOk(); - if (!string.IsNullOrEmpty(result.Secret) && result.Profile != null && result.Account != null) + if (!string.IsNullOrEmpty(result.Message.Secret) && result.Message.Profile != null && result.Message.Account != null) { - client.AuthSecret = result.Secret; - return result.Profile; + client.AuthKey = result.Message.Secret; + client.CurrentUser = result.Message.Account; + return result.Message.Profile; } return null; @@ -22,8 +23,8 @@ public class LoginApiClient(OwnCharApiClient client) public async Task Logout() { - await client.MakeRequest("/auth/logout", new()); - client.AuthSecret = null; - return true; + var res = await client.SendRequest("/auth/logout"); + client.AuthKey = null; + return res.IsOk; } } diff --git a/OwnChar/Api/Clients/UsersApiClient.cs b/OwnChar/Api/Clients/UsersApiClient.cs index bc6456a..ce66ef7 100644 --- a/OwnChar/Api/Clients/UsersApiClient.cs +++ b/OwnChar/Api/Clients/UsersApiClient.cs @@ -1,5 +1,5 @@ namespace OwnChar.Api.Clients; -public class UsersApiClient(OwnCharApiClient client) +internal class UsersApiClient(IOwnCharApiClient client) : IUsersApiClient { } diff --git a/OwnChar/Api/IOwnCharApiClient.cs b/OwnChar/Api/IOwnCharApiClient.cs new file mode 100644 index 0000000..86ceb8b --- /dev/null +++ b/OwnChar/Api/IOwnCharApiClient.cs @@ -0,0 +1,21 @@ +using OwnChar.Api.Clients; +using OwnChar.Data.Model.Client; +using Pilz.Net.Api; +using System.Diagnostics.CodeAnalysis; + +namespace OwnChar.Api; +public interface IOwnCharApiClient : IApiClient +{ + UserAccount? CurrentUser { get; } + + [MemberNotNullWhen(true, nameof(AuthKey), nameof(CurrentUser))] + bool IsLoggedIn { get; } + + ILoginApiClient Auth { get; } + + IGroupsApiClient Groups { get; } + + ICharactersApiClient Characters { get; } + + IUsersApiClient Users { get; } +} \ No newline at end of file diff --git a/OwnChar/Api/OwnCharApiClient.cs b/OwnChar/Api/OwnCharApiClient.cs index 8052a4f..06eb7a3 100644 --- a/OwnChar/Api/OwnCharApiClient.cs +++ b/OwnChar/Api/OwnCharApiClient.cs @@ -1,49 +1,38 @@ using OwnChar.Api.Clients; -using OwnChar.Api.Exceptions; -using OwnChar.Api.Packets; +using OwnChar.Data.Model.Client; using Pilz.Cryptography; using Pilz.Net.Api; +using System.Diagnostics.CodeAnalysis; namespace OwnChar.Api; -public class OwnCharApiClient : ApiClient +internal class OwnCharApiClient : ApiClient, IOwnCharApiClient { - private readonly Dictionary clients = []; + public UserAccount? CurrentUser { get; internal set; } - internal string? AuthSecret { get; set; } = null; - public bool IsLoggedIn => AuthSecret != null; + [MemberNotNullWhen(true, nameof(AuthKey), nameof(CurrentUser))] + public bool IsLoggedIn => CurrentUser != null && !string.IsNullOrWhiteSpace(AuthKey); - public LoginApiClient Auth { get; } - public UsersApiClient Users { get; } - public CharactersApiClient Characters { get; } - public GroupsApiClient Groups { get; } + public ILoginApiClient Auth { get; } + + public IGroupsApiClient Groups { get; } + + public ICharactersApiClient Characters { get; } + + public IUsersApiClient Users { get; } public OwnCharApiClient(string apiUrl) : base(apiUrl) { - Auth = GetClient(); - Users = GetClient(); - Characters = GetClient(); - Groups = GetClient(); - } - - public T GetClient() where T : class - { - var t = typeof(T); - - if (clients.TryGetValue(t, out var client) && client is T clientT1) - return clientT1; - - if (Activator.CreateInstance(t, this) is T clientT2) - { - clients.Add(t, clientT2); - return clientT2; - } - - throw new Exception("Client could not be created!"); + Auth = new LoginApiClient(this); + Groups = new GroupsApiClient(this); + Characters = new CharactersApiClient(this); + Users = new UsersApiClient(this); } protected override string? EncodeAuthKey() { - return new SecureString(base.EncodeAuthKey(), false); + if (IsLoggedIn && !string.IsNullOrWhiteSpace(CurrentUser.Username)) + return new SecureString($"{CurrentUser}:{AuthKey}", false).EncryptedValue; + return AuthKey; } } diff --git a/OwnChar/Api/Packets/General/DeleteObjectResponse.cs b/OwnChar/Api/Packets/General/DeleteObjectResponse.cs deleted file mode 100644 index 5ac38e8..0000000 --- a/OwnChar/Api/Packets/General/DeleteObjectResponse.cs +++ /dev/null @@ -1,7 +0,0 @@ -using OwnChar.Api.Packets; - -namespace OwnChar.Api.Packets.General; - -public class DeleteObjectResponse : OwnCharResponse -{ -} diff --git a/OwnChar/Api/Packets/General/LogoutRequest.cs b/OwnChar/Api/Packets/General/LogoutRequest.cs deleted file mode 100644 index bd5a4c2..0000000 --- a/OwnChar/Api/Packets/General/LogoutRequest.cs +++ /dev/null @@ -1,7 +0,0 @@ -using OwnChar.Api.Packets; - -namespace OwnChar.Api.Packets.General; - -public class LogoutRequest : OwnCharRequest -{ -} diff --git a/OwnChar/Api/Packets/General/LogoutResponse.cs b/OwnChar/Api/Packets/General/LogoutResponse.cs deleted file mode 100644 index 6d90973..0000000 --- a/OwnChar/Api/Packets/General/LogoutResponse.cs +++ /dev/null @@ -1,7 +0,0 @@ -using OwnChar.Api.Packets; - -namespace OwnChar.Api.Packets.General; - -public class LogoutResponse : OwnCharResponse -{ -} diff --git a/OwnChar/Api/Packets/General/SetOwnerResponse.cs b/OwnChar/Api/Packets/General/SetOwnerResponse.cs deleted file mode 100644 index 8f49dbe..0000000 --- a/OwnChar/Api/Packets/General/SetOwnerResponse.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace OwnChar.Api.Packets.General; - -public class SetOwnerResponse : OwnCharResponse -{ -} diff --git a/OwnChar/Api/Packets/General/UpdateResponse.cs b/OwnChar/Api/Packets/General/UpdateResponse.cs deleted file mode 100644 index a67686e..0000000 --- a/OwnChar/Api/Packets/General/UpdateResponse.cs +++ /dev/null @@ -1,7 +0,0 @@ -using OwnChar.Api.Packets; - -namespace OwnChar.Api.Packets.General; - -public class UpdateResponse : OwnCharResponse -{ -} diff --git a/OwnChar/Api/Packets/OwnCharRequest.cs b/OwnChar/Api/Packets/OwnCharRequest.cs index 1b66310..7f5f777 100644 --- a/OwnChar/Api/Packets/OwnCharRequest.cs +++ b/OwnChar/Api/Packets/OwnCharRequest.cs @@ -1,9 +1,7 @@ -using Pilz.Cryptography; +using Pilz.Net.Api; namespace OwnChar.Api.Packets; -public class OwnCharRequest +public class OwnCharRequest : ApiMessage { - public string? Username { get; set; } = null; - public SecureString? AuthSecret { get; set; } = null; } diff --git a/OwnChar/Api/Packets/OwnCharResponse.cs b/OwnChar/Api/Packets/OwnCharResponse.cs index adea60a..9396e71 100644 --- a/OwnChar/Api/Packets/OwnCharResponse.cs +++ b/OwnChar/Api/Packets/OwnCharResponse.cs @@ -1,11 +1,7 @@ -using System.Text.Json.Serialization; +using Pilz.Net.Api; namespace OwnChar.Api.Packets; -public class OwnCharResponse +public class OwnCharResponse : ApiMessage { - public OwnCharResponseError ErrorCode { get; set; } - - [JsonIgnore] - public bool IsSuccess => ErrorCode != OwnCharResponseError.None; } diff --git a/OwnChar/Api/Packets/OwnCharResponseError.cs b/OwnChar/Api/Packets/OwnCharResponseError.cs deleted file mode 100644 index 9d3c45b..0000000 --- a/OwnChar/Api/Packets/OwnCharResponseError.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace OwnChar.Api.Packets; - -public enum OwnCharResponseError -{ - None, - Default, - NotFound, - StillInUse, -} diff --git a/OwnChar/Extensions/ApiRequestInfoExtensions.cs b/OwnChar/Extensions/ApiRequestInfoExtensions.cs new file mode 100644 index 0000000..d6942a1 --- /dev/null +++ b/OwnChar/Extensions/ApiRequestInfoExtensions.cs @@ -0,0 +1,11 @@ +using Pilz.Net.Api; + +namespace OwnChar.Extensions; + +public static class ApiRequestInfoExtensions +{ + public static string? GetUsername(this ApiRequestInfo @this) + { + return @this.AuthKey?.Split(':').ElementAtOrDefault(0); + } +} diff --git a/OwnChar/IOwnCharManager.cs b/OwnChar/IOwnCharManager.cs index 93309b6..3534f18 100644 --- a/OwnChar/IOwnCharManager.cs +++ b/OwnChar/IOwnCharManager.cs @@ -8,17 +8,16 @@ namespace OwnChar; public interface IOwnCharManager { bool IsLoggedIn { get; } - OwnCharApiClient? Api { get; } + + IOwnCharApiClient? Api { get; } IUserManager Users { get; } + IGroupsManager Groups { get; } + ICharacterManager Characters { get; } Task Login(string? username, SecureString? password); - Task Logout(); - public static IOwnCharManager CreateDefault() - { - return new OwnCharManager(); - } + Task Logout(); } \ No newline at end of file diff --git a/OwnChar/OwnCharManager.cs b/OwnChar/OwnCharManager.cs index af08da6..94157d2 100644 --- a/OwnChar/OwnCharManager.cs +++ b/OwnChar/OwnCharManager.cs @@ -7,17 +7,17 @@ using System.Diagnostics.CodeAnalysis; namespace OwnChar; -internal class OwnCharManager : IOwnCharManager +public class OwnCharManager : IOwnCharManager { - // User + [MemberNotNullWhen(true, nameof(Api))] public bool IsLoggedIn => Api is not null && Api.IsLoggedIn; - // Data Provider - public OwnCharApiClient? Api { get; private set; } + public IOwnCharApiClient? Api { get; private set; } - // Manager public IUserManager Users { get; } + public IGroupsManager Groups { get; } + public ICharacterManager Characters { get; } public OwnCharManager()