WebUI gibt keine Geheimnisse mehr heraus und aendert keine Zugangseinstellungen
Behebt #562. Entscheidung Richard, 13.09.2026: Geheimnisse verwalten wir ausschliesslich im Desktop. Bis dahin lieferte GET /api/settings/webui das Zugangs-Token im Klartext. Ueber das WebUI liessen sich ausserdem ein Token setzen, ein neues erzeugen und LocalOnly abschalten. Wer das Token hatte, konnte das WebUI damit ueber unverschluesseltes HTTP ins Netz oeffnen, sich den Zugang verlegen oder sich selbst aussperren. Jetzt: - GET /api/settings/webui liefert Enabled, Port, LocalOnly und vom Token nur hasToken. - POST /api/settings/webui und /webui/generate-token antworten mit 403 und protokollieren den Versuch. Sie bleiben als ausdrueckliche Ablehnung stehen: Ohne eigene Route faengt die Fallback-Route den POST ab und antwortet mit 200, ein altes Skript hielte das fuer einen Erfolg. - Die WebUI-Einstellungsansicht zeigt den Zugang nur noch an. Gepflegt wird er im Desktop unter Einstellungen -> WebUI. WebUiSecretsTests zaehlt alle GET-Routen selbst auf und prueft jede Antwort gegen Kanarienwerte. Geprueft werden ApiKey, ApiSecret, ApiPassphrase und PrivateKey eines Kontos, Mullvad-Account, Alchemy-Key, Watchdog-Token, Lizenzschluessel und das WebUI-Token. Eine neue Route, die ein Konto oder die Server-Einstellungen serialisiert, faellt damit auf, ohne dass jemand an diesen Test denken muss. Gegen die alte Route schlug er fehl ("GET /api/settings/webui liefert ein Geheimnis aus"), jetzt ist er gruen. Ausserdem festgehalten: /api/accounts kennt nur GET. Polymarket-Konten bleiben im WebUI lesbar und nicht aenderbar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,9 +7,22 @@ using PolyTraderSharp.Services;
|
||||
|
||||
namespace PolyTrader.Web.Endpoints
|
||||
{
|
||||
/// <summary>
|
||||
/// Zugangseinstellungen des WebUI - nur lesend (#562).
|
||||
///
|
||||
/// <para>Entscheidung Richard, 13.09.2026: Geheimnisse verwalten wir ausschliesslich im Desktop. Bis
|
||||
/// dahin lieferte GET /api/settings/webui das Zugangs-Token im Klartext aus, und ueber das WebUI
|
||||
/// liessen sich Token setzen, ein neues erzeugen und LocalOnly abschalten. Wer das Token hatte,
|
||||
/// konnte damit das WebUI ins Netz oeffnen (unverschluesseltes HTTP), sich den Zugang verlegen oder
|
||||
/// sich selbst aussperren.</para>
|
||||
///
|
||||
/// <para>Port, LocalOnly, Enabled und das Token werden jetzt nur noch im Desktop unter
|
||||
/// Einstellungen -> WebUI gepflegt. Das WebUI zeigt die Werte an, vom Token nur, ob es gesetzt ist.</para>
|
||||
/// </summary>
|
||||
public static class SettingsEndpoints
|
||||
{
|
||||
public record UpdateWebUiSettingsRequest(bool Enabled, int Port, bool LocalOnly, string? AuthToken);
|
||||
internal const string DesktopOnlyMessage =
|
||||
"Zugang, Port und Token des WebUI werden ausschließlich im Desktop verwaltet (Einstellungen → WebUI).";
|
||||
|
||||
public static IEndpointRouteBuilder MapSettingsEndpoints(this IEndpointRouteBuilder routes)
|
||||
{
|
||||
@@ -24,51 +37,23 @@ namespace PolyTrader.Web.Endpoints
|
||||
port = opt.Port,
|
||||
localOnly = opt.LocalOnly,
|
||||
hasToken = !string.IsNullOrWhiteSpace(opt.AuthToken),
|
||||
token = opt.AuthToken
|
||||
managedIn = "desktop"
|
||||
});
|
||||
});
|
||||
|
||||
group.MapPost("/webui", (UpdateWebUiSettingsRequest req, IOptions<WebUiOptions> optionsProvider, TerminalLogger logger) =>
|
||||
{
|
||||
var opt = optionsProvider.Value;
|
||||
opt.Enabled = req.Enabled;
|
||||
opt.Port = req.Port > 0 && req.Port <= 65535 ? req.Port : 6001;
|
||||
opt.LocalOnly = req.LocalOnly;
|
||||
if (req.AuthToken != null)
|
||||
{
|
||||
opt.AuthToken = req.AuthToken.Trim();
|
||||
}
|
||||
|
||||
WebUiConfigManager.SaveToLocalSettings(opt);
|
||||
logger.Info($"🌐 WebUI: Einstellungen gespeichert (Port {opt.Port}, LocalOnly: {opt.LocalOnly}).");
|
||||
|
||||
return Results.Ok(new
|
||||
{
|
||||
success = true,
|
||||
enabled = opt.Enabled,
|
||||
port = opt.Port,
|
||||
localOnly = opt.LocalOnly,
|
||||
hasToken = !string.IsNullOrWhiteSpace(opt.AuthToken)
|
||||
});
|
||||
});
|
||||
|
||||
group.MapPost("/webui/generate-token", (IOptions<WebUiOptions> optionsProvider, TerminalLogger logger) =>
|
||||
{
|
||||
var opt = optionsProvider.Value;
|
||||
string newToken = WebUiConfigManager.GenerateSecureToken();
|
||||
opt.AuthToken = newToken;
|
||||
|
||||
WebUiConfigManager.SaveToLocalSettings(opt);
|
||||
logger.Info("🔐 WebUI: Neues Zugangs-Token generiert und in appsettings.Local.json gespeichert.");
|
||||
|
||||
return Results.Ok(new
|
||||
{
|
||||
success = true,
|
||||
token = newToken
|
||||
});
|
||||
});
|
||||
// Die frueheren Schreibwege bleiben als ausdrueckliche Ablehnung stehen, statt zu verschwinden:
|
||||
// Ohne eigene Route faengt die Fallback-Route (index.html) den POST ab und antwortet mit 200 -
|
||||
// ein altes Skript hielte das fuer einen Erfolg.
|
||||
group.MapPost("/webui", RejectDesktopOnly);
|
||||
group.MapPost("/webui/generate-token", RejectDesktopOnly);
|
||||
|
||||
return routes;
|
||||
}
|
||||
|
||||
private static IResult RejectDesktopOnly(HttpContext context, TerminalLogger logger)
|
||||
{
|
||||
logger.Warning($"🌐 WebUI: Änderung der Zugangseinstellungen über {context.Request.Path} abgelehnt – nur im Desktop möglich.");
|
||||
return Results.Json(new { error = DesktopOnlyMessage }, statusCode: StatusCodes.Status403Forbidden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user