Files
123123/ZA.CoreService.ESBCertificateManager/Setup/SetupWizardForm.cs
T

1107 lines
32 KiB
C#

using ZA.CoreService.ESBCertificateManager.Models;
namespace ZA.CoreService.ESBCertificateManager.Setup;
public sealed class SetupWizardForm : Form
{
private readonly SetupCoordinator _coordinator;
private readonly bool _isSettingsMode;
private Panel _sidebar = null!;
private Panel _contentHost = null!;
private Panel _panelStatus = null!;
private Panel _panelSystems = null!;
private Panel _panelContainers = null!;
private Panel _panelPaths = null!;
private Panel _panelProfiles = null!;
private readonly List<Button> _navButtons = [];
private Button _activeNav = null!;
private Label _lblRuntime = null!;
private Label _lblCertificate = null!;
private Label _lblDatabase = null!;
private Label _lblSelection = null!;
private Label _lblEnvironmentBadge = null!;
private ListView _lvSystems = null!;
private ListView _lvContainers = null!;
private ListView _lvPaths = null!;
private ComboBox _cmbSystem = null!;
private ComboBox _cmbCredential = null!;
private Label _lblSystemDetails = null!;
private Button _btnImportCertificate = null!;
private Button _btnSaveSelection = null!;
private Button _btnFinish = null!;
private Button _btnAddCredential = null!;
private IReadOnlyList<SonicSystemOption> _systems = [];
private IReadOnlyList<SonicCredentialProfile> _profiles = [];
private bool _running;
public SetupWizardForm(
SetupCoordinator coordinator,
bool isSettingsMode = false)
{
_coordinator = coordinator;
_isSettingsMode = isSettingsMode;
Text = "Einstellungen";
StartPosition = FormStartPosition.CenterScreen;
Size = new Size(1180, 760);
MinimumSize = new Size(1080, 700);
BackColor = SettingsUi.Background;
ForeColor = SettingsUi.Text;
Font = new Font("Segoe UI", 10f);
DoubleBuffered = true;
BuildShell();
BuildStatusPanel();
BuildSystemsPanel();
BuildContainersPanel();
BuildPathsPanel();
BuildProfilesPanel();
ShowPanel(_panelStatus, _navButtons[0]);
Shown += async (_, _) => await RefreshAllAsync();
}
private void BuildShell()
{
_sidebar = new Panel
{
Dock = DockStyle.Left,
Width = 230,
BackColor = SettingsUi.Sidebar
};
Label brand = new()
{
Text = "ESB Certificate",
Location = new Point(22, 28),
AutoSize = true,
ForeColor = SettingsUi.Gold,
Font = new Font("Segoe UI Semibold", 11f, FontStyle.Bold)
};
Label brandSub = new()
{
Text = "Einstellungen",
Location = new Point(22, 52),
AutoSize = true,
ForeColor = SettingsUi.Text,
Font = new Font("Segoe UI Semibold", 20f, FontStyle.Bold)
};
_lblEnvironmentBadge = new Label
{
Text = _coordinator.Settings.EnvironmentCode,
Location = new Point(22, 95),
AutoSize = true,
Padding = new Padding(10, 4, 10, 4),
BackColor = Color.FromArgb(40, 208, 171, 57),
ForeColor = SettingsUi.Gold,
Font = new Font("Segoe UI Semibold", 9f, FontStyle.Bold)
};
_sidebar.Controls.Add(brand);
_sidebar.Controls.Add(brandSub);
_sidebar.Controls.Add(_lblEnvironmentBadge);
string[] navItems =
[
"Prüfung",
"Systeme",
"Container",
"Pfade",
"Profile"
];
int y = 150;
foreach (string item in navItems)
{
Button nav = CreateNavButton(item);
nav.Location = new Point(14, y);
y += 48;
_navButtons.Add(nav);
_sidebar.Controls.Add(nav);
}
_navButtons[0].Click += (_, _) =>
ShowPanel(_panelStatus, _navButtons[0]);
_navButtons[1].Click += async (_, _) =>
{
ShowPanel(_panelSystems, _navButtons[1]);
await LoadSystemsListAsync();
};
_navButtons[2].Click += async (_, _) =>
{
ShowPanel(_panelContainers, _navButtons[2]);
await LoadContainersListAsync();
};
_navButtons[3].Click += async (_, _) =>
{
ShowPanel(_panelPaths, _navButtons[3]);
await LoadPathsListAsync();
};
_navButtons[4].Click += async (_, _) =>
{
ShowPanel(_panelProfiles, _navButtons[4]);
await LoadSystemsAsync();
};
Panel footer = new()
{
Dock = DockStyle.Bottom,
Height = 72,
BackColor = SettingsUi.Background
};
Button closeButton = SettingsUi.CreateGhostButton(
_isSettingsMode ? "Schließen" : "Abbrechen");
closeButton.Location = new Point(Width - 340, 16);
closeButton.Size = new Size(120, 40);
closeButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
closeButton.Click += async (_, _) => await CloseAsync();
_btnFinish = SettingsUi.CreatePrimaryButton(
_isSettingsMode ? "Übernehmen" : "Fertig");
_btnFinish.Location = new Point(Width - 200, 16);
_btnFinish.Size = new Size(160, 40);
_btnFinish.Anchor = AnchorStyles.Top | AnchorStyles.Right;
_btnFinish.Enabled = false;
_btnFinish.Click += (_, _) =>
{
DialogResult = DialogResult.OK;
Close();
};
Button refresh = SettingsUi.CreateGhostButton("Aktualisieren");
refresh.Location = new Point(250, 16);
refresh.Size = new Size(130, 40);
refresh.Click += async (_, _) => await RefreshAllAsync();
footer.Controls.Add(refresh);
footer.Controls.Add(closeButton);
footer.Controls.Add(_btnFinish);
_contentHost = new Panel
{
Dock = DockStyle.Fill,
BackColor = SettingsUi.Background,
Padding = new Padding(28, 24, 28, 12)
};
Controls.Add(_contentHost);
Controls.Add(footer);
Controls.Add(_sidebar);
Resize += (_, _) =>
{
closeButton.Left = footer.Width - 340;
_btnFinish.Left = footer.Width - 200;
};
}
private Button CreateNavButton(string text)
{
Button button = new()
{
Text = " " + text,
Size = new Size(200, 42),
FlatStyle = FlatStyle.Flat,
TextAlign = ContentAlignment.MiddleLeft,
BackColor = SettingsUi.Sidebar,
ForeColor = SettingsUi.Muted,
Font = new Font("Segoe UI Semibold", 10.5f, FontStyle.Bold),
Cursor = Cursors.Hand
};
button.FlatAppearance.BorderSize = 0;
button.FlatAppearance.MouseOverBackColor = SettingsUi.CardHover;
return button;
}
private void ShowPanel(Panel panel, Button nav)
{
foreach (Control control in _contentHost.Controls)
{
control.Visible = false;
}
panel.Visible = true;
panel.BringToFront();
foreach (Button button in _navButtons)
{
button.BackColor = SettingsUi.Sidebar;
button.ForeColor = SettingsUi.Muted;
}
nav.BackColor = SettingsUi.Card;
nav.ForeColor = SettingsUi.Gold;
_activeNav = nav;
}
private Panel CreateContentPanel(string title, string subtitle)
{
Panel panel = new()
{
Dock = DockStyle.Fill,
BackColor = SettingsUi.Background,
Visible = false,
Padding = new Padding(4)
};
// Reihenfolge für Dock: Fill zuerst, dann Toolbar (Top), Header zuletzt (Top außen).
Panel header = CreateHeaderPanel(title, subtitle);
panel.Tag = header;
_contentHost.Controls.Add(panel);
return panel;
}
private static Panel CreateHeaderPanel(string title, string subtitle)
{
Panel header = new()
{
Dock = DockStyle.Top,
Height = 72,
BackColor = SettingsUi.Background
};
Label heading = new()
{
Text = title,
AutoSize = true,
Location = new Point(4, 2),
ForeColor = SettingsUi.Text,
Font = new Font("Segoe UI Semibold", 22f, FontStyle.Bold)
};
Label sub = new()
{
Text = subtitle,
AutoSize = true,
Location = new Point(8, 40),
ForeColor = SettingsUi.Muted,
Font = new Font("Segoe UI", 10f)
};
header.Controls.Add(heading);
header.Controls.Add(sub);
return header;
}
private static void FinishPanelLayout(Panel panel, Control list, Panel toolbar)
{
Panel header = (Panel)panel.Tag!;
// 1) Fill 2) Toolbar Top 3) Header Top (außen)
panel.Controls.Add(list);
panel.Controls.Add(toolbar);
panel.Controls.Add(header);
}
private void BuildStatusPanel()
{
_panelStatus = CreateContentPanel(
"Systemprüfung",
"Runtime, Zertifikat, Datenbank und aktuelle Auswahl.");
Panel card = SettingsUi.CreateCard();
card.Dock = DockStyle.Fill;
card.Padding = new Padding(12);
card.Paint += SettingsUi.PaintCardBorder;
_lblRuntime = CreateStatusLabel(20, 24);
_lblCertificate = CreateStatusLabel(20, 78);
_lblDatabase = CreateStatusLabel(20, 132);
_lblSelection = CreateStatusLabel(20, 186);
_btnImportCertificate = SettingsUi.CreatePrimaryButton("PFX importieren");
_btnImportCertificate.Location = new Point(640, 72);
_btnImportCertificate.Size = new Size(180, 38);
_btnImportCertificate.Anchor = AnchorStyles.Top | AnchorStyles.Right;
_btnImportCertificate.Click += async (_, _) =>
await ImportCertificateAsync();
Label tip = new()
{
Text =
"Tipp: Unter „Systeme“, „Container“ und „Pfade“ kannst du " +
"die Katalogdaten für die aktuelle Umgebung pflegen.",
Location = new Point(20, 235),
Size = new Size(780, 28),
ForeColor = SettingsUi.Muted
};
card.Controls.Add(_lblRuntime);
card.Controls.Add(_lblCertificate);
card.Controls.Add(_lblDatabase);
card.Controls.Add(_lblSelection);
card.Controls.Add(_btnImportCertificate);
card.Controls.Add(tip);
Panel header = (Panel)_panelStatus.Tag!;
_panelStatus.Controls.Add(card);
_panelStatus.Controls.Add(header);
}
private void BuildSystemsPanel()
{
_panelSystems = CreateContentPanel(
"Sonic-Systeme",
"Management-Verbindungen der aktuellen Umgebung.");
Panel toolbar = CreateToolbar(
"+ System hinzufügen",
async () => await AddSystemAsync());
_lvSystems = SettingsUi.CreateListView();
_lvSystems.Dock = DockStyle.Fill;
_lvSystems.Columns.Add("Name", 160);
_lvSystems.Columns.Add("Host", 180);
_lvSystems.Columns.Add("Port", 70);
_lvSystems.Columns.Add("Domain", 180);
_lvSystems.Columns.Add("Protokoll", 80);
_lvSystems.Columns.Add("URL", 180);
FinishPanelLayout(_panelSystems, _lvSystems, toolbar);
}
private void BuildContainersPanel()
{
_panelContainers = CreateContentPanel(
"Container",
"Sonic-Container je Company und System.");
Panel toolbar = CreateToolbar(
"+ Container hinzufügen",
async () => await AddContainerAsync());
_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);
FinishPanelLayout(_panelContainers, _lvContainers, toolbar);
}
private void BuildPathsPanel()
{
_panelPaths = CreateContentPanel(
"Zertifikat-Pfade",
"Zielverzeichnisse und Dateinamen für Deployments.");
Panel toolbar = CreateToolbar(
"+ Pfad hinzufügen",
async () => await AddPathAsync());
_lvPaths = SettingsUi.CreateListView();
_lvPaths.Dock = DockStyle.Fill;
_lvPaths.Columns.Add("Company", 70);
_lvPaths.Columns.Add("Container", 140);
_lvPaths.Columns.Add("Verzeichnis", 280);
_lvPaths.Columns.Add("Datei", 120);
_lvPaths.Columns.Add("Backup", 80);
_lvPaths.Columns.Add("System", 140);
FinishPanelLayout(_panelPaths, _lvPaths, toolbar);
}
private Panel CreateToolbar(
string addButtonText,
Func<Task> onAdd)
{
Panel toolbar = new()
{
Dock = DockStyle.Top,
Height = 56,
BackColor = SettingsUi.Background,
Padding = new Padding(8, 8, 8, 8)
};
Button add = SettingsUi.CreatePrimaryButton(addButtonText);
add.Dock = DockStyle.Left;
add.Width = 230;
add.Click += async (_, _) => await onAdd();
toolbar.Controls.Add(add);
return toolbar;
}
private void BuildProfilesPanel()
{
_panelProfiles = CreateContentPanel(
"Profil & Auswahl",
"Aktives Sonic-System und Benutzerprofil für Neustarts.");
Panel card = SettingsUi.CreateCard();
card.Dock = DockStyle.Fill;
card.Padding = new Padding(12);
card.Paint += SettingsUi.PaintCardBorder;
Label systemLabel = SettingsUi.CreateFieldLabel("Sonic-System");
systemLabel.Location = new Point(24, 24);
_cmbSystem = SettingsUi.CreateComboBox();
_cmbSystem.Location = new Point(24, 48);
_cmbSystem.Width = 340;
_cmbSystem.SelectedIndexChanged += async (_, _) =>
await SystemChangedAsync();
Label credentialLabel = SettingsUi.CreateFieldLabel("Benutzerprofil");
credentialLabel.Location = new Point(24, 100);
_cmbCredential = SettingsUi.CreateComboBox();
_cmbCredential.Location = new Point(24, 124);
_cmbCredential.Width = 340;
_btnAddCredential = SettingsUi.CreateGhostButton("Profil hinzufügen");
_btnAddCredential.Location = new Point(380, 122);
_btnAddCredential.Size = new Size(160, 34);
_btnAddCredential.Click += async (_, _) =>
await AddCredentialAsync();
_lblSystemDetails = new Label
{
Location = new Point(24, 180),
Size = new Size(780, 50),
ForeColor = SettingsUi.Muted
};
_btnSaveSelection = SettingsUi.CreatePrimaryButton("Auswahl übernehmen");
_btnSaveSelection.Location = new Point(600, 220);
_btnSaveSelection.Size = new Size(220, 40);
_btnSaveSelection.Click += async (_, _) =>
await SaveSelectionAsync();
card.Controls.Add(systemLabel);
card.Controls.Add(_cmbSystem);
card.Controls.Add(credentialLabel);
card.Controls.Add(_cmbCredential);
card.Controls.Add(_btnAddCredential);
card.Controls.Add(_lblSystemDetails);
card.Controls.Add(_btnSaveSelection);
Panel header = (Panel)_panelProfiles.Tag!;
_panelProfiles.Controls.Add(card);
_panelProfiles.Controls.Add(header);
}
private static Label CreateStatusLabel(int x, int y)
{
return new Label
{
Location = new Point(x, y),
Size = new Size(600, 40),
ForeColor = SettingsUi.Muted,
Font = new Font("Segoe UI", 10.5f)
};
}
private async Task RefreshAllAsync()
{
if (_running)
{
return;
}
SetRunning(true);
try
{
SetupCheckResult result =
await _coordinator.CheckAsync();
SetStatus(
_lblRuntime,
"Runtime",
result.RuntimeReady,
result.RuntimeMessage);
SetStatus(
_lblCertificate,
"Always Encrypted",
result.CertificateReady,
result.CertificateMessage);
SetStatus(
_lblDatabase,
"Datenbank",
result.DatabaseReady,
result.DatabaseMessage);
SetStatus(
_lblSelection,
"Auswahl",
result.CredentialsReady,
result.CredentialsMessage);
_btnImportCertificate.Visible = !result.CertificateReady;
_btnFinish.Enabled = result.IsReady;
if (result.CertificateReady)
{
await LoadSystemsAsync();
await LoadSystemsListAsync();
await LoadContainersListAsync();
await LoadPathsListAsync();
}
}
catch (Exception ex)
{
MessageBox.Show(
this,
ex.Message,
"Einstellungen",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
finally
{
SetRunning(false);
}
}
private async Task LoadSystemsListAsync()
{
try
{
_systems = await _coordinator.LoadSystemsAsync();
_lvSystems.Items.Clear();
foreach (SonicSystemOption system in _systems)
{
ListViewItem item = new(system.ConnectionName);
item.SubItems.Add(system.ManagementHost);
item.SubItems.Add(system.ManagementPort.ToString());
item.SubItems.Add(system.DomainName);
item.SubItems.Add(system.ConnectionProtocol);
item.SubItems.Add(system.ConnectionUrl);
item.Tag = system;
_lvSystems.Items.Add(item);
}
}
catch (Exception ex)
{
ShowError(ex.Message);
}
}
private async Task LoadContainersListAsync()
{
try
{
IReadOnlyList<ContainerOption> containers =
await _coordinator.LoadContainersAsync();
_lvContainers.Items.Clear();
foreach (ContainerOption container in containers)
{
ListViewItem item = new(container.CompanyCode);
item.SubItems.Add(container.ContainerName);
item.SubItems.Add(container.ContainerDisplayName ?? "—");
item.SubItems.Add(container.ConnectionName);
item.SubItems.Add(container.RestartTimeoutSeconds + " s");
item.Tag = container;
_lvContainers.Items.Add(item);
}
}
catch (Exception ex)
{
ShowError(ex.Message);
}
}
private async Task LoadPathsListAsync()
{
try
{
IReadOnlyList<CertificateTargetOption> targets =
await _coordinator.LoadCertificateTargetsAsync();
_lvPaths.Items.Clear();
foreach (CertificateTargetOption target in targets)
{
ListViewItem item = new(target.CompanyCode);
item.SubItems.Add(target.ContainerName);
item.SubItems.Add(target.TargetDirectory);
item.SubItems.Add(target.TargetFileName);
item.SubItems.Add(
target.BackupEnabled
? target.BackupDirectoryName
: "aus");
item.SubItems.Add(target.ConnectionName);
item.Tag = target;
_lvPaths.Items.Add(item);
}
}
catch (Exception ex)
{
ShowError(ex.Message);
}
}
private async Task AddSystemAsync()
{
using AddSonicSystemForm dialog = new(_coordinator);
if (dialog.ShowDialog(this) != DialogResult.OK
|| dialog.CreatedSonicConnectionId is not int createdId)
{
return;
}
await LoadSystemsListAsync();
await LoadSystemsAsync();
await RefreshAllAsync();
bool visible = _lvSystems.Items
.Cast<ListViewItem>()
.Any(item =>
item.Tag is SonicSystemOption system
&& system.SonicConnectionId == createdId);
if (!visible)
{
ShowError(
$"Anlage-Prüfung fehlgeschlagen: System-Id {createdId} " +
"ist nach dem Speichern nicht in der Liste.");
return;
}
SelectListItem(
_lvSystems,
item =>
item.Tag is SonicSystemOption system
&& system.SonicConnectionId == createdId);
MessageBox.Show(
this,
$"System wurde gespeichert und geprüft (Id {createdId}).",
"Prüfung OK",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
private async Task AddContainerAsync()
{
int? preferred = null;
if (_lvSystems.SelectedItems.Count > 0
&& _lvSystems.SelectedItems[0].Tag is SonicSystemOption system)
{
preferred = system.SonicConnectionId;
}
using AddContainerForm dialog = new(_coordinator, preferred);
if (dialog.ShowDialog(this) != DialogResult.OK
|| dialog.CreatedSonicContainerId is not int createdId)
{
return;
}
await LoadContainersListAsync();
await LoadSystemsListAsync();
await RefreshAllAsync();
bool visible = _lvContainers.Items
.Cast<ListViewItem>()
.Any(item =>
item.Tag is ContainerOption container
&& container.SonicContainerId == createdId);
if (!visible)
{
ShowError(
$"Anlage-Prüfung fehlgeschlagen: Container-Id {createdId} " +
"ist nach dem Speichern nicht in der Liste.");
return;
}
SelectListItem(
_lvContainers,
item =>
item.Tag is ContainerOption container
&& container.SonicContainerId == createdId);
MessageBox.Show(
this,
$"Container wurde gespeichert und geprüft (Id {createdId}).",
"Prüfung OK",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
private async Task AddPathAsync()
{
int? preferred = null;
if (_lvContainers.SelectedItems.Count > 0
&& _lvContainers.SelectedItems[0].Tag is ContainerOption container)
{
preferred = container.SonicContainerId;
}
using AddTargetPathForm dialog = new(_coordinator, preferred);
if (dialog.ShowDialog(this) != DialogResult.OK
|| dialog.CreatedCertificateTargetId is not int createdId)
{
return;
}
await LoadPathsListAsync();
await RefreshAllAsync();
bool visible = _lvPaths.Items
.Cast<ListViewItem>()
.Any(item =>
item.Tag is CertificateTargetOption target
&& target.CertificateTargetId == createdId);
if (!visible)
{
ShowError(
$"Anlage-Prüfung fehlgeschlagen: Pfad-Id {createdId} " +
"ist nach dem Speichern nicht in der Liste.");
return;
}
SelectListItem(
_lvPaths,
item =>
item.Tag is CertificateTargetOption target
&& target.CertificateTargetId == createdId);
MessageBox.Show(
this,
$"Zertifikat-Pfad wurde gespeichert und geprüft (Id {createdId}).",
"Prüfung OK",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
private static void SelectListItem(
ListView listView,
Func<ListViewItem, bool> match)
{
foreach (ListViewItem item in listView.Items)
{
if (!match(item))
{
continue;
}
item.Selected = true;
item.EnsureVisible();
listView.Focus();
return;
}
}
private async Task LoadSystemsAsync()
{
LocalSetupSelection? previousSelection =
_coordinator.LoadSelection();
_systems = await _coordinator.LoadSystemsAsync();
_cmbSystem.Items.Clear();
_cmbCredential.Items.Clear();
foreach (SonicSystemOption system in _systems)
{
_cmbSystem.Items.Add(system);
}
if (_systems.Count == 0)
{
_lblSystemDetails.Text =
"Kein System vorhanden. Lege zuerst unter „Systeme“ eines an.";
return;
}
int selectedIndex = 0;
if (previousSelection is not null)
{
for (int index = 0; index < _systems.Count; index++)
{
if (_systems[index].SonicConnectionId
== previousSelection.SonicConnectionId)
{
selectedIndex = index;
break;
}
}
}
_cmbSystem.SelectedIndex = selectedIndex;
}
private async Task AddCredentialAsync()
{
if (_cmbSystem.SelectedItem is not SonicSystemOption system)
{
ShowWarning("Bitte zuerst ein Sonic-System auswählen.");
return;
}
using AddCredentialProfileForm dialog =
new(_coordinator, system);
if (dialog.ShowDialog(this) != DialogResult.OK
|| dialog.CreatedProfile is null)
{
return;
}
await SystemChangedAsync();
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(
this,
"Profil geladen. Jetzt „Auswahl übernehmen“ klicken.",
"Benutzerprofil",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
private async Task SystemChangedAsync()
{
if (_cmbSystem.SelectedItem is not SonicSystemOption system)
{
return;
}
_lblSystemDetails.Text =
$"Domain: {system.DomainName} · {system.ConnectionUrl}";
_profiles =
await _coordinator.LoadCredentialsAsync(
system.SonicConnectionId);
_cmbCredential.Items.Clear();
foreach (SonicCredentialProfile profile in _profiles)
{
_cmbCredential.Items.Add(profile);
}
if (_profiles.Count == 0)
{
_lblSystemDetails.Text +=
Environment.NewLine
+ "Noch kein Benutzerprofil — bitte hinzufügen.";
_btnSaveSelection.Enabled = false;
return;
}
_btnSaveSelection.Enabled = true;
LocalSetupSelection? selection = _coordinator.LoadSelection();
int selectedIndex = 0;
if (selection is not null)
{
for (int index = 0; index < _profiles.Count; index++)
{
if (_profiles[index].SonicCredentialId
== selection.SonicCredentialId)
{
selectedIndex = index;
break;
}
}
}
else
{
selectedIndex = _profiles
.Select((profile, index) => new { profile, index })
.Where(item => item.profile.IsDefault)
.Select(item => item.index)
.FirstOrDefault();
}
_cmbCredential.SelectedIndex = selectedIndex;
}
private async Task SaveSelectionAsync()
{
if (_cmbSystem.SelectedItem is not SonicSystemOption system)
{
ShowWarning("Bitte ein Sonic-System auswählen.");
return;
}
if (_cmbCredential.SelectedItem is not SonicCredentialProfile profile)
{
ShowWarning("Bitte ein Benutzerprofil auswählen.");
return;
}
_coordinator.SaveSelection(system, profile);
MessageBox.Show(
this,
"Auswahl gespeichert.",
"Einstellungen",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
await RefreshAllAsync();
}
private async Task ImportCertificateAsync()
{
using OpenFileDialog dialog = new()
{
Title = "Always-Encrypted-PFX auswählen",
Filter = "PFX-Zertifikat (*.pfx)|*.pfx",
CheckFileExists = true
};
if (dialog.ShowDialog(this) != DialogResult.OK)
{
return;
}
string? password = PromptForPassword();
if (password is null)
{
return;
}
try
{
_coordinator.CertificateService.ImportPfx(
dialog.FileName,
password);
await RefreshAllAsync();
}
finally
{
password = string.Empty;
}
}
private async Task CloseAsync()
{
if (_isSettingsMode)
{
SetupCheckResult check = await _coordinator.CheckAsync();
DialogResult = check.IsReady
? DialogResult.OK
: DialogResult.Cancel;
}
else
{
DialogResult = DialogResult.Cancel;
}
Close();
}
private static string? PromptForPassword()
{
using Form form = new()
{
Text = "PFX-Kennwort",
Size = new Size(390, 170),
StartPosition = FormStartPosition.CenterParent,
FormBorderStyle = FormBorderStyle.FixedDialog,
BackColor = SettingsUi.Background,
ForeColor = SettingsUi.Text
};
TextBox textBox = SettingsUi.CreateTextBox();
textBox.Location = new Point(20, 40);
textBox.Width = 330;
textBox.UseSystemPasswordChar = true;
Button ok = SettingsUi.CreatePrimaryButton("OK");
ok.Location = new Point(160, 85);
ok.Size = new Size(90, 34);
ok.DialogResult = DialogResult.OK;
Button cancel = SettingsUi.CreateGhostButton("Abbrechen");
cancel.Location = new Point(260, 85);
cancel.Size = new Size(90, 34);
cancel.DialogResult = DialogResult.Cancel;
form.Controls.Add(textBox);
form.Controls.Add(ok);
form.Controls.Add(cancel);
form.AcceptButton = ok;
form.CancelButton = cancel;
return form.ShowDialog() == DialogResult.OK
? textBox.Text
: null;
}
private void SetRunning(bool running)
{
_running = running;
UseWaitCursor = running;
}
private void ShowWarning(string message)
{
MessageBox.Show(
this,
message,
"Einstellungen",
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
}
private void ShowError(string message)
{
MessageBox.Show(
this,
message,
"Einstellungen",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
private static void SetStatus(
Label label,
string category,
bool success,
string message)
{
label.Text =
$"{(success ? "" : "")} {category}\n {message}";
label.ForeColor = success
? SettingsUi.Green
: SettingsUi.Red;
}
}