Deployment-Center-Integration im WinFormsHost
Loest die getrennten Server Watchdog (watchdog.mhdf.de) und LicenseLabrador (license.mhdf.de) durch das Deployment Center (dc.mhdf.de) ab. - DcConfig: einkompilierte Basis-URL und Produkt-Slug, Version aus BuildInfo - DcApiClient: gemeinsamer HTTP-Zugang - DcHeartbeatService: Heartbeat mit Metriken und DB-Health-Check - DcErrorReporter/DcErrorSink: Error- und Fatal-Meldungen an den Fehler-Stream - DcUpdateService: Update-Pruefung gegen den UpdateService - LicenseGuard/LicenseDialog: Lizenzgate ueber /api/license/v1/validate, mit LicenseSession, Hardware-ID v2 und Unterscheidung transienter Fehler WatchdogHeartbeatService entfernt, Betriebsdoku ersetzt. Build: 0 Fehler. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
using LicenseLabrador.Client;
|
||||
using Deploymentcenter.Client;
|
||||
|
||||
namespace Predictalytics.WinFormsHost.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Modal dialog shown at startup when no usable license is present.
|
||||
/// Lets the user enter/activate a license key; closes with OK only after a
|
||||
/// successful, checksum-verified validation.
|
||||
/// Lets the user enter/activate a license key; closes with OK only after the Deployment
|
||||
/// Center confirmed the activation for this machine.
|
||||
/// </summary>
|
||||
public sealed class LicenseDialog : Form
|
||||
{
|
||||
@@ -15,9 +15,10 @@ public sealed class LicenseDialog : Form
|
||||
private readonly Button _btnActivate;
|
||||
private readonly Button _btnExit;
|
||||
|
||||
public LicenseResult? Result { get; private set; }
|
||||
/// <summary>Set once the activation succeeded.</summary>
|
||||
public LicenseSession? Session { get; private set; }
|
||||
|
||||
public LicenseDialog(LicenseClient client, LicenseResult? lastResult)
|
||||
public LicenseDialog(LicenseClient client, HardwareIdResult hardware, LicenseValidationResult? lastResult)
|
||||
{
|
||||
_client = client;
|
||||
|
||||
@@ -26,27 +27,38 @@ public sealed class LicenseDialog : Form
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
ClientSize = new Size(460, 190);
|
||||
ClientSize = new Size(560, 230);
|
||||
|
||||
var lblInfo = new Label
|
||||
{
|
||||
Text = "Diese Installation benötigt eine gültige Lizenz.\nBitte Lizenzschlüssel eingeben (Format: XXXXX-XXXXX-XXXXX-XXXXX-XXXXX):",
|
||||
Location = new Point(12, 12),
|
||||
Size = new Size(436, 34)
|
||||
Size = new Size(536, 34)
|
||||
};
|
||||
|
||||
_txtKey = new TextBox
|
||||
{
|
||||
Location = new Point(12, 52),
|
||||
Size = new Size(436, 26),
|
||||
Size = new Size(536, 26),
|
||||
Font = new Font("Consolas", 11f),
|
||||
CharacterCasing = CharacterCasing.Upper
|
||||
};
|
||||
|
||||
// The hardware ID is what the activation is bound to — without it, support cannot
|
||||
// tell which slot to release when a machine is replaced.
|
||||
var lblHardware = new Label
|
||||
{
|
||||
Text = $"Hardware-ID: {hardware.HardwareId} (Quelle: {hardware.HwidSource})",
|
||||
Location = new Point(12, 84),
|
||||
Size = new Size(536, 20),
|
||||
ForeColor = Color.DimGray,
|
||||
AutoEllipsis = true
|
||||
};
|
||||
|
||||
_lblStatus = new Label
|
||||
{
|
||||
Location = new Point(12, 84),
|
||||
Size = new Size(436, 50),
|
||||
Location = new Point(12, 110),
|
||||
Size = new Size(536, 62),
|
||||
ForeColor = Color.Firebrick,
|
||||
Text = FormatInitialStatus(lastResult)
|
||||
};
|
||||
@@ -54,7 +66,7 @@ public sealed class LicenseDialog : Form
|
||||
_btnActivate = new Button
|
||||
{
|
||||
Text = "Aktivieren",
|
||||
Location = new Point(252, 146),
|
||||
Location = new Point(352, 186),
|
||||
Size = new Size(96, 30)
|
||||
};
|
||||
_btnActivate.Click += async (_, _) => await ActivateAsync();
|
||||
@@ -62,20 +74,29 @@ public sealed class LicenseDialog : Form
|
||||
_btnExit = new Button
|
||||
{
|
||||
Text = "Beenden",
|
||||
Location = new Point(354, 146),
|
||||
Location = new Point(454, 186),
|
||||
Size = new Size(94, 30),
|
||||
DialogResult = DialogResult.Cancel
|
||||
};
|
||||
|
||||
AcceptButton = _btnActivate;
|
||||
CancelButton = _btnExit;
|
||||
Controls.AddRange(new Control[] { lblInfo, _txtKey, _lblStatus, _btnActivate, _btnExit });
|
||||
Controls.AddRange(new Control[] { lblInfo, _txtKey, lblHardware, _lblStatus, _btnActivate, _btnExit });
|
||||
}
|
||||
|
||||
private static string FormatInitialStatus(LicenseResult? lastResult)
|
||||
private static string FormatInitialStatus(LicenseValidationResult? lastResult)
|
||||
{
|
||||
if (lastResult == null || lastResult.State == LicenseState.NoLicense) return "";
|
||||
return $"Letzte Prüfung: {lastResult.State} — {lastResult.Message}";
|
||||
if (lastResult is null) return "";
|
||||
|
||||
// IsTransient means the server gave no verdict at all — telling the user their
|
||||
// license is bad would be wrong, the connection is.
|
||||
if (lastResult.IsTransient)
|
||||
{
|
||||
return "Das Deployment Center ist derzeit nicht erreichbar und es liegt keine " +
|
||||
"gültige Offline-Prüfung mehr vor. Bitte Verbindung prüfen und erneut versuchen.\n" +
|
||||
lastResult.Message;
|
||||
}
|
||||
return $"Letzte Prüfung: {lastResult.Status} — {lastResult.Message}";
|
||||
}
|
||||
|
||||
private async Task ActivateAsync()
|
||||
@@ -83,27 +104,28 @@ public sealed class LicenseDialog : Form
|
||||
var key = _txtKey.Text.Trim();
|
||||
if (string.IsNullOrWhiteSpace(key))
|
||||
{
|
||||
_lblStatus.ForeColor = Color.Firebrick;
|
||||
_lblStatus.Text = "Bitte einen Lizenzschlüssel eingeben.";
|
||||
return;
|
||||
}
|
||||
|
||||
_btnActivate.Enabled = false;
|
||||
_lblStatus.ForeColor = Color.DimGray;
|
||||
_lblStatus.Text = "Prüfe Lizenz am Server...";
|
||||
_lblStatus.Text = "Prüfe Lizenz am Deployment Center...";
|
||||
|
||||
try
|
||||
{
|
||||
var result = await _client.ValidateAsync(key);
|
||||
if (result.IsUsable && _client.VerifyChecksum(result))
|
||||
var result = await _client.ValidateAsync(DcConfig.ProductSlug, key, DcConfig.BaseUrl);
|
||||
if (result.IsValid)
|
||||
{
|
||||
Result = result;
|
||||
Session = new LicenseSession(_client, key, result);
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
_lblStatus.ForeColor = Color.Firebrick;
|
||||
_lblStatus.Text = $"Lizenz nicht nutzbar ({result.State}):\n{result.Message}";
|
||||
_lblStatus.Text = $"Lizenz nicht nutzbar ({result.Status}):\n{result.Message}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user