chore: sync LIAM solution snapshot incl. diagnostics tooling

- update multiple LIAM projects and solution/config files

- add LiamWorkflowDiagnostics app sources and generated outputs

- include current workspace state (dependencies and build outputs)
This commit is contained in:
Meik
2026-02-27 09:12:34 +01:00
parent f563d78417
commit 3d4f60d83e
721 changed files with 936335 additions and 653393 deletions

31
AGENTS.md Normal file
View File

@@ -0,0 +1,31 @@
# Repository Guidelines
## Project Structure & Module Organization
The solution `LIAM.sln` covers all Matrix42 integration projects. Runtime code centers on `LiamM42WebApi` (service endpoints), `LiamWorkflowActivities*` (workflow logic and designers), and adapters such as `LiamActiveDirectory`, `LiamExchange`, and `LiamMsTeams`. Shared helpers live in `LiamBaseClasses` and `LiamHelper`. The `_shared` directory pins required third-party binaries; do not modify or rename them. NuGet restore artifacts belong in `packages/`, and the WinForms tooling `LiamTestTeams` supports manual verification.
## Build, Test, and Development Commands
Run `nuget restore LIAM.sln` once per clone to hydrate packages. Build locally with `msbuild LIAM.sln /p:Configuration=Debug`; use `Release` for deployable artifacts. For a clean rebuild, execute `msbuild LIAM.sln /t:Clean,Build /p:Configuration=Debug`. Visual Studio can open `LIAM.sln`, with `LiamM42WebApi` as the suggested startup project. When self-hosting the API, deploy it to IIS or IIS Express pointing at the project folder.
## Coding Style & Naming Conventions
Follow C# Allman braces with four-space indentation. Maintain `PascalCase` for classes, members, and constants (e.g., `constFragmentNameConfigProviderBase`), and `camelCase` for locals and parameters. Keep `using` directives sorted and trimmed. New projects should link `SharedAssemblyInfo.cs` to align assembly metadata. Format via Visual Studio or `dotnet format` if the SDK is available.
## Testing Guidelines
Automated tests are currently absent; regression work relies on targeted manual runs. Use `LiamTestTeams` to drive Microsoft Teams scenarios and validate API calls. Document manual steps in pull requests until automated coverage is added. When introducing tests, co-locate them with the feature project and add the project to `LIAM.sln` so CI can call the standard `msbuild` targets.
## Commit & Pull Request Guidelines
History is minimal (`initial`), so prefer concise, imperative commit subjects and reference tracking IDs when applicable (e.g., `Add Graph delta sync for users (LIAM-123)`). Squash tooling-only commits before merge. Pull requests should note the impacted integration area, configuration changes, and manual verification evidence (logs, screenshots, or request IDs). Confirm no secrets are included and request review from the owner of each touched module.
### Mandatory Workflow Rules
- Before making any code change, the working tree must be clean (`git diff` and `git diff --cached` must be empty).
- If the working tree is not clean before starting, stop and clarify with the requester before proceeding.
- After completing a requested code change, always create a commit with a concise, imperative message.
## Security & Configuration Tips
Exclude environment-specific `web.config`, `app.config`, and credential artifacts from version control. Treat binaries under `_shared` as read-only dependencies. When updating external references, confirm compatibility with the target Matrix42 environment and record the expected deployment steps in the PR.***

View File

