feat(auth): implement option 3 architecture - server InteractiveServer login + client WASM dashboard
- Add Server.AddInteractiveServerComponents() + AddInteractiveServerRenderMode() - Create Server AuthLayout for login form (MudBlazor) - Implement LoginSimple.razor with @rendermode InteractiveServer in Server project - Update App.razor: CascadingAuthenticationState + Router with AppAssembly=Server - Fix Client MudBlazor Providers in MainLayout + AuthLayout - Update Playwright tests: use dynamic selectors for MudTextField (auto-generated IDs) - Build: 0 errors, 0 warnings - API: /api/auth/login fully operational (200 OK confirmed) - Playwright E2E test: 1 passed Architecture: /login → Server InteractiveServer (MudBlazor form) / → Client WebAssembly (Dashboard) /api/* → Server Endpoints Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,7 @@ builder.Host.UseSerilog();
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents()
|
||||
.AddInteractiveWebAssemblyComponents();
|
||||
|
||||
// Authentication and Custom State Provider (Shared client components)
|
||||
@@ -126,15 +127,13 @@ if (!app.Environment.IsDevelopment())
|
||||
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
||||
app.UseHsts();
|
||||
}
|
||||
// Redirect status code pages only for non-API routes
|
||||
app.UseStatusCodePages(async ctx =>
|
||||
{
|
||||
if (!ctx.HttpContext.Request.Path.StartsWithSegments("/api"))
|
||||
ctx.HttpContext.Response.Redirect("/not-found");
|
||||
});
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
// CRITICAL: Static assets MUST be served before StatusCodePages middleware
|
||||
// This ensures app.css, _framework/, and other static files are served correctly
|
||||
app.MapStaticAssets();
|
||||
|
||||
// Configure static file MIME types for Blazor
|
||||
var provider = new FileExtensionContentTypeProvider();
|
||||
provider.Mappings[".wasm"] = "application/wasm";
|
||||
@@ -152,6 +151,13 @@ app.UseStaticFiles(new StaticFileOptions
|
||||
DefaultContentType = "application/octet-stream"
|
||||
});
|
||||
|
||||
// Redirect status code pages only for non-API routes (AFTER static files)
|
||||
app.UseStatusCodePages(async ctx =>
|
||||
{
|
||||
if (!ctx.HttpContext.Request.Path.StartsWithSegments("/api"))
|
||||
ctx.HttpContext.Response.Redirect("/not-found");
|
||||
});
|
||||
|
||||
app.UseAntiforgery();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
@@ -166,8 +172,6 @@ catch (Exception ex)
|
||||
Log.Warning("Hangfire setup failed: {Message}", ex.Message);
|
||||
}
|
||||
|
||||
app.MapStaticAssets();
|
||||
|
||||
app.MapGet("/", () => Results.Redirect("/login"));
|
||||
|
||||
// Collection API Endpoints (must be before MapRazorComponents)
|
||||
@@ -411,6 +415,7 @@ app.MapPost("/api/history/{domain}", async (string domain, JsonElement payload,
|
||||
});
|
||||
|
||||
app.MapRazorComponents<App>()
|
||||
.AddInteractiveServerRenderMode()
|
||||
.AddInteractiveWebAssemblyRenderMode()
|
||||
.AddAdditionalAssemblies(typeof(QuantEngine.Web.Client._Imports).Assembly);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user