Files
LIAM/LiamWorkflowDiagnostics/MainWindow.xaml.cs

912 lines
42 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.IO;
using C4IT.LIAM;
using C4IT.Logging;
using C4IT.Matrix42.ServerInfo;
using LiamWorkflowActivities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace LiamWorkflowDiagnostics
{
public partial class MainWindow : Window
{
private readonly ObservableCollection<string> _logEntries = new ObservableCollection<string>();
private ProviderTestSession _session;
private readonly string _settingsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "LiamWorkflowDiagnostics.settings.json");
public MainWindow()
{
InitializeComponent();
LogListBox.ItemsSource = _logEntries;
InitializeLogging();
InitializeCombos();
MaxDepthTextBox.Text = "1";
LoadSettings();
this.Closing += MainWindow_Closing;
AppendLog("Diagnostics tool bereit.");
}
private void InitializeLogging()
{
try
{
var baseDir = AppDomain.CurrentDomain.BaseDirectory;
var logDirectory = Path.Combine(baseDir, "logs");
Directory.CreateDirectory(logDirectory);
var logPath = Path.Combine(logDirectory, "LiamWorkflowDiagnostics.log");
cLogManagerFile.CreateInstance(logPath);
cLogManager.Instance.Level = LogLevels.Debug;
AppendLog($"Logdatei: {logPath} (Level: Debug)");
}
catch (Exception ex)
{
AppendLog($"Konnte Logging nicht initialisieren: {ex.Message}", LogLevels.Warning);
}
}
private void InitializeCombos()
{
var providerTypes = new[]
{
eLiamProviderTypes.MsTeams,
eLiamProviderTypes.Ntfs,
eLiamProviderTypes.ActiveDirectory,
eLiamProviderTypes.Exchange
};
ProviderTypeCombo.ItemsSource = providerTypes;
ProviderTypeCombo.SelectedItem = eLiamProviderTypes.MsTeams;
GroupStrategyCombo.ItemsSource = Enum.GetValues(typeof(eLiamGroupStrategies)).Cast<eLiamGroupStrategies>();
GroupStrategyCombo.SelectedItem = eLiamGroupStrategies.Ntfs_AGDLP;
FetchDataAreasButton.IsEnabled = false;
FetchSecurityGroupsButton.IsEnabled = false;
}
private void AppendLog(string message, LogLevels level = LogLevels.Info)
{
if (message == null)
{
message = string.Empty;
}
void AddEntry()
{
var timestamped = $"{DateTime.Now:HH:mm:ss} {message}";
_logEntries.Add(timestamped);
LogListBox.ScrollIntoView(timestamped);
StatusTextBlock.Text = message;
}
if (!Dispatcher.CheckAccess())
{
Dispatcher.Invoke(AddEntry);
}
else
{
AddEntry();
}
try
{
cLogManager.DefaultLogger?.LogEntry(level, message);
}
catch { /* ignore */ }
}
private void AppendLogMultiline(string text, LogLevels level = LogLevels.Info)
{
if (string.IsNullOrEmpty(text))
return;
foreach (var line in text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None))
{
AppendLog(line, level);
}
}
private async void InitializeButton_Click(object sender, RoutedEventArgs e)
{
ToggleActionButtons(false);
try
{
var providerData = BuildProviderDataFromFields();
var maskToken = string.IsNullOrWhiteSpace(MaskTokenTextBox.Text) ? "***" : MaskTokenTextBox.Text.Trim();
var providerConfigClassId = (ProviderConfigIdTextBox.Text ?? string.Empty).Trim();
var providerConfigObjectId = (ProviderConfigObjectIdTextBox.Text ?? string.Empty).Trim();
ApplyMatrix42Environment(ServerNameTextBox.Text, UseHttpsCheckBox.IsChecked ?? false);
ApplyLicense(LicenseTextBox.Text);
_session = new ProviderTestSession(msg => AppendLog(msg));
var success = await _session.InitializeAsync(providerData, maskToken, CreateProviderInstance, providerConfigClassId, providerConfigObjectId);
if (success)
{
AppendLog("Provider initialisiert und authentifiziert.", LogLevels.Info);
FetchDataAreasButton.IsEnabled = true;
FetchSecurityGroupsButton.IsEnabled = true;
ResultTextBox.Text = _session.SanitizedConfigJson;
}
else
{
AppendLog("Initialisierung fehlgeschlagen. Prüfe Log für Details.", LogLevels.Error);
FetchDataAreasButton.IsEnabled = false;
FetchSecurityGroupsButton.IsEnabled = false;
}
}
catch (Exception ex)
{
AppendLog($"Fehler bei Initialisierung: {ex.Message}", LogLevels.Error);
MessageBox.Show(this, ex.ToString(), "Initialisierung fehlgeschlagen", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
ToggleActionButtons(true);
}
}
private void ToggleActionButtons(bool enabled)
{
InitializeButton.IsEnabled = enabled;
LoadJsonButton.IsEnabled = enabled;
ExportJsonButton.IsEnabled = enabled;
}
private void ClearLogButton_Click(object sender, RoutedEventArgs e)
{
_logEntries.Clear();
StatusTextBlock.Text = string.Empty;
AppendLog("Log gelöscht.", LogLevels.Debug);
}
private void LoadSettings()
{
ToolSettings settings = null;
try
{
if (File.Exists(_settingsPath))
{
var json = File.ReadAllText(_settingsPath, Encoding.UTF8);
settings = JsonConvert.DeserializeObject<ToolSettings>(json);
}
}
catch (Exception ex)
{
AppendLog($"Einstellungen konnten nicht geladen werden: {ex.Message}", LogLevels.Warning);
}
if (settings == null)
{
settings = new ToolSettings();
}
ApplySettingsToUi(settings);
}
private void ApplySettingsToUi(ToolSettings settings)
{
if (settings == null)
return;
if (Enum.IsDefined(typeof(eLiamProviderTypes), settings.ProviderType))
ProviderTypeCombo.SelectedItem = (eLiamProviderTypes)settings.ProviderType;
DomainTextBox.Text = settings.Domain ?? string.Empty;
RootPathTextBox.Text = settings.RootPath ?? string.Empty;
MaxDepthTextBox.Text = string.IsNullOrWhiteSpace(settings.MaxDepth) ? "1" : settings.MaxDepth;
GroupFilterTextBox.Text = settings.GroupFilter ?? string.Empty;
GroupPathTextBox.Text = settings.GroupPath ?? string.Empty;
DataAreaFilterTextBox.Text = settings.DataAreaFilter ?? string.Empty;
DataAreaRegexTextBox.Text = settings.DataAreaRegex ?? string.Empty;
GroupRegexTextBox.Text = settings.GroupRegex ?? string.Empty;
TraverseGroupTextBox.Text = settings.TraverseGroup ?? string.Empty;
OwnerGroupGlobalTextBox.Text = settings.OwnerGroupGlobal ?? string.Empty;
OwnerGroupLocalTextBox.Text = settings.OwnerGroupLocal ?? string.Empty;
WriteGroupGlobalTextBox.Text = settings.WriteGroupGlobal ?? string.Empty;
WriteGroupLocalTextBox.Text = settings.WriteGroupLocal ?? string.Empty;
ReadGroupGlobalTextBox.Text = settings.ReadGroupGlobal ?? string.Empty;
ReadGroupLocalTextBox.Text = settings.ReadGroupLocal ?? string.Empty;
CredentialUserTextBox.Text = settings.CredentialUser ?? string.Empty;
CredentialDomainTextBox.Text = settings.CredentialDomain ?? string.Empty;
MaskTokenTextBox.Text = settings.MaskToken ?? "***";
AdditionalConfigTextBox.Text = settings.AdditionalConfiguration ?? string.Empty;
CustomTagsTextBox.Text = settings.CustomTags ?? string.Empty;
NamingConventionsTextBox.Text = settings.NamingConventions ?? string.Empty;
RawJsonTextBox.Text = settings.RawJson ?? string.Empty;
ProviderConfigIdTextBox.Text = settings.ProviderConfigClassId ?? string.Empty;
ProviderConfigObjectIdTextBox.Text = settings.ProviderConfigObjectId ?? string.Empty;
ServerNameTextBox.Text = settings.ServerName ?? string.Empty;
UseHttpsCheckBox.IsChecked = settings.UseHttps;
LicenseTextBox.Text = settings.License ?? string.Empty;
if (Enum.IsDefined(typeof(eLiamGroupStrategies), settings.GroupStrategy))
GroupStrategyCombo.SelectedItem = (eLiamGroupStrategies)settings.GroupStrategy;
}
private void SaveSettings()
{
try
{
var settings = new ToolSettings
{
ProviderType = ProviderTypeCombo.SelectedItem is eLiamProviderTypes type ? (int)type : (int)eLiamProviderTypes.MsTeams,
Domain = DomainTextBox.Text ?? string.Empty,
RootPath = RootPathTextBox.Text ?? string.Empty,
MaxDepth = MaxDepthTextBox.Text ?? string.Empty,
GroupFilter = GroupFilterTextBox.Text ?? string.Empty,
GroupPath = GroupPathTextBox.Text ?? string.Empty,
DataAreaFilter = DataAreaFilterTextBox.Text ?? string.Empty,
DataAreaRegex = DataAreaRegexTextBox.Text ?? string.Empty,
GroupRegex = GroupRegexTextBox.Text ?? string.Empty,
TraverseGroup = TraverseGroupTextBox.Text ?? string.Empty,
OwnerGroupGlobal = OwnerGroupGlobalTextBox.Text ?? string.Empty,
OwnerGroupLocal = OwnerGroupLocalTextBox.Text ?? string.Empty,
WriteGroupGlobal = WriteGroupGlobalTextBox.Text ?? string.Empty,
WriteGroupLocal = WriteGroupLocalTextBox.Text ?? string.Empty,
ReadGroupGlobal = ReadGroupGlobalTextBox.Text ?? string.Empty,
ReadGroupLocal = ReadGroupLocalTextBox.Text ?? string.Empty,
CredentialUser = CredentialUserTextBox.Text ?? string.Empty,
CredentialDomain = CredentialDomainTextBox.Text ?? string.Empty,
MaskToken = MaskTokenTextBox.Text ?? "***",
AdditionalConfiguration = AdditionalConfigTextBox.Text ?? string.Empty,
CustomTags = CustomTagsTextBox.Text ?? string.Empty,
NamingConventions = NamingConventionsTextBox.Text ?? string.Empty,
RawJson = RawJsonTextBox.Text ?? string.Empty,
ProviderConfigClassId = ProviderConfigIdTextBox.Text ?? string.Empty,
ProviderConfigObjectId = ProviderConfigObjectIdTextBox.Text ?? string.Empty,
ServerName = ServerNameTextBox.Text ?? string.Empty,
UseHttps = UseHttpsCheckBox.IsChecked ?? false,
License = LicenseTextBox.Text ?? string.Empty,
GroupStrategy = GroupStrategyCombo.SelectedItem is eLiamGroupStrategies gs ? (int)gs : (int)eLiamGroupStrategies.Ntfs_AGDLP
};
var directory = Path.GetDirectoryName(_settingsPath);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
Directory.CreateDirectory(directory);
var json = JsonConvert.SerializeObject(settings, Formatting.Indented);
File.WriteAllText(_settingsPath, json, Encoding.UTF8);
}
catch (Exception ex)
{
AppendLog($"Einstellungen konnten nicht gespeichert werden: {ex.Message}", LogLevels.Warning);
}
}
private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
SaveSettings();
}
private async void FetchDataAreasButton_Click(object sender, RoutedEventArgs e)
{
if (_session?.Provider == null)
{
AppendLog("Kein Provider initialisiert.", LogLevels.Warning);
return;
}
try
{
var maxDepth = _session.Provider.MaxDepth >= 0 ? _session.Provider.MaxDepth : 1;
AppendLog($"Lese DataAreas (MaxDepth={maxDepth}) ...");
var areas = await _session.Provider.getDataAreasAsync(maxDepth);
if (areas == null)
{
var providerMessage = _session.Provider.GetLastErrorMessage();
if (_session.Provider is cLiamProviderExchange exchangeProvider)
{
var code = exchangeProvider.GetLastErrorCode();
if (string.IsNullOrWhiteSpace(code))
code = "EXCH_GET_DATAAREAS_FAILED";
AppendLog($"DataAreas-Call fehlgeschlagen [{code}]: {providerMessage}", LogLevels.Error);
}
else
{
AppendLog($"DataAreas-Call fehlgeschlagen: {providerMessage}", LogLevels.Error);
}
ResultTextBox.Text = "[]";
return;
}
if (areas.Count == 0)
{
AppendLog("Keine DataAreas gefunden.", LogLevels.Warning);
ResultTextBox.Text = "[]";
return;
}
var entries = ConvertDataAreas(areas);
var json = JsonConvert.SerializeObject(entries, Formatting.Indented);
ResultTextBox.Text = json;
AppendLog($"DataAreas erhalten: {entries.Count}");
}
catch (Exception ex)
{
AppendLog($"Fehler beim Laden der DataAreas: {ex.Message}", LogLevels.Error);
MessageBox.Show(this, ex.ToString(), "Fehler beim DataArea-Call", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private async void FetchSecurityGroupsButton_Click(object sender, RoutedEventArgs e)
{
if (_session?.Provider == null)
{
AppendLog("Kein Provider initialisiert.", LogLevels.Warning);
return;
}
try
{
AppendLog($"Lese SecurityGroups (Filter='{_session.Provider.GroupFilter}') ...");
var groups = await _session.Provider.getSecurityGroupsAsync(_session.Provider.GroupFilter);
if (groups == null)
{
var providerMessage = _session.Provider.GetLastErrorMessage();
if (_session.Provider is cLiamProviderExchange exchangeProvider)
{
var code = exchangeProvider.GetLastErrorCode();
if (string.IsNullOrWhiteSpace(code))
code = "EXCH_GET_SECURITYGROUPS_FAILED";
AppendLog($"SecurityGroups-Call fehlgeschlagen [{code}]: {providerMessage}", LogLevels.Error);
}
else
{
AppendLog($"SecurityGroups-Call fehlgeschlagen: {providerMessage}", LogLevels.Error);
}
ResultTextBox.Text = "[]";
return;
}
if (groups.Count == 0)
{
AppendLog("Keine SecurityGroups gefunden.", LogLevels.Warning);
ResultTextBox.Text = "[]";
return;
}
var entries = ConvertSecurityGroups(groups);
var json = JsonConvert.SerializeObject(entries, Formatting.Indented);
ResultTextBox.Text = json;
AppendLog($"SecurityGroups erhalten: {entries.Count}");
}
catch (Exception ex)
{
AppendLog($"Fehler beim Laden der SecurityGroups: {ex.Message}", LogLevels.Error);
MessageBox.Show(this, ex.ToString(), "Fehler beim SecurityGroup-Call", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void LoadJsonButton_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(RawJsonTextBox.Text))
{
AppendLog("Kein JSON zum Laden vorhanden.", LogLevels.Warning);
return;
}
try
{
var data = ParseProviderDataFromInput(RawJsonTextBox.Text);
if (data == null)
{
AppendLog("JSON enthielt keine gültigen Providerdaten.", LogLevels.Error);
return;
}
PopulateFields(data);
AppendLog("Providerdaten aus JSON übernommen.");
}
catch (Exception ex)
{
AppendLog($"JSON konnte nicht geparst werden: {ex.Message}", LogLevels.Error);
MessageBox.Show(this, ex.ToString(), "JSON-Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private cLiamProviderData ParseProviderDataFromInput(string input)
{
if (string.IsNullOrWhiteSpace(input))
return null;
try
{
var token = JToken.Parse(input);
return ParseProviderDataFromToken(token);
}
catch (JsonReaderException)
{
// Fallback: direkter Versuch, falls nur der reine Provider-Datensatz eingegeben wurde.
return JsonConvert.DeserializeObject<cLiamProviderData>(input);
}
}
private cLiamProviderData ParseProviderDataFromToken(JToken token)
{
if (token == null)
return null;
switch (token.Type)
{
case JTokenType.Object:
var obj = (JObject)token;
SetProviderIdentifiersFromObject(obj);
// Wenn der Export-Endpunkt verwendet wurde, liegt die Konfiguration im Feld "configuration".
var configurationProperty = obj.Properties()
.FirstOrDefault(p => string.Equals(p.Name, "configuration", StringComparison.OrdinalIgnoreCase));
if (configurationProperty != null)
{
var configToken = configurationProperty.Value;
var provider = configToken?.ToObject<cLiamProviderData>();
if (provider == null)
return null;
var sanitizedProperty = obj.Properties()
.FirstOrDefault(p => string.Equals(p.Name, "sanitizedJson", StringComparison.OrdinalIgnoreCase));
if (sanitizedProperty?.Value != null && sanitizedProperty.Value.Type == JTokenType.String)
{
var sanitized = sanitizedProperty.Value.Value<string>();
if (!string.IsNullOrWhiteSpace(sanitized))
RawJsonTextBox.Text = sanitized;
}
else
{
RawJsonTextBox.Text = JsonConvert.SerializeObject(provider, Formatting.Indented);
}
return provider;
}
// Alternativ: ein Objekt mit direkt eingebettetem Sanitized JSON.
var sanitizedJsonProperty = obj.Properties()
.FirstOrDefault(p => string.Equals(p.Name, "sanitizedJson", StringComparison.OrdinalIgnoreCase));
if (sanitizedJsonProperty?.Value != null)
{
var sanitized = sanitizedJsonProperty.Value.Type == JTokenType.String
? sanitizedJsonProperty.Value.Value<string>()
: sanitizedJsonProperty.Value.ToString();
if (!string.IsNullOrWhiteSpace(sanitized))
{
RawJsonTextBox.Text = sanitized;
return JsonConvert.DeserializeObject<cLiamProviderData>(sanitized);
}
}
// Wenn nichts davon zutrifft, versuchen wir das Objekt direkt zu konvertieren.
var direct = obj.ToObject<cLiamProviderData>();
if (direct != null)
RawJsonTextBox.Text = JsonConvert.SerializeObject(direct, Formatting.Indented);
return direct;
case JTokenType.String:
var json = token.Value<string>();
if (string.IsNullOrWhiteSpace(json))
return null;
RawJsonTextBox.Text = json;
return JsonConvert.DeserializeObject<cLiamProviderData>(json);
default:
return token.ToObject<cLiamProviderData>();
}
}
private void SetProviderIdentifiersFromObject(JObject obj)
{
if (obj == null)
return;
var classIdProp = obj.Properties().FirstOrDefault(p => string.Equals(p.Name, "providerconfigclassid", StringComparison.OrdinalIgnoreCase));
if (classIdProp?.Value != null)
{
var value = classIdProp.Value.Type == JTokenType.String ? classIdProp.Value.Value<string>() : classIdProp.Value.ToString();
ProviderConfigIdTextBox.Text = value?.Trim();
}
var objectIdProp = obj.Properties().FirstOrDefault(p => string.Equals(p.Name, "providerconfigobjectid", StringComparison.OrdinalIgnoreCase));
if (objectIdProp?.Value != null)
{
var value = objectIdProp.Value.Type == JTokenType.String ? objectIdProp.Value.Value<string>() : objectIdProp.Value.ToString();
ProviderConfigObjectIdTextBox.Text = value?.Trim();
}
}
private void ExportJsonButton_Click(object sender, RoutedEventArgs e)
{
try
{
var providerData = BuildProviderDataFromFields();
var maskToken = string.IsNullOrWhiteSpace(MaskTokenTextBox.Text) ? "***" : MaskTokenTextBox.Text.Trim();
var sanitized = ProviderTestSession.BuildSanitizedJson(providerData, maskToken);
ResultTextBox.Text = sanitized;
AppendLog("Provider-Konfiguration als sanitisiertes JSON exportiert.");
}
catch (Exception ex)
{
AppendLog($"Export fehlgeschlagen: {ex.Message}", LogLevels.Error);
MessageBox.Show(this, ex.ToString(), "Export-Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private cLiamProviderBase CreateProviderInstance(cLiamProviderData data)
{
if (data == null)
throw new ArgumentNullException(nameof(data));
data.ReplaceCustomTags();
var configuration = new cLiamConfiguration();
switch (data.ProviderType)
{
case eLiamProviderTypes.MsTeams:
return new cLiamProviderMsTeams(configuration, data);
case eLiamProviderTypes.Ntfs:
return new cLiamProviderNtfs(configuration, data);
case eLiamProviderTypes.ActiveDirectory:
return new cLiamProviderAD(configuration, data);
case eLiamProviderTypes.Exchange:
return new cLiamProviderExchange(configuration, data);
default:
throw new NotSupportedException($"ProviderType '{data.ProviderType}' wird nicht unterstützt.");
}
}
private cLiamProviderData BuildProviderDataFromFields()
{
if (!(ProviderTypeCombo.SelectedItem is eLiamProviderTypes providerType) || providerType == eLiamProviderTypes.Unknown)
throw new InvalidOperationException("Bitte einen Provider-Typ auswählen.");
var additional = ParseKeyValueLines(AdditionalConfigTextBox.Text, "Additional Configuration");
var customTags = ParseKeyValueLines(CustomTagsTextBox.Text, "Custom Tags");
var namingConventions = ParseNamingConventions(NamingConventionsTextBox.Text);
var password = CredentialPasswordBox.Password ?? string.Empty;
var credentialDomain = string.IsNullOrWhiteSpace(CredentialDomainTextBox.Text)
? DomainTextBox.Text?.Trim()
: CredentialDomainTextBox.Text.Trim();
if (string.IsNullOrWhiteSpace(password))
throw new InvalidOperationException("Bitte ein Kennwort für den Logon hinterlegen.");
var data = new cLiamProviderData
{
ProviderType = providerType,
Domain = DomainTextBox.Text?.Trim() ?? string.Empty,
RootPath = RootPathTextBox.Text?.Trim() ?? string.Empty,
MaxDepth = ParseInt(MaxDepthTextBox.Text, 1),
GroupFilter = GroupFilterTextBox.Text?.Trim() ?? string.Empty,
GroupPath = GroupPathTextBox.Text?.Trim() ?? string.Empty,
GroupStrategy = GroupStrategyCombo.SelectedItem is eLiamGroupStrategies gs ? gs : eLiamGroupStrategies.None,
DataAreaFilter = DataAreaFilterTextBox.Text?.Trim() ?? string.Empty,
DataAreaRegEx = DataAreaRegexTextBox.Text?.Trim() ?? string.Empty,
GroupRegEx = GroupRegexTextBox.Text?.Trim() ?? string.Empty,
TraverseGroup = TraverseGroupTextBox.Text?.Trim() ?? string.Empty,
OwnerGroupGlobal = OwnerGroupGlobalTextBox.Text?.Trim() ?? string.Empty,
OwnerGroupLocal = OwnerGroupLocalTextBox.Text?.Trim() ?? string.Empty,
WriteGroupGlobal = WriteGroupGlobalTextBox.Text?.Trim() ?? string.Empty,
WriteGroupLocal = WriteGroupLocalTextBox.Text?.Trim() ?? string.Empty,
ReadGroupGlobal = ReadGroupGlobalTextBox.Text?.Trim() ?? string.Empty,
ReadGroupLocal = ReadGroupLocalTextBox.Text?.Trim() ?? string.Empty,
Credential = new cLiamCredential
{
Domain = credentialDomain ?? string.Empty,
Identification = CredentialUserTextBox.Text?.Trim() ?? string.Empty,
Secret = password
},
AdditionalConfiguration = additional,
CustomTags = customTags,
NamingConventions = namingConventions
};
if (string.IsNullOrWhiteSpace(data.Credential.Identification))
throw new InvalidOperationException("Bitte ein Konto für den Logon hinterlegen.");
SaveSettings();
return data;
}
private Dictionary<string, string> ParseKeyValueLines(string text, string context)
{
var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
if (string.IsNullOrWhiteSpace(text))
return result;
var lines = text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var trimmed = line.Trim();
if (trimmed.Length == 0 || trimmed.StartsWith("#"))
continue;
var parts = trimmed.Split(new[] { '=' }, 2);
if (parts.Length != 2)
throw new InvalidOperationException($"{context}: Ungültige Zeile '{line}'. Verwende Format key=value.");
result[parts[0].Trim()] = parts[1].Trim();
}
return result;
}
private List<cLiamNamingConvention> ParseNamingConventions(string text)
{
if (string.IsNullOrWhiteSpace(text))
return new List<cLiamNamingConvention>();
try
{
return JsonConvert.DeserializeObject<List<cLiamNamingConvention>>(text) ?? new List<cLiamNamingConvention>();
}
catch (Exception ex)
{
throw new InvalidOperationException($"Naming Conventions JSON ungültig: {ex.Message}");
}
}
private List<DataAreaEntry> ConvertDataAreas(IEnumerable<cLiamDataAreaBase> dataAreas)
{
var result = new List<DataAreaEntry>();
foreach (var dataArea in dataAreas ?? Enumerable.Empty<cLiamDataAreaBase>())
{
var ntfsPermissionArea = dataArea as cLiamNtfsPermissionDataAreaBase;
var ntfsFolder = dataArea as cLiamNtfsFolder;
var adGroup = dataArea as cLiamAdGroupAsDataArea;
var exchMailbox = dataArea as cLiamExchangeSharedMailbox;
var exchDistribution = dataArea as cLiamExchangeDistributionGroup;
var owner = exchMailbox?.OwnerGroupIdentifier
?? exchDistribution?.OwnerGroupIdentifier
?? adGroup?.ManagedBySID
?? ntfsPermissionArea?.OwnerGroupIdentifier
?? string.Empty;
var write = exchMailbox != null
? exchMailbox.FullAccessGroupSid
: exchDistribution != null
? exchDistribution.MemberGroupSid
: adGroup?.UID
?? ntfsPermissionArea?.WriteGroupIdentifier
?? string.Empty;
var read = exchMailbox != null
? exchMailbox.SendAsGroupSid
: ntfsPermissionArea?.ReadGroupIdentifier
?? string.Empty;
var traverse = ntfsPermissionArea?.TraverseGroupIdentifier ?? string.Empty;
var created = ntfsFolder?.CreatedDate ?? string.Empty;
var description = adGroup?.Description ?? string.Empty;
result.Add(new DataAreaEntry
{
DisplayName = dataArea.DisplayName ?? string.Empty,
UID = dataArea.UID ?? string.Empty,
TechnicalName = dataArea.TechnicalName ?? string.Empty,
Description = description,
TargetType = ((int)dataArea.Provider.ProviderType).ToString(),
ParentUID = dataArea.ParentUID ?? string.Empty,
Level = dataArea.Level.ToString(),
Owner = owner,
Write = write,
Read = read,
Traverse = traverse,
CreatedDate = created,
ConfigurationId = !string.IsNullOrWhiteSpace(_session?.ProviderConfigObjectId)
? _session.ProviderConfigObjectId
: (!string.IsNullOrWhiteSpace(_session?.ProviderConfigId) ? _session.ProviderConfigId : string.Empty),
BaseFolder = ntfsFolder?.Share?.TechnicalName ?? dataArea.Provider?.RootPath ?? string.Empty,
UniqueId = dataArea.UID ?? string.Empty,
DataAreaType = ((int)dataArea.DataType).ToString()
});
}
return result;
}
private List<SecurityGroupEntry> ConvertSecurityGroups(IEnumerable<cLiamDataAreaBase> groups)
{
var result = new List<SecurityGroupEntry>();
foreach (var sg in groups ?? Enumerable.Empty<cLiamDataAreaBase>())
{
var entry = new SecurityGroupEntry
{
DisplayName = sg.TechnicalName ?? sg.DisplayName ?? string.Empty,
TechnicalName = sg.UID ?? string.Empty,
TargetType = ((int)sg.Provider.ProviderType).ToString()
};
switch (sg)
{
case cLiamAdGroup adGroup:
entry.UID = adGroup.dn;
entry.Scope = adGroup.scope;
break;
case cLiamAdGroup2 adGroup2:
entry.UID = adGroup2.dn;
entry.Scope = adGroup2.scope;
break;
case cLiamExchangeSecurityGroup exchangeGroup:
entry.UID = exchangeGroup.dn;
break;
default:
entry.UID = sg.UID;
break;
}
result.Add(entry);
}
return result;
}
private void PopulateFields(cLiamProviderData data)
{
if (data == null)
return;
if (Enum.IsDefined(typeof(eLiamProviderTypes), data.ProviderType))
ProviderTypeCombo.SelectedItem = data.ProviderType;
DomainTextBox.Text = data.Domain ?? string.Empty;
RootPathTextBox.Text = data.RootPath ?? string.Empty;
MaxDepthTextBox.Text = data.MaxDepth.ToString();
GroupFilterTextBox.Text = data.GroupFilter ?? string.Empty;
GroupPathTextBox.Text = data.GroupPath ?? string.Empty;
DataAreaFilterTextBox.Text = data.DataAreaFilter ?? string.Empty;
DataAreaRegexTextBox.Text = data.DataAreaRegEx ?? string.Empty;
GroupRegexTextBox.Text = data.GroupRegEx ?? string.Empty;
TraverseGroupTextBox.Text = data.TraverseGroup ?? string.Empty;
OwnerGroupGlobalTextBox.Text = data.OwnerGroupGlobal ?? string.Empty;
OwnerGroupLocalTextBox.Text = data.OwnerGroupLocal ?? string.Empty;
WriteGroupGlobalTextBox.Text = data.WriteGroupGlobal ?? string.Empty;
WriteGroupLocalTextBox.Text = data.WriteGroupLocal ?? string.Empty;
ReadGroupGlobalTextBox.Text = data.ReadGroupGlobal ?? string.Empty;
ReadGroupLocalTextBox.Text = data.ReadGroupLocal ?? string.Empty;
if (Enum.IsDefined(typeof(eLiamGroupStrategies), data.GroupStrategy))
GroupStrategyCombo.SelectedItem = data.GroupStrategy;
CredentialUserTextBox.Text = data.Credential?.Identification ?? string.Empty;
CredentialDomainTextBox.Text = data.Credential?.Domain ?? string.Empty;
CredentialPasswordBox.Password = string.Empty;
AdditionalConfigTextBox.Text = FormatKeyValueLines(data.AdditionalConfiguration);
CustomTagsTextBox.Text = FormatKeyValueLines(data.CustomTags);
NamingConventionsTextBox.Text = data.NamingConventions != null && data.NamingConventions.Count > 0
? JsonConvert.SerializeObject(data.NamingConventions, Formatting.Indented)
: string.Empty;
SaveSettings();
}
private string FormatKeyValueLines(Dictionary<string, string> source)
{
if (source == null || source.Count == 0)
return string.Empty;
var builder = new StringBuilder();
foreach (var kvp in source)
{
builder.Append(kvp.Key);
builder.Append('=');
builder.AppendLine(kvp.Value);
}
return builder.ToString();
}
private int ParseInt(string value, int fallback)
{
if (int.TryParse(value, out var result))
return result;
return fallback;
}
private void ApplyLicense(string licenseRaw)
{
if (string.IsNullOrWhiteSpace(licenseRaw))
{
AppendLog("Keine Lizenz angegeben. Lizenzprüfung könnte fehlschlagen.", LogLevels.Warning);
return;
}
try
{
if (cC4ITLicenseM42ESM.Instance == null)
_ = new cC4ITLicenseM42ESM(new Guid(cLIAMM42BaseActivity.LiamProductGuid));
cC4ITLicenseM42ESM.Instance.LoadFromString(licenseRaw);
AppendLog($"Lizenz geladen. Gültig: {cC4ITLicenseM42ESM.Instance.IsValid}", cC4ITLicenseM42ESM.Instance.IsValid ? LogLevels.Info : LogLevels.Warning);
}
catch (Exception ex)
{
AppendLog($"Lizenz konnte nicht geladen werden: {ex.Message}", LogLevels.Error);
throw;
}
}
private void ApplyMatrix42Environment(string serverName, bool useHttps)
{
var trimmed = serverName?.Trim();
if (string.IsNullOrEmpty(trimmed))
{
AppendLog("Kein Portal-Server angegeben. Lizenz muss ggf. \"*\" enthalten.", LogLevels.Warning);
return;
}
try
{
var instance = cMatrix42ServerInfo.DefaultInstance;
if (instance == null)
{
var type = typeof(cMatrix42ServerInfo);
instance = (cMatrix42ServerInfo)Activator.CreateInstance(type, nonPublic: true);
SetProperty(type, instance, "InstallationPath", string.Empty);
}
var lowered = trimmed.ToLowerInvariant();
SetProperty(instance.GetType(), instance, "ServerName", lowered);
SetProperty(instance.GetType(), instance, "IsHttps", useHttps);
var defaultProp = typeof(cMatrix42ServerInfo).GetProperty("DefaultInstance", BindingFlags.Static | BindingFlags.Public);
var setter = defaultProp?.GetSetMethod(true);
setter?.Invoke(null, new object[] { instance });
AppendLog($"Matrix42 ServerInfo gesetzt auf '{lowered}' (HTTPS={(useHttps ? "ja" : "nein")}).");
}
catch (Exception ex)
{
AppendLog($"Matrix42 ServerInfo konnte nicht gesetzt werden: {ex.Message}", LogLevels.Warning);
}
}
private void SetProperty(Type type, object instance, string propertyName, object value)
{
var prop = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
var setter = prop?.GetSetMethod(true);
setter?.Invoke(instance, new[] { value });
}
private class ToolSettings
{
public int ProviderType { get; set; } = (int)eLiamProviderTypes.MsTeams;
public int GroupStrategy { get; set; } = (int)eLiamGroupStrategies.Ntfs_AGDLP;
public string Domain { get; set; } = string.Empty;
public string RootPath { get; set; } = string.Empty;
public string MaxDepth { get; set; } = "1";
public string GroupFilter { get; set; } = string.Empty;
public string GroupPath { get; set; } = string.Empty;
public string DataAreaFilter { get; set; } = string.Empty;
public string DataAreaRegex { get; set; } = string.Empty;
public string GroupRegex { get; set; } = string.Empty;
public string TraverseGroup { get; set; } = string.Empty;
public string OwnerGroupGlobal { get; set; } = string.Empty;
public string OwnerGroupLocal { get; set; } = string.Empty;
public string WriteGroupGlobal { get; set; } = string.Empty;
public string WriteGroupLocal { get; set; } = string.Empty;
public string ReadGroupGlobal { get; set; } = string.Empty;
public string ReadGroupLocal { get; set; } = string.Empty;
public string CredentialUser { get; set; } = string.Empty;
public string CredentialDomain { get; set; } = string.Empty;
public string MaskToken { get; set; } = "***";
public string AdditionalConfiguration { get; set; } = string.Empty;
public string CustomTags { get; set; } = string.Empty;
public string NamingConventions { get; set; } = string.Empty;
public string RawJson { get; set; } = string.Empty;
public string ProviderConfigClassId { get; set; } = string.Empty;
public string ProviderConfigObjectId { get; set; } = string.Empty;
public string ServerName { get; set; } = string.Empty;
public bool UseHttps { get; set; } = false;
public string License { get; set; } = string.Empty;
}
}
}