@@ -39,6 +39,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiamActiveDirectory", "LIAM
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiamExchange", "LiamExchange\LiamExchange.csproj", "{12586A29-BB1E-49B4-B971-88E520D6A77C}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiamExchange", "LiamExchange\LiamExchange.csproj", "{12586A29-BB1E-49B4-B971-88E520D6A77C}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiamWorkflowDiagnostics", "LiamWorkflowDiagnostics\LiamWorkflowDiagnostics.csproj", "{2D7FADB7-3F21-4D4F-9A60-639746F1B1B1}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug_and_copy|Any CPU = Debug_and_copy|Any CPU Debug_and_copy|Any CPU = Debug_and_copy|Any CPU
@@ -112,6 +114,12 @@ Global
{12586A29-BB1E-49B4-B971-88E520D6A77C}.Debug|Any CPU.Build.0 = Debug|Any CPU {12586A29-BB1E-49B4-B971-88E520D6A77C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{12586A29-BB1E-49B4-B971-88E520D6A77C}.Release|Any CPU.ActiveCfg = Release|Any CPU {12586A29-BB1E-49B4-B971-88E520D6A77C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{12586A29-BB1E-49B4-B971-88E520D6A77C}.Release|Any CPU.Build.0 = Release|Any CPU {12586A29-BB1E-49B4-B971-88E520D6A77C}.Release|Any CPU.Build.0 = Release|Any CPU
{2D7FADB7-3F21-4D4F-9A60-639746F1B1B1}.Debug_and_copy|Any CPU.ActiveCfg = Debug|Any CPU
{2D7FADB7-3F21-4D4F-9A60-639746F1B1B1}.Debug_and_copy|Any CPU.Build.0 = Debug|Any CPU
{2D7FADB7-3F21-4D4F-9A60-639746F1B1B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D7FADB7-3F21-4D4F-9A60-639746F1B1B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D7FADB7-3F21-4D4F-9A60-639746F1B1B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D7FADB7-3F21-4D4F-9A60-639746F1B1B1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -51,6 +51,9 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="cActiveDirectoryBase.cs" /> <Compile Include="cActiveDirectoryBase.cs" />
<Compile Include="C4IT.LIAM.AD.cs" /> <Compile Include="C4IT.LIAM.AD.cs" />
<Compile Include="cADBase.cs" /> <Compile Include="cADBase.cs" />

View File

@@ -5,13 +5,9 @@ using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("LIAMActiveDirectory")] [assembly: AssemblyTitle("LIAM AD Module")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LIAMActiveDirectory")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible // Setting ComVisible to false makes the types in this assembly not visible
@@ -21,16 +17,3 @@ using System.Runtime.InteropServices;
// The following GUID is for the ID of the typelib if this project is exposed to COM // The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("aeca0ad2-8b91-4767-9afa-e160f6662dbe")] [assembly: Guid("aeca0ad2-8b91-4767-9afa-e160f6662dbe")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -12,3 +12,17 @@ C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Debug\LiamActiveD
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.pdb C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.pdb
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\System.ValueTuple.dll C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\System.ValueTuple.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\System.ValueTuple.xml C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\System.ValueTuple.xml
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\LiamActiveDirectory.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\LiamActiveDirectory.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\LiamBaseClasses.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\LiamHelper.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\System.ValueTuple.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\Newtonsoft.Json.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\LiamBaseClasses.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\LiamHelper.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\System.ValueTuple.xml
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.csproj.AssemblyReference.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.csproj.CoreCompileInputs.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Debug\LiamActi.8091FDFC.Up2Date
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.pdb

View File

@@ -1 +1 @@
88ca960765b758a5c4edcddedf6dc811f2a49d840cd7ade015d7644911a99c77 0f439131d442d0ee4d6473d1fe79783624433c39a44374a60e15e079e468a4be

View File

@@ -12,3 +12,17 @@ C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Release\LIAMActiv
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Release\LiamActi.8091FDFC.Up2Date C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Release\LiamActi.8091FDFC.Up2Date
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\System.ValueTuple.dll C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\System.ValueTuple.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\System.ValueTuple.xml C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\System.ValueTuple.xml
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Release\LiamActiveDirectory.csproj.AssemblyReference.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Release\LiamActiveDirectory.csproj.CoreCompileInputs.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Release\LiamActiveDirectory.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Release\LiamActiveDirectory.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\LiamActiveDirectory.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\LiamActiveDirectory.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\LiamBaseClasses.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\LiamHelper.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\System.ValueTuple.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\Newtonsoft.Json.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\LiamBaseClasses.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\LiamHelper.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\System.ValueTuple.xml
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Release\LiamActi.8091FDFC.Up2Date

View File

@@ -1 +1 @@
ab9bb136583040c5ab0b8fc2b80edba3f154caa1532f30973b39973f0def47e6 e6f9f5153aa55a3a910f7c5ef0287e4500a3f354c3a1c3198c24d7eea04e0de2

View File

@@ -1 +1 @@
3908855f9633bf09d020c2efbd1fa153a9ad8a91b6e76b39255ee0403b9907f8 d0283af9d4075f4a557253c483f33e9a0d4fae295f6ce748fa39a1e639aafbb6

View File

@@ -8,3 +8,13 @@ C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Debug\LiamBaseClasses
C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Debug\LiamBase.24B0A51E.Up2Date C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Debug\LiamBase.24B0A51E.Up2Date
C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Debug\LiamBaseClasses.dll C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Debug\LiamBaseClasses.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Debug\LiamBaseClasses.pdb C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Debug\LiamBaseClasses.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\bin\Debug\LiamBaseClasses.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\bin\Debug\LiamBaseClasses.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\bin\Debug\LiamHelper.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\bin\Debug\Newtonsoft.Json.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\bin\Debug\LiamHelper.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\obj\Debug\LiamBaseClasses.csproj.AssemblyReference.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\obj\Debug\LiamBaseClasses.csproj.CoreCompileInputs.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\obj\Debug\LiamBase.24B0A51E.Up2Date
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\obj\Debug\LiamBaseClasses.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\obj\Debug\LiamBaseClasses.pdb

View File

@@ -1 +1 @@
77f86ea35cc63f1fe117fbff3ddf1a527617a8ddb75413eb5ef7f6b4cf6c8399 135510e8387d9e004d20f72096af679b01eba0ea20db7534ef81cc95461b16c6

View File

@@ -8,3 +8,13 @@ C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Release\LiamBaseClass
C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Release\LiamBase.24B0A51E.Up2Date C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Release\LiamBase.24B0A51E.Up2Date
C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Release\LiamBaseClasses.dll C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Release\LiamBaseClasses.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Release\LiamBaseClasses.pdb C:\Workspace\C4IT DEV LIAM WEB Service\LiamBaseClasses\obj\Release\LiamBaseClasses.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\bin\Release\LiamBaseClasses.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\bin\Release\LiamBaseClasses.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\bin\Release\LiamHelper.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\bin\Release\Newtonsoft.Json.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\bin\Release\LiamHelper.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\obj\Release\LiamBaseClasses.csproj.AssemblyReference.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\obj\Release\LiamBaseClasses.csproj.CoreCompileInputs.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\obj\Release\LiamBase.24B0A51E.Up2Date
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\obj\Release\LiamBaseClasses.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamBaseClasses\obj\Release\LiamBaseClasses.pdb

View File

@@ -26,6 +26,7 @@ namespace C4IT.LIAM
private string exchangeUri; private string exchangeUri;
private PSCredential credential; private PSCredential credential;
private string organizationalUnit; private string organizationalUnit;
private string lastErrorCode = string.Empty;
private string lastErrorMessage; private string lastErrorMessage;
private bool isLoggedOn = false; private bool isLoggedOn = false;
@@ -81,44 +82,73 @@ namespace C4IT.LIAM
return value?.ToString() ?? string.Empty; return value?.ToString() ?? string.Empty;
} }
public string GetLastErrorCode()
{
return lastErrorCode;
}
private void ClearLastError()
{
lastErrorCode = string.Empty;
lastErrorMessage = string.Empty;
}
private void SetLastError(string code, string message)
{
lastErrorCode = string.IsNullOrWhiteSpace(code) ? "EXCH_UNKNOWN_ERROR" : code;
lastErrorMessage = message ?? string.Empty;
LogEntry($"[{lastErrorCode}] {lastErrorMessage}", LogLevels.Error);
}
public override async Task<bool> LogonAsync() public override async Task<bool> LogonAsync()
{ {
var CM = MethodBase.GetCurrentMethod(); var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM); LogMethodBegin(CM);
try try
{ {
ClearLastError();
if (!cC4ITLicenseM42ESM.Instance.IsValid) if (!cC4ITLicenseM42ESM.Instance.IsValid)
{ {
LogEntry("Error: License not valid or Exchange module not licensed", LogLevels.Error); SetLastError("EXCH_LOGON_LICENSE_INVALID", "License not valid or Exchange module not licensed");
lastErrorMessage = "License not valid or Exchange module not licensed";
return false; return false;
} }
try try
{ {
var testMailboxes = exchangeManager.GetSharedMailboxes("Name -like '*'"); var testMailboxes = exchangeManager.GetSharedMailboxes(
"Name -like '*'",
out string errorCode,
out string errorMessage);
if (testMailboxes == null)
{
SetLastError(errorCode, $"Failed to connect to Exchange: {errorMessage}");
isLoggedOn = false;
return false;
}
if (testMailboxes != null) if (testMailboxes != null)
{ {
LogEntry("Successfully connected to Exchange", LogLevels.Info); LogEntry("Successfully connected to Exchange", LogLevels.Info);
isLoggedOn = true; isLoggedOn = true;
ClearLastError();
return true; return true;
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
LogException(ex); LogException(ex);
lastErrorMessage = $"Failed to connect to Exchange: {ex.Message}"; SetLastError("EXCH_LOGON_EXCEPTION", $"Failed to connect to Exchange: {ex.Message}");
isLoggedOn = false; isLoggedOn = false;
return false; return false;
} }
lastErrorMessage = "Unknown error connecting to Exchange"; SetLastError("EXCH_LOGON_FAILED", "Unknown error connecting to Exchange");
return false; return false;
} }
catch (Exception E) catch (Exception E)
{ {
LogException(E); LogException(E);
lastErrorMessage = $"Exception during Exchange logon: {E.Message}"; SetLastError("EXCH_LOGON_EXCEPTION", $"Exception during Exchange logon: {E.Message}");
return false; return false;
} }
finally finally
@@ -138,9 +168,10 @@ namespace C4IT.LIAM
LogMethodBegin(CM); LogMethodBegin(CM);
try try
{ {
ClearLastError();
if (!cC4ITLicenseM42ESM.Instance.IsValid) if (!cC4ITLicenseM42ESM.Instance.IsValid)
{ {
LogEntry("Error: License not valid or Exchange module not licensed", LogLevels.Error); SetLastError("EXCH_GET_DATAAREAS_LICENSE_INVALID", "License not valid or Exchange module not licensed");
return new List<cLiamDataAreaBase>(); return new List<cLiamDataAreaBase>();
} }
@@ -150,59 +181,65 @@ namespace C4IT.LIAM
var DataAreas = new List<cLiamDataAreaBase>(); var DataAreas = new List<cLiamDataAreaBase>();
// Shared Mailboxes // Shared Mailboxes
try var sharedMailboxes = exchangeManager.GetSharedMailboxes(
null,
out string sharedErrorCode,
out string sharedErrorMessage);
if (sharedMailboxes == null)
{ {
var sharedMailboxes = exchangeManager.GetSharedMailboxes(); SetLastError(sharedErrorCode, $"Failed to read shared mailboxes: {sharedErrorMessage}");
foreach (var mailbox in sharedMailboxes) return null;
{
var displayName = mailbox.Properties["DisplayName"]?.Value?.ToString();
var alias = mailbox.Properties["Alias"]?.Value?.ToString();
var primarySmtpAddress = mailbox.Properties["PrimarySmtpAddress"]?.Value?.ToString();
var objectGuid = ExtractObjectGuid(mailbox.Properties);
// Filterung via Regex
if (!string.IsNullOrEmpty(this.DataAreaRegEx) &&
!Regex.Match(displayName, this.DataAreaRegEx).Success)
continue;
var exchangeMailbox = new cLiamExchangeSharedMailbox(this, displayName, primarySmtpAddress, alias, objectGuid);
DataAreas.Add(exchangeMailbox);
}
} }
catch (Exception ex)
foreach (var mailbox in sharedMailboxes)
{ {
LogException(ex); var displayName = mailbox.Properties["DisplayName"]?.Value?.ToString();
var alias = mailbox.Properties["Alias"]?.Value?.ToString();
var primarySmtpAddress = mailbox.Properties["PrimarySmtpAddress"]?.Value?.ToString();
var objectGuid = ExtractObjectGuid(mailbox.Properties);
// Filterung via Regex
if (!string.IsNullOrEmpty(this.DataAreaRegEx) &&
!Regex.Match(displayName, this.DataAreaRegEx).Success)
continue;
var exchangeMailbox = new cLiamExchangeSharedMailbox(this, displayName, primarySmtpAddress, alias, objectGuid);
DataAreas.Add(exchangeMailbox);
} }
// Distribution Groups // Distribution Groups
try var distributionGroups = exchangeManager.GetDistributionGroups(
null,
out string distErrorCode,
out string distErrorMessage);
if (distributionGroups == null)
{ {
var distributionGroups = exchangeManager.GetDistributionGroups(); SetLastError(distErrorCode, $"Failed to read distribution groups: {distErrorMessage}");
foreach (var group in distributionGroups) return null;
{
var displayName = group.Properties["DisplayName"]?.Value?.ToString();
var alias = group.Properties["Alias"]?.Value?.ToString();
var primarySmtpAddress = group.Properties["PrimarySmtpAddress"]?.Value?.ToString();
var objectGuid = ExtractObjectGuid(group.Properties);
if (!string.IsNullOrEmpty(this.DataAreaRegEx) &&
!Regex.Match(displayName, this.DataAreaRegEx).Success)
continue;
var exchangeGroup = new cLiamExchangeDistributionGroup(this, displayName, primarySmtpAddress, alias, objectGuid);
DataAreas.Add(exchangeGroup);
}
}
catch (Exception ex)
{
LogException(ex);
} }
foreach (var group in distributionGroups)
{
var displayName = group.Properties["DisplayName"]?.Value?.ToString();
var alias = group.Properties["Alias"]?.Value?.ToString();
var primarySmtpAddress = group.Properties["PrimarySmtpAddress"]?.Value?.ToString();
var objectGuid = ExtractObjectGuid(group.Properties);
if (!string.IsNullOrEmpty(this.DataAreaRegEx) &&
!Regex.Match(displayName, this.DataAreaRegEx).Success)
continue;
var exchangeGroup = new cLiamExchangeDistributionGroup(this, displayName, primarySmtpAddress, alias, objectGuid);
DataAreas.Add(exchangeGroup);
}
ClearLastError();
return DataAreas; return DataAreas;
} }
catch (Exception E) catch (Exception E)
{ {
LogException(E); LogException(E);
SetLastError("EXCH_GET_DATAAREAS_EXCEPTION", E.Message);
} }
finally finally
{ {
@@ -258,9 +295,10 @@ namespace C4IT.LIAM
LogMethodBegin(CM); LogMethodBegin(CM);
try try
{ {
ClearLastError();
if (!cC4ITLicenseM42ESM.Instance.IsValid) if (!cC4ITLicenseM42ESM.Instance.IsValid)
{ {
LogEntry("Error: License not valid or Exchange module not licensed", LogLevels.Error); SetLastError("EXCH_GET_SECURITYGROUPS_LICENSE_INVALID", "License not valid or Exchange module not licensed");
return new List<cLiamDataAreaBase>(); return new List<cLiamDataAreaBase>();
} }
@@ -268,33 +306,38 @@ namespace C4IT.LIAM
return null; return null;
var securityGroups = new List<cLiamDataAreaBase>(); var securityGroups = new List<cLiamDataAreaBase>();
try var groups = exchangeManager.GetSecurityGroups(
groupFilter,
out string errorCode,
out string errorMessage);
if (groups == null)
{ {
var groups = exchangeManager.GetSecurityGroups(groupFilter); SetLastError(errorCode, $"Failed to read security groups: {errorMessage}");
foreach (var group in groups) return null;
{
var displayName = group.Properties["DisplayName"]?.Value?.ToString();
var sid = group.Properties["Sid"]?.Value?.ToString();
var dn = group.Properties["DistinguishedName"]?.Value?.ToString();
var objectGuid = ExtractObjectGuid(group.Properties);
if (!string.IsNullOrEmpty(this.GroupRegEx) &&
!Regex.Match(displayName, this.GroupRegEx).Success)
continue;
var securityGroup = new cLiamExchangeSecurityGroup(this, displayName, sid, dn, objectGuid);
securityGroups.Add(securityGroup);
}
} }
catch (Exception ex)
foreach (var group in groups)
{ {
LogException(ex); var displayName = group.Properties["DisplayName"]?.Value?.ToString();
var sid = group.Properties["Sid"]?.Value?.ToString();
var dn = group.Properties["DistinguishedName"]?.Value?.ToString();
var objectGuid = ExtractObjectGuid(group.Properties);
if (!string.IsNullOrEmpty(this.GroupRegEx) &&
!Regex.Match(displayName, this.GroupRegEx).Success)
continue;
var securityGroup = new cLiamExchangeSecurityGroup(this, displayName, sid, dn, objectGuid);
securityGroups.Add(securityGroup);
} }
ClearLastError();
return securityGroups; return securityGroups;
} }
catch (Exception E) catch (Exception E)
{ {
LogException(E); LogException(E);
SetLastError("EXCH_GET_SECURITYGROUPS_EXCEPTION", E.Message);
} }
finally finally
{ {

View File

@@ -13,6 +13,7 @@ using System.DirectoryServices.ActiveDirectory;
using System.DirectoryServices; using System.DirectoryServices;
using System.ComponentModel; using System.ComponentModel;
using System.Security.AccessControl; using System.Security.AccessControl;
using System.Threading;
namespace C4IT.LIAM namespace C4IT.LIAM
{ {
@@ -21,6 +22,8 @@ namespace C4IT.LIAM
/// </summary> /// </summary>
public partial class ExchangeManager public partial class ExchangeManager
{ {
private static readonly TimeSpan RunspaceOpenTimeout = TimeSpan.FromSeconds(30);
private readonly cLiamProviderBase _provider; private readonly cLiamProviderBase _provider;
private readonly string _exchangeUri; private readonly string _exchangeUri;
private readonly PSCredential _credential; private readonly PSCredential _credential;
@@ -57,7 +60,35 @@ namespace C4IT.LIAM
connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Kerberos; connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Kerberos;
var runspace = RunspaceFactory.CreateRunspace(connectionInfo); var runspace = RunspaceFactory.CreateRunspace(connectionInfo);
runspace.Open(); LogEntry($"Opening Exchange runspace (timeout: {RunspaceOpenTimeout.TotalSeconds:0}s) for endpoint '{_exchangeUri}'", LogLevels.Debug);
IAsyncResult openResult = null;
try
{
openResult = runspace.BeginOpen(null, null);
if (!openResult.AsyncWaitHandle.WaitOne(RunspaceOpenTimeout))
{
try
{
runspace.Dispose();
}
catch (Exception disposeEx)
{
LogException(disposeEx);
}
throw new TimeoutException(
$"Timeout while opening Exchange runspace after {RunspaceOpenTimeout.TotalSeconds:0} seconds.");
}
runspace.EndOpen(openResult);
}
finally
{
openResult?.AsyncWaitHandle?.Close();
}
LogEntry("Exchange runspace opened successfully", LogLevels.Debug);
return runspace; return runspace;
} }
catch (Exception ex) catch (Exception ex)
@@ -223,8 +254,20 @@ namespace C4IT.LIAM
/// Gets all shared mailboxes matching an optional filter /// Gets all shared mailboxes matching an optional filter
/// </summary> /// </summary>
public IEnumerable<PSObject> GetSharedMailboxes(string filter = null) public IEnumerable<PSObject> GetSharedMailboxes(string filter = null)
{
var result = GetSharedMailboxes(filter, out _, out _);
return result ?? Enumerable.Empty<PSObject>();
}
/// <summary>
/// Gets all shared mailboxes matching an optional filter.
/// Returns null on failure and exposes an error code/message.
/// </summary>
public IEnumerable<PSObject> GetSharedMailboxes(string filter, out string errorCode, out string errorMessage)
{ {
LogMethodBegin(MethodBase.GetCurrentMethod()); LogMethodBegin(MethodBase.GetCurrentMethod());
errorCode = "OK";
errorMessage = string.Empty;
try try
{ {
using (var runspace = CreateRunspace()) using (var runspace = CreateRunspace())
@@ -238,13 +281,22 @@ namespace C4IT.LIAM
{ {
ps.AddParameter("Filter", filter); ps.AddParameter("Filter", filter);
} }
return ps.Invoke(); return InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-Mailbox SharedMailbox filter='{filter ?? string.Empty}'");
} }
} }
catch (TimeoutException ex)
{
LogException(ex);
errorCode = "EXCH_GET_SHAREDMAILBOXES_TIMEOUT";
errorMessage = ex.Message;
return null;
}
catch (Exception ex) catch (Exception ex)
{ {
LogException(ex); LogException(ex);
return Enumerable.Empty<PSObject>(); errorCode = "EXCH_GET_SHAREDMAILBOXES_FAILED";
errorMessage = ex.Message;
return null;
} }
finally finally
{ {
@@ -268,7 +320,7 @@ namespace C4IT.LIAM
.AddParameter("RecipientTypeDetails", "SharedMailbox") .AddParameter("RecipientTypeDetails", "SharedMailbox")
.AddParameter("PrimarySmtpAddress", primarySmtpAddress); .AddParameter("PrimarySmtpAddress", primarySmtpAddress);
var results = ps.Invoke(); var results = InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-Mailbox SharedMailbox address='{primarySmtpAddress}'");
return results.Count > 0 ? results[0] : null; return results.Count > 0 ? results[0] : null;
} }
} }
@@ -287,8 +339,20 @@ namespace C4IT.LIAM
/// Gets all distribution groups matching an optional filter /// Gets all distribution groups matching an optional filter
/// </summary> /// </summary>
public IEnumerable<PSObject> GetDistributionGroups(string filter = null) public IEnumerable<PSObject> GetDistributionGroups(string filter = null)
{
var result = GetDistributionGroups(filter, out _, out _);
return result ?? Enumerable.Empty<PSObject>();
}
/// <summary>
/// Gets all distribution groups matching an optional filter.
/// Returns null on failure and exposes an error code/message.
/// </summary>
public IEnumerable<PSObject> GetDistributionGroups(string filter, out string errorCode, out string errorMessage)
{ {
LogMethodBegin(MethodBase.GetCurrentMethod()); LogMethodBegin(MethodBase.GetCurrentMethod());
errorCode = "OK";
errorMessage = string.Empty;
try try
{ {
using (var runspace = CreateRunspace()) using (var runspace = CreateRunspace())
@@ -301,13 +365,22 @@ namespace C4IT.LIAM
{ {
ps.AddParameter("Filter", filter); ps.AddParameter("Filter", filter);
} }
return ps.Invoke(); return InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-DistributionGroup filter='{filter ?? string.Empty}'");
} }
} }
catch (TimeoutException ex)
{
LogException(ex);
errorCode = "EXCH_GET_DISTRIBUTIONGROUPS_TIMEOUT";
errorMessage = ex.Message;
return null;
}
catch (Exception ex) catch (Exception ex)
{ {
LogException(ex); LogException(ex);
return Enumerable.Empty<PSObject>(); errorCode = "EXCH_GET_DISTRIBUTIONGROUPS_FAILED";
errorMessage = ex.Message;
return null;
} }
finally finally
{ {
@@ -331,7 +404,7 @@ namespace C4IT.LIAM
ps.AddCommand("Get-DistributionGroup") ps.AddCommand("Get-DistributionGroup")
.AddParameter("PrimarySmtpAddress", primarySmtpAddress); .AddParameter("PrimarySmtpAddress", primarySmtpAddress);
var results = ps.Invoke(); var results = InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-DistributionGroup address='{primarySmtpAddress}'");
return results.Count > 0 ? results[0] : null; return results.Count > 0 ? results[0] : null;
} }
} }
@@ -358,8 +431,9 @@ namespace C4IT.LIAM
// alle Members des DL holen // alle Members des DL holen
ps.AddCommand("Get-DistributionGroupMember") ps.AddCommand("Get-DistributionGroupMember")
.AddParameter("Identity", distributionListIdentity) .AddParameter("Identity", distributionListIdentity)
.AddParameter("ResultSize", "Unlimited"); .AddParameter("ResultSize", "Unlimited")
var members = ps.Invoke(); .AddParameter("ErrorAction", "Stop");
var members = InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-DistributionGroupMember '{distributionListIdentity}'");
if (ps.HadErrors || members.Count == 0) if (ps.HadErrors || members.Count == 0)
return Enumerable.Empty<PSObject>(); return Enumerable.Empty<PSObject>();
@@ -499,8 +573,9 @@ namespace C4IT.LIAM
{ {
ps.Runspace = runspace; ps.Runspace = runspace;
ps.AddCommand("Get-ADPermission") ps.AddCommand("Get-ADPermission")
.AddParameter("Identity", mailboxIdentity); .AddParameter("Identity", mailboxIdentity)
var perms = ps.Invoke(); .AddParameter("ErrorAction", "Stop");
var perms = InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-ADPermission (SendAsGroups) '{mailboxIdentity}'");
if (ps.HadErrors || perms.Count == 0) if (ps.HadErrors || perms.Count == 0)
return Enumerable.Empty<PSObject>(); return Enumerable.Empty<PSObject>();
@@ -595,8 +670,9 @@ namespace C4IT.LIAM
// 1) Alle FullAccess-Berechtigungen für das Postfach holen // 1) Alle FullAccess-Berechtigungen für das Postfach holen
ps.AddCommand("Get-MailboxPermission") ps.AddCommand("Get-MailboxPermission")
.AddParameter("Identity", mailboxIdentity); .AddParameter("Identity", mailboxIdentity)
var perms = ps.Invoke(); .AddParameter("ErrorAction", "Stop");
var perms = InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-MailboxPermission (FullAccessGroups) '{mailboxIdentity}'");
if (ps.HadErrors || perms.Count == 0) if (ps.HadErrors || perms.Count == 0)
return Enumerable.Empty<PSObject>(); return Enumerable.Empty<PSObject>();
@@ -731,8 +807,20 @@ namespace C4IT.LIAM
/// Nutzt hierfür die übergebenen Anmeldeinformationen. /// Nutzt hierfür die übergebenen Anmeldeinformationen.
/// </summary> /// </summary>
public IEnumerable<PSObject> GetSecurityGroups(string nameWildcard) public IEnumerable<PSObject> GetSecurityGroups(string nameWildcard)
{
var result = GetSecurityGroups(nameWildcard, out _, out _);
return result ?? new List<PSObject>();
}
/// <summary>
/// Sucht im angegebenen ADDomain/OU nach SecurityGruppen, deren Name zum Wildcard passt.
/// Returns null on failure and exposes an error code/message.
/// </summary>
public IEnumerable<PSObject> GetSecurityGroups(string nameWildcard, out string errorCode, out string errorMessage)
{ {
LogMethodBegin(MethodBase.GetCurrentMethod()); LogMethodBegin(MethodBase.GetCurrentMethod());
errorCode = "OK";
errorMessage = string.Empty;
try try
{ {
// Credentials in NetworkCredential konvertieren // Credentials in NetworkCredential konvertieren
@@ -752,8 +840,14 @@ namespace C4IT.LIAM
using (var searcher = new PrincipalSearcher(qbe)) using (var searcher = new PrincipalSearcher(qbe))
{ {
var result = new List<PSObject>(); var result = new List<PSObject>();
var findTask = Task.Run(() => searcher.FindAll().OfType<GroupPrincipal>().ToList());
if (!findTask.Wait(PowerShellInvokeTimeout))
{
throw new TimeoutException(
$"Directory search operation 'GetSecurityGroups' timed out after {PowerShellInvokeTimeout.TotalSeconds:0} seconds.");
}
foreach (var principal in searcher.FindAll().OfType<GroupPrincipal>()) foreach (var principal in findTask.Result)
{ {
// DirectoryEntry benötigt man, um DistinguishedName auszulesen // DirectoryEntry benötigt man, um DistinguishedName auszulesen
var de = principal.GetUnderlyingObject() as DirectoryEntry; var de = principal.GetUnderlyingObject() as DirectoryEntry;
@@ -777,10 +871,19 @@ namespace C4IT.LIAM
} }
} }
} }
catch (TimeoutException ex)
{
LogException(ex);
errorCode = "EXCH_GET_SECURITYGROUPS_TIMEOUT";
errorMessage = ex.Message;
return null;
}
catch (Exception ex) catch (Exception ex)
{ {
LogException(ex); LogException(ex);
return new List<PSObject>(); errorCode = "EXCH_GET_SECURITYGROUPS_FAILED";
errorMessage = ex.Message;
return null;
} }
finally finally
{ {

View File

@@ -2,6 +2,7 @@
using System.Linq; using System.Linq;
using System.Management.Automation; using System.Management.Automation;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security; using System.Security;
using System.DirectoryServices; using System.DirectoryServices;
@@ -9,11 +10,78 @@ using System.Diagnostics;
using System.Threading; using System.Threading;
using System.Management.Automation.Runspaces; using System.Management.Automation.Runspaces;
using System.Security.Principal; using System.Security.Principal;
using C4IT.Logging;
using static C4IT.Logging.cLogManager;
namespace C4IT.LIAM namespace C4IT.LIAM
{ {
public partial class ExchangeManager public partial class ExchangeManager
{ {
private static readonly TimeSpan PowerShellInvokeTimeout = TimeSpan.FromSeconds(120);
private static Collection<PSObject> InvokePowerShellWithTimeout(PowerShell ps, TimeSpan timeout, string operationName)
{
IAsyncResult asyncResult = null;
try
{
asyncResult = ps.BeginInvoke();
if (!asyncResult.AsyncWaitHandle.WaitOne(timeout))
{
try
{
ps.Stop();
}
catch (Exception stopEx)
{
LogException(stopEx);
}
throw new TimeoutException(
$"PowerShell operation '{operationName}' timed out after {timeout.TotalSeconds:0} seconds.");
}
var results = ps.EndInvoke(asyncResult);
if (ps.HadErrors)
{
var errorMessage = CollectPowerShellErrors(ps);
throw new InvalidOperationException(
string.IsNullOrWhiteSpace(errorMessage)
? $"PowerShell operation '{operationName}' failed without detailed error output."
: $"PowerShell operation '{operationName}' failed: {errorMessage}");
}
return results;
}
finally
{
if (asyncResult != null)
asyncResult.AsyncWaitHandle.Close();
}
}
private static string CollectPowerShellErrors(PowerShell ps)
{
if (ps?.Streams?.Error == null || ps.Streams.Error.Count <= 0)
return string.Empty;
var errors = ps.Streams.Error
.Select(e => e.Exception?.Message ?? e.ToString())
.Where(m => !string.IsNullOrWhiteSpace(m))
.Take(3);
return string.Join(" | ", errors);
}
private static string GetSharedMailboxCreateErrorCode(Exception ex)
{
return ex is TimeoutException ? "EXCH_SHAREDMAILBOX_TIMEOUT" : "EXCH_SHAREDMAILBOX_CREATE_FAILED";
}
private static string GetDistributionGroupCreateErrorCode(Exception ex)
{
return ex is TimeoutException ? "EXCH_DISTRIBUTIONGROUP_TIMEOUT" : "EXCH_DISTRIBUTIONGROUP_CREATE_FAILED";
}
/// <summary> /// <summary>
/// Stellt sicher, dass eine AD-Sicherheitsgruppe für den angegebenen AccessRole existiert (erstellt sie falls nicht) /// Stellt sicher, dass eine AD-Sicherheitsgruppe für den angegebenen AccessRole existiert (erstellt sie falls nicht)
/// und wartet optional, bis die Replikation abgeschlossen ist. /// und wartet optional, bis die Replikation abgeschlossen ist.
@@ -199,22 +267,63 @@ namespace C4IT.LIAM
string displayName = null, string displayName = null,
string primarySmtpAddress = null) string primarySmtpAddress = null)
{ {
string errorCode;
string errorMessage;
var result = CreateSharedMailboxWithOwnershipGroups(
name,
alias,
displayName,
primarySmtpAddress,
out errorCode,
out errorMessage);
if (result == null)
throw new InvalidOperationException($"[{errorCode}] {errorMessage}");
return result;
}
/// <summary>
/// Erstellt eine Shared Mailbox samt zugehöriger AD-Gruppen (FullAccess, SendAs, Owner) und setzt die nötigen Berechtigungen.
/// Liefert bei Fehlern einen Error-Code und eine Message zurück.
/// </summary>
public Tuple<Guid, List<Tuple<string, string, string, string>>> CreateSharedMailboxWithOwnershipGroups(
string name,
string alias,
string displayName,
string primarySmtpAddress,
out string errorCode,
out string errorMessage)
{
errorCode = string.Empty;
errorMessage = string.Empty;
CreationResult result = new CreationResult(); CreationResult result = new CreationResult();
// Ensure AD groups try
string fullAccessGroup = EnsureSecurityGroup(eLiamAccessRoles.ExchangeSMBFullAccess, name);
string sendAsGroup = EnsureSecurityGroup(eLiamAccessRoles.ExchangeSMBSendAs, name);
string ownerGroup = EnsureSecurityGroup(eLiamAccessRoles.ExchangeSMBOwner, name);
SetManagedBy(fullAccessGroup, ownerGroup);
SetManagedBy(sendAsGroup, ownerGroup);
// Create mailbox
using (Runspace rs = CreateRunspace())
{ {
LogEntry(
$"Start shared mailbox creation: Name='{name}', Alias='{alias}', DisplayName='{displayName}', PrimarySmtpAddress='{primarySmtpAddress}'",
LogLevels.Info);
// Ensure AD groups
string fullAccessGroup = EnsureSecurityGroup(eLiamAccessRoles.ExchangeSMBFullAccess, name);
string sendAsGroup = EnsureSecurityGroup(eLiamAccessRoles.ExchangeSMBSendAs, name);
string ownerGroup = EnsureSecurityGroup(eLiamAccessRoles.ExchangeSMBOwner, name);
SetManagedBy(fullAccessGroup, ownerGroup);
SetManagedBy(sendAsGroup, ownerGroup);
LogEntry(
$"Shared mailbox groups prepared: FullAccess='{fullAccessGroup}', SendAs='{sendAsGroup}', Owner='{ownerGroup}'",
LogLevels.Debug);
// Create mailbox and permissions
using (Runspace rs = CreateRunspace())
using (PowerShell ps = PowerShell.Create()) using (PowerShell ps = PowerShell.Create())
{ {
ps.Runspace = rs; ps.Runspace = rs;
ps.AddCommand("New-Mailbox"); ps.AddCommand("New-Mailbox");
ps.AddParameter("Name", name); ps.AddParameter("Name", name);
ps.AddParameter("Alias", alias); ps.AddParameter("Alias", alias);
@@ -224,45 +333,75 @@ namespace C4IT.LIAM
ps.AddParameter("DisplayName", displayName); ps.AddParameter("DisplayName", displayName);
if (!string.IsNullOrEmpty(primarySmtpAddress)) if (!string.IsNullOrEmpty(primarySmtpAddress))
ps.AddParameter("PrimarySmtpAddress", primarySmtpAddress); ps.AddParameter("PrimarySmtpAddress", primarySmtpAddress);
ps.Invoke();
AddMailboxPermission(name, fullAccessGroup, "FullAccess"); InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"New-Mailbox '{alias}'");
AddSendAsPermission(name, sendAsGroup).GetAwaiter().GetResult();
ps.Commands.Clear();
ps.AddCommand("Add-MailboxPermission");
ps.AddParameter("Identity", name);
ps.AddParameter("User", fullAccessGroup);
ps.AddParameter("AccessRights", "FullAccess");
ps.AddParameter("InheritanceType", "All");
ps.AddParameter("ErrorAction", "Stop");
InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Add-MailboxPermission '{name}' -> '{fullAccessGroup}'");
ps.Commands.Clear();
ps.AddCommand("Add-ADPermission");
ps.AddParameter("Identity", name);
ps.AddParameter("User", sendAsGroup);
ps.AddParameter("ExtendedRights", "Send-As");
ps.AddParameter("AccessRights", "ExtendedRight");
ps.AddParameter("ErrorAction", "Stop");
InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Add-ADPermission Send-As '{name}' -> '{sendAsGroup}'");
} }
}
// Retrieve mailbox GUID // Retrieve mailbox GUID
DirectoryEntry mbEntry = FindAdObject("(&(objectClass=user)(mailNickname=" + alias + "))"); DirectoryEntry mbEntry = FindAdObject("(&(objectClass=user)(mailNickname=" + alias + "))");
if (mbEntry != null && mbEntry.Properties.Contains("objectGUID") && mbEntry.Properties["objectGUID"].Count > 0) if (mbEntry != null && mbEntry.Properties.Contains("objectGUID") && mbEntry.Properties["objectGUID"].Count > 0)
{
byte[] bytes = (byte[])mbEntry.Properties["objectGUID"][0];
result.ObjectGuid = new Guid(bytes);
}
// Collect group details
string[] roles = new string[] {
eLiamAccessRoles.ExchangeSMBFullAccess.ToString(),
eLiamAccessRoles.ExchangeSMBSendAs.ToString(),
eLiamAccessRoles.ExchangeSMBOwner.ToString()
};
string[] names = new string[] {
fullAccessGroup,
sendAsGroup,
ownerGroup
};
for (int i = 0; i < roles.Length; i++)
{
DirectoryEntry grpEntry = FindAdObject("(&(objectCategory=group)(sAMAccountName=" + names[i] + "))");
if (grpEntry != null && grpEntry.Properties.Contains("objectSid") && grpEntry.Properties["objectSid"].Count > 0)
{ {
byte[] sidBytes = (byte[])grpEntry.Properties["objectSid"][0]; byte[] bytes = (byte[])mbEntry.Properties["objectGUID"][0];
string sid = new SecurityIdentifier(sidBytes, 0).Value; result.ObjectGuid = new Guid(bytes);
string distinguishedName = grpEntry.Properties["distinguishedName"][0].ToString();
result.Groups.Add(Tuple.Create(roles[i], sid, names[i], distinguishedName));
} }
}
return Tuple.Create(result.ObjectGuid, result.Groups); // Collect group details
string[] roles = new string[] {
eLiamAccessRoles.ExchangeSMBFullAccess.ToString(),
eLiamAccessRoles.ExchangeSMBSendAs.ToString(),
eLiamAccessRoles.ExchangeSMBOwner.ToString()
};
string[] names = new string[] {
fullAccessGroup,
sendAsGroup,
ownerGroup
};
for (int i = 0; i < roles.Length; i++)
{
DirectoryEntry grpEntry = FindAdObject("(&(objectCategory=group)(sAMAccountName=" + names[i] + "))");
if (grpEntry != null && grpEntry.Properties.Contains("objectSid") && grpEntry.Properties["objectSid"].Count > 0)
{
byte[] sidBytes = (byte[])grpEntry.Properties["objectSid"][0];
string sid = new SecurityIdentifier(sidBytes, 0).Value;
string distinguishedName = grpEntry.Properties["distinguishedName"][0].ToString();
result.Groups.Add(Tuple.Create(roles[i], sid, names[i], distinguishedName));
}
}
errorCode = "OK";
LogEntry(
$"Shared mailbox created successfully: Name='{name}', Alias='{alias}', ObjectGuid='{result.ObjectGuid}', GroupCount='{result.Groups.Count}'",
LogLevels.Info);
return Tuple.Create(result.ObjectGuid, result.Groups);
}
catch (Exception ex)
{
errorCode = GetSharedMailboxCreateErrorCode(ex);
errorMessage = ex.Message;
LogEntry($"Shared mailbox creation failed [{errorCode}] {errorMessage}", LogLevels.Error);
LogException(ex);
return null;
}
} }
/// <summary> /// <summary>
@@ -274,17 +413,56 @@ namespace C4IT.LIAM
string displayName = null, string displayName = null,
string primarySmtpAddress = null) string primarySmtpAddress = null)
{ {
string errorCode;
string errorMessage;
var result = CreateDistributionGroupWithOwnershipGroups(
name,
alias,
displayName,
primarySmtpAddress,
out errorCode,
out errorMessage);
if (result == null)
throw new InvalidOperationException($"[{errorCode}] {errorMessage}");
return result;
}
/// <summary>
/// Erstellt eine Distribution Group samt zugehöriger AD-Gruppen (Member, Owner) und setzt die nötigen Berechtigungen.
/// Liefert bei Fehlern einen Error-Code und eine Message zurück.
/// </summary>
public Tuple<Guid, List<Tuple<string, string, string, string>>> CreateDistributionGroupWithOwnershipGroups(
string name,
string alias,
string displayName,
string primarySmtpAddress,
out string errorCode,
out string errorMessage)
{
errorCode = string.Empty;
errorMessage = string.Empty;
CreationResult result = new CreationResult(); CreationResult result = new CreationResult();
// Ensure AD groups try
string memberGroup = EnsureSecurityGroup(eLiamAccessRoles.ExchangeMLMember, name);
string ownerGroup = EnsureSecurityGroup(eLiamAccessRoles.ExchangeMLOwner, name);
SetManagedBy(memberGroup, ownerGroup);
// Create distribution group
using (Runspace rs = CreateRunspace())
{ {
LogEntry(
$"Start distribution group creation: Name='{name}', Alias='{alias}', DisplayName='{displayName}', PrimarySmtpAddress='{primarySmtpAddress}'",
LogLevels.Info);
// Ensure AD groups
string memberGroup = EnsureSecurityGroup(eLiamAccessRoles.ExchangeMLMember, name);
string ownerGroup = EnsureSecurityGroup(eLiamAccessRoles.ExchangeMLOwner, name);
SetManagedBy(memberGroup, ownerGroup);
LogEntry(
$"Distribution group permission groups prepared: Member='{memberGroup}', Owner='{ownerGroup}'",
LogLevels.Debug);
// Create distribution group and permissions
using (Runspace rs = CreateRunspace())
using (PowerShell ps = PowerShell.Create()) using (PowerShell ps = PowerShell.Create())
{ {
ps.Runspace = rs; ps.Runspace = rs;
@@ -296,13 +474,14 @@ namespace C4IT.LIAM
ps.AddParameter("DisplayName", displayName); ps.AddParameter("DisplayName", displayName);
if (!string.IsNullOrEmpty(primarySmtpAddress)) if (!string.IsNullOrEmpty(primarySmtpAddress))
ps.AddParameter("PrimarySmtpAddress", primarySmtpAddress); ps.AddParameter("PrimarySmtpAddress", primarySmtpAddress);
ps.Invoke(); InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"New-DistributionGroup '{alias}'");
// b) GUID holen // GUID holen
ps.Commands.Clear(); ps.Commands.Clear();
ps.AddCommand("Get-DistributionGroup") ps.AddCommand("Get-DistributionGroup")
.AddParameter("Identity", name); .AddParameter("Identity", name);
var dg = ps.Invoke().FirstOrDefault(); var dg = InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Get-DistributionGroup '{name}'")
.FirstOrDefault();
if (dg != null && dg.Properties["Guid"] != null) if (dg != null && dg.Properties["Guid"] != null)
{ {
var guidVal = dg.Properties["Guid"].Value; var guidVal = dg.Properties["Guid"].Value;
@@ -310,36 +489,58 @@ namespace C4IT.LIAM
else if (guidVal is string s && Guid.TryParse(s, out Guid parsed)) result.ObjectGuid = parsed; else if (guidVal is string s && Guid.TryParse(s, out Guid parsed)) result.ObjectGuid = parsed;
} }
AddMemberToDistributionGroup(name, memberGroup); ps.Commands.Clear();
SetDistributionGroupManagedBy(name, ownerGroup); ps.AddCommand("Add-DistributionGroupMember")
.AddParameter("Identity", name)
.AddParameter("Member", memberGroup)
.AddParameter("ErrorAction", "Stop");
InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Add-DistributionGroupMember '{name}' -> '{memberGroup}'");
ps.Commands.Clear();
ps.AddCommand("Set-DistributionGroup")
.AddParameter("Identity", name)
.AddParameter("ManagedBy", ownerGroup)
.AddParameter("ErrorAction", "Stop");
InvokePowerShellWithTimeout(ps, PowerShellInvokeTimeout, $"Set-DistributionGroup ManagedBy '{name}' -> '{ownerGroup}'");
} }
}
// Collect group details
string[] dRoles = new string[] {
eLiamAccessRoles.ExchangeMLMember.ToString(),
eLiamAccessRoles.ExchangeMLOwner.ToString()
};
string[] dNames = new string[] {
memberGroup,
ownerGroup
};
for (int i = 0; i < dRoles.Length; i++)
// Collect group details
string[] dRoles = new string[] {
eLiamAccessRoles.ExchangeMLMember.ToString(),
eLiamAccessRoles.ExchangeMLOwner.ToString()
};
string[] dNames = new string[] {
memberGroup,
ownerGroup
};
for (int i = 0; i < dRoles.Length; i++)
{
DirectoryEntry grpEntry = FindAdObject("(&(objectCategory=group)(sAMAccountName=" + dNames[i] + "))");
if (grpEntry != null && grpEntry.Properties.Contains("objectSid") && grpEntry.Properties["objectSid"].Count > 0)
{ {
byte[] sidBytes = (byte[])grpEntry.Properties["objectSid"][0]; DirectoryEntry grpEntry = FindAdObject("(&(objectCategory=group)(sAMAccountName=" + dNames[i] + "))");
string sid = new SecurityIdentifier(sidBytes, 0).Value; if (grpEntry != null && grpEntry.Properties.Contains("objectSid") && grpEntry.Properties["objectSid"].Count > 0)
string distinguishedName = grpEntry.Properties["distinguishedName"][0].ToString(); {
result.Groups.Add(Tuple.Create(dRoles[i], sid, dNames[i], distinguishedName)); byte[] sidBytes = (byte[])grpEntry.Properties["objectSid"][0];
string sid = new SecurityIdentifier(sidBytes, 0).Value;
string distinguishedName = grpEntry.Properties["distinguishedName"][0].ToString();
result.Groups.Add(Tuple.Create(dRoles[i], sid, dNames[i], distinguishedName));
}
} }
}
return Tuple.Create(result.ObjectGuid, result.Groups); errorCode = "OK";
LogEntry(
$"Distribution group created successfully: Name='{name}', Alias='{alias}', ObjectGuid='{result.ObjectGuid}', GroupCount='{result.Groups.Count}'",
LogLevels.Info);
return Tuple.Create(result.ObjectGuid, result.Groups);
}
catch (Exception ex)
{
errorCode = GetDistributionGroupCreateErrorCode(ex);
errorMessage = ex.Message;
LogEntry($"Distribution group creation failed [{errorCode}] {errorMessage}", LogLevels.Error);
LogException(ex);
return null;
}
} }

View File

@@ -75,6 +75,9 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="C4IT.LIAM.Exchange.cs" /> <Compile Include="C4IT.LIAM.Exchange.cs" />
<Compile Include="ExchangeManager.Extensions.cs" /> <Compile Include="ExchangeManager.Extensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />

View File

@@ -5,13 +5,9 @@ using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("LiamExchange")] [assembly: AssemblyTitle("LIAM Exchange Module")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LiamExchange")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible // Setting ComVisible to false makes the types in this assembly not visible
@@ -21,13 +17,3 @@ using System.Runtime.InteropServices;
// The following GUID is for the ID of the typelib if this project is exposed to COM // The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("12586a29-bb1e-49b4-b971-88e520d6a77c")] [assembly: Guid("12586a29-bb1e-49b4-b971-88e520d6a77c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
f6e128d7149dc184a405058b92396b0925da92456f0d37d8147cf7685d3d5e9f da7102665519855eb23a49e4ee611583f6e728b782090de35692769521dc096f

View File

@@ -1,34 +1,70 @@
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\LiamExchange.dll.config C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/LiamExchange.dll.config
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\LiamExchange.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/LiamExchange.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\LiamExchange.pdb C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/LiamExchange.pdb
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\LiamBaseClasses.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/LiamBaseClasses.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\LiamHelper.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/LiamHelper.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\LiamNtfs.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/LiamNtfs.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\Microsoft.Bcl.Cryptography.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/Microsoft.Bcl.Cryptography.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Buffers.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Buffers.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Formats.Asn1.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Formats.Asn1.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Management.Automation.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Management.Automation.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Memory.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Memory.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Numerics.Vectors.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Numerics.Vectors.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Runtime.CompilerServices.Unsafe.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Runtime.CompilerServices.Unsafe.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Security.Principal.Windows.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Security.Principal.Windows.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.ValueTuple.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.ValueTuple.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\Newtonsoft.Json.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/Newtonsoft.Json.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\Microsoft.Management.Infrastructure.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/Microsoft.Management.Infrastructure.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\LiamBaseClasses.pdb C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/LiamBaseClasses.pdb
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\LiamHelper.pdb C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/LiamHelper.pdb
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\LiamNtfs.pdb C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/LiamNtfs.pdb
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\Microsoft.Bcl.Cryptography.xml C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/Microsoft.Bcl.Cryptography.xml
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Buffers.xml C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Buffers.xml
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Formats.Asn1.xml C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Formats.Asn1.xml
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Management.Automation.xml C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Management.Automation.xml
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Memory.xml C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Memory.xml
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Numerics.Vectors.xml C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Numerics.Vectors.xml
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Runtime.CompilerServices.Unsafe.xml C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Runtime.CompilerServices.Unsafe.xml
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.Security.Principal.Windows.xml C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.Security.Principal.Windows.xml
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\bin\Debug\System.ValueTuple.xml C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/bin/Debug/System.ValueTuple.xml
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\obj\Debug\LiamExchange.csproj.AssemblyReference.cache C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/obj/Debug/LiamExchange.csproj.AssemblyReference.cache
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\obj\Debug\LiamExchange.csproj.CoreCompileInputs.cache C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/obj/Debug/LiamExchange.csproj.CoreCompileInputs.cache
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\obj\Debug\LiamExch.7F93E524.Up2Date C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/obj/Debug/LiamExch.7F93E524.Up2Date
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\obj\Debug\LiamExchange.dll C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/obj/Debug/LiamExchange.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\obj\Debug\LiamExchange.pdb C:/Workspace/C4IT DEV LIAM WEB Service/LiamExchange/obj/Debug/LiamExchange.pdb
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/LiamExchange.dll.config
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/LiamExchange.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/LiamExchange.pdb
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/LiamBaseClasses.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/LiamHelper.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/LiamNtfs.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/Microsoft.Bcl.Cryptography.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Buffers.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Formats.Asn1.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Management.Automation.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Memory.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Numerics.Vectors.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Runtime.CompilerServices.Unsafe.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Security.Principal.Windows.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.ValueTuple.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/Newtonsoft.Json.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/Microsoft.Management.Infrastructure.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/LiamBaseClasses.pdb
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/LiamHelper.pdb
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/LiamNtfs.pdb
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/Microsoft.Bcl.Cryptography.xml
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Buffers.xml
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Formats.Asn1.xml
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Management.Automation.xml
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Memory.xml
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Numerics.Vectors.xml
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Runtime.CompilerServices.Unsafe.xml
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.Security.Principal.Windows.xml
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/bin/Debug/System.ValueTuple.xml
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/obj/Debug/LiamExchange.csproj.AssemblyReference.cache
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/obj/Debug/LiamExchange.csproj.CoreCompileInputs.cache
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/obj/Debug/LiamExch.7F93E524.Up2Date
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/obj/Debug/LiamExchange.dll
C:/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/obj/Debug/LiamExchange.pdb
/mnt/c/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/obj/Debug/LiamExchange.dll
/mnt/c/Workspace/C4IT DEV LIAM WEB Service_git/LiamExchange/obj/Debug/LiamExchange.pdb

View File

@@ -1 +1 @@
98cf57f4af408c0d6fb600e7f35f4b4ad9afb179b478f70b8c3490f5c097e5b7 1dca58070b44de25f73d487f9b204428a4b6eccec8abc748391cb2e754958859

View File

@@ -32,3 +32,37 @@ C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\obj\Release\LiamExchange.csp
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\obj\Release\LiamExch.7F93E524.Up2Date C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\obj\Release\LiamExch.7F93E524.Up2Date
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\obj\Release\LiamExchange.dll C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\obj\Release\LiamExchange.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\obj\Release\LiamExchange.pdb C:\Workspace\C4IT DEV LIAM WEB Service\LiamExchange\obj\Release\LiamExchange.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\obj\Release\LiamExchange.csproj.AssemblyReference.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\obj\Release\LiamExchange.csproj.CoreCompileInputs.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\obj\Release\LiamExchange.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\obj\Release\LiamExchange.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\LiamExchange.dll.config
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\LiamExchange.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\LiamExchange.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\LiamBaseClasses.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\LiamHelper.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\LiamNtfs.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\Microsoft.Bcl.Cryptography.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Buffers.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Formats.Asn1.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Management.Automation.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Memory.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Numerics.Vectors.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Runtime.CompilerServices.Unsafe.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Security.Principal.Windows.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.ValueTuple.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\Newtonsoft.Json.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\Microsoft.Management.Infrastructure.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\LiamBaseClasses.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\LiamHelper.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\LiamNtfs.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\Microsoft.Bcl.Cryptography.xml
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Buffers.xml
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Formats.Asn1.xml
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Management.Automation.xml
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Memory.xml
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Numerics.Vectors.xml
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Runtime.CompilerServices.Unsafe.xml
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.Security.Principal.Windows.xml
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\bin\Release\System.ValueTuple.xml
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamExchange\obj\Release\LiamExch.7F93E524.Up2Date

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
fa1308e47d656f8d45ff7eb54320edbe298f027def67be470e1176380e178ef8 4d880001029880fa07c3ae9616191eb233516cb594f201236c5a15cc450b0d73

View File

@@ -6,3 +6,11 @@ C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Debug\LiamHelper.csproj.Co
C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Debug\LiamHelper.csproj.Up2Date C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Debug\LiamHelper.csproj.Up2Date
C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Debug\LiamHelper.dll C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Debug\LiamHelper.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Debug\LiamHelper.pdb C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Debug\LiamHelper.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\bin\Debug\LiamHelper.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\bin\Debug\LiamHelper.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\bin\Debug\Newtonsoft.Json.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\obj\Debug\LiamHelper.csproj.AssemblyReference.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\obj\Debug\LiamHelper.csproj.CoreCompileInputs.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\obj\Debug\LiamHelper.csproj.Up2Date
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\obj\Debug\LiamHelper.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\obj\Debug\LiamHelper.pdb

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
e5ff73ca7ab222930200dc95f233677e4358ddfc4482a612b7d96d638bfb1715 582b6753ab7a28fa087bc18dfc7dd79f3608320e1df5d150182d323666f1e3b9

View File

@@ -6,3 +6,11 @@ C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Release\LiamHelper.csproj.
C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Release\LiamHelper.csproj.Up2Date C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Release\LiamHelper.csproj.Up2Date
C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Release\LiamHelper.dll C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Release\LiamHelper.dll
C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Release\LiamHelper.pdb C:\Workspace\C4IT DEV LIAM WEB Service\LiamHelper\obj\Release\LiamHelper.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\bin\Release\LiamHelper.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\bin\Release\LiamHelper.pdb
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\bin\Release\Newtonsoft.Json.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\obj\Release\LiamHelper.csproj.AssemblyReference.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\obj\Release\LiamHelper.csproj.CoreCompileInputs.cache
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\obj\Release\LiamHelper.csproj.Up2Date
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\obj\Release\LiamHelper.dll
C:\Workspace\C4IT DEV LIAM WEB Service_git\LiamHelper\obj\Release\LiamHelper.pdb

View File

@@ -557,94 +557,207 @@ where ";
return RetVal; return RetVal;
} }
private cLiamProviderBase createProvider(DataTable dtMain, DataTable dtBase, DataTable dtAdditional, DataTable dtNamingConvention = null, DataTable dtCustomTag = null) private bool TryLoadProviderFragments(Guid providerConfigClassID, out Guid objectId, out DataTable tblMain, out DataTable tblBase, out DataTable tblAdditionalAttr, out DataTable tblNamingConvention, out DataTable tblCustomTags)
{ {
var CM = MethodBase.GetCurrentMethod(); objectId = Guid.Empty;
LogMethodBegin(CM); tblMain = null;
tblBase = null;
tblAdditionalAttr = null;
tblNamingConvention = null;
tblCustomTags = null;
try try
{ {
if (dtMain?.Rows == null || dtMain.Rows.Count <= 0) var classID = SPSDataEngineSchemaReader.ClassGetIDFromName(constFragmentNameConfigProviderMain);
return null; LogEntry($"Config provider class ID: {classID}", LogLevels.Debug);
if (dtBase?.Rows == null || dtBase.Rows.Count <= 0) var fragment = FragmentRequest.GetSPSFragment(classID, providerConfigClassID);
return null; if (fragment == null)
if (dtAdditional?.Rows == null) {
return null; LogEntry($"Provider config fragment not found: ClassID={classID}, FragmentId={providerConfigClassID}", LogLevels.Debug);
return false;
}
var dataMain = dtMain.Rows[0]; objectId = fragment.ObjectID;
var dataBase = dtBase.Rows[0]; if (objectId == Guid.Empty)
{
LogEntry($"Provider config fragment not found: ClassID={classID}, FragmentId={providerConfigClassID}", LogLevels.Debug);
return false;
}
var encPW = cLIAMHelper.getStringFromObject(dataBase["Password"]); tblMain = fragment.FragmentTable;
if (!CryptoManager.Instance.TryDecryptDBText(encPW, out string PW)) LogEntry($"Config provider object ID: {objectId}", LogLevels.Debug);
PW = encPW;
var DataProviderData = new cLiamProviderData() classID = SPSDataEngineSchemaReader.ClassGetIDFromName(constFragmentNameConfigProviderBase);
LogEntry($"Config provider base class ID: {classID}", LogLevels.Debug);
Guid[] ids = { objectId };
tblBase = FragmentRequestBase.SimpleLoad(classID,
"Account, Password",
AsqlHelper.BuildInCondition("[Expression-ObjectID]", ids));
if (tblBase?.Rows == null || tblBase.Rows.Count <= 0)
{
LogEntry($"Provider config base fragment not found: ClassId={classID}, ObjectId={objectId}", LogLevels.Debug);
return false;
}
classID = SPSDataEngineSchemaReader.ClassGetIDFromName(constFragmentNameConfigProviderAdditionalAttributes);
LogEntry($"Config provider additional config class ID: {classID}", LogLevels.Debug);
tblAdditionalAttr = FragmentRequestBase.SimpleLoad(classID,
"Name, Value",
AsqlHelper.BuildInCondition("[Expression-ObjectID]", ids));
if (tblAdditionalAttr == null)
{
LogEntry($"Provider additional config class fragment not found: ClassId={classID}, ObjectId={objectId}", LogLevels.Debug);
return false;
}
classID = SPSDataEngineSchemaReader.ClassGetIDFromName(constFragmentNameCustomTagBase);
LogEntry($"Custom Tag class ID: {classID}", LogLevels.Debug);
tblCustomTags = FragmentRequestBase.SimpleLoad(classID, "Key, Name", $"[Expression-ObjectID]='{objectId}'") ?? new DataTable();
classID = SPSDataEngineSchemaReader.ClassGetIDFromName(constFragmentNameConfigNamingConvention);
LogEntry($"Naming convention config class ID: {classID}", LogLevels.Debug);
tblNamingConvention = FragmentRequestBase.SimpleLoad(classID,
"ID, Usage, NamingConvention.Description as Description, NamingConvention.DescriptionTemplate as DescriptionTemplate, " +
"NamingConvention.Name as Name, NamingConvention.NamingTemplate as NamingTemplate, NamingConvention.Wildcard as Wildcard",
$"[Expression-ObjectID]='{objectId}'") ?? new DataTable();
return true;
}
catch (Exception e)
{
LogException(e);
return false;
}
}
private cLiamProviderData buildProviderData(DataTable dtMain, DataTable dtBase, DataTable dtAdditional, DataTable dtNamingConvention, DataTable dtCustomTag, bool includeSecret, out string sanitizedJson)
{
sanitizedJson = null;
if (dtMain?.Rows == null || dtMain.Rows.Count <= 0)
return null;
if (dtBase?.Rows == null || dtBase.Rows.Count <= 0)
return null;
if (dtAdditional == null)
return null;
var dataMain = dtMain.Rows[0];
var dataBase = dtBase.Rows[0];
var encPW = cLIAMHelper.getStringFromObject(dataBase["Password"]);
if (!CryptoManager.Instance.TryDecryptDBText(encPW, out string password))
password = encPW;
var providerData = new cLiamProviderData()
{
Domain = cLIAMHelper.getStringFromObject(dataMain["GCCDomain"]),
Credential = new cLiamCredential()
{ {
Domain = cLIAMHelper.getStringFromObject(dataMain["GCCDomain"]), Domain = cLIAMHelper.getStringFromObject(dataMain["GCCDomain"]),
Credential = new cLiamCredential() Identification = cLIAMHelper.getStringFromObject(dataBase["Account"]),
{ Secret = "***"
Domain = cLIAMHelper.getStringFromObject(dataMain["GCCDomain"]), },
Identification = cLIAMHelper.getStringFromObject(dataBase["Account"]), RootPath = cLIAMHelper.getStringFromObject(dataMain["GCCTarget"]),
Secret = "***" MaxDepth = cLIAMHelper.getIntFromObject(dataMain["GCCMaxDepth"]),
}, GroupFilter = cLIAMHelper.getStringFromObject(dataMain["GCCgroupLDAPFilter"]),
RootPath = cLIAMHelper.getStringFromObject(dataMain["GCCTarget"]), GroupPath = cLIAMHelper.getStringFromObject(dataMain["GCCgroupOUPath"]),
MaxDepth = cLIAMHelper.getIntFromObject(dataMain["GCCMaxDepth"]), GroupStrategy = (eLiamGroupStrategies)cLIAMHelper.getIntFromObject(dataMain["GCCPermissionGroupStrategy"]),
GroupFilter = cLIAMHelper.getStringFromObject(dataMain["GCCgroupLDAPFilter"]), ProviderType = (eLiamProviderTypes)cLIAMHelper.getIntFromObject(dataMain["GCCtargetType"])
GroupPath = cLIAMHelper.getStringFromObject(dataMain["GCCgroupOUPath"]), };
GroupStrategy = (eLiamGroupStrategies)cLIAMHelper.getIntFromObject(dataMain["GCCPermissionGroupStrategy"]),
ProviderType = (eLiamProviderTypes)cLIAMHelper.getIntFromObject(dataMain["GCCtargetType"]) if (dtAdditional?.Rows != null)
}; {
foreach (DataRow row in dtAdditional.Rows) foreach (DataRow row in dtAdditional.Rows)
{ {
var Name = cLIAMHelper.getStringFromObject(row["Name"]); var name = cLIAMHelper.getStringFromObject(row["Name"]);
var Value = cLIAMHelper.getStringFromObject(row["Value"]); var value = cLIAMHelper.getStringFromObject(row["Value"]);
DataProviderData.AdditionalConfiguration[Name] = Value; if (!string.IsNullOrEmpty(name))
providerData.AdditionalConfiguration[name] = value;
} }
}
if (dtCustomTag?.Rows != null)
{
foreach (DataRow row in dtCustomTag.Rows) foreach (DataRow row in dtCustomTag.Rows)
{ {
var Name = cLIAMHelper.getStringFromObject(row["Key"]); var name = cLIAMHelper.getStringFromObject(row["Key"]);
var Value = cLIAMHelper.getStringFromObject(row["Name"]); var value = cLIAMHelper.getStringFromObject(row["Name"]);
DataProviderData.CustomTags[Name] = Value; if (!string.IsNullOrEmpty(name))
providerData.CustomTags[name] = value;
} }
}
if (dtNamingConvention?.Rows != null)
{
foreach (DataRow row in dtNamingConvention.Rows) foreach (DataRow row in dtNamingConvention.Rows)
{ {
var Usage = cLIAMHelper.getIntFromObject(row["Usage"]); var usage = cLIAMHelper.getIntFromObject(row["Usage"]);
var AccessRole = eLiamAccessRoles.Read; var accessRole = eLiamAccessRoles.Read;
var Scope = eLiamAccessRoleScopes.Unknown; var scope = eLiamAccessRoleScopes.Unknown;
switch (Usage) switch (usage)
{ {
case -10: case -10:
AccessRole = eLiamAccessRoles.Traverse; accessRole = eLiamAccessRoles.Traverse;
Scope = eLiamAccessRoleScopes.Global; scope = eLiamAccessRoleScopes.Global;
break; break;
case 10: case 10:
AccessRole = eLiamAccessRoles.Read; accessRole = eLiamAccessRoles.Read;
Scope = eLiamAccessRoleScopes.Global; scope = eLiamAccessRoleScopes.Global;
break; break;
case 20: case 20:
AccessRole = eLiamAccessRoles.Write; accessRole = eLiamAccessRoles.Write;
Scope = eLiamAccessRoleScopes.Global; scope = eLiamAccessRoleScopes.Global;
break; break;
case 30: case 30:
AccessRole = eLiamAccessRoles.Owner; accessRole = eLiamAccessRoles.Owner;
Scope = eLiamAccessRoleScopes.Global; scope = eLiamAccessRoleScopes.Global;
break; break;
case 40: case 40:
AccessRole = eLiamAccessRoles.Read; accessRole = eLiamAccessRoles.Read;
Scope = eLiamAccessRoleScopes.DomainLocal; scope = eLiamAccessRoleScopes.DomainLocal;
break; break;
case 50: case 50:
AccessRole = eLiamAccessRoles.Write; accessRole = eLiamAccessRoles.Write;
Scope = eLiamAccessRoleScopes.DomainLocal; scope = eLiamAccessRoleScopes.DomainLocal;
break; break;
case 60: case 60:
AccessRole = eLiamAccessRoles.Owner; accessRole = eLiamAccessRoles.Owner;
Scope = eLiamAccessRoleScopes.DomainLocal; scope = eLiamAccessRoleScopes.DomainLocal;
break;
case 100:
accessRole = eLiamAccessRoles.ADOwner;
scope = eLiamAccessRoleScopes.Global;
break;
case 110:
accessRole = eLiamAccessRoles.ADMember;
scope = eLiamAccessRoleScopes.Global;
break;
case 200:
accessRole = eLiamAccessRoles.ExchangeMLMember;
scope = eLiamAccessRoleScopes.Universal;
break;
case 210:
accessRole = eLiamAccessRoles.ExchangeMLOwner;
scope = eLiamAccessRoleScopes.Universal;
break;
case 250:
accessRole = eLiamAccessRoles.ExchangeSMBFullAccess;
scope = eLiamAccessRoleScopes.Universal;
break;
case 260:
accessRole = eLiamAccessRoles.ExchangeSMBSendAs;
scope = eLiamAccessRoleScopes.Universal;
break;
case 270:
accessRole = eLiamAccessRoles.ExchangeSMBOwner;
scope = eLiamAccessRoleScopes.Universal;
break; break;
} }
DataProviderData.NamingConventions.Add(new cLiamNamingConvention()
providerData.NamingConventions.Add(new cLiamNamingConvention()
{ {
AccessRole = AccessRole, AccessRole = accessRole,
Scope = Scope, Scope = scope,
Description = cLIAMHelper.getStringFromObject(row["Description"]), Description = cLIAMHelper.getStringFromObject(row["Description"]),
DescriptionTemplate = cLIAMHelper.getStringFromObject(row["DescriptionTemplate"]), DescriptionTemplate = cLIAMHelper.getStringFromObject(row["DescriptionTemplate"]),
Name = cLIAMHelper.getStringFromObject(row["Name"]), Name = cLIAMHelper.getStringFromObject(row["Name"]),
@@ -652,11 +765,29 @@ where ";
Wildcard = cLIAMHelper.getStringFromObject(row["Wildcard"]) Wildcard = cLIAMHelper.getStringFromObject(row["Wildcard"])
}); });
} }
}
sanitizedJson = JsonConvert.SerializeObject(providerData, Newtonsoft.Json.Formatting.Indented);
if (includeSecret && providerData.Credential != null)
providerData.Credential.Secret = password;
return providerData;
}
private cLiamProviderBase createProvider(DataTable dtMain, DataTable dtBase, DataTable dtAdditional, DataTable dtNamingConvention = null, DataTable dtCustomTag = null)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var DataProviderData = buildProviderData(dtMain, dtBase, dtAdditional, dtNamingConvention, dtCustomTag, includeSecret: true, out var sanitizedJson);
if (DataProviderData == null)
return null;
LogEntry("Provider configuration (sanitized JSON, copy for diagnostics tool):", LogLevels.Info);
LogEntry(sanitizedJson, LogLevels.Info);
var strJson = JsonConvert.SerializeObject(DataProviderData);
LogEntry("Data provider data:", LogLevels.Debug);
LogEntry(strJson, LogLevels.Debug);
DataProviderData.Credential.Secret = PW;
var DataProvider = CreateProviderInstance(new cLiamConfiguration(), DataProviderData); var DataProvider = CreateProviderInstance(new cLiamConfiguration(), DataProviderData);
return DataProvider; return DataProvider;
@@ -701,6 +832,53 @@ where ";
} }
} }
[Route("exportProviderConfiguration"), HttpGet]
public IHttpActionResult exportProviderConfiguration(Guid ProviderConfigClassID)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
if (cC4ITLicenseM42ESM.Instance == null)
LoadLicensingInformation();
if (!cC4ITLicenseM42ESM.Instance.IsValid)
{
LogEntry($"Error: License not valid", LogLevels.Error);
return Content(HttpStatusCode.Forbidden, "License not valid");
}
if (!TryLoadProviderFragments(ProviderConfigClassID, out var objectId, out var tblMain, out var tblBase, out var tblAdditionalAttr, out var tblNamingConvention, out var tblCustomTags))
{
return Content(HttpStatusCode.NotFound, $"Provider configuration '{ProviderConfigClassID}' not found.");
}
var providerData = buildProviderData(tblMain, tblBase, tblAdditionalAttr, tblNamingConvention, tblCustomTags, includeSecret: false, out var sanitizedJson);
if (providerData == null)
return Content(HttpStatusCode.InternalServerError, "Provider configuration could not be loaded.");
var export = new ProviderConfigurationExport
{
ProviderConfigClassID = ProviderConfigClassID,
ProviderConfigObjectID = objectId,
SanitizedJson = sanitizedJson,
Configuration = providerData,
GeneratedAtUtc = DateTime.UtcNow
};
return Ok(export);
}
catch (Exception E)
{
LogException(E);
return InternalServerError(E);
}
finally
{
LogMethodEnd(CM);
}
}
private async Task<ProviderCacheEntry> getDataProvider(Guid ProviderConfigClassID, bool force = false) private async Task<ProviderCacheEntry> getDataProvider(Guid ProviderConfigClassID, bool force = false)
{ {
var CM = MethodBase.GetCurrentMethod(); var CM = MethodBase.GetCurrentMethod();
@@ -716,56 +894,16 @@ where ";
return Provider; return Provider;
} }
} }
var ClassID = SPSDataEngineSchemaReader.ClassGetIDFromName(constFragmentNameConfigProviderMain); if (!TryLoadProviderFragments(ProviderConfigClassID, out var ObjectID, out var tblMain, out var tblBase, out var tblAdditionalAttr, out var tblNamingConvention, out var tblCustomTags))
LogEntry($"Config provider class ID: {ClassID}", LogLevels.Debug); return null;
var Frag1 = FragmentRequest.GetSPSFragment(ClassID, ProviderConfigClassID);
if (Frag1 == null) var DataProvider = createProvider(tblMain, tblBase, tblAdditionalAttr, tblNamingConvention, tblCustomTags);
if (DataProvider == null)
{ {
LogEntry($"Provider config fragment not found: ClassID={ClassID}, FragmentId={ProviderConfigClassID}", LogLevels.Debug); LogEntry($"Provider configuration '{ProviderConfigClassID}' could not be materialized.", LogLevels.Warning);
return null; return null;
} }
var ObjectID = Frag1.ObjectID;
if (ObjectID == Guid.Empty)
{
LogEntry($"Provider config fragment not found: ClassID={ClassID}, FragmentId={ProviderConfigClassID}", LogLevels.Debug);
return null;
}
LogEntry($"Config provider object ID: {ObjectID}", LogLevels.Debug);
ClassID = SPSDataEngineSchemaReader.ClassGetIDFromName(constFragmentNameConfigProviderBase);
LogEntry($"Config provider base class ID: {ClassID}", LogLevels.Debug);
Guid[] ids = { ObjectID };
var tbl = FragmentRequestBase.SimpleLoad(ClassID,
"Account, Password",
AsqlHelper.BuildInCondition("[Expression-ObjectID]",
ids));
if (tbl?.Rows == null || tbl.Rows.Count <= 0)
{
LogEntry($"Provider config base fragment not found: ClassId={ClassID}, ObjectId={ObjectID}", LogLevels.Debug);
return null;
}
ClassID = SPSDataEngineSchemaReader.ClassGetIDFromName(constFragmentNameConfigProviderAdditionalAttributes);
LogEntry($"Config provider additional config class ID: {ClassID}", LogLevels.Debug);
var tblAdditionalAttr = FragmentRequestBase.SimpleLoad(ClassID,
"Name, Value",
AsqlHelper.BuildInCondition("[Expression-ObjectID]",
ids));
if (tblAdditionalAttr?.Rows == null)
{
LogEntry($"Provider additional config class fragment not found: ClassId={ClassID}, ObjectId={ObjectID}", LogLevels.Debug);
return null;
}
ClassID = SPSDataEngineSchemaReader.ClassGetIDFromName(constFragmentNameCustomTagBase);
LogEntry($"Custom Tag class ID: {ClassID}", LogLevels.Debug);
var tblCustomTags = FragmentRequestBase.SimpleLoad(ClassID, "Key, Name", $"[Expression-ObjectID]='{ObjectID}'");
ClassID = SPSDataEngineSchemaReader.ClassGetIDFromName(constFragmentNameConfigNamingConvention);
LogEntry($"Naming convention config class ID: {ClassID}", LogLevels.Debug);
var tblNamingConvention = FragmentRequestBase.SimpleLoad(ClassID, "ID, Usage, NamingConvention.Description as Description, NamingConvention.DescriptionTemplate as DescriptionTemplate, NamingConvention.Name as Name, NamingConvention.NamingTemplate as NamingTemplate, NamingConvention.Wildcard as Wildcard", $"[Expression-ObjectID]='{ObjectID}'");
var DataProvider = createProvider(Frag1.FragmentTable, tbl, tblAdditionalAttr, tblNamingConvention, tblCustomTags);
var validLogon = await DataProvider.LogonAsync(); var validLogon = await DataProvider.LogonAsync();
if (!validLogon) if (!validLogon)
return null; return null;
@@ -1738,6 +1876,15 @@ where ";
} }
return UPN; return UPN;
} }
public class ProviderConfigurationExport
{
public Guid ProviderConfigClassID { get; set; }
public Guid ProviderConfigObjectID { get; set; }
public string SanitizedJson { get; set; }
public cLiamProviderData Configuration { get; set; }
public DateTime GeneratedAtUtc { get; set; }
}
} }
} }

Some files were not shown because too many files have changed in this diff Show More