802 lines
20 KiB
C#
802 lines
20 KiB
C#
using ZA.CoreService.ESBCertificateManager.Models;
|
|
|
|
namespace ZA.CoreService.ESBCertificateManager.Setup;
|
|
|
|
public sealed class SetupWizardForm : Form
|
|
{
|
|
private readonly SetupCoordinator _coordinator;
|
|
|
|
private readonly Color _backgroundColor =
|
|
Color.FromArgb(10, 18, 34);
|
|
|
|
private readonly Color _cardColor =
|
|
Color.FromArgb(16, 38, 65);
|
|
|
|
private readonly Color _textColor =
|
|
Color.FromArgb(241, 245, 249);
|
|
|
|
private readonly Color _mutedTextColor =
|
|
Color.FromArgb(169, 184, 200);
|
|
|
|
private readonly Color _goldColor =
|
|
Color.FromArgb(208, 171, 57);
|
|
|
|
private readonly Color _greenColor =
|
|
Color.FromArgb(60, 203, 127);
|
|
|
|
private readonly Color _redColor =
|
|
Color.FromArgb(239, 106, 106);
|
|
|
|
private Label _lblRuntime = null!;
|
|
private Label _lblCertificate = null!;
|
|
private Label _lblDatabase = null!;
|
|
private Label _lblSelection = null!;
|
|
private Label _lblEnvironment = null!;
|
|
private Label _lblSystemDetails = null!;
|
|
|
|
private ComboBox _cmbSystem = null!;
|
|
private ComboBox _cmbCredential = null!;
|
|
|
|
private Button _btnImportCertificate = null!;
|
|
private Button _btnRefresh = 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)
|
|
{
|
|
_coordinator = coordinator;
|
|
|
|
BuildInterface();
|
|
|
|
Shown += async (_, _) =>
|
|
await InitializeAsync();
|
|
}
|
|
|
|
private void BuildInterface()
|
|
{
|
|
Text = "ESB Certificate Manager einrichten";
|
|
StartPosition = FormStartPosition.CenterScreen;
|
|
Size = new Size(950, 690);
|
|
MinimumSize = new Size(900, 650);
|
|
MaximizeBox = false;
|
|
|
|
BackColor = _backgroundColor;
|
|
ForeColor = _textColor;
|
|
Font = new Font("Segoe UI", 10);
|
|
|
|
Label title = new()
|
|
{
|
|
Text = "Ersteinrichtung",
|
|
AutoSize = true,
|
|
Location = new Point(38, 25),
|
|
ForeColor = _textColor,
|
|
Font = new Font(
|
|
"Segoe UI",
|
|
24,
|
|
FontStyle.Bold)
|
|
};
|
|
|
|
Label subtitle = new()
|
|
{
|
|
Text =
|
|
"Runtime, Datenbank, Zertifikat und Systemauswahl prüfen.",
|
|
AutoSize = true,
|
|
Location = new Point(42, 70),
|
|
ForeColor = _mutedTextColor
|
|
};
|
|
|
|
Panel checkCard = CreateCard(
|
|
new Point(38, 105),
|
|
new Size(870, 225));
|
|
|
|
Label checkTitle = CreateTitle(
|
|
"Systemprüfung",
|
|
new Point(20, 16));
|
|
|
|
_lblRuntime = CreateStatus(
|
|
new Point(20, 55));
|
|
|
|
_lblCertificate = CreateStatus(
|
|
new Point(20, 95));
|
|
|
|
_lblDatabase = CreateStatus(
|
|
new Point(20, 135));
|
|
|
|
_lblSelection = CreateStatus(
|
|
new Point(20, 175));
|
|
|
|
_btnImportCertificate = CreateButton(
|
|
"PFX importieren");
|
|
|
|
_btnImportCertificate.Location =
|
|
new Point(680, 90);
|
|
|
|
_btnImportCertificate.Size =
|
|
new Size(160, 38);
|
|
|
|
_btnImportCertificate.Click +=
|
|
async (_, _) =>
|
|
await ImportCertificateAsync();
|
|
_cmbCredential = new ComboBox
|
|
{
|
|
Location = new Point(185, 133),
|
|
Size = new Size(300, 30),
|
|
DropDownStyle =
|
|
ComboBoxStyle.DropDownList
|
|
};
|
|
|
|
checkCard.Controls.Add(checkTitle);
|
|
checkCard.Controls.Add(_lblRuntime);
|
|
checkCard.Controls.Add(_lblCertificate);
|
|
checkCard.Controls.Add(_lblDatabase);
|
|
checkCard.Controls.Add(_lblSelection);
|
|
checkCard.Controls.Add(_btnImportCertificate);
|
|
|
|
Panel selectionCard = CreateCard(
|
|
new Point(38, 350),
|
|
new Size(870, 205));
|
|
|
|
Label selectionTitle = CreateTitle(
|
|
"System auswählen",
|
|
new Point(20, 16));
|
|
|
|
_lblEnvironment = new Label
|
|
{
|
|
Text =
|
|
$"Umgebung: {_coordinator.Settings.EnvironmentCode}",
|
|
AutoSize = true,
|
|
Location = new Point(22, 55),
|
|
ForeColor = _goldColor,
|
|
Font = new Font(
|
|
"Segoe UI",
|
|
10,
|
|
FontStyle.Bold)
|
|
};
|
|
|
|
Label systemLabel = CreateLabel(
|
|
"Sonic-System",
|
|
new Point(22, 92));
|
|
|
|
_cmbSystem = new ComboBox
|
|
{
|
|
Location = new Point(185, 88),
|
|
Size = new Size(300, 30),
|
|
DropDownStyle =
|
|
ComboBoxStyle.DropDownList
|
|
};
|
|
|
|
_cmbSystem.SelectedIndexChanged +=
|
|
async (_, _) =>
|
|
await SystemChangedAsync();
|
|
|
|
Label credentialLabel = CreateLabel(
|
|
"Benutzerprofil",
|
|
new Point(22, 137));
|
|
|
|
_cmbCredential = new ComboBox
|
|
{
|
|
Location = new Point(185, 133),
|
|
Size = new Size(300, 30),
|
|
DropDownStyle =
|
|
ComboBoxStyle.DropDownList
|
|
};
|
|
|
|
_lblSystemDetails = new Label
|
|
{
|
|
Location = new Point(515, 88),
|
|
Size = new Size(325, 72),
|
|
ForeColor = _mutedTextColor
|
|
};
|
|
|
|
_btnSaveSelection = CreateButton(
|
|
"Auswahl übernehmen");
|
|
|
|
_btnSaveSelection.Location =
|
|
new Point(640, 153);
|
|
|
|
_btnSaveSelection.Size =
|
|
new Size(200, 38);
|
|
|
|
_btnSaveSelection.Click +=
|
|
async (_, _) =>
|
|
await SaveSelectionAsync();
|
|
_btnAddCredential = CreateButton(
|
|
"Profil hinzufügen");
|
|
|
|
_btnAddCredential.Location =
|
|
new Point(495, 132);
|
|
|
|
_btnAddCredential.Size =
|
|
new Size(140, 32);
|
|
|
|
_btnAddCredential.Click +=
|
|
async (_, _) =>
|
|
await AddCredentialAsync();
|
|
selectionCard.Controls.Add(selectionTitle);
|
|
selectionCard.Controls.Add(_lblEnvironment);
|
|
selectionCard.Controls.Add(systemLabel);
|
|
selectionCard.Controls.Add(_cmbSystem);
|
|
selectionCard.Controls.Add(credentialLabel);
|
|
selectionCard.Controls.Add(credentialLabel);
|
|
selectionCard.Controls.Add(_cmbCredential);
|
|
selectionCard.Controls.Add(_btnAddCredential);
|
|
selectionCard.Controls.Add(_lblSystemDetails);
|
|
selectionCard.Controls.Add(_btnSaveSelection);
|
|
|
|
_btnRefresh = CreateButton(
|
|
"Erneut prüfen");
|
|
|
|
_btnRefresh.Location =
|
|
new Point(525, 580);
|
|
|
|
_btnRefresh.Size =
|
|
new Size(140, 42);
|
|
|
|
_btnRefresh.Click +=
|
|
async (_, _) =>
|
|
await InitializeAsync();
|
|
|
|
Button cancelButton = CreateButton(
|
|
"Abbrechen");
|
|
|
|
cancelButton.Location =
|
|
new Point(675, 580);
|
|
|
|
cancelButton.Size =
|
|
new Size(110, 42);
|
|
|
|
cancelButton.Click += (_, _) =>
|
|
{
|
|
DialogResult = DialogResult.Cancel;
|
|
Close();
|
|
};
|
|
|
|
_btnFinish = CreateButton(
|
|
"Setup abschließen");
|
|
|
|
_btnFinish.Location =
|
|
new Point(795, 580);
|
|
|
|
_btnFinish.Size =
|
|
new Size(140, 42);
|
|
|
|
_btnFinish.Enabled = false;
|
|
|
|
_btnFinish.Click += (_, _) =>
|
|
{
|
|
DialogResult = DialogResult.OK;
|
|
Close();
|
|
};
|
|
|
|
Controls.Add(title);
|
|
Controls.Add(subtitle);
|
|
Controls.Add(checkCard);
|
|
Controls.Add(selectionCard);
|
|
Controls.Add(_btnRefresh);
|
|
Controls.Add(cancelButton);
|
|
Controls.Add(_btnFinish);
|
|
}
|
|
|
|
private async Task InitializeAsync()
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(
|
|
this,
|
|
ex.Message,
|
|
"Setup fehlgeschlagen",
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
}
|
|
finally
|
|
{
|
|
SetRunning(false);
|
|
}
|
|
}
|
|
|
|
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 für die gewählte Umgebung gefunden.";
|
|
|
|
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 (_running)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (_cmbSystem.SelectedItem
|
|
is not SonicSystemOption system)
|
|
{
|
|
ShowWarning(
|
|
"Bitte zuerst ein Sonic-System auswählen.");
|
|
|
|
return;
|
|
}
|
|
|
|
using AddCredentialProfileForm dialog =
|
|
new(
|
|
_coordinator,
|
|
system);
|
|
|
|
DialogResult dialogResult =
|
|
dialog.ShowDialog(this);
|
|
|
|
if (dialogResult != DialogResult.OK
|
|
|| dialog.CreatedProfile is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SetRunning(true);
|
|
|
|
try
|
|
{
|
|
_profiles =
|
|
await _coordinator.LoadCredentialsAsync(
|
|
system.SonicConnectionId);
|
|
|
|
_cmbCredential.Items.Clear();
|
|
|
|
foreach (SonicCredentialProfile profile
|
|
in _profiles)
|
|
{
|
|
_cmbCredential.Items.Add(profile);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
_lblSystemDetails.Text =
|
|
$"Domain: {system.DomainName}"
|
|
+ Environment.NewLine
|
|
+ $"Adresse: {system.ConnectionUrl}"
|
|
+ Environment.NewLine
|
|
+ $"Profil: {dialog.CreatedProfile.CredentialName}";
|
|
|
|
MessageBox.Show(
|
|
this,
|
|
"Das geprüfte Benutzerprofil wurde geladen. " +
|
|
"Klicke jetzt auf „Auswahl übernehmen“.",
|
|
"Benutzerprofil hinzugefügt",
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Information);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(
|
|
this,
|
|
ex.Message,
|
|
"Benutzerprofile konnten nicht neu geladen werden",
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Error);
|
|
}
|
|
finally
|
|
{
|
|
SetRunning(false);
|
|
}
|
|
}
|
|
private async Task SystemChangedAsync()
|
|
{
|
|
if (_cmbSystem.SelectedItem
|
|
is not SonicSystemOption system)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_lblSystemDetails.Text =
|
|
$"Domain: {system.DomainName}" +
|
|
Environment.NewLine +
|
|
$"Adresse: {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
|
|
+ "Kein Benutzerprofil vorhanden. "
|
|
+ "Bitte ein neues Profil 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
|
|
{
|
|
int defaultIndex =
|
|
_profiles
|
|
.Select(
|
|
(profile, index) =>
|
|
new
|
|
{
|
|
profile,
|
|
index
|
|
})
|
|
.Where(item =>
|
|
item.profile.IsDefault)
|
|
.Select(item => item.index)
|
|
.FirstOrDefault();
|
|
|
|
selectedIndex = defaultIndex;
|
|
}
|
|
|
|
_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,
|
|
"System und Benutzerprofil wurden ausgewählt.",
|
|
"Setup",
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Information);
|
|
|
|
await InitializeAsync();
|
|
}
|
|
|
|
private async Task ImportCertificateAsync()
|
|
{
|
|
using OpenFileDialog dialog = new()
|
|
{
|
|
Title =
|
|
"Always-Encrypted-PFX auswählen",
|
|
Filter =
|
|
"PFX-Zertifikat (*.pfx)|*.pfx",
|
|
CheckFileExists = true,
|
|
Multiselect = false
|
|
};
|
|
|
|
if (dialog.ShowDialog(this)
|
|
!= DialogResult.OK)
|
|
{
|
|
return;
|
|
}
|
|
|
|
string? password =
|
|
PromptForPassword();
|
|
|
|
if (password is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
_coordinator.CertificateService.ImportPfx(
|
|
dialog.FileName,
|
|
password);
|
|
|
|
password = string.Empty;
|
|
|
|
await InitializeAsync();
|
|
}
|
|
finally
|
|
{
|
|
password = string.Empty;
|
|
}
|
|
}
|
|
|
|
private static string? PromptForPassword()
|
|
{
|
|
using Form form = new()
|
|
{
|
|
Text = "PFX-Kennwort",
|
|
Size = new Size(390, 160),
|
|
StartPosition =
|
|
FormStartPosition.CenterParent,
|
|
FormBorderStyle =
|
|
FormBorderStyle.FixedDialog
|
|
};
|
|
|
|
TextBox textBox = new()
|
|
{
|
|
Location = new Point(15, 35),
|
|
Width = 340,
|
|
UseSystemPasswordChar = true
|
|
};
|
|
|
|
Button ok = new()
|
|
{
|
|
Text = "OK",
|
|
Location = new Point(190, 75),
|
|
DialogResult = DialogResult.OK
|
|
};
|
|
|
|
Button cancel = new()
|
|
{
|
|
Text = "Abbrechen",
|
|
Location = new Point(275, 75),
|
|
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;
|
|
|
|
_cmbSystem.Enabled = !running;
|
|
_cmbCredential.Enabled = !running;
|
|
_btnAddCredential.Enabled = !running;
|
|
_btnSaveSelection.Enabled = !running;
|
|
_btnRefresh.Enabled = !running;
|
|
_btnImportCertificate.Enabled = !running;
|
|
|
|
Cursor =
|
|
running
|
|
? Cursors.WaitCursor
|
|
: Cursors.Default;
|
|
}
|
|
|
|
private void ShowWarning(string message)
|
|
{
|
|
MessageBox.Show(
|
|
this,
|
|
message,
|
|
"Setup",
|
|
MessageBoxButtons.OK,
|
|
MessageBoxIcon.Warning);
|
|
}
|
|
|
|
private Panel CreateCard(
|
|
Point location,
|
|
Size size)
|
|
{
|
|
return new Panel
|
|
{
|
|
Location = location,
|
|
Size = size,
|
|
BackColor = _cardColor,
|
|
BorderStyle =
|
|
BorderStyle.FixedSingle
|
|
};
|
|
}
|
|
|
|
private Label CreateTitle(
|
|
string text,
|
|
Point location)
|
|
{
|
|
return new Label
|
|
{
|
|
Text = text,
|
|
Location = location,
|
|
AutoSize = true,
|
|
ForeColor = _textColor,
|
|
Font = new Font(
|
|
"Segoe UI",
|
|
14,
|
|
FontStyle.Bold)
|
|
};
|
|
}
|
|
|
|
private Label CreateLabel(
|
|
string text,
|
|
Point location)
|
|
{
|
|
return new Label
|
|
{
|
|
Text = text,
|
|
Location = location,
|
|
AutoSize = true,
|
|
ForeColor = _mutedTextColor
|
|
};
|
|
}
|
|
|
|
private Label CreateStatus(
|
|
Point location)
|
|
{
|
|
return new Label
|
|
{
|
|
Location = location,
|
|
Size = new Size(620, 32),
|
|
ForeColor = _mutedTextColor
|
|
};
|
|
}
|
|
|
|
private Button CreateButton(string text)
|
|
{
|
|
return new Button
|
|
{
|
|
Text = text,
|
|
BackColor = _goldColor,
|
|
ForeColor =
|
|
Color.FromArgb(30, 25, 10),
|
|
FlatStyle = FlatStyle.Flat,
|
|
Font = new Font(
|
|
"Segoe UI",
|
|
9,
|
|
FontStyle.Bold),
|
|
Cursor = Cursors.Hand
|
|
};
|
|
}
|
|
|
|
private void SetStatus(
|
|
Label label,
|
|
string category,
|
|
bool success,
|
|
string message)
|
|
{
|
|
label.Text =
|
|
$"{(success ? "✓" : "✗")} " +
|
|
$"{category}: {message}";
|
|
|
|
label.ForeColor =
|
|
success
|
|
? _greenColor
|
|
: _redColor;
|
|
}
|
|
} |