From 9ab69ffef5e721f6776c8d040801882b97f2d47f Mon Sep 17 00:00:00 2001 From: ChiaraBm Date: Sun, 5 Oct 2025 16:07:27 +0000 Subject: [PATCH] Upgraded mooncore versions. Cleaned up code, especially startup code. Changed versions --- .../Moonlight.ApiServer.Runtime.csproj | 2 +- Moonlight.ApiServer.Runtime/Program.cs | 23 +++-- .../Admin/ApiKeys/ApiKeysController.cs | 4 +- .../Sys/Customisation/ThemesController.cs | 9 +- .../Admin/Sys/DiagnoseController.cs | 1 - .../Admin/Users/UsersController.cs | 5 +- .../Http/Controllers/Auth/AuthController.cs | 1 - .../Controllers/Frontend/FrontendPage.razor | 1 - .../LocalAuth/LocalAuthController.cs | 2 - Moonlight.ApiServer/IAssemblyMarker.cs | 3 + .../Implementations/Startup/CoreStartup.cs | 34 ++++---- .../Moonlight.ApiServer.csproj | 8 +- Moonlight.ApiServer/Plugins/IPluginStartup.cs | 8 +- Moonlight.ApiServer/Startup/Startup.Auth.cs | 44 +++++----- Moonlight.ApiServer/Startup/Startup.Base.cs | 57 +++++++------ Moonlight.ApiServer/Startup/Startup.Config.cs | 34 ++++---- .../Startup/Startup.Database.cs | 20 ++--- .../Startup/Startup.Hangfire.cs | 23 +++-- .../Startup/Startup.Logging.cs | 39 ++++----- Moonlight.ApiServer/Startup/Startup.Misc.cs | 33 ++++---- .../Startup/Startup.Plugins.cs | 84 +++---------------- .../Startup/Startup.SignalR.cs | 23 ++--- Moonlight.ApiServer/Startup/Startup.cs | 79 ++++++----------- .../Moonlight.Client.Runtime.csproj | 4 +- Moonlight.Client.Runtime/Program.cs | 14 ++-- Moonlight.Client/IAssemblyMarker.cs | 3 + .../Implementations/CoreStartup.cs | 10 +-- Moonlight.Client/Moonlight.Client.csproj | 6 +- Moonlight.Client/Plugins/IPluginStartup.cs | 4 +- Moonlight.Client/Services/ThemeService.cs | 2 - Moonlight.Client/Startup/Startup.Auth.cs | 17 ++-- Moonlight.Client/Startup/Startup.Base.cs | 29 ++++--- Moonlight.Client/Startup/Startup.Logging.cs | 27 ++---- Moonlight.Client/Startup/Startup.Misc.cs | 33 +------- Moonlight.Client/Startup/Startup.Plugins.cs | 77 ++++------------- Moonlight.Client/Startup/Startup.cs | 46 +++------- .../MoonCore.Blazor.FlyonUi/mooncore.map | 62 +++++++++----- Moonlight.Client/Styles/mappings/classes.map | 39 ++++++++- Moonlight.Client/UI/Layouts/MainLayout.razor | 4 +- .../UI/Views/Admin/Api/Index.razor | 37 ++++---- .../Views/Admin/Sys/Customisation/Index.razor | 61 +++++++------- .../UI/Views/Admin/Users/Index.razor | 47 +++++------ Moonlight.Shared/Moonlight.Shared.csproj | 2 +- 43 files changed, 429 insertions(+), 632 deletions(-) create mode 100644 Moonlight.ApiServer/IAssemblyMarker.cs create mode 100644 Moonlight.Client/IAssemblyMarker.cs diff --git a/Moonlight.ApiServer.Runtime/Moonlight.ApiServer.Runtime.csproj b/Moonlight.ApiServer.Runtime/Moonlight.ApiServer.Runtime.csproj index 562c6ad9..44073a4e 100644 --- a/Moonlight.ApiServer.Runtime/Moonlight.ApiServer.Runtime.csproj +++ b/Moonlight.ApiServer.Runtime/Moonlight.ApiServer.Runtime.csproj @@ -18,7 +18,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Moonlight.ApiServer.Runtime/Program.cs b/Moonlight.ApiServer.Runtime/Program.cs index 94027838..5bb192b2 100644 --- a/Moonlight.ApiServer.Runtime/Program.cs +++ b/Moonlight.ApiServer.Runtime/Program.cs @@ -1,28 +1,25 @@ -using Moonlight.ApiServer.Runtime; +using Moonlight.ApiServer.Configuration; +using Moonlight.ApiServer.Runtime; using Moonlight.ApiServer.Startup; var pluginLoader = new PluginLoader(); pluginLoader.Initialize(); -/* -await startup.Run(args, pluginLoader.Instances); - -*/ - -var cs = new Startup(); - -await cs.InitializeAsync(args, pluginLoader.Instances); var builder = WebApplication.CreateBuilder(args); -await cs.AddMoonlightAsync(builder); +builder.AddMoonlight(pluginLoader.Instances); var app = builder.Build(); -await cs.AddMoonlightAsync(app); +app.UseMoonlight(pluginLoader.Instances); + +// Add frontend +var configuration = AppConfiguration.CreateEmpty(); +builder.Configuration.Bind(configuration); // Handle setup of wasm app hosting in the runtime // so the Moonlight.ApiServer doesn't need the wasm package -if (cs.Configuration.Frontend.EnableHosting) +if (configuration.Frontend.EnableHosting) { if (app.Environment.IsDevelopment()) app.UseWebAssemblyDebugging(); @@ -31,5 +28,7 @@ if (cs.Configuration.Frontend.EnableHosting) app.UseStaticFiles(); } +app.MapMoonlight(pluginLoader.Instances); + await app.RunAsync(); \ No newline at end of file diff --git a/Moonlight.ApiServer/Http/Controllers/Admin/ApiKeys/ApiKeysController.cs b/Moonlight.ApiServer/Http/Controllers/Admin/ApiKeys/ApiKeysController.cs index 4cf928e7..f79fc823 100644 --- a/Moonlight.ApiServer/Http/Controllers/Admin/ApiKeys/ApiKeysController.cs +++ b/Moonlight.ApiServer/Http/Controllers/Admin/ApiKeys/ApiKeysController.cs @@ -1,8 +1,8 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using MoonCore.Common; using MoonCore.Extended.Abstractions; -using MoonCore.Models; using Moonlight.ApiServer.Database.Entities; using Moonlight.ApiServer.Mappers; using Moonlight.ApiServer.Services; @@ -26,7 +26,7 @@ public class ApiKeysController : Controller [HttpGet] [Authorize(Policy = "permissions:admin.apikeys.get")] - public async Task>> GetAsync( + public async Task>> GetAsync( [FromQuery] int startIndex, [FromQuery] int count, [FromQuery] string? orderBy, diff --git a/Moonlight.ApiServer/Http/Controllers/Admin/Sys/Customisation/ThemesController.cs b/Moonlight.ApiServer/Http/Controllers/Admin/Sys/Customisation/ThemesController.cs index 0a16e7c3..670fcbe6 100644 --- a/Moonlight.ApiServer/Http/Controllers/Admin/Sys/Customisation/ThemesController.cs +++ b/Moonlight.ApiServer/Http/Controllers/Admin/Sys/Customisation/ThemesController.cs @@ -1,11 +1,8 @@ -using System.ComponentModel.DataAnnotations; -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -using MoonCore.Exceptions; +using MoonCore.Common; using MoonCore.Extended.Abstractions; -using MoonCore.Extended.Models; -using MoonCore.Models; using Moonlight.ApiServer.Database.Entities; using Moonlight.ApiServer.Mappers; using Moonlight.Shared.Http.Requests.Admin.Sys.Theme; @@ -26,7 +23,7 @@ public class ThemesController : Controller [HttpGet] [Authorize(Policy = "permissions:admin.system.customisation.themes.read")] - public async Task>> GetAsync( + public async Task>> GetAsync( [FromQuery] int startIndex, [FromQuery] int count, [FromQuery] string? orderBy, diff --git a/Moonlight.ApiServer/Http/Controllers/Admin/Sys/DiagnoseController.cs b/Moonlight.ApiServer/Http/Controllers/Admin/Sys/DiagnoseController.cs index cc32ded1..d07e7ee9 100644 --- a/Moonlight.ApiServer/Http/Controllers/Admin/Sys/DiagnoseController.cs +++ b/Moonlight.ApiServer/Http/Controllers/Admin/Sys/DiagnoseController.cs @@ -1,5 +1,4 @@ using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Moonlight.ApiServer.Services; using Moonlight.Shared.Http.Requests.Admin.Sys; diff --git a/Moonlight.ApiServer/Http/Controllers/Admin/Users/UsersController.cs b/Moonlight.ApiServer/Http/Controllers/Admin/Users/UsersController.cs index 411c281d..9f11acfa 100644 --- a/Moonlight.ApiServer/Http/Controllers/Admin/Users/UsersController.cs +++ b/Moonlight.ApiServer/Http/Controllers/Admin/Users/UsersController.cs @@ -2,10 +2,9 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; -using MoonCore.Exceptions; +using MoonCore.Common; using MoonCore.Extended.Abstractions; using MoonCore.Extended.Helpers; -using MoonCore.Models; using Moonlight.ApiServer.Database.Entities; using Moonlight.ApiServer.Services; using Moonlight.ApiServer.Mappers; @@ -27,7 +26,7 @@ public class UsersController : Controller [HttpGet] [Authorize(Policy = "permissions:admin.users.get")] - public async Task>> GetAsync( + public async Task>> GetAsync( [FromQuery] int startIndex, [FromQuery] int count, [FromQuery] string? orderBy, diff --git a/Moonlight.ApiServer/Http/Controllers/Auth/AuthController.cs b/Moonlight.ApiServer/Http/Controllers/Auth/AuthController.cs index 6be998cd..790b4177 100644 --- a/Moonlight.ApiServer/Http/Controllers/Auth/AuthController.cs +++ b/Moonlight.ApiServer/Http/Controllers/Auth/AuthController.cs @@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Moonlight.ApiServer.Configuration; -using Moonlight.ApiServer.Implementations.LocalAuth; using Moonlight.ApiServer.Interfaces; using Moonlight.Shared.Http.Responses.Auth; diff --git a/Moonlight.ApiServer/Http/Controllers/Frontend/FrontendPage.razor b/Moonlight.ApiServer/Http/Controllers/Frontend/FrontendPage.razor index d7a7efca..321977af 100644 --- a/Moonlight.ApiServer/Http/Controllers/Frontend/FrontendPage.razor +++ b/Moonlight.ApiServer/Http/Controllers/Frontend/FrontendPage.razor @@ -1,5 +1,4 @@ @using Moonlight.ApiServer.Database.Entities -@using Moonlight.Shared.Misc diff --git a/Moonlight.ApiServer/Http/Controllers/LocalAuth/LocalAuthController.cs b/Moonlight.ApiServer/Http/Controllers/LocalAuth/LocalAuthController.cs index d8715e35..add14783 100644 --- a/Moonlight.ApiServer/Http/Controllers/LocalAuth/LocalAuthController.cs +++ b/Moonlight.ApiServer/Http/Controllers/LocalAuth/LocalAuthController.cs @@ -1,11 +1,9 @@ using System.Security.Claims; using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using MoonCore.Exceptions; using MoonCore.Extended.Abstractions; using MoonCore.Extended.Helpers; using MoonCore.Helpers; diff --git a/Moonlight.ApiServer/IAssemblyMarker.cs b/Moonlight.ApiServer/IAssemblyMarker.cs new file mode 100644 index 00000000..fdbc64c3 --- /dev/null +++ b/Moonlight.ApiServer/IAssemblyMarker.cs @@ -0,0 +1,3 @@ +namespace Moonlight.ApiServer; + +public interface IAssemblyMarker; \ No newline at end of file diff --git a/Moonlight.ApiServer/Implementations/Startup/CoreStartup.cs b/Moonlight.ApiServer/Implementations/Startup/CoreStartup.cs index 042b3619..1fb2f010 100644 --- a/Moonlight.ApiServer/Implementations/Startup/CoreStartup.cs +++ b/Moonlight.ApiServer/Implementations/Startup/CoreStartup.cs @@ -1,7 +1,6 @@ using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; using Moonlight.ApiServer.Configuration; @@ -21,11 +20,12 @@ namespace Moonlight.ApiServer.Implementations.Startup; public class CoreStartup : IPluginStartup { - public Task BuildApplicationAsync(IServiceProvider serviceProvider, IHostApplicationBuilder builder) + public void AddPlugin(WebApplicationBuilder builder) { - var configuration = serviceProvider.GetRequiredService(); - - #region Api Docs + var configuration = AppConfiguration.CreateEmpty(); + builder.Configuration.Bind(configuration); + + #region Api Docs if (configuration.Development.EnableApiDocs) { @@ -138,31 +138,27 @@ public class CoreStartup : IPluginStartup } #endregion - - return Task.CompletedTask; } - public Task ConfigureApplicationAsync(IServiceProvider serviceProvider, IApplicationBuilder app) + public void UsePlugin(WebApplication app) { - var configuration = serviceProvider.GetRequiredService(); - + var configuration = AppConfiguration.CreateEmpty(); + app.Configuration.Bind(configuration); + #region Prometheus if (configuration.OpenTelemetry is { Enable: true, Metrics.EnablePrometheus: true }) app.UseOpenTelemetryPrometheusScrapingEndpoint(); #endregion - - return Task.CompletedTask; } - public Task ConfigureEndpointsAsync(IServiceProvider serviceProvider, IEndpointRouteBuilder routeBuilder) + public void MapPlugin(WebApplication app) { - var configuration = serviceProvider.GetRequiredService(); - + var configuration = AppConfiguration.CreateEmpty(); + app.Configuration.Bind(configuration); + if (configuration.Development.EnableApiDocs) - routeBuilder.MapSwagger("/api/swagger/{documentName}"); - - return Task.CompletedTask; + app.MapSwagger("/api/swagger/{documentName}"); } } \ No newline at end of file diff --git a/Moonlight.ApiServer/Moonlight.ApiServer.csproj b/Moonlight.ApiServer/Moonlight.ApiServer.csproj index 11ea9d5d..5987c097 100644 --- a/Moonlight.ApiServer/Moonlight.ApiServer.csproj +++ b/Moonlight.ApiServer/Moonlight.ApiServer.csproj @@ -13,7 +13,7 @@ Moonlight.ApiServer - 2.1.11 + 2.1.12 Moonlight Panel A build of the api server for moonlight development https://github.com/Moonlight-Panel/Moonlight @@ -27,9 +27,9 @@ - - - + + + diff --git a/Moonlight.ApiServer/Plugins/IPluginStartup.cs b/Moonlight.ApiServer/Plugins/IPluginStartup.cs index 1db8c646..29c56df6 100644 --- a/Moonlight.ApiServer/Plugins/IPluginStartup.cs +++ b/Moonlight.ApiServer/Plugins/IPluginStartup.cs @@ -1,12 +1,10 @@ using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.Hosting; namespace Moonlight.ApiServer.Plugins; public interface IPluginStartup { - public Task BuildApplicationAsync(IServiceProvider serviceProvider, IHostApplicationBuilder builder); - public Task ConfigureApplicationAsync(IServiceProvider serviceProvider, IApplicationBuilder app); - public Task ConfigureEndpointsAsync(IServiceProvider serviceProvider, IEndpointRouteBuilder routeBuilder); + public void AddPlugin(WebApplicationBuilder builder); + public void UsePlugin(WebApplication app); + public void MapPlugin(WebApplication app); } \ No newline at end of file diff --git a/Moonlight.ApiServer/Startup/Startup.Auth.cs b/Moonlight.ApiServer/Startup/Startup.Auth.cs index d2362204..6fc15509 100644 --- a/Moonlight.ApiServer/Startup/Startup.Auth.cs +++ b/Moonlight.ApiServer/Startup/Startup.Auth.cs @@ -3,19 +3,24 @@ using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; using MoonCore.Permissions; +using Moonlight.ApiServer.Configuration; using Moonlight.ApiServer.Implementations.LocalAuth; using Moonlight.ApiServer.Services; namespace Moonlight.ApiServer.Startup; -public partial class Startup +public static partial class Startup { - private Task RegisterAuthAsync() + private static void AddAuth(this WebApplicationBuilder builder) { - WebApplicationBuilder.Services + var configuration = AppConfiguration.CreateEmpty(); + builder.Configuration.Bind(configuration); + + builder.Services .AddAuthentication(options => { options.DefaultScheme = "MainScheme"; }) .AddPolicyScheme("MainScheme", null, options => { @@ -42,15 +47,15 @@ public partial class Startup options.TokenValidationParameters = new() { IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes( - Configuration.Authentication.Secret + configuration.Authentication.Secret )), ValidateIssuerSigningKey = true, ValidateLifetime = true, ClockSkew = TimeSpan.Zero, ValidateAudience = true, - ValidAudience = Configuration.PublicUrl, + ValidAudience = configuration.PublicUrl, ValidateIssuer = true, - ValidIssuer = Configuration.PublicUrl + ValidIssuer = configuration.PublicUrl }; options.Events = new JwtBearerEvents() @@ -81,11 +86,11 @@ public partial class Startup }) .AddCookie("Session", null, options => { - options.ExpireTimeSpan = TimeSpan.FromDays(Configuration.Authentication.Sessions.ExpiresIn); + options.ExpireTimeSpan = TimeSpan.FromDays(configuration.Authentication.Sessions.ExpiresIn); options.Cookie = new CookieBuilder() { - Name = Configuration.Authentication.Sessions.CookieName, + Name = configuration.Authentication.Sessions.CookieName, Path = "/", IsEssential = true, SecurePolicy = CookieSecurePolicy.SameAsRequest @@ -150,16 +155,16 @@ public partial class Startup options.SignInScheme = "Session"; }); - WebApplicationBuilder.Services.AddAuthorization(); + builder.Services.AddAuthorization(); - WebApplicationBuilder.Services.AddAuthorizationPermissions(options => + builder.Services.AddAuthorizationPermissions(options => { options.ClaimName = "Permissions"; options.Prefix = "permissions:"; }); - WebApplicationBuilder.Services.AddScoped(); - WebApplicationBuilder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); // Setup data protection storage within storage folder // so its persists in containers @@ -167,23 +172,18 @@ public partial class Startup Directory.CreateDirectory(dpKeyPath); - WebApplicationBuilder.Services + builder.Services .AddDataProtection() .PersistKeysToFileSystem( new DirectoryInfo(dpKeyPath) ); - WebApplicationBuilder.Services.AddScoped(); - - return Task.CompletedTask; + builder.Services.AddScoped(); } - private Task UseAuthAsync() + private static void UseAuth(this WebApplication application) { - WebApplication.UseAuthentication(); - - WebApplication.UseAuthorization(); - - return Task.CompletedTask; + application.UseAuthentication(); + application.UseAuthorization(); } } \ No newline at end of file diff --git a/Moonlight.ApiServer/Startup/Startup.Base.cs b/Moonlight.ApiServer/Startup/Startup.Base.cs index 48be2b28..c8ee6c85 100644 --- a/Moonlight.ApiServer/Startup/Startup.Base.cs +++ b/Moonlight.ApiServer/Startup/Startup.Base.cs @@ -1,63 +1,62 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using MoonCore.Extended.Extensions; using MoonCore.Extensions; using MoonCore.Helpers; +using Moonlight.ApiServer.Configuration; +using Moonlight.ApiServer.Plugins; namespace Moonlight.ApiServer.Startup; -public partial class Startup +public static partial class Startup { - private Task RegisterBaseAsync() + private static void AddBase(this WebApplicationBuilder builder, IPluginStartup[] startups) { - WebApplicationBuilder.Services.AutoAddServices(); - WebApplicationBuilder.Services.AddHttpClient(); + builder.Services.AutoAddServices(); + builder.Services.AddHttpClient(); - WebApplicationBuilder.Services.AddApiExceptionHandler(); - - // Add pre-existing services - WebApplicationBuilder.Services.AddSingleton(Configuration); + builder.Services.AddApiExceptionHandler(); // Configure controllers - var mvcBuilder = WebApplicationBuilder.Services.AddControllers(); + var mvcBuilder = builder.Services.AddControllers(); // Add plugin assemblies as application parts - foreach (var pluginStartup in PluginStartups.Select(x => x.GetType().Assembly).Distinct()) + foreach (var pluginStartup in startups.Select(x => x.GetType().Assembly).Distinct()) mvcBuilder.AddApplicationPart(pluginStartup.GetType().Assembly); - - return Task.CompletedTask; } - private Task UseBaseAsync() + private static void UseBase(this WebApplication application) { - WebApplication.UseRouting(); - WebApplication.UseExceptionHandler(); - - return Task.CompletedTask; + application.UseRouting(); + application.UseExceptionHandler(); } - private Task MapBaseAsync() + private static void MapBase(this WebApplication application) { - WebApplication.MapControllers(); - - if (Configuration.Frontend.EnableHosting) - WebApplication.MapFallbackToController("Index", "Frontend"); - - return Task.CompletedTask; + application.MapControllers(); + + // Frontend + var configuration = AppConfiguration.CreateEmpty(); + application.Configuration.Bind(configuration); + + if (configuration.Frontend.EnableHosting) + application.MapFallbackToController("Index", "Frontend"); } - private Task ConfigureKestrelAsync() + private static void ConfigureKestrel(this WebApplicationBuilder builder) { - WebApplicationBuilder.WebHost.ConfigureKestrel(kestrelOptions => + var configuration = AppConfiguration.CreateEmpty(); + builder.Configuration.Bind(configuration); + + builder.WebHost.ConfigureKestrel(kestrelOptions => { var maxUploadInBytes = ByteConverter - .FromMegaBytes(Configuration.Kestrel.UploadLimit) + .FromMegaBytes(configuration.Kestrel.UploadLimit) .Bytes; kestrelOptions.Limits.MaxRequestBodySize = maxUploadInBytes; }); - - return Task.CompletedTask; } } \ No newline at end of file diff --git a/Moonlight.ApiServer/Startup/Startup.Config.cs b/Moonlight.ApiServer/Startup/Startup.Config.cs index 3631ad8f..645a0959 100644 --- a/Moonlight.ApiServer/Startup/Startup.Config.cs +++ b/Moonlight.ApiServer/Startup/Startup.Config.cs @@ -1,3 +1,4 @@ +using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using MoonCore.EnvConfiguration; @@ -6,30 +7,23 @@ using Moonlight.ApiServer.Configuration; namespace Moonlight.ApiServer.Startup; -public partial class Startup +public static partial class Startup { - private async Task SetupAppConfigurationAsync() + private static void AddConfiguration(this WebApplicationBuilder builder) { - var configPath = Path.Combine("storage", "config.yml"); + // Yaml + var yamlPath = Path.Combine("storage", "config.yml"); - await YamlDefaultGenerator.GenerateAsync(configPath); + YamlDefaultGenerator.GenerateAsync(yamlPath).Wait(); - // Configure configuration (wow) - var configurationBuilder = new ConfigurationBuilder(); - - configurationBuilder.AddYamlFile(configPath); - configurationBuilder.AddEnvironmentVariables(prefix: "MOONLIGHT_", separator: "_"); - - var configurationRoot = configurationBuilder.Build(); + builder.Configuration.AddYamlFile(yamlPath); - // Retrieve configuration - Configuration = AppConfiguration.CreateEmpty(); - configurationRoot.Bind(Configuration); - } - - private Task RegisterAppConfigurationAsync() - { - WebApplicationBuilder.Services.AddSingleton(Configuration); - return Task.CompletedTask; + // Env + builder.Configuration.AddEnvironmentVariables(prefix: "MOONLIGHT_", separator: "_"); + + var configuration = AppConfiguration.CreateEmpty(); + builder.Configuration.Bind(configuration); + + builder.Services.AddSingleton(configuration); } } \ No newline at end of file diff --git a/Moonlight.ApiServer/Startup/Startup.Database.cs b/Moonlight.ApiServer/Startup/Startup.Database.cs index 6c50f914..109468fb 100644 --- a/Moonlight.ApiServer/Startup/Startup.Database.cs +++ b/Moonlight.ApiServer/Startup/Startup.Database.cs @@ -1,25 +1,17 @@ +using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using MoonCore.Extended.Abstractions; using MoonCore.Extended.Extensions; namespace Moonlight.ApiServer.Startup; -public partial class Startup +public static partial class Startup { - private Task RegisterDatabaseAsync() + private static void AddDatabase(this WebApplicationBuilder builder) { - WebApplicationBuilder.Services.AddDatabaseMappings(); - WebApplicationBuilder.Services.AddServiceCollectionAccessor(); + builder.Services.AddDbAutoMigrations(); + builder.Services.AddDatabaseMappings(); - WebApplicationBuilder.Services.AddScoped(typeof(DatabaseRepository<>)); - - return Task.CompletedTask; - } - - private async Task PrepareDatabaseAsync() - { - await WebApplication.Services.EnsureDatabaseMigratedAsync(); - - WebApplication.Services.GenerateDatabaseMappings(); + builder.Services.AddScoped(typeof(DatabaseRepository<>)); } } \ No newline at end of file diff --git a/Moonlight.ApiServer/Startup/Startup.Hangfire.cs b/Moonlight.ApiServer/Startup/Startup.Hangfire.cs index 2f8922fd..ed61016e 100644 --- a/Moonlight.ApiServer/Startup/Startup.Hangfire.cs +++ b/Moonlight.ApiServer/Startup/Startup.Hangfire.cs @@ -1,5 +1,6 @@ using Hangfire; using Hangfire.EntityFrameworkCore; +using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -7,11 +8,11 @@ using Moonlight.ApiServer.Database; namespace Moonlight.ApiServer.Startup; -public partial class Startup +public static partial class Startup { - private Task RegisterHangfireAsync() + private static void AddMoonlightHangfire(this WebApplicationBuilder builder) { - WebApplicationBuilder.Services.AddHangfire((provider, configuration) => + builder.Services.AddHangfire((provider, configuration) => { configuration.SetDataCompatibilityLevel(CompatibilityLevel.Version_180); configuration.UseSimpleAssemblyNameTypeSerializer(); @@ -23,26 +24,22 @@ public partial class Startup }, new EFCoreStorageOptions()); }); - WebApplicationBuilder.Services.AddHangfireServer(); + builder.Services.AddHangfireServer(); - WebApplicationBuilder.Logging.AddFilter( + builder.Logging.AddFilter( "Hangfire.Server.BackgroundServerProcess", LogLevel.Warning ); - WebApplicationBuilder.Logging.AddFilter( + builder.Logging.AddFilter( "Hangfire.BackgroundJobServer", LogLevel.Warning ); - - return Task.CompletedTask; } - private Task UseHangfireAsync() + private static void UseMoonlightHangfire(this WebApplication application) { - if (WebApplication.Environment.IsDevelopment()) - WebApplication.UseHangfireDashboard(); - - return Task.CompletedTask; + if (application.Environment.IsDevelopment()) + application.UseHangfireDashboard(); } } \ No newline at end of file diff --git a/Moonlight.ApiServer/Startup/Startup.Logging.cs b/Moonlight.ApiServer/Startup/Startup.Logging.cs index 2eb51ed9..b8071a53 100644 --- a/Moonlight.ApiServer/Startup/Startup.Logging.cs +++ b/Moonlight.ApiServer/Startup/Startup.Logging.cs @@ -1,32 +1,24 @@ using System.Text.Json; +using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Logging; using MoonCore.Logging; namespace Moonlight.ApiServer.Startup; -public partial class Startup +public static partial class Startup { - private Task SetupLoggingAsync() + private static void AddLogging(this WebApplicationBuilder builder) { - var loggerFactory = new LoggerFactory(); - loggerFactory.AddAnsiConsole(); - - Logger = loggerFactory.CreateLogger(); - - return Task.CompletedTask; - } - - private async Task RegisterLoggingAsync() - { - // Configure application logging - WebApplicationBuilder.Logging.ClearProviders(); - WebApplicationBuilder.Logging.AddAnsiConsole(); - WebApplicationBuilder.Logging.AddFile(Path.Combine("storage", "logs", "moonlight.log")); + // Logging providers + builder.Logging.ClearProviders(); + + builder.Logging.AddAnsiConsole(); + builder.Logging.AddFile(Path.Combine("storage", "logs", "moonlight.log")); // Logging levels var logConfigPath = Path.Combine("storage", "logConfig.json"); - // Ensure logging config, add a default one is missing + // Ensure default log levels exist if (!File.Exists(logConfigPath)) { var defaultLogLevels = new Dictionary @@ -38,25 +30,26 @@ public partial class Startup }; var logLevelsJson = JsonSerializer.Serialize(defaultLogLevels); - await File.WriteAllTextAsync(logConfigPath, logLevelsJson); + File.WriteAllText(logConfigPath, logLevelsJson); } - // Add logging configuration + // Read log levels var logLevels = JsonSerializer.Deserialize>( - await File.ReadAllTextAsync(logConfigPath) + File.ReadAllText(logConfigPath) )!; + // Apply configured log levels foreach (var level in logLevels) - WebApplicationBuilder.Logging.AddFilter(level.Key, Enum.Parse(level.Value)); + builder.Logging.AddFilter(level.Key, Enum.Parse(level.Value)); // Mute exception handler middleware // https://github.com/dotnet/aspnetcore/issues/19740 - WebApplicationBuilder.Logging.AddFilter( + builder.Logging.AddFilter( "Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware", LogLevel.Critical ); - WebApplicationBuilder.Logging.AddFilter( + builder.Logging.AddFilter( "Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware", LogLevel.Critical ); diff --git a/Moonlight.ApiServer/Startup/Startup.Misc.cs b/Moonlight.ApiServer/Startup/Startup.Misc.cs index d106500a..0b4de7bd 100644 --- a/Moonlight.ApiServer/Startup/Startup.Misc.cs +++ b/Moonlight.ApiServer/Startup/Startup.Misc.cs @@ -1,12 +1,14 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Cors.Infrastructure; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Moonlight.ApiServer.Configuration; namespace Moonlight.ApiServer.Startup; -public partial class Startup +public static partial class Startup { - private Task PrintVersionAsync() + private static void PrintVersionAsync() { // Fancy start console output... yes very fancy :> var rainbow = new Crayon.Rainbow(0.5); @@ -21,23 +23,22 @@ public partial class Startup } Console.WriteLine(); - - return Task.CompletedTask; } - private Task CreateStorageAsync() + private static void CreateStorageAsync() { Directory.CreateDirectory("storage"); Directory.CreateDirectory(Path.Combine("storage", "logs")); - - return Task.CompletedTask; } - - private Task RegisterCorsAsync() - { - var allowedOrigins = Configuration.Kestrel.AllowedOrigins; - WebApplicationBuilder.Services.AddCors(options => + private static void AddMoonlightCors(this WebApplicationBuilder builder) + { + var configuration = AppConfiguration.CreateEmpty(); + builder.Configuration.Bind(configuration); + + var allowedOrigins = configuration.Kestrel.AllowedOrigins; + + builder.Services.AddCors(options => { var cors = new CorsPolicyBuilder(); @@ -60,14 +61,10 @@ public partial class Startup cors.Build() ); }); - - return Task.CompletedTask; } - private Task UseCorsAsync() + private static void UseMoonlightCors(this WebApplication application) { - WebApplication.UseCors(); - - return Task.CompletedTask; + application.UseCors(); } } \ No newline at end of file diff --git a/Moonlight.ApiServer/Startup/Startup.Plugins.cs b/Moonlight.ApiServer/Startup/Startup.Plugins.cs index f6644859..4764d647 100644 --- a/Moonlight.ApiServer/Startup/Startup.Plugins.cs +++ b/Moonlight.ApiServer/Startup/Startup.Plugins.cs @@ -1,87 +1,25 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using MoonCore.Logging; +using Microsoft.AspNetCore.Builder; using Moonlight.ApiServer.Plugins; namespace Moonlight.ApiServer.Startup; -public partial class Startup +public static partial class Startup { - private IServiceProvider PluginLoadServiceProvider; - private IPluginStartup[] PluginStartups; - - private Task InitializePluginsAsync() + private static void AddPlugins(this WebApplicationBuilder builder, IPluginStartup[] startups) { - // Create service provider for starting up - var serviceCollection = new ServiceCollection(); - - serviceCollection.AddSingleton(Configuration); - - serviceCollection.AddLogging(builder => - { - builder.ClearProviders(); - builder.AddAnsiConsole(); - }); - - PluginLoadServiceProvider = serviceCollection.BuildServiceProvider(); - - return Task.CompletedTask; + foreach (var startup in startups) + startup.AddPlugin(builder); } - private async Task HookPluginBuildAsync() + private static void UsePlugins(this WebApplication application, IPluginStartup[] startups) { - foreach (var pluginAppStartup in PluginStartups) - { - try - { - await pluginAppStartup.BuildApplicationAsync(PluginLoadServiceProvider, WebApplicationBuilder); - } - catch (Exception e) - { - Logger.LogError( - "An error occured while processing 'BuildApp' for '{name}': {e}", - pluginAppStartup.GetType().FullName, - e - ); - } - } + foreach (var startup in startups) + startup.UsePlugin(application); } - private async Task HookPluginConfigureAsync() + private static void MapPlugins(this WebApplication application, IPluginStartup[] startups) { - foreach (var pluginAppStartup in PluginStartups) - { - try - { - await pluginAppStartup.ConfigureApplicationAsync(PluginLoadServiceProvider, WebApplication); - } - catch (Exception e) - { - Logger.LogError( - "An error occured while processing 'ConfigureApp' for '{name}': {e}", - pluginAppStartup.GetType().FullName, - e - ); - } - } - } - - private async Task HookPluginEndpointsAsync() - { - foreach (var pluginEndpointStartup in PluginStartups) - { - try - { - await pluginEndpointStartup.ConfigureEndpointsAsync(PluginLoadServiceProvider, WebApplication); - } - catch (Exception e) - { - Logger.LogError( - "An error occured while processing 'ConfigureEndpoints' for '{name}': {e}", - pluginEndpointStartup.GetType().FullName, - e - ); - } - } + foreach (var startup in startups) + startup.MapPlugin(application); } } \ No newline at end of file diff --git a/Moonlight.ApiServer/Startup/Startup.SignalR.cs b/Moonlight.ApiServer/Startup/Startup.SignalR.cs index f1feef1d..51bb233a 100644 --- a/Moonlight.ApiServer/Startup/Startup.SignalR.cs +++ b/Moonlight.ApiServer/Startup/Startup.SignalR.cs @@ -1,25 +1,26 @@ using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Moonlight.ApiServer.Configuration; using Moonlight.ApiServer.Http.Hubs; namespace Moonlight.ApiServer.Startup; -public partial class Startup +public static partial class Startup { - public Task RegisterSignalRAsync() + private static void AddMoonlightSignalR(this WebApplicationBuilder builder) { - var signalRBuilder = WebApplicationBuilder.Services.AddSignalR(); - - if (Configuration.SignalR.UseRedis) - signalRBuilder.AddStackExchangeRedis(Configuration.SignalR.RedisConnectionString); + var configuration = AppConfiguration.CreateEmpty(); + builder.Configuration.Bind(configuration); - return Task.CompletedTask; + var signalRBuilder = builder.Services.AddSignalR(); + + if (configuration.SignalR.UseRedis) + signalRBuilder.AddStackExchangeRedis(configuration.SignalR.RedisConnectionString); } - public Task MapSignalRAsync() + private static void MapMoonlightSignalR(this WebApplication application) { - WebApplication.MapHub("/api/admin/system/diagnose/ws"); - - return Task.CompletedTask; + application.MapHub("/api/admin/system/diagnose/ws"); } } \ No newline at end of file diff --git a/Moonlight.ApiServer/Startup/Startup.cs b/Moonlight.ApiServer/Startup/Startup.cs index e612581f..b21d72b9 100644 --- a/Moonlight.ApiServer/Startup/Startup.cs +++ b/Moonlight.ApiServer/Startup/Startup.cs @@ -1,69 +1,42 @@ using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.Logging; -using Moonlight.ApiServer.Configuration; using Moonlight.ApiServer.Plugins; namespace Moonlight.ApiServer.Startup; -public partial class Startup +public static partial class Startup { - private string[] Args; - - // Logger - public ILogger Logger { get; private set; } - - // Configuration - public AppConfiguration Configuration { get; private set; } - - // WebApplication Stuff - public WebApplication WebApplication { get; private set; } - public WebApplicationBuilder WebApplicationBuilder { get; private set; } - - public Task InitializeAsync(string[] args, IPluginStartup[]? plugins = null) + public static void AddMoonlight(this WebApplicationBuilder builder, IPluginStartup[] startups) { - Args = args; - PluginStartups = plugins ?? []; + PrintVersionAsync(); + CreateStorageAsync(); - return Task.CompletedTask; + builder.AddConfiguration(); + builder.AddLogging(); + + builder.ConfigureKestrel(); + builder.AddBase(startups); + builder.AddDatabase(); + builder.AddAuth(); + builder.AddMoonlightCors(); + builder.AddMoonlightHangfire(); + builder.AddMoonlightSignalR(); + + builder.AddPlugins(startups); } - public async Task AddMoonlightAsync(WebApplicationBuilder builder) + public static void UseMoonlight(this WebApplication application, IPluginStartup[] startups) { - WebApplicationBuilder = builder; - - await PrintVersionAsync(); - - await CreateStorageAsync(); - await SetupAppConfigurationAsync(); - await SetupLoggingAsync(); - await InitializePluginsAsync(); - - await ConfigureKestrelAsync(); - await RegisterAppConfigurationAsync(); - await RegisterLoggingAsync(); - await RegisterBaseAsync(); - await RegisterDatabaseAsync(); - await RegisterAuthAsync(); - await RegisterCorsAsync(); - await RegisterHangfireAsync(); - await RegisterSignalRAsync(); - await HookPluginBuildAsync(); + application.UseBase(); + application.UseMoonlightCors(); + application.UseAuth(); + application.UseMoonlightHangfire(); + application.UsePlugins(startups); } - public async Task AddMoonlightAsync(WebApplication application) + public static void MapMoonlight(this WebApplication application, IPluginStartup[] startups) { - WebApplication = application; - - await PrepareDatabaseAsync(); - - await UseCorsAsync(); - await UseBaseAsync(); - await UseAuthAsync(); - await UseHangfireAsync(); - await HookPluginConfigureAsync(); - - await MapBaseAsync(); - await MapSignalRAsync(); - await HookPluginEndpointsAsync(); + application.MapBase(); + application.MapMoonlightSignalR(); + application.MapPlugins(startups); } } \ No newline at end of file diff --git a/Moonlight.Client.Runtime/Moonlight.Client.Runtime.csproj b/Moonlight.Client.Runtime/Moonlight.Client.Runtime.csproj index 4c67e785..510c55a4 100644 --- a/Moonlight.Client.Runtime/Moonlight.Client.Runtime.csproj +++ b/Moonlight.Client.Runtime/Moonlight.Client.Runtime.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/Moonlight.Client.Runtime/Program.cs b/Moonlight.Client.Runtime/Program.cs index a45cb934..6b4aea89 100644 --- a/Moonlight.Client.Runtime/Program.cs +++ b/Moonlight.Client.Runtime/Program.cs @@ -5,16 +5,12 @@ using Moonlight.Client.Startup; var pluginLoader = new PluginLoader(); pluginLoader.Initialize(); -var startup = new Startup(); +var builder = WebAssemblyHostBuilder.CreateDefault(args); -await startup.InitializeAsync(pluginLoader.Instances); +builder.AddMoonlight(pluginLoader.Instances); -var wasmHostBuilder = WebAssemblyHostBuilder.CreateDefault(args); +var app = builder.Build(); -await startup.AddMoonlightAsync(wasmHostBuilder); +app.ConfigureMoonlight(pluginLoader.Instances); -var wasmApp = wasmHostBuilder.Build(); - -await startup.AddMoonlightAsync(wasmApp); - -await wasmApp.RunAsync(); \ No newline at end of file +await app.RunAsync(); \ No newline at end of file diff --git a/Moonlight.Client/IAssemblyMarker.cs b/Moonlight.Client/IAssemblyMarker.cs new file mode 100644 index 00000000..bd73daa6 --- /dev/null +++ b/Moonlight.Client/IAssemblyMarker.cs @@ -0,0 +1,3 @@ +namespace Moonlight.Client; + +public interface IAssemblyMarker; \ No newline at end of file diff --git a/Moonlight.Client/Implementations/CoreStartup.cs b/Moonlight.Client/Implementations/CoreStartup.cs index b8307bc6..3e009450 100644 --- a/Moonlight.Client/Implementations/CoreStartup.cs +++ b/Moonlight.Client/Implementations/CoreStartup.cs @@ -7,14 +7,14 @@ namespace Moonlight.Client.Implementations; public class CoreStartup : IPluginStartup { - public Task BuildApplicationAsync(IServiceProvider serviceProvider, WebAssemblyHostBuilder builder) + public void AddPlugin(WebAssemblyHostBuilder builder) { builder.Services.AddSingleton(); builder.Services.AddSingleton(); - - return Task.CompletedTask; } - public Task ConfigureApplicationAsync(IServiceProvider serviceProvider, WebAssemblyHost app) - => Task.CompletedTask; + public void ConfigurePlugin(WebAssemblyHost app) + { + + } } \ No newline at end of file diff --git a/Moonlight.Client/Moonlight.Client.csproj b/Moonlight.Client/Moonlight.Client.csproj index 5777e3c2..90754840 100644 --- a/Moonlight.Client/Moonlight.Client.csproj +++ b/Moonlight.Client/Moonlight.Client.csproj @@ -12,7 +12,7 @@ frontend Moonlight.Client - 2.1.11 + 2.1.12 Moonlight Panel A build of the client for moonlight development https://github.com/Moonlight-Panel/Moonlight @@ -25,8 +25,8 @@ - - + + diff --git a/Moonlight.Client/Plugins/IPluginStartup.cs b/Moonlight.Client/Plugins/IPluginStartup.cs index 213d5cd8..2a7c3f8f 100644 --- a/Moonlight.Client/Plugins/IPluginStartup.cs +++ b/Moonlight.Client/Plugins/IPluginStartup.cs @@ -4,6 +4,6 @@ namespace Moonlight.Client.Plugins; public interface IPluginStartup { - public Task BuildApplicationAsync(IServiceProvider serviceProvider, WebAssemblyHostBuilder builder); - public Task ConfigureApplicationAsync(IServiceProvider serviceProvider, WebAssemblyHost app); + public void AddPlugin(WebAssemblyHostBuilder builder); + public void ConfigurePlugin(WebAssemblyHost app); } \ No newline at end of file diff --git a/Moonlight.Client/Services/ThemeService.cs b/Moonlight.Client/Services/ThemeService.cs index 638f743b..58774bff 100644 --- a/Moonlight.Client/Services/ThemeService.cs +++ b/Moonlight.Client/Services/ThemeService.cs @@ -1,9 +1,7 @@ using MoonCore.Attributes; using MoonCore.Helpers; -using MoonCore.Models; using Moonlight.Shared.Http.Requests.Admin.Sys.Theme; using Moonlight.Shared.Http.Responses.Admin; -using Moonlight.Shared.Misc; namespace Moonlight.Client.Services; diff --git a/Moonlight.Client/Startup/Startup.Auth.cs b/Moonlight.Client/Startup/Startup.Auth.cs index d3217534..2f164288 100644 --- a/Moonlight.Client/Startup/Startup.Auth.cs +++ b/Moonlight.Client/Startup/Startup.Auth.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.Extensions.DependencyInjection; using MoonCore.Blazor.FlyonUi.Exceptions; using MoonCore.Permissions; @@ -7,22 +8,20 @@ using Moonlight.Client.Services; namespace Moonlight.Client.Startup; -public partial class Startup +public static partial class Startup { - private Task RegisterAuthenticationAsync() + private static void AddAuth(this WebAssemblyHostBuilder builder) { - WebAssemblyHostBuilder.Services.AddAuthorizationCore(); - WebAssemblyHostBuilder.Services.AddCascadingAuthenticationState(); + builder.Services.AddAuthorizationCore(); + builder.Services.AddCascadingAuthenticationState(); - WebAssemblyHostBuilder.Services.AddScoped(); - WebAssemblyHostBuilder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); - WebAssemblyHostBuilder.Services.AddAuthorizationPermissions(options => + builder.Services.AddAuthorizationPermissions(options => { options.ClaimName = "Permissions"; options.Prefix = "permissions:"; }); - - return Task.CompletedTask; } } \ No newline at end of file diff --git a/Moonlight.Client/Startup/Startup.Base.cs b/Moonlight.Client/Startup/Startup.Base.cs index 6188d904..772af308 100644 --- a/Moonlight.Client/Startup/Startup.Base.cs +++ b/Moonlight.Client/Startup/Startup.Base.cs @@ -1,39 +1,42 @@ +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.Extensions.DependencyInjection; using MoonCore.Blazor.FlyonUi; +using MoonCore.Blazor.FlyonUi.Exceptions; using MoonCore.Extensions; using MoonCore.Helpers; +using Moonlight.Client.Implementations; using Moonlight.Client.Services; using Moonlight.Client.UI; namespace Moonlight.Client.Startup; -public partial class Startup +public static partial class Startup { - private Task RegisterBaseAsync() + private static void AddBase(this WebAssemblyHostBuilder builder) { - WebAssemblyHostBuilder.RootComponents.Add("#app"); - WebAssemblyHostBuilder.RootComponents.Add("head::after"); + builder.RootComponents.Add("#app"); + builder.RootComponents.Add("head::after"); - WebAssemblyHostBuilder.Services.AddScoped(_ => + builder.Services.AddScoped(_ => new HttpClient { - BaseAddress = new Uri(Configuration.ApiUrl) + BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) } ); - WebAssemblyHostBuilder.Services.AddScoped(sp => + builder.Services.AddScoped(sp => { var httpClient = sp.GetRequiredService(); return new HttpApiClient(httpClient); }); - WebAssemblyHostBuilder.Services.AddFileManagerOperations(); - WebAssemblyHostBuilder.Services.AddFlyonUiServices(); + builder.Services.AddFileManagerOperations(); + builder.Services.AddFlyonUiServices(); - WebAssemblyHostBuilder.Services.AddScoped(); + builder.Services.AddScoped(); - WebAssemblyHostBuilder.Services.AutoAddServices(); - - return Task.CompletedTask; + builder.Services.AutoAddServices(); + + builder.Services.AddScoped(); } } \ No newline at end of file diff --git a/Moonlight.Client/Startup/Startup.Logging.cs b/Moonlight.Client/Startup/Startup.Logging.cs index f3ae38e3..045eda2c 100644 --- a/Moonlight.Client/Startup/Startup.Logging.cs +++ b/Moonlight.Client/Startup/Startup.Logging.cs @@ -1,30 +1,13 @@ -using Microsoft.Extensions.DependencyInjection; -using MoonCore.Blazor.FlyonUi.Exceptions; +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using MoonCore.Logging; -using Moonlight.Client.Implementations; namespace Moonlight.Client.Startup; -public partial class Startup +public static partial class Startup { - private Task SetupLoggingAsync() + private static void AddLogging(this WebAssemblyHostBuilder builder) { - var loggerFactory = new LoggerFactory(); - - loggerFactory.AddAnsiConsole(); - - Logger = loggerFactory.CreateLogger(); - - return Task.CompletedTask; - } - - private Task RegisterLoggingAsync() - { - WebAssemblyHostBuilder.Logging.ClearProviders(); - WebAssemblyHostBuilder.Logging.AddAnsiConsole(); - - WebAssemblyHostBuilder.Services.AddScoped(); - - return Task.CompletedTask; + builder.Logging.ClearProviders(); + builder.Logging.AddAnsiConsole(); } } \ No newline at end of file diff --git a/Moonlight.Client/Startup/Startup.Misc.cs b/Moonlight.Client/Startup/Startup.Misc.cs index b93c48f0..08009f57 100644 --- a/Moonlight.Client/Startup/Startup.Misc.cs +++ b/Moonlight.Client/Startup/Startup.Misc.cs @@ -1,12 +1,8 @@ -using System.Text.Json; -using Microsoft.Extensions.DependencyInjection; -using Moonlight.Shared.Misc; - namespace Moonlight.Client.Startup; -public partial class Startup +public static partial class Startup { - private Task PrintVersionAsync() + private static void PrintVersion() { // Fancy start console output... yes very fancy :> Console.Write("Running "); @@ -23,30 +19,5 @@ public partial class Startup } Console.WriteLine(); - - return Task.CompletedTask; - } - - private async Task LoadConfigurationAsync() - { - try - { - using var httpClient = new HttpClient(); - httpClient.BaseAddress = new Uri(WebAssemblyHostBuilder.HostEnvironment.BaseAddress); - - var jsonText = await httpClient.GetStringAsync("frontend.json"); - - Configuration = JsonSerializer.Deserialize(jsonText, new JsonSerializerOptions() - { - PropertyNameCaseInsensitive = true - })!; - - WebAssemblyHostBuilder.Services.AddSingleton(Configuration); - } - catch (Exception e) - { - Logger.LogCritical("Unable to load configuration. Unable to continue: {e}", e); - throw; - } } } \ No newline at end of file diff --git a/Moonlight.Client/Startup/Startup.Plugins.cs b/Moonlight.Client/Startup/Startup.Plugins.cs index 128d11cb..63fcaf77 100644 --- a/Moonlight.Client/Startup/Startup.Plugins.cs +++ b/Moonlight.Client/Startup/Startup.Plugins.cs @@ -1,5 +1,5 @@ +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.Extensions.DependencyInjection; -using MoonCore.Logging; using Moonlight.Client.Plugins; using Moonlight.Client.Services; @@ -7,72 +7,25 @@ namespace Moonlight.Client.Startup; public partial class Startup { - private IPluginStartup[] PluginStartups; - private IServiceProvider PluginLoadServiceProvider; - - private Task InitializePluginsAsync() + private static void AddPlugins(this WebAssemblyHostBuilder builder, IPluginStartup[] startups) { - // Define minimal service collection - var startupSc = new ServiceCollection(); - - // Create logging proxy - startupSc.AddLogging(builder => + foreach (var startup in startups) + startup.AddPlugin(builder); + + // Get all assemblies and combine them into the application assembly service + // TODO: Consider rewriting this as it may not be that performant to do string checking to find distinct items + builder.Services.AddSingleton(new ApplicationAssemblyService() { - builder.ClearProviders(); - builder.AddAnsiConsole(); - }); - - PluginLoadServiceProvider = startupSc.BuildServiceProvider(); - - // Add application assembly service - var appAssemblyService = new ApplicationAssemblyService(); - - appAssemblyService.Assemblies.AddRange( - PluginStartups + Assemblies = startups .Select(x => x.GetType().Assembly) - .Distinct() - ); - - WebAssemblyHostBuilder.Services.AddSingleton(appAssemblyService); - - return Task.CompletedTask; + .DistinctBy(x => x.FullName) + .ToList() + }); } - private async Task HookPluginBuildAsync() + private static void ConfigurePlugins(this WebAssemblyHost app, IPluginStartup[] startups) { - foreach (var pluginAppStartup in PluginStartups) - { - try - { - await pluginAppStartup.BuildApplicationAsync(PluginLoadServiceProvider, WebAssemblyHostBuilder); - } - catch (Exception e) - { - Logger.LogError( - "An error occured while processing 'BuildApp' for '{name}': {e}", - pluginAppStartup.GetType().FullName, - e - ); - } - } - } - - private async Task HookPluginConfigureAsync() - { - foreach (var pluginAppStartup in PluginStartups) - { - try - { - await pluginAppStartup.ConfigureApplicationAsync(PluginLoadServiceProvider, WebAssemblyHost); - } - catch (Exception e) - { - Logger.LogError( - "An error occured while processing 'ConfigureApp' for '{name}': {e}", - pluginAppStartup.GetType().FullName, - e - ); - } - } + foreach (var startup in startups) + startup.ConfigurePlugin(app); } } \ No newline at end of file diff --git a/Moonlight.Client/Startup/Startup.cs b/Moonlight.Client/Startup/Startup.cs index eb60f0d4..ba0c5d95 100644 --- a/Moonlight.Client/Startup/Startup.cs +++ b/Moonlight.Client/Startup/Startup.cs @@ -1,48 +1,22 @@ using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Moonlight.Client.Plugins; -using Moonlight.Shared.Misc; namespace Moonlight.Client.Startup; -public partial class Startup +public static partial class Startup { - public ILogger Logger { get; private set; } - - // WebAssemblyHost - public WebAssemblyHostBuilder WebAssemblyHostBuilder { get; private set; } - public WebAssemblyHost WebAssemblyHost { get; private set; } - - // Configuration - public FrontendConfiguration Configuration { get; private set; } - - - public Task InitializeAsync(IPluginStartup[]? plugins = null) + public static void AddMoonlight(this WebAssemblyHostBuilder builder, IPluginStartup[] startups) { - PluginStartups = plugins ?? []; - - return Task.CompletedTask; + PrintVersion(); + + builder.AddLogging(); + builder.AddBase(); + builder.AddAuth(); + builder.AddPlugins(startups); } - public async Task AddMoonlightAsync(WebAssemblyHostBuilder builder) + public static void ConfigureMoonlight(this WebAssemblyHost app, IPluginStartup[] startups) { - WebAssemblyHostBuilder = builder; - - await PrintVersionAsync(); - - await SetupLoggingAsync(); - await LoadConfigurationAsync(); - await InitializePluginsAsync(); - - await RegisterLoggingAsync(); - await RegisterBaseAsync(); - await RegisterAuthenticationAsync(); - await HookPluginBuildAsync(); - } - - public async Task AddMoonlightAsync(WebAssemblyHost assemblyHost) - { - WebAssemblyHost = assemblyHost; - - await HookPluginConfigureAsync(); + app.ConfigurePlugins(startups); } } \ No newline at end of file diff --git a/Moonlight.Client/Styles/MoonCore.Blazor.FlyonUi/mooncore.map b/Moonlight.Client/Styles/MoonCore.Blazor.FlyonUi/mooncore.map index 691427a6..9ef1ee81 100755 --- a/Moonlight.Client/Styles/MoonCore.Blazor.FlyonUi/mooncore.map +++ b/Moonlight.Client/Styles/MoonCore.Blazor.FlyonUi/mooncore.map @@ -14,7 +14,6 @@ !rounded-xs !text-sm !w-2.5 -*:[grid-area:1/1] *:first:rounded-tl-lg *:last:rounded-tr-lg -left-4 @@ -43,18 +42,11 @@ alert-soft align-bottom align-middle animate-bounce -animate-ping animate-spin -aria-[current='page']:text-bg-soft-primary avatar avatar-placeholder badge -badge-error -badge-info -badge-outline -badge-primary -badge-soft -badge-success +basis-full bg-background bg-background/60 bg-base-100 @@ -62,6 +54,7 @@ bg-base-150 bg-base-200 bg-base-200! bg-base-200/50 +bg-base-250 bg-base-300 bg-base-300/45 bg-base-300/50 @@ -157,7 +150,15 @@ disabled divide-base-150/60 divide-y divider -drop-shadow +drawer +drawer-body +drawer-bottom +drawer-end +drawer-footer +drawer-header +drawer-start +drawer-title +drawer-top dropdown dropdown-active dropdown-disabled @@ -217,14 +218,13 @@ gap-y-2.5 gap-y-3 grid grid-cols-1 -grid-cols-4 grid-flow-col grow grow-0 h-10 h-2 h-3 -h-32 +h-36 h-64 h-8 h-auto @@ -270,7 +270,6 @@ justify-center justify-end justify-start label-text -leading-3 leading-3.5 leading-none left-0 @@ -296,7 +295,6 @@ link-animated link-hover list-disc list-inside -list-none loading loading-sm loading-spinner @@ -310,9 +308,10 @@ max-lg:flex-col max-lg:hidden max-md:flex-wrap max-md:justify-center +max-md:w-full max-sm:hidden +max-w-64 max-w-7xl -max-w-8 max-w-80 max-w-full max-w-lg @@ -323,10 +322,16 @@ mb-1 mb-1.5 mb-2 mb-2.5 +mb-25 mb-3 mb-4 mb-5 +md:flex +md:gap-2 +md:hidden! +md:items-center md:min-w-md +md:navbar-end md:table-cell md:text-3xl me-1 @@ -340,6 +345,7 @@ menu-disabled menu-dropdown menu-dropdown-show menu-horizontal +menu-sm menu-title min-h-0 min-h-svh @@ -376,9 +382,12 @@ mt-5 mt-8 mx-1 mx-auto +my-20 my-3 my-5 my-auto +navbar +navbar-start object-cover opacity-0 opacity-100 @@ -392,6 +401,9 @@ overflow-x-auto overflow-y-auto overlay-open:duration-50 overlay-open:opacity-100 +overlay-open:translate-x-0 +overlay-open:translate-y-0 +p-0 p-0.5 p-1 p-1.5 @@ -403,6 +415,7 @@ p-5 p-6 p-8 pb-1 +pe-1 pin-input placeholder-base-content/60 pointer-events-auto @@ -427,7 +440,6 @@ py-2 py-2.5 py-6 radial-progress -radio range relative resize @@ -455,6 +467,8 @@ selected:select-active shadow-base-300/20 shadow-lg shadow-md +shadow-none +shadow-sm shadow-xs shrink-0 size-10 @@ -462,8 +476,7 @@ size-12 size-4 size-5 size-8 -skeleton -skeleton-animated +size-8.5 sm:auto-cols-max sm:flex sm:items-center @@ -492,7 +505,6 @@ sr-only stack static status -status-error sticky success-message switch @@ -548,26 +560,32 @@ tooltip tooltip-content top-0 top-1/2 +top-3 top-full transform transition transition-all transition-opacity +transition-transform translate-x-0 +translate-x-full truncate underline uppercase validate w-0 w-0.5 -w-12 w-13 +w-20 w-4 w-56 +w-6 w-64 w-fit w-full whitespace-nowrap -z-10 +z-1 z-40 -z-50 \ No newline at end of file +z-50 +z-69 +z-70 \ No newline at end of file diff --git a/Moonlight.Client/Styles/mappings/classes.map b/Moonlight.Client/Styles/mappings/classes.map index 599f38f7..6594176c 100644 --- a/Moonlight.Client/Styles/mappings/classes.map +++ b/Moonlight.Client/Styles/mappings/classes.map @@ -64,6 +64,7 @@ badge-outline badge-primary badge-soft badge-success +basis-full bg-background bg-background/60 bg-base-100 @@ -71,6 +72,7 @@ bg-base-150 bg-base-200 bg-base-200! bg-base-200/50 +bg-base-250 bg-base-300 bg-base-300/45 bg-base-300/50 @@ -189,6 +191,15 @@ disabled divide-base-150/60 divide-y divider +drawer +drawer-body +drawer-bottom +drawer-end +drawer-footer +drawer-header +drawer-start +drawer-title +drawer-top drop-shadow dropdown dropdown-active @@ -275,6 +286,7 @@ h-14 h-2 h-3 h-32 +h-36 h-6 h-64 h-8 @@ -372,7 +384,9 @@ max-lg:flex-col max-lg:hidden max-md:flex-wrap max-md:justify-center +max-md:w-full max-sm:hidden +max-w-64 max-w-7xl max-w-8 max-w-80 @@ -386,14 +400,20 @@ mb-1 mb-1.5 mb-2 mb-2.5 +mb-25 mb-3 mb-4 mb-5 mb-8 md:col-span-1 md:col-span-6 +md:flex +md:gap-2 md:grid-cols-2 +md:hidden! +md:items-center md:min-w-md +md:navbar-end md:table-cell md:text-3xl me-1 @@ -408,6 +428,7 @@ menu-dropdown menu-dropdown-show menu-focus menu-horizontal +menu-sm menu-title min-h-0 min-h-full @@ -452,10 +473,13 @@ mt-8 mx-1 mx-auto my-2.5 +my-20 my-3 my-5 my-8 my-auto +navbar +navbar-start object-cover opacity-0 opacity-100 @@ -470,6 +494,9 @@ overflow-x-hidden overflow-y-auto overlay-open:duration-50 overlay-open:opacity-100 +overlay-open:translate-x-0 +overlay-open:translate-y-0 +p-0 p-0.5 p-1 p-1.5 @@ -481,6 +508,7 @@ p-5 p-6 p-8 pb-1 +pe-1 pe-1.5 pin-input pin-input-underline @@ -548,6 +576,7 @@ shadow shadow-base-300/20 shadow-lg shadow-md +shadow-none shadow-sm shadow-xs shrink-0 @@ -557,6 +586,7 @@ size-4 size-5 size-7 size-8 +size-8.5 skeleton skeleton-animated sm:auto-cols-max @@ -686,6 +716,7 @@ tooltip tooltip-content top-0 top-1/2 +top-3 top-full tracking-tight tracking-wide @@ -693,7 +724,9 @@ transform transition transition-all transition-opacity +transition-transform translate-x-0 +translate-x-full truncate underline uppercase @@ -703,9 +736,11 @@ w-0 w-0.5 w-12 w-13 +w-20 w-32 w-4 w-56 +w-6 w-64 w-8 w-auto @@ -717,4 +752,6 @@ xl:grid-cols-4 z-1 z-10 z-40 -z-50 \ No newline at end of file +z-50 +z-69 +z-70 \ No newline at end of file diff --git a/Moonlight.Client/UI/Layouts/MainLayout.razor b/Moonlight.Client/UI/Layouts/MainLayout.razor index 7e2510ab..943d8cf9 100644 --- a/Moonlight.Client/UI/Layouts/MainLayout.razor +++ b/Moonlight.Client/UI/Layouts/MainLayout.razor @@ -1,4 +1,5 @@ -@using Moonlight.Client.UI.Partials +@using MoonCore.Blazor.FlyonUi.Drawers +@using Moonlight.Client.UI.Partials @using MoonCore.Blazor.FlyonUi.Files.Drop @inherits LayoutComponentBase @@ -20,6 +21,7 @@ + diff --git a/Moonlight.Client/UI/Views/Admin/Api/Index.razor b/Moonlight.Client/UI/Views/Admin/Api/Index.razor index 45630b1a..fd07813a 100644 --- a/Moonlight.Client/UI/Views/Admin/Api/Index.razor +++ b/Moonlight.Client/UI/Views/Admin/Api/Index.razor @@ -1,11 +1,12 @@ @page "/admin/api" +@using MoonCore.Blazor.FlyonUi.Common @using MoonCore.Helpers -@using MoonCore.Models @using Moonlight.Shared.Http.Responses.Admin.ApiKeys @using MoonCore.Blazor.FlyonUi.Grid @using MoonCore.Blazor.FlyonUi.Grid.Columns @using MoonCore.Blazor.FlyonUi.Grid.ToolbarItems +@using MoonCore.Common @inject HttpApiClient ApiClient @inject AlertService AlertService @@ -51,9 +52,7 @@ + ItemSource="ItemSource"> @@ -91,27 +90,25 @@ @code { private DataGrid Grid; - - private async Task> ItemsProviderAsync(DataGridItemRequest request) - { - var query = $"?startIndex={request.StartIndex}&count={request.Count}"; - if (!string.IsNullOrEmpty(request.SortColumn)) + private ItemSource ItemSource => ItemSourceFactory.From(LoadItemsAsync); + + private async Task> LoadItemsAsync( + int startIndex, int count, string? filter, SortOption? sortOption + ) + { + var query = $"?startIndex={startIndex}&count={count}"; + + if (sortOption != null) { - var dir = request.SortDirection == SortState.Descending ? "desc" : "asc"; - query += $"&orderBy={request.SortColumn}&orderByDir={dir}"; + var dir = sortOption.Direction == SortDirection.Descending ? "desc" : "asc"; + query += $"&orderBy={sortOption.Column}&orderByDir={dir}"; } - if (!string.IsNullOrEmpty(request.Filter)) - query += $"&filter={request.Filter}"; + if (!string.IsNullOrEmpty(filter)) + query += $"&filter={filter}"; - var data = await ApiClient.GetJson>($"api/admin/apikeys{query}"); - - return new() - { - Items = data.Items, - TotalCount = data.TotalCount - }; + return await ApiClient.GetJson>($"api/admin/apikeys{query}"); } private async Task DeleteAsync(ApiKeyResponse apiKeyResponse) diff --git a/Moonlight.Client/UI/Views/Admin/Sys/Customisation/Index.razor b/Moonlight.Client/UI/Views/Admin/Sys/Customisation/Index.razor index 615f6fd6..81eec357 100644 --- a/Moonlight.Client/UI/Views/Admin/Sys/Customisation/Index.razor +++ b/Moonlight.Client/UI/Views/Admin/Sys/Customisation/Index.razor @@ -2,12 +2,13 @@ @using System.Text.Json @using Microsoft.AspNetCore.Authorization +@using MoonCore.Blazor.FlyonUi.Common @using MoonCore.Blazor.FlyonUi.Grid @using MoonCore.Blazor.FlyonUi.Grid.Columns @using MoonCore.Blazor.FlyonUi.Grid.ToolbarItems @using MoonCore.Blazor.FlyonUi.Helpers +@using MoonCore.Common @using MoonCore.Helpers -@using MoonCore.Models @using Moonlight.Client.Models @using Moonlight.Client.Services @using Moonlight.Shared.Http.Requests.Admin.Sys.Theme @@ -30,11 +31,9 @@
- - + ItemSource="ItemSource"> + +
@@ -47,9 +46,9 @@
- - - + + +
@@ -69,7 +68,8 @@ } - + Export @@ -90,7 +90,7 @@ Import -
- - - - + ItemSource="ItemSource"> + + + +
@@ -45,29 +43,26 @@ @code { private DataGrid Grid; - - private async Task> ItemsProviderAsync(DataGridItemRequest request) - { - var query = $"?startIndex={request.StartIndex}&count={request.Count}"; + private ItemSource ItemSource => ItemSourceFactory.From(LoadItemsAsync); - if (!string.IsNullOrEmpty(request.SortColumn)) + private async Task> LoadItemsAsync( + int startIndex, int count, string? filter, SortOption? sortOption + ) + { + var query = $"?startIndex={startIndex}&count={count}"; + + if (sortOption != null) { - var dir = request.SortDirection == SortState.Descending ? "desc" : "asc"; - query += $"&orderBy={request.SortColumn}&orderByDir={dir}"; + var dir = sortOption.Direction == SortDirection.Descending ? "desc" : "asc"; + query += $"&orderBy={sortOption.Column}&orderByDir={dir}"; } - if (!string.IsNullOrEmpty(request.Filter)) - query += $"&filter={request.Filter}"; + if (!string.IsNullOrEmpty(filter)) + query += $"&filter={filter}"; - var data = await ApiClient.GetJson>($"api/admin/users{query}"); - - return new() - { - Items = data.Items, - TotalCount = data.TotalCount - }; + return await ApiClient.GetJson>($"api/admin/users{query}"); } - + private async Task DeleteAsync(UserResponse response) { await AlertService.ConfirmDangerAsync( diff --git a/Moonlight.Shared/Moonlight.Shared.csproj b/Moonlight.Shared/Moonlight.Shared.csproj index 83079495..e0e01c49 100644 --- a/Moonlight.Shared/Moonlight.Shared.csproj +++ b/Moonlight.Shared/Moonlight.Shared.csproj @@ -9,7 +9,7 @@ Moonlight.Shared shared Moonlight.Shared - 2.1.11 + 2.1.12 Moonlight Panel A build of the shared classes for moonlight development https://github.com/Moonlight-Panel/Moonlight