Share workflow runtime with diagnostics tool

This commit is contained in:
Meik
2026-03-13 15:14:03 +01:00
parent 55ff17c4b4
commit 4909c93bef
5 changed files with 705 additions and 528 deletions

View File

@@ -537,39 +537,28 @@ namespace LiamWorkflowDiagnostics
try
{
var maxDepth = _session.Provider.MaxDepth >= 0 ? _session.Provider.MaxDepth : 1;
var maxDepth = _session.Provider.MaxDepth;
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);
}
var result = await LiamWorkflowRuntime.GetDataAreasFromProviderAsync(
_session.Provider,
!string.IsNullOrWhiteSpace(_session.ProviderConfigObjectId)
? _session.ProviderConfigObjectId
: (_session.ProviderConfigId ?? string.Empty));
ResultTextBox.Text = JsonConvert.SerializeObject(result, Formatting.Indented);
ResultTextBox.Text = "[]";
if (!result.Success)
{
AppendLog($"DataAreas-Call fehlgeschlagen [{result.ErrorCode}]: {result.ErrorMessage}", LogLevels.Error);
return;
}
if (areas.Count == 0)
if (result.DataAreas.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}");
AppendLog($"DataAreas erhalten: {result.DataAreas.Count}");
}
catch (Exception ex)
{
@@ -595,16 +584,20 @@ namespace LiamWorkflowDiagnostics
if (ownerSids.Count == 0)
throw new InvalidOperationException("Owner SIDs: mindestens ein Eintrag ist fuer die Ordneranlage erforderlich.");
var result = EnsureSuccessfulResultToken(await provider.CreateDataAreaAsync(
var result = await LiamWorkflowRuntime.CreateDataAreaAsync(
provider,
folderPath,
parentPath,
ParseKeyValueLines(CustomTagsTextBox.Text, "Custom Tags"),
null,
ownerSids,
ParseIdentifierList(NtfsCreateReaderSidsTextBox.Text, "Reader SIDs"),
ParseIdentifierList(NtfsCreateWriterSidsTextBox.Text, "Writer SIDs")),
"NTFS Folder Create");
ParseIdentifierList(NtfsCreateWriterSidsTextBox.Text, "Writer SIDs"));
return MapResultToken(result);
return new
{
result.Success,
ResultToken = MapResultToken(result.ResultToken)
};
});
}
@@ -614,15 +607,20 @@ namespace LiamWorkflowDiagnostics
{
var provider = EnsureInitializedProvider<cLiamProviderNtfs>("NTFS");
var folderPath = GetRequiredText(NtfsEnsureFolderPathTextBox.Text, "Folder Path");
var result = await provider.EnsureMissingPermissionGroupsAsync(
var result = await LiamWorkflowRuntime.EnsureNtfsPermissionGroupsAsync(
provider,
folderPath,
ParseKeyValueLines(CustomTagsTextBox.Text, "Custom Tags"),
null,
ParseIdentifierList(NtfsEnsureOwnerSidsTextBox.Text, "Owner SIDs"),
ParseIdentifierList(NtfsEnsureReaderSidsTextBox.Text, "Reader SIDs"),
ParseIdentifierList(NtfsEnsureWriterSidsTextBox.Text, "Writer SIDs"),
NtfsEnsureTraverseCheckBox.IsChecked ?? false);
return MapResultToken(EnsureSuccessfulResultToken(result, "NTFS Ensure Groups / ACLs"));
return new
{
result.Success,
ResultToken = MapResultToken(result.ResultToken)
};
});
}
@@ -642,7 +640,8 @@ namespace LiamWorkflowDiagnostics
var ownerSids = ParseIdentifierList(AdOwnerSidsTextBox.Text, "Owner SIDs");
var memberSids = ParseIdentifierList(AdMemberSidsTextBox.Text, "Member SIDs");
var result = await Task.Run(() => provider.CreateServiceGroups(
var result = await Task.Run(() => LiamWorkflowRuntime.CreateAdServiceGroups(
provider,
serviceName,
description,
scope,
@@ -650,7 +649,7 @@ namespace LiamWorkflowDiagnostics
ownerSids,
memberSids));
return MapSecurityGroupResults(result);
return result;
});
}
@@ -663,7 +662,8 @@ namespace LiamWorkflowDiagnostics
var newTeamName = GetRequiredText(MsTeamsNewNameTextBox.Text, "New Team Name");
var visibility = GetSelectedMsTeamsVisibility();
var result = await provider.cloneTeam(
var result = await LiamWorkflowRuntime.CloneTeamAsync(
provider,
sourceTeamId,
newTeamName,
NormalizeOptionalText(MsTeamsDescriptionTextBox.Text),
@@ -672,7 +672,7 @@ namespace LiamWorkflowDiagnostics
string.Join(";", ParseIdentifierList(MsTeamsAdditionalMembersTextBox.Text, "Additional Members")),
string.Join(";", ParseIdentifierList(MsTeamsAdditionalOwnersTextBox.Text, "Additional Owners")));
return MapMsGraphResult(result);
return result;
});
}
@@ -685,17 +685,14 @@ namespace LiamWorkflowDiagnostics
var alias = GetRequiredText(ExchangeMailboxAliasTextBox.Text, "Alias");
var displayName = NormalizeOptionalText(ExchangeMailboxDisplayNameTextBox.Text);
var primarySmtp = NormalizeOptionalText(ExchangeMailboxPrimarySmtpTextBox.Text);
var result = await Task.Run(() => provider.exchangeManager.CreateSharedMailboxWithOwnershipGroups(
var result = await Task.Run(() => LiamWorkflowRuntime.CreateSharedMailbox(
provider,
name,
alias,
displayName,
primarySmtp));
return new
{
ObjectGuid = result.Item1,
Groups = MapSecurityGroupResults(result.Item2)
};
return result;
});
}
@@ -708,17 +705,14 @@ namespace LiamWorkflowDiagnostics
var alias = GetRequiredText(ExchangeDistributionAliasTextBox.Text, "Alias");
var displayName = NormalizeOptionalText(ExchangeDistributionDisplayNameTextBox.Text);
var primarySmtp = NormalizeOptionalText(ExchangeDistributionPrimarySmtpTextBox.Text);
var result = await Task.Run(() => provider.exchangeManager.CreateDistributionGroupWithOwnershipGroups(
var result = await Task.Run(() => LiamWorkflowRuntime.CreateDistributionGroup(
provider,
name,
alias,
displayName,
primarySmtp));
return new
{
ObjectGuid = result.Item1,
Groups = MapSecurityGroupResults(result.Item2)
};
return result;
});
}
@@ -733,37 +727,22 @@ namespace LiamWorkflowDiagnostics
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);
}
var result = await LiamWorkflowRuntime.GetSecurityGroupsFromProviderAsync(_session.Provider);
ResultTextBox.Text = JsonConvert.SerializeObject(result, Formatting.Indented);
ResultTextBox.Text = "[]";
if (!result.Success)
{
AppendLog($"SecurityGroups-Call fehlgeschlagen [{result.ErrorCode}]: {result.ErrorMessage}", LogLevels.Error);
return;
}
if (groups.Count == 0)
if (result.SecurityGroups.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}");
AppendLog($"SecurityGroups erhalten: {result.SecurityGroups.Count}");
}
catch (Exception ex)
{
@@ -810,7 +789,10 @@ namespace LiamWorkflowDiagnostics
AppendLog($"{actionName} gestartet.");
var result = await action();
ResultTextBox.Text = JsonConvert.SerializeObject(result, Formatting.Indented);
AppendLog($"{actionName} erfolgreich abgeschlossen.");
if (TryGetSuccessFlag(result, out var success) && !success)
AppendLog($"{actionName} mit Fehlerstatus abgeschlossen.", LogLevels.Warning);
else
AppendLog($"{actionName} erfolgreich abgeschlossen.");
}
catch (Exception ex)
{
@@ -823,6 +805,24 @@ namespace LiamWorkflowDiagnostics
}
}
private bool TryGetSuccessFlag(object instance, out bool success)
{
success = false;
if (instance == null)
return false;
var property = instance.GetType().GetProperty("Success", BindingFlags.Instance | BindingFlags.Public);
if (property == null || property.PropertyType != typeof(bool))
return false;
var rawValue = property.GetValue(instance);
if (!(rawValue is bool boolValue))
return false;
success = boolValue;
return true;
}
private TProvider EnsureInitializedProvider<TProvider>(string providerName) where TProvider : cLiamProviderBase
{
if (_session?.Provider == null)
@@ -914,51 +914,6 @@ namespace LiamWorkflowDiagnostics
};
}
private ResultToken EnsureSuccessfulResultToken(ResultToken token, string actionName)
{
if (token == null)
throw new InvalidOperationException($"{actionName}: kein Ergebnis vom Provider erhalten.");
if (token.resultErrorId != 0)
{
var message = string.IsNullOrWhiteSpace(token.resultMessage)
? "Unbekannter Fehler im Provider."
: token.resultMessage.Trim();
throw new InvalidOperationException($"[{token.resultErrorId}] {message}");
}
return token;
}
private List<object> MapSecurityGroupResults(IEnumerable<Tuple<string, string, string, string>> groups)
{
return (groups ?? Enumerable.Empty<Tuple<string, string, string, string>>())
.Select(i => (object)new
{
Role = i.Item1 ?? string.Empty,
Sid = i.Item2 ?? string.Empty,
Name = i.Item3 ?? string.Empty,
DistinguishedName = i.Item4 ?? string.Empty
})
.ToList();
}
private object MapMsGraphResult(object result)
{
if (result == null)
return null;
var resultType = result.GetType();
return new
{
Id = ReadPropertyValue<string>(result, resultType, "ID"),
DisplayName = ReadPropertyValue<string>(result, resultType, "DisplayName"),
ODataId = ReadPropertyValue<string>(result, resultType, "ODataId"),
Context = ReadPropertyValue<string>(result, resultType, "Context"),
Result = ReadPropertyValue<object>(result, resultType, "Result")
};
}
private int GetSelectedMsTeamsVisibility()
{
var selectedValue = MsTeamsVisibilityComboBox.SelectedValue;
@@ -978,22 +933,6 @@ namespace LiamWorkflowDiagnostics
|| value == MsTeamsVisibilityHiddenMembership;
}
private T ReadPropertyValue<T>(object instance, Type instanceType, string propertyName)
{
var property = instanceType.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
if (property == null)
return default(T);
var value = property.GetValue(instance);
if (value == null)
return default(T);
if (value is T typedValue)
return typedValue;
return default(T);
}
private cLiamProviderData ParseProviderDataFromInput(string input)
{
if (string.IsNullOrWhiteSpace(input))
@@ -1236,100 +1175,6 @@ namespace LiamWorkflowDiagnostics
}
}
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)