From 255ba2348d8b3d75cac13499d6f7c14b951bed92 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 22 Aug 2024 15:12:57 +0200 Subject: [PATCH] party migrate to Pilz.Net --- OwnChar.Server/Api/Endpoint/ApiBuilder.cs | 13 --- OwnChar.Server/Api/Endpoint/ApiMapInfo.cs | 3 - .../Api/Endpoint/ApiRequestMethods.cs | 12 --- .../{Implementations => }/CharactersApi.cs | 5 +- .../{Implementations => }/GroupsApi.cs | 4 +- OwnChar.Server/Api/Endpoint/IApiBuilder.cs | 8 -- .../{Implementations => }/LoginApi.cs | 2 +- .../{Implementations => }/UsersApi.cs | 4 +- OwnChar.Server/Api/IServer.cs | 5 +- .../Api/Plugins/ApiEndpointFeature.cs | 4 +- OwnChar.Server/OwnChar.Server.csproj | 5 +- OwnChar.Server/ServerContext.cs | 102 ++++-------------- 12 files changed, 30 insertions(+), 137 deletions(-) delete mode 100644 OwnChar.Server/Api/Endpoint/ApiBuilder.cs delete mode 100644 OwnChar.Server/Api/Endpoint/ApiMapInfo.cs delete mode 100644 OwnChar.Server/Api/Endpoint/ApiRequestMethods.cs rename OwnChar.Server/Api/Endpoint/{Implementations => }/CharactersApi.cs (81%) rename OwnChar.Server/Api/Endpoint/{Implementations => }/GroupsApi.cs (99%) delete mode 100644 OwnChar.Server/Api/Endpoint/IApiBuilder.cs rename OwnChar.Server/Api/Endpoint/{Implementations => }/LoginApi.cs (95%) rename OwnChar.Server/Api/Endpoint/{Implementations => }/UsersApi.cs (88%) diff --git a/OwnChar.Server/Api/Endpoint/ApiBuilder.cs b/OwnChar.Server/Api/Endpoint/ApiBuilder.cs deleted file mode 100644 index 508c4a0..0000000 --- a/OwnChar.Server/Api/Endpoint/ApiBuilder.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace OwnChar.Server.Api.Endpoint; - -internal class ApiBuilder : IApiBuilder -{ - private readonly Dictionary handlers = []; - - public IReadOnlyDictionary Handlers => handlers; - - public void Map(string pattern, Delegate action) - { - handlers.Add(new(pattern, "POST"), action); - } -} diff --git a/OwnChar.Server/Api/Endpoint/ApiMapInfo.cs b/OwnChar.Server/Api/Endpoint/ApiMapInfo.cs deleted file mode 100644 index 98f25ba..0000000 --- a/OwnChar.Server/Api/Endpoint/ApiMapInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace OwnChar.Server.Api.Endpoint; - -public record struct ApiMapInfo(string Pattern, string Method); \ No newline at end of file diff --git a/OwnChar.Server/Api/Endpoint/ApiRequestMethods.cs b/OwnChar.Server/Api/Endpoint/ApiRequestMethods.cs deleted file mode 100644 index 828e010..0000000 --- a/OwnChar.Server/Api/Endpoint/ApiRequestMethods.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Net; - -namespace OwnChar.Server.Api.Endpoint; - -public static class ApiRequestMethods -{ - public static string Get => WebRequestMethods.Http.Get; - public static string Put => WebRequestMethods.Http.Put; - public static string Post => WebRequestMethods.Http.Post; - public static string Patch => "PATCH"; - public static string Delete => "DELETE"; -} diff --git a/OwnChar.Server/Api/Endpoint/Implementations/CharactersApi.cs b/OwnChar.Server/Api/Endpoint/CharactersApi.cs similarity index 81% rename from OwnChar.Server/Api/Endpoint/Implementations/CharactersApi.cs rename to OwnChar.Server/Api/Endpoint/CharactersApi.cs index ab0f1a4..40469e1 100644 --- a/OwnChar.Server/Api/Endpoint/Implementations/CharactersApi.cs +++ b/OwnChar.Server/Api/Endpoint/CharactersApi.cs @@ -1,7 +1,4 @@ -using OwnChar.Server.Api; -using OwnChar.Server.Api.Endpoint; - -namespace OwnChar.Server.Api.Endpoint.Implementations; +namespace OwnChar.Server.Api.Endpoint; internal class CharactersApi(IServer server) : IApiEndpoint { diff --git a/OwnChar.Server/Api/Endpoint/Implementations/GroupsApi.cs b/OwnChar.Server/Api/Endpoint/GroupsApi.cs similarity index 99% rename from OwnChar.Server/Api/Endpoint/Implementations/GroupsApi.cs rename to OwnChar.Server/Api/Endpoint/GroupsApi.cs index 9bc9f35..808ebaf 100644 --- a/OwnChar.Server/Api/Endpoint/Implementations/GroupsApi.cs +++ b/OwnChar.Server/Api/Endpoint/GroupsApi.cs @@ -7,7 +7,7 @@ using OwnChar.Data.Model.Client; using OwnChar.Server.Data.Model; using OwnChar.Server.Extensions; -namespace OwnChar.Server.Api.Endpoint.Implementations; +namespace OwnChar.Server.Api.Endpoint; internal class GroupsApi(IServer server) : IApiEndpoint { @@ -58,7 +58,7 @@ internal class GroupsApi(IServer server) : IApiEndpoint return TypedResults.Unauthorized(); var group = new GroupDb(); - + if (!string.IsNullOrWhiteSpace(request.Name)) group.Name = request.Name; diff --git a/OwnChar.Server/Api/Endpoint/IApiBuilder.cs b/OwnChar.Server/Api/Endpoint/IApiBuilder.cs deleted file mode 100644 index 8662ef2..0000000 --- a/OwnChar.Server/Api/Endpoint/IApiBuilder.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace OwnChar.Server.Api.Endpoint; - -public interface IApiBuilder -{ - public IReadOnlyDictionary Handlers { get; } - - void Map(string path, Delegate action); -} diff --git a/OwnChar.Server/Api/Endpoint/Implementations/LoginApi.cs b/OwnChar.Server/Api/Endpoint/LoginApi.cs similarity index 95% rename from OwnChar.Server/Api/Endpoint/Implementations/LoginApi.cs rename to OwnChar.Server/Api/Endpoint/LoginApi.cs index 5038938..69aab94 100644 --- a/OwnChar.Server/Api/Endpoint/Implementations/LoginApi.cs +++ b/OwnChar.Server/Api/Endpoint/LoginApi.cs @@ -3,7 +3,7 @@ using OwnChar.Api.Packets.General; using OwnChar.Server.Data.Model; using OwnChar.Server.Extensions; -namespace OwnChar.Server.Api.Endpoint.Implementations; +namespace OwnChar.Server.Api.Endpoint; internal class LoginApi(ServerContext server) : IApiEndpoint { diff --git a/OwnChar.Server/Api/Endpoint/Implementations/UsersApi.cs b/OwnChar.Server/Api/Endpoint/UsersApi.cs similarity index 88% rename from OwnChar.Server/Api/Endpoint/Implementations/UsersApi.cs rename to OwnChar.Server/Api/Endpoint/UsersApi.cs index fbc4cab..f0167bb 100644 --- a/OwnChar.Server/Api/Endpoint/Implementations/UsersApi.cs +++ b/OwnChar.Server/Api/Endpoint/UsersApi.cs @@ -1,6 +1,4 @@ -using OwnChar.Server.Api; - -namespace OwnChar.Server.Api.Endpoint.Implementations; +namespace OwnChar.Server.Api.Endpoint; internal class UsersApi(IServer server) : IApiEndpoint { diff --git a/OwnChar.Server/Api/IServer.cs b/OwnChar.Server/Api/IServer.cs index b12711e..8c64d5e 100644 --- a/OwnChar.Server/Api/IServer.cs +++ b/OwnChar.Server/Api/IServer.cs @@ -1,16 +1,15 @@ using Microsoft.EntityFrameworkCore; using OwnChar.Data.Model.Base; using Pilz.Configuration; +using Pilz.Net.Api; using System.Diagnostics.CodeAnalysis; -using ILogger = Castle.Core.Logging.ILogger; namespace OwnChar.Server.Api; -public interface IServer +public interface IServer : IApiServer { ISettings Settings { get; } DbContext? Data { get; } - ILogger Log { get; } [MemberNotNull(nameof(Data))] void CheckLogin(string secret); diff --git a/OwnChar.Server/Api/Plugins/ApiEndpointFeature.cs b/OwnChar.Server/Api/Plugins/ApiEndpointFeature.cs index aa71c44..e4a770c 100644 --- a/OwnChar.Server/Api/Plugins/ApiEndpointFeature.cs +++ b/OwnChar.Server/Api/Plugins/ApiEndpointFeature.cs @@ -3,9 +3,9 @@ using Pilz.Plugins.Advanced; namespace OwnChar.Server.Api.Plugins; -public abstract class ApiEndpointFeature(string identifier) : PluginFeature(FeatureType, identifier), IApiEndpoint +public abstract class ApiEndpointFeature(string identifier) : PluginFeature(FeatureType, identifier) { public static string FeatureType => "ownchar.server.apiep"; - public abstract void Initialize(IApiBuilder builder); + public abstract void OnServerInit(IServer init); } diff --git a/OwnChar.Server/OwnChar.Server.csproj b/OwnChar.Server/OwnChar.Server.csproj index 86ec53f..64b039d 100644 --- a/OwnChar.Server/OwnChar.Server.csproj +++ b/OwnChar.Server/OwnChar.Server.csproj @@ -8,8 +8,9 @@ - - + + + diff --git a/OwnChar.Server/ServerContext.cs b/OwnChar.Server/ServerContext.cs index 2cf8fbf..9cf8e0f 100644 --- a/OwnChar.Server/ServerContext.cs +++ b/OwnChar.Server/ServerContext.cs @@ -1,124 +1,58 @@ -using Castle.Core.Logging; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using OwnChar.Data.Model.Base; using OwnChar.Server.Api; using OwnChar.Server.Api.Endpoint; -using OwnChar.Server.Api.Endpoint.Implementations; using OwnChar.Server.Api.Plugins; using OwnChar.Server.Data; using Pilz.Configuration; using Pilz.Cryptography; +using Pilz.Extensions.Collections; +using Pilz.Net.Api; using Pilz.Plugins.Advanced; -using System.Net; namespace OwnChar.Server; -internal class ServerContext(ISettings settings) : IServer +internal class ServerContext(ISettings settings) : ApiServer(settings.Get().ApiUrl!), IServer { private readonly Dictionary users = []; - private readonly HttpListener httpListener = new(); - private readonly ApiBuilder apiBuilder = new(); public DbContext? Data { get; private set; } public ISettings Settings { get; } = settings; - public ILogger Log { get; set; } = NullLogger.Instance; - - public void Start(string[] args) + public override void Start() { Log.Info("Prepairing server"); // Load database - Log.Debug("Loading database"); var settings = Settings.Get(); + Log.Debug("Loading database"); Data = new DatabaseContext(settings.DbServer, settings.DbUser, settings.DbPassword); // Built-in endpoints Log.Debug("Loading internal api endpoints"); - var apibuilder = new ApiBuilder(); - new LoginApi(this).Initialize(apibuilder); - new UsersApi(this).Initialize(apibuilder); - new GroupsApi(this).Initialize(apibuilder); - new CharactersApi(this).Initialize(apibuilder); + RegisterHandler(new LoginApi(this)); + RegisterHandler(new UsersApi(this)); + RegisterHandler(new GroupsApi(this)); + RegisterHandler(new CharactersApi(this)); // Plugin endpoints Log.Debug("Loading plugin api endpoints"); - var endpoints = PluginFeatureController.Instance.Features.Get(ApiEndpointFeature.FeatureType).OfType(); - if (endpoints.Any()) - { - foreach (var endpoint in endpoints) - endpoint.Initialize(apibuilder); - } + PluginFeatureController.Instance.Features.Get(ApiEndpointFeature.FeatureType).OfType().ForEach(n => n.OnServerInit(this)); // Run server Log.Info("Starting webserver"); - httpListener.Start(); - Listen(); + base.Start(); } - private void Listen() + protected override string? DecodeAuthKey(string authKey) { - var apiUrl = Settings.Get().ApiUrl; - if (string.IsNullOrWhiteSpace(apiUrl)) - throw new NullReferenceException("ApiUrl is empty!"); + return base.DecodeAuthKey(new SecureString(authKey, true)); + } - while (httpListener.IsListening) - { - var context = httpListener.GetContext(); - - if (context.Request.HttpMethod != HttpMethod.Post.Method - || context.Request.ContentType is not string contentType - || contentType.Contains("application/json") - || context.Request.AcceptTypes is null - || context.Request.AcceptTypes.Contains("application/json")) - { - close(); - continue; - } - - // Parse url - var path = context.Request.Url?.PathAndQuery.Replace(apiUrl, string.Empty); - if (string.IsNullOrWhiteSpace(path) || context.Request.ContentLength64 <= 0) - { - close(); - continue; - } - - // Find mapped function and get target type - if (!apiBuilder.Handlers.TryGetValue(new(path, context.Request.HttpMethod), out var postAction)) - { - close(); - return; - } - // ... - - // Read input content - using StreamReader input = new(context.Request.InputStream); - var contentJson = input.ReadToEnd(); - - // Deserialize request - if (JsonHelpers.DeserializeRequest(contentJson) is not T request) - { - close(); - continue; - } - - // Set response parameters - context.Response.StatusCode = (int)args.ResponseStatusCode; - context.Response.StatusDescription = args.ResponseStatusDescription; - - // Write response content - if (args.ResponseContent != null) - { - context.Response.ContentType = ContentTypes.CONTENT_TYPE_JSON; - using StreamWriter output = new(context.Response.OutputStream); - output.Write(args.ResponseContent); - } - - close(); - void close() => context.Response.OutputStream.Close(); - } + protected override bool CheckAuthentication(string authKey) + { + return base.CheckAuthentication(authKey) || IsLoggedIn(authKey); } public string Login(UserAccountBase account)