Add diagnostics WhatIf mode

This commit is contained in:
Meik
2026-03-18 14:05:51 +01:00
parent 2bda1010d1
commit 24e10feffc
2 changed files with 181 additions and 13 deletions

View File

@@ -455,6 +455,12 @@
</GroupBox>
<StackPanel Grid.Row="5" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,0,8">
<CheckBox x:Name="WhatIfCheckBox"
Content="WhatIf aktiv (Schreibaktionen nur simulieren)"
Margin="0,0,16,0"
VerticalAlignment="Center"
IsChecked="True"
Click="WhatIfCheckBox_Click"/>
<Button x:Name="LoadJsonButton" Content="Load JSON" Width="110" Margin="0,0,8,0" Click="LoadJsonButton_Click"/>
<Button x:Name="ExportJsonButton" Content="Export Sanitized JSON" Width="170" Margin="0,0,8,0" Click="ExportJsonButton_Click"/>
<Button x:Name="InitializeButton" Content="Initialize Provider" Width="160" Margin="0,0,8,0" Click="InitializeButton_Click"/>

View File

@@ -113,6 +113,7 @@ namespace LiamWorkflowDiagnostics
MsTeamsVisibilityComboBox.SelectedValue = MsTeamsVisibilityPrivate;
MsTeamsCloneSettingsCheckBox.IsChecked = true;
MsTeamsCloneChannelsCheckBox.IsChecked = true;
WhatIfCheckBox.IsChecked = true;
FetchDataAreasButton.IsEnabled = false;
FetchSecurityGroupsButton.IsEnabled = false;
@@ -240,6 +241,18 @@ namespace LiamWorkflowDiagnostics
AppendLog("Log gelöscht.", LogLevels.Debug);
}
private void WhatIfCheckBox_Click(object sender, RoutedEventArgs e)
{
if (_isInitializingUi)
return;
UpdateActionHint();
SaveSettings();
AppendLog(IsWhatIfEnabled
? "WhatIf aktiviert. Schreibende Aktionen im Diagnostics Tool werden nur simuliert."
: "WhatIf deaktiviert. Schreibende Aktionen im Diagnostics Tool werden real ausgeführt.", LogLevels.Warning);
}
private void LogListBox_KeyDown(object sender, KeyEventArgs e)
{
if ((Keyboard.Modifiers & ModifierKeys.Control) != ModifierKeys.Control)
@@ -327,6 +340,7 @@ namespace LiamWorkflowDiagnostics
ServerNameTextBox.Text = settings.ServerName ?? string.Empty;
UseHttpsCheckBox.IsChecked = settings.UseHttps;
LicenseTextBox.Text = settings.License ?? string.Empty;
WhatIfCheckBox.IsChecked = settings.EnableWhatIf;
NtfsCreateFolderPathTextBox.Text = settings.NtfsCreateFolderPath ?? string.Empty;
NtfsCreateParentPathTextBox.Text = settings.NtfsCreateParentPath ?? string.Empty;
NtfsCreateOwnerSidsTextBox.Text = settings.NtfsCreateOwnerSids ?? string.Empty;
@@ -405,6 +419,7 @@ namespace LiamWorkflowDiagnostics
ServerName = ServerNameTextBox.Text ?? string.Empty,
UseHttps = UseHttpsCheckBox.IsChecked ?? false,
License = LicenseTextBox.Text ?? string.Empty,
EnableWhatIf = WhatIfCheckBox.IsChecked ?? true,
GroupStrategy = GroupStrategyCombo.SelectedItem is eLiamGroupStrategies gs ? (int)gs : (int)eLiamGroupStrategies.Ntfs_AGDLP,
NtfsCreateFolderPath = NtfsCreateFolderPathTextBox.Text ?? string.Empty,
NtfsCreateParentPath = NtfsCreateParentPathTextBox.Text ?? string.Empty,
@@ -522,9 +537,13 @@ namespace LiamWorkflowDiagnostics
break;
}
var modeHint = IsWhatIfEnabled
? " WhatIf ist aktiv: Schreibende Diagnostics-Aktionen werden nur simuliert."
: " WhatIf ist deaktiviert: Schreibende Diagnostics-Aktionen werden real ausgeführt.";
ActionHintTextBlock.Text = providerReady
? providerHint
: $"Initialisiere zuerst einen Provider. {providerHint}";
? providerHint + modeHint
: $"Initialisiere zuerst einen Provider. {providerHint}{modeHint}";
}
private async void FetchDataAreasButton_Click(object sender, RoutedEventArgs e)
@@ -583,6 +602,8 @@ namespace LiamWorkflowDiagnostics
var ownerSids = ParseIdentifierList(NtfsCreateOwnerSidsTextBox.Text, "Owner SIDs");
if (ownerSids.Count == 0)
throw new InvalidOperationException("Owner SIDs: mindestens ein Eintrag ist fuer die Ordneranlage erforderlich.");
var readerSids = ParseIdentifierList(NtfsCreateReaderSidsTextBox.Text, "Reader SIDs");
var writerSids = ParseIdentifierList(NtfsCreateWriterSidsTextBox.Text, "Writer SIDs");
var result = await LiamWorkflowRuntime.CreateDataAreaAsync(
provider,
@@ -590,14 +611,41 @@ namespace LiamWorkflowDiagnostics
parentPath,
null,
ownerSids,
ParseIdentifierList(NtfsCreateReaderSidsTextBox.Text, "Reader SIDs"),
ParseIdentifierList(NtfsCreateWriterSidsTextBox.Text, "Writer SIDs"));
readerSids,
writerSids);
return new
{
result.Success,
ResultToken = MapResultToken(result.ResultToken)
};
}, () =>
{
var provider = EnsureInitializedProvider<cLiamProviderNtfs>("NTFS");
var folderPath = GetRequiredText(NtfsCreateFolderPathTextBox.Text, "New Folder Path");
var parentPath = NormalizeOptionalText(NtfsCreateParentPathTextBox.Text);
if (string.IsNullOrWhiteSpace(parentPath))
{
parentPath = Directory.GetParent(folderPath)?.FullName;
}
if (string.IsNullOrWhiteSpace(parentPath))
throw new InvalidOperationException("Parent Folder Path konnte nicht ermittelt werden.");
var ownerSids = ParseIdentifierList(NtfsCreateOwnerSidsTextBox.Text, "Owner SIDs");
if (ownerSids.Count == 0)
throw new InvalidOperationException("Owner SIDs: mindestens ein Eintrag ist fuer die Ordneranlage erforderlich.");
return CreateWhatIfResult(
"NTFS Folder Create",
"Wuerde einen Ordner anlegen und fehlende Gruppen sowie ACLs sicherstellen. Es wurden keine Aenderungen ausgefuehrt.",
new
{
ProviderRootPath = provider.RootPath,
NewFolderPath = folderPath,
ParentFolderPath = parentPath,
OwnerSids = ownerSids,
ReaderSids = ParseIdentifierList(NtfsCreateReaderSidsTextBox.Text, "Reader SIDs"),
WriterSids = ParseIdentifierList(NtfsCreateWriterSidsTextBox.Text, "Writer SIDs")
});
});
}
@@ -607,20 +655,40 @@ namespace LiamWorkflowDiagnostics
{
var provider = EnsureInitializedProvider<cLiamProviderNtfs>("NTFS");
var folderPath = GetRequiredText(NtfsEnsureFolderPathTextBox.Text, "Folder Path");
var ownerSids = ParseIdentifierList(NtfsEnsureOwnerSidsTextBox.Text, "Owner SIDs");
var readerSids = ParseIdentifierList(NtfsEnsureReaderSidsTextBox.Text, "Reader SIDs");
var writerSids = ParseIdentifierList(NtfsEnsureWriterSidsTextBox.Text, "Writer SIDs");
var ensureTraverse = NtfsEnsureTraverseCheckBox.IsChecked ?? false;
var result = await LiamWorkflowRuntime.EnsureNtfsPermissionGroupsAsync(
provider,
folderPath,
null,
ParseIdentifierList(NtfsEnsureOwnerSidsTextBox.Text, "Owner SIDs"),
ParseIdentifierList(NtfsEnsureReaderSidsTextBox.Text, "Reader SIDs"),
ParseIdentifierList(NtfsEnsureWriterSidsTextBox.Text, "Writer SIDs"),
NtfsEnsureTraverseCheckBox.IsChecked ?? false);
ownerSids,
readerSids,
writerSids,
ensureTraverse);
return new
{
result.Success,
ResultToken = MapResultToken(result.ResultToken)
};
}, () =>
{
var provider = EnsureInitializedProvider<cLiamProviderNtfs>("NTFS");
var folderPath = GetRequiredText(NtfsEnsureFolderPathTextBox.Text, "Folder Path");
return CreateWhatIfResult(
"NTFS Ensure Groups / ACLs",
"Wuerde fehlende NTFS-Berechtigungsgruppen und ACLs additiv sicherstellen. Es wurden keine Aenderungen ausgefuehrt.",
new
{
ProviderRootPath = provider.RootPath,
FolderPath = folderPath,
OwnerSids = ParseIdentifierList(NtfsEnsureOwnerSidsTextBox.Text, "Owner SIDs"),
ReaderSids = ParseIdentifierList(NtfsEnsureReaderSidsTextBox.Text, "Reader SIDs"),
WriterSids = ParseIdentifierList(NtfsEnsureWriterSidsTextBox.Text, "Writer SIDs"),
EnsureTraverseGroups = NtfsEnsureTraverseCheckBox.IsChecked ?? false
});
});
}
@@ -650,6 +718,30 @@ namespace LiamWorkflowDiagnostics
memberSids));
return result;
}, () =>
{
_ = EnsureInitializedProvider<cLiamProviderAD>("Active Directory");
var serviceName = GetRequiredText(AdServiceNameTextBox.Text, "Service Name");
var description = NormalizeOptionalText(AdDescriptionTextBox.Text);
var scope = AdScopeComboBox.SelectedItem is eLiamAccessRoleScopes selectedScope
? selectedScope
: eLiamAccessRoleScopes.Universal;
var groupType = AdGroupTypeComboBox.SelectedItem is ADServiceGroupCreator.ADGroupType selectedType
? selectedType
: ADServiceGroupCreator.ADGroupType.Distribution;
return CreateWhatIfResult(
"AD Ensure Service Groups",
"Wuerde Service-Gruppen im Active Directory anhand der Namenskonvention sicherstellen. Es wurden keine Aenderungen ausgefuehrt.",
new
{
ServiceName = serviceName,
Description = description,
Scope = scope.ToString(),
GroupType = groupType.ToString(),
OwnerSids = ParseIdentifierList(AdOwnerSidsTextBox.Text, "Owner SIDs"),
MemberSids = ParseIdentifierList(AdMemberSidsTextBox.Text, "Member SIDs")
});
});
}
@@ -661,6 +753,8 @@ namespace LiamWorkflowDiagnostics
var sourceTeamId = GetRequiredText(MsTeamsSourceTeamIdTextBox.Text, "Source Team ID");
var newTeamName = GetRequiredText(MsTeamsNewNameTextBox.Text, "New Team Name");
var visibility = GetSelectedMsTeamsVisibility();
var additionalMembers = ParseIdentifierList(MsTeamsAdditionalMembersTextBox.Text, "Additional Members");
var additionalOwners = ParseIdentifierList(MsTeamsAdditionalOwnersTextBox.Text, "Additional Owners");
var result = await LiamWorkflowRuntime.CloneTeamAsync(
provider,
@@ -669,10 +763,29 @@ namespace LiamWorkflowDiagnostics
NormalizeOptionalText(MsTeamsDescriptionTextBox.Text),
visibility,
GetSelectedCloneParts(),
string.Join(";", ParseIdentifierList(MsTeamsAdditionalMembersTextBox.Text, "Additional Members")),
string.Join(";", ParseIdentifierList(MsTeamsAdditionalOwnersTextBox.Text, "Additional Owners")));
string.Join(";", additionalMembers),
string.Join(";", additionalOwners));
return result;
}, () =>
{
_ = EnsureInitializedProvider<cLiamProviderMsTeams>("MsTeams");
var sourceTeamId = GetRequiredText(MsTeamsSourceTeamIdTextBox.Text, "Source Team ID");
var newTeamName = GetRequiredText(MsTeamsNewNameTextBox.Text, "New Team Name");
return CreateWhatIfResult(
"MsTeams Clone Team",
"Wuerde ein Team anhand der gewaehlten Clone-Bestandteile klonen. Es wurden keine Aenderungen ausgefuehrt.",
new
{
SourceTeamId = sourceTeamId,
NewTeamName = newTeamName,
Description = NormalizeOptionalText(MsTeamsDescriptionTextBox.Text),
Visibility = GetSelectedMsTeamsVisibility(),
PartsToClone = GetSelectedCloneParts(),
AdditionalMembers = ParseIdentifierList(MsTeamsAdditionalMembersTextBox.Text, "Additional Members"),
AdditionalOwners = ParseIdentifierList(MsTeamsAdditionalOwnersTextBox.Text, "Additional Owners")
});
});
}
@@ -693,6 +806,19 @@ namespace LiamWorkflowDiagnostics
primarySmtp));
return result;
}, () =>
{
_ = EnsureInitializedProvider<cLiamProviderExchange>("Exchange");
return CreateWhatIfResult(
"Exchange Create Shared Mailbox",
"Wuerde eine Shared Mailbox inklusive Ownership-Gruppen erzeugen. Es wurden keine Aenderungen ausgefuehrt.",
new
{
Name = GetRequiredText(ExchangeMailboxNameTextBox.Text, "Name"),
Alias = GetRequiredText(ExchangeMailboxAliasTextBox.Text, "Alias"),
DisplayName = NormalizeOptionalText(ExchangeMailboxDisplayNameTextBox.Text),
PrimarySmtpAddress = NormalizeOptionalText(ExchangeMailboxPrimarySmtpTextBox.Text)
});
});
}
@@ -713,6 +839,19 @@ namespace LiamWorkflowDiagnostics
primarySmtp));
return result;
}, () =>
{
_ = EnsureInitializedProvider<cLiamProviderExchange>("Exchange");
return CreateWhatIfResult(
"Exchange Create Distribution Group",
"Wuerde eine Distribution Group inklusive Ownership-Gruppen erzeugen. Es wurden keine Aenderungen ausgefuehrt.",
new
{
Name = GetRequiredText(ExchangeDistributionNameTextBox.Text, "Name"),
Alias = GetRequiredText(ExchangeDistributionAliasTextBox.Text, "Alias"),
DisplayName = NormalizeOptionalText(ExchangeDistributionDisplayNameTextBox.Text),
PrimarySmtpAddress = NormalizeOptionalText(ExchangeDistributionPrimarySmtpTextBox.Text)
});
});
}
@@ -777,7 +916,7 @@ namespace LiamWorkflowDiagnostics
}
}
private async Task ExecuteProviderActionAsync(string actionName, Func<Task<object>> action)
private async Task ExecuteProviderActionAsync(string actionName, Func<Task<object>> action, Func<object> whatIfAction = null)
{
if (action == null)
throw new ArgumentNullException(nameof(action));
@@ -786,11 +925,18 @@ namespace LiamWorkflowDiagnostics
try
{
SaveSettings();
AppendLog($"{actionName} gestartet.");
var result = await action();
var runInWhatIfMode = IsWhatIfEnabled && whatIfAction != null;
AppendLog(runInWhatIfMode
? $"{actionName} im WhatIf-Modus gestartet. Schreibende Aenderungen werden nur simuliert."
: $"{actionName} gestartet.");
var result = runInWhatIfMode
? whatIfAction()
: await action();
ResultTextBox.Text = JsonConvert.SerializeObject(result, Formatting.Indented);
if (TryGetSuccessFlag(result, out var success) && !success)
AppendLog($"{actionName} mit Fehlerstatus abgeschlossen.", LogLevels.Warning);
else if (runInWhatIfMode)
AppendLog($"{actionName} im WhatIf-Modus simuliert abgeschlossen.", LogLevels.Warning);
else
AppendLog($"{actionName} erfolgreich abgeschlossen.");
}
@@ -823,6 +969,21 @@ namespace LiamWorkflowDiagnostics
return true;
}
private bool IsWhatIfEnabled => WhatIfCheckBox.IsChecked ?? true;
private object CreateWhatIfResult(string actionName, string message, object input)
{
return new
{
Success = true,
WhatIf = true,
Operation = actionName,
Message = message ?? string.Empty,
TimestampUtc = DateTime.UtcNow.ToString("s") + "Z",
Input = input
};
}
private TProvider EnsureInitializedProvider<TProvider>(string providerName) where TProvider : cLiamProviderBase
{
if (_session?.Provider == null)
@@ -1334,6 +1495,7 @@ namespace LiamWorkflowDiagnostics
public string ServerName { get; set; } = string.Empty;
public bool UseHttps { get; set; } = false;
public string License { get; set; } = string.Empty;
public bool EnableWhatIf { get; set; } = true;
public string NtfsCreateFolderPath { get; set; } = string.Empty;
public string NtfsCreateParentPath { get; set; } = string.Empty;
public string NtfsCreateOwnerSids { get; set; } = string.Empty;