first commit
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace C4IT.Configuration
|
||||
{
|
||||
}
|
||||
BIN
F4SD-Cockpit-ServerCore/C4IT_2016.ico
Normal file
BIN
F4SD-Cockpit-ServerCore/C4IT_2016.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 470 KiB |
240
F4SD-Cockpit-ServerCore/Common/C4IT.FASD.Communication.Citrix.cs
Normal file
240
F4SD-Cockpit-ServerCore/Common/C4IT.FASD.Communication.Citrix.cs
Normal file
@@ -0,0 +1,240 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using C4IT.HTTP;
|
||||
using C4IT.MsGraph;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using C4IT.Logging;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using C4IT.DataHistoryProvider;
|
||||
|
||||
namespace C4IT.FASD.Communication.Citrix
|
||||
{
|
||||
public class cCitrixCommunication : cHttpApiBase
|
||||
{
|
||||
public const int constMaxPageSize = 1000;
|
||||
public const string constCitrixBaseUrl = "https://api.cloud.com/{Request}";
|
||||
public const string constCitrixUserList = "monitorodata/Users?$top={top}&$skip={skip}&$select=Id,Sid,Upn,Domain&$filter=Domain ne ''";
|
||||
public const string constCitrixUserSessions = "monitorodata/Sessions?$filter=UserId eq {UserId} and (EndDate eq null or StartDate ge {MinStartDate})&$expand=Machine($select=Id,DnsName,Name)&$select=SessionKey,StartDate,EndDate,ConnectionState";
|
||||
|
||||
public cCitrixCommunication() : base("Citrix ID tenant", "https://api.cloud.com/cctrustoauth2/{Tenant}/tokens/clients", "Citrix Comunication")
|
||||
{
|
||||
KnownAutoRetryErrors.Add(HttpStatusCode.Forbidden);
|
||||
autoRetryCount = 2;
|
||||
autoRetryDelay = 100;
|
||||
}
|
||||
|
||||
private protected override List<KeyValuePair<string, string>> GetRequestHeaders(cOAuthLogonInfo privLogonInfo)
|
||||
{
|
||||
|
||||
return new List<KeyValuePair<string, string>>()
|
||||
{
|
||||
new KeyValuePair<string, string>("Authorization", $"CwsAuth Bearer={AccessToken}"),
|
||||
new KeyValuePair<string, string>("Citrix-CustomerId", privLogonInfo.Tenant),
|
||||
new KeyValuePair<string, string>("Citrix-InstanceId", privLogonInfo.InstanceId)
|
||||
};
|
||||
}
|
||||
public async Task<cCitrixResultBase> RequestAsync(string Request, eHttpMethod httpMethod = eHttpMethod.get, object JsonData = null, bool retryForbidden = false, string nameProperty = null, bool noAutoRelogon = false)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
|
||||
var strUrl = constCitrixBaseUrl;
|
||||
strUrl = strUrl.Replace("{Request}", Request);
|
||||
|
||||
var data = await privRequestAsync(strUrl, httpMethod, JsonData, retryForbidden, noAutoRelogon: noAutoRelogon);
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
if (data is bool isValid)
|
||||
{
|
||||
if (isValid)
|
||||
return new cCitrixResultBase(null);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
var RetVal = new cCitrixResultBase(data, nameProperty);
|
||||
return RetVal;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
cLogManager.LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<cCitrixResultList> RequestListAsync(string Request, bool loadPaged = false, bool retryForbidden = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
// get the request url
|
||||
|
||||
var strUrl = constCitrixBaseUrl;
|
||||
strUrl = strUrl.Replace("{Request}", Request);
|
||||
|
||||
var res = await privRequestAsync(strUrl, autoRetry: retryForbidden);
|
||||
if (res != null)
|
||||
{
|
||||
var RetVal = new cCitrixResultList(retryForbidden);
|
||||
RetVal.AddResult(res);
|
||||
if (!RetVal.hasRemaining || loadPaged)
|
||||
return RetVal;
|
||||
while (RetVal.hasRemaining)
|
||||
{
|
||||
if (!await RequestNextAsync(RetVal))
|
||||
return RetVal;
|
||||
}
|
||||
return RetVal;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogException(E);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<bool> RequestNextAsync(cCitrixResultList List)
|
||||
{
|
||||
try
|
||||
{
|
||||
var res = await privRequestAsync(List.NextResultUrl, autoRetry: List.retryForbidden);
|
||||
if (res != null)
|
||||
{
|
||||
List.AddResult(res);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogException(E);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public class cCitrixResultList : List<cCitrixResultBase>
|
||||
{
|
||||
public string NextResultUrl { get; private set; } = null;
|
||||
public bool retryForbidden { get; private set; } = false;
|
||||
|
||||
public cCitrixResultList(bool retryForbidden)
|
||||
{
|
||||
this.retryForbidden = retryForbidden;
|
||||
}
|
||||
|
||||
public bool hasRemaining
|
||||
{
|
||||
get
|
||||
{
|
||||
return !string.IsNullOrEmpty(NextResultUrl);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddResult(dynamic Result)
|
||||
{
|
||||
try
|
||||
{
|
||||
NextResultUrl = null;
|
||||
|
||||
if (Result.TryGetValue("@odata.nextLink", out JToken JT))
|
||||
{
|
||||
var JO = (JValue)JT;
|
||||
|
||||
NextResultUrl = Result["@odata.nextLink"];
|
||||
}
|
||||
|
||||
if (Result.TryGetValue("value", out JToken JT2))
|
||||
{
|
||||
foreach (dynamic Entry in Result.value)
|
||||
try
|
||||
{
|
||||
var val = new cCitrixResultBase(Entry);
|
||||
this.Add(val);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogException(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class cCitrixResultBase
|
||||
{
|
||||
public string ID { get; private set; } = null;
|
||||
public string ODataId { get; private set; } = null;
|
||||
public string DisplayName { get; private set; } = null;
|
||||
|
||||
public string Context { get; private set; } = null;
|
||||
|
||||
public dynamic Result { get; private set; } = null;
|
||||
|
||||
public cCitrixResultBase(dynamic Result, string namePropery = null)
|
||||
{
|
||||
this.Result = Result;
|
||||
|
||||
try { ID = Result.Id; } catch { }
|
||||
;
|
||||
try
|
||||
{
|
||||
if (namePropery == null)
|
||||
namePropery = "displayName";
|
||||
if (Result.TryGetValue(namePropery, out JToken JT1))
|
||||
{
|
||||
var _ty = JT1.GetType().ToString();
|
||||
if (JT1 is JValue _jVal)
|
||||
DisplayName = _jVal.Value?.ToString();
|
||||
}
|
||||
else if (Result.TryGetValue("name", out JToken JT2))
|
||||
DisplayName = Result.name;
|
||||
}
|
||||
catch { }
|
||||
try { Context = Result["@odata.context"]; } catch { }
|
||||
ODataId = GetStringFromDynamic(Result, "@odata.id");
|
||||
if (string.IsNullOrEmpty(ODataId))
|
||||
ODataId = @"https://api.cloud.com/" + ID;
|
||||
}
|
||||
|
||||
public cCitrixResultBase(cCitrixResultBase Result)
|
||||
{
|
||||
if (Result == null)
|
||||
return;
|
||||
|
||||
this.Result = Result.Result;
|
||||
ID = Result.ID;
|
||||
ODataId = Result.ODataId;
|
||||
DisplayName = Result.DisplayName;
|
||||
Context = Result.Context;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string GetStringFromDynamic(dynamic O, string ProperyName)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (string)O[ProperyName];
|
||||
}
|
||||
catch { }
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
134
F4SD-Cockpit-ServerCore/ConfigCache.cs
Normal file
134
F4SD-Cockpit-ServerCore/ConfigCache.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Web;
|
||||
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.XML;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
public class cConfigCacheEntry
|
||||
{
|
||||
public string FullPath { get; set; } = null;
|
||||
public DateTime TimeStamp { get; set; }
|
||||
public string Content { get; set; }
|
||||
|
||||
public static cConfigCacheEntry GetCacheEntry(enumFasdConfigurationType configType)
|
||||
{
|
||||
var output = new cConfigCacheEntry();
|
||||
|
||||
if (output.IsValidConfig(configType) && !string.IsNullOrEmpty(output.FullPath))
|
||||
{
|
||||
output.TimeStamp = File.GetLastWriteTimeUtc(output.FullPath);
|
||||
output.Content = File.ReadAllText(output.FullPath);
|
||||
return output;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool CheckIfNewerExists()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(FullPath))
|
||||
return false;
|
||||
|
||||
if (File.GetLastWriteTimeUtc(FullPath) > TimeStamp)
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsValidConfig(enumFasdConfigurationType configType)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
try
|
||||
{
|
||||
var RetVal = cFasdBaseConfig.GetConfigByType(configType);
|
||||
if (RetVal != null && RetVal.IsValid)
|
||||
{
|
||||
FullPath = RetVal.FilePath;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class cConfigCache
|
||||
{
|
||||
private static Dictionary<enumFasdConfigurationType, cConfigCacheEntry> Cache = new Dictionary<enumFasdConfigurationType, cConfigCacheEntry>();
|
||||
|
||||
public static cConfigCacheEntry Get(enumFasdConfigurationType configType)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
if (Cache.TryGetValue(configType, out var result))
|
||||
{
|
||||
if (!result.CheckIfNewerExists())
|
||||
return result;
|
||||
}
|
||||
|
||||
result = cConfigCacheEntry.GetCacheEntry(configType);
|
||||
|
||||
if (result != null)
|
||||
Cache[configType] = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
var _lst = Enum.GetValues(typeof(enumFasdConfigurationType)).Cast<enumFasdConfigurationType>();
|
||||
foreach (var _item in _lst)
|
||||
{
|
||||
if (_item != enumFasdConfigurationType.unknown)
|
||||
Get(_item);
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7575
F4SD-Cockpit-ServerCore/DataHistoryCollector.cs
Normal file
7575
F4SD-Cockpit-ServerCore/DataHistoryCollector.cs
Normal file
File diff suppressed because it is too large
Load Diff
3830
F4SD-Cockpit-ServerCore/DataHistoryCollectorActiveDirectory.cs
Normal file
3830
F4SD-Cockpit-ServerCore/DataHistoryCollectorActiveDirectory.cs
Normal file
File diff suppressed because it is too large
Load Diff
2959
F4SD-Cockpit-ServerCore/DataHistoryCollectorCitrix.cs
Normal file
2959
F4SD-Cockpit-ServerCore/DataHistoryCollectorCitrix.cs
Normal file
File diff suppressed because it is too large
Load Diff
2542
F4SD-Cockpit-ServerCore/DataHistoryCollectorClientAgent.cs
Normal file
2542
F4SD-Cockpit-ServerCore/DataHistoryCollectorClientAgent.cs
Normal file
File diff suppressed because it is too large
Load Diff
3413
F4SD-Cockpit-ServerCore/DataHistoryCollectorM42Wpm.cs
Normal file
3413
F4SD-Cockpit-ServerCore/DataHistoryCollectorM42Wpm.cs
Normal file
File diff suppressed because it is too large
Load Diff
2854
F4SD-Cockpit-ServerCore/DataHistoryCollectorNxql.cs
Normal file
2854
F4SD-Cockpit-ServerCore/DataHistoryCollectorNxql.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,92 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
public static class cDataHistoryCollectorSearchTaskCache
|
||||
{
|
||||
private static Dictionary<Guid, cDataHistoryCollectorSearchTaskEntry> taskCache = new Dictionary<Guid, cDataHistoryCollectorSearchTaskEntry>();
|
||||
|
||||
public static Guid AddTask(CancellationTokenSource cancellationToken, Task<cFasdApiSearchResultCollection> task)
|
||||
{
|
||||
var retVal = Guid.NewGuid();
|
||||
lock (taskCache)
|
||||
taskCache[retVal] = new cDataHistoryCollectorSearchTaskEntry() { cancellationTokenSource = cancellationToken, task = task };
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static void StopTask(Guid taskID)
|
||||
{
|
||||
cDataHistoryCollectorSearchTaskEntry _taskInfo;
|
||||
|
||||
lock (taskCache)
|
||||
{
|
||||
if (!taskCache.TryGetValue(taskID, out _taskInfo))
|
||||
{
|
||||
LogEntry($"StopSearchTask: Could not find task with ID: {taskID}");
|
||||
return;
|
||||
}
|
||||
taskCache.Remove(taskID);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LogEntry($"StopSearchTask: cancelling task: {taskID}");
|
||||
_taskInfo.cancellationTokenSource.Cancel(true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<cFasdApiSearchResultCollection> GetResultAsync(Guid taskID)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
try
|
||||
{
|
||||
cDataHistoryCollectorSearchTaskEntry _taskInfo;
|
||||
lock (taskCache)
|
||||
{
|
||||
if (!taskCache.TryGetValue(taskID, out _taskInfo))
|
||||
return null;
|
||||
}
|
||||
|
||||
cFasdApiSearchResultCollection _result = null;
|
||||
|
||||
try
|
||||
{
|
||||
_result = await _taskInfo.task;
|
||||
}
|
||||
catch { }
|
||||
|
||||
lock (taskCache) { taskCache.Remove(taskID); }
|
||||
|
||||
return _result;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal class cDataHistoryCollectorSearchTaskEntry
|
||||
{
|
||||
public CancellationTokenSource cancellationTokenSource;
|
||||
public Task<cFasdApiSearchResultCollection> task;
|
||||
}
|
||||
}
|
||||
405
F4SD-Cockpit-ServerCore/DataHistoryCollectorTokenCache.cs
Normal file
405
F4SD-Cockpit-ServerCore/DataHistoryCollectorTokenCache.cs
Normal file
@@ -0,0 +1,405 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.Security;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
public class cDataHistoryCollectorTokenCache
|
||||
{
|
||||
private const int timerCleanupInterval = 15 * 60 * 1000;
|
||||
|
||||
private System.Threading.Timer cleanupTimer;
|
||||
|
||||
private cDataHistoryCollector Collector;
|
||||
|
||||
private Dictionary<Guid, Dictionary<cF4SDTokenRegistration.enumTokenType, cTokenInfo>> dicToken = null;
|
||||
|
||||
public class cTokenInfo
|
||||
{
|
||||
public Guid id;
|
||||
public cF4SDTokenRegistration.enumTokenType type;
|
||||
public string name;
|
||||
public string name2;
|
||||
public string secret;
|
||||
public DateTime validUntil;
|
||||
public DateTime renewUntil;
|
||||
|
||||
public bool IsValid()
|
||||
{
|
||||
if (id == Guid.Empty)
|
||||
return false;
|
||||
if (validUntil < DateTime.UtcNow + TimeSpan.FromMinutes(cDataHistoryCollector.constMinutesUntilTokenIsInvalid))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public cTokenInfo GetNewInstance()
|
||||
{
|
||||
var _sec = secret;
|
||||
if (HasTokenTypeLongLifetime(type))
|
||||
_sec = cSecurePassword.Instance.Decode(secret);
|
||||
var _ret = new cTokenInfo()
|
||||
{
|
||||
id = id,
|
||||
type = type,
|
||||
name = name,
|
||||
name2 = name2,
|
||||
secret = _sec,
|
||||
validUntil = validUntil,
|
||||
renewUntil = renewUntil
|
||||
};
|
||||
|
||||
return _ret;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TokenCacheCriticalSection
|
||||
{
|
||||
private static SemaphoreSlim Semaphore = new SemaphoreSlim(1, 1);
|
||||
|
||||
public static async Task EnterAsync()
|
||||
{
|
||||
await Semaphore.WaitAsync();
|
||||
}
|
||||
|
||||
public static void Leave()
|
||||
{
|
||||
Semaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool HasTokenTypeLongLifetime(cF4SDTokenRegistration.enumTokenType tokenType)
|
||||
{
|
||||
switch (tokenType)
|
||||
{
|
||||
case cF4SDTokenRegistration.enumTokenType.M42Api:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public cDataHistoryCollectorTokenCache(cDataHistoryCollector Collector, cF4sdWebRequestInfo requestInfo, int LogDeep)
|
||||
{
|
||||
this.Collector = Collector;
|
||||
cleanupTimer = new System.Threading.Timer(async (x) => await DoCleanup(requestInfo, 0), null, timerCleanupInterval, timerCleanupInterval);
|
||||
}
|
||||
|
||||
private bool privInsert(cTokenInfo info, bool overwite)
|
||||
{
|
||||
if (dicToken == null)
|
||||
return false;
|
||||
|
||||
if (!dicToken.TryGetValue(info.id, out var _entyId))
|
||||
{
|
||||
_entyId = new Dictionary<cF4SDTokenRegistration.enumTokenType, cTokenInfo>();
|
||||
dicToken.Add(info.id, _entyId);
|
||||
}
|
||||
|
||||
if (!overwite && _entyId.ContainsKey(info.type))
|
||||
return false;
|
||||
|
||||
_entyId[info.type] = info;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task LoadAsync(cDbConnection DbConn, CancellationToken Token, cF4sdWebRequestInfo requestInfo, int LogDeep)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
|
||||
var _startTime = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
{
|
||||
if (dicToken == null)
|
||||
dicToken = new Dictionary<Guid, Dictionary<cF4SDTokenRegistration.enumTokenType, cTokenInfo>>();
|
||||
|
||||
if (!DataHistorySqlHelper.GetWellKnownSqlStatement("GetAllExternalTokens", out var Query))
|
||||
return;
|
||||
|
||||
var sqlerror = 0;
|
||||
var sqlStartTime = DateTime.UtcNow;
|
||||
|
||||
await TokenCacheCriticalSection.EnterAsync();
|
||||
try
|
||||
{
|
||||
dicToken.Clear();
|
||||
|
||||
using (var _reader = await DataHistorySqlHelper.GetDataReaderAsync(DbConn, Query, null, Token))
|
||||
{
|
||||
if (_reader != null)
|
||||
try
|
||||
{
|
||||
if (_reader.HasRows)
|
||||
{
|
||||
var _toDelete = new List<cTokenInfo>();
|
||||
while (await _reader.ReadAsync())
|
||||
{
|
||||
try
|
||||
{
|
||||
var _entry = new cTokenInfo();
|
||||
_entry.id = _reader.GetGuid(0);
|
||||
_entry.type = (cF4SDTokenRegistration.enumTokenType)_reader.GetInt32(1);
|
||||
_entry.name = _reader.IsDBNull(2) ? null : _reader.GetString(2);
|
||||
_entry.name2 = _reader.IsDBNull(3) ? null : _reader.GetString(3);
|
||||
var _secret = _reader.IsDBNull(4) ? null : _reader.GetString(4);
|
||||
if (HasTokenTypeLongLifetime(_entry.type))
|
||||
_entry.secret = _secret;
|
||||
else
|
||||
_entry.secret = cSecurePassword.Instance.Decode(_secret);
|
||||
_entry.validUntil = _reader.IsDBNull(5) ? DateTime.MinValue : _reader.GetDateTime(5);
|
||||
_entry.renewUntil = _reader.IsDBNull(6) ? DateTime.MinValue : _reader.GetDateTime(6);
|
||||
if (_entry.IsValid())
|
||||
{
|
||||
if (!privInsert(_entry, false))
|
||||
_toDelete.Add(_entry);
|
||||
}
|
||||
else
|
||||
_toDelete.Add(_entry);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogException(E);
|
||||
}
|
||||
|
||||
if (Token.IsCancellationRequested)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogException(E);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
sqlerror = E.HResult;
|
||||
cLogManager.DefaultLogger.LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TokenCacheCriticalSection.Leave();
|
||||
if (DataHistorySqlHelper.LogSql) DataHistorySqlHelper.SaveSqlTimingEntry(Query.Name, sqlStartTime, "", sqlerror);
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (cPerformanceLogger.IsActive && requestInfo != null) { cPerformanceLogger.LogPerformanceEnd(LogDeep, CM, requestInfo.id, requestInfo.created, _startTime); }
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SetAsync(cF4SDTokenRegistration _tokenRegistration, cF4SDTokenValidityPeriod validityPeriod, CancellationToken Token, cF4sdWebRequestInfo requestInfo, int LogDeep)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
|
||||
var _startTime = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
{
|
||||
// encryption of the secret for non-temporary tokens
|
||||
string _sec = _tokenRegistration.Secret;
|
||||
string _secEnc = cSecurePassword.Instance.Encode(_tokenRegistration.Secret);
|
||||
if (HasTokenTypeLongLifetime(_tokenRegistration.TokenType))
|
||||
_sec = _secEnc;
|
||||
|
||||
var _tokenInfo = new cTokenInfo()
|
||||
{
|
||||
id = _tokenRegistration.UserId,
|
||||
type = _tokenRegistration.TokenType,
|
||||
name = _tokenRegistration.Name,
|
||||
name2 = _tokenRegistration.Name2,
|
||||
secret = _sec,
|
||||
validUntil = validityPeriod.validUntil,
|
||||
renewUntil = validityPeriod.renewUntil
|
||||
};
|
||||
|
||||
if (!DataHistorySqlHelper.GetWellKnownSqlStatement("InsertOrUpdateExternalToken", out var Query))
|
||||
return;
|
||||
|
||||
var Params = new Dictionary<string, object>()
|
||||
{
|
||||
{ "Id", _tokenInfo.id },
|
||||
{ "Type", (int)_tokenInfo.type },
|
||||
{ "Name", _tokenInfo.name },
|
||||
{ "Name2", _tokenInfo.name2 },
|
||||
{ "Secret", _secEnc },
|
||||
{ "ValidUntil", _tokenInfo.validUntil },
|
||||
{ "RenewUntil", _tokenInfo.renewUntil },
|
||||
};
|
||||
|
||||
var sqlerror = 0;
|
||||
var sqlStartTime = DateTime.UtcNow;
|
||||
|
||||
await TokenCacheCriticalSection.EnterAsync();
|
||||
try
|
||||
{
|
||||
privInsert(_tokenInfo, true);
|
||||
|
||||
|
||||
using (var Conn = new cDbConnection(Collector.mainDbConnection))
|
||||
{
|
||||
if (!Conn.IsOpen)
|
||||
{
|
||||
LogEntry($"Could not open main database '{Collector.mainDbConnection.Database}', aborting query'", LogLevels.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
await DataHistorySqlHelper.ExecuteAsync(Conn, Query, Params, requestInfo, Token);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
sqlerror = E.HResult;
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TokenCacheCriticalSection.Leave();
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (cPerformanceLogger.IsActive && requestInfo != null) { cPerformanceLogger.LogPerformanceEnd(LogDeep, CM, requestInfo.id, requestInfo.created, _startTime); }
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<cTokenInfo> GetAsync(Guid UserId, cF4SDTokenRegistration.enumTokenType TokenType, cF4sdWebRequestInfo requestInfo, int LogDeep)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
if (dicToken == null)
|
||||
return null;
|
||||
|
||||
var doCleanup = false;
|
||||
try
|
||||
{
|
||||
await TokenCacheCriticalSection.EnterAsync();
|
||||
if (dicToken.TryGetValue(UserId, out var _entry))
|
||||
if (_entry.TryGetValue(TokenType, out var _tokenInfo))
|
||||
{
|
||||
if (_tokenInfo.validUntil < DateTime.UtcNow)
|
||||
return null;
|
||||
|
||||
return _tokenInfo.GetNewInstance();
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TokenCacheCriticalSection.Leave();
|
||||
if (doCleanup)
|
||||
await DoCleanup(requestInfo, LogDeep + 1);
|
||||
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task DoCleanup(cF4sdWebRequestInfo requestInfo, int LogDeep)
|
||||
{
|
||||
if (dicToken == null)
|
||||
return;
|
||||
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
|
||||
var _startTime = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
{
|
||||
var _current = DateTime.UtcNow;
|
||||
// remove all expiered tokens in the cache
|
||||
await TokenCacheCriticalSection.EnterAsync();
|
||||
cleanupTimer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
var _toRemove1 = new List<Guid>();
|
||||
foreach (var _entry in dicToken)
|
||||
{
|
||||
var _toRemove2 = new List<cF4SDTokenRegistration.enumTokenType>();
|
||||
foreach (var _tokenInfoPair in _entry.Value)
|
||||
{
|
||||
if (_tokenInfoPair.Value.validUntil < _current)
|
||||
_toRemove2.Add(_tokenInfoPair.Key);
|
||||
}
|
||||
|
||||
foreach (var token in _toRemove2)
|
||||
_entry.Value.Remove(token);
|
||||
|
||||
if (_entry.Value.Count == 0)
|
||||
_toRemove1.Add(_entry.Key);
|
||||
}
|
||||
foreach (var _entry in _toRemove1)
|
||||
dicToken.Remove(_entry);
|
||||
|
||||
// synchronize the sql table with the cache
|
||||
if (!DataHistorySqlHelper.GetWellKnownSqlStatement("RemoveExpieredExternalTokens", out var Query))
|
||||
return;
|
||||
|
||||
// remove the expired tokens
|
||||
var Params = new Dictionary<string, object>()
|
||||
{
|
||||
{ "ValidUntil", _current }
|
||||
};
|
||||
|
||||
var sqlStartTime = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
using (var Conn = new cDbConnection(Collector.mainDbConnection))
|
||||
{
|
||||
if (!Conn.IsOpen)
|
||||
{
|
||||
LogEntry($"Could not open main database '{Collector.mainDbConnection.Database}', aborting query'", LogLevels.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var _n = await DataHistorySqlHelper.ExecuteAsync(Conn, Query, Params, requestInfo, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TokenCacheCriticalSection.Leave();
|
||||
cleanupTimer.Change(timerCleanupInterval, timerCleanupInterval);
|
||||
if (cPerformanceLogger.IsActive && requestInfo != null) { cPerformanceLogger.LogPerformanceEnd(LogDeep, CM, requestInfo.id, requestInfo.created, _startTime); }
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
647
F4SD-Cockpit-ServerCore/DataHistoryConfigActiveDirectory.cs
Normal file
647
F4SD-Cockpit-ServerCore/DataHistoryConfigActiveDirectory.cs
Normal file
@@ -0,0 +1,647 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.Security;
|
||||
using C4IT.XML;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
public class cDataHistoryConfigActiveDirectory : IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; private set; } = false;
|
||||
|
||||
public bool ScanPhoneNumbers { get; private set; } = false;
|
||||
|
||||
public cDataHistoryScanTiming ScanTiming { get; private set; } = null;
|
||||
|
||||
|
||||
public Dictionary<string, cDataHistoryAdDomain> Domains { get; private set; } = new Dictionary<string, cDataHistoryAdDomain>();
|
||||
public Dictionary<string, cDataHistoryAdScan> Scans { get; private set; } = new Dictionary<string, cDataHistoryAdScan>();
|
||||
|
||||
public cDataHistoryConfigActiveDirectory(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
var XNode2 = XNode.SelectSingleNode("Active-Directory");
|
||||
if (!(XNode2 is XmlElement XRoot))
|
||||
{
|
||||
Parser.AddMessage(XNode, "Could not find a valid <Active-Directory> element.");
|
||||
return;
|
||||
}
|
||||
|
||||
Parser.EnterElement("Active-Directory");
|
||||
try
|
||||
{
|
||||
ScanPhoneNumbers = cXmlParser.GetBoolFromXmlAttribute(XNode2, "ScanPhoneNumbers");
|
||||
|
||||
ScanTiming = new cDataHistoryScanTiming(XRoot, TimeSpan.FromHours(24), TimeSpan.FromMinutes(10), Parser);
|
||||
|
||||
Domains = cDataHistoryAdDomain.LoadFromXml(XRoot, Credentials, Parser);
|
||||
if (Domains == null || Domains.Count == 0)
|
||||
{
|
||||
Parser.AddMessage(XNode, "The element <Active-Directory> has no valid <AD-Domain> entries.");
|
||||
return;
|
||||
}
|
||||
|
||||
Scans = cDataHistoryAdScan.LoadFromXml(XRoot, this, Parser);
|
||||
if (Scans == null || Scans.Count == 0)
|
||||
{
|
||||
Parser.AddMessage(XNode, "The element <Active-Directory> has no valid <AD-Scan> entries.");
|
||||
return;
|
||||
}
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Active-Directory");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class cDataHistoryAdScan : cConfigNodeNamed
|
||||
{
|
||||
public enumFasdInformationClass Type { get; private set; }
|
||||
|
||||
public List<cDataHistoryAdScanNode> ScanNodes { get; private set; } = new List<cDataHistoryAdScanNode>();
|
||||
|
||||
internal cDataHistoryAdScan(XmlElement XNode, cDataHistoryConfigActiveDirectory AdConfig, cXmlParser Parser) :
|
||||
base(XNode, Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
if (!IsValid)
|
||||
return;
|
||||
|
||||
IsValid = false;
|
||||
|
||||
Type = (enumFasdInformationClass)cXmlParser.GetEnumFromAttribute<enumFasdInformationClass>(XNode, "Type", enumFasdInformationClass.Unknown);
|
||||
if (Type != enumFasdInformationClass.User && Type != enumFasdInformationClass.Computer)
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Name, "AD-Type");
|
||||
return;
|
||||
}
|
||||
|
||||
ScanNodes = cDataHistoryAdScanNode.LoadFromXml(XNode, AdConfig, this, Parser);
|
||||
|
||||
if (ScanNodes == null || ScanNodes.Count == 0)
|
||||
{
|
||||
Parser.AddMessage(XNode, "The <AD-Scan> element has no valid <AD-Scan-Node> entries.");
|
||||
return;
|
||||
}
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
internal static Dictionary<string, cDataHistoryAdScan> LoadFromXml(XmlElement XNode, cDataHistoryConfigActiveDirectory AdConfig, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var RetVal = new Dictionary<string, cDataHistoryAdScan>();
|
||||
|
||||
try
|
||||
{
|
||||
var XRoot = XNode.SelectSingleNode("AD-Scans");
|
||||
if (XRoot == null)
|
||||
{
|
||||
Parser.AddMessage(XNode, $"No <AD-Scans> element found within element <{XNode.Name}>.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Parser.EnterElement("AD-Scans");
|
||||
try
|
||||
{
|
||||
var XList = XRoot.SelectNodes("AD-Scan");
|
||||
if (XList != null && XList.Count > 0)
|
||||
{
|
||||
Parser.EnterElement("AD-Scan");
|
||||
try
|
||||
{
|
||||
foreach (var Entry in XList)
|
||||
{
|
||||
if (!(Entry is XmlElement XEntry))
|
||||
continue;
|
||||
|
||||
var Node = new cDataHistoryAdScan(XEntry, AdConfig, Parser);
|
||||
if (Node.IsValid)
|
||||
{
|
||||
if (RetVal.ContainsKey(Node.Name))
|
||||
{
|
||||
Parser.AddDuplicateName(XEntry, Node.Name, LogLevels.Warning);
|
||||
}
|
||||
else
|
||||
RetVal.Add(Node.Name, Node);
|
||||
}
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("AD-Scan");
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("AD-Scans");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class cDataHistoryAdScanNode : IConfigNodeValidation
|
||||
{
|
||||
public enum enumFilterPropery { unknown = 0, commonName, distinguishedName, samAccountName }
|
||||
|
||||
public bool IsValid { get; private set; } = false;
|
||||
public cDataHistoryAdDomain AdDomain { get; private set; }
|
||||
public string Path { get; private set; }
|
||||
public string LdapFilter { get; private set; }
|
||||
public enumFilterPropery FilterProperty { get; private set; } = enumFilterPropery.unknown;
|
||||
public bool WildcardFilterNot { get; private set; } = false;
|
||||
public Regex WildcardFilter { get; private set; }
|
||||
public Regex RegExFilter { get; private set; }
|
||||
|
||||
public cDataHistoryAdScan parentScan { get; private set; }
|
||||
|
||||
internal cDataHistoryAdScanNode(XmlElement XNode, cDataHistoryConfigActiveDirectory AdConfig, cDataHistoryAdScan Scan, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
parentScan = Scan;
|
||||
var strAdDomain = cXmlParser.GetStringFromXmlAttribute(XNode, "AD-Domain");
|
||||
if (!AdConfig.Domains.TryGetValue(strAdDomain, out var AdD))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, null, "AD-Domain");
|
||||
return;
|
||||
}
|
||||
AdDomain = AdD;
|
||||
|
||||
Path = cXmlParser.GetStringFromXmlAttribute(XNode, "Path", "");
|
||||
|
||||
LdapFilter = cXmlParser.GetStringFromXmlAttribute(XNode, "LDAP-Filter");
|
||||
|
||||
FilterProperty = cXmlParser.GetEnumFromAttribute<enumFilterPropery>(XNode, "Filter-Property", enumFilterPropery.unknown);
|
||||
|
||||
var strWildcardFilter = cXmlParser.GetStringFromXmlAttribute(XNode, "Wildcard-Filter");
|
||||
if (!string.IsNullOrEmpty(strWildcardFilter))
|
||||
{
|
||||
if (strWildcardFilter.StartsWith("!"))
|
||||
{
|
||||
WildcardFilterNot = true;
|
||||
strWildcardFilter.Remove(0, 1);
|
||||
}
|
||||
var _expression = "^" + Regex.Escape(strWildcardFilter)
|
||||
.Replace("\\\\\\?", "??").Replace("\\?", ".").Replace("??", "\\?")
|
||||
.Replace("\\\\\\*", "**").Replace("\\*", ".*").Replace("**", "\\*") + "$";
|
||||
WildcardFilter = new Regex(_expression, RegexOptions.Compiled);
|
||||
}
|
||||
|
||||
var strRexExFilter = cXmlParser.GetStringFromXmlAttribute(XNode, "RegEx-Filter");
|
||||
if (!string.IsNullOrEmpty(strRexExFilter))
|
||||
RegExFilter = new Regex(strRexExFilter, RegexOptions.Compiled);
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
internal static List<cDataHistoryAdScanNode> LoadFromXml(XmlElement XNode, cDataHistoryConfigActiveDirectory AdConfig, cDataHistoryAdScan Scan, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var RetVal = new List<cDataHistoryAdScanNode>();
|
||||
try
|
||||
{
|
||||
var XList = XNode.SelectNodes("AD-Scan-Node");
|
||||
if (XList != null && XList.Count > 0)
|
||||
{
|
||||
Parser.EnterElement("AD-Scan-Node");
|
||||
try
|
||||
{
|
||||
foreach (var Entry in XList)
|
||||
{
|
||||
if (!(Entry is XmlElement XEntry))
|
||||
continue;
|
||||
|
||||
var Node = new cDataHistoryAdScanNode(XEntry, AdConfig, Scan, Parser);
|
||||
if (Node.IsValid)
|
||||
RetVal.Add(Node);
|
||||
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("AD-Scan-Node");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
}
|
||||
|
||||
public class cDataHistoryAdDomain : cConfigNodeNamed
|
||||
{
|
||||
public string FQDN { get; private set; } = null;
|
||||
public cCredential Credential { get; private set; } = null;
|
||||
|
||||
public List<cDataHistoryAdServer> Servers { get; private set; } = new List<cDataHistoryAdServer>();
|
||||
|
||||
internal cDataHistoryAdDomain(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser) :
|
||||
base(XNode, Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
if (!IsValid)
|
||||
return;
|
||||
|
||||
IsValid = false;
|
||||
|
||||
FQDN = cXmlParser.GetStringFromXmlAttribute(XNode, "FQDN");
|
||||
if (string.IsNullOrWhiteSpace(FQDN))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, null, "FQDN");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
var strCreds = cXmlParser.GetStringFromXmlAttribute(XNode, "Credential");
|
||||
if (!string.IsNullOrWhiteSpace(strCreds))
|
||||
{
|
||||
if (Credentials.TryGetValue(strCreds, out var Cred))
|
||||
Credential = Cred;
|
||||
}
|
||||
|
||||
if (Credential == null)
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Name, "Credential");
|
||||
return;
|
||||
}
|
||||
|
||||
Servers = cDataHistoryAdServer.LoadFromXml(XNode, Parser);
|
||||
if (Servers?.Count == 0)
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Name, "No valid <AD-Server> element could be found.");
|
||||
return;
|
||||
}
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
internal static Dictionary<string, cDataHistoryAdDomain> LoadFromXml(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var RetVal = new Dictionary<string, cDataHistoryAdDomain>();
|
||||
|
||||
try
|
||||
{
|
||||
var XRoot = XNode.SelectSingleNode("AD-Domains");
|
||||
if (XRoot == null)
|
||||
{
|
||||
Parser.AddMessage(XNode, $"No <AD-Domains> element found within element <{XNode.Name}>.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Parser.EnterElement("AD-Domains");
|
||||
try
|
||||
{
|
||||
var XList = XRoot.SelectNodes("AD-Domain");
|
||||
if (XList != null && XList.Count > 0)
|
||||
{
|
||||
Parser.EnterElement("AD-Domain");
|
||||
try
|
||||
{
|
||||
foreach (var Entry in XList)
|
||||
{
|
||||
if (!(Entry is XmlElement XEntry))
|
||||
continue;
|
||||
|
||||
var Node = new cDataHistoryAdDomain(XEntry, Credentials, Parser);
|
||||
if (Node.IsValid)
|
||||
{
|
||||
if (RetVal.ContainsKey(Node.Name))
|
||||
{
|
||||
Parser.AddDuplicateName(XEntry, Node.Name, LogLevels.Warning);
|
||||
}
|
||||
else
|
||||
RetVal.Add(Node.Name, Node);
|
||||
}
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("AD-Domain");
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("AD-Domains");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
}
|
||||
|
||||
public class cDataHistoryAdServer : IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; private set; } = false;
|
||||
public string FQDN { get; private set; }
|
||||
public int Port { get; private set; }
|
||||
public bool useSSL { get; private set; }
|
||||
|
||||
internal cDataHistoryAdServer(XmlElement XNode, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
FQDN = cXmlParser.GetStringFromXmlAttribute(XNode, "FQDN");
|
||||
if (string.IsNullOrWhiteSpace(FQDN))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, null, "FQDN");
|
||||
return;
|
||||
}
|
||||
|
||||
Port = cXmlParser.GetIntegerFromXmlAttribute(XNode, "Port");
|
||||
useSSL = cXmlParser.GetBoolFromXmlAttribute(XNode, "UseSSL");
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
internal static List<cDataHistoryAdServer> LoadFromXml(XmlElement XNode, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var RetVal = new List<cDataHistoryAdServer>();
|
||||
try
|
||||
{
|
||||
var XList = XNode.SelectNodes("AD-Server");
|
||||
if (XList != null && XList.Count > 0)
|
||||
{
|
||||
Parser.EnterElement("AD-Server");
|
||||
try
|
||||
{
|
||||
foreach (var Entry in XList)
|
||||
{
|
||||
if (!(Entry is XmlElement XEntry))
|
||||
continue;
|
||||
|
||||
var Node = new cDataHistoryAdServer(XEntry, Parser);
|
||||
if (Node.IsValid)
|
||||
RetVal.Add(Node);
|
||||
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("AD-Server");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
}
|
||||
|
||||
public class cDataHistoryAzureTenant : IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; private set; } = false;
|
||||
|
||||
public string Domain { get; private set; } = "";
|
||||
|
||||
public Guid TenantID { get; private set; } = Guid.Empty;
|
||||
|
||||
public cCredential Credential { get; private set; } = null;
|
||||
public bool ScanIntuneDevices { get; private set; } = false;
|
||||
public bool WithMobileDevices { get; private set; } = false;
|
||||
|
||||
internal cDataHistoryAzureTenant(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
Domain = cXmlParser.GetStringFromXmlAttribute(XNode, "Domain");
|
||||
if (string.IsNullOrWhiteSpace(Domain))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, null, "Domain");
|
||||
return;
|
||||
}
|
||||
TenantID = cXmlParser.GetGuidFromXmlAttribute(XNode, "TenantID");
|
||||
if (TenantID == Guid.Empty)
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Domain, "TenantID");
|
||||
return;
|
||||
}
|
||||
|
||||
var strCreds = cXmlParser.GetStringFromXmlAttribute(XNode, "Credential");
|
||||
if (!string.IsNullOrWhiteSpace(strCreds))
|
||||
{
|
||||
if (Credentials.TryGetValue(strCreds, out var Cred))
|
||||
Credential = Cred;
|
||||
}
|
||||
|
||||
if (Credential == null)
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Domain, "Credential");
|
||||
return;
|
||||
}
|
||||
ScanIntuneDevices = cXmlParser.GetBoolFromXmlAttribute(XNode, "ScanIntuneDevices");
|
||||
WithMobileDevices = cXmlParser.GetBoolFromXmlAttribute(XNode, "WithMobileDevices");
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
internal static Dictionary<string, cDataHistoryAzureTenant> LoadFromXml(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var RetVal = new Dictionary<string, cDataHistoryAzureTenant>();
|
||||
|
||||
try
|
||||
{
|
||||
var XRoot = XNode.SelectSingleNode("Azure-AD");
|
||||
if (XRoot == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Parser.EnterElement("Azure-AD");
|
||||
try
|
||||
{
|
||||
var XList = XRoot.SelectNodes("Azure-Tenant");
|
||||
if (XList != null && XList.Count > 0)
|
||||
{
|
||||
Parser.EnterElement("Azure-Tenant");
|
||||
try
|
||||
{
|
||||
foreach (var Entry in XList)
|
||||
{
|
||||
if (!(Entry is XmlElement XEntry))
|
||||
continue;
|
||||
|
||||
var Node = new cDataHistoryAzureTenant(XEntry, Credentials, Parser);
|
||||
if (Node.IsValid)
|
||||
{
|
||||
if (RetVal.ContainsKey(Node.Domain))
|
||||
{
|
||||
Parser.AddDuplicateName(XEntry, Node.Domain, LogLevels.Warning);
|
||||
}
|
||||
else
|
||||
RetVal.Add(Node.Domain, Node);
|
||||
}
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Azure-Tenant");
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Azure-AD");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class cWildcardPattern
|
||||
{
|
||||
private readonly string _expression;
|
||||
private readonly Regex _regex;
|
||||
|
||||
public cWildcardPattern(string pattern)
|
||||
{
|
||||
if (string.IsNullOrEmpty(pattern)) throw new ArgumentNullException(nameof(pattern));
|
||||
|
||||
_expression = "^" + Regex.Escape(pattern)
|
||||
.Replace("\\\\\\?", "??").Replace("\\?", ".").Replace("??", "\\?")
|
||||
.Replace("\\\\\\*", "**").Replace("\\*", ".*").Replace("**", "\\*") + "$";
|
||||
_regex = new Regex(_expression, RegexOptions.Compiled);
|
||||
}
|
||||
|
||||
public bool IsMatch(string value)
|
||||
{
|
||||
return _regex.IsMatch(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
188
F4SD-Cockpit-ServerCore/DataHistoryConfigCitrix.cs
Normal file
188
F4SD-Cockpit-ServerCore/DataHistoryConfigCitrix.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
using C4IT.DataHistoryProvider;
|
||||
using C4IT.Logging;
|
||||
using C4IT.Security;
|
||||
using C4IT.XML;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT_DataHistoryProvider
|
||||
{
|
||||
public class cDataHistoryConfigCitrix : IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; private set; } = false;
|
||||
|
||||
public string Domain { get; private set; } = "";
|
||||
|
||||
public string TenantID { get; private set; } = String.Empty;
|
||||
|
||||
public cCredential Credential { get; private set; } = null;
|
||||
public cDataHistoryScanTiming ScanTiming { get; private set; } = null;
|
||||
public cDataHistoryConfigCitrix(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
|
||||
var XNode2 = XNode.SelectSingleNode("Citrix");
|
||||
if (!(XNode2 is XmlElement XCitrix))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Parser.EnterElement("Citrix");
|
||||
|
||||
try
|
||||
{
|
||||
ScanTiming = new cDataHistoryScanTiming(XCitrix, TimeSpan.FromHours(24), TimeSpan.FromMinutes(10), Parser);
|
||||
IsValid = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Citrix");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class cDataHistoryCitrixTenant : IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; private set; } = false;
|
||||
|
||||
public string Domain { get; private set; } = "";
|
||||
|
||||
public string TenantID { get; private set; } = String.Empty;
|
||||
public string InstanceID { get; private set; } = String.Empty;
|
||||
|
||||
public cCredential Credential { get; private set; } = null;
|
||||
|
||||
internal cDataHistoryCitrixTenant(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
Domain = cXmlParser.GetStringFromXmlAttribute(XNode, "Domain");
|
||||
if (string.IsNullOrWhiteSpace(Domain))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, null, "Domain");
|
||||
return;
|
||||
}
|
||||
TenantID = cXmlParser.GetStringFromXmlAttribute(XNode, "TenantID");
|
||||
if (TenantID == String.Empty)
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Domain, "TenantID");
|
||||
return;
|
||||
}
|
||||
|
||||
InstanceID = cXmlParser.GetStringFromXmlAttribute(XNode, "InstanceID");
|
||||
if (InstanceID == String.Empty)
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Domain, "InstanceID");
|
||||
return;
|
||||
}
|
||||
|
||||
var strCreds = cXmlParser.GetStringFromXmlAttribute(XNode, "Credential");
|
||||
if (!string.IsNullOrWhiteSpace(strCreds))
|
||||
{
|
||||
if (Credentials.TryGetValue(strCreds, out var Cred))
|
||||
Credential = Cred;
|
||||
}
|
||||
|
||||
if (Credential == null)
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Domain, "Credential");
|
||||
return;
|
||||
}
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
internal static Dictionary<string, cDataHistoryCitrixTenant> LoadFromXml(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var RetVal = new Dictionary<string, cDataHistoryCitrixTenant>();
|
||||
|
||||
try
|
||||
{
|
||||
var XRoot = XNode.SelectSingleNode("Citrix");
|
||||
if (XRoot == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Parser.EnterElement("Citrix");
|
||||
try
|
||||
{
|
||||
|
||||
var XList = XRoot.SelectNodes("Citrix-Tenant");
|
||||
if (XList != null && XList.Count > 0)
|
||||
{
|
||||
Parser.EnterElement("Citrix-Tenant");
|
||||
try
|
||||
{
|
||||
foreach (var Entry in XList)
|
||||
{
|
||||
if (!(Entry is XmlElement XEntry))
|
||||
continue;
|
||||
|
||||
var Node = new cDataHistoryCitrixTenant(XEntry, Credentials, Parser);
|
||||
if (Node.IsValid)
|
||||
{
|
||||
if (RetVal.ContainsKey(Node.Domain))
|
||||
{
|
||||
Parser.AddDuplicateName(XEntry, Node.Domain, LogLevels.Warning);
|
||||
}
|
||||
else
|
||||
RetVal.Add(Node.Domain, Node);
|
||||
}
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Citrix-Tenant");
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Citrix");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
229
F4SD-Cockpit-ServerCore/DataHistoryConfigClientAgent.cs
Normal file
229
F4SD-Cockpit-ServerCore/DataHistoryConfigClientAgent.cs
Normal file
@@ -0,0 +1,229 @@
|
||||
using C4IT.Logging;
|
||||
using C4IT.Security;
|
||||
using C4IT.XML;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
public class cDataHistoryConfigClientAgent : IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; set; } = false;
|
||||
|
||||
public cDataHistoryConfigSqlConnection Connection { get; private set; } = null;
|
||||
|
||||
public Uri ServerUri { get; private set; } = null;
|
||||
|
||||
public int MaxDeviceAge { get; private set; } = 30;
|
||||
|
||||
public Uri ApiPath { get; private set; } = null;
|
||||
|
||||
public cCredential ApiCredential { get; private set; } = null;
|
||||
|
||||
public string ApiSecret { get; private set; } = null;
|
||||
|
||||
public string Organization { get; private set; } = null;
|
||||
|
||||
public cDataHistoryScanTiming ScanTiming { get; private set; } = null;
|
||||
|
||||
public List<cDataHistoryConfigLocalAccountAssignment> localAccountAssignments = null;
|
||||
|
||||
|
||||
internal cDataHistoryConfigClientAgent(XmlElement XNode, Dictionary<string, cCredential> Credentials, Dictionary<string, cDataHistoryConfigDbConnection> DbConnections, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
if (!(XNode.SelectSingleNode("ClientAgent") is XmlElement XNode2))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The root element <{XNode.Name}> does not have a <ClientAgent> element.");
|
||||
return;
|
||||
}
|
||||
|
||||
Parser.EnterElement("ClientAgent");
|
||||
|
||||
try
|
||||
{
|
||||
var strConnection = cXmlParser.GetStringFromXmlAttribute(XNode2, "DB-Connection");
|
||||
if (string.IsNullOrWhiteSpace(strConnection))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The element <{XNode2.Name}> does not have a 'DB-Connection' attribute.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DbConnections.TryGetValue(strConnection, out var Conn))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"Could not find a DB connection '{strConnection}' in element <{XNode2.Name}>.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(Conn is cDataHistoryConfigSqlConnection SqlConn))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The DB connection '{strConnection}' in element <{XNode2.Name}> has to be a SQL connection.");
|
||||
return;
|
||||
}
|
||||
|
||||
var strServerUri = cXmlParser.GetStringFromXmlAttribute(XNode2, "Server-Url", "");
|
||||
if (!Uri.TryCreate(strServerUri, UriKind.Absolute, out var _uri))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The attribute 'Server-Url' in element <{XNode2.Name}> is not a valid URL.");
|
||||
return;
|
||||
}
|
||||
ServerUri = _uri;
|
||||
|
||||
strServerUri = cXmlParser.GetStringFromXmlAttribute(XNode2, "Api-Path", "api/management");
|
||||
if (!Uri.TryCreate(strServerUri, UriKind.Relative, out _uri))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The attribute 'Api-Path' in element <{XNode2.Name}> is not a valid URL path.");
|
||||
return;
|
||||
}
|
||||
ApiPath = _uri;
|
||||
|
||||
|
||||
Organization = cXmlParser.GetStringFromXmlAttribute(XNode2, "Organization");
|
||||
|
||||
MaxDeviceAge = cXmlParser.GetIntegerFromXmlAttribute(XNode2, "MaxDeviceAge", 30);
|
||||
if (MaxDeviceAge <= 0)
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The attribute 'MaxDeviceAge' in element <{XNode2.Name}> is not a valid positive number of days.");
|
||||
return;
|
||||
}
|
||||
Connection = SqlConn;
|
||||
|
||||
var strCredential = cXmlParser.GetStringFromXmlAttribute(XNode2, "Api-Credential");
|
||||
if (string.IsNullOrWhiteSpace(strCredential))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, null, "Api-Credential");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Credentials.TryGetValue(strCredential, out var _Cred))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The credential attribute value '{strCredential}' of the element <{XNode.Name}> coud not be resolved.");
|
||||
return;
|
||||
}
|
||||
ApiCredential = _Cred;
|
||||
ApiSecret = cSecurePassword.Instance.Encode(_Cred.NwCredential.Password);
|
||||
|
||||
ScanTiming = new cDataHistoryScanTiming(XNode2, TimeSpan.FromHours(1), TimeSpan.FromMinutes(10), Parser);
|
||||
|
||||
localAccountAssignments = cDataHistoryConfigLocalAccountAssignment.LoadFromXml(XNode2, Parser);
|
||||
|
||||
IsValid = true;
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("ClientAgent");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class cDataHistoryConfigLocalAccountAssignment : IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; set; } = false;
|
||||
public string Domain = null;
|
||||
public string DomainDns = null;
|
||||
public string RegExFilter = null;
|
||||
public string AccountMask = null;
|
||||
|
||||
internal cDataHistoryConfigLocalAccountAssignment(XmlElement XNode, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
Domain = cXmlParser.GetStringFromXmlAttribute(XNode, "Domain");
|
||||
if (string.IsNullOrEmpty(Domain))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, null, "Domain", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
RegExFilter = cXmlParser.GetStringFromXmlAttribute(XNode, "RegExFilter");
|
||||
AccountMask = cXmlParser.GetStringFromXmlAttribute(XNode, "AccountMask");
|
||||
if (!string.IsNullOrEmpty(AccountMask) && !AccountMask.Contains("*"))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The <{XNode.Name}> element with Domain='{Domain}' has no '*' placeholder in the 'AccountMask' attribute.", LogLevels.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
internal static List<cDataHistoryConfigLocalAccountAssignment> LoadFromXml(XmlElement XNode, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
var XDataClusters = XNode.SelectNodes("Local-Account-Assignment");
|
||||
if (XDataClusters == null || XDataClusters.Count <= 0)
|
||||
return null;
|
||||
|
||||
Parser.EnterElement("Local-Account-Assignment");
|
||||
var RetVal = new List<cDataHistoryConfigLocalAccountAssignment>(XDataClusters.Count);
|
||||
try
|
||||
{
|
||||
foreach (XmlNode XNode2 in XDataClusters)
|
||||
{
|
||||
if (!(XNode2 is XmlElement XDataCluster))
|
||||
continue;
|
||||
|
||||
var LocalAssignment = new cDataHistoryConfigLocalAccountAssignment(XDataCluster, Parser);
|
||||
if ((LocalAssignment != null) && (LocalAssignment.IsValid))
|
||||
{
|
||||
RetVal.Add(LocalAssignment);
|
||||
}
|
||||
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Local-Account-Assignment");
|
||||
}
|
||||
|
||||
if (RetVal.Count > 0)
|
||||
return RetVal;
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
2659
F4SD-Cockpit-ServerCore/DataHistoryConfigClusters.cs
Normal file
2659
F4SD-Cockpit-ServerCore/DataHistoryConfigClusters.cs
Normal file
File diff suppressed because it is too large
Load Diff
171
F4SD-Cockpit-ServerCore/DataHistoryConfigDbConnection.cs
Normal file
171
F4SD-Cockpit-ServerCore/DataHistoryConfigDbConnection.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
using C4IT.Logging;
|
||||
using C4IT.Security;
|
||||
using C4IT.XML;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
public abstract class cDataHistoryConfigDbConnection : cConfigNodeNamed
|
||||
{
|
||||
internal cDataHistoryConfigDbConnection(XmlElement XNode, cXmlParser Parser) :
|
||||
base(XNode, Parser)
|
||||
{
|
||||
}
|
||||
|
||||
static public Dictionary<string, cDataHistoryConfigDbConnection> LoadListFromXml(XmlElement XNode, cXmlParser Parser, Dictionary<string, cCredential> Credentials)
|
||||
{
|
||||
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
|
||||
var RetVal = new Dictionary<string, cDataHistoryConfigDbConnection>();
|
||||
|
||||
try
|
||||
{
|
||||
XmlNode LRoot = XNode;
|
||||
LRoot = XNode.SelectSingleNode("DB-Connections");
|
||||
if (LRoot == null)
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The <{XNode.Name}> does not contain a element 'DB-Connections'", LogLevels.Error);
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
Parser.EnterElement("DB-Connections");
|
||||
|
||||
// cluster the db commections in a dictionary by db connection type (element node)
|
||||
var XList = LRoot.SelectNodes("SQL-Connection");
|
||||
var lstConnectionNodes = new Dictionary<string, List<XmlElement>>();
|
||||
foreach (XmlNode Entry in XList)
|
||||
{
|
||||
if (!(Entry is XmlElement XDbNode))
|
||||
continue;
|
||||
|
||||
if (!lstConnectionNodes.TryGetValue(XDbNode.Name, out var lstConn))
|
||||
{
|
||||
lstConn = new List<XmlElement>() { XDbNode };
|
||||
lstConnectionNodes.Add(XDbNode.Name, lstConn);
|
||||
}
|
||||
else
|
||||
lstConn.Add(XDbNode);
|
||||
}
|
||||
|
||||
if (lstConnectionNodes.Count == 0)
|
||||
{
|
||||
Parser.AddMessage(XNode, "No valid DB connection entries could be found in the infrastructure configuration.", LogLevels.Error);
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
// parse the clustered db connection nodes
|
||||
foreach (var lstDbConn in lstConnectionNodes)
|
||||
{
|
||||
Parser.EnterElement(lstDbConn.Key);
|
||||
foreach (var XDbConn in lstDbConn.Value)
|
||||
{
|
||||
cDataHistoryConfigDbConnection DbConn = null;
|
||||
switch (lstDbConn.Key)
|
||||
{
|
||||
case "SQL-Connection":
|
||||
DbConn = new cDataHistoryConfigSqlConnection(XDbConn, Credentials, Parser);
|
||||
break;
|
||||
default:
|
||||
Parser.AddMessage(XDbConn, $"The element '<{lstDbConn.Key}>' is not a valid DB connection element.", LogLevels.Error);
|
||||
break;
|
||||
}
|
||||
if (DbConn != null)
|
||||
RetVal.Add(DbConn.Name, DbConn);
|
||||
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
Parser.LeaveElement(lstDbConn.Key);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("DB-Connections");
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class cDataHistoryConfigSqlConnection : cDataHistoryConfigDbConnection
|
||||
{
|
||||
public cCredential Credential { get; private set; } = null;
|
||||
|
||||
public bool NativeAccount { get; private set; }
|
||||
|
||||
public string Server { get; private set; }
|
||||
|
||||
public string Instance { get; private set; }
|
||||
|
||||
public string Database { get; private set; }
|
||||
|
||||
public int Timeout { get; private set; } = -1;
|
||||
|
||||
internal cDataHistoryConfigSqlConnection(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser) :
|
||||
base(XNode, Parser)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsValid)
|
||||
return;
|
||||
|
||||
IsValid = false;
|
||||
|
||||
NativeAccount = cXmlParser.GetBoolFromXmlAttribute(XNode, "NativeAccount");
|
||||
Server = cXmlParser.GetStringFromXmlAttribute(XNode, "Server");
|
||||
if (string.IsNullOrWhiteSpace(Server))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Name, "Server");
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = cXmlParser.GetStringFromXmlAttribute(XNode, "Instance");
|
||||
|
||||
Database = cXmlParser.GetStringFromXmlAttribute(XNode, "Database");
|
||||
if (string.IsNullOrWhiteSpace(Server))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Name, "Database");
|
||||
return;
|
||||
}
|
||||
|
||||
var strCredential = cXmlParser.GetStringFromXmlAttribute(XNode, "Credential");
|
||||
if (string.IsNullOrWhiteSpace(strCredential))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Name, "Credential");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Credentials.TryGetValue(strCredential, out var _Cred))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The credential attribute value '{strCredential}' of the element <{XNode.Name}> coud not be resolved.");
|
||||
return;
|
||||
}
|
||||
Credential = _Cred;
|
||||
|
||||
Timeout = cXmlParser.GetIntegerFromXmlAttribute(XNode, "Timeout", -1);
|
||||
if (Timeout < -1)
|
||||
Timeout = -1;
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
337
F4SD-Cockpit-ServerCore/DataHistoryConfigGolabalParameters.cs
Normal file
337
F4SD-Cockpit-ServerCore/DataHistoryConfigGolabalParameters.cs
Normal file
@@ -0,0 +1,337 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using C4IT.Configuration;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.XML;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using static C4IT.Configuration.cConfigRegistryHelper;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
public class cDataHistoryConfigGolabalParameters : cFasdBaseConfig
|
||||
{
|
||||
public const string constFileNameF4sdConfig = "F4SD-Global-Configuration.xml";
|
||||
private const string constFileNameF4sdSchema = "F4SD-Global-Configuration.xsd";
|
||||
private const string constConfigRootElement = "F4SD-Global-Configuration";
|
||||
|
||||
public cConfigHelperParameterList Parameters { get; private set; } = null;
|
||||
|
||||
private cDataHistoryConfigInfrastructure InfrastructureConfig = null;
|
||||
|
||||
internal cDataHistoryConfigGolabalParameters(cDataHistoryConfigInfrastructure configInfrastructure) :
|
||||
base(constFileNameF4sdConfig, constFileNameF4sdSchema, constConfigRootElement, true)
|
||||
{
|
||||
InfrastructureConfig = configInfrastructure;
|
||||
}
|
||||
|
||||
public override bool InstantiateProperties(XmlElement RootElement, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
try
|
||||
{
|
||||
Parameters = LoadParameters(RootElement, Parser );
|
||||
|
||||
var _s = JsonConvert.SerializeObject(Parameters, Newtonsoft.Json.Formatting.Indented);
|
||||
|
||||
this.IsValid = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
private cConfigHelperParameterList LoadParameters (XmlElement XRoot, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var _result = new cConfigHelperParameterList();
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
var Items = XRoot.ChildNodes;
|
||||
foreach (var _node in Items)
|
||||
{
|
||||
if (!(_node is XmlElement _item)) continue;
|
||||
|
||||
Parser.EnterElement(_item.Name);
|
||||
|
||||
try
|
||||
{
|
||||
var _attPolicy = _item.GetAttribute("Policy");
|
||||
var _attValue = _item.GetAttribute("Value");
|
||||
|
||||
var _ElementCount = 0;
|
||||
foreach (XmlNode _subNode in _item.ChildNodes)
|
||||
{
|
||||
if (_subNode is XmlElement)
|
||||
_ElementCount++;
|
||||
}
|
||||
|
||||
// check for special parameters
|
||||
switch (_item.Name)
|
||||
{
|
||||
case "InformationClassSearchPriority":
|
||||
var _val = getInformationClassSearchPriority(_item, Parser);
|
||||
if (_val != null)
|
||||
_result.Items[_val.Name] = _val;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_attPolicy != null && _attValue != null && _ElementCount == 0)
|
||||
{
|
||||
// we have a simple parameter
|
||||
var _policy = cXmlParser.GetEnumFromAttribute<enumConfigPolicy>(_item, "Policy", enumConfigPolicy.Default);
|
||||
var _value = cXmlParser.GetStringFromXmlAttribute(_item, "Value", String.Empty);
|
||||
|
||||
_result.Items[_item.Name] = new cConfigHelperParameterEntry()
|
||||
{
|
||||
Name = _item.Name,
|
||||
Value = _value,
|
||||
Policy = _policy.ToString(),
|
||||
};
|
||||
}
|
||||
else if (string.IsNullOrEmpty(_attPolicy) && string.IsNullOrEmpty(_attValue) && _ElementCount > 0)
|
||||
{
|
||||
// we have a sublist
|
||||
if (_result.SubItems == null)
|
||||
_result.SubItems = new Dictionary<string, cConfigHelperParameterList>();
|
||||
_result.SubItems[_item.Name] = LoadParameters(_item, Parser);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have an invalid entry
|
||||
var _msg = $"Invalid entry in F4SD-Global-Configuration.xml: {_item.Name}";
|
||||
Parser.AddMessage(_item, _msg, LogLevels.Warning);
|
||||
LogEntry(_msg, LogLevels.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement(_item.Name);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return _result;
|
||||
}
|
||||
|
||||
private cConfigHelperParameterEntry getInformationClassSearchPriority(XmlElement XNode, cXmlParser Parser)
|
||||
{
|
||||
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
try
|
||||
{
|
||||
var _xNodes = XNode.ChildNodes;
|
||||
|
||||
var _policy = cXmlParser.GetEnumFromAttribute<enumConfigPolicy>(XNode, "Policy", enumConfigPolicy.Default);
|
||||
|
||||
var _result = new List<string>();
|
||||
|
||||
foreach (var _xNode in _xNodes)
|
||||
{
|
||||
if (!(_xNode is XmlElement _item))
|
||||
continue;
|
||||
|
||||
Parser.EnterElement(_item.Name);
|
||||
|
||||
try
|
||||
{
|
||||
if (_item.Name != "InformationClass")
|
||||
{
|
||||
// we have an invalid entry
|
||||
var _msg = $"Invalid entry in F4SD-Global-Configuration.xml: {_item.Name}, should be <InformationClass/>";
|
||||
Parser.AddMessage(_item, _msg, LogLevels.Warning);
|
||||
LogEntry(_msg, LogLevels.Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
var _InfoClass = cXmlParser.GetEnumFromAttribute<enumFasdInformationClass>(_item, "Type", enumFasdInformationClass.Unknown);
|
||||
if (_InfoClass == enumFasdInformationClass.Unknown)
|
||||
{
|
||||
// we have an invalid type attribute
|
||||
var _strType = cXmlParser.GetStringFromXmlAttribute(_item, "Type", String.Empty);
|
||||
var _msg = $"Invalid type attribute value ({_strType}) in entry {_item.Name}";
|
||||
Parser.AddMessage(_item, _msg, LogLevels.Warning);
|
||||
LogEntry(_msg, LogLevels.Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
var _strInfoClass = _InfoClass.ToString();
|
||||
if (!_result.Contains(_strInfoClass))
|
||||
_result.Add(_strInfoClass);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement(_item.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new cConfigHelperParameterEntry()
|
||||
{
|
||||
Name = XNode.Name,
|
||||
ValueList = _result,
|
||||
Policy = _policy.ToString()
|
||||
};
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool DoXmlUpdates(XmlElement XmlRoot, bool withM42Config = false, bool withIntuneConfig = false, bool withMobileDeviceConfig = false, bool withCitrixConfig = false)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var RetVal = false;
|
||||
try
|
||||
{
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, ""
|
||||
, "ShouldSkipSlimView"
|
||||
, "<ShouldSkipSlimView Policy=\"Default\" Value=\"false\" />"
|
||||
);
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, ""
|
||||
, "SmallViewAlignment"
|
||||
, "<SmallViewAlignment Policy=\"Default\" Value=\"Right\" />"
|
||||
);
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, ""
|
||||
, "FavouriteBarAlignment"
|
||||
, "<FavouriteBarAlignment Policy=\"Default\" Value=\"Right\" />"
|
||||
);
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, ""
|
||||
, "InformationClassSearchPriority"
|
||||
, "<InformationClassSearchPriority Policy=\"Default\" />"
|
||||
);
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "InformationClassSearchPriority"
|
||||
, "InformationClass[@Type='User']"
|
||||
, "<InformationClass Type=\"User\" />"
|
||||
);
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "InformationClassSearchPriority"
|
||||
, "InformationClass[@Type='Computer']"
|
||||
, "<InformationClass Type=\"Computer\" />"
|
||||
);
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "InformationClassSearchPriority"
|
||||
, "InformationClass[@Type='VirtualSession']"
|
||||
, "<InformationClass Type=\"VirtualSession\" />"
|
||||
);
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "InformationClassSearchPriority"
|
||||
, "InformationClass[@Type='Ticket']"
|
||||
, "<InformationClass Type=\"Ticket\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, ""
|
||||
, "TicketConfiguration"
|
||||
, "<TicketConfiguration />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "NotesMandatory"
|
||||
, "<NotesMandatory Policy=\"Hidden\" Value=\"false\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "ShowOverview"
|
||||
, "<ShowOverview Policy=\"Hidden\" Value=\"true\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "OverviewPollingPersonal"
|
||||
, $"<OverviewPollingPersonal Policy=\"Hidden\" Value=\"{cF4sdTicketConfig.DefaultOverviewPollingPersonal}\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "OverviewPollingRole"
|
||||
, $"<OverviewPollingRole Policy=\"Hidden\" Value=\"{cF4sdTicketConfig.DefaultOverviewPollingRoles}\" />"
|
||||
);
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
var oldShowDocumentCaseDialog = InfrastructureConfig?.M42Wpm?.ShowDocumentCaseDialog ?? enumShowDocumentCaseDialog.ifRequired;
|
||||
var oldDisableAutomaticTimeTracking = InfrastructureConfig?.M42Wpm?.DisableAutomaticTimeTracking ?? false;
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "CompletitionPolicy"
|
||||
, $"<CompletitionPolicy Policy=\"Hidden\" Value=\"{oldShowDocumentCaseDialog.ToString()}\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "DisableAutomaticTimeTracking"
|
||||
, $"<DisableAutomaticTimeTracking Policy=\"Mandatory\" Value=\"{oldDisableAutomaticTimeTracking.ToString()}\" />"
|
||||
);
|
||||
}
|
||||
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
949
F4SD-Cockpit-ServerCore/DataHistoryConfigInfrastructure.cs
Normal file
949
F4SD-Cockpit-ServerCore/DataHistoryConfigInfrastructure.cs
Normal file
@@ -0,0 +1,949 @@
|
||||
using C4IT.Configuration;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.Security;
|
||||
using C4IT.XML;
|
||||
using C4IT_DataHistoryProvider;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using static C4IT_DataHistoryProvider.cDataHistoryConfigCitrix;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
public class cDataHistoryConfigInfrastructure : cFasdBaseConfig
|
||||
{
|
||||
private const string constFileNameF4sdConfig = "F4SD-Infrastructure-Configuration.xml";
|
||||
private const string constFileNameF4sdSchema = "F4SD-Infrastructure-Configuration.xsd";
|
||||
private const string constConfigRootElement = "F4SD-Infrastructure-Configuration";
|
||||
|
||||
public static readonly Guid ConfigId = new Guid("21CECFEE-0944-403F-A13F-11372BEE6905");
|
||||
|
||||
public Guid getId() { return ConfigId; }
|
||||
|
||||
public Dictionary<string, cCredential> Credentials { get; private set; } = new Dictionary<string, cCredential>();
|
||||
|
||||
public Dictionary<string, cDataHistoryConfigDbConnection> DbConnections { get; private set; } = new Dictionary<string, cDataHistoryConfigDbConnection>();
|
||||
|
||||
public cDataHistoryConfigDatabase HistoryDB { get; private set; } = null;
|
||||
public cF4SDAnalyticsConfigDatabase F4SDAnalyticsDB { get; private set; } = null;
|
||||
public cDataHistoryConfigClientAgent ClientAgent { get; private set; } = null;
|
||||
|
||||
public cDataHistoryConfigM42Wpm M42Wpm { get; private set; } = null;
|
||||
public cDataHistoryConfigCitrix Citrix { get; private set; } = null;
|
||||
public Dictionary<string, cDataHistoryCitrixTenant> CitrixTenants { get; private set; } = null;
|
||||
public cDataHistoryConfigNexthink Nexthink { get; private set; } = null;
|
||||
|
||||
public cDataHistoryConfigActiveDirectory ActiveDirectory { get; private set; } = null;
|
||||
|
||||
public Dictionary<string, cDataHistoryAzureTenant> AzureTenants { get; private set; } = null;
|
||||
|
||||
public cF4SDAuthorisation Authorisation { get; private set; } = null;
|
||||
|
||||
|
||||
internal cDataHistoryConfigInfrastructure() :
|
||||
base(constFileNameF4sdConfig, constFileNameF4sdSchema, constConfigRootElement)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool InstantiateProperties(XmlElement XRoot, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
// get the credentials
|
||||
var Creds = cCredentialXml.LoadListFromXml(XRoot, Parser, "Credentials");
|
||||
if (Creds == null || Creds.Count == 0 || Parser.LogMessages.Count > 0)
|
||||
return false;
|
||||
Credentials = Creds;
|
||||
|
||||
// get the db connections
|
||||
var Conns = cDataHistoryConfigDbConnection.LoadListFromXml(XRoot, Parser, Creds);
|
||||
if (Conns == null || Conns.Count == 0 || Parser.LogMessages.Count > 0)
|
||||
return false;
|
||||
DbConnections = Conns;
|
||||
|
||||
// get the history db config
|
||||
var _db = new cDataHistoryConfigDatabase(XRoot, Conns, Parser);
|
||||
if (_db == null || !_db.IsValid || Parser.LogMessages.Count > 0)
|
||||
return false;
|
||||
HistoryDB = _db;
|
||||
|
||||
var _db2 = new cF4SDAnalyticsConfigDatabase(XRoot, Conns, Parser);
|
||||
if (_db2 != null && _db2.IsValid && Parser.LogMessages.Count == 0)
|
||||
F4SDAnalyticsDB = _db2;
|
||||
|
||||
// get the active directory config
|
||||
var _ad = new cDataHistoryConfigActiveDirectory(XRoot, Credentials, Parser);
|
||||
if (_ad?.IsValid == true)
|
||||
ActiveDirectory = _ad;
|
||||
|
||||
AzureTenants = cDataHistoryAzureTenant.LoadFromXml(XRoot, Credentials, Parser);
|
||||
CitrixTenants = cDataHistoryCitrixTenant.LoadFromXml(XRoot, Credentials, Parser);
|
||||
|
||||
// get the client agent config
|
||||
var _cla = new cDataHistoryConfigClientAgent(XRoot, Credentials, Conns, Parser);
|
||||
if (_cla?.IsValid == true)
|
||||
ClientAgent = _cla;
|
||||
|
||||
// get the M42 WPM config
|
||||
var _m42wpm = new cDataHistoryConfigM42Wpm(XRoot, Credentials, Parser);
|
||||
if (_m42wpm?.IsValid == true)
|
||||
M42Wpm = _m42wpm;
|
||||
|
||||
var _citrix = new cDataHistoryConfigCitrix(XRoot, Credentials, Parser);
|
||||
if (_citrix?.IsValid == true)
|
||||
Citrix = _citrix;
|
||||
|
||||
// get the nexthink config
|
||||
var _nxt = new cDataHistoryConfigNexthink(XRoot, Credentials, Parser);
|
||||
if (_nxt?.IsValid == true)
|
||||
Nexthink = _nxt;
|
||||
|
||||
var _auth = new cF4SDAuthorisation(XRoot, Parser, this);
|
||||
if (_auth?.IsValid == true)
|
||||
Authorisation = _auth;
|
||||
|
||||
IsValid = true;
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class cDataHistoryConfigDatabase : IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; set; } = false;
|
||||
|
||||
public cDataHistoryConfigSqlConnection Connection { get; private set; } = null;
|
||||
|
||||
public bool SearchForPhoneNumbers { get; set; } = false;
|
||||
public bool SearchWithLike { get; set; } = false;
|
||||
|
||||
public int DaysToCache { get; set; } = 60;
|
||||
|
||||
public List<cDataHistoryCleanupTimeFrame> CleanupTimeFrames = null;
|
||||
|
||||
internal cDataHistoryConfigDatabase(XmlElement XNode, Dictionary<string, cDataHistoryConfigDbConnection> DbConnections, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
|
||||
var XNode2 = XNode.SelectSingleNode("DataHistory-DB");
|
||||
if (!(XNode2 is XmlElement XNode3))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The root element <{XNode.Name}> does not have a <DataHistory-DB> element.");
|
||||
return;
|
||||
}
|
||||
|
||||
Parser.EnterElement("DataHistory-DB");
|
||||
|
||||
try
|
||||
{
|
||||
var strConnection = cXmlParser.GetStringFromXmlAttribute(XNode2, "DB-Connection");
|
||||
if (string.IsNullOrWhiteSpace(strConnection))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The element <{XNode2.Name}> does not have a 'DB-Connection' attribute.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DbConnections.TryGetValue(strConnection, out var Conn))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"Could not find a DB connection '{strConnection}' in element <{XNode2.Name}>.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(Conn is cDataHistoryConfigSqlConnection SqlConn))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The DB connection '{strConnection}' in element <{XNode2.Name}> has to be a SQL connection.");
|
||||
return;
|
||||
}
|
||||
|
||||
Connection = SqlConn;
|
||||
|
||||
SearchForPhoneNumbers = cXmlParser.GetBoolFromXmlAttribute(XNode2, "SearchForPhoneNumbers");
|
||||
|
||||
SearchWithLike = cXmlParser.GetBoolFromXmlAttribute(XNode2, "SearchWithLike");
|
||||
|
||||
DaysToCache = cXmlParser.GetIntegerFromXmlAttribute(XNode2, "DaysToCache", DaysToCache);
|
||||
|
||||
CleanupTimeFrames = cDataHistoryCleanupTimeFrame.LoadFromXml(XNode3, Parser);
|
||||
|
||||
IsValid = true;
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("DataHistory-DB");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class cF4SDAnalyticsConfigDatabase : IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; set; } = false;
|
||||
public bool AnonymousUser { get; set; }
|
||||
public int SessionTimeout { get; set; } = 60;
|
||||
public int CaseTimeout { get; set; } = 5;
|
||||
public int SessionCheckInterval { get; set; } = 20;
|
||||
public int CaseCheckInterval { get; set; } = 1;
|
||||
public cDataHistoryConfigSqlConnection Connection { get; private set; } = null;
|
||||
|
||||
internal cF4SDAnalyticsConfigDatabase(XmlElement XNode, Dictionary<string, cDataHistoryConfigDbConnection> DbConnections, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
|
||||
var XNode2 = XNode.SelectSingleNode("F4SDAnalytics-DB");
|
||||
if (!(XNode2 is XmlElement XNode3))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The root element <{XNode.Name}> does not have a <F4SDAnalytics-DB> element.", LogLevels.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
Parser.EnterElement("F4SDAnalytics-DB");
|
||||
|
||||
try
|
||||
{
|
||||
var strConnection = cXmlParser.GetStringFromXmlAttribute(XNode2, "DB-Connection");
|
||||
if (string.IsNullOrWhiteSpace(strConnection))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The element <{XNode2.Name}> does not have a 'DB-Connection' attribute.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DbConnections.TryGetValue(strConnection, out var Conn))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"Could not find a DB connection '{strConnection}' in element <{XNode2.Name}>.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(Conn is cDataHistoryConfigSqlConnection SqlConn))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The DB connection '{strConnection}' in element <{XNode2.Name}> has to be a SQL connection.");
|
||||
return;
|
||||
}
|
||||
|
||||
Connection = SqlConn;
|
||||
AnonymousUser = !cXmlParser.GetBoolFromXmlAttribute(XNode2, "EnableUserId");
|
||||
SessionTimeout = cXmlParser.GetIntegerFromXmlAttribute(XNode2, "SessionTimeout", 60);
|
||||
CaseTimeout = cXmlParser.GetIntegerFromXmlAttribute(XNode2, "CaseTimeout", 5);
|
||||
SessionCheckInterval = cXmlParser.GetIntegerFromXmlAttribute(XNode2, "SessionCheckInterval", 20);
|
||||
CaseCheckInterval = cXmlParser.GetIntegerFromXmlAttribute(XNode2, "CaseCheckInterval", 2);
|
||||
IsValid = true;
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("F4SDAnalytics-DB");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class cDataHistoryCleanupTimeFrame : IConfigNodeValidation
|
||||
{
|
||||
private const string constXmlTag = "Cleanup-Timeframe";
|
||||
public bool IsValid { get; set; } = false;
|
||||
|
||||
public int DowFrom = 0;
|
||||
public int DowTo = 0;
|
||||
public TimeSpan TimeFrom = new TimeSpan(0, 0, 0);
|
||||
public TimeSpan TimeTo = new TimeSpan(23, 59, 59);
|
||||
public TimeZoneInfo TimeZone = TimeZoneInfo.Utc;
|
||||
|
||||
internal cDataHistoryCleanupTimeFrame(XmlElement XNode, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
TimeZone = cXmlParser.GetTimeZoneInfoFromAttribute(XNode, "Timezone");
|
||||
if (TimeZone == null)
|
||||
TimeZone = TimeZoneInfo.Utc;
|
||||
|
||||
var strFromDay = cXmlParser.GetStringFromXmlAttribute(XNode, "StartDay");
|
||||
var fromTime = cXmlParser.GetTimeSpanFromAttribute(XNode, "StartTime", null);
|
||||
var strToDay = cXmlParser.GetStringFromXmlAttribute(XNode, "StopDay");
|
||||
var toTime = cXmlParser.GetTimeSpanFromAttribute(XNode, "StopTime", null);
|
||||
|
||||
if (fromTime == null || toTime == null)
|
||||
return;
|
||||
|
||||
TimeFrom = (TimeSpan)fromTime;
|
||||
TimeTo = (TimeSpan)toTime;
|
||||
|
||||
DowFrom = GetDayOfWeek(strFromDay);
|
||||
if (DowFrom < 0)
|
||||
return;
|
||||
|
||||
DowTo = GetDayOfWeek(strToDay);
|
||||
if (DowTo < 0)
|
||||
{
|
||||
if (TimeTo <= TimeFrom)
|
||||
DowTo = (DowFrom + 1) % 7;
|
||||
else
|
||||
DowTo = DowFrom;
|
||||
}
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int GetDayOfWeek(string Day)
|
||||
{
|
||||
try
|
||||
{
|
||||
int DayOfWeek = -1;
|
||||
if (Day != null)
|
||||
{
|
||||
var strDow = Day.ToUpperInvariant();
|
||||
switch (strDow)
|
||||
{
|
||||
case "MON":
|
||||
DayOfWeek = 1;
|
||||
break;
|
||||
case "TUE":
|
||||
DayOfWeek = 2;
|
||||
break;
|
||||
case "WED":
|
||||
DayOfWeek = 3;
|
||||
break;
|
||||
case "THU":
|
||||
DayOfWeek = 4;
|
||||
break;
|
||||
case "FRI":
|
||||
DayOfWeek = 5;
|
||||
break;
|
||||
case "SAT":
|
||||
DayOfWeek = 6;
|
||||
break;
|
||||
case "SUN":
|
||||
DayOfWeek = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return DayOfWeek;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogException(LogLevels.Error, E);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
internal static List<cDataHistoryCleanupTimeFrame> LoadFromXml(XmlElement XNode, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var RetVal = new List<cDataHistoryCleanupTimeFrame>();
|
||||
|
||||
try
|
||||
{
|
||||
var XList = XNode.SelectNodes(constXmlTag);
|
||||
if (XList != null && XList.Count > 0)
|
||||
{
|
||||
Parser.EnterElement(constXmlTag);
|
||||
try
|
||||
{
|
||||
foreach (var Entry in XList)
|
||||
{
|
||||
if (!(Entry is XmlElement XEntry))
|
||||
continue;
|
||||
|
||||
var Node = new cDataHistoryCleanupTimeFrame(XEntry, Parser);
|
||||
if (Node.IsValid)
|
||||
RetVal.Add(Node);
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement(constXmlTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
private static int Compare(int DowFrom, TimeSpan TimeFrom, int DowTo, TimeSpan TimeTo)
|
||||
{
|
||||
if (DowFrom == DowTo)
|
||||
{
|
||||
if (TimeTo > TimeFrom)
|
||||
return 1;
|
||||
else if (TimeTo < TimeFrom)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else if (DowTo > DowFrom)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
public bool Check()
|
||||
{
|
||||
try
|
||||
{
|
||||
var Now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, this.TimeZone);
|
||||
var dow = (int)Now.DayOfWeek;
|
||||
var time = Now.TimeOfDay;
|
||||
|
||||
var c0 = Compare(DowFrom, TimeFrom, DowTo, TimeTo);
|
||||
var c1 = Compare(DowFrom, TimeFrom, dow, time);
|
||||
var c2 = Compare(DowTo, TimeTo, dow, time);
|
||||
if (c0 <= 0)
|
||||
return c1 >= 0 || c2 <= 0;
|
||||
else
|
||||
return c1 >= 0 && c2 <= 0;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogException(LogLevels.Error, E);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class cDataHistoryScanTiming : IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; set; } = false;
|
||||
public TimeSpan Interval { get; set; }
|
||||
|
||||
public TimeSpan Offset { get; set; }
|
||||
|
||||
public TimeZoneInfo Timezone { get; set; }
|
||||
|
||||
public cDataHistoryScanTiming()
|
||||
{
|
||||
}
|
||||
|
||||
internal cDataHistoryScanTiming(XmlElement XNode, TimeSpan DefaultInterval, TimeSpan DefaultOffset, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
Interval = DefaultInterval;
|
||||
Offset = DefaultOffset;
|
||||
Timezone = TimeZoneInfo.Local;
|
||||
|
||||
var XNode2 = XNode.SelectSingleNode("Scan-Timing");
|
||||
if (XNode2 == null)
|
||||
return;
|
||||
|
||||
Parser.EnterElement("Scan-Timing");
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
Interval = (TimeSpan)cXmlParser.GetTimeSpanFromAttribute(XNode2, "ScanInterval", Interval);
|
||||
Offset = (TimeSpan)cXmlParser.GetTimeSpanFromAttribute(XNode2, "ScanOffset", Interval);
|
||||
Timezone = cXmlParser.GetTimeZoneInfoFromAttribute(XNode2, "Timezone");
|
||||
if (Timezone == null)
|
||||
Timezone = TimeZoneInfo.Utc;
|
||||
IsValid = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Scan-Timing");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class cF4SDAuthorisation : IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; set; } = false;
|
||||
|
||||
public cF4SDMembershipGroups MembershipGroups = null;
|
||||
|
||||
public Dictionary<string, cF4SDRole> Roles = null;
|
||||
|
||||
public cF4SDAuthorisation(XmlElement XNode, cXmlParser Parser, cDataHistoryConfigInfrastructure InfratructureConfig)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
if (!(XNode.SelectSingleNode("Authorization") is XmlElement _xmlAuth))
|
||||
return;
|
||||
|
||||
Parser.EnterElement("Authorization");
|
||||
|
||||
try
|
||||
{
|
||||
var _groups = new cF4SDMembershipGroups(_xmlAuth, Parser, InfratructureConfig);
|
||||
if (_groups?.IsValid != true)
|
||||
return;
|
||||
MembershipGroups = _groups;
|
||||
|
||||
var _roles = cF4SDRole.LoadFromXml(_xmlAuth, Parser, MembershipGroups);
|
||||
if (_roles?.Count > 0)
|
||||
Roles = _roles;
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
Parser.LeaveElement("Authorization");
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class cF4SDMembershipGroups : Dictionary<string, cF4SDMembershipGroup>, IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; set; } = false;
|
||||
|
||||
public Dictionary<string, cF4SDMembershipGroupsAd> GroupsAd = null;
|
||||
public cF4SDMembershipGroupsM42 GroupsM42 = null;
|
||||
|
||||
public cF4SDMembershipGroups(XmlElement XNode, cXmlParser Parser, cDataHistoryConfigInfrastructure InfratructureConfig)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
if (!(XNode.SelectSingleNode("Membership-Groups") is XmlElement _xmlGroups))
|
||||
return;
|
||||
|
||||
Parser.EnterElement("Membership-Groups");
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
GroupsAd = cF4SDMembershipGroupsAd.LoadFromXml(_xmlGroups, Parser, InfratructureConfig?.ActiveDirectory?.Domains);
|
||||
if (GroupsAd != null)
|
||||
foreach (var _entry in GroupsAd.Values)
|
||||
foreach (var _entry2 in _entry.Values)
|
||||
this[_entry2.Name] = _entry2;
|
||||
|
||||
var _groupM42 = new cF4SDMembershipGroupsM42(_xmlGroups, Parser);
|
||||
if (_groupM42?.IsValid == true)
|
||||
{
|
||||
GroupsM42 = _groupM42;
|
||||
foreach (var _entry in GroupsM42)
|
||||
this[_entry.Key] = _entry.Value;
|
||||
}
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
Parser.LeaveElement("Membership-Groups");
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class cF4SDMembershipGroup : cConfigNodeNamed
|
||||
{
|
||||
public cF4SDMembershipGroup(XmlElement XNode, cXmlParser Parser) : base(XNode, Parser)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class cF4SDMembershipGroupsAd : Dictionary<string, cF4SDMembershipGroupAd>, IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; set; } = false;
|
||||
public string strDomain { get; private set; } = null;
|
||||
public cDataHistoryAdDomain Domain { get; private set; } = null;
|
||||
|
||||
|
||||
public cF4SDMembershipGroupsAd(XmlElement XNode, cXmlParser Parser, Dictionary<string, cDataHistoryAdDomain> Domains)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
strDomain = cXmlParser.GetStringFromXmlAttribute(XNode, "Domain");
|
||||
if (!string.IsNullOrEmpty(strDomain))
|
||||
{
|
||||
if (Domains.TryGetValue(strDomain, out var _dom))
|
||||
{
|
||||
Domain = _dom;
|
||||
|
||||
var _xList = XNode.SelectNodes("Membership-Group-AD");
|
||||
if (_xList != null && _xList.Count > 0)
|
||||
{
|
||||
Parser.EnterElement("Membership-Group-AD");
|
||||
foreach (var _x in _xList)
|
||||
{
|
||||
if (!(_x is XmlElement _xEl))
|
||||
continue;
|
||||
|
||||
var _grp = new cF4SDMembershipGroupAd(_xEl, Parser);
|
||||
if (_grp?.IsValid == true)
|
||||
this[_grp.Name] = _grp;
|
||||
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
Parser.LeaveElement("Membership-Group-AD");
|
||||
}
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
public static Dictionary<string, cF4SDMembershipGroupsAd> LoadFromXml(XmlElement XNode, cXmlParser Parser, Dictionary<string, cDataHistoryAdDomain> Domains)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var _retVal = new Dictionary<string, cF4SDMembershipGroupsAd>();
|
||||
try
|
||||
{
|
||||
var _xmlList = XNode.SelectNodes("Membership-Groups-AD");
|
||||
if (_xmlList != null && _xmlList.Count > 0)
|
||||
{
|
||||
Parser.EnterElement("Membership-Groups-AD");
|
||||
foreach (var _xmlEntry in _xmlList)
|
||||
{
|
||||
if (!(_xmlEntry is XmlElement _xmlEl))
|
||||
continue;
|
||||
var _node = new cF4SDMembershipGroupsAd(_xmlEl, Parser, Domains);
|
||||
if (_node?.IsValid == true)
|
||||
_retVal[_node.Domain.Name] = _node;
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
Parser.LeaveElement("Membership-Groups-AD");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return _retVal; ;
|
||||
}
|
||||
}
|
||||
|
||||
public class cF4SDMembershipGroupsM42 : Dictionary<string, cF4SDMembershipGroupM42>, IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; set; } = false;
|
||||
|
||||
public cF4SDMembershipGroupsM42(XmlElement XNode, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
if (!(XNode.SelectSingleNode("Membership-Groups-Matrix42") is XmlElement _xGroup))
|
||||
return;
|
||||
|
||||
Parser.EnterElement("Membership-Groups-Matrix42");
|
||||
|
||||
var _xList = _xGroup.SelectNodes("Membership-Group-Matrix42");
|
||||
if (_xList != null && _xList.Count > 0)
|
||||
{
|
||||
Parser.EnterElement("Membership-Group-Matrix42");
|
||||
foreach (var _x in _xList)
|
||||
{
|
||||
if (!(_x is XmlElement _xEl))
|
||||
continue;
|
||||
|
||||
var _grp = new cF4SDMembershipGroupM42(_xEl, Parser);
|
||||
if (_grp?.IsValid == true)
|
||||
this[_grp.Name] = _grp;
|
||||
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
Parser.LeaveElement("Membership-Group-Matrix42");
|
||||
}
|
||||
|
||||
Parser.LeaveElement("Membership-Groups-Matrix42");
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class cF4SDMembershipGroupAd : cF4SDMembershipGroup
|
||||
{
|
||||
public string Account { get; private set; } = null;
|
||||
|
||||
public string SID { get; set; } = null;
|
||||
|
||||
|
||||
public cF4SDMembershipGroupAd(XmlElement XNode, cXmlParser Parser) : base(XNode, Parser)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!this.IsValid)
|
||||
return;
|
||||
IsValid = false;
|
||||
|
||||
Account = cXmlParser.GetStringFromXmlAttribute(XNode, "Account");
|
||||
|
||||
if (string.IsNullOrEmpty(Account))
|
||||
return;
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class cF4SDMembershipGroupM42 : cF4SDMembershipGroup
|
||||
{
|
||||
public string RoleName { get; private set; } = null;
|
||||
public Guid RoleId { get; private set; } = Guid.Empty;
|
||||
|
||||
public cF4SDMembershipGroupM42(XmlElement XNode, cXmlParser Parser) : base(XNode, Parser)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!this.IsValid)
|
||||
return;
|
||||
IsValid = false;
|
||||
|
||||
RoleName = cXmlParser.GetStringFromXmlAttribute(XNode, "RoleName");
|
||||
|
||||
if (string.IsNullOrEmpty(RoleName) || string.IsNullOrEmpty(Name))
|
||||
return;
|
||||
|
||||
RoleId = cXmlParser.GetGuidFromXmlAttribute(XNode, "RoleID");
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class cF4SDRole : cConfigNodeNamed
|
||||
{
|
||||
public List<cF4SDMembershipGroup> MembershipGroups { get; private set; } = null;
|
||||
|
||||
public cF4SDRole(XmlElement XNode, cXmlParser Parser, cF4SDMembershipGroups _MembershipGroups) : base(XNode, Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
if (!IsValid)
|
||||
return;
|
||||
IsValid = false;
|
||||
|
||||
var _lstGroupNames = new List<string>();
|
||||
var _strGroup = cXmlParser.GetStringFromXmlAttribute(XNode, "Group");
|
||||
if (!string.IsNullOrEmpty(_strGroup))
|
||||
_lstGroupNames.Add(_strGroup);
|
||||
|
||||
var _xmlGroups = XNode.SelectNodes("GroupRef");
|
||||
|
||||
if (_xmlGroups?.Count > 0)
|
||||
{
|
||||
Parser.EnterElement("GroupRef");
|
||||
|
||||
foreach (var _ref in _xmlGroups)
|
||||
{
|
||||
if (!(_ref is XmlElement _refGroup))
|
||||
continue;
|
||||
|
||||
_strGroup = cXmlParser.GetStringFromXmlAttribute(_refGroup, "Name");
|
||||
if (!string.IsNullOrEmpty(_strGroup) && !_lstGroupNames.Contains(_strGroup))
|
||||
_lstGroupNames.Add(_strGroup);
|
||||
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
|
||||
Parser.LeaveElement("GroupRef");
|
||||
}
|
||||
|
||||
if (_lstGroupNames.Count > 0)
|
||||
{
|
||||
var _lstMembers = new List<cF4SDMembershipGroup>();
|
||||
foreach (var _entry in _lstGroupNames)
|
||||
{
|
||||
if (_MembershipGroups.TryGetValue(_entry, out var _grp))
|
||||
{
|
||||
if (!_lstMembers.Contains(_grp))
|
||||
_lstMembers.Add(_grp);
|
||||
}
|
||||
}
|
||||
|
||||
if (_lstMembers.Count > 0)
|
||||
{
|
||||
MembershipGroups = _lstMembers;
|
||||
IsValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
public static Dictionary<string, cF4SDRole> LoadFromXml(XmlElement XNode, cXmlParser Parser, cF4SDMembershipGroups MembershipGroups)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var _retVal = new Dictionary<string, cF4SDRole>();
|
||||
try
|
||||
{
|
||||
var _xmlNode2 = XNode.SelectSingleNode("Roles");
|
||||
if (!(_xmlNode2 is XmlElement _xmlRoles))
|
||||
return null;
|
||||
|
||||
Parser.EnterElement("Roles");
|
||||
|
||||
try
|
||||
{
|
||||
var _xmlListRoles = _xmlRoles.SelectNodes("Role");
|
||||
if (!(_xmlListRoles?.Count > 0))
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
Parser.EnterElement("Role");
|
||||
foreach (var _xmlEntry in _xmlListRoles)
|
||||
{
|
||||
if (!(_xmlEntry is XmlElement _xmlEl))
|
||||
continue;
|
||||
|
||||
var _group = new cF4SDRole(_xmlEl, Parser, MembershipGroups);
|
||||
if (_group?.IsValid == true)
|
||||
_retVal[_group.Name] = _group;
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Role");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Roles");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return _retVal; ;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
211
F4SD-Cockpit-ServerCore/DataHistoryConfigM42Wpm.cs
Normal file
211
F4SD-Cockpit-ServerCore/DataHistoryConfigM42Wpm.cs
Normal file
@@ -0,0 +1,211 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MultiLanguage;
|
||||
using C4IT.Security;
|
||||
using C4IT.XML;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
public class cDataHistoryConfigM42Wpm : IConfigNodeValidation
|
||||
{
|
||||
public enum enumApiTokenLifetime
|
||||
{
|
||||
days30 = 30,
|
||||
days90 = 90,
|
||||
days180 = 180,
|
||||
year1 = 360,
|
||||
never = -1
|
||||
};
|
||||
|
||||
public bool IsValid { get; private set; } = false;
|
||||
|
||||
public string Server { get; private set; } = null;
|
||||
|
||||
public cCredential Credential { get; private set; } = null;
|
||||
|
||||
public int ClosedTicketHistory { get; private set; } = 10;
|
||||
public enumActivityQueueFilterOptions ActivityQueueFilterOption { get; private set; } = enumActivityQueueFilterOptions.showAll;
|
||||
public List<cApiM42TicketQueueInfo> ActivityQueues { get; private set; } = new List<cApiM42TicketQueueInfo>();
|
||||
|
||||
[Obsolete("This property is no longer used and will be removed in future versions.")]
|
||||
public bool DisableAutomaticTimeTracking { get; private set; } = false;
|
||||
|
||||
public cMultiLanguageDictionary DisplayNames { get; private set; } = new cMultiLanguageDictionary();
|
||||
|
||||
public enumApiTokenLifetime ApiLifetime { get; private set; } = enumApiTokenLifetime.never;
|
||||
|
||||
[Obsolete("This property is no longer used and will be removed in future versions.")]
|
||||
public enumShowDocumentCaseDialog ShowDocumentCaseDialog { get; private set; } = enumShowDocumentCaseDialog.ifRequired;
|
||||
|
||||
internal cDataHistoryConfigM42Wpm(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null;
|
||||
if (cLogManager.DefaultLogger.IsDebug)
|
||||
{
|
||||
CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
}
|
||||
try
|
||||
{
|
||||
if (!(XNode.SelectSingleNode("Matrix42-WPM") is XmlElement XNode2))
|
||||
return;
|
||||
|
||||
Parser.EnterElement("Matrix42-WPM");
|
||||
|
||||
try
|
||||
{
|
||||
Server = cXmlParser.GetStringFromXmlAttribute(XNode2, "Server", "");
|
||||
if (string.IsNullOrWhiteSpace(Server))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The attribute 'Server' in element <{XNode2.Name}> is not set.");
|
||||
return;
|
||||
}
|
||||
|
||||
var strCredential = cXmlParser.GetStringFromXmlAttribute(XNode2, "Credential");
|
||||
if (string.IsNullOrWhiteSpace(strCredential))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, null, "Credential");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Credentials.TryGetValue(strCredential, out var _Cred))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"The credential attribute value '{strCredential}' of the element <{XNode.Name}> coud not be resolved.");
|
||||
return;
|
||||
}
|
||||
Credential = _Cred;
|
||||
|
||||
ClosedTicketHistory = cXmlParser.GetIntegerFromXmlAttribute(XNode2, "ClosedTicketHistory", ClosedTicketHistory);
|
||||
|
||||
ActivityQueueFilterOption = cXmlParser.GetEnumFromAttribute(XNode2, "ActivityQueueFilter", enumActivityQueueFilterOptions.showAll);
|
||||
if ((XNode2.SelectSingleNode("Queues") is XmlElement XNode3))
|
||||
{
|
||||
Parser.EnterElement("Queues");
|
||||
try
|
||||
{
|
||||
ActivityQueues = cXmlParser.GetObjectsFromXml(
|
||||
XNode3,
|
||||
"Queue",
|
||||
node =>
|
||||
{
|
||||
XmlAttributeCollection a = node.Attributes;
|
||||
if (a == null) return null;
|
||||
|
||||
string name = a["QueueName"]?.Value;
|
||||
string id = a["QueueID"]?.Value;
|
||||
Guid guid;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(name) || !Guid.TryParse(id, out guid))
|
||||
return null;
|
||||
|
||||
return new cApiM42TicketQueueInfo
|
||||
{
|
||||
QueueName = name.Trim(),
|
||||
QueueID = guid
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Queues");
|
||||
}
|
||||
}
|
||||
DisplayNames.LoadFromXmlAttributeList(XNode2, "DisplayName");
|
||||
|
||||
var _str = cXmlParser.GetStringFromXmlAttribute(XNode2, "ApiTokenLifetime")?.ToLowerInvariant();
|
||||
switch (_str)
|
||||
{
|
||||
case "90 days":
|
||||
ApiLifetime = enumApiTokenLifetime.days90;
|
||||
break;
|
||||
case "180 days":
|
||||
ApiLifetime = enumApiTokenLifetime.days180;
|
||||
break;
|
||||
case "1 year":
|
||||
ApiLifetime = enumApiTokenLifetime.year1;
|
||||
break;
|
||||
case "never":
|
||||
ApiLifetime = enumApiTokenLifetime.never;
|
||||
break;
|
||||
default:
|
||||
ApiLifetime = enumApiTokenLifetime.days30;
|
||||
break;
|
||||
}
|
||||
parseMatrix42Ticket(XNode2, Parser);
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Matrix42-WPM");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
internal void parseMatrix42Ticket(XmlElement XNode, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null;
|
||||
if (cLogManager.DefaultLogger.IsDebug)
|
||||
{
|
||||
CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
}
|
||||
try
|
||||
{
|
||||
if (!(XNode.SelectSingleNode("Matrix42-Ticket") is XmlElement XNode2))
|
||||
return;
|
||||
|
||||
Parser.EnterElement("Matrix42-Ticket");
|
||||
|
||||
try
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
DisableAutomaticTimeTracking = cXmlParser.GetBoolFromXmlAttribute(XNode2, "DisableAutomaticTimeTracking");
|
||||
ShowDocumentCaseDialog = cXmlParser.GetEnumFromAttribute(XNode2, "ShowDocumentCaseDialog", enumShowDocumentCaseDialog.ifRequired);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Matrix42-Ticket");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
258
F4SD-Cockpit-ServerCore/DataHistoryConfigNexthink.cs
Normal file
258
F4SD-Cockpit-ServerCore/DataHistoryConfigNexthink.cs
Normal file
@@ -0,0 +1,258 @@
|
||||
using C4IT.Logging;
|
||||
using C4IT.Security;
|
||||
using C4IT.XML;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
public class cDataHistoryConfigNexthink : IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; set; } = false;
|
||||
|
||||
public cDataHistoryScanTiming ScanTiming { get; private set; } = null;
|
||||
|
||||
public Dictionary<string, cDataHistoryNxtPortal> Portals = new Dictionary<string, cDataHistoryNxtPortal>();
|
||||
|
||||
internal cDataHistoryConfigNexthink(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
|
||||
var XNode2 = XNode.SelectSingleNode("Nexthink");
|
||||
if (!(XNode2 is XmlElement XNexthink))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Parser.EnterElement("Nexthink");
|
||||
|
||||
try
|
||||
{
|
||||
ScanTiming = new cDataHistoryScanTiming(XNexthink, TimeSpan.FromHours(24), TimeSpan.FromMinutes(10), Parser);
|
||||
|
||||
Portals = cDataHistoryNxtPortal.LoadFromXml(XNexthink, Credentials, Parser);
|
||||
|
||||
if (Portals != null && Portals.Count > 0)
|
||||
IsValid = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Nexthink");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class cDataHistoryNxtPortal : cConfigNodeNamed
|
||||
{
|
||||
public string Address { get; set; }
|
||||
|
||||
public cCredential Credential { get; set; }
|
||||
|
||||
public bool IsCloud { get; set; } = false;
|
||||
|
||||
public Dictionary<string, cDataHistoryNxtEngine> Engines = new Dictionary<string, cDataHistoryNxtEngine>();
|
||||
|
||||
|
||||
internal cDataHistoryNxtPortal(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser) :
|
||||
base(XNode, Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
if (!IsValid)
|
||||
return;
|
||||
|
||||
IsValid = false;
|
||||
|
||||
Address = cXmlParser.GetStringFromXmlAttribute(XNode, "Address");
|
||||
if (string.IsNullOrWhiteSpace(Address))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Name, "Address");
|
||||
return;
|
||||
}
|
||||
|
||||
var _strCredential = cXmlParser.GetStringFromXmlAttribute(XNode, "Credential");
|
||||
if (string.IsNullOrWhiteSpace(_strCredential))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Name, "Credential");
|
||||
return;
|
||||
}
|
||||
if (!Credentials.TryGetValue(_strCredential, out var _Cred))
|
||||
{
|
||||
Parser.AddMessage(XNode, $"Could not find the credential '{_strCredential}' in element <{XNode.Name}>");
|
||||
return;
|
||||
}
|
||||
Credential = _Cred;
|
||||
|
||||
IsCloud = cXmlParser.GetBoolFromXmlAttribute(XNode, "IsCloud");
|
||||
|
||||
Engines = cDataHistoryNxtEngine.LoadFromXml(XNode, this, Parser);
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
internal static Dictionary<string, cDataHistoryNxtPortal> LoadFromXml(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
var lstXNode = XNode.SelectNodes("Nxt-Portal");
|
||||
if (lstXNode == null || lstXNode.Count == 0)
|
||||
{
|
||||
Parser.AddMessage(XNode, "Could not find a valid <Nxt-Portal> element.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Parser.EnterElement("Nxt-Portal");
|
||||
try
|
||||
{
|
||||
var RetVal = new Dictionary<string, cDataHistoryNxtPortal>(lstXNode.Count);
|
||||
foreach (var XENtry in lstXNode)
|
||||
{
|
||||
if (!(XENtry is XmlElement XPortal))
|
||||
continue;
|
||||
|
||||
var Po = new cDataHistoryNxtPortal(XPortal, Credentials, Parser);
|
||||
if (Po != null && Po.IsValid)
|
||||
RetVal.Add(Po.Name, Po);
|
||||
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Nxt-Portal");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class cDataHistoryNxtEngine : cConfigNodeNamed
|
||||
{
|
||||
public string Address { get; set; }
|
||||
|
||||
public int Port { get; set; } = -1;
|
||||
|
||||
internal cDataHistoryNxtEngine(XmlElement XNode, cDataHistoryNxtPortal Portal, cXmlParser Parser) :
|
||||
base(XNode, Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
if (!IsValid)
|
||||
return;
|
||||
|
||||
IsValid = false;
|
||||
|
||||
Address = cXmlParser.GetStringFromXmlAttribute(XNode, "Address");
|
||||
if (string.IsNullOrWhiteSpace(Address))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, Name, "Address");
|
||||
return;
|
||||
}
|
||||
|
||||
Port = 1671;
|
||||
if (Portal.IsCloud)
|
||||
Port = 443;
|
||||
Port = cXmlParser.GetIntegerFromXmlAttribute(XNode, "Port", Port);
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal static Dictionary<string, cDataHistoryNxtEngine> LoadFromXml(XmlElement XNode, cDataHistoryNxtPortal Portal, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
var lstXNode = XNode.SelectNodes("Nxt-Engine");
|
||||
if (lstXNode == null || lstXNode.Count == 0)
|
||||
{
|
||||
Parser.AddMessage(XNode, "Could not find a valid <Nxt-Engine> element.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Parser.EnterElement("Nxt-Engine");
|
||||
try
|
||||
{
|
||||
var RetVal = new Dictionary<string, cDataHistoryNxtEngine>(lstXNode.Count);
|
||||
foreach (var XENtry in lstXNode)
|
||||
{
|
||||
if (!(XENtry is XmlElement XPortal))
|
||||
continue;
|
||||
|
||||
var En = new cDataHistoryNxtEngine(XPortal, Portal, Parser);
|
||||
if (En != null && En.IsValid)
|
||||
RetVal.Add(En.Name, En);
|
||||
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Nxt-Engine");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
1667
F4SD-Cockpit-ServerCore/DataHistorySqlHelper.cs
Normal file
1667
F4SD-Cockpit-ServerCore/DataHistorySqlHelper.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
using C4IT.FASD.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace C4IT_DataHistoryProvider_Base.DataSources
|
||||
{
|
||||
public interface ISearchResultRelationProvider
|
||||
{
|
||||
HashSet<enumFasdInformationClass> GetSupportedInformationClasses();
|
||||
|
||||
/// <summary>
|
||||
/// Find objects, which are somehow related to the given objects.
|
||||
/// </summary>
|
||||
/// <param name="ids">Identifies the objects for which relations should be searched</param>
|
||||
/// <param name="informationClass">Determines the information class the objects have, for which relations should be searched.</param>
|
||||
/// <param name="ageInDays">Specifies the time, in which the relations should be considered.</param>
|
||||
/// <returns></returns>
|
||||
Task<cF4sdStagedSearchResultRelations> GetRelationsAsync(IEnumerable<cF4sdIdentityEntry> ids, enumFasdInformationClass informationClass, int ageInDays, CancellationToken token = default);
|
||||
}
|
||||
}
|
||||
185
F4SD-Cockpit-ServerCore/F4SD-Cockpit-ServerCore.csproj
Normal file
185
F4SD-Cockpit-ServerCore/F4SD-Cockpit-ServerCore.csproj
Normal file
@@ -0,0 +1,185 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="Globals">
|
||||
<SccProjectName>SAK</SccProjectName>
|
||||
<SccProvider>SAK</SccProvider>
|
||||
<SccAuxPath>SAK</SccAuxPath>
|
||||
<SccLocalPath>SAK</SccLocalPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>C4IT_DataHistoryProvider_Base</RootNamespace>
|
||||
<Configurations>Debug;Debug-Demo;Release;Release-Demo</Configurations>
|
||||
<Deterministic>false</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;VITALSIGN_MONITORING</DefineConstants>
|
||||
<NoWarn>MSB3305</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<NoWarn>MSB3305</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>C4IT_2016.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release-Demo|AnyCPU'">
|
||||
<OutputPath>bin\Release-Demo\</OutputPath>
|
||||
<DefineConstants>TRACE;DEMOLICENSE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>MSB3305</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug-Demo|AnyCPU'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug-Demo\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;DEMOLICENSE</DefineConstants>
|
||||
<NoWarn>MSB3305</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AssemblyTitle>F4SD Cockpit Server base library</AssemblyTitle>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net472'">
|
||||
<Reference Include="System.Web" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Web.Administration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>.\Microsoft.Web.Administration.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.F4SD.GlobalConfig.cs">
|
||||
<Link>Common\C4IT.F4SD.GlobalConfig.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.F4SD.HealthCardConfig.cs">
|
||||
<Link>Common\C4IT.F4SD.HealthCardConfig.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.F4SD.MenuItem.cs">
|
||||
<Link>Common\C4IT.F4SD.MenuItem.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.FASD.Base.cs">
|
||||
<Link>Common\C4IT.FASD.Base.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.FASD.Communication.Agent.cs">
|
||||
<Link>Common\C4IT.FASD.Communication.Agent.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.FASD.ConfigBase.cs">
|
||||
<Link>Common\C4IT.FASD.ConfigBase.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.FASD.CopyTemplatesConfig.cs">
|
||||
<Link>Common\C4IT.FASD.CopyTemplatesConfig.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.FASD.IconConfig.cs">
|
||||
<Link>Common\C4IT.FASD.IconConfig.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.FASD.MenuSectionConfig.cs">
|
||||
<Link>Common\C4IT.FASD.MenuSectionConfig.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.FASD.QuickActionConfig.cs">
|
||||
<Link>Common\C4IT.FASD.QuickActionConfig.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.FASD.Security.cs">
|
||||
<Link>Common\C4IT.FASD.Security.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\Configuration\C4IT.Configuration.ConfigHelper.cs">
|
||||
<Link>Common\C4IT.Configuration.ConfigHelper.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\FileImport\C4IT.FileImport.CsvFile.cs">
|
||||
<Link>Common\C4IT.FileImport.CsvFile.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\Http\C4IT.HTTP.HttpApiBase.cs">
|
||||
<Link>Common\C4IT.HTTP.HttpApiBase.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\Http\C4IT.HttpHelper.cs">
|
||||
<Link>Common\C4IT.HttpHelper.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\Licensing\C4IT.Licensing.LicenseBase.cs">
|
||||
<Link>Common\C4IT.Licensing.LicenseBase.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\Logging\C4IT.Logging.LogManager.cs">
|
||||
<Link>Common\C4IT.Logging.LogManager.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\Logging\C4IT.Logging.LogNetwork.cs">
|
||||
<Link>Common\C4IT.Logging.LogNetwork.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\Logging\C4IT.Logging.LogPerformance.cs">
|
||||
<Link>Common\C4IT.Logging.LogPerformance.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\MsCloud\C4IT.MsGraph.Base.cs">
|
||||
<Link>Common\C4IT.MsGraph.Base.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\MultiLanguage\C4IT.MultiLanguage.MultiLanguageSupport.cs">
|
||||
<Link>Common\C4IT.MultiLanguage.MultiLanguageSupport.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\Security\C4IT.Security.Base32.cs">
|
||||
<Link>Common\C4IT.Security.Base32.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\Security\C4IT.Security.Credential.cs">
|
||||
<Link>Common\C4IT.Security.Credential.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\Security\C4IT.Security.SecurePassword.cs">
|
||||
<Link>Common\C4IT.Security.SecurePassword.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\XML\C4IT.XML.ConfigParsing.cs">
|
||||
<Link>Common\C4IT.XML.ConfigParsing.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Common Code\XML\C4IT.XML.Credentials.cs">
|
||||
<Link>Common\C4IT.XML.Credentials.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\Matrix42\M42CommonCode\M42WebClient\C4IT.Matrix42.WebClient.cs">
|
||||
<Link>Common\C4IT.Matrix42.WebClient.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\NexThink\NxCommonCode\NXQL\C4IT.Nexthink.NXQL.cs">
|
||||
<Link>Common\C4IT.Nexthink.NXQL.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\NexThink\NxCommonCode\NXQL\C4IT.Nexthink.NxqlOrchestration.cs">
|
||||
<Link>Common\C4IT.Nexthink.NxqlOrchestration.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\CommonAssemblyAttributes.cs">
|
||||
<Link>Common\CommonAssemblyAttributes.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\CommonAssemblyInfo.cs">
|
||||
<Link>Properties\CommonAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="C4IT_2016.ico" />
|
||||
<Content Include="Microsoft.Web.Administration.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<COMReference Include="ActiveDs">
|
||||
<Guid>{97D25DB0-0363-11CF-ABC4-02608C9E7553}</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MaterialIcons" Version="1.0.3" NoWarn="NU1701" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.0" />
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="System.DirectoryServices" Version="9.0.7" />
|
||||
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="9.0.7" />
|
||||
<PackageReference Include="System.DirectoryServices.Protocols" Version="9.0.7" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="9.0.7" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.13.0" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.2" />
|
||||
<PackageReference Include="System.Security.Permissions" Version="9.0.7" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="9.0.7" />
|
||||
</ItemGroup>
|
||||
<Target Name="AfterBuild" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<FrameworkDirectory>net472/</FrameworkDirectory>
|
||||
</PropertyGroup>
|
||||
<Message Text="Start to publish component" Importance="high" />
|
||||
<Copy SourceFiles="$(ProjectDir)$(OutputPath)$(FrameworkDirectory)$(AssemblyName).dll" DestinationFolder="$(ProjectDir)Publish$(TargetFramework)" />
|
||||
</Target>
|
||||
</Project>
|
||||
48
F4SD-Cockpit-ServerCore/F4SDConfigGlobalParametersXml.cs
Normal file
48
F4SD-Cockpit-ServerCore/F4SDConfigGlobalParametersXml.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
using C4IT.XML;
|
||||
|
||||
namespace C4IT.FASD.Base
|
||||
{
|
||||
public class cF4SDConfigGlobalParametersXml : cFasdBaseConfig
|
||||
{
|
||||
public const string constFileNameFasdConfig = "F4SD-Global-Configuration.xml";
|
||||
private const string constFileNameFasdConfigSchema = "F4SD-Global-Configuration.xsd";
|
||||
private const string constConfigRootElement = "F4SD-Global-Configuration";
|
||||
|
||||
private Dictionary<string, cConfigurationSubnode> Nodes = new Dictionary<string, cConfigurationSubnode>();
|
||||
private Dictionary<string, cConfigurationValue> Values = new Dictionary<string, cConfigurationValue>();
|
||||
|
||||
public cF4SDConfigGlobalParametersXml(string fileNameConfig, string fileNameConfigSchema, string configRootElement) : base(fileNameConfig, fileNameConfigSchema, configRootElement)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool InstantiateProperties(XmlElement RootElement, cXmlParser Parser)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private class cConfigurationSubnode : IConfigNodeNamed
|
||||
{
|
||||
public bool IsValid { get; private set; } = false;
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
||||
}
|
||||
|
||||
private class cConfigurationValue : IConfigNodeNamed
|
||||
{
|
||||
public bool IsValid { get; private set; } = false;
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
294
F4SD-Cockpit-ServerCore/F4SD_License.cs
Normal file
294
F4SD-Cockpit-ServerCore/F4SD_License.cs
Normal file
@@ -0,0 +1,294 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
using System.IO;
|
||||
|
||||
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using C4IT.Licensing;
|
||||
using C4IT.Logging;
|
||||
using C4IT.DataHistoryProvider;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.FASD.Licensing
|
||||
{
|
||||
public class cF4SDLicense : cC4itLicenseBase
|
||||
{
|
||||
static public cF4SDLicense Instance = null;
|
||||
|
||||
public bool IsIntrinsic { get; private set; } = false;
|
||||
|
||||
static cF4SDLicense()
|
||||
{
|
||||
Instance = new cF4SDLicense
|
||||
{
|
||||
IsIntrinsic = true
|
||||
};
|
||||
//Instance.CreateIntrinsicModules();
|
||||
//Instance.SetValid();
|
||||
}
|
||||
|
||||
public cF4SDLicense() : base(new Guid("776D99A6-D341-4B70-BA4B-2CC55B76A079"))
|
||||
{
|
||||
if (Instance == null)
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
public void SetValid()
|
||||
{
|
||||
this.StartDate = null;
|
||||
this.EndDate = null;
|
||||
this.licenseType = LicenseType.productive;
|
||||
this.LicenseMetrics = new cLicenseMetrics()
|
||||
{
|
||||
MetricType = cLicenseMetrics.eLicenseMetricType.ManagedUsers,
|
||||
Count = int.MaxValue
|
||||
};
|
||||
}
|
||||
|
||||
protected override cC4itLicenseBaseEntry CreateLicenseEntry()
|
||||
{
|
||||
return new cF4SDLicenseEntry();
|
||||
}
|
||||
|
||||
public class cF4SDLicenseEntry : cC4itLicenseBaseEntry
|
||||
{
|
||||
public override bool Validate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static public string GetProgramFolderLocation(Assembly ExecutingAssembly, string SubFolder, string Location)
|
||||
{
|
||||
try
|
||||
{
|
||||
var Ass = ExecutingAssembly;
|
||||
if (Ass == null)
|
||||
Ass = Assembly.GetEntryAssembly();
|
||||
|
||||
if (Ass == null)
|
||||
return null;
|
||||
|
||||
var P = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Path.GetFullPath(Ass.Location))));
|
||||
if (!string.IsNullOrEmpty(SubFolder))
|
||||
P = Path.Combine(P, SubFolder);
|
||||
var FullPath = Path.Combine(P, Location);
|
||||
if (File.Exists(FullPath))
|
||||
return FullPath;
|
||||
|
||||
P = Ass.CodeBase;
|
||||
var uri = new Uri(P);
|
||||
string path = uri.LocalPath;
|
||||
path = Path.GetDirectoryName(path);
|
||||
string webserviceProgramFolder = Path.GetFullPath(path);
|
||||
if (!string.IsNullOrEmpty(SubFolder))
|
||||
webserviceProgramFolder = Path.Combine(webserviceProgramFolder, SubFolder);
|
||||
webserviceProgramFolder = Path.Combine(webserviceProgramFolder, Location);
|
||||
webserviceProgramFolder = Path.GetFullPath(webserviceProgramFolder);
|
||||
if (File.Exists(webserviceProgramFolder))
|
||||
{
|
||||
FullPath = webserviceProgramFolder;
|
||||
return webserviceProgramFolder;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static class RegistryHelper
|
||||
{
|
||||
public const int KEY_WOW64_32KEY = 0x200;
|
||||
|
||||
[DllImport("advapi32.dll", EntryPoint = "RegQueryInfoKey", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
|
||||
private static extern int RegQueryInfoKey(
|
||||
UIntPtr hkey,
|
||||
out StringBuilder lpClass,
|
||||
ref uint lpcbClass,
|
||||
IntPtr lpReserved,
|
||||
out uint lpcSubKeys,
|
||||
out uint lpcbMaxSubKeyLen,
|
||||
out uint lpcbMaxClassLen,
|
||||
out uint lpcValues,
|
||||
out uint lpcbMaxValueNameLen,
|
||||
out uint lpcbMaxValueLen,
|
||||
out uint lpcbSecurityDescriptor,
|
||||
ref FILETIME lpftLastWriteTime);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError = true)]
|
||||
private static extern int RegCloseKey(UIntPtr hKey);
|
||||
|
||||
|
||||
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
|
||||
private static extern int RegOpenKeyEx(
|
||||
UIntPtr hKey,
|
||||
string subKey,
|
||||
int ulOptions,
|
||||
int samDesired,
|
||||
out UIntPtr hkResult);
|
||||
|
||||
private static DateTime ToDateTime(FILETIME ft)
|
||||
{
|
||||
IntPtr buf = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
long[] longArray = new long[1];
|
||||
int cb = Marshal.SizeOf(ft);
|
||||
buf = Marshal.AllocHGlobal(cb);
|
||||
Marshal.StructureToPtr(ft, buf, false);
|
||||
Marshal.Copy(buf, longArray, 0, 1);
|
||||
return DateTime.FromFileTime(longArray[0]);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (buf != IntPtr.Zero) Marshal.FreeHGlobal(buf);
|
||||
}
|
||||
}
|
||||
|
||||
public static DateTime? GetDateModified(RegistryHive registryHive, string path, bool use32Bit)
|
||||
{
|
||||
var lastModified = new FILETIME();
|
||||
var lpcbClass = new uint();
|
||||
var lpReserved = new IntPtr();
|
||||
UIntPtr key = UIntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
int samDesired = (int)RegistryRights.ReadKey;
|
||||
if (use32Bit)
|
||||
samDesired |= KEY_WOW64_32KEY;
|
||||
|
||||
var hive = new UIntPtr(unchecked((uint)registryHive));
|
||||
if (RegOpenKeyEx(hive, path, 0, samDesired, out key) != 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (RegQueryInfoKey(
|
||||
key,
|
||||
out StringBuilder sb,
|
||||
ref lpcbClass,
|
||||
lpReserved,
|
||||
out uint lpcbSubKeys,
|
||||
out uint lpcbMaxKeyLen,
|
||||
out uint lpcbMaxClassLen,
|
||||
out uint lpcValues,
|
||||
out uint maxValueName,
|
||||
out uint maxValueLen,
|
||||
out uint securityDescriptor,
|
||||
ref lastModified) != 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var result = ToDateTime(lastModified);
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (key != UIntPtr.Zero)
|
||||
RegCloseKey(key);
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void CreateIntrinsicModules()
|
||||
{
|
||||
if (!IsIntrinsic)
|
||||
return;
|
||||
|
||||
if (this.Modules == null)
|
||||
this.Modules = new Dictionary<Guid, cC4itLicenseBaseModule>(2);
|
||||
|
||||
var _mod = new cC4itLicenseBaseModule()
|
||||
{
|
||||
Name = cDataHistoryCollectorClientAgent.constConnectorName,
|
||||
Id = new Guid(cDataHistoryCollectorClientAgent.constLicenseId)
|
||||
};
|
||||
this.Modules.Add(_mod.Id,_mod);
|
||||
|
||||
_mod = new cC4itLicenseBaseModule()
|
||||
{
|
||||
Name = cDataHistoryCollectorActiveDirectory.constConnectorName,
|
||||
Id = new Guid(cDataHistoryCollectorActiveDirectory.constLicenseId)
|
||||
};
|
||||
this.Modules.Add(_mod.Id, _mod);
|
||||
|
||||
}
|
||||
|
||||
static public void CheckLicense(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
var strLicPath = cF4SDLicense.GetProgramFolderLocation(Assembly.GetCallingAssembly(), "..\\License", "F4SD_License.xml");
|
||||
if (!File.Exists(strLicPath))
|
||||
strLicPath = cF4SDLicense.GetProgramFolderLocation(Assembly.GetCallingAssembly(), "License", "F4SD_License.xml");
|
||||
|
||||
if (File.Exists(strLicPath))
|
||||
{
|
||||
var Lic = new cF4SDLicense();
|
||||
if (Lic.LoadFromFile(strLicPath, false))
|
||||
cF4SDLicense.Instance = Lic;
|
||||
}
|
||||
if (cF4SDLicense.Instance.IsIntrinsic)
|
||||
cLogManager.DefaultLogger.LogEntry(LogLevels.Info, $"Intrinsic license set");
|
||||
}
|
||||
|
||||
static public List<string> LogLicenseState()
|
||||
{
|
||||
var s = new List<string>();
|
||||
var _lic = Instance;
|
||||
if (_lic == null)
|
||||
return null;
|
||||
|
||||
if (_lic.IsIntrinsic)
|
||||
s.Add("The F4SD license is intrinsic.");
|
||||
if (_lic.IsValid && _lic.licenseType == LicenseType.productive)
|
||||
s.Add("The F4SD License is valid.");
|
||||
else if (_lic.IsValid)
|
||||
s.Add($"The F4SD License is valid only for {_lic.licenseType.ToString().ToLowerInvariant()} purposes.");
|
||||
else
|
||||
s.Add("The F4SD License is invalid.");
|
||||
|
||||
if (_lic.IsValid || _lic.IsExpired)
|
||||
{
|
||||
s.Add($" Customer:{_lic.Customer}");
|
||||
if (_lic.EndDate == null)
|
||||
s.Add($" valid until: everytime");
|
||||
else
|
||||
s.Add($" valid until: {(DateTime)_lic.EndDate}");
|
||||
if (_lic.LicenseMetrics != null)
|
||||
s.Add($" license count {_lic.LicenseMetrics.Count}");
|
||||
|
||||
}
|
||||
s.Add("");
|
||||
s.Add("Licensed modules:");
|
||||
if (_lic.Modules == null || _lic.Modules.Count == 0)
|
||||
s.Add("- none -");
|
||||
else
|
||||
foreach (var _mod in _lic.Modules.Values)
|
||||
s.Add($" {_mod.Name}");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
119
F4SD-Cockpit-ServerCore/IisConfigHelper.cs
Normal file
119
F4SD-Cockpit-ServerCore/IisConfigHelper.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.Web.Administration;
|
||||
|
||||
using C4IT.Logging;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT_DataHistoryProvider_Base
|
||||
{
|
||||
public static class IisConfigHelper
|
||||
{
|
||||
public static cIssConfiguration CheckIISConfiguration()
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
var _res = new cIssConfiguration();
|
||||
CheckIISComponents(_res);
|
||||
CheckIISConfiuration(_res);
|
||||
|
||||
return _res;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void CheckIISComponents(cIssConfiguration _issConfig)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
var _regBase = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
|
||||
var _regKey = _regBase.OpenSubKey("SOFTWARE\\Microsoft\\InetStp\\Components", false);
|
||||
if (_regKey != null)
|
||||
{
|
||||
var _regVal1 = _regKey.GetValue("WindowsAuthentication")?.ToString();
|
||||
var _regVal2 = _regKey.GetValue("WindowsAuthenticationBinaries")?.ToString();
|
||||
_issConfig.IsIssWindowsAuthenticationInstalled = _regVal1 == "1" && _regVal2 == "1";
|
||||
|
||||
var _regVal3 = _regKey.GetValue("WebSockets")?.ToString();
|
||||
_issConfig.IsWebSocketInstalled = _regVal3 == "1";
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckIISConfiuration(cIssConfiguration _issConfig)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
var _serverManager = new ServerManager();
|
||||
|
||||
var _siteCollections = _serverManager.Sites;
|
||||
foreach (var _site in _siteCollections)
|
||||
{
|
||||
var _applications = _site.Applications;
|
||||
foreach (var _application in _applications)
|
||||
{
|
||||
if (_application.Path.ToLowerInvariant() != "/f4sdcockpit")
|
||||
continue;
|
||||
|
||||
var _appConfig = _application.GetWebConfiguration();
|
||||
var _cfgWindowsAuthentication = _appConfig.GetSection("system.webServer/security/authentication/windowsAuthentication");
|
||||
if (_cfgWindowsAuthentication != null)
|
||||
{
|
||||
var _attr = _cfgWindowsAuthentication.Attributes.FirstOrDefault(v => v.Name == "enabled");
|
||||
if (_attr != null)
|
||||
{
|
||||
if (_attr.Value is bool _valWindowsAuthentication)
|
||||
_issConfig.IsIssWindowsAuthenticationEnabled |= _valWindowsAuthentication;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class cIssConfiguration
|
||||
{
|
||||
public bool IsIssWindowsAuthenticationInstalled = false;
|
||||
public bool IsWebSocketInstalled = false;
|
||||
public bool IsIssWindowsAuthenticationEnabled = false;
|
||||
}
|
||||
}
|
||||
BIN
F4SD-Cockpit-ServerCore/Microsoft.Web.Administration.dll
Normal file
BIN
F4SD-Cockpit-ServerCore/Microsoft.Web.Administration.dll
Normal file
Binary file not shown.
5
F4SD-Cockpit-ServerCore/Properties/AssemblyInfo.cs
Normal file
5
F4SD-Cockpit-ServerCore/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: Guid("49452fc2-05ce-4077-8b40-8adf5eca212e")]
|
||||
28
F4SD-Cockpit-ServerCore/Services/IStagedRelationService.cs
Normal file
28
F4SD-Cockpit-ServerCore/Services/IStagedRelationService.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using C4IT.FASD.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace C4IT_DataHistoryProvider_Base.Services
|
||||
{
|
||||
public interface IStagedRelationService
|
||||
{
|
||||
/// <summary>
|
||||
/// Triggers search for relations to given information objects.
|
||||
/// </summary>
|
||||
cF4sdStagedSearchResultRelationTaskId StartGatheringRelatedObjects(IEnumerable<cFasdApiSearchResultEntry> relatedTo, int ageInDays);
|
||||
|
||||
/// <summary>
|
||||
/// Used after triggering search for related objects in <see cref="StartGatheringRelatedObjects"/> to retrieve the already found relations.
|
||||
/// </summary>
|
||||
/// <param name="id">Id returned by <see cref="StartGatheringRelatedObjects"/> to reference the results to a search term.</param>
|
||||
Task<cF4sdStagedSearchResultRelations> GetRelatedObjectsAsync(Guid id, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Cancels the gathering of related objects.
|
||||
/// </summary>
|
||||
/// <param name="id">Id returned by <see cref="StartGatheringRelatedObjects"/> to reference the gathering process.</param>
|
||||
void StopGatheringRelatedObjects(Guid id);
|
||||
}
|
||||
}
|
||||
168
F4SD-Cockpit-ServerCore/Services/StagedRelationService.cs
Normal file
168
F4SD-Cockpit-ServerCore/Services/StagedRelationService.cs
Normal file
@@ -0,0 +1,168 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT_DataHistoryProvider_Base.DataSources;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT_DataHistoryProvider_Base.Services
|
||||
{
|
||||
public class StagedRelationService : IStagedRelationService
|
||||
{
|
||||
private static readonly Dictionary<Guid, GatherRelatedObjectTask> _relationTasks = new Dictionary<Guid, GatherRelatedObjectTask>();
|
||||
private readonly IEnumerable<ISearchResultRelationProvider> _providers;
|
||||
|
||||
private static readonly System.Timers.Timer _relationTaskCleanupTimer = new System.Timers.Timer(CleanupInterval);
|
||||
private const int CleanupInterval = 5 * 60 * 1000;
|
||||
private readonly TimeSpan RelationTaskExpiration = TimeSpan.FromMinutes(15);
|
||||
|
||||
public StagedRelationService(IEnumerable<ISearchResultRelationProvider> providers)
|
||||
{
|
||||
_providers = providers;
|
||||
SetupCleanupTimer();
|
||||
}
|
||||
|
||||
private void SetupCleanupTimer()
|
||||
{
|
||||
if (_relationTaskCleanupTimer.Enabled)
|
||||
return;
|
||||
|
||||
_relationTaskCleanupTimer.Interval = CleanupInterval;
|
||||
_relationTaskCleanupTimer.Elapsed += CleanUpRelationTasks;
|
||||
_relationTaskCleanupTimer.Start();
|
||||
}
|
||||
|
||||
public cF4sdStagedSearchResultRelationTaskId StartGatheringRelatedObjects(IEnumerable<cFasdApiSearchResultEntry> relatedTo, int age)
|
||||
{
|
||||
cF4sdStagedSearchResultRelationTaskId taskId = new cF4sdStagedSearchResultRelationTaskId();
|
||||
try
|
||||
{
|
||||
if (relatedTo.Count() == 0)
|
||||
return taskId;
|
||||
|
||||
GatherRelatedObjectTask relationTask = new GatherRelatedObjectTask() { RelatedObjectTasks = new List<(HashSet<enumFasdInformationClass> PendingInformationClasses, Task<cF4sdStagedSearchResultRelations> Task)>() };
|
||||
enumFasdInformationClass relatedToInformationClass = cF4sdIdentityEntry.GetFromSearchResult(relatedTo.FirstOrDefault().Type);
|
||||
|
||||
List<cF4sdIdentityEntry> identities = relatedTo.Select(relation => new cF4sdIdentityEntry() { Id = relation.id, Class = relatedToInformationClass }).ToList();
|
||||
|
||||
foreach (var collectorModule in _providers)
|
||||
{
|
||||
taskId.PendingInformationClasses.UnionWith(collectorModule.GetSupportedInformationClasses());
|
||||
|
||||
Task<cF4sdStagedSearchResultRelations> task = Task.Run(() =>
|
||||
collectorModule.GetRelationsAsync(identities, relatedToInformationClass, age, relationTask.TokenSource.Token));
|
||||
|
||||
relationTask.RelatedObjectTasks.Add((collectorModule.GetSupportedInformationClasses(), task));
|
||||
}
|
||||
|
||||
taskId.Id = Guid.NewGuid();
|
||||
_relationTasks.Add(taskId.Id, relationTask);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public async Task<cF4sdStagedSearchResultRelations> GetRelatedObjectsAsync(Guid id, CancellationToken token)
|
||||
{
|
||||
HashSet<enumFasdInformationClass> pendingInformationClasses = null;
|
||||
try
|
||||
{
|
||||
if (!_relationTasks.TryGetValue(id, out var gatherRelatedTask))
|
||||
{
|
||||
LogEntry($"Could find any task find related objects with Id '{id}'", LogLevels.Info);
|
||||
return null;
|
||||
}
|
||||
|
||||
IEnumerable<Task<cF4sdStagedSearchResultRelations>> gatheringTasks = gatherRelatedTask.RelatedObjectTasks.Select(relatedObjectTask => relatedObjectTask.Task);
|
||||
await Task.WhenAny(gatheringTasks);
|
||||
|
||||
lock (_relationTasks)
|
||||
{
|
||||
gatherRelatedTask.LastRetrievel = DateTime.UtcNow;
|
||||
var completedTasks = gatherRelatedTask.RelatedObjectTasks.Where(t => t.Task.IsCompleted).ToArray();
|
||||
|
||||
foreach (var completedTask in completedTasks)
|
||||
{
|
||||
gatherRelatedTask.RelatedObjectTasks.Remove(completedTask);
|
||||
}
|
||||
|
||||
pendingInformationClasses = new HashSet<enumFasdInformationClass>(gatherRelatedTask.RelatedObjectTasks.SelectMany(t => t.PendingInformationClasses));
|
||||
var relations = completedTasks.SelectMany(t => t.Task.Result.Relations ?? Enumerable.Empty<cF4sdApiSearchResultRelation>());
|
||||
return new cF4sdStagedSearchResultRelations() { Relations = relations, PendingInformationClasses = pendingInformationClasses };
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pendingInformationClasses?.Count == 0)
|
||||
_relationTasks.Remove(id);
|
||||
}
|
||||
|
||||
return new cF4sdStagedSearchResultRelations() { Relations = Enumerable.Empty<cF4sdApiSearchResultRelation>(), PendingInformationClasses = pendingInformationClasses };
|
||||
}
|
||||
|
||||
public void StopGatheringRelatedObjects(Guid id)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_relationTasks.TryGetValue(id, out var task))
|
||||
return;
|
||||
|
||||
task.TokenSource.Cancel();
|
||||
_relationTasks.Remove(id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void CleanUpRelationTasks(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
DateTime currentTime = DateTime.UtcNow;
|
||||
|
||||
List<Guid> expiredTasks = new List<Guid>();
|
||||
lock (_relationTasks)
|
||||
{
|
||||
foreach (var relationTask in _relationTasks)
|
||||
{
|
||||
if (currentTime - relationTask.Value.LastRetrievel < RelationTaskExpiration)
|
||||
continue;
|
||||
expiredTasks.Add(relationTask.Key);
|
||||
}
|
||||
|
||||
expiredTasks.ForEach(task => _relationTasks.Remove(task));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private class GatherRelatedObjectTask
|
||||
{
|
||||
public CancellationTokenSource TokenSource { get; set; }
|
||||
public DateTime LastRetrievel { get; set; }
|
||||
public ICollection<(HashSet<enumFasdInformationClass> PendingInformationClasses, Task<cF4sdStagedSearchResultRelations> Task)> RelatedObjectTasks { get; set; }
|
||||
|
||||
public GatherRelatedObjectTask()
|
||||
{
|
||||
TokenSource = new CancellationTokenSource();
|
||||
LastRetrievel = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
232
F4SD-Cockpit-ServerCore/SuccessorCache.cs
Normal file
232
F4SD-Cockpit-ServerCore/SuccessorCache.cs
Normal file
@@ -0,0 +1,232 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Web;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using static C4IT.FASD.Base.cF4SDHealthCardRawData;
|
||||
using System.Threading;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
public class cSuccessorJob
|
||||
{
|
||||
public List<string> Tables = new List<string>();
|
||||
public cF4SDHealthCardRawData data = null;
|
||||
public Task<bool> task = null;
|
||||
public CancellationToken Token = CancellationToken.None;
|
||||
public bool Finished = false;
|
||||
public DateTime FinishedTime;
|
||||
public List<Int64> Usage = null;
|
||||
}
|
||||
|
||||
public class SuccessorEntry : List<cSuccessorJob>
|
||||
{
|
||||
public List<Int64> UsageInfo = null;
|
||||
}
|
||||
|
||||
public static class SuccessorCache
|
||||
{
|
||||
private static Timer _timerCache = new Timer(callbackTimerCache, null, 1000, 10000);
|
||||
|
||||
private static void callbackTimerCache(object state)
|
||||
{
|
||||
var myNow = DateTime.UtcNow;
|
||||
lock (Cache)
|
||||
{
|
||||
var lstIds = new List<Guid>();
|
||||
|
||||
foreach (var Entry in Cache)
|
||||
{
|
||||
var lstJobs = new List<cSuccessorJob>();
|
||||
foreach (var Job in Entry.Value)
|
||||
{
|
||||
if (Job.Finished && (myNow - Job.FinishedTime) > TimeSpan.FromSeconds(60))
|
||||
lstJobs.Add(Job);
|
||||
}
|
||||
|
||||
foreach (var Job in lstJobs)
|
||||
Entry.Value.Remove(Job);
|
||||
|
||||
if (Entry.Value.Count == 0)
|
||||
lstIds.Add(Entry.Key);
|
||||
}
|
||||
|
||||
foreach (var id in lstIds)
|
||||
Cache.Remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<Guid, SuccessorEntry> Cache = new Dictionary<Guid, SuccessorEntry>();
|
||||
|
||||
|
||||
public static bool AddTask(Guid Id, List<string> Tables, Task<List<cF4SDHealthCardRawData.cHealthCardTable>> task, List<Int64> UsageInfo, CancellationToken Token)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
var Job = new cSuccessorJob();
|
||||
lock (Cache)
|
||||
{
|
||||
if (!Cache.TryGetValue(Id, out var lst))
|
||||
{
|
||||
lst = new SuccessorEntry() { Job };
|
||||
Cache.Add(Id, lst);
|
||||
}
|
||||
else
|
||||
lst.Add(Job);
|
||||
|
||||
if (UsageInfo != null)
|
||||
lst.UsageInfo = UsageInfo;
|
||||
}
|
||||
|
||||
Job.Tables = Tables;
|
||||
Job.task = Task.Run<bool>(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var res = await task;
|
||||
Dictionary<string, cHealthCardTable> tbls = null;
|
||||
if (res != null)
|
||||
tbls = res.ToDictionary(x => x.Name, x => x);
|
||||
lock (Cache)
|
||||
{
|
||||
Job.task = null;
|
||||
Job.data = new cF4SDHealthCardRawData()
|
||||
{
|
||||
Id = Id,
|
||||
Tables = tbls
|
||||
};
|
||||
Job.Finished = true;
|
||||
Job.FinishedTime = DateTime.UtcNow;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
return false;
|
||||
}, Token);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static async Task<cF4SDHealthCardRawData> GetNextResult(cDataHistoryCollector Collector, Guid Id, bool noAwait, cF4sdWebRequestInfo requestInfo, int LogDeep)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
|
||||
var _startTime = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
{
|
||||
var lstResults = new SuccessorEntry();
|
||||
var lstTasks = new SuccessorEntry();
|
||||
var lstWaitingTables = new List<string>();
|
||||
lock (Cache)
|
||||
{
|
||||
if (!Cache.TryGetValue(Id, out var lstObj))
|
||||
return null;
|
||||
|
||||
foreach (var Entry in lstObj)
|
||||
{
|
||||
if (Entry.Finished)
|
||||
lstResults.Add(Entry);
|
||||
else
|
||||
{
|
||||
lstTasks.Add(Entry);
|
||||
lstWaitingTables.AddRange(Entry.Tables);
|
||||
}
|
||||
}
|
||||
foreach (var Entry in lstResults)
|
||||
lstObj.Remove(Entry);
|
||||
}
|
||||
|
||||
if (lstTasks.Count == 0)
|
||||
Cache.Remove(Id);
|
||||
|
||||
if (lstResults.Count > 0)
|
||||
{
|
||||
var RetVal = lstResults[0];
|
||||
for (int i = 1; i < lstResults.Count; i++)
|
||||
{
|
||||
var res = lstResults[i];
|
||||
if (res?.data?.Tables != null)
|
||||
{
|
||||
foreach (var Entry in res.data.Tables)
|
||||
{
|
||||
if (RetVal?.data?.Tables != null)
|
||||
RetVal.data.Tables[Entry.Key] = Entry.Value;
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
foreach (var Table in lstWaitingTables)
|
||||
{
|
||||
var tbl = new cF4SDHealthCardRawData.cHealthCardTable()
|
||||
{
|
||||
Name = Table,
|
||||
IsIncomplete = true,
|
||||
};
|
||||
if (RetVal?.data?.Tables != null)
|
||||
RetVal.data.Tables[Table] = tbl;
|
||||
}
|
||||
|
||||
// correct the result due to usage information
|
||||
if (RetVal.data != null && lstTasks.UsageInfo != null)
|
||||
cDataHistoryCollector.CorrectUsage(Collector, RetVal.data, lstTasks.UsageInfo);
|
||||
|
||||
return RetVal.data;
|
||||
}
|
||||
|
||||
if (noAwait)
|
||||
return null;
|
||||
|
||||
var arrTask = new Task<bool>[lstTasks.Count];
|
||||
for (int i = 0; i < lstTasks.Count; i++)
|
||||
arrTask[i] = lstTasks[i].task;
|
||||
|
||||
var tskFinished = await Task.WhenAny(arrTask);
|
||||
|
||||
return await GetNextResult(Collector, Id, true, requestInfo, LogDeep+1);
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (cPerformanceLogger.IsActive && requestInfo != null) { cPerformanceLogger.LogPerformanceEnd(LogDeep, CM, requestInfo.id, requestInfo.created, _startTime); }
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
39
F4SD-Cockpit-ServerCore/app.config
Normal file
39
F4SD-Cockpit-ServerCore/app.config
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Text.Encodings.Web" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.3.0" newVersion="6.0.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-8.0.0.5" newVersion="8.0.0.5" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user