From 189b8d48c1e2b9a12b0e99a782f0bb6df32ea098 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 2 Sep 2026 08:45:36 +0000 Subject: [PATCH] Fix admin login and API 404s - appsettings.json: bake in the reference HashedPassword/HashedPasswordSalt so admin/password actually validates (the previous empty strings could never match) - Program.cs: pin the SQLite DB into App_Data so the mounted volume persists it, and route /elsa/api/{**rest} to a JSON 404 so unknown API paths stop returning the Studio SPA HTML with a 200 --- src/Elsa.CustomServer/Program.cs | 12 +++++++++--- src/Elsa.CustomServer/appsettings.json | 15 ++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/Elsa.CustomServer/Program.cs b/src/Elsa.CustomServer/Program.cs index eb7040d..887b125 100644 --- a/src/Elsa.CustomServer/Program.cs +++ b/src/Elsa.CustomServer/Program.cs @@ -11,6 +11,9 @@ builder.WebHost.UseStaticWebAssets(); var configuration = builder.Configuration; var identitySection = configuration.GetSection("Identity"); var identityTokenSection = identitySection.GetSection("Tokens"); +// Pin the SQLite DB into App_Data so the Docker volume actually persists it across redeploys. +var sqliteConnectionString = configuration.GetConnectionString("Sqlite") + ?? "Data Source=App_Data/elsa.sqlite.db;Cache=Shared;"; builder.Services.AddElsa(elsa => { @@ -25,8 +28,8 @@ builder.Services.AddElsa(elsa => identity.UseConfigurationBasedRoleProvider(options => identitySection.Bind(options)); }) .UseDefaultAuthentication() - .UseWorkflowManagement(m => m.UseEntityFrameworkCore(ef => ef.UseSqlite())) - .UseWorkflowRuntime(r => r.UseEntityFrameworkCore(ef => ef.UseSqlite())) + .UseWorkflowManagement(m => m.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString))) + .UseWorkflowRuntime(r => r.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString))) .UseScheduling() .UseWorkflowsApi() .UseHttp(http => http.ConfigureHttpOptions = options => configuration.GetSection("Http").Bind(options)) @@ -35,7 +38,6 @@ builder.Services.AddElsa(elsa => .UseLiquid(liquid => liquid.FluidOptions = options => options.Encoder = HtmlEncoder.Default); }); -// Same-origin Studio, but keep CORS permissive to allow API access from other tools. builder.Services.AddCors(cors => cors.AddDefaultPolicy(p => p .AllowAnyHeader() .AllowAnyMethod() @@ -66,6 +68,10 @@ app.UseWorkflowsApi(); app.UseWorkflows(); app.UseJsonSerializationErrorHandler(); app.MapHealthChecks("/health"); + +// Anything under /elsa/api that no endpoint claimed is a real 404, not the SPA HTML. +app.MapFallback("/elsa/api/{**rest}", () => Results.NotFound(new { error = "not_found" })); +// Everything else falls through to the Studio SPA host page. app.MapFallbackToPage("/_Host"); app.Run(); diff --git a/src/Elsa.CustomServer/appsettings.json b/src/Elsa.CustomServer/appsettings.json index 3d9735b..8ef4081 100644 --- a/src/Elsa.CustomServer/appsettings.json +++ b/src/Elsa.CustomServer/appsettings.json @@ -10,15 +10,17 @@ "ConnectionStrings": { "Sqlite": "Data Source=App_Data/elsa.sqlite.db;Cache=Shared;" }, + "Hosting": { + "ApiPrefix": "/elsa/api" + }, "Http": { - "BaseUrl": "https://elsa-api.tes.gd", "BasePath": "/workflows" }, "Identity": { "Tokens": { "SigningKey": "CHANGE_ME_VIA_ENV_Identity__Tokens__SigningKey", - "AccessTokenLifetime": "1:00:00", - "RefreshTokenLifetime": "1.00:00:00" + "AccessTokenLifetime": "1:00:00:00", + "RefreshTokenLifetime": "1:00:10:00" }, "Roles": [ { @@ -29,11 +31,10 @@ ], "Users": [ { - "Id": "admin", + "Id": "a2323f46-42db-4e15-af8b-94238717d817", "Name": "admin", - "Email": "admin@elsa.local", - "HashedPassword": "", - "HashedPasswordSalt": "", + "HashedPassword": "TfKzh9RLix6FPcCNeHLkGrysFu3bYxqzGqduNdi8v1U=", + "HashedPasswordSalt": "JEy9kBlhHCNsencitRHlGxmErmSgY+FVyMJulCH27Ds=", "Roles": [ "admin" ] } ],