Module im WebUI aktivieren und deaktivieren
Umsetzung von #560. Die Ansicht "Moduleinstellungen" zeigte bisher nur an, ob ein Modul laeuft. Jetzt laesst sich dort wie im Modul-Tab des Desktops festlegen, welche Module beim naechsten Start geladen werden. POST /api/modules/{name}/enabled nimmt den gewuenschten Zustand ausdruecklich entgegen ({"enabled": true|false}) und schaltet nicht einfach um. Zwei Klicks aus zwei Fenstern heben sich damit nicht auf, und ein wiederholter Aufruf aendert nichts mehr. Fehlerfaelle: - Unbekanntes Modul: 404. - Modul mit Aktivierungs-Blocker: 409. - Fehlender Zustand: 400. Die Pruefung war zuerst lueckenhaft, der Test hat es gefunden: Mit "bool Enabled" machte ein leerer Rumpf {} daraus false, und ein unvollstaendiger Aufruf haette das Modul deaktiviert. Gemeinsame Quelle statt Kopien: - KnownModules: Die Modulliste stand viermal im Code (Program, CoreViews, ModuleViews, hartkodiert im WebUI). Der Start registriert jetzt die eine Liste. - ModuleActivationView: Die Statusregeln des Desktops ("Aktiv - stoppt nach Neustart" usw.) liegen im Core. Desktop und WebUI zeigen dasselbe. ServerSettingsFile - gefunden, bevor das WebUI in die Datei schreiben durfte: ServerSettings.Load verschluckt jeden Lesefehler und liefert Vorgaben. "Frisch lesen, ein Feld aendern, speichern" haette eine gesperrte oder beschaedigte server_settings.xml durch Vorgaben ersetzt, und mit ihr Lizenzschluessel, Watchdog-Token, Mullvad-Account und Alchemy-Key. Genau so schrieb auch der Modul-Schalter des Desktops. ServerSettingsFile: - liest streng und schreibt bei unlesbarer Datei nichts, - schreibt atomar ueber eine Nachbardatei, - erhaelt unter Linux die Dateirechte, - serialisiert Aenderungen prozessweit. Der Desktop-Schalter benutzt ihn jetzt ebenfalls. Tests: Lizenzschluessel, Token und Alchemy-Key bleiben beim Umschalten in der Datei; eine kaputte Datei bleibt Byte fuer Byte unveraendert und die Anzeige bietet dann kein Umschalten an; Blocker, 404, 400, Idempotenz; die Statustabelle; strenges Lesen, atomares Schreiben und Rechte am Dateiobjekt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,7 @@ namespace PolyTrader.Tests.WebUi
|
||||
public const string Token = "webui-test-token-7f3a9c1e5b2d4f6a8c0e";
|
||||
|
||||
private readonly IHost _host;
|
||||
private readonly string _settingsDirectory;
|
||||
|
||||
public TradingState State { get; }
|
||||
public CopyTradingState CopyState { get; }
|
||||
@@ -44,6 +45,9 @@ namespace PolyTrader.Tests.WebUi
|
||||
public JobManager Jobs { get; }
|
||||
public WebUiOptions WebOptions { get; }
|
||||
|
||||
/// <summary>Eigene server_settings.xml je Testhost in einem temporaeren Ordner - nie die echte.</summary>
|
||||
public string SettingsPath => System.IO.Path.Combine(_settingsDirectory, "server_settings.xml");
|
||||
|
||||
/// <summary>Mit gueltigem Token.</summary>
|
||||
public HttpClient Client { get; }
|
||||
|
||||
@@ -51,9 +55,10 @@ namespace PolyTrader.Tests.WebUi
|
||||
public HttpClient Anonymous { get; }
|
||||
|
||||
private WebUiTestHost(IHost host, TradingState state, CopyTradingState copyState,
|
||||
TerminalLogger logger, JobManager jobs, WebUiOptions options)
|
||||
TerminalLogger logger, JobManager jobs, WebUiOptions options, string settingsDirectory)
|
||||
{
|
||||
_host = host;
|
||||
_settingsDirectory = settingsDirectory;
|
||||
State = state;
|
||||
CopyState = copyState;
|
||||
Logger = logger;
|
||||
@@ -82,6 +87,8 @@ namespace PolyTrader.Tests.WebUi
|
||||
var jobs = new JobManager();
|
||||
var options = new WebUiOptions { Enabled = true, AuthToken = Token };
|
||||
configureOptions?.Invoke(options);
|
||||
string settingsDirectory = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "polytrader-webui-" + Guid.NewGuid().ToString("N"));
|
||||
System.IO.Directory.CreateDirectory(settingsDirectory);
|
||||
|
||||
var host = await new HostBuilder()
|
||||
.ConfigureWebHost(web =>
|
||||
@@ -95,13 +102,24 @@ namespace PolyTrader.Tests.WebUi
|
||||
services.AddSingleton(copyState);
|
||||
services.AddSingleton(logger);
|
||||
services.AddSingleton(jobs);
|
||||
// Wie im Betrieb (Program): alle Module und die Einstellungsdatei. Tests koennen beides
|
||||
// in configureServices ersetzen - die letzte Registrierung gewinnt.
|
||||
services.AddSingleton(new PolyTrader.Core.Modularity.KnownModules(new PolyTrader.Core.Modularity.IPolyTraderModule[]
|
||||
{
|
||||
new PolyTrader.Modules.CopyTrading.CopyTradingModule(),
|
||||
new PolyTrader.Modules.ResolutionFarming.ResolutionFarmingModule(),
|
||||
new PolyTrader.Modules.Supervisor.SupervisorModule(),
|
||||
new PolyTrader.Modules.Accounting.AccountingModule()
|
||||
}));
|
||||
services.AddSingleton(new PolyTrader.Core.Configuration.ServerSettingsFile(
|
||||
System.IO.Path.Combine(settingsDirectory, "server_settings.xml")));
|
||||
configureServices?.Invoke(services);
|
||||
});
|
||||
web.Configure(app => app.UsePolyTraderWebPipeline());
|
||||
})
|
||||
.StartAsync();
|
||||
|
||||
return new WebUiTestHost(host, state, copyState, logger, jobs, options);
|
||||
return new WebUiTestHost(host, state, copyState, logger, jobs, options, settingsDirectory);
|
||||
}
|
||||
|
||||
/// <summary>CopyTrading-Repositories auf einer eigenen InMemory-Datenbank.</summary>
|
||||
@@ -158,6 +176,7 @@ namespace PolyTrader.Tests.WebUi
|
||||
Anonymous.Dispose();
|
||||
await _host.StopAsync();
|
||||
_host.Dispose();
|
||||
try { System.IO.Directory.Delete(_settingsDirectory, recursive: true); } catch { /* temporaer, darf liegen bleiben */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user