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:
31
AGENTS.md
Normal file
31
AGENTS.md
Normal 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.***
|
||||||
8
LIAM.sln
8
LIAM.sln
@@ -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
|
||||||
|
|||||||
@@ -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" />
|
||||||
|
|||||||
@@ -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")]
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||||
|
|||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
88ca960765b758a5c4edcddedf6dc811f2a49d840cd7ade015d7644911a99c77
|
0f439131d442d0ee4d6473d1fe79783624433c39a44374a60e15e079e468a4be
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||||
|
|||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
ab9bb136583040c5ab0b8fc2b80edba3f154caa1532f30973b39973f0def47e6
|
e6f9f5153aa55a3a910f7c5ef0287e4500a3f354c3a1c3198c24d7eea04e0de2
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
3908855f9633bf09d020c2efbd1fa153a9ad8a91b6e76b39255ee0403b9907f8
|
d0283af9d4075f4a557253c483f33e9a0d4fae295f6ce748fa39a1e639aafbb6
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
77f86ea35cc63f1fe117fbff3ddf1a527617a8ddb75413eb5ef7f6b4cf6c8399
|
135510e8387d9e004d20f72096af679b01eba0ea20db7534ef81cc95461b16c6
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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 AD‑Domain/OU nach Security‑Gruppen, 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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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" />
|
||||||
|
|||||||
@@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
f6e128d7149dc184a405058b92396b0925da92456f0d37d8147cf7685d3d5e9f
|
da7102665519855eb23a49e4ee611583f6e728b782090de35692769521dc096f
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
98cf57f4af408c0d6fb600e7f35f4b4ad9afb179b478f70b8c3490f5c097e5b7
|
1dca58070b44de25f73d487f9b204428a4b6eccec8abc748391cb2e754958859
|
||||||
|
|||||||
@@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
fa1308e47d656f8d45ff7eb54320edbe298f027def67be470e1176380e178ef8
|
4d880001029880fa07c3ae9616191eb233516cb594f201236c5a15cc450b0d73
|
||||||
|
|||||||
@@ -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.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
e5ff73ca7ab222930200dc95f233677e4358ddfc4482a612b7d96d638bfb1715
|
582b6753ab7a28fa087bc18dfc7dd79f3608320e1df5d150182d323666f1e3b9
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -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; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user