Implemented hybrid cache for user sessions, api keys and database provided settings. Cleaned up startup and adjusted caching option models for features

This commit is contained in:
2026-02-12 15:29:35 +01:00
parent dd44e5bb86
commit 741a60adc6
19 changed files with 240 additions and 132 deletions

View File

@@ -17,20 +17,26 @@ public partial class Startup
{
private static void AddAuth(WebApplicationBuilder builder)
{
// OIDC
var oidcOptions = new OidcOptions();
builder.Configuration.GetSection("Moonlight:Oidc").Bind(oidcOptions);
// API Key
var apiKeyOptions = new ApiOptions();
builder.Configuration.GetSection("Moonlight:Api").Bind(apiKeyOptions);
builder.Services.AddOptions<ApiOptions>().BindConfiguration("Moonlight:Api");
// Session
builder.Services.AddOptions<UserOptions>().BindConfiguration("Moonlight:User");
builder.Services.AddScoped<UserAuthService>();
// Authentication
builder.Services.AddAuthentication("Main")
.AddPolicyScheme("Main", null, options =>
{
options.ForwardDefaultSelector += context => context.Request.Headers.Authorization.Count > 0 ? "ApiKey" : "Session";
})
.AddPolicyScheme("Main", null,
options =>
{
options.ForwardDefaultSelector += context =>
context.Request.Headers.Authorization.Count > 0 ? "ApiKey" : "Session";
})
.AddCookie("Session", null, options =>
{
options.Events.OnSigningIn += async context =>
@@ -83,7 +89,7 @@ public partial class Startup
var scopes = oidcOptions.Scopes ?? ["openid", "email", "profile"];
options.Scope.Clear();
foreach (var scope in scopes)
options.Scope.Add(scope);
@@ -97,18 +103,26 @@ public partial class Startup
options.GetClaimsFromUserInfoEndpoint = true;
})
.AddScheme<ApiKeySchemeOptions, ApiKeySchemeHandler>("ApiKey", null, options =>
{
options.LookupCacheTime = TimeSpan.FromMinutes(apiKeyOptions.LookupCacheMinutes);
});
builder.Logging.AddFilter("Moonlight.Api.Implementations.ApiKeyScheme.ApiKeySchemeHandler", LogLevel.Warning);
.AddScheme<ApiKeySchemeOptions, ApiKeySchemeHandler>("ApiKey", null,
options =>
{
options.LookupL1CacheTime = apiKeyOptions.LookupCacheL1Expiry;
options.LookupL2CacheTime = apiKeyOptions.LookupCacheL2Expiry;
});
// Authorization
builder.Services.AddAuthorization();
// Reduce log noise
builder.Logging.AddFilter("Moonlight.Api.Implementations.ApiKeyScheme.ApiKeySchemeHandler", LogLevel.Warning);
// Custom permission handling using named policies
builder.Services.AddSingleton<IAuthorizationHandler, PermissionAuthorizationHandler>();
builder.Services.AddSingleton<IAuthorizationPolicyProvider, PermissionPolicyProvider>();
builder.Services.AddOptions<SettingsOptions>().BindConfiguration("Moonlight:Settings");
builder.Services.AddScoped<SettingsService>();
builder.Services.AddScoped<UserDeletionService>();
builder.Services.AddScoped<UserLogoutService>();
builder.Services.AddScoped<UserAuthService>();
}
private static void UseAuth(WebApplication application)