feat(ui): Blazor WebAssembly 마이그레이션 및 API-First 로그인 구현
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
using QuantEngine.Web.Components;
|
||||
using QuantEngine.Web.Services;
|
||||
using QuantEngine.Infrastructure.Data;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using QuantEngine.Web.Infrastructure;
|
||||
using QuantEngine.Infrastructure.Repositories;
|
||||
using QuantEngine.Infrastructure.Services;
|
||||
using QuantEngine.Core.Interfaces;
|
||||
@@ -10,7 +10,8 @@ using System.Text.Json;
|
||||
using static QuantEngine.Application.Services.DataCollectionService;
|
||||
using Microsoft.FluentUI.AspNetCore.Components;
|
||||
using Serilog;
|
||||
using QuantEngine.Web.Infrastructure;
|
||||
using QuantEngine.Web.Client.Infrastructure;
|
||||
using QuantEngine.Web.Client.Services;
|
||||
using QuantEngine.Web.Endpoints;
|
||||
|
||||
// Serilog Configuration with Telegram Sink
|
||||
@@ -25,10 +26,11 @@ builder.Host.UseSerilog();
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents();
|
||||
.AddInteractiveWebAssemblyComponents();
|
||||
|
||||
// Authentication and Custom State Provider
|
||||
// Authentication and Custom State Provider (Shared client components)
|
||||
builder.Services.AddCascadingAuthenticationState();
|
||||
builder.Services.AddScoped<LocalStorageService>();
|
||||
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
|
||||
builder.Services.AddAuthorizationCore();
|
||||
|
||||
@@ -100,6 +102,32 @@ app.MapStaticAssets();
|
||||
// Collection API Endpoints (must be before MapRazorComponents)
|
||||
app.MapCollectionEndpoints();
|
||||
|
||||
// Login API (API-First for Blazor WASM client authentication)
|
||||
app.MapPost("/api/auth/login", (LoginRequest request, IConfiguration config) =>
|
||||
{
|
||||
var expectedUser = config["AdminSettings:Username"] ?? "admin";
|
||||
var expectedPass = config["AdminSettings:Password"] ?? "quant123!";
|
||||
|
||||
if (request.Username == expectedUser && request.Password == expectedPass)
|
||||
{
|
||||
return Results.Ok(new { success = true, username = request.Username });
|
||||
}
|
||||
return Results.Json(new { success = false, error = "invalid_credentials" }, statusCode: 401);
|
||||
});
|
||||
|
||||
// Operational Report serving API (WASM safe file loading substitute)
|
||||
app.MapGet("/api/operational-report", async (IWebHostEnvironment env) =>
|
||||
{
|
||||
var path = Path.GetFullPath(Path.Combine(env.ContentRootPath, "..", "..", "..", "Temp", "operational_report.json"));
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return Results.NotFound(new { gate = "FAIL", error = "operational_report_missing" });
|
||||
}
|
||||
var json = await File.ReadAllTextAsync(path);
|
||||
using var doc = JsonDocument.Parse(json);
|
||||
return Results.Ok(doc.RootElement);
|
||||
});
|
||||
|
||||
app.MapGet("/api/history/{domain}", async (string domain, int? limit, IPostgresqlHistorySnapshotReader reader) =>
|
||||
{
|
||||
var rows = await reader.ReadAsync(domain, limit ?? 500);
|
||||
@@ -144,7 +172,14 @@ app.MapPost("/api/history/{domain}", async (string domain, JsonElement payload,
|
||||
});
|
||||
|
||||
app.MapRazorComponents<App>()
|
||||
.AddInteractiveServerRenderMode();
|
||||
.AddInteractiveWebAssemblyRenderMode()
|
||||
.AddAdditionalAssemblies(typeof(QuantEngine.Web.Client._Imports).Assembly);
|
||||
|
||||
app.Run();
|
||||
|
||||
public class LoginRequest
|
||||
{
|
||||
public string Username { get; set; } = "";
|
||||
public string Password { get; set; } = "";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user