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

456 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using ZA.CoreService.ESBCertificateManager.Models;
using ZA.CoreService.ESBCertificateManager.Services;
namespace ZA.CoreService.ESBCertificateManager.Setup;
public sealed class AddTargetPathForm : Form
{
private readonly SetupCoordinator _coordinator;
private readonly CertificateProbeService _probeService = new();
private readonly CertificateTargetOption? _existing;
private readonly int? _preferredSonicContainerId;
private readonly ComboBox _cmbContainer;
private readonly TextBox _txtFullPath;
private readonly TextBox _txtBackupFolder;
private readonly CheckBox _chkBackup;
private readonly Label _lblProbeResult;
private readonly Button _btnProbe;
private readonly Button _btnSave;
private CertificateProbeResult? _lastProbe;
private bool _running;
public int? CreatedCertificateTargetId { get; private set; }
public bool IsEditMode => _existing is not null;
public AddTargetPathForm(
SetupCoordinator coordinator,
int? preferredSonicContainerId = null,
CertificateTargetOption? existing = null)
{
_coordinator = coordinator;
_preferredSonicContainerId = preferredSonicContainerId;
_existing = existing;
Text = IsEditMode
? "Zertifikat-Pfad bearbeiten"
: "Zertifikat-Pfad hinzufügen";
StartPosition = FormStartPosition.CenterParent;
FormBorderStyle = FormBorderStyle.FixedDialog;
MaximizeBox = false;
MinimizeBox = false;
ShowInTaskbar = false;
ClientSize = new Size(640, 560);
BackColor = SettingsUi.Background;
ForeColor = SettingsUi.Text;
Font = new Font("Segoe UI", 10f);
Label title = new()
{
Text = IsEditMode
? "Zertifikat-Pfad bearbeiten"
: "Zertifikat-Datei-Pfad",
Location = new Point(28, 18),
AutoSize = true,
Font = new Font("Segoe UI Semibold", 18f, FontStyle.Bold),
ForeColor = SettingsUi.Text
};
Label subtitle = new()
{
Text =
"UNC- oder lokaler Dateipfad zur .cer/.crt/.pem/.pfx/.p12-Datei. "
+ "Der Container ist nur das Neustart-Ziel.",
Location = new Point(30, 54),
MaximumSize = new Size(580, 40),
AutoSize = true,
ForeColor = SettingsUi.Muted
};
Panel card = SettingsUi.CreateCard();
card.Location = new Point(28, 100);
card.Size = new Size(584, 360);
card.Paint += SettingsUi.PaintCardBorder;
_txtFullPath = SettingsUi.CreateTextBox();
_txtFullPath.Text = _existing?.FullTargetPath
?? DemoCertificatePath.FullPath;
_txtFullPath.PlaceholderText = DemoCertificatePath.FullPath;
Button browse = SettingsUi.CreateGhostButton("…");
browse.Size = new Size(40, 32);
browse.Click += (_, _) => BrowseForFile();
_btnProbe = SettingsUi.CreateGhostButton("Prüfen");
_btnProbe.Size = new Size(100, 32);
_btnProbe.Click += (_, _) => RunProbe();
_lblProbeResult = new Label
{
AutoSize = false,
Size = new Size(548, 52),
ForeColor = SettingsUi.Muted,
Font = new Font("Segoe UI", 9f),
Text =
"Noch nicht geprüft. Bitte Pfad prüfen bei vorhandener "
+ "Datei wird der Ablauf angezeigt."
};
_cmbContainer = SettingsUi.CreateComboBox();
_txtBackupFolder = SettingsUi.CreateTextBox();
_txtBackupFolder.Text = _existing?.BackupDirectoryName ?? "Backup";
_chkBackup = new CheckBox
{
Text = "Backup vor dem Überschreiben",
AutoSize = true,
Checked = _existing?.BackupEnabled ?? true,
ForeColor = SettingsUi.Text,
Font = new Font("Segoe UI", 9.5f)
};
Label pathLabel = SettingsUi.CreateFieldLabel(
"Vollständiger Pfad zur Zertifikatsdatei");
pathLabel.Location = new Point(18, 16);
_txtFullPath.Location = new Point(18, 38);
_txtFullPath.Width = 370;
browse.Location = new Point(394, 38);
_btnProbe.Location = new Point(440, 38);
_lblProbeResult.Location = new Point(18, 78);
Label containerLabel = SettingsUi.CreateFieldLabel(
"Neustart-Ziel (Sonic-Container) nicht der Dateipfad");
containerLabel.Location = new Point(18, 140);
_cmbContainer.Location = new Point(18, 162);
_cmbContainer.Width = 548;
Label hint = new()
{
Text =
"Nach dem Austausch wird dieser Container über MfApi "
+ "neu gestartet. Der Pfad oben ist unabhängig davon.",
Location = new Point(18, 202),
MaximumSize = new Size(548, 36),
AutoSize = true,
ForeColor = SettingsUi.Muted,
Font = new Font("Segoe UI", 8.5f)
};
AddField(card, "Backup-Ordner", _txtBackupFolder, 18, 250, 220);
_chkBackup.Location = new Point(258, 272);
card.Controls.Add(_chkBackup);
card.Controls.Add(pathLabel);
card.Controls.Add(_txtFullPath);
card.Controls.Add(browse);
card.Controls.Add(_btnProbe);
card.Controls.Add(_lblProbeResult);
card.Controls.Add(containerLabel);
card.Controls.Add(_cmbContainer);
card.Controls.Add(hint);
_btnSave = SettingsUi.CreatePrimaryButton(
IsEditMode ? "Änderungen speichern" : "Pfad anlegen");
_btnSave.Location = new Point(392, 490);
_btnSave.Size = new Size(220, 40);
_btnSave.Click += async (_, _) => await SaveAsync();
Button cancel = SettingsUi.CreateGhostButton("Abbrechen");
cancel.Location = new Point(270, 490);
cancel.Size = new Size(110, 40);
cancel.Click += (_, _) =>
{
DialogResult = DialogResult.Cancel;
Close();
};
Controls.Add(title);
Controls.Add(subtitle);
Controls.Add(card);
Controls.Add(cancel);
Controls.Add(_btnSave);
Shown += async (_, _) => await LoadContainersAsync();
}
private void BrowseForFile()
{
using OpenFileDialog dialog = new()
{
Title = "Vorhandene Zertifikatsdatei wählen",
Filter =
"Zertifikate (*.cer;*.crt;*.pem;*.pfx;*.p12)|"
+ "*.cer;*.crt;*.pem;*.pfx;*.p12|"
+ "Alle Dateien (*.*)|*.*",
CheckFileExists = false,
Multiselect = false
};
if (dialog.ShowDialog(this) != DialogResult.OK)
{
return;
}
_txtFullPath.Text = dialog.FileName;
RunProbe();
}
private void RunProbe()
{
_lastProbe = _probeService.Probe(
_txtFullPath.Text,
() => PromptForPassword(this));
if (!_lastProbe.Success)
{
_lblProbeResult.ForeColor = Color.FromArgb(220, 100, 100);
_lblProbeResult.Text = _lastProbe.Message;
return;
}
if (!_lastProbe.FileExists)
{
_lblProbeResult.ForeColor = Color.FromArgb(230, 180, 80);
_lblProbeResult.Text =
_lastProbe.Message
+ " Pfad kann trotzdem gespeichert werden "
+ "(erstes Deployment).";
return;
}
CertificateInfo cert = _lastProbe.Certificate!;
string expiry = cert.ValidUntil.ToLocalTime()
.ToString("dd.MM.yyyy HH:mm");
_lblProbeResult.ForeColor = cert.IsCurrentlyValid
? Color.FromArgb(90, 200, 140)
: Color.FromArgb(220, 100, 100);
_lblProbeResult.Text =
$"Datei vorhanden · Subject: {cert.Subject}\n"
+ $"Ablauf: {expiry} · Fingerprint: {cert.FingerprintSha256}";
}
private async Task LoadContainersAsync()
{
try
{
IReadOnlyList<ContainerOption> containers =
await _coordinator.LoadContainersAsync();
_cmbContainer.Items.Clear();
int selected = 0;
int? preferredId =
_existing?.SonicContainerId ?? _preferredSonicContainerId;
for (int index = 0; index < containers.Count; index++)
{
_cmbContainer.Items.Add(containers[index]);
if (preferredId is int id
&& containers[index].SonicContainerId == id)
{
selected = index;
}
}
if (_cmbContainer.Items.Count > 0)
{
_cmbContainer.SelectedIndex = selected;
}
}
catch (Exception ex)
{
MessageBox.Show(
this,
ex.Message,
"Zertifikat-Pfad",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
private async Task SaveAsync()
{
if (_running)
{
return;
}
if (_cmbContainer.SelectedItem is not ContainerOption container)
{
MessageBox.Show(
this,
"Bitte ein Neustart-Ziel (Sonic-Container) wählen.",
"Zertifikat-Pfad",
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
return;
}
if (!CertificateProbeService.TrySplitTargetPath(
_txtFullPath.Text,
out string directory,
out string fileName,
out string? splitError))
{
MessageBox.Show(
this,
splitError ?? "Ungültiger Pfad.",
"Zertifikat-Pfad",
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
return;
}
// Vor dem Speichern immer prüfen
RunProbe();
if (_lastProbe is null || !_lastProbe.Success)
{
MessageBox.Show(
this,
_lastProbe?.Message
?? "Pfad konnte nicht geprüft werden.",
"Zertifikat-Pfad",
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
return;
}
if (!_lastProbe.FileExists)
{
DialogResult confirm = MessageBox.Show(
this,
"Am Ziel liegt noch keine Zertifikatsdatei.\n\n"
+ "Pfad trotzdem speichern?",
"Datei fehlt",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (confirm != DialogResult.Yes)
{
return;
}
}
_running = true;
_btnSave.Enabled = false;
Cursor = Cursors.WaitCursor;
try
{
if (_existing is not null)
{
await _coordinator.UpdateCertificateTargetAsync(
_existing.CertificateTargetId,
container.SonicContainerId,
directory,
fileName,
_chkBackup.Checked,
_txtBackupFolder.Text);
CreatedCertificateTargetId = _existing.CertificateTargetId;
}
else
{
CreatedCertificateTargetId =
await _coordinator.AddCertificateTargetAsync(
container.SonicContainerId,
directory,
fileName,
_chkBackup.Checked,
_txtBackupFolder.Text);
}
DialogResult = DialogResult.OK;
Close();
}
catch (Exception ex)
{
MessageBox.Show(
this,
ex.Message,
"Zertifikat-Pfad",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
finally
{
_running = false;
_btnSave.Enabled = true;
Cursor = Cursors.Default;
}
}
private static string? PromptForPassword(IWin32Window owner)
{
using Form dialog = new()
{
Text = "PFX/P12-Kennwort",
FormBorderStyle = FormBorderStyle.FixedDialog,
StartPosition = FormStartPosition.CenterParent,
ClientSize = new Size(360, 140),
MaximizeBox = false,
MinimizeBox = false,
ShowInTaskbar = false,
BackColor = SettingsUi.Background,
ForeColor = SettingsUi.Text
};
Label label = new()
{
Text = "Kennwort für die Zertifikatsdatei:",
Location = new Point(16, 16),
AutoSize = true
};
TextBox txtPwd = new()
{
Location = new Point(16, 44),
Width = 320,
UseSystemPasswordChar = true
};
Button btnOk = SettingsUi.CreatePrimaryButton("OK");
btnOk.Location = new Point(196, 90);
btnOk.Size = new Size(140, 32);
btnOk.DialogResult = DialogResult.OK;
Button btnCancel = SettingsUi.CreateGhostButton("Abbrechen");
btnCancel.Location = new Point(100, 90);
btnCancel.Size = new Size(90, 32);
btnCancel.DialogResult = DialogResult.Cancel;
dialog.Controls.Add(label);
dialog.Controls.Add(txtPwd);
dialog.Controls.Add(btnOk);
dialog.Controls.Add(btnCancel);
dialog.AcceptButton = btnOk;
dialog.CancelButton = btnCancel;
return dialog.ShowDialog(owner) == DialogResult.OK
? txtPwd.Text
: null;
}
private static void AddField(
Control parent,
string label,
Control input,
int x,
int y,
int width)
{
Label fieldLabel = SettingsUi.CreateFieldLabel(label);
fieldLabel.Location = new Point(x, y);
input.Location = new Point(x, y + 22);
input.Width = width;
parent.Controls.Add(fieldLabel);
parent.Controls.Add(input);
}
}