fix: await NTFS ACL resolution for root data areas

This commit is contained in:
Meik
2026-03-09 09:11:31 +01:00
parent 9a20f3d1f0
commit e4b907856c
3 changed files with 452 additions and 432 deletions

View File

@@ -51,50 +51,50 @@ namespace LiamWorkflowActivities
internal IExtensionExecutor executor;
internal ISchemaReaderProvider schemaReader;
internal IDataReaderProvider dataProvider;
public static bool IsInitialized { get; private set; } = false;
private static Object initLock = new object();
protected string LastOperationErrorCode { get; private set; } = string.Empty;
protected string LastOperationErrorMessage { get; private set; } = string.Empty;
protected void ClearOperationError()
{
LastOperationErrorCode = string.Empty;
LastOperationErrorMessage = string.Empty;
}
protected void SetOperationError(string code, string message)
{
LastOperationErrorCode = string.IsNullOrWhiteSpace(code) ? "WF_OPERATION_FAILED" : code;
LastOperationErrorMessage = message ?? string.Empty;
LogEntry($"[{LastOperationErrorCode}] {LastOperationErrorMessage}", LogLevels.Error);
}
protected void SetOperationErrorFromProvider(cLiamProviderBase provider, string fallbackCode, string fallbackMessage)
{
if (provider is cLiamProviderExchange exProvider)
{
var code = exProvider.GetLastErrorCode();
var message = exProvider.GetLastErrorMessage();
if (!string.IsNullOrWhiteSpace(code) || !string.IsNullOrWhiteSpace(message))
{
SetOperationError(
string.IsNullOrWhiteSpace(code) ? fallbackCode : code,
string.IsNullOrWhiteSpace(message) ? fallbackMessage : message);
return;
}
}
var providerMessage = provider?.GetLastErrorMessage();
SetOperationError(
fallbackCode,
string.IsNullOrWhiteSpace(providerMessage) ? fallbackMessage : providerMessage);
}
protected void Initialize(NativeActivityContext context)
{
internal IDataReaderProvider dataProvider;
public static bool IsInitialized { get; private set; } = false;
private static Object initLock = new object();
protected string LastOperationErrorCode { get; private set; } = string.Empty;
protected string LastOperationErrorMessage { get; private set; } = string.Empty;
protected void ClearOperationError()
{
LastOperationErrorCode = string.Empty;
LastOperationErrorMessage = string.Empty;
}
protected void SetOperationError(string code, string message)
{
LastOperationErrorCode = string.IsNullOrWhiteSpace(code) ? "WF_OPERATION_FAILED" : code;
LastOperationErrorMessage = message ?? string.Empty;
LogEntry($"[{LastOperationErrorCode}] {LastOperationErrorMessage}", LogLevels.Error);
}
protected void SetOperationErrorFromProvider(cLiamProviderBase provider, string fallbackCode, string fallbackMessage)
{
if (provider is cLiamProviderExchange exProvider)
{
var code = exProvider.GetLastErrorCode();
var message = exProvider.GetLastErrorMessage();
if (!string.IsNullOrWhiteSpace(code) || !string.IsNullOrWhiteSpace(message))
{
SetOperationError(
string.IsNullOrWhiteSpace(code) ? fallbackCode : code,
string.IsNullOrWhiteSpace(message) ? fallbackMessage : message);
return;
}
}
var providerMessage = provider?.GetLastErrorMessage();
SetOperationError(
fallbackCode,
string.IsNullOrWhiteSpace(providerMessage) ? fallbackMessage : providerMessage);
}
protected void Initialize(NativeActivityContext context)
{
try
{
lock (initLock)
@@ -349,11 +349,11 @@ namespace LiamWorkflowActivities
});
}
}
var sanitizedJson = JsonConvert.SerializeObject(DataProviderData, Newtonsoft.Json.Formatting.Indented);
LogEntry("Provider configuration (sanitized JSON, copy for diagnostics tool):", LogLevels.Info);
LogEntry(sanitizedJson, LogLevels.Info);
DataProviderData.Credential.Secret = PW;
var DataProvider = CreateProviderInstance(new cLiamConfiguration(), DataProviderData);
var sanitizedJson = JsonConvert.SerializeObject(DataProviderData, Newtonsoft.Json.Formatting.Indented);
LogEntry("Provider configuration (sanitized JSON, copy for diagnostics tool):", LogLevels.Info);
LogEntry(sanitizedJson, LogLevels.Info);
DataProviderData.Credential.Secret = PW;
var DataProvider = CreateProviderInstance(new cLiamConfiguration(), DataProviderData);
return DataProvider;
@@ -398,45 +398,45 @@ namespace LiamWorkflowActivities
}
}
public async Task<IEnumerable<SecurityGroupEntry>> getSecurityGroupsFromProvider(Guid ProviderConfigClassID)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
ClearOperationError();
if (cC4ITLicenseM42ESM.Instance == null)
LoadLicensingInformation();
if (!cC4ITLicenseM42ESM.Instance.IsValid)
{
LogEntry($"Error: License not valid", LogLevels.Error);
SetOperationError("WF_GET_SECURITYGROUPS_LICENSE_INVALID", "License not valid");
return new List<SecurityGroupEntry>();
}
var ProviderEntry = getDataProvider(ProviderConfigClassID);
if (ProviderEntry == null)
{
LogEntry($"Could not initialize Provider config class with ID {ProviderConfigClassID}", LogLevels.Warning);
SetOperationError("WF_GET_SECURITYGROUPS_PROVIDER_NOT_FOUND", $"Could not initialize Provider config class with ID {ProviderConfigClassID}");
return null;
}
var lstSecurityGroups = await ProviderEntry.Provider.getSecurityGroupsAsync(ProviderEntry.Provider.GroupFilter);
if (lstSecurityGroups == null)
{
SetOperationErrorFromProvider(
ProviderEntry.Provider,
"WF_GET_SECURITYGROUPS_PROVIDER_CALL_FAILED",
"Provider returned null while reading security groups.");
return null;
}
if (lstSecurityGroups.Count == 0)
{
LogEntry($"No security groups found for Provider config class with ID {ProviderConfigClassID}", LogLevels.Warning);
return new List<SecurityGroupEntry>();
}
public async Task<IEnumerable<SecurityGroupEntry>> getSecurityGroupsFromProvider(Guid ProviderConfigClassID)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
ClearOperationError();
if (cC4ITLicenseM42ESM.Instance == null)
LoadLicensingInformation();
if (!cC4ITLicenseM42ESM.Instance.IsValid)
{
LogEntry($"Error: License not valid", LogLevels.Error);
SetOperationError("WF_GET_SECURITYGROUPS_LICENSE_INVALID", "License not valid");
return new List<SecurityGroupEntry>();
}
var ProviderEntry = getDataProvider(ProviderConfigClassID);
if (ProviderEntry == null)
{
LogEntry($"Could not initialize Provider config class with ID {ProviderConfigClassID}", LogLevels.Warning);
SetOperationError("WF_GET_SECURITYGROUPS_PROVIDER_NOT_FOUND", $"Could not initialize Provider config class with ID {ProviderConfigClassID}");
return null;
}
var lstSecurityGroups = await ProviderEntry.Provider.getSecurityGroupsAsync(ProviderEntry.Provider.GroupFilter);
if (lstSecurityGroups == null)
{
SetOperationErrorFromProvider(
ProviderEntry.Provider,
"WF_GET_SECURITYGROUPS_PROVIDER_CALL_FAILED",
"Provider returned null while reading security groups.");
return null;
}
if (lstSecurityGroups.Count == 0)
{
LogEntry($"No security groups found for Provider config class with ID {ProviderConfigClassID}", LogLevels.Warning);
return new List<SecurityGroupEntry>();
}
var SGs = new List<SecurityGroupEntry>();
foreach (var sg in lstSecurityGroups)
@@ -467,64 +467,64 @@ namespace LiamWorkflowActivities
SGs.Add(entry);
}
return SGs;
}
catch (Exception E)
{
LogException(E);
SetOperationError("WF_GET_SECURITYGROUPS_EXCEPTION", E.Message);
return null;
}
finally
{
LogMethodEnd(CM);
return SGs;
}
catch (Exception E)
{
LogException(E);
SetOperationError("WF_GET_SECURITYGROUPS_EXCEPTION", E.Message);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
public async Task<IEnumerable<DataAreaEntry>> getDataAreasFromProvider(Guid ProviderConfigClassID)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
ClearOperationError();
if (cC4ITLicenseM42ESM.Instance == null)
LoadLicensingInformation();
if (!cC4ITLicenseM42ESM.Instance.IsValid)
{
LogEntry($"Error: License not valid", LogLevels.Error);
SetOperationError("WF_GET_DATAAREAS_LICENSE_INVALID", "License not valid");
return new List<DataAreaEntry>();
}
var ProviderEntry = getDataProvider(ProviderConfigClassID);
if (ProviderEntry == null)
{
LogEntry($"Could not initialize Provider config class with ID {ProviderConfigClassID}", LogLevels.Warning);
SetOperationError("WF_GET_DATAAREAS_PROVIDER_NOT_FOUND", $"Could not initialize Provider config class with ID {ProviderConfigClassID}");
return null;
}
var lstDataAreas = await ProviderEntry.Provider.getDataAreasAsync(ProviderEntry.Provider.MaxDepth);
if (lstDataAreas == null)
{
SetOperationErrorFromProvider(
ProviderEntry.Provider,
"WF_GET_DATAAREAS_PROVIDER_CALL_FAILED",
"Provider returned null while reading data areas.");
return null;
}
if (lstDataAreas.Count <= 0)
{
LogEntry($"No data areas found for Provider config class with ID {ProviderConfigClassID}", LogLevels.Warning);
return new List<DataAreaEntry>();
}
public async Task<IEnumerable<DataAreaEntry>> getDataAreasFromProvider(Guid ProviderConfigClassID)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
ClearOperationError();
if (cC4ITLicenseM42ESM.Instance == null)
LoadLicensingInformation();
if (!cC4ITLicenseM42ESM.Instance.IsValid)
{
LogEntry($"Error: License not valid", LogLevels.Error);
SetOperationError("WF_GET_DATAAREAS_LICENSE_INVALID", "License not valid");
return new List<DataAreaEntry>();
}
var ProviderEntry = getDataProvider(ProviderConfigClassID);
if (ProviderEntry == null)
{
LogEntry($"Could not initialize Provider config class with ID {ProviderConfigClassID}", LogLevels.Warning);
SetOperationError("WF_GET_DATAAREAS_PROVIDER_NOT_FOUND", $"Could not initialize Provider config class with ID {ProviderConfigClassID}");
return null;
}
var lstDataAreas = await ProviderEntry.Provider.getDataAreasAsync(ProviderEntry.Provider.MaxDepth);
if (lstDataAreas == null)
{
SetOperationErrorFromProvider(
ProviderEntry.Provider,
"WF_GET_DATAAREAS_PROVIDER_CALL_FAILED",
"Provider returned null while reading data areas.");
return null;
}
if (lstDataAreas.Count <= 0)
{
LogEntry($"No data areas found for Provider config class with ID {ProviderConfigClassID}", LogLevels.Warning);
return new List<DataAreaEntry>();
}
return lstDataAreas
.Select(DataArea =>
{
var ntfs = DataArea as cLiamNtfsFolder;
var ntfsPermissionArea = DataArea as cLiamNtfsPermissionDataAreaBase;
var adGrp = DataArea as cLiamAdGroupAsDataArea;
var exchMB = DataArea as cLiamExchangeSharedMailbox;
var exchDL = DataArea as cLiamExchangeDistributionGroup;
@@ -537,7 +537,7 @@ namespace LiamWorkflowActivities
string owner = exchMB?.OwnerGroupIdentifier
?? exchDL?.OwnerGroupIdentifier
?? adGrp?.ManagedBySID
?? ntfs?.OwnerGroupIdentifier
?? ntfsPermissionArea?.OwnerGroupIdentifier
?? string.Empty;
// 2) WriteSID
@@ -548,9 +548,9 @@ namespace LiamWorkflowActivities
string write = exchMB != null
? exchMB.FullAccessGroupSid
: exchDL != null
? exchDL.MemberGroupSid
? exchDL.MemberGroupSid
: adGrp?.UID
?? ntfs?.WriteGroupIdentifier
?? ntfsPermissionArea?.WriteGroupIdentifier
?? string.Empty;
// 3) ReadSID
@@ -559,14 +559,14 @@ namespace LiamWorkflowActivities
// - NTFS-Folder: ReadGroupIdentifier
string read = exchMB != null
? exchMB.SendAsGroupSid
: ntfs?.ReadGroupIdentifier
: ntfsPermissionArea?.ReadGroupIdentifier
?? string.Empty;
// 4) Traverse nur NTFS-Folder
string traverse = ntfs?.TraverseGroupIdentifier ?? string.Empty;
// 4) Traverse nur NTFS-Objekte
string traverse = ntfsPermissionArea?.TraverseGroupIdentifier ?? string.Empty;
// 5) CreatedDate nur NTFS-Folder
string created = ntfs?.CreatedDate ?? DateTime.MinValue.ToString("o");
// 5) CreatedDate nur NTFS-Objekte
string created = ntfsPermissionArea?.CreatedDate ?? DateTime.MinValue.ToString("o");
// 6) Description: nur AD-Group
string desc = adGrp?.Description ?? string.Empty;
@@ -592,14 +592,14 @@ namespace LiamWorkflowActivities
})
.ToList();
}
catch (Exception E)
{
LogException(E);
SetOperationError("WF_GET_DATAAREAS_EXCEPTION", E.Message);
return null;
}
finally
{
catch (Exception E)
{
LogException(E);
SetOperationError("WF_GET_DATAAREAS_EXCEPTION", E.Message);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
@@ -970,32 +970,32 @@ namespace LiamWorkflowActivities
return false;
}
// Auf den konkreten Exchange-Provider casten
if (providerEntry.Provider is cLiamProviderExchange exProv)
{
// Aufruf der Methode im Provider
var result = exProv.exchangeManager.CreateDistributionGroupWithOwnershipGroups(
name,
alias,
displayName,
primarySmtpAddress,
out string errorCode,
out string errorMessage
);
if (result == null)
{
LogEntry(
$"createDistributionGroup failed [{errorCode}] {errorMessage}",
LogLevels.Error);
return false;
}
LogEntry(
$"createDistributionGroup succeeded. ObjectGuid='{result.Item1}', GroupCount='{result.Item2?.Count ?? 0}'",
LogLevels.Info);
return true;
}
// Auf den konkreten Exchange-Provider casten
if (providerEntry.Provider is cLiamProviderExchange exProv)
{
// Aufruf der Methode im Provider
var result = exProv.exchangeManager.CreateDistributionGroupWithOwnershipGroups(
name,
alias,
displayName,
primarySmtpAddress,
out string errorCode,
out string errorMessage
);
if (result == null)
{
LogEntry(
$"createDistributionGroup failed [{errorCode}] {errorMessage}",
LogLevels.Error);
return false;
}
LogEntry(
$"createDistributionGroup succeeded. ObjectGuid='{result.Item1}', GroupCount='{result.Item2?.Count ?? 0}'",
LogLevels.Info);
return true;
}
LogEntry($"Provider is not a cLiamProviderExchange, but {providerEntry.Provider.GetType().Name}", LogLevels.Warning);
return false;
@@ -1043,32 +1043,32 @@ namespace LiamWorkflowActivities
return false;
}
// Auf den konkreten Exchange-Provider casten
if (providerEntry.Provider is cLiamProviderExchange exProv)
{
// Aufruf der Methode im Provider
var result = exProv.exchangeManager.CreateSharedMailboxWithOwnershipGroups(
name,
alias,
displayName,
primarySmtpAddress,
out string errorCode,
out string errorMessage
);
if (result == null)
{
LogEntry(
$"createSharedMailbox failed [{errorCode}] {errorMessage}",
LogLevels.Error);
return false;
}
LogEntry(
$"createSharedMailbox succeeded. ObjectGuid='{result.Item1}', GroupCount='{result.Item2?.Count ?? 0}'",
LogLevels.Info);
return true;
}
// Auf den konkreten Exchange-Provider casten
if (providerEntry.Provider is cLiamProviderExchange exProv)
{
// Aufruf der Methode im Provider
var result = exProv.exchangeManager.CreateSharedMailboxWithOwnershipGroups(
name,
alias,
displayName,
primarySmtpAddress,
out string errorCode,
out string errorMessage
);
if (result == null)
{
LogEntry(
$"createSharedMailbox failed [{errorCode}] {errorMessage}",
LogLevels.Error);
return false;
}
LogEntry(
$"createSharedMailbox succeeded. ObjectGuid='{result.Item1}', GroupCount='{result.Item2?.Count ?? 0}'",
LogLevels.Info);
return true;
}
LogEntry($"Provider is not a cLiamProviderExchange, but {providerEntry.Provider.GetType().Name}", LogLevels.Warning);
return false;