433 lines
13 KiB
C#
433 lines
13 KiB
C#
using ZA.CoreService.ESBCertificateManager.Models;
|
||
using ZA.CoreService.ESBCertificateManager.Services;
|
||
|
||
namespace ZA.CoreService.ESBCertificateManager.Setup;
|
||
|
||
public sealed class SelectContainersForm : Form
|
||
{
|
||
private readonly SetupCoordinator _coordinator;
|
||
private readonly SonicSystemOption _system;
|
||
private readonly SonicContainerScanner _scanner;
|
||
|
||
private readonly ComboBox _cmbCompany;
|
||
private readonly CheckedListBox _lstContainers;
|
||
private readonly TextBox _txtManual;
|
||
private readonly TextBox _txtUser;
|
||
private readonly TextBox _txtPassword;
|
||
private readonly Label _lblStatus;
|
||
private readonly Button _btnScan;
|
||
private readonly Button _btnSave;
|
||
private bool _running;
|
||
|
||
public int SavedCount { get; private set; }
|
||
|
||
public SelectContainersForm(
|
||
SetupCoordinator coordinator,
|
||
SonicSystemOption system)
|
||
{
|
||
_coordinator = coordinator;
|
||
_system = system;
|
||
_scanner = new SonicContainerScanner(coordinator.Settings.Runtime);
|
||
|
||
Text = "Container auswählen";
|
||
StartPosition = FormStartPosition.CenterParent;
|
||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||
MaximizeBox = false;
|
||
MinimizeBox = false;
|
||
ShowInTaskbar = false;
|
||
ClientSize = new Size(640, 620);
|
||
BackColor = SettingsUi.Background;
|
||
ForeColor = SettingsUi.Text;
|
||
Font = new Font("Segoe UI", 10f);
|
||
|
||
Label title = new()
|
||
{
|
||
Text = "Container für System",
|
||
Location = new Point(28, 20),
|
||
AutoSize = true,
|
||
Font = new Font("Segoe UI Semibold", 18f, FontStyle.Bold),
|
||
ForeColor = SettingsUi.Text
|
||
};
|
||
|
||
Label subtitle = new()
|
||
{
|
||
Text =
|
||
$"{system.ConnectionName} · {system.ConnectionUrl}"
|
||
+ Environment.NewLine
|
||
+ "Scan von Sonic oder manuell eintragen, dann übernehmen.",
|
||
Location = new Point(30, 54),
|
||
Size = new Size(580, 40),
|
||
ForeColor = SettingsUi.Muted
|
||
};
|
||
|
||
Panel card = SettingsUi.CreateCard();
|
||
card.Location = new Point(28, 110);
|
||
card.Size = new Size(584, 430);
|
||
card.Paint += SettingsUi.PaintCardBorder;
|
||
|
||
_cmbCompany = SettingsUi.CreateComboBox();
|
||
_lstContainers = new CheckedListBox
|
||
{
|
||
BackColor = Color.FromArgb(12, 28, 48),
|
||
ForeColor = SettingsUi.Text,
|
||
BorderStyle = BorderStyle.FixedSingle,
|
||
CheckOnClick = true,
|
||
Font = new Font("Segoe UI", 10f)
|
||
};
|
||
|
||
_txtManual = SettingsUi.CreateTextBox();
|
||
_txtUser = SettingsUi.CreateTextBox();
|
||
_txtPassword = SettingsUi.CreateTextBox();
|
||
_txtPassword.UseSystemPasswordChar = true;
|
||
|
||
AddField(card, "Company", _cmbCompany, 18, 16, 540);
|
||
AddField(card, "Gefundene / gewählte Container", _lstContainers, 18, 76, 540, 150);
|
||
|
||
Label manualLabel = SettingsUi.CreateFieldLabel("Manuell hinzufügen");
|
||
manualLabel.Location = new Point(18, 240);
|
||
_txtManual.Location = new Point(18, 262);
|
||
_txtManual.Width = 400;
|
||
|
||
Button btnAddManual = SettingsUi.CreateGhostButton("+");
|
||
btnAddManual.Location = new Point(430, 260);
|
||
btnAddManual.Size = new Size(50, 32);
|
||
btnAddManual.Click += (_, _) => AddManualContainer();
|
||
|
||
Button btnSuggest = SettingsUi.CreateGhostButton("ct-ZADBService");
|
||
btnSuggest.Location = new Point(490, 260);
|
||
btnSuggest.Size = new Size(68, 32);
|
||
btnSuggest.Font = new Font("Segoe UI", 7.5f, FontStyle.Bold);
|
||
btnSuggest.Click += (_, _) =>
|
||
{
|
||
_txtManual.Text = "ct-ZADBService";
|
||
AddManualContainer();
|
||
};
|
||
|
||
AddField(card, "Sonic-Benutzer (für Scan)", _txtUser, 18, 308, 250);
|
||
AddField(card, "Kennwort", _txtPassword, 288, 308, 270);
|
||
|
||
_btnScan = SettingsUi.CreatePrimaryButton("Von Sonic scannen");
|
||
_btnScan.Location = new Point(18, 375);
|
||
_btnScan.Size = new Size(200, 36);
|
||
_btnScan.Click += async (_, _) => await ScanAsync();
|
||
|
||
_lblStatus = new Label
|
||
{
|
||
Location = new Point(230, 380),
|
||
Size = new Size(330, 30),
|
||
ForeColor = SettingsUi.Muted
|
||
};
|
||
|
||
card.Controls.Add(manualLabel);
|
||
card.Controls.Add(_txtManual);
|
||
card.Controls.Add(btnAddManual);
|
||
card.Controls.Add(btnSuggest);
|
||
card.Controls.Add(_btnScan);
|
||
card.Controls.Add(_lblStatus);
|
||
|
||
_btnSave = SettingsUi.CreatePrimaryButton("Auswahl speichern");
|
||
_btnSave.Location = new Point(352, 555);
|
||
_btnSave.Size = new Size(260, 42);
|
||
_btnSave.Click += async (_, _) => await SaveAsync();
|
||
|
||
Button skip = SettingsUi.CreateGhostButton("Später");
|
||
skip.Location = new Point(230, 555);
|
||
skip.Size = new Size(110, 42);
|
||
skip.Click += (_, _) =>
|
||
{
|
||
DialogResult = DialogResult.Cancel;
|
||
Close();
|
||
};
|
||
|
||
Controls.Add(title);
|
||
Controls.Add(subtitle);
|
||
Controls.Add(card);
|
||
Controls.Add(skip);
|
||
Controls.Add(_btnSave);
|
||
|
||
Shown += async (_, _) => await InitializeAsync();
|
||
}
|
||
|
||
private async Task InitializeAsync()
|
||
{
|
||
try
|
||
{
|
||
IReadOnlyList<CompanyOption> companies =
|
||
await _coordinator.LoadCompaniesAsync();
|
||
|
||
_cmbCompany.Items.Clear();
|
||
|
||
foreach (CompanyOption company in companies)
|
||
{
|
||
_cmbCompany.Items.Add(company);
|
||
}
|
||
|
||
if (_cmbCompany.Items.Count > 0)
|
||
{
|
||
int deIndex = 0;
|
||
|
||
for (int index = 0; index < companies.Count; index++)
|
||
{
|
||
if (string.Equals(
|
||
companies[index].CompanyCode,
|
||
"DE",
|
||
StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
deIndex = index;
|
||
break;
|
||
}
|
||
}
|
||
|
||
_cmbCompany.SelectedIndex = deIndex;
|
||
}
|
||
|
||
IReadOnlyList<SonicCredentialProfile> profiles =
|
||
await _coordinator.LoadCredentialsAsync(
|
||
_system.SonicConnectionId);
|
||
|
||
SonicCredentialProfile? profile =
|
||
profiles.FirstOrDefault(item => item.IsDefault)
|
||
?? profiles.FirstOrDefault();
|
||
|
||
if (profile is not null)
|
||
{
|
||
_txtUser.Text = profile.UserName;
|
||
_txtPassword.Text = profile.Secret;
|
||
_lblStatus.Text =
|
||
"Profil geladen — Scan möglich.";
|
||
_lblStatus.ForeColor = SettingsUi.Green;
|
||
}
|
||
else
|
||
{
|
||
_lblStatus.Text =
|
||
"Kein Profil — Benutzer/Kennwort für Scan eingeben oder manuell.";
|
||
_lblStatus.ForeColor = SettingsUi.Gold;
|
||
}
|
||
|
||
// Bereits vorhandene Container vorselektieren
|
||
IReadOnlyList<ContainerOption> existing =
|
||
await _coordinator.LoadContainersAsync(
|
||
_system.SonicConnectionId);
|
||
|
||
foreach (ContainerOption container in existing)
|
||
{
|
||
AddContainerName(container.ContainerName, check: true);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_lblStatus.Text = ex.Message;
|
||
_lblStatus.ForeColor = SettingsUi.Red;
|
||
}
|
||
}
|
||
|
||
private void AddManualContainer()
|
||
{
|
||
string name = _txtManual.Text.Trim();
|
||
|
||
if (name.Length == 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
AddContainerName(name, check: true);
|
||
_txtManual.Clear();
|
||
_txtManual.Focus();
|
||
}
|
||
|
||
private void AddContainerName(string name, bool check)
|
||
{
|
||
for (int index = 0; index < _lstContainers.Items.Count; index++)
|
||
{
|
||
if (string.Equals(
|
||
_lstContainers.Items[index]?.ToString(),
|
||
name,
|
||
StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
_lstContainers.SetItemChecked(index, check);
|
||
return;
|
||
}
|
||
}
|
||
|
||
int added = _lstContainers.Items.Add(name);
|
||
_lstContainers.SetItemChecked(added, check);
|
||
}
|
||
|
||
private async Task ScanAsync()
|
||
{
|
||
if (_running)
|
||
{
|
||
return;
|
||
}
|
||
|
||
_running = true;
|
||
_btnScan.Enabled = false;
|
||
_btnSave.Enabled = false;
|
||
Cursor = Cursors.WaitCursor;
|
||
_lblStatus.Text = "Scanne Domain…";
|
||
_lblStatus.ForeColor = SettingsUi.Muted;
|
||
|
||
try
|
||
{
|
||
ContainerScanResult result =
|
||
await _scanner.ScanAsync(
|
||
_system,
|
||
_txtUser.Text,
|
||
_txtPassword.Text);
|
||
|
||
if (!result.Success)
|
||
{
|
||
_lblStatus.Text = result.Message;
|
||
_lblStatus.ForeColor = SettingsUi.Red;
|
||
return;
|
||
}
|
||
|
||
foreach (string container in result.Containers)
|
||
{
|
||
AddContainerName(container, check: true);
|
||
}
|
||
|
||
_lblStatus.Text =
|
||
result.Containers.Count == 0
|
||
? "Scan OK, aber keine Container gefunden — bitte manuell."
|
||
: $"{result.Containers.Count} Container gescannt und vorausgewählt.";
|
||
|
||
_lblStatus.ForeColor =
|
||
result.Containers.Count == 0
|
||
? SettingsUi.Gold
|
||
: SettingsUi.Green;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_lblStatus.Text = ex.Message;
|
||
_lblStatus.ForeColor = SettingsUi.Red;
|
||
}
|
||
finally
|
||
{
|
||
_running = false;
|
||
_btnScan.Enabled = true;
|
||
_btnSave.Enabled = true;
|
||
Cursor = Cursors.Default;
|
||
}
|
||
}
|
||
|
||
private async Task SaveAsync()
|
||
{
|
||
if (_running)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (_cmbCompany.SelectedItem is not CompanyOption company)
|
||
{
|
||
MessageBox.Show(
|
||
this,
|
||
"Bitte eine Company wählen.",
|
||
"Container",
|
||
MessageBoxButtons.OK,
|
||
MessageBoxIcon.Warning);
|
||
return;
|
||
}
|
||
|
||
List<string> selected = _lstContainers.CheckedItems
|
||
.Cast<object>()
|
||
.Select(item => item.ToString() ?? string.Empty)
|
||
.Where(name => name.Length > 0)
|
||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||
.ToList();
|
||
|
||
if (selected.Count == 0)
|
||
{
|
||
MessageBox.Show(
|
||
this,
|
||
"Bitte mindestens einen Container angehakt lassen "
|
||
+ "oder manuell hinzufügen.",
|
||
"Container",
|
||
MessageBoxButtons.OK,
|
||
MessageBoxIcon.Warning);
|
||
return;
|
||
}
|
||
|
||
_running = true;
|
||
_btnSave.Enabled = false;
|
||
Cursor = Cursors.WaitCursor;
|
||
|
||
try
|
||
{
|
||
IReadOnlyList<ContainerOption> existing =
|
||
await _coordinator.LoadContainersAsync(
|
||
_system.SonicConnectionId);
|
||
|
||
HashSet<string> existingNames = existing
|
||
.Select(item => item.ContainerName)
|
||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||
|
||
int created = 0;
|
||
|
||
foreach (string containerName in selected)
|
||
{
|
||
if (existingNames.Contains(containerName))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
await _coordinator.AddSonicContainerAsync(
|
||
company.CompanyId,
|
||
_system.SonicConnectionId,
|
||
containerName,
|
||
containerDisplayName: null,
|
||
restartTimeoutSeconds: 180);
|
||
|
||
created++;
|
||
}
|
||
|
||
SavedCount = created;
|
||
|
||
MessageBox.Show(
|
||
this,
|
||
created == 0
|
||
? "Alle gewählten Container waren bereits vorhanden."
|
||
: $"{created} Container gespeichert und geprüft.",
|
||
"Prüfung OK",
|
||
MessageBoxButtons.OK,
|
||
MessageBoxIcon.Information);
|
||
|
||
DialogResult = DialogResult.OK;
|
||
Close();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show(
|
||
this,
|
||
ex.Message,
|
||
"Container",
|
||
MessageBoxButtons.OK,
|
||
MessageBoxIcon.Error);
|
||
}
|
||
finally
|
||
{
|
||
_running = false;
|
||
_btnSave.Enabled = true;
|
||
Cursor = Cursors.Default;
|
||
}
|
||
}
|
||
|
||
private static void AddField(
|
||
Control parent,
|
||
string label,
|
||
Control input,
|
||
int x,
|
||
int y,
|
||
int width,
|
||
int height = 30)
|
||
{
|
||
Label fieldLabel = SettingsUi.CreateFieldLabel(label);
|
||
fieldLabel.Location = new Point(x, y);
|
||
input.Location = new Point(x, y + 22);
|
||
input.Width = width;
|
||
input.Height = height;
|
||
parent.Controls.Add(fieldLabel);
|
||
parent.Controls.Add(input);
|
||
}
|
||
}
|