License grace period: keep running when the master is down or rejects the key (LicenseGraceHours, default 72 h), start with the last confirmed license, auto-retry; panel restart button (port/panel settings without program restart, login kept); tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -486,6 +486,49 @@ async Task PanelTests()
|
||||
using (var da = new System.IO.Compression.ZipArchive(new MemoryStream(downZip)))
|
||||
Check(down.IsSuccessStatusCode && da.GetEntry("defaultES2File.txt") != null, "The current save can be downloaded as ZIP");
|
||||
|
||||
// Lizenz: Master fällt aus -> der Server läuft weiter, erst nach der Kulanzzeit wird er gestoppt
|
||||
LicenseCache.Save(dir, "test", "Tester", "Test", DateTime.UtcNow.AddHours(-5));
|
||||
var cachedLicense = LicenseCache.Load(dir, "test");
|
||||
Check(cachedLicense != null && cachedLicense.Owner == "Tester" && LicenseCache.Load(dir, "other-key") == null
|
||||
&& !File.ReadAllText(Path.Combine(dir, "license.json")).Contains("\"test\""),
|
||||
"The last license check is remembered (only a hash of the key)");
|
||||
Srv().LicenseConfirmedUtc = DateTime.UtcNow.AddHours(-10); // innerhalb der 72 h: läuft weiter
|
||||
await Task.Delay(500);
|
||||
Check(host.State == HostState.Running, "Server keeps running while the license is unconfirmed but within the grace period");
|
||||
Srv().LicenseConfirmedUtc = DateTime.UtcNow.AddHours(-100); // Kulanzzeit abgelaufen
|
||||
await WaitForState(HostState.Error);
|
||||
Check(host.State == HostState.Error && (host.LastError ?? "").Contains("license"), "After the grace period the game server stops: " + host.LastError);
|
||||
Check((await Call(owner, "GET", "api/session")).status == 200, "The panel stays reachable after the license stop");
|
||||
Check((await Call(owner, "POST", "api/server/start")).status == 200, "It can be started again");
|
||||
await WaitForState(HostState.Running);
|
||||
Check(host.State == HostState.Running, "Running again after the start");
|
||||
|
||||
// Panel neu starten: eigener Port, danach wieder zurück auf den Spiel-Port - angemeldet bleiben
|
||||
Check((await Call(owner, "POST", "api/config", new { panelPort = 17791 })).status == 200, "Panel port can be changed");
|
||||
var pr = await Call(owner, "POST", "api/server/restart-panel");
|
||||
Check(pr.status == 200 && pr.json.GetProperty("url").GetString().Contains(":17791/"), "Restart panel returns the new address: " + pr.json);
|
||||
int code = 0;
|
||||
for (int i = 0; i < 30 && code != 200; i++)
|
||||
{
|
||||
await Task.Delay(300);
|
||||
try { code = (int)(await owner.GetAsync("http://127.0.0.1:17791/api/status")).StatusCode; } catch { }
|
||||
}
|
||||
Check(code == 200, "Panel answers on the new port and the login is kept");
|
||||
var back = new HttpRequestMessage(HttpMethod.Post, "http://127.0.0.1:17791/api/config")
|
||||
{ Content = new StringContent("{\"panelPort\":0}", System.Text.Encoding.UTF8, "application/json") };
|
||||
back.Headers.Add("X-MSCO-Panel", "1");
|
||||
await owner.SendAsync(back);
|
||||
var back2 = new HttpRequestMessage(HttpMethod.Post, "http://127.0.0.1:17791/api/server/restart-panel");
|
||||
back2.Headers.Add("X-MSCO-Panel", "1");
|
||||
await owner.SendAsync(back2);
|
||||
code = 0;
|
||||
for (int i = 0; i < 30 && code != 200; i++)
|
||||
{
|
||||
await Task.Delay(300);
|
||||
try { code = (await Call(owner, "GET", "api/status")).status; } catch { }
|
||||
}
|
||||
Check(code == 200 && host.Panel.SharesGamePort, "Panel is back on the game port");
|
||||
|
||||
await Call(owner, "POST", "api/logout");
|
||||
Check((await Call(owner, "GET", "api/status")).status == 401, "Logout ends the session");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user