Add live TLS certificate probing and improve restart error handling.
Configure CertificateCheckUrl per container for curl-like TLS checks, classify Sonic permission errors, and extend setup wizard for container management. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using ZA.CoreService.ESBCertificateManager.Models;
|
||||
using ZA.CoreService.ESBCertificateManager.Services;
|
||||
|
||||
namespace ZA.CoreService.ESBCertificateManager.Setup;
|
||||
|
||||
@@ -11,8 +12,10 @@ public sealed class AddContainerForm : Form
|
||||
private readonly ComboBox _cmbSystem;
|
||||
private readonly TextBox _txtName;
|
||||
private readonly TextBox _txtDisplay;
|
||||
private readonly TextBox _txtCheckUrl;
|
||||
private readonly TextBox _txtTimeout;
|
||||
private readonly Button _btnSave;
|
||||
private readonly Button _btnProbeUrl;
|
||||
private bool _running;
|
||||
|
||||
public int? CreatedSonicContainerId { get; private set; }
|
||||
@@ -36,7 +39,7 @@ public sealed class AddContainerForm : Form
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
ShowInTaskbar = false;
|
||||
ClientSize = new Size(540, 470);
|
||||
ClientSize = new Size(540, 560);
|
||||
BackColor = SettingsUi.Background;
|
||||
ForeColor = SettingsUi.Text;
|
||||
Font = new Font("Segoe UI", 10f);
|
||||
@@ -55,7 +58,7 @@ public sealed class AddContainerForm : Form
|
||||
Label subtitle = new()
|
||||
{
|
||||
Text =
|
||||
"Container einer Company und einem Sonic-System zuordnen.",
|
||||
"Container zuordnen und optional TLS-Prüf-URL hinterlegen.",
|
||||
Location = new Point(30, 58),
|
||||
AutoSize = true,
|
||||
ForeColor = SettingsUi.Muted
|
||||
@@ -63,13 +66,14 @@ public sealed class AddContainerForm : Form
|
||||
|
||||
Panel card = SettingsUi.CreateCard();
|
||||
card.Location = new Point(28, 95);
|
||||
card.Size = new Size(484, 290);
|
||||
card.Size = new Size(484, 370);
|
||||
card.Paint += SettingsUi.PaintCardBorder;
|
||||
|
||||
_cmbCompany = SettingsUi.CreateComboBox();
|
||||
_cmbSystem = SettingsUi.CreateComboBox();
|
||||
_txtName = SettingsUi.CreateTextBox();
|
||||
_txtDisplay = SettingsUi.CreateTextBox();
|
||||
_txtCheckUrl = SettingsUi.CreateTextBox();
|
||||
_txtTimeout = SettingsUi.CreateTextBox();
|
||||
_txtTimeout.Text = "180";
|
||||
|
||||
@@ -77,6 +81,7 @@ public sealed class AddContainerForm : Form
|
||||
{
|
||||
_txtName.Text = _existing.ContainerName;
|
||||
_txtDisplay.Text = _existing.ContainerDisplayName ?? string.Empty;
|
||||
_txtCheckUrl.Text = _existing.CertificateCheckUrl ?? string.Empty;
|
||||
_txtTimeout.Text = _existing.RestartTimeoutSeconds.ToString();
|
||||
}
|
||||
|
||||
@@ -85,15 +90,39 @@ public sealed class AddContainerForm : Form
|
||||
AddField(card, "Container-Name", _txtName, 18, 138, 440);
|
||||
AddField(card, "Anzeigename (optional)", _txtDisplay, 18, 198, 280);
|
||||
AddField(card, "Timeout (s)", _txtTimeout, 318, 198, 140);
|
||||
AddField(
|
||||
card,
|
||||
"Zertifikat prüfen (URL / Host:Port)",
|
||||
_txtCheckUrl,
|
||||
18,
|
||||
258,
|
||||
440);
|
||||
|
||||
Label urlHint = new()
|
||||
{
|
||||
Text = "z. B. https://server:8443 oder server:8443",
|
||||
Location = new Point(18, 312),
|
||||
AutoSize = true,
|
||||
ForeColor = SettingsUi.Muted,
|
||||
Font = new Font("Segoe UI", 8.5f)
|
||||
};
|
||||
|
||||
_btnProbeUrl = SettingsUi.CreateGhostButton("URL prüfen");
|
||||
_btnProbeUrl.Location = new Point(318, 318);
|
||||
_btnProbeUrl.Size = new Size(140, 30);
|
||||
_btnProbeUrl.Click += (_, _) => ProbeUrl();
|
||||
|
||||
card.Controls.Add(urlHint);
|
||||
card.Controls.Add(_btnProbeUrl);
|
||||
|
||||
_btnSave = SettingsUi.CreatePrimaryButton(
|
||||
IsEditMode ? "Änderungen speichern" : "Container anlegen");
|
||||
_btnSave.Location = new Point(292, 405);
|
||||
_btnSave.Location = new Point(292, 490);
|
||||
_btnSave.Size = new Size(220, 40);
|
||||
_btnSave.Click += async (_, _) => await SaveAsync();
|
||||
|
||||
Button cancel = SettingsUi.CreateGhostButton("Abbrechen");
|
||||
cancel.Location = new Point(170, 405);
|
||||
cancel.Location = new Point(170, 490);
|
||||
cancel.Size = new Size(110, 40);
|
||||
cancel.Click += (_, _) =>
|
||||
{
|
||||
@@ -110,6 +139,53 @@ public sealed class AddContainerForm : Form
|
||||
Shown += async (_, _) => await LoadLookupsAsync();
|
||||
}
|
||||
|
||||
private void ProbeUrl()
|
||||
{
|
||||
string url = _txtCheckUrl.Text.Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
{
|
||||
MessageBox.Show(
|
||||
this,
|
||||
"Bitte zuerst eine Prüf-URL eintragen.",
|
||||
"URL prüfen",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
TlsEndpointProbeService probe = new();
|
||||
CertificateProbeResult result = probe.Probe(url);
|
||||
|
||||
if (result.Success && result.Certificate is not null)
|
||||
{
|
||||
string expiry = result.Certificate.ValidUntil
|
||||
.ToLocalTime()
|
||||
.ToString("dd.MM.yyyy HH:mm");
|
||||
|
||||
MessageBox.Show(
|
||||
this,
|
||||
$"TLS-Zertifikat erreichbar.\n\n"
|
||||
+ $"Subject: {result.Certificate.Subject}\n"
|
||||
+ $"Aussteller: {result.Certificate.Issuer}\n"
|
||||
+ $"Gültig bis: {expiry}\n"
|
||||
+ $"Status: {(result.Certificate.IsCurrentlyValid ? "gültig" : "abgelaufen")}",
|
||||
"URL prüfen",
|
||||
MessageBoxButtons.OK,
|
||||
result.Certificate.IsCurrentlyValid
|
||||
? MessageBoxIcon.Information
|
||||
: MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBox.Show(
|
||||
this,
|
||||
result.Message,
|
||||
"URL prüfen",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning);
|
||||
}
|
||||
|
||||
private async Task LoadLookupsAsync()
|
||||
{
|
||||
try
|
||||
@@ -211,6 +287,29 @@ public sealed class AddContainerForm : Form
|
||||
return;
|
||||
}
|
||||
|
||||
string? checkUrl = _txtCheckUrl.Text.Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(checkUrl))
|
||||
{
|
||||
checkUrl = null;
|
||||
}
|
||||
else if (!TlsEndpointProbeService.TryParseEndpoint(
|
||||
checkUrl,
|
||||
out _,
|
||||
out _,
|
||||
out _,
|
||||
out string? parseError))
|
||||
{
|
||||
MessageBox.Show(
|
||||
this,
|
||||
parseError ?? "Ungültige Prüf-URL.",
|
||||
"Container",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning);
|
||||
_txtCheckUrl.Focus();
|
||||
return;
|
||||
}
|
||||
|
||||
_running = true;
|
||||
_btnSave.Enabled = false;
|
||||
Cursor = Cursors.WaitCursor;
|
||||
@@ -225,7 +324,8 @@ public sealed class AddContainerForm : Form
|
||||
system.SonicConnectionId,
|
||||
_txtName.Text,
|
||||
_txtDisplay.Text,
|
||||
timeout);
|
||||
timeout,
|
||||
checkUrl);
|
||||
|
||||
CreatedSonicContainerId = _existing.SonicContainerId;
|
||||
}
|
||||
@@ -237,7 +337,8 @@ public sealed class AddContainerForm : Form
|
||||
system.SonicConnectionId,
|
||||
_txtName.Text,
|
||||
_txtDisplay.Text,
|
||||
timeout);
|
||||
timeout,
|
||||
checkUrl);
|
||||
}
|
||||
|
||||
DialogResult = DialogResult.OK;
|
||||
|
||||
@@ -8,6 +8,7 @@ public sealed class AddCredentialProfileForm : Form
|
||||
{
|
||||
private readonly SetupCoordinator _coordinator;
|
||||
private readonly SonicSystemOption _system;
|
||||
private readonly SonicCredentialProfile? _existing;
|
||||
|
||||
private readonly TextBox _txtProfileName;
|
||||
private readonly TextBox _txtUserName;
|
||||
@@ -16,6 +17,7 @@ public sealed class AddCredentialProfileForm : Form
|
||||
private readonly CheckBox _chkDefault;
|
||||
private readonly Button _btnSave;
|
||||
private readonly Button _btnCancel;
|
||||
private readonly Label _lblPasswordHint;
|
||||
|
||||
private bool _operationRunning;
|
||||
|
||||
@@ -25,9 +27,12 @@ public sealed class AddCredentialProfileForm : Form
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool IsEditMode => _existing is not null;
|
||||
|
||||
public AddCredentialProfileForm(
|
||||
SetupCoordinator coordinator,
|
||||
SonicSystemOption system)
|
||||
SonicSystemOption system,
|
||||
SonicCredentialProfile? existing = null)
|
||||
{
|
||||
_coordinator =
|
||||
coordinator
|
||||
@@ -39,13 +44,17 @@ public sealed class AddCredentialProfileForm : Form
|
||||
?? throw new ArgumentNullException(
|
||||
nameof(system));
|
||||
|
||||
Text = "Benutzerprofil hinzufügen";
|
||||
_existing = existing;
|
||||
|
||||
Text = IsEditMode
|
||||
? "Benutzerprofil bearbeiten"
|
||||
: "Benutzerprofil hinzufügen";
|
||||
|
||||
StartPosition =
|
||||
FormStartPosition.CenterParent;
|
||||
|
||||
ClientSize =
|
||||
new Size(560, 525);
|
||||
new Size(560, 545);
|
||||
|
||||
FormBorderStyle =
|
||||
FormBorderStyle.FixedDialog;
|
||||
@@ -65,8 +74,9 @@ public sealed class AddCredentialProfileForm : Form
|
||||
|
||||
Label title = new()
|
||||
{
|
||||
Text =
|
||||
$"Profil für {_system.ConnectionName}",
|
||||
Text = IsEditMode
|
||||
? $"Profil bearbeiten · {_system.ConnectionName}"
|
||||
: $"Profil für {_system.ConnectionName}",
|
||||
|
||||
Location =
|
||||
new Point(28, 22),
|
||||
@@ -112,7 +122,7 @@ public sealed class AddCredentialProfileForm : Form
|
||||
CreateTextBox(185);
|
||||
|
||||
_txtProfileName.Text =
|
||||
"Administrator";
|
||||
_existing?.CredentialName ?? "Administrator";
|
||||
|
||||
Label userLabel =
|
||||
CreateLabel(
|
||||
@@ -123,7 +133,7 @@ public sealed class AddCredentialProfileForm : Form
|
||||
CreateTextBox(250);
|
||||
|
||||
_txtUserName.Text =
|
||||
"Administrator";
|
||||
_existing?.UserName ?? "Administrator";
|
||||
|
||||
Label passwordLabel =
|
||||
CreateLabel(
|
||||
@@ -136,13 +146,25 @@ public sealed class AddCredentialProfileForm : Form
|
||||
_txtPassword.UseSystemPasswordChar =
|
||||
true;
|
||||
|
||||
_lblPasswordHint = new Label
|
||||
{
|
||||
Text = IsEditMode
|
||||
? "Leer lassen = bisheriges Kennwort behalten"
|
||||
: string.Empty,
|
||||
|
||||
Location = new Point(30, 343),
|
||||
AutoSize = true,
|
||||
ForeColor = Color.FromArgb(169, 184, 200),
|
||||
Font = new Font("Segoe UI", 8.5f)
|
||||
};
|
||||
|
||||
Label repeatLabel =
|
||||
CreateLabel(
|
||||
"Kennwort wiederholen",
|
||||
355);
|
||||
365);
|
||||
|
||||
_txtPasswordRepeat =
|
||||
CreateTextBox(380);
|
||||
CreateTextBox(390);
|
||||
|
||||
_txtPasswordRepeat.UseSystemPasswordChar =
|
||||
true;
|
||||
@@ -153,10 +175,10 @@ public sealed class AddCredentialProfileForm : Form
|
||||
"Als Standardprofil verwenden",
|
||||
|
||||
Location =
|
||||
new Point(30, 425),
|
||||
new Point(30, 435),
|
||||
|
||||
AutoSize = true,
|
||||
Checked = true,
|
||||
Checked = _existing?.IsDefault ?? true,
|
||||
|
||||
ForeColor =
|
||||
Color.FromArgb(241, 245, 249)
|
||||
@@ -167,7 +189,7 @@ public sealed class AddCredentialProfileForm : Form
|
||||
Text = "Abbrechen",
|
||||
|
||||
Location =
|
||||
new Point(125, 465),
|
||||
new Point(125, 480),
|
||||
|
||||
Size =
|
||||
new Size(110, 38),
|
||||
@@ -189,11 +211,12 @@ public sealed class AddCredentialProfileForm : Form
|
||||
|
||||
_btnSave = new Button
|
||||
{
|
||||
Text =
|
||||
"Verbindung prüfen und hinzufügen",
|
||||
Text = IsEditMode
|
||||
? "Prüfen und speichern"
|
||||
: "Verbindung prüfen und hinzufügen",
|
||||
|
||||
Location =
|
||||
new Point(245, 465),
|
||||
new Point(245, 480),
|
||||
|
||||
Size =
|
||||
new Size(280, 38),
|
||||
@@ -228,6 +251,7 @@ public sealed class AddCredentialProfileForm : Form
|
||||
Controls.Add(_txtUserName);
|
||||
Controls.Add(passwordLabel);
|
||||
Controls.Add(_txtPassword);
|
||||
Controls.Add(_lblPasswordHint);
|
||||
Controls.Add(repeatLabel);
|
||||
Controls.Add(_txtPasswordRepeat);
|
||||
Controls.Add(_chkDefault);
|
||||
@@ -328,7 +352,7 @@ public sealed class AddCredentialProfileForm : Form
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(password))
|
||||
if (!IsEditMode && string.IsNullOrEmpty(password))
|
||||
{
|
||||
ShowWarning("Kennwort fehlt.");
|
||||
|
||||
@@ -344,7 +368,8 @@ public sealed class AddCredentialProfileForm : Form
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.Equals(
|
||||
if (!string.IsNullOrEmpty(password)
|
||||
&& !string.Equals(
|
||||
password,
|
||||
passwordRepeat,
|
||||
StringComparison.Ordinal))
|
||||
@@ -372,13 +397,27 @@ public sealed class AddCredentialProfileForm : Form
|
||||
|
||||
try
|
||||
{
|
||||
CreatedProfile =
|
||||
await _coordinator.AddCredentialAsync(
|
||||
_system,
|
||||
profileName,
|
||||
userName,
|
||||
password,
|
||||
_chkDefault.Checked);
|
||||
if (IsEditMode && _existing is not null)
|
||||
{
|
||||
CreatedProfile =
|
||||
await _coordinator.UpdateCredentialAsync(
|
||||
_system,
|
||||
_existing,
|
||||
profileName,
|
||||
userName,
|
||||
password,
|
||||
_chkDefault.Checked);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreatedProfile =
|
||||
await _coordinator.TestAndAddCredentialAsync(
|
||||
_system,
|
||||
profileName,
|
||||
userName,
|
||||
password,
|
||||
_chkDefault.Checked);
|
||||
}
|
||||
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
@@ -391,7 +430,11 @@ public sealed class AddCredentialProfileForm : Form
|
||||
{
|
||||
MessageBox.Show(
|
||||
this,
|
||||
"Profil konnte nicht angelegt werden.",
|
||||
string.IsNullOrWhiteSpace(exception.Message)
|
||||
? (IsEditMode
|
||||
? "Profil konnte nicht aktualisiert werden."
|
||||
: "Profil konnte nicht angelegt werden.")
|
||||
: exception.Message,
|
||||
"Benutzerprofil",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Error);
|
||||
@@ -423,7 +466,9 @@ public sealed class AddCredentialProfileForm : Form
|
||||
_btnSave.Text =
|
||||
isRunning
|
||||
? "Verbindung wird geprüft ..."
|
||||
: "Verbindung prüfen und hinzufügen";
|
||||
: IsEditMode
|
||||
? "Prüfen und speichern"
|
||||
: "Verbindung prüfen und hinzufügen";
|
||||
}
|
||||
|
||||
private void ShowWarning(string message)
|
||||
@@ -435,4 +480,4 @@ public sealed class AddCredentialProfileForm : Form
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +207,10 @@ public sealed class AddTargetPathForm : Form
|
||||
if (!_lastProbe.Success)
|
||||
{
|
||||
_lblProbeResult.ForeColor = Color.FromArgb(220, 100, 100);
|
||||
_lblProbeResult.Text = _lastProbe.Message;
|
||||
_lblProbeResult.Text = _lastProbe.AccessDenied
|
||||
? CertificateProbeResult.AccessDeniedShortText
|
||||
+ " – Anmeldung am Freigabe-Pfad erforderlich."
|
||||
: _lastProbe.Message;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -160,6 +160,78 @@ public sealed class SetupCoordinator
|
||||
|
||||
return createdProfile;
|
||||
}
|
||||
|
||||
public async Task<SonicCredentialProfile> UpdateCredentialAsync(
|
||||
SonicSystemOption system,
|
||||
SonicCredentialProfile existing,
|
||||
string credentialName,
|
||||
string userName,
|
||||
string secret,
|
||||
bool isDefault,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(system);
|
||||
ArgumentNullException.ThrowIfNull(existing);
|
||||
|
||||
if (system.SonicConnectionId <= 0
|
||||
|| existing.SonicCredentialId <= 0)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Das ausgewählte Profil oder System ist ungültig.");
|
||||
}
|
||||
|
||||
string passwordToStore =
|
||||
string.IsNullOrEmpty(secret)
|
||||
? existing.Secret
|
||||
: secret;
|
||||
|
||||
CredentialTestResult testResult =
|
||||
await _credentialTester.TestAsync(
|
||||
system,
|
||||
userName,
|
||||
passwordToStore,
|
||||
system.ValidationContainerName,
|
||||
cancellationToken);
|
||||
|
||||
if (!testResult.Success)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Das Benutzerprofil wurde nicht gespeichert."
|
||||
+ Environment.NewLine
|
||||
+ Environment.NewLine
|
||||
+ testResult.Message);
|
||||
}
|
||||
|
||||
await _repository.UpdateCredentialAsync(
|
||||
existing.SonicCredentialId,
|
||||
system.SonicConnectionId,
|
||||
credentialName,
|
||||
userName,
|
||||
passwordToStore,
|
||||
isDefault,
|
||||
cancellationToken);
|
||||
|
||||
IReadOnlyList<SonicCredentialProfile> profiles =
|
||||
await _repository.GetCredentialsAsync(
|
||||
system.SonicConnectionId,
|
||||
cancellationToken);
|
||||
|
||||
SonicCredentialProfile? updated =
|
||||
profiles.FirstOrDefault(
|
||||
profile =>
|
||||
profile.SonicCredentialId
|
||||
== existing.SonicCredentialId);
|
||||
|
||||
if (updated is null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Das Benutzerprofil wurde gespeichert, "
|
||||
+ "konnte anschließend aber nicht geladen werden.");
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
public async Task<SetupCheckResult> CheckAsync(
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -396,6 +468,7 @@ public sealed class SetupCoordinator
|
||||
string containerName,
|
||||
string? containerDisplayName,
|
||||
int restartTimeoutSeconds,
|
||||
string? certificateCheckUrl = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
int id = await _setupRepository.AddSonicContainerAsync(
|
||||
@@ -404,6 +477,7 @@ public sealed class SetupCoordinator
|
||||
containerName,
|
||||
containerDisplayName,
|
||||
restartTimeoutSeconds,
|
||||
certificateCheckUrl,
|
||||
cancellationToken);
|
||||
|
||||
await EnsureExistsAsync(
|
||||
@@ -520,6 +594,7 @@ public sealed class SetupCoordinator
|
||||
string containerName,
|
||||
string? containerDisplayName,
|
||||
int restartTimeoutSeconds,
|
||||
string? certificateCheckUrl = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _setupRepository.UpdateSonicContainerAsync(
|
||||
@@ -529,6 +604,7 @@ public sealed class SetupCoordinator
|
||||
containerName,
|
||||
containerDisplayName,
|
||||
restartTimeoutSeconds,
|
||||
certificateCheckUrl,
|
||||
cancellationToken);
|
||||
|
||||
await EnsureExistsAsync(
|
||||
|
||||
@@ -36,6 +36,7 @@ public sealed class SetupWizardForm : Form
|
||||
private Button _btnSaveSelection = null!;
|
||||
private Button _btnFinish = null!;
|
||||
private Button _btnAddCredential = null!;
|
||||
private Button _btnEditCredential = null!;
|
||||
|
||||
private IReadOnlyList<SonicSystemOption> _systems = [];
|
||||
private IReadOnlyList<SonicCredentialProfile> _profiles = [];
|
||||
@@ -385,11 +386,12 @@ public sealed class SetupWizardForm : Form
|
||||
|
||||
_lvContainers = SettingsUi.CreateListView();
|
||||
_lvContainers.Dock = DockStyle.Fill;
|
||||
_lvContainers.Columns.Add("Company", 80);
|
||||
_lvContainers.Columns.Add("Container", 180);
|
||||
_lvContainers.Columns.Add("Anzeige", 160);
|
||||
_lvContainers.Columns.Add("System", 160);
|
||||
_lvContainers.Columns.Add("Timeout", 90);
|
||||
_lvContainers.Columns.Add("Company", 70);
|
||||
_lvContainers.Columns.Add("Container", 150);
|
||||
_lvContainers.Columns.Add("Anzeige", 120);
|
||||
_lvContainers.Columns.Add("System", 120);
|
||||
_lvContainers.Columns.Add("Prüf-URL", 180);
|
||||
_lvContainers.Columns.Add("Timeout", 80);
|
||||
_lvContainers.DoubleClick += async (_, _) => await EditSelectedContainerAsync();
|
||||
|
||||
FinishPanelLayout(_panelContainers, _lvContainers, toolbar);
|
||||
@@ -484,6 +486,12 @@ public sealed class SetupWizardForm : Form
|
||||
_btnAddCredential.Click += async (_, _) =>
|
||||
await AddCredentialAsync();
|
||||
|
||||
_btnEditCredential = SettingsUi.CreateGhostButton("Profil bearbeiten");
|
||||
_btnEditCredential.Location = new Point(550, 122);
|
||||
_btnEditCredential.Size = new Size(160, 34);
|
||||
_btnEditCredential.Click += async (_, _) =>
|
||||
await EditCredentialAsync();
|
||||
|
||||
_lblSystemDetails = new Label
|
||||
{
|
||||
Location = new Point(24, 180),
|
||||
@@ -502,6 +510,7 @@ public sealed class SetupWizardForm : Form
|
||||
card.Controls.Add(credentialLabel);
|
||||
card.Controls.Add(_cmbCredential);
|
||||
card.Controls.Add(_btnAddCredential);
|
||||
card.Controls.Add(_btnEditCredential);
|
||||
card.Controls.Add(_lblSystemDetails);
|
||||
card.Controls.Add(_btnSaveSelection);
|
||||
|
||||
@@ -625,6 +634,10 @@ public sealed class SetupWizardForm : Form
|
||||
item.SubItems.Add(container.ContainerName);
|
||||
item.SubItems.Add(container.ContainerDisplayName ?? "—");
|
||||
item.SubItems.Add(container.ConnectionName);
|
||||
item.SubItems.Add(
|
||||
string.IsNullOrWhiteSpace(container.CertificateCheckUrl)
|
||||
? "—"
|
||||
: container.CertificateCheckUrl);
|
||||
item.SubItems.Add(container.RestartTimeoutSeconds + " s");
|
||||
item.Tag = container;
|
||||
_lvContainers.Items.Add(item);
|
||||
@@ -722,7 +735,12 @@ public sealed class SetupWizardForm : Form
|
||||
return "Kennwort nötig";
|
||||
}
|
||||
|
||||
return result.Success ? "fehlt" : "n/a";
|
||||
if (result.AccessDenied)
|
||||
{
|
||||
return CertificateProbeResult.AccessDeniedShortText;
|
||||
}
|
||||
|
||||
return result.Success ? "fehlt" : "nicht erreichbar";
|
||||
}
|
||||
|
||||
private static string? PromptCertificatePassword(IWin32Window owner)
|
||||
@@ -1228,19 +1246,9 @@ public sealed class SetupWizardForm : Form
|
||||
}
|
||||
|
||||
await SystemChangedAsync();
|
||||
SelectCredential(dialog.CreatedProfile.SonicCredentialId);
|
||||
|
||||
for (int index = 0; index < _cmbCredential.Items.Count; index++)
|
||||
{
|
||||
if (_cmbCredential.Items[index] is SonicCredentialProfile profile
|
||||
&& profile.SonicCredentialId
|
||||
== dialog.CreatedProfile.SonicCredentialId)
|
||||
{
|
||||
_cmbCredential.SelectedIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MessageBox.Show(
|
||||
MessageBox.Show(
|
||||
this,
|
||||
"Profil geladen.",
|
||||
"Benutzerprofil",
|
||||
@@ -1248,6 +1256,53 @@ public sealed class SetupWizardForm : Form
|
||||
MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
private async Task EditCredentialAsync()
|
||||
{
|
||||
if (_cmbSystem.SelectedItem is not SonicSystemOption system)
|
||||
{
|
||||
ShowWarning("Bitte System wählen.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_cmbCredential.SelectedItem is not SonicCredentialProfile profile)
|
||||
{
|
||||
ShowWarning("Bitte Profil wählen.");
|
||||
return;
|
||||
}
|
||||
|
||||
using AddCredentialProfileForm dialog =
|
||||
new(_coordinator, system, profile);
|
||||
|
||||
if (dialog.ShowDialog(this) != DialogResult.OK
|
||||
|| dialog.CreatedProfile is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await SystemChangedAsync();
|
||||
SelectCredential(dialog.CreatedProfile.SonicCredentialId);
|
||||
|
||||
MessageBox.Show(
|
||||
this,
|
||||
"Profil aktualisiert.",
|
||||
"Benutzerprofil",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
private void SelectCredential(int sonicCredentialId)
|
||||
{
|
||||
for (int index = 0; index < _cmbCredential.Items.Count; index++)
|
||||
{
|
||||
if (_cmbCredential.Items[index] is SonicCredentialProfile profile
|
||||
&& profile.SonicCredentialId == sonicCredentialId)
|
||||
{
|
||||
_cmbCredential.SelectedIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SystemChangedAsync()
|
||||
{
|
||||
if (_cmbSystem.SelectedItem is not SonicSystemOption system)
|
||||
@@ -1275,9 +1330,12 @@ public sealed class SetupWizardForm : Form
|
||||
Environment.NewLine
|
||||
+ "Noch kein Benutzerprofil — bitte hinzufügen.";
|
||||
_btnSaveSelection.Enabled = false;
|
||||
_btnEditCredential.Enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_btnEditCredential.Enabled = true;
|
||||
|
||||
_btnSaveSelection.Enabled = true;
|
||||
|
||||
LocalSetupSelection? selection = _coordinator.LoadSelection();
|
||||
|
||||
Reference in New Issue
Block a user