Upgraded mooncore versions. Cleaned up code, especially startup code. Changed versions
This commit is contained in:
@@ -18,7 +18,7 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.8" />
|
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.9" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Import Project="Plugins.props" />
|
<Import Project="Plugins.props" />
|
||||||
|
|||||||
@@ -1,28 +1,25 @@
|
|||||||
using Moonlight.ApiServer.Runtime;
|
using Moonlight.ApiServer.Configuration;
|
||||||
|
using Moonlight.ApiServer.Runtime;
|
||||||
using Moonlight.ApiServer.Startup;
|
using Moonlight.ApiServer.Startup;
|
||||||
|
|
||||||
var pluginLoader = new PluginLoader();
|
var pluginLoader = new PluginLoader();
|
||||||
pluginLoader.Initialize();
|
pluginLoader.Initialize();
|
||||||
/*
|
|
||||||
await startup.Run(args, pluginLoader.Instances);
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
var cs = new Startup();
|
|
||||||
|
|
||||||
await cs.InitializeAsync(args, pluginLoader.Instances);
|
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
await cs.AddMoonlightAsync(builder);
|
builder.AddMoonlight(pluginLoader.Instances);
|
||||||
|
|
||||||
var app = builder.Build();
|
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
|
// Handle setup of wasm app hosting in the runtime
|
||||||
// so the Moonlight.ApiServer doesn't need the wasm package
|
// so the Moonlight.ApiServer doesn't need the wasm package
|
||||||
if (cs.Configuration.Frontend.EnableHosting)
|
if (configuration.Frontend.EnableHosting)
|
||||||
{
|
{
|
||||||
if (app.Environment.IsDevelopment())
|
if (app.Environment.IsDevelopment())
|
||||||
app.UseWebAssemblyDebugging();
|
app.UseWebAssemblyDebugging();
|
||||||
@@ -31,5 +28,7 @@ if (cs.Configuration.Frontend.EnableHosting)
|
|||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.MapMoonlight(pluginLoader.Instances);
|
||||||
|
|
||||||
|
|
||||||
await app.RunAsync();
|
await app.RunAsync();
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using MoonCore.Common;
|
||||||
using MoonCore.Extended.Abstractions;
|
using MoonCore.Extended.Abstractions;
|
||||||
using MoonCore.Models;
|
|
||||||
using Moonlight.ApiServer.Database.Entities;
|
using Moonlight.ApiServer.Database.Entities;
|
||||||
using Moonlight.ApiServer.Mappers;
|
using Moonlight.ApiServer.Mappers;
|
||||||
using Moonlight.ApiServer.Services;
|
using Moonlight.ApiServer.Services;
|
||||||
@@ -26,7 +26,7 @@ public class ApiKeysController : Controller
|
|||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Authorize(Policy = "permissions:admin.apikeys.get")]
|
[Authorize(Policy = "permissions:admin.apikeys.get")]
|
||||||
public async Task<ActionResult<ICountedData<ApiKeyResponse>>> GetAsync(
|
public async Task<ActionResult<CountedData<ApiKeyResponse>>> GetAsync(
|
||||||
[FromQuery] int startIndex,
|
[FromQuery] int startIndex,
|
||||||
[FromQuery] int count,
|
[FromQuery] int count,
|
||||||
[FromQuery] string? orderBy,
|
[FromQuery] string? orderBy,
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using MoonCore.Exceptions;
|
using MoonCore.Common;
|
||||||
using MoonCore.Extended.Abstractions;
|
using MoonCore.Extended.Abstractions;
|
||||||
using MoonCore.Extended.Models;
|
|
||||||
using MoonCore.Models;
|
|
||||||
using Moonlight.ApiServer.Database.Entities;
|
using Moonlight.ApiServer.Database.Entities;
|
||||||
using Moonlight.ApiServer.Mappers;
|
using Moonlight.ApiServer.Mappers;
|
||||||
using Moonlight.Shared.Http.Requests.Admin.Sys.Theme;
|
using Moonlight.Shared.Http.Requests.Admin.Sys.Theme;
|
||||||
@@ -26,7 +23,7 @@ public class ThemesController : Controller
|
|||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Authorize(Policy = "permissions:admin.system.customisation.themes.read")]
|
[Authorize(Policy = "permissions:admin.system.customisation.themes.read")]
|
||||||
public async Task<ActionResult<ICountedData<ThemeResponse>>> GetAsync(
|
public async Task<ActionResult<CountedData<ThemeResponse>>> GetAsync(
|
||||||
[FromQuery] int startIndex,
|
[FromQuery] int startIndex,
|
||||||
[FromQuery] int count,
|
[FromQuery] int count,
|
||||||
[FromQuery] string? orderBy,
|
[FromQuery] string? orderBy,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Moonlight.ApiServer.Services;
|
using Moonlight.ApiServer.Services;
|
||||||
using Moonlight.Shared.Http.Requests.Admin.Sys;
|
using Moonlight.Shared.Http.Requests.Admin.Sys;
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ using Microsoft.AspNetCore.Authorization;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using MoonCore.Exceptions;
|
using MoonCore.Common;
|
||||||
using MoonCore.Extended.Abstractions;
|
using MoonCore.Extended.Abstractions;
|
||||||
using MoonCore.Extended.Helpers;
|
using MoonCore.Extended.Helpers;
|
||||||
using MoonCore.Models;
|
|
||||||
using Moonlight.ApiServer.Database.Entities;
|
using Moonlight.ApiServer.Database.Entities;
|
||||||
using Moonlight.ApiServer.Services;
|
using Moonlight.ApiServer.Services;
|
||||||
using Moonlight.ApiServer.Mappers;
|
using Moonlight.ApiServer.Mappers;
|
||||||
@@ -27,7 +26,7 @@ public class UsersController : Controller
|
|||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Authorize(Policy = "permissions:admin.users.get")]
|
[Authorize(Policy = "permissions:admin.users.get")]
|
||||||
public async Task<ActionResult<ICountedData<UserResponse>>> GetAsync(
|
public async Task<ActionResult<CountedData<UserResponse>>> GetAsync(
|
||||||
[FromQuery] int startIndex,
|
[FromQuery] int startIndex,
|
||||||
[FromQuery] int count,
|
[FromQuery] int count,
|
||||||
[FromQuery] string? orderBy,
|
[FromQuery] string? orderBy,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Authorization;
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Moonlight.ApiServer.Configuration;
|
using Moonlight.ApiServer.Configuration;
|
||||||
using Moonlight.ApiServer.Implementations.LocalAuth;
|
|
||||||
using Moonlight.ApiServer.Interfaces;
|
using Moonlight.ApiServer.Interfaces;
|
||||||
using Moonlight.Shared.Http.Responses.Auth;
|
using Moonlight.Shared.Http.Responses.Auth;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
@using Moonlight.ApiServer.Database.Entities
|
@using Moonlight.ApiServer.Database.Entities
|
||||||
@using Moonlight.Shared.Misc
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-background text-base-content font-inter">
|
<html lang="en" class="bg-background text-base-content font-inter">
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using MoonCore.Exceptions;
|
|
||||||
using MoonCore.Extended.Abstractions;
|
using MoonCore.Extended.Abstractions;
|
||||||
using MoonCore.Extended.Helpers;
|
using MoonCore.Extended.Helpers;
|
||||||
using MoonCore.Helpers;
|
using MoonCore.Helpers;
|
||||||
|
|||||||
3
Moonlight.ApiServer/IAssemblyMarker.cs
Normal file
3
Moonlight.ApiServer/IAssemblyMarker.cs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Moonlight.ApiServer;
|
||||||
|
|
||||||
|
public interface IAssemblyMarker;
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Moonlight.ApiServer.Configuration;
|
using Moonlight.ApiServer.Configuration;
|
||||||
@@ -21,9 +20,10 @@ namespace Moonlight.ApiServer.Implementations.Startup;
|
|||||||
|
|
||||||
public class CoreStartup : IPluginStartup
|
public class CoreStartup : IPluginStartup
|
||||||
{
|
{
|
||||||
public Task BuildApplicationAsync(IServiceProvider serviceProvider, IHostApplicationBuilder builder)
|
public void AddPlugin(WebApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
var configuration = serviceProvider.GetRequiredService<AppConfiguration>();
|
var configuration = AppConfiguration.CreateEmpty();
|
||||||
|
builder.Configuration.Bind(configuration);
|
||||||
|
|
||||||
#region Api Docs
|
#region Api Docs
|
||||||
|
|
||||||
@@ -138,13 +138,12 @@ public class CoreStartup : IPluginStartup
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task ConfigureApplicationAsync(IServiceProvider serviceProvider, IApplicationBuilder app)
|
public void UsePlugin(WebApplication app)
|
||||||
{
|
{
|
||||||
var configuration = serviceProvider.GetRequiredService<AppConfiguration>();
|
var configuration = AppConfiguration.CreateEmpty();
|
||||||
|
app.Configuration.Bind(configuration);
|
||||||
|
|
||||||
#region Prometheus
|
#region Prometheus
|
||||||
|
|
||||||
@@ -152,17 +151,14 @@ public class CoreStartup : IPluginStartup
|
|||||||
app.UseOpenTelemetryPrometheusScrapingEndpoint();
|
app.UseOpenTelemetryPrometheusScrapingEndpoint();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task ConfigureEndpointsAsync(IServiceProvider serviceProvider, IEndpointRouteBuilder routeBuilder)
|
public void MapPlugin(WebApplication app)
|
||||||
{
|
{
|
||||||
var configuration = serviceProvider.GetRequiredService<AppConfiguration>();
|
var configuration = AppConfiguration.CreateEmpty();
|
||||||
|
app.Configuration.Bind(configuration);
|
||||||
|
|
||||||
if (configuration.Development.EnableApiDocs)
|
if (configuration.Development.EnableApiDocs)
|
||||||
routeBuilder.MapSwagger("/api/swagger/{documentName}");
|
app.MapSwagger("/api/swagger/{documentName}");
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PackageId>Moonlight.ApiServer</PackageId>
|
<PackageId>Moonlight.ApiServer</PackageId>
|
||||||
<Version>2.1.11</Version>
|
<Version>2.1.12</Version>
|
||||||
<Authors>Moonlight Panel</Authors>
|
<Authors>Moonlight Panel</Authors>
|
||||||
<Description>A build of the api server for moonlight development</Description>
|
<Description>A build of the api server for moonlight development</Description>
|
||||||
<PackageProjectUrl>https://github.com/Moonlight-Panel/Moonlight</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/Moonlight-Panel/Moonlight</PackageProjectUrl>
|
||||||
@@ -27,9 +27,9 @@
|
|||||||
<PackageReference Include="Hangfire.EntityFrameworkCore" Version="0.7.0"/>
|
<PackageReference Include="Hangfire.EntityFrameworkCore" Version="0.7.0"/>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.9" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.9" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="9.0.9" />
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="9.0.9" />
|
||||||
<PackageReference Include="MoonCore" Version="2.0.1" />
|
<PackageReference Include="MoonCore" Version="2.0.4" />
|
||||||
<PackageReference Include="MoonCore.Extended" Version="1.4.0" />
|
<PackageReference Include="MoonCore.Extended" Version="1.4.2" />
|
||||||
<PackageReference Include="MoonCore.PluginFramework.Generator" Version="1.0.2"/>
|
<PackageReference Include="MoonCore.PluginFramework.Generator" Version="1.0.3" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
||||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
|
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
|
||||||
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.12.0-beta.1"/>
|
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.12.0-beta.1"/>
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Routing;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Plugins;
|
namespace Moonlight.ApiServer.Plugins;
|
||||||
|
|
||||||
public interface IPluginStartup
|
public interface IPluginStartup
|
||||||
{
|
{
|
||||||
public Task BuildApplicationAsync(IServiceProvider serviceProvider, IHostApplicationBuilder builder);
|
public void AddPlugin(WebApplicationBuilder builder);
|
||||||
public Task ConfigureApplicationAsync(IServiceProvider serviceProvider, IApplicationBuilder app);
|
public void UsePlugin(WebApplication app);
|
||||||
public Task ConfigureEndpointsAsync(IServiceProvider serviceProvider, IEndpointRouteBuilder routeBuilder);
|
public void MapPlugin(WebApplication app);
|
||||||
}
|
}
|
||||||
@@ -3,19 +3,24 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.DataProtection;
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using MoonCore.Permissions;
|
using MoonCore.Permissions;
|
||||||
|
using Moonlight.ApiServer.Configuration;
|
||||||
using Moonlight.ApiServer.Implementations.LocalAuth;
|
using Moonlight.ApiServer.Implementations.LocalAuth;
|
||||||
using Moonlight.ApiServer.Services;
|
using Moonlight.ApiServer.Services;
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Startup;
|
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"; })
|
.AddAuthentication(options => { options.DefaultScheme = "MainScheme"; })
|
||||||
.AddPolicyScheme("MainScheme", null, options =>
|
.AddPolicyScheme("MainScheme", null, options =>
|
||||||
{
|
{
|
||||||
@@ -42,15 +47,15 @@ public partial class Startup
|
|||||||
options.TokenValidationParameters = new()
|
options.TokenValidationParameters = new()
|
||||||
{
|
{
|
||||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(
|
||||||
Configuration.Authentication.Secret
|
configuration.Authentication.Secret
|
||||||
)),
|
)),
|
||||||
ValidateIssuerSigningKey = true,
|
ValidateIssuerSigningKey = true,
|
||||||
ValidateLifetime = true,
|
ValidateLifetime = true,
|
||||||
ClockSkew = TimeSpan.Zero,
|
ClockSkew = TimeSpan.Zero,
|
||||||
ValidateAudience = true,
|
ValidateAudience = true,
|
||||||
ValidAudience = Configuration.PublicUrl,
|
ValidAudience = configuration.PublicUrl,
|
||||||
ValidateIssuer = true,
|
ValidateIssuer = true,
|
||||||
ValidIssuer = Configuration.PublicUrl
|
ValidIssuer = configuration.PublicUrl
|
||||||
};
|
};
|
||||||
|
|
||||||
options.Events = new JwtBearerEvents()
|
options.Events = new JwtBearerEvents()
|
||||||
@@ -81,11 +86,11 @@ public partial class Startup
|
|||||||
})
|
})
|
||||||
.AddCookie("Session", null, options =>
|
.AddCookie("Session", null, options =>
|
||||||
{
|
{
|
||||||
options.ExpireTimeSpan = TimeSpan.FromDays(Configuration.Authentication.Sessions.ExpiresIn);
|
options.ExpireTimeSpan = TimeSpan.FromDays(configuration.Authentication.Sessions.ExpiresIn);
|
||||||
|
|
||||||
options.Cookie = new CookieBuilder()
|
options.Cookie = new CookieBuilder()
|
||||||
{
|
{
|
||||||
Name = Configuration.Authentication.Sessions.CookieName,
|
Name = configuration.Authentication.Sessions.CookieName,
|
||||||
Path = "/",
|
Path = "/",
|
||||||
IsEssential = true,
|
IsEssential = true,
|
||||||
SecurePolicy = CookieSecurePolicy.SameAsRequest
|
SecurePolicy = CookieSecurePolicy.SameAsRequest
|
||||||
@@ -150,16 +155,16 @@ public partial class Startup
|
|||||||
options.SignInScheme = "Session";
|
options.SignInScheme = "Session";
|
||||||
});
|
});
|
||||||
|
|
||||||
WebApplicationBuilder.Services.AddAuthorization();
|
builder.Services.AddAuthorization();
|
||||||
|
|
||||||
WebApplicationBuilder.Services.AddAuthorizationPermissions(options =>
|
builder.Services.AddAuthorizationPermissions(options =>
|
||||||
{
|
{
|
||||||
options.ClaimName = "Permissions";
|
options.ClaimName = "Permissions";
|
||||||
options.Prefix = "permissions:";
|
options.Prefix = "permissions:";
|
||||||
});
|
});
|
||||||
|
|
||||||
WebApplicationBuilder.Services.AddScoped<UserAuthService>();
|
builder.Services.AddScoped<UserAuthService>();
|
||||||
WebApplicationBuilder.Services.AddScoped<ApiKeyAuthService>();
|
builder.Services.AddScoped<ApiKeyAuthService>();
|
||||||
|
|
||||||
// Setup data protection storage within storage folder
|
// Setup data protection storage within storage folder
|
||||||
// so its persists in containers
|
// so its persists in containers
|
||||||
@@ -167,23 +172,18 @@ public partial class Startup
|
|||||||
|
|
||||||
Directory.CreateDirectory(dpKeyPath);
|
Directory.CreateDirectory(dpKeyPath);
|
||||||
|
|
||||||
WebApplicationBuilder.Services
|
builder.Services
|
||||||
.AddDataProtection()
|
.AddDataProtection()
|
||||||
.PersistKeysToFileSystem(
|
.PersistKeysToFileSystem(
|
||||||
new DirectoryInfo(dpKeyPath)
|
new DirectoryInfo(dpKeyPath)
|
||||||
);
|
);
|
||||||
|
|
||||||
WebApplicationBuilder.Services.AddScoped<UserDeletionService>();
|
builder.Services.AddScoped<UserDeletionService>();
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task UseAuthAsync()
|
private static void UseAuth(this WebApplication application)
|
||||||
{
|
{
|
||||||
WebApplication.UseAuthentication();
|
application.UseAuthentication();
|
||||||
|
application.UseAuthorization();
|
||||||
WebApplication.UseAuthorization();
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,63 +1,62 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using MoonCore.Extended.Extensions;
|
using MoonCore.Extended.Extensions;
|
||||||
using MoonCore.Extensions;
|
using MoonCore.Extensions;
|
||||||
using MoonCore.Helpers;
|
using MoonCore.Helpers;
|
||||||
|
using Moonlight.ApiServer.Configuration;
|
||||||
|
using Moonlight.ApiServer.Plugins;
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Startup;
|
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<Startup>();
|
builder.Services.AutoAddServices<IAssemblyMarker>();
|
||||||
WebApplicationBuilder.Services.AddHttpClient();
|
builder.Services.AddHttpClient();
|
||||||
|
|
||||||
WebApplicationBuilder.Services.AddApiExceptionHandler();
|
builder.Services.AddApiExceptionHandler();
|
||||||
|
|
||||||
// Add pre-existing services
|
|
||||||
WebApplicationBuilder.Services.AddSingleton(Configuration);
|
|
||||||
|
|
||||||
// Configure controllers
|
// Configure controllers
|
||||||
var mvcBuilder = WebApplicationBuilder.Services.AddControllers();
|
var mvcBuilder = builder.Services.AddControllers();
|
||||||
|
|
||||||
// Add plugin assemblies as application parts
|
// 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);
|
mvcBuilder.AddApplicationPart(pluginStartup.GetType().Assembly);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task UseBaseAsync()
|
private static void UseBase(this WebApplication application)
|
||||||
{
|
{
|
||||||
WebApplication.UseRouting();
|
application.UseRouting();
|
||||||
WebApplication.UseExceptionHandler();
|
application.UseExceptionHandler();
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task MapBaseAsync()
|
private static void MapBase(this WebApplication application)
|
||||||
{
|
{
|
||||||
WebApplication.MapControllers();
|
application.MapControllers();
|
||||||
|
|
||||||
if (Configuration.Frontend.EnableHosting)
|
// Frontend
|
||||||
WebApplication.MapFallbackToController("Index", "Frontend");
|
var configuration = AppConfiguration.CreateEmpty();
|
||||||
|
application.Configuration.Bind(configuration);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
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
|
var maxUploadInBytes = ByteConverter
|
||||||
.FromMegaBytes(Configuration.Kestrel.UploadLimit)
|
.FromMegaBytes(configuration.Kestrel.UploadLimit)
|
||||||
.Bytes;
|
.Bytes;
|
||||||
|
|
||||||
kestrelOptions.Limits.MaxRequestBodySize = maxUploadInBytes;
|
kestrelOptions.Limits.MaxRequestBodySize = maxUploadInBytes;
|
||||||
});
|
});
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using MoonCore.EnvConfiguration;
|
using MoonCore.EnvConfiguration;
|
||||||
@@ -6,30 +7,23 @@ using Moonlight.ApiServer.Configuration;
|
|||||||
|
|
||||||
namespace Moonlight.ApiServer.Startup;
|
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<AppConfiguration>(configPath);
|
YamlDefaultGenerator.GenerateAsync<AppConfiguration>(yamlPath).Wait();
|
||||||
|
|
||||||
// Configure configuration (wow)
|
builder.Configuration.AddYamlFile(yamlPath);
|
||||||
var configurationBuilder = new ConfigurationBuilder();
|
|
||||||
|
|
||||||
configurationBuilder.AddYamlFile(configPath);
|
// Env
|
||||||
configurationBuilder.AddEnvironmentVariables(prefix: "MOONLIGHT_", separator: "_");
|
builder.Configuration.AddEnvironmentVariables(prefix: "MOONLIGHT_", separator: "_");
|
||||||
|
|
||||||
var configurationRoot = configurationBuilder.Build();
|
var configuration = AppConfiguration.CreateEmpty();
|
||||||
|
builder.Configuration.Bind(configuration);
|
||||||
|
|
||||||
// Retrieve configuration
|
builder.Services.AddSingleton(configuration);
|
||||||
Configuration = AppConfiguration.CreateEmpty();
|
|
||||||
configurationRoot.Bind(Configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task RegisterAppConfigurationAsync()
|
|
||||||
{
|
|
||||||
WebApplicationBuilder.Services.AddSingleton(Configuration);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,17 @@
|
|||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using MoonCore.Extended.Abstractions;
|
using MoonCore.Extended.Abstractions;
|
||||||
using MoonCore.Extended.Extensions;
|
using MoonCore.Extended.Extensions;
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Startup;
|
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();
|
builder.Services.AddDbAutoMigrations();
|
||||||
WebApplicationBuilder.Services.AddServiceCollectionAccessor();
|
builder.Services.AddDatabaseMappings();
|
||||||
|
|
||||||
WebApplicationBuilder.Services.AddScoped(typeof(DatabaseRepository<>));
|
builder.Services.AddScoped(typeof(DatabaseRepository<>));
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task PrepareDatabaseAsync()
|
|
||||||
{
|
|
||||||
await WebApplication.Services.EnsureDatabaseMigratedAsync();
|
|
||||||
|
|
||||||
WebApplication.Services.GenerateDatabaseMappings();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using Hangfire;
|
using Hangfire;
|
||||||
using Hangfire.EntityFrameworkCore;
|
using Hangfire.EntityFrameworkCore;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -7,11 +8,11 @@ using Moonlight.ApiServer.Database;
|
|||||||
|
|
||||||
namespace Moonlight.ApiServer.Startup;
|
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.SetDataCompatibilityLevel(CompatibilityLevel.Version_180);
|
||||||
configuration.UseSimpleAssemblyNameTypeSerializer();
|
configuration.UseSimpleAssemblyNameTypeSerializer();
|
||||||
@@ -23,26 +24,22 @@ public partial class Startup
|
|||||||
}, new EFCoreStorageOptions());
|
}, new EFCoreStorageOptions());
|
||||||
});
|
});
|
||||||
|
|
||||||
WebApplicationBuilder.Services.AddHangfireServer();
|
builder.Services.AddHangfireServer();
|
||||||
|
|
||||||
WebApplicationBuilder.Logging.AddFilter(
|
builder.Logging.AddFilter(
|
||||||
"Hangfire.Server.BackgroundServerProcess",
|
"Hangfire.Server.BackgroundServerProcess",
|
||||||
LogLevel.Warning
|
LogLevel.Warning
|
||||||
);
|
);
|
||||||
|
|
||||||
WebApplicationBuilder.Logging.AddFilter(
|
builder.Logging.AddFilter(
|
||||||
"Hangfire.BackgroundJobServer",
|
"Hangfire.BackgroundJobServer",
|
||||||
LogLevel.Warning
|
LogLevel.Warning
|
||||||
);
|
);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task UseHangfireAsync()
|
private static void UseMoonlightHangfire(this WebApplication application)
|
||||||
{
|
{
|
||||||
if (WebApplication.Environment.IsDevelopment())
|
if (application.Environment.IsDevelopment())
|
||||||
WebApplication.UseHangfireDashboard();
|
application.UseHangfireDashboard();
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,32 +1,24 @@
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MoonCore.Logging;
|
using MoonCore.Logging;
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Startup;
|
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();
|
// Logging providers
|
||||||
loggerFactory.AddAnsiConsole();
|
builder.Logging.ClearProviders();
|
||||||
|
|
||||||
Logger = loggerFactory.CreateLogger<Startup>();
|
builder.Logging.AddAnsiConsole();
|
||||||
|
builder.Logging.AddFile(Path.Combine("storage", "logs", "moonlight.log"));
|
||||||
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 levels
|
// Logging levels
|
||||||
var logConfigPath = Path.Combine("storage", "logConfig.json");
|
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))
|
if (!File.Exists(logConfigPath))
|
||||||
{
|
{
|
||||||
var defaultLogLevels = new Dictionary<string, string>
|
var defaultLogLevels = new Dictionary<string, string>
|
||||||
@@ -38,25 +30,26 @@ public partial class Startup
|
|||||||
};
|
};
|
||||||
|
|
||||||
var logLevelsJson = JsonSerializer.Serialize(defaultLogLevels);
|
var logLevelsJson = JsonSerializer.Serialize(defaultLogLevels);
|
||||||
await File.WriteAllTextAsync(logConfigPath, logLevelsJson);
|
File.WriteAllText(logConfigPath, logLevelsJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add logging configuration
|
// Read log levels
|
||||||
var logLevels = JsonSerializer.Deserialize<Dictionary<string, string>>(
|
var logLevels = JsonSerializer.Deserialize<Dictionary<string, string>>(
|
||||||
await File.ReadAllTextAsync(logConfigPath)
|
File.ReadAllText(logConfigPath)
|
||||||
)!;
|
)!;
|
||||||
|
|
||||||
|
// Apply configured log levels
|
||||||
foreach (var level in logLevels)
|
foreach (var level in logLevels)
|
||||||
WebApplicationBuilder.Logging.AddFilter(level.Key, Enum.Parse<LogLevel>(level.Value));
|
builder.Logging.AddFilter(level.Key, Enum.Parse<LogLevel>(level.Value));
|
||||||
|
|
||||||
// Mute exception handler middleware
|
// Mute exception handler middleware
|
||||||
// https://github.com/dotnet/aspnetcore/issues/19740
|
// https://github.com/dotnet/aspnetcore/issues/19740
|
||||||
WebApplicationBuilder.Logging.AddFilter(
|
builder.Logging.AddFilter(
|
||||||
"Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware",
|
"Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware",
|
||||||
LogLevel.Critical
|
LogLevel.Critical
|
||||||
);
|
);
|
||||||
|
|
||||||
WebApplicationBuilder.Logging.AddFilter(
|
builder.Logging.AddFilter(
|
||||||
"Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware",
|
"Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware",
|
||||||
LogLevel.Critical
|
LogLevel.Critical
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Moonlight.ApiServer.Configuration;
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Startup;
|
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 :>
|
// Fancy start console output... yes very fancy :>
|
||||||
var rainbow = new Crayon.Rainbow(0.5);
|
var rainbow = new Crayon.Rainbow(0.5);
|
||||||
@@ -21,23 +23,22 @@ public partial class Startup
|
|||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task CreateStorageAsync()
|
private static void CreateStorageAsync()
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory("storage");
|
Directory.CreateDirectory("storage");
|
||||||
Directory.CreateDirectory(Path.Combine("storage", "logs"));
|
Directory.CreateDirectory(Path.Combine("storage", "logs"));
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task RegisterCorsAsync()
|
private static void AddMoonlightCors(this WebApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
var allowedOrigins = Configuration.Kestrel.AllowedOrigins;
|
var configuration = AppConfiguration.CreateEmpty();
|
||||||
|
builder.Configuration.Bind(configuration);
|
||||||
|
|
||||||
WebApplicationBuilder.Services.AddCors(options =>
|
var allowedOrigins = configuration.Kestrel.AllowedOrigins;
|
||||||
|
|
||||||
|
builder.Services.AddCors(options =>
|
||||||
{
|
{
|
||||||
var cors = new CorsPolicyBuilder();
|
var cors = new CorsPolicyBuilder();
|
||||||
|
|
||||||
@@ -60,14 +61,10 @@ public partial class Startup
|
|||||||
cors.Build()
|
cors.Build()
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task UseCorsAsync()
|
private static void UseMoonlightCors(this WebApplication application)
|
||||||
{
|
{
|
||||||
WebApplication.UseCors();
|
application.UseCors();
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,87 +1,25 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using MoonCore.Logging;
|
|
||||||
using Moonlight.ApiServer.Plugins;
|
using Moonlight.ApiServer.Plugins;
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Startup;
|
namespace Moonlight.ApiServer.Startup;
|
||||||
|
|
||||||
public partial class Startup
|
public static partial class Startup
|
||||||
{
|
{
|
||||||
private IServiceProvider PluginLoadServiceProvider;
|
private static void AddPlugins(this WebApplicationBuilder builder, IPluginStartup[] startups)
|
||||||
private IPluginStartup[] PluginStartups;
|
|
||||||
|
|
||||||
private Task InitializePluginsAsync()
|
|
||||||
{
|
{
|
||||||
// Create service provider for starting up
|
foreach (var startup in startups)
|
||||||
var serviceCollection = new ServiceCollection();
|
startup.AddPlugin(builder);
|
||||||
|
|
||||||
serviceCollection.AddSingleton(Configuration);
|
|
||||||
|
|
||||||
serviceCollection.AddLogging(builder =>
|
|
||||||
{
|
|
||||||
builder.ClearProviders();
|
|
||||||
builder.AddAnsiConsole();
|
|
||||||
});
|
|
||||||
|
|
||||||
PluginLoadServiceProvider = serviceCollection.BuildServiceProvider();
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HookPluginBuildAsync()
|
private static void UsePlugins(this WebApplication application, IPluginStartup[] startups)
|
||||||
{
|
{
|
||||||
foreach (var pluginAppStartup in PluginStartups)
|
foreach (var startup in startups)
|
||||||
{
|
startup.UsePlugin(application);
|
||||||
try
|
|
||||||
{
|
|
||||||
await pluginAppStartup.BuildApplicationAsync(PluginLoadServiceProvider, WebApplicationBuilder);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.LogError(
|
|
||||||
"An error occured while processing 'BuildApp' for '{name}': {e}",
|
|
||||||
pluginAppStartup.GetType().FullName,
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HookPluginConfigureAsync()
|
private static void MapPlugins(this WebApplication application, IPluginStartup[] startups)
|
||||||
{
|
{
|
||||||
foreach (var pluginAppStartup in PluginStartups)
|
foreach (var startup in startups)
|
||||||
{
|
startup.MapPlugin(application);
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,26 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Moonlight.ApiServer.Configuration;
|
||||||
using Moonlight.ApiServer.Http.Hubs;
|
using Moonlight.ApiServer.Http.Hubs;
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Startup;
|
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();
|
var configuration = AppConfiguration.CreateEmpty();
|
||||||
|
builder.Configuration.Bind(configuration);
|
||||||
|
|
||||||
if (Configuration.SignalR.UseRedis)
|
var signalRBuilder = builder.Services.AddSignalR();
|
||||||
signalRBuilder.AddStackExchangeRedis(Configuration.SignalR.RedisConnectionString);
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
if (configuration.SignalR.UseRedis)
|
||||||
|
signalRBuilder.AddStackExchangeRedis(configuration.SignalR.RedisConnectionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task MapSignalRAsync()
|
private static void MapMoonlightSignalR(this WebApplication application)
|
||||||
{
|
{
|
||||||
WebApplication.MapHub<DiagnoseHub>("/api/admin/system/diagnose/ws");
|
application.MapHub<DiagnoseHub>("/api/admin/system/diagnose/ws");
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,69 +1,42 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Moonlight.ApiServer.Configuration;
|
|
||||||
using Moonlight.ApiServer.Plugins;
|
using Moonlight.ApiServer.Plugins;
|
||||||
|
|
||||||
namespace Moonlight.ApiServer.Startup;
|
namespace Moonlight.ApiServer.Startup;
|
||||||
|
|
||||||
public partial class Startup
|
public static partial class Startup
|
||||||
{
|
{
|
||||||
private string[] Args;
|
public static void AddMoonlight(this WebApplicationBuilder builder, IPluginStartup[] startups)
|
||||||
|
|
||||||
// Logger
|
|
||||||
public ILogger<Startup> 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)
|
|
||||||
{
|
{
|
||||||
Args = args;
|
PrintVersionAsync();
|
||||||
PluginStartups = plugins ?? [];
|
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;
|
application.UseBase();
|
||||||
|
application.UseMoonlightCors();
|
||||||
await PrintVersionAsync();
|
application.UseAuth();
|
||||||
|
application.UseMoonlightHangfire();
|
||||||
await CreateStorageAsync();
|
application.UsePlugins(startups);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddMoonlightAsync(WebApplication application)
|
public static void MapMoonlight(this WebApplication application, IPluginStartup[] startups)
|
||||||
{
|
{
|
||||||
WebApplication = application;
|
application.MapBase();
|
||||||
|
application.MapMoonlightSignalR();
|
||||||
await PrepareDatabaseAsync();
|
application.MapPlugins(startups);
|
||||||
|
|
||||||
await UseCorsAsync();
|
|
||||||
await UseBaseAsync();
|
|
||||||
await UseAuthAsync();
|
|
||||||
await UseHangfireAsync();
|
|
||||||
await HookPluginConfigureAsync();
|
|
||||||
|
|
||||||
await MapBaseAsync();
|
|
||||||
await MapSignalRAsync();
|
|
||||||
await HookPluginEndpointsAsync();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,8 +12,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.8" />
|
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.9" />
|
||||||
<PackageReference Include="MoonCore.PluginFramework.Generator" Version="1.0.2" />
|
<PackageReference Include="MoonCore.PluginFramework.Generator" Version="1.0.3" />
|
||||||
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.9" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.9" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.9" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.9" PrivateAssets="all" />
|
||||||
|
|||||||
@@ -5,16 +5,12 @@ using Moonlight.Client.Startup;
|
|||||||
var pluginLoader = new PluginLoader();
|
var pluginLoader = new PluginLoader();
|
||||||
pluginLoader.Initialize();
|
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 app.RunAsync();
|
||||||
|
|
||||||
await startup.AddMoonlightAsync(wasmApp);
|
|
||||||
|
|
||||||
await wasmApp.RunAsync();
|
|
||||||
3
Moonlight.Client/IAssemblyMarker.cs
Normal file
3
Moonlight.Client/IAssemblyMarker.cs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Moonlight.Client;
|
||||||
|
|
||||||
|
public interface IAssemblyMarker;
|
||||||
@@ -7,14 +7,14 @@ namespace Moonlight.Client.Implementations;
|
|||||||
|
|
||||||
public class CoreStartup : IPluginStartup
|
public class CoreStartup : IPluginStartup
|
||||||
{
|
{
|
||||||
public Task BuildApplicationAsync(IServiceProvider serviceProvider, WebAssemblyHostBuilder builder)
|
public void AddPlugin(WebAssemblyHostBuilder builder)
|
||||||
{
|
{
|
||||||
builder.Services.AddSingleton<ISidebarItemProvider, DefaultSidebarItemProvider>();
|
builder.Services.AddSingleton<ISidebarItemProvider, DefaultSidebarItemProvider>();
|
||||||
builder.Services.AddSingleton<IOverviewElementProvider, DefaultOverviewElementProvider>();
|
builder.Services.AddSingleton<IOverviewElementProvider, DefaultOverviewElementProvider>();
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task ConfigureApplicationAsync(IServiceProvider serviceProvider, WebAssemblyHost app)
|
public void ConfigurePlugin(WebAssemblyHost app)
|
||||||
=> Task.CompletedTask;
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PackageTags>frontend</PackageTags>
|
<PackageTags>frontend</PackageTags>
|
||||||
<PackageId>Moonlight.Client</PackageId>
|
<PackageId>Moonlight.Client</PackageId>
|
||||||
<Version>2.1.11</Version>
|
<Version>2.1.12</Version>
|
||||||
<Authors>Moonlight Panel</Authors>
|
<Authors>Moonlight Panel</Authors>
|
||||||
<Description>A build of the client for moonlight development</Description>
|
<Description>A build of the client for moonlight development</Description>
|
||||||
<PackageProjectUrl>https://github.com/Moonlight-Panel/Moonlight</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/Moonlight-Panel/Moonlight</PackageProjectUrl>
|
||||||
@@ -25,8 +25,8 @@
|
|||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.9" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.9" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.9" />
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.9" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.8" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.8" />
|
||||||
<PackageReference Include="MoonCore" Version="2.0.1" />
|
<PackageReference Include="MoonCore" Version="2.0.4" />
|
||||||
<PackageReference Include="MoonCore.Blazor.FlyonUi" Version="1.2.5" />
|
<PackageReference Include="MoonCore.Blazor.FlyonUi" Version="1.3.1" />
|
||||||
<PackageReference Include="System.Security.Claims" Version="4.3.0" />
|
<PackageReference Include="System.Security.Claims" Version="4.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ namespace Moonlight.Client.Plugins;
|
|||||||
|
|
||||||
public interface IPluginStartup
|
public interface IPluginStartup
|
||||||
{
|
{
|
||||||
public Task BuildApplicationAsync(IServiceProvider serviceProvider, WebAssemblyHostBuilder builder);
|
public void AddPlugin(WebAssemblyHostBuilder builder);
|
||||||
public Task ConfigureApplicationAsync(IServiceProvider serviceProvider, WebAssemblyHost app);
|
public void ConfigurePlugin(WebAssemblyHost app);
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
using MoonCore.Attributes;
|
using MoonCore.Attributes;
|
||||||
using MoonCore.Helpers;
|
using MoonCore.Helpers;
|
||||||
using MoonCore.Models;
|
|
||||||
using Moonlight.Shared.Http.Requests.Admin.Sys.Theme;
|
using Moonlight.Shared.Http.Requests.Admin.Sys.Theme;
|
||||||
using Moonlight.Shared.Http.Responses.Admin;
|
using Moonlight.Shared.Http.Responses.Admin;
|
||||||
using Moonlight.Shared.Misc;
|
|
||||||
|
|
||||||
namespace Moonlight.Client.Services;
|
namespace Moonlight.Client.Services;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.AspNetCore.Components.Authorization;
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using MoonCore.Blazor.FlyonUi.Exceptions;
|
using MoonCore.Blazor.FlyonUi.Exceptions;
|
||||||
using MoonCore.Permissions;
|
using MoonCore.Permissions;
|
||||||
@@ -7,22 +8,20 @@ using Moonlight.Client.Services;
|
|||||||
|
|
||||||
namespace Moonlight.Client.Startup;
|
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();
|
builder.Services.AddAuthorizationCore();
|
||||||
WebAssemblyHostBuilder.Services.AddCascadingAuthenticationState();
|
builder.Services.AddCascadingAuthenticationState();
|
||||||
|
|
||||||
WebAssemblyHostBuilder.Services.AddScoped<AuthenticationStateProvider, RemoteAuthStateProvider>();
|
builder.Services.AddScoped<AuthenticationStateProvider, RemoteAuthStateProvider>();
|
||||||
WebAssemblyHostBuilder.Services.AddScoped<IGlobalErrorFilter, UnauthenticatedErrorFilter>();
|
builder.Services.AddScoped<IGlobalErrorFilter, UnauthenticatedErrorFilter>();
|
||||||
|
|
||||||
WebAssemblyHostBuilder.Services.AddAuthorizationPermissions(options =>
|
builder.Services.AddAuthorizationPermissions(options =>
|
||||||
{
|
{
|
||||||
options.ClaimName = "Permissions";
|
options.ClaimName = "Permissions";
|
||||||
options.Prefix = "permissions:";
|
options.Prefix = "permissions:";
|
||||||
});
|
});
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,39 +1,42 @@
|
|||||||
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using MoonCore.Blazor.FlyonUi;
|
using MoonCore.Blazor.FlyonUi;
|
||||||
|
using MoonCore.Blazor.FlyonUi.Exceptions;
|
||||||
using MoonCore.Extensions;
|
using MoonCore.Extensions;
|
||||||
using MoonCore.Helpers;
|
using MoonCore.Helpers;
|
||||||
|
using Moonlight.Client.Implementations;
|
||||||
using Moonlight.Client.Services;
|
using Moonlight.Client.Services;
|
||||||
using Moonlight.Client.UI;
|
using Moonlight.Client.UI;
|
||||||
|
|
||||||
namespace Moonlight.Client.Startup;
|
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>("#app");
|
builder.RootComponents.Add<App>("#app");
|
||||||
WebAssemblyHostBuilder.RootComponents.Add<HeadOutlet>("head::after");
|
builder.RootComponents.Add<HeadOutlet>("head::after");
|
||||||
|
|
||||||
WebAssemblyHostBuilder.Services.AddScoped(_ =>
|
builder.Services.AddScoped(_ =>
|
||||||
new HttpClient
|
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<HttpClient>();
|
var httpClient = sp.GetRequiredService<HttpClient>();
|
||||||
return new HttpApiClient(httpClient);
|
return new HttpApiClient(httpClient);
|
||||||
});
|
});
|
||||||
|
|
||||||
WebAssemblyHostBuilder.Services.AddFileManagerOperations();
|
builder.Services.AddFileManagerOperations();
|
||||||
WebAssemblyHostBuilder.Services.AddFlyonUiServices();
|
builder.Services.AddFlyonUiServices();
|
||||||
|
|
||||||
WebAssemblyHostBuilder.Services.AddScoped<ThemeService>();
|
builder.Services.AddScoped<ThemeService>();
|
||||||
|
|
||||||
WebAssemblyHostBuilder.Services.AutoAddServices<Startup>();
|
builder.Services.AutoAddServices<IAssemblyMarker>();
|
||||||
|
|
||||||
return Task.CompletedTask;
|
builder.Services.AddScoped<IGlobalErrorFilter, LogErrorFilter>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,30 +1,13 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
using MoonCore.Blazor.FlyonUi.Exceptions;
|
|
||||||
using MoonCore.Logging;
|
using MoonCore.Logging;
|
||||||
using Moonlight.Client.Implementations;
|
|
||||||
|
|
||||||
namespace Moonlight.Client.Startup;
|
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();
|
builder.Logging.ClearProviders();
|
||||||
|
builder.Logging.AddAnsiConsole();
|
||||||
loggerFactory.AddAnsiConsole();
|
|
||||||
|
|
||||||
Logger = loggerFactory.CreateLogger<Startup>();
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task RegisterLoggingAsync()
|
|
||||||
{
|
|
||||||
WebAssemblyHostBuilder.Logging.ClearProviders();
|
|
||||||
WebAssemblyHostBuilder.Logging.AddAnsiConsole();
|
|
||||||
|
|
||||||
WebAssemblyHostBuilder.Services.AddScoped<IGlobalErrorFilter, LogErrorFilter>();
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,8 @@
|
|||||||
using System.Text.Json;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Moonlight.Shared.Misc;
|
|
||||||
|
|
||||||
namespace Moonlight.Client.Startup;
|
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 :>
|
// Fancy start console output... yes very fancy :>
|
||||||
Console.Write("Running ");
|
Console.Write("Running ");
|
||||||
@@ -23,30 +19,5 @@ public partial class Startup
|
|||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine();
|
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<FrontendConfiguration>(jsonText, new JsonSerializerOptions()
|
|
||||||
{
|
|
||||||
PropertyNameCaseInsensitive = true
|
|
||||||
})!;
|
|
||||||
|
|
||||||
WebAssemblyHostBuilder.Services.AddSingleton(Configuration);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.LogCritical("Unable to load configuration. Unable to continue: {e}", e);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using MoonCore.Logging;
|
|
||||||
using Moonlight.Client.Plugins;
|
using Moonlight.Client.Plugins;
|
||||||
using Moonlight.Client.Services;
|
using Moonlight.Client.Services;
|
||||||
|
|
||||||
@@ -7,72 +7,25 @@ namespace Moonlight.Client.Startup;
|
|||||||
|
|
||||||
public partial class Startup
|
public partial class Startup
|
||||||
{
|
{
|
||||||
private IPluginStartup[] PluginStartups;
|
private static void AddPlugins(this WebAssemblyHostBuilder builder, IPluginStartup[] startups)
|
||||||
private IServiceProvider PluginLoadServiceProvider;
|
|
||||||
|
|
||||||
private Task InitializePluginsAsync()
|
|
||||||
{
|
{
|
||||||
// Define minimal service collection
|
foreach (var startup in startups)
|
||||||
var startupSc = new ServiceCollection();
|
startup.AddPlugin(builder);
|
||||||
|
|
||||||
// Create logging proxy
|
// Get all assemblies and combine them into the application assembly service
|
||||||
startupSc.AddLogging(builder =>
|
// 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();
|
Assemblies = startups
|
||||||
builder.AddAnsiConsole();
|
|
||||||
});
|
|
||||||
|
|
||||||
PluginLoadServiceProvider = startupSc.BuildServiceProvider();
|
|
||||||
|
|
||||||
// Add application assembly service
|
|
||||||
var appAssemblyService = new ApplicationAssemblyService();
|
|
||||||
|
|
||||||
appAssemblyService.Assemblies.AddRange(
|
|
||||||
PluginStartups
|
|
||||||
.Select(x => x.GetType().Assembly)
|
.Select(x => x.GetType().Assembly)
|
||||||
.Distinct()
|
.DistinctBy(x => x.FullName)
|
||||||
);
|
.ToList()
|
||||||
|
});
|
||||||
WebAssemblyHostBuilder.Services.AddSingleton(appAssemblyService);
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HookPluginBuildAsync()
|
private static void ConfigurePlugins(this WebAssemblyHost app, IPluginStartup[] startups)
|
||||||
{
|
{
|
||||||
foreach (var pluginAppStartup in PluginStartups)
|
foreach (var startup in startups)
|
||||||
{
|
startup.ConfigurePlugin(app);
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,48 +1,22 @@
|
|||||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
using Moonlight.Client.Plugins;
|
using Moonlight.Client.Plugins;
|
||||||
using Moonlight.Shared.Misc;
|
|
||||||
|
|
||||||
namespace Moonlight.Client.Startup;
|
namespace Moonlight.Client.Startup;
|
||||||
|
|
||||||
public partial class Startup
|
public static partial class Startup
|
||||||
{
|
{
|
||||||
public ILogger<Startup> Logger { get; private set; }
|
public static void AddMoonlight(this WebAssemblyHostBuilder builder, IPluginStartup[] startups)
|
||||||
|
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
PluginStartups = plugins ?? [];
|
PrintVersion();
|
||||||
|
|
||||||
return Task.CompletedTask;
|
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;
|
app.ConfigurePlugins(startups);
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,6 @@
|
|||||||
!rounded-xs
|
!rounded-xs
|
||||||
!text-sm
|
!text-sm
|
||||||
!w-2.5
|
!w-2.5
|
||||||
*:[grid-area:1/1]
|
|
||||||
*:first:rounded-tl-lg
|
*:first:rounded-tl-lg
|
||||||
*:last:rounded-tr-lg
|
*:last:rounded-tr-lg
|
||||||
-left-4
|
-left-4
|
||||||
@@ -43,18 +42,11 @@ alert-soft
|
|||||||
align-bottom
|
align-bottom
|
||||||
align-middle
|
align-middle
|
||||||
animate-bounce
|
animate-bounce
|
||||||
animate-ping
|
|
||||||
animate-spin
|
animate-spin
|
||||||
aria-[current='page']:text-bg-soft-primary
|
|
||||||
avatar
|
avatar
|
||||||
avatar-placeholder
|
avatar-placeholder
|
||||||
badge
|
badge
|
||||||
badge-error
|
basis-full
|
||||||
badge-info
|
|
||||||
badge-outline
|
|
||||||
badge-primary
|
|
||||||
badge-soft
|
|
||||||
badge-success
|
|
||||||
bg-background
|
bg-background
|
||||||
bg-background/60
|
bg-background/60
|
||||||
bg-base-100
|
bg-base-100
|
||||||
@@ -62,6 +54,7 @@ bg-base-150
|
|||||||
bg-base-200
|
bg-base-200
|
||||||
bg-base-200!
|
bg-base-200!
|
||||||
bg-base-200/50
|
bg-base-200/50
|
||||||
|
bg-base-250
|
||||||
bg-base-300
|
bg-base-300
|
||||||
bg-base-300/45
|
bg-base-300/45
|
||||||
bg-base-300/50
|
bg-base-300/50
|
||||||
@@ -157,7 +150,15 @@ disabled
|
|||||||
divide-base-150/60
|
divide-base-150/60
|
||||||
divide-y
|
divide-y
|
||||||
divider
|
divider
|
||||||
drop-shadow
|
drawer
|
||||||
|
drawer-body
|
||||||
|
drawer-bottom
|
||||||
|
drawer-end
|
||||||
|
drawer-footer
|
||||||
|
drawer-header
|
||||||
|
drawer-start
|
||||||
|
drawer-title
|
||||||
|
drawer-top
|
||||||
dropdown
|
dropdown
|
||||||
dropdown-active
|
dropdown-active
|
||||||
dropdown-disabled
|
dropdown-disabled
|
||||||
@@ -217,14 +218,13 @@ gap-y-2.5
|
|||||||
gap-y-3
|
gap-y-3
|
||||||
grid
|
grid
|
||||||
grid-cols-1
|
grid-cols-1
|
||||||
grid-cols-4
|
|
||||||
grid-flow-col
|
grid-flow-col
|
||||||
grow
|
grow
|
||||||
grow-0
|
grow-0
|
||||||
h-10
|
h-10
|
||||||
h-2
|
h-2
|
||||||
h-3
|
h-3
|
||||||
h-32
|
h-36
|
||||||
h-64
|
h-64
|
||||||
h-8
|
h-8
|
||||||
h-auto
|
h-auto
|
||||||
@@ -270,7 +270,6 @@ justify-center
|
|||||||
justify-end
|
justify-end
|
||||||
justify-start
|
justify-start
|
||||||
label-text
|
label-text
|
||||||
leading-3
|
|
||||||
leading-3.5
|
leading-3.5
|
||||||
leading-none
|
leading-none
|
||||||
left-0
|
left-0
|
||||||
@@ -296,7 +295,6 @@ link-animated
|
|||||||
link-hover
|
link-hover
|
||||||
list-disc
|
list-disc
|
||||||
list-inside
|
list-inside
|
||||||
list-none
|
|
||||||
loading
|
loading
|
||||||
loading-sm
|
loading-sm
|
||||||
loading-spinner
|
loading-spinner
|
||||||
@@ -310,9 +308,10 @@ max-lg:flex-col
|
|||||||
max-lg:hidden
|
max-lg:hidden
|
||||||
max-md:flex-wrap
|
max-md:flex-wrap
|
||||||
max-md:justify-center
|
max-md:justify-center
|
||||||
|
max-md:w-full
|
||||||
max-sm:hidden
|
max-sm:hidden
|
||||||
|
max-w-64
|
||||||
max-w-7xl
|
max-w-7xl
|
||||||
max-w-8
|
|
||||||
max-w-80
|
max-w-80
|
||||||
max-w-full
|
max-w-full
|
||||||
max-w-lg
|
max-w-lg
|
||||||
@@ -323,10 +322,16 @@ mb-1
|
|||||||
mb-1.5
|
mb-1.5
|
||||||
mb-2
|
mb-2
|
||||||
mb-2.5
|
mb-2.5
|
||||||
|
mb-25
|
||||||
mb-3
|
mb-3
|
||||||
mb-4
|
mb-4
|
||||||
mb-5
|
mb-5
|
||||||
|
md:flex
|
||||||
|
md:gap-2
|
||||||
|
md:hidden!
|
||||||
|
md:items-center
|
||||||
md:min-w-md
|
md:min-w-md
|
||||||
|
md:navbar-end
|
||||||
md:table-cell
|
md:table-cell
|
||||||
md:text-3xl
|
md:text-3xl
|
||||||
me-1
|
me-1
|
||||||
@@ -340,6 +345,7 @@ menu-disabled
|
|||||||
menu-dropdown
|
menu-dropdown
|
||||||
menu-dropdown-show
|
menu-dropdown-show
|
||||||
menu-horizontal
|
menu-horizontal
|
||||||
|
menu-sm
|
||||||
menu-title
|
menu-title
|
||||||
min-h-0
|
min-h-0
|
||||||
min-h-svh
|
min-h-svh
|
||||||
@@ -376,9 +382,12 @@ mt-5
|
|||||||
mt-8
|
mt-8
|
||||||
mx-1
|
mx-1
|
||||||
mx-auto
|
mx-auto
|
||||||
|
my-20
|
||||||
my-3
|
my-3
|
||||||
my-5
|
my-5
|
||||||
my-auto
|
my-auto
|
||||||
|
navbar
|
||||||
|
navbar-start
|
||||||
object-cover
|
object-cover
|
||||||
opacity-0
|
opacity-0
|
||||||
opacity-100
|
opacity-100
|
||||||
@@ -392,6 +401,9 @@ overflow-x-auto
|
|||||||
overflow-y-auto
|
overflow-y-auto
|
||||||
overlay-open:duration-50
|
overlay-open:duration-50
|
||||||
overlay-open:opacity-100
|
overlay-open:opacity-100
|
||||||
|
overlay-open:translate-x-0
|
||||||
|
overlay-open:translate-y-0
|
||||||
|
p-0
|
||||||
p-0.5
|
p-0.5
|
||||||
p-1
|
p-1
|
||||||
p-1.5
|
p-1.5
|
||||||
@@ -403,6 +415,7 @@ p-5
|
|||||||
p-6
|
p-6
|
||||||
p-8
|
p-8
|
||||||
pb-1
|
pb-1
|
||||||
|
pe-1
|
||||||
pin-input
|
pin-input
|
||||||
placeholder-base-content/60
|
placeholder-base-content/60
|
||||||
pointer-events-auto
|
pointer-events-auto
|
||||||
@@ -427,7 +440,6 @@ py-2
|
|||||||
py-2.5
|
py-2.5
|
||||||
py-6
|
py-6
|
||||||
radial-progress
|
radial-progress
|
||||||
radio
|
|
||||||
range
|
range
|
||||||
relative
|
relative
|
||||||
resize
|
resize
|
||||||
@@ -455,6 +467,8 @@ selected:select-active
|
|||||||
shadow-base-300/20
|
shadow-base-300/20
|
||||||
shadow-lg
|
shadow-lg
|
||||||
shadow-md
|
shadow-md
|
||||||
|
shadow-none
|
||||||
|
shadow-sm
|
||||||
shadow-xs
|
shadow-xs
|
||||||
shrink-0
|
shrink-0
|
||||||
size-10
|
size-10
|
||||||
@@ -462,8 +476,7 @@ size-12
|
|||||||
size-4
|
size-4
|
||||||
size-5
|
size-5
|
||||||
size-8
|
size-8
|
||||||
skeleton
|
size-8.5
|
||||||
skeleton-animated
|
|
||||||
sm:auto-cols-max
|
sm:auto-cols-max
|
||||||
sm:flex
|
sm:flex
|
||||||
sm:items-center
|
sm:items-center
|
||||||
@@ -492,7 +505,6 @@ sr-only
|
|||||||
stack
|
stack
|
||||||
static
|
static
|
||||||
status
|
status
|
||||||
status-error
|
|
||||||
sticky
|
sticky
|
||||||
success-message
|
success-message
|
||||||
switch
|
switch
|
||||||
@@ -548,26 +560,32 @@ tooltip
|
|||||||
tooltip-content
|
tooltip-content
|
||||||
top-0
|
top-0
|
||||||
top-1/2
|
top-1/2
|
||||||
|
top-3
|
||||||
top-full
|
top-full
|
||||||
transform
|
transform
|
||||||
transition
|
transition
|
||||||
transition-all
|
transition-all
|
||||||
transition-opacity
|
transition-opacity
|
||||||
|
transition-transform
|
||||||
translate-x-0
|
translate-x-0
|
||||||
|
translate-x-full
|
||||||
truncate
|
truncate
|
||||||
underline
|
underline
|
||||||
uppercase
|
uppercase
|
||||||
validate
|
validate
|
||||||
w-0
|
w-0
|
||||||
w-0.5
|
w-0.5
|
||||||
w-12
|
|
||||||
w-13
|
w-13
|
||||||
|
w-20
|
||||||
w-4
|
w-4
|
||||||
w-56
|
w-56
|
||||||
|
w-6
|
||||||
w-64
|
w-64
|
||||||
w-fit
|
w-fit
|
||||||
w-full
|
w-full
|
||||||
whitespace-nowrap
|
whitespace-nowrap
|
||||||
z-10
|
z-1
|
||||||
z-40
|
z-40
|
||||||
z-50
|
z-50
|
||||||
|
z-69
|
||||||
|
z-70
|
||||||
@@ -64,6 +64,7 @@ badge-outline
|
|||||||
badge-primary
|
badge-primary
|
||||||
badge-soft
|
badge-soft
|
||||||
badge-success
|
badge-success
|
||||||
|
basis-full
|
||||||
bg-background
|
bg-background
|
||||||
bg-background/60
|
bg-background/60
|
||||||
bg-base-100
|
bg-base-100
|
||||||
@@ -71,6 +72,7 @@ bg-base-150
|
|||||||
bg-base-200
|
bg-base-200
|
||||||
bg-base-200!
|
bg-base-200!
|
||||||
bg-base-200/50
|
bg-base-200/50
|
||||||
|
bg-base-250
|
||||||
bg-base-300
|
bg-base-300
|
||||||
bg-base-300/45
|
bg-base-300/45
|
||||||
bg-base-300/50
|
bg-base-300/50
|
||||||
@@ -189,6 +191,15 @@ disabled
|
|||||||
divide-base-150/60
|
divide-base-150/60
|
||||||
divide-y
|
divide-y
|
||||||
divider
|
divider
|
||||||
|
drawer
|
||||||
|
drawer-body
|
||||||
|
drawer-bottom
|
||||||
|
drawer-end
|
||||||
|
drawer-footer
|
||||||
|
drawer-header
|
||||||
|
drawer-start
|
||||||
|
drawer-title
|
||||||
|
drawer-top
|
||||||
drop-shadow
|
drop-shadow
|
||||||
dropdown
|
dropdown
|
||||||
dropdown-active
|
dropdown-active
|
||||||
@@ -275,6 +286,7 @@ h-14
|
|||||||
h-2
|
h-2
|
||||||
h-3
|
h-3
|
||||||
h-32
|
h-32
|
||||||
|
h-36
|
||||||
h-6
|
h-6
|
||||||
h-64
|
h-64
|
||||||
h-8
|
h-8
|
||||||
@@ -372,7 +384,9 @@ max-lg:flex-col
|
|||||||
max-lg:hidden
|
max-lg:hidden
|
||||||
max-md:flex-wrap
|
max-md:flex-wrap
|
||||||
max-md:justify-center
|
max-md:justify-center
|
||||||
|
max-md:w-full
|
||||||
max-sm:hidden
|
max-sm:hidden
|
||||||
|
max-w-64
|
||||||
max-w-7xl
|
max-w-7xl
|
||||||
max-w-8
|
max-w-8
|
||||||
max-w-80
|
max-w-80
|
||||||
@@ -386,14 +400,20 @@ mb-1
|
|||||||
mb-1.5
|
mb-1.5
|
||||||
mb-2
|
mb-2
|
||||||
mb-2.5
|
mb-2.5
|
||||||
|
mb-25
|
||||||
mb-3
|
mb-3
|
||||||
mb-4
|
mb-4
|
||||||
mb-5
|
mb-5
|
||||||
mb-8
|
mb-8
|
||||||
md:col-span-1
|
md:col-span-1
|
||||||
md:col-span-6
|
md:col-span-6
|
||||||
|
md:flex
|
||||||
|
md:gap-2
|
||||||
md:grid-cols-2
|
md:grid-cols-2
|
||||||
|
md:hidden!
|
||||||
|
md:items-center
|
||||||
md:min-w-md
|
md:min-w-md
|
||||||
|
md:navbar-end
|
||||||
md:table-cell
|
md:table-cell
|
||||||
md:text-3xl
|
md:text-3xl
|
||||||
me-1
|
me-1
|
||||||
@@ -408,6 +428,7 @@ menu-dropdown
|
|||||||
menu-dropdown-show
|
menu-dropdown-show
|
||||||
menu-focus
|
menu-focus
|
||||||
menu-horizontal
|
menu-horizontal
|
||||||
|
menu-sm
|
||||||
menu-title
|
menu-title
|
||||||
min-h-0
|
min-h-0
|
||||||
min-h-full
|
min-h-full
|
||||||
@@ -452,10 +473,13 @@ mt-8
|
|||||||
mx-1
|
mx-1
|
||||||
mx-auto
|
mx-auto
|
||||||
my-2.5
|
my-2.5
|
||||||
|
my-20
|
||||||
my-3
|
my-3
|
||||||
my-5
|
my-5
|
||||||
my-8
|
my-8
|
||||||
my-auto
|
my-auto
|
||||||
|
navbar
|
||||||
|
navbar-start
|
||||||
object-cover
|
object-cover
|
||||||
opacity-0
|
opacity-0
|
||||||
opacity-100
|
opacity-100
|
||||||
@@ -470,6 +494,9 @@ overflow-x-hidden
|
|||||||
overflow-y-auto
|
overflow-y-auto
|
||||||
overlay-open:duration-50
|
overlay-open:duration-50
|
||||||
overlay-open:opacity-100
|
overlay-open:opacity-100
|
||||||
|
overlay-open:translate-x-0
|
||||||
|
overlay-open:translate-y-0
|
||||||
|
p-0
|
||||||
p-0.5
|
p-0.5
|
||||||
p-1
|
p-1
|
||||||
p-1.5
|
p-1.5
|
||||||
@@ -481,6 +508,7 @@ p-5
|
|||||||
p-6
|
p-6
|
||||||
p-8
|
p-8
|
||||||
pb-1
|
pb-1
|
||||||
|
pe-1
|
||||||
pe-1.5
|
pe-1.5
|
||||||
pin-input
|
pin-input
|
||||||
pin-input-underline
|
pin-input-underline
|
||||||
@@ -548,6 +576,7 @@ shadow
|
|||||||
shadow-base-300/20
|
shadow-base-300/20
|
||||||
shadow-lg
|
shadow-lg
|
||||||
shadow-md
|
shadow-md
|
||||||
|
shadow-none
|
||||||
shadow-sm
|
shadow-sm
|
||||||
shadow-xs
|
shadow-xs
|
||||||
shrink-0
|
shrink-0
|
||||||
@@ -557,6 +586,7 @@ size-4
|
|||||||
size-5
|
size-5
|
||||||
size-7
|
size-7
|
||||||
size-8
|
size-8
|
||||||
|
size-8.5
|
||||||
skeleton
|
skeleton
|
||||||
skeleton-animated
|
skeleton-animated
|
||||||
sm:auto-cols-max
|
sm:auto-cols-max
|
||||||
@@ -686,6 +716,7 @@ tooltip
|
|||||||
tooltip-content
|
tooltip-content
|
||||||
top-0
|
top-0
|
||||||
top-1/2
|
top-1/2
|
||||||
|
top-3
|
||||||
top-full
|
top-full
|
||||||
tracking-tight
|
tracking-tight
|
||||||
tracking-wide
|
tracking-wide
|
||||||
@@ -693,7 +724,9 @@ transform
|
|||||||
transition
|
transition
|
||||||
transition-all
|
transition-all
|
||||||
transition-opacity
|
transition-opacity
|
||||||
|
transition-transform
|
||||||
translate-x-0
|
translate-x-0
|
||||||
|
translate-x-full
|
||||||
truncate
|
truncate
|
||||||
underline
|
underline
|
||||||
uppercase
|
uppercase
|
||||||
@@ -703,9 +736,11 @@ w-0
|
|||||||
w-0.5
|
w-0.5
|
||||||
w-12
|
w-12
|
||||||
w-13
|
w-13
|
||||||
|
w-20
|
||||||
w-32
|
w-32
|
||||||
w-4
|
w-4
|
||||||
w-56
|
w-56
|
||||||
|
w-6
|
||||||
w-64
|
w-64
|
||||||
w-8
|
w-8
|
||||||
w-auto
|
w-auto
|
||||||
@@ -718,3 +753,5 @@ z-1
|
|||||||
z-10
|
z-10
|
||||||
z-40
|
z-40
|
||||||
z-50
|
z-50
|
||||||
|
z-69
|
||||||
|
z-70
|
||||||
@@ -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
|
@using MoonCore.Blazor.FlyonUi.Files.Drop
|
||||||
|
|
||||||
@inherits LayoutComponentBase
|
@inherits LayoutComponentBase
|
||||||
@@ -20,6 +21,7 @@
|
|||||||
|
|
||||||
<ToastLauncher/>
|
<ToastLauncher/>
|
||||||
<ModalLauncher/>
|
<ModalLauncher/>
|
||||||
|
<DrawerLauncher />
|
||||||
|
|
||||||
<DropHandler />
|
<DropHandler />
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
@page "/admin/api"
|
@page "/admin/api"
|
||||||
|
|
||||||
|
@using MoonCore.Blazor.FlyonUi.Common
|
||||||
@using MoonCore.Helpers
|
@using MoonCore.Helpers
|
||||||
@using MoonCore.Models
|
|
||||||
@using Moonlight.Shared.Http.Responses.Admin.ApiKeys
|
@using Moonlight.Shared.Http.Responses.Admin.ApiKeys
|
||||||
@using MoonCore.Blazor.FlyonUi.Grid
|
@using MoonCore.Blazor.FlyonUi.Grid
|
||||||
@using MoonCore.Blazor.FlyonUi.Grid.Columns
|
@using MoonCore.Blazor.FlyonUi.Grid.Columns
|
||||||
@using MoonCore.Blazor.FlyonUi.Grid.ToolbarItems
|
@using MoonCore.Blazor.FlyonUi.Grid.ToolbarItems
|
||||||
|
@using MoonCore.Common
|
||||||
|
|
||||||
@inject HttpApiClient ApiClient
|
@inject HttpApiClient ApiClient
|
||||||
@inject AlertService AlertService
|
@inject AlertService AlertService
|
||||||
@@ -51,9 +52,7 @@
|
|||||||
|
|
||||||
<DataGrid @ref="Grid"
|
<DataGrid @ref="Grid"
|
||||||
TGridItem="ApiKeyResponse"
|
TGridItem="ApiKeyResponse"
|
||||||
ItemsProvider="ItemsProviderAsync"
|
ItemSource="ItemSource">
|
||||||
EnableFiltering="true"
|
|
||||||
EnablePagination="true">
|
|
||||||
<PropertyColumn Field="x => x.Id" Sortable="true" />
|
<PropertyColumn Field="x => x.Id" Sortable="true" />
|
||||||
<PropertyColumn Field="x => x.Description" />
|
<PropertyColumn Field="x => x.Description" />
|
||||||
<TemplateColumn Sortable="true" Title="Expires At">
|
<TemplateColumn Sortable="true" Title="Expires At">
|
||||||
@@ -92,26 +91,24 @@
|
|||||||
{
|
{
|
||||||
private DataGrid<ApiKeyResponse> Grid;
|
private DataGrid<ApiKeyResponse> Grid;
|
||||||
|
|
||||||
private async Task<DataGridItemResult<ApiKeyResponse>> ItemsProviderAsync(DataGridItemRequest request)
|
private ItemSource<ApiKeyResponse> ItemSource => ItemSourceFactory.From(LoadItemsAsync);
|
||||||
{
|
|
||||||
var query = $"?startIndex={request.StartIndex}&count={request.Count}";
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.SortColumn))
|
private async Task<IEnumerable<ApiKeyResponse>> LoadItemsAsync(
|
||||||
|
int startIndex, int count, string? filter, SortOption? sortOption
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var dir = request.SortDirection == SortState.Descending ? "desc" : "asc";
|
var query = $"?startIndex={startIndex}&count={count}";
|
||||||
query += $"&orderBy={request.SortColumn}&orderByDir={dir}";
|
|
||||||
|
if (sortOption != null)
|
||||||
|
{
|
||||||
|
var dir = sortOption.Direction == SortDirection.Descending ? "desc" : "asc";
|
||||||
|
query += $"&orderBy={sortOption.Column}&orderByDir={dir}";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.Filter))
|
if (!string.IsNullOrEmpty(filter))
|
||||||
query += $"&filter={request.Filter}";
|
query += $"&filter={filter}";
|
||||||
|
|
||||||
var data = await ApiClient.GetJson<CountedData<ApiKeyResponse>>($"api/admin/apikeys{query}");
|
return await ApiClient.GetJson<CountedData<ApiKeyResponse>>($"api/admin/apikeys{query}");
|
||||||
|
|
||||||
return new()
|
|
||||||
{
|
|
||||||
Items = data.Items,
|
|
||||||
TotalCount = data.TotalCount
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteAsync(ApiKeyResponse apiKeyResponse)
|
private async Task DeleteAsync(ApiKeyResponse apiKeyResponse)
|
||||||
|
|||||||
@@ -2,12 +2,13 @@
|
|||||||
|
|
||||||
@using System.Text.Json
|
@using System.Text.Json
|
||||||
@using Microsoft.AspNetCore.Authorization
|
@using Microsoft.AspNetCore.Authorization
|
||||||
|
@using MoonCore.Blazor.FlyonUi.Common
|
||||||
@using MoonCore.Blazor.FlyonUi.Grid
|
@using MoonCore.Blazor.FlyonUi.Grid
|
||||||
@using MoonCore.Blazor.FlyonUi.Grid.Columns
|
@using MoonCore.Blazor.FlyonUi.Grid.Columns
|
||||||
@using MoonCore.Blazor.FlyonUi.Grid.ToolbarItems
|
@using MoonCore.Blazor.FlyonUi.Grid.ToolbarItems
|
||||||
@using MoonCore.Blazor.FlyonUi.Helpers
|
@using MoonCore.Blazor.FlyonUi.Helpers
|
||||||
|
@using MoonCore.Common
|
||||||
@using MoonCore.Helpers
|
@using MoonCore.Helpers
|
||||||
@using MoonCore.Models
|
|
||||||
@using Moonlight.Client.Models
|
@using Moonlight.Client.Models
|
||||||
@using Moonlight.Client.Services
|
@using Moonlight.Client.Services
|
||||||
@using Moonlight.Shared.Http.Requests.Admin.Sys.Theme
|
@using Moonlight.Shared.Http.Requests.Admin.Sys.Theme
|
||||||
@@ -30,9 +31,7 @@
|
|||||||
|
|
||||||
<div class="my-8">
|
<div class="my-8">
|
||||||
<DataGrid TGridItem="ThemeResponse"
|
<DataGrid TGridItem="ThemeResponse"
|
||||||
ItemsProvider="ItemsProviderAsync"
|
ItemSource="ItemSource">
|
||||||
EnableFiltering="true"
|
|
||||||
EnablePagination="true">
|
|
||||||
|
|
||||||
<PropertyColumn Field="x => x.Id" Sortable="true"/>
|
<PropertyColumn Field="x => x.Id" Sortable="true"/>
|
||||||
<TemplateColumn Title="Name" Sortable="true">
|
<TemplateColumn Title="Name" Sortable="true">
|
||||||
@@ -69,7 +68,8 @@
|
|||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
|
|
||||||
<a @onclick="() => ExportAsync(context)" @onclick:preventDefault href="#" class="flex items-center mr-2 sm:mr-3">
|
<a @onclick="() => ExportAsync(context)" @onclick:preventDefault href="#"
|
||||||
|
class="flex items-center mr-2 sm:mr-3">
|
||||||
<i class="text-success icon-download me-1"></i>
|
<i class="text-success icon-download me-1"></i>
|
||||||
<span class="text-success">Export</span>
|
<span class="text-success">Export</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -104,27 +104,24 @@
|
|||||||
@code
|
@code
|
||||||
{
|
{
|
||||||
private DataGrid<ThemeResponse> Grid;
|
private DataGrid<ThemeResponse> Grid;
|
||||||
|
private ItemSource<ThemeResponse> ItemSource => ItemSourceFactory.From(LoadItemsAsync);
|
||||||
|
|
||||||
private async Task<DataGridItemResult<ThemeResponse>> ItemsProviderAsync(DataGridItemRequest request)
|
private async Task<IEnumerable<ThemeResponse>> LoadItemsAsync(
|
||||||
|
int startIndex, int count, string? filter, SortOption? sortOption
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var query = $"?startIndex={request.StartIndex}&count={request.Count}";
|
var query = $"?startIndex={startIndex}&count={count}";
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.SortColumn))
|
if (sortOption != null)
|
||||||
{
|
{
|
||||||
var dir = request.SortDirection == SortState.Descending ? "desc" : "asc";
|
var dir = sortOption.Direction == SortDirection.Descending ? "desc" : "asc";
|
||||||
query += $"&orderBy={request.SortColumn}&orderByDir={dir}";
|
query += $"&orderBy={sortOption.Column}&orderByDir={dir}";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.Filter))
|
if (!string.IsNullOrEmpty(filter))
|
||||||
query += $"&filter={request.Filter}";
|
query += $"&filter={filter}";
|
||||||
|
|
||||||
var data = await ApiClient.GetJson<CountedData<ThemeResponse>>($"api/admin/system/customisation/themes{query}");
|
return await ApiClient.GetJson<CountedData<ThemeResponse>>($"api/admin/system/customisation/themes{query}");
|
||||||
|
|
||||||
return new()
|
|
||||||
{
|
|
||||||
Items = data.Items,
|
|
||||||
TotalCount = data.TotalCount
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ImportAsync(InputFileChangeEventArgs eventArgs)
|
private async Task ImportAsync(InputFileChangeEventArgs eventArgs)
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
@page "/admin/users"
|
@page "/admin/users"
|
||||||
|
|
||||||
|
@using MoonCore.Blazor.FlyonUi.Common
|
||||||
@using MoonCore.Helpers
|
@using MoonCore.Helpers
|
||||||
@using MoonCore.Models
|
|
||||||
@using Moonlight.Shared.Http.Responses.Admin.Users
|
@using Moonlight.Shared.Http.Responses.Admin.Users
|
||||||
@using MoonCore.Blazor.FlyonUi.Grid
|
@using MoonCore.Blazor.FlyonUi.Grid
|
||||||
@using MoonCore.Blazor.FlyonUi.Grid.Columns
|
@using MoonCore.Blazor.FlyonUi.Grid.Columns
|
||||||
|
@using MoonCore.Common
|
||||||
|
|
||||||
@inject HttpApiClient ApiClient
|
@inject HttpApiClient ApiClient
|
||||||
@inject AlertService AlertService
|
@inject AlertService AlertService
|
||||||
@@ -19,10 +20,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<DataGrid @ref="Grid"
|
<DataGrid @ref="Grid"
|
||||||
TGridItem="UserResponse"
|
ItemSource="ItemSource">
|
||||||
ItemsProvider="ItemsProviderAsync"
|
|
||||||
EnableFiltering="true"
|
|
||||||
EnablePagination="true">
|
|
||||||
<PropertyColumn Field="x => x.Id" Sortable="true"/>
|
<PropertyColumn Field="x => x.Id" Sortable="true"/>
|
||||||
<PropertyColumn Field="x => x.Username" Sortable="true"/>
|
<PropertyColumn Field="x => x.Username" Sortable="true"/>
|
||||||
<PropertyColumn Field="x => x.Email" Sortable="true"/>
|
<PropertyColumn Field="x => x.Email" Sortable="true"/>
|
||||||
@@ -45,27 +43,24 @@
|
|||||||
@code
|
@code
|
||||||
{
|
{
|
||||||
private DataGrid<UserResponse> Grid;
|
private DataGrid<UserResponse> Grid;
|
||||||
|
private ItemSource<UserResponse> ItemSource => ItemSourceFactory.From(LoadItemsAsync);
|
||||||
|
|
||||||
private async Task<DataGridItemResult<UserResponse>> ItemsProviderAsync(DataGridItemRequest request)
|
private async Task<IEnumerable<UserResponse>> LoadItemsAsync(
|
||||||
|
int startIndex, int count, string? filter, SortOption? sortOption
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var query = $"?startIndex={request.StartIndex}&count={request.Count}";
|
var query = $"?startIndex={startIndex}&count={count}";
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.SortColumn))
|
if (sortOption != null)
|
||||||
{
|
{
|
||||||
var dir = request.SortDirection == SortState.Descending ? "desc" : "asc";
|
var dir = sortOption.Direction == SortDirection.Descending ? "desc" : "asc";
|
||||||
query += $"&orderBy={request.SortColumn}&orderByDir={dir}";
|
query += $"&orderBy={sortOption.Column}&orderByDir={dir}";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.Filter))
|
if (!string.IsNullOrEmpty(filter))
|
||||||
query += $"&filter={request.Filter}";
|
query += $"&filter={filter}";
|
||||||
|
|
||||||
var data = await ApiClient.GetJson<CountedData<UserResponse>>($"api/admin/users{query}");
|
return await ApiClient.GetJson<CountedData<UserResponse>>($"api/admin/users{query}");
|
||||||
|
|
||||||
return new()
|
|
||||||
{
|
|
||||||
Items = data.Items,
|
|
||||||
TotalCount = data.TotalCount
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteAsync(UserResponse response)
|
private async Task DeleteAsync(UserResponse response)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<Title>Moonlight.Shared</Title>
|
<Title>Moonlight.Shared</Title>
|
||||||
<PackageTags>shared</PackageTags>
|
<PackageTags>shared</PackageTags>
|
||||||
<PackageId>Moonlight.Shared</PackageId>
|
<PackageId>Moonlight.Shared</PackageId>
|
||||||
<Version>2.1.11</Version>
|
<Version>2.1.12</Version>
|
||||||
<Authors>Moonlight Panel</Authors>
|
<Authors>Moonlight Panel</Authors>
|
||||||
<Description>A build of the shared classes for moonlight development</Description>
|
<Description>A build of the shared classes for moonlight development</Description>
|
||||||
<PackageProjectUrl>https://github.com/Moonlight-Panel/Moonlight</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/Moonlight-Panel/Moonlight</PackageProjectUrl>
|
||||||
|
|||||||
Reference in New Issue
Block a user