Separating runtime from application code to improve building. Upgraded mooncore packages. Started switching to flyonui. Added PluginFramework plugin loading via mooncore

This commit is contained in:
2025-07-11 17:13:37 +02:00
parent 7e158d48c6
commit eaece9e334
67 changed files with 448 additions and 234 deletions

View File

@@ -4,6 +4,7 @@ using Moonlight.ApiServer.Database;
using Moonlight.ApiServer.Implementations.Diagnose;
using Moonlight.ApiServer.Implementations.Metrics;
using Moonlight.ApiServer.Interfaces;
using Moonlight.ApiServer.Models;
using Moonlight.ApiServer.Plugins;
using Moonlight.ApiServer.Services;
using OpenTelemetry.Metrics;
@@ -11,7 +12,6 @@ using OpenTelemetry.Trace;
namespace Moonlight.ApiServer.Implementations.Startup;
[PluginStartup]
public class CoreStartup : IPluginStartup
{
public Task BuildApplication(IServiceProvider serviceProvider, IHostApplicationBuilder builder)
@@ -81,20 +81,37 @@ public class CoreStartup : IPluginStartup
#endregion
#region Client / Frontend
if (configuration.Client.Enable)
{
builder.Services.AddSingleton(new FrontendConfigurationOption()
{
Scripts =
[
"/_content/Moonlight.Client/js/moonlight.js", "/_content/Moonlight.Client/js/moonCore.js",
"/_content/Moonlight.Client/ace/ace.js"
],
Styles = ["/css/style.min.css"]
});
}
#endregion
return Task.CompletedTask;
}
public Task ConfigureApplication(IServiceProvider serviceProvider, IApplicationBuilder app)
{
var configuration = serviceProvider.GetRequiredService<AppConfiguration>();
#region Prometheus
if(configuration.Metrics.Enable)
if (configuration.Metrics.Enable)
app.UseOpenTelemetryPrometheusScrapingEndpoint();
#endregion
return Task.CompletedTask;
}

View File

@@ -0,0 +1,62 @@
using System.Security.Claims;
using Microsoft.EntityFrameworkCore;
using MoonCore.Extended.Abstractions;
using MoonCore.Extended.JwtInvalidation;
using Moonlight.ApiServer.Database.Entities;
namespace Moonlight.ApiServer.Implementations;
public class UserAuthInvalidation : IJwtInvalidateHandler
{
private readonly DatabaseRepository<User> UserRepository;
private readonly DatabaseRepository<ApiKey> ApiKeyRepository;
public UserAuthInvalidation(
DatabaseRepository<User> userRepository,
DatabaseRepository<ApiKey> apiKeyRepository
)
{
UserRepository = userRepository;
ApiKeyRepository = apiKeyRepository;
}
public async Task<bool> Handle(ClaimsPrincipal principal)
{
var userIdClaim = principal.FindFirstValue("userId");
if (!string.IsNullOrEmpty(userIdClaim))
{
var userId = int.Parse(userIdClaim);
var user = await UserRepository
.Get()
.FirstOrDefaultAsync(x => x.Id == userId);
if (user == null)
return true; // User is deleted, invalidate session
var iatStr = principal.FindFirstValue("iat")!;
var iat = DateTimeOffset.FromUnixTimeSeconds(long.Parse(iatStr));
// If the token has been issued before the token valid time, its expired, and we want to invalidate it
return user.TokenValidTimestamp > iat;
}
var apiKeyIdClaim = principal.FindFirstValue("apiKeyId");
if (!string.IsNullOrEmpty(apiKeyIdClaim))
{
var apiKeyId = int.Parse(apiKeyIdClaim);
var apiKey = await ApiKeyRepository
.Get()
.FirstOrDefaultAsync(x => x.Id == apiKeyId);
// If the api key exists, we don't want to invalidate the request.
// If it doesn't exist we want to invalidate the request
return apiKey == null;
}
return true;
}
}