FEAT: Migrate Collection and User Auth endpoints to FastEndpoints (API-First), implement MudDialog based Users CRUD (MVVM) and update AGENTS.md guidelines
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Failing after 6s
Quant Engine CI/CD Pipeline / validate-core (push) Failing after 10s
Quant Engine CI/CD Pipeline / validate-ui-and-storage (push) Has been skipped
Deploy to Production / Build & Deploy to Production (push) Failing after 1m5s

This commit is contained in:
2026-07-06 10:24:00 +09:00
parent 5e22844a4a
commit dbb3a78afb
5 changed files with 711 additions and 208 deletions
+18 -5
View File
@@ -3,6 +3,7 @@ using QuantEngine.Infrastructure.Data;
using Microsoft.AspNetCore.Components.Authorization;
using QuantEngine.Web.Infrastructure;
using Npgsql;
using FastEndpoints;
using QuantEngine.Infrastructure.Repositories;
using QuantEngine.Infrastructure.Services;
using QuantEngine.Core.Interfaces;
@@ -92,11 +93,13 @@ builder.Services.AddScoped<IKisApiClient, KisApiClient>();
// builder.Services.AddScoped<ICollectionOrchestrator, KisDataCollectionOrchestrator>();
// builder.Services.AddScoped<DataCollectionService>();
// HTTP Client & API Services
builder.Services.AddHttpClient<ApiClient>();
builder.Services.AddScoped<ApiClient>();
builder.Services.AddFastEndpoints();
var app = builder.Build();
app.UseFastEndpoints();
var adminSettings = app.Configuration.GetSection("AdminSettings");
var adminUsername = adminSettings["Username"] ?? "admin";
var adminPassword = adminSettings["Password"] ?? string.Empty;
@@ -202,9 +205,6 @@ app.MapGet("/login", (HttpContext ctx) =>
ctx.Response.Redirect("/login.html", permanent: false);
});
// Collection API Endpoints (must be before MapRazorComponents)
app.MapCollectionEndpoints();
// Login API (API-First for Blazor WASM client authentication)
app.MapPost("/api/auth/login", async (JsonElement payload, HttpContext httpContext, IWorkspaceRepository workspaceRepo, IWebHostEnvironment env) =>
{
@@ -522,12 +522,25 @@ internal sealed class QuantAdminAuthHandler : AuthenticationHandler<Authenticati
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
// Check quant_auth_token cookie for server-side authorization of static Page routes
if (Request.Cookies.TryGetValue("quant_auth_token", out var token) && !string.IsNullOrWhiteSpace(token))
{
var claims = new[] {
new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, "admin"),
new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Role, "Admin")
};
var identity = new System.Security.Claims.ClaimsIdentity(claims, Scheme.Name);
var principal = new System.Security.Claims.ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, Scheme.Name);
return Task.FromResult(AuthenticateResult.Success(ticket));
}
return Task.FromResult(AuthenticateResult.NoResult());
}
protected override Task HandleChallengeAsync(AuthenticationProperties properties)
{
Response.StatusCode = StatusCodes.Status401Unauthorized;
// Instead of hard 401 response which breaks routing or triggers static page redirects, redirect to login page
Response.Redirect("/login.html");
return Task.CompletedTask;
}
}