Prepare Data History Provider 2.7 integration update
- modularize Citrix and agent integrations and add remote desktop endpoints - extend ticket overview, ticket links, token validation, and staged relation handling - update configuration, licensing, project, signing, and publish artifacts
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Diagnostics;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.DirectoryServices.ActiveDirectory;
|
||||
using System.Globalization;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
@@ -13,28 +17,26 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.DirectoryServices.ActiveDirectory;
|
||||
using System.IO;
|
||||
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using C4IT.Configuration;
|
||||
using C4IT.DataHistoryProvider.Base.Modules.Citrix;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Licensing;
|
||||
using C4IT.Logging;
|
||||
using C4IT.Matrix42.WebClient;
|
||||
using C4IT.Security;
|
||||
using C4IT.XML;
|
||||
using C4IT.Matrix42.WebClient;
|
||||
|
||||
using C4IT_DataHistoryProvider_Base;
|
||||
using C4IT_DataHistoryProvider_Base.DataSources;
|
||||
using C4IT_DataHistoryProvider_Base.Services;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using static C4IT.FASD.Base.cF4sdQuickActionRevision;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
|
||||
@@ -105,7 +107,18 @@ namespace C4IT.DataHistoryProvider
|
||||
|
||||
public abstract Task<bool> DoScanAsync(bool Always, bool Rescan, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken Token, bool EnhancedDebug = false);
|
||||
|
||||
public abstract Task<List<object>> GetIds(cF4sdConnectorIds IdEntry, enumFasdInformationClass InfoClass, cF4sdWebRequestInfo requestInfo, int LogDeep);
|
||||
public virtual async Task<List<object>> GetIds(cF4sdConnectorIds IdEntry, enumFasdInformationClass InfoClass, cF4sdWebRequestInfo requestInfo, int LogDeep)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
if (IdEntry.sid == null)
|
||||
return null;
|
||||
return new List<object>() { IdEntry.Id };
|
||||
}
|
||||
|
||||
public virtual bool UseForeignUserIds()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual List<object> GetFilterValues(List<object> IDs, enumFasdInformationClass InfoClass)
|
||||
{
|
||||
@@ -222,6 +235,15 @@ namespace C4IT.DataHistoryProvider
|
||||
await Task.CompletedTask;
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual async Task<int> ValidateTokenInfo(cDataHistoryCollectorTokenCache.cTokenInfo tokenInfo)
|
||||
// 0: Token Info is correct
|
||||
// -1: Token Info is incorrect
|
||||
// 1: Token Info as to be updated due to newer infos
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class cDataHistoryCollector : cDataHistoryCollectorModule, IConfigNodeValidation, ISearchResultRelationProvider
|
||||
@@ -257,6 +279,7 @@ namespace C4IT.DataHistoryProvider
|
||||
public cDataHistoryCollectorM42Wpm M42WpmCollector { get; private set; } = null;
|
||||
public cDataHistoryCollectorNxql NxqlCollector { get; private set; } = null;
|
||||
public cDataHistoryCollectorCitrix CitrixCollector { get; private set; } = null;
|
||||
//public cDataHistoryCollectorEmpirum EmpirumCollector { get; private set; } = null;
|
||||
public bool F4SDAnalyticsValid = false;
|
||||
public cF4SDAnalyticsConfigDatabase F4SDAnalyticsDb { get; private set; } = null;
|
||||
public event DataHistoryUiMessageFunc ProcessUiMessage;
|
||||
@@ -279,6 +302,8 @@ namespace C4IT.DataHistoryProvider
|
||||
|
||||
private readonly List<ISearchResultRelationProvider> _searchResultRelationProviders = new List<ISearchResultRelationProvider>();
|
||||
|
||||
private Dictionary<cF4SDTokenRegistration.enumTokenType, cDataHistoryCollectorModule> _tokenValidators = new Dictionary<cF4SDTokenRegistration.enumTokenType, cDataHistoryCollectorModule>();
|
||||
|
||||
public bool RunningInIISExpress = false;
|
||||
|
||||
#region Services
|
||||
@@ -288,7 +313,7 @@ namespace C4IT.DataHistoryProvider
|
||||
public IStagedRelationService GetStagedRelationService()
|
||||
{
|
||||
if (_stagedRelationService is null)
|
||||
_stagedRelationService = new StagedRelationService(_searchResultRelationProviders);
|
||||
_stagedRelationService = new StagedRelationService(this, _searchResultRelationProviders);
|
||||
|
||||
return _stagedRelationService;
|
||||
}
|
||||
@@ -329,7 +354,7 @@ namespace C4IT.DataHistoryProvider
|
||||
if (cF4SDLicense.Instance.Modules.ContainsKey(_ActiveDirectory.LicenseId))
|
||||
{
|
||||
ActiveDirectory = _ActiveDirectory;
|
||||
Connectors.Add(enumDataHistoryOrigin.ActiveDirectory, ActiveDirectory);
|
||||
Connectors.Add(enumDataHistoryOrigin.ActiveDirectory, ActiveDirectory);
|
||||
}
|
||||
|
||||
var _F4sdAgent = new cDataHistoryCollectorClientAgent(this);
|
||||
@@ -450,6 +475,7 @@ namespace C4IT.DataHistoryProvider
|
||||
var HasIntuneConfig = (_cfgInfrastructure.AzureTenants?.Values.Any(t => t.ScanIntuneDevices) == true);
|
||||
var HasMobileDeviceConfig = (_cfgInfrastructure.AzureTenants?.Values.Any(t => t.WithMobileDevices) == true);
|
||||
var HasCitrixConfig = (InfrastructureConfig.Citrix != null);
|
||||
var HasEmpirumConfig = true;
|
||||
|
||||
DoProcessUiMessage(1, "resolving the ad membership groups");
|
||||
ActiveDirectory.ResolveWinAuthenticationGroups();
|
||||
@@ -462,7 +488,7 @@ namespace C4IT.DataHistoryProvider
|
||||
DoProcessUiMessage(0, "");
|
||||
DoProcessUiMessage(1, "loading the data cluster definitions...");
|
||||
var _cfgDataClusters = new cDataHistoryConfigClusters();
|
||||
_cfgDataClusters.LoadFromFile(out PMs, withM42Config: HasM42Config, withIntuneConfig: HasIntuneConfig,withMobileDeviceConfig:HasMobileDeviceConfig,withCitrixConfig:HasCitrixConfig);
|
||||
_cfgDataClusters.LoadFromFile(out PMs, withM42Config: HasM42Config, withIntuneConfig: HasIntuneConfig, withMobileDeviceConfig: HasMobileDeviceConfig, withCitrixConfig: HasCitrixConfig);
|
||||
|
||||
if (PMs != null && PMs.Count > 0)
|
||||
DoProcessUiMessage(2, PMs);
|
||||
@@ -509,24 +535,32 @@ namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
var _CitrixCollector = new cDataHistoryCollectorCitrix(this);
|
||||
if (cF4SDLicense.Instance?.Modules != null)
|
||||
//if (cF4SDLicense.Instance.Modules.ContainsKey(_CitrixCollector.LicenseId))
|
||||
//{
|
||||
CitrixCollector = _CitrixCollector;
|
||||
Connectors.Add(enumDataHistoryOrigin.Citrix, _CitrixCollector);
|
||||
RegisterSearchRelationProvider(_CitrixCollector);
|
||||
//}
|
||||
if (cF4SDLicense.Instance.Modules.ContainsKey(_CitrixCollector.LicenseId))
|
||||
{
|
||||
CitrixCollector = _CitrixCollector;
|
||||
Connectors.Add(enumDataHistoryOrigin.Citrix, _CitrixCollector);
|
||||
RegisterSearchRelationProvider(_CitrixCollector);
|
||||
}
|
||||
}
|
||||
|
||||
if(HasIntuneConfig)
|
||||
if (HasIntuneConfig)
|
||||
{
|
||||
Connectors.Add(enumDataHistoryOrigin.Intune, ActiveDirectory);
|
||||
|
||||
|
||||
}
|
||||
//if (HasIntuneConfig && HasMobileDeviceConfig)
|
||||
//{
|
||||
// RegisterSearchRelationProvider(ActiveDirectory);
|
||||
//}
|
||||
|
||||
//if (HasEmpirumConfig)
|
||||
//{
|
||||
// var _EmpirumCollector = new cDataHistoryCollectorEmpirum(this);
|
||||
// EmpirumCollector = _EmpirumCollector;
|
||||
// Connectors.Add(enumDataHistoryOrigin.Empirum, EmpirumCollector);
|
||||
|
||||
//}
|
||||
|
||||
// do the post configuration tasks afer the infrastructure was loaded
|
||||
DoProcessUiMessage(1, "processing post configuration tasks");
|
||||
foreach (var Table in _cfgDataClusters.Tables.Values)
|
||||
@@ -673,7 +707,7 @@ namespace C4IT.DataHistoryProvider
|
||||
var HasMobileDeviceConfig = (InfrastructureConfig.AzureTenants?.Values.Any(t => t.WithMobileDevices) == true);
|
||||
var HasCitrixConfig = (InfrastructureConfig.Citrix != null);
|
||||
|
||||
var _cfg = cFasdBaseConfig.GetConfigByType(_item, null, _msg, withM42Config: HasM42Config, withIntuneConfig: HasIntuneConfig, withMobileDeviceConfig: HasMobileDeviceConfig, withCitrixConfig:HasCitrixConfig);
|
||||
var _cfg = cFasdBaseConfig.GetConfigByType(_item, null, _msg, withM42Config: HasM42Config, withIntuneConfig: HasIntuneConfig, withMobileDeviceConfig: HasMobileDeviceConfig, withCitrixConfig: HasCitrixConfig);
|
||||
if (_cfg.IsValid)
|
||||
{
|
||||
_Configs[_item] = _cfg;
|
||||
@@ -1201,7 +1235,6 @@ namespace C4IT.DataHistoryProvider
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private async Task<bool> UpdateF4SDAnalyticsViewsAsync(cDbConnection DbConn, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken Token, bool ForceCreate)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
@@ -2490,7 +2523,7 @@ namespace C4IT.DataHistoryProvider
|
||||
var anonymous = InfrastructureConfig.F4SDAnalyticsDB?.AnonymousUser;
|
||||
Guid.TryParse(requestInfo.userInfo?.Id.ToString(), out Guid userGuid);
|
||||
if (anonymous != null && (bool)anonymous)
|
||||
Param.User = GetUserHashGuid(userGuid).ToString();
|
||||
Param.User = GetUserHashGuid(userGuid).ToString();
|
||||
else
|
||||
Param.User = userGuid.ToString();
|
||||
|
||||
@@ -2666,17 +2699,27 @@ namespace C4IT.DataHistoryProvider
|
||||
}
|
||||
|
||||
|
||||
public async Task<cF4sdUserInfo> GetCurrentUserInfoAsync(CancellationToken Token, cF4sdWebRequestInfo requestInfo, int LogDeep)
|
||||
public async Task<cF4sdUserInfo> GetCurrentUserInfoAsync(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;
|
||||
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 _user = WindowsIdentity.GetCurrent();
|
||||
var _res = await GetWinUserInfoAsync(_user, CultureInfo.CurrentCulture.DisplayName, true, Token, requestInfo, LogDeep + 1);
|
||||
return _res;
|
||||
if (!ActiveDirectory.WinAuthenticationGropsResolved)
|
||||
{
|
||||
ActiveDirectory.ResolveWinAuthenticationGroups();
|
||||
|
||||
if (!ActiveDirectory.WinAuthenticationGropsResolved)
|
||||
{
|
||||
LogEntry("Could not resolve authentication groups", LogLevels.Warning);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
WindowsIdentity user = WindowsIdentity.GetCurrent();
|
||||
return await GetWinUserInfoAsync(user, CultureInfo.CurrentCulture.DisplayName, true, Token, requestInfo, logDeep + 1);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
@@ -2684,7 +2727,7 @@ namespace C4IT.DataHistoryProvider
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (cPerformanceLogger.IsActive && requestInfo != null) { cPerformanceLogger.LogPerformanceEnd(LogDeep, CM, requestInfo.id, requestInfo.created, _startTime); }
|
||||
if (cPerformanceLogger.IsActive && requestInfo != null) { cPerformanceLogger.LogPerformanceEnd(logDeep, CM, requestInfo.id, requestInfo.created, startTime); }
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
@@ -2938,8 +2981,8 @@ namespace C4IT.DataHistoryProvider
|
||||
}
|
||||
if (strPhone != null)
|
||||
{
|
||||
Entry.Result.Name = strName + " (" + strPhone + ")";
|
||||
Entry.Result.DisplayName = strName + " (" + strPhone + ")";
|
||||
Entry.Result.Name = strName;
|
||||
Entry.Result.DisplayName = $"{strName} ({strPhone})";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3853,7 +3896,7 @@ namespace C4IT.DataHistoryProvider
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<List<cF4sdApiSearchResultRelation>> GetUsageFromOnlyAgentData(enumFasdInformationClass infoClass, List<Guid> Ids, int Age, CancellationToken Token, cF4sdWebRequestInfo requestInfo, int LogDeep)
|
||||
public async Task<List<cF4sdApiSearchResultRelation>> GetUsageFromOnlyAgentData(IEnumerable<cF4sdConnectorIds> ids, enumFasdInformationClass infoClass, int Age, CancellationToken Token, cF4sdWebRequestInfo requestInfo, int LogDeep)
|
||||
{
|
||||
MethodBase CM = null;
|
||||
if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
@@ -3862,20 +3905,15 @@ namespace C4IT.DataHistoryProvider
|
||||
|
||||
try
|
||||
{
|
||||
var _count = ids.Count();
|
||||
var Age2 = Age;
|
||||
if (Ids.Count == 1)
|
||||
if (_count == 1)
|
||||
Age2 = 365;
|
||||
var AgentLimit = DateTime.UtcNow + TimeSpan.FromDays(-Age2);
|
||||
|
||||
var idInput = Ids.Select(v => new cF4sdIdentityEntry() { Id = v, Class = infoClass }).ToList();
|
||||
var listIds = await getConnectorIdList(idInput, Token, requestInfo, LogDeep + 1);
|
||||
var lstAgentIds = new Dictionary<int, cDataHistoryUsageIdInfo>(_count);
|
||||
|
||||
if (listIds == null || listIds.Count == 0)
|
||||
return null;
|
||||
|
||||
var lstAgentIds = new Dictionary<int, cDataHistoryUsageIdInfo>(Ids.Count);
|
||||
|
||||
foreach (var Entry in listIds)
|
||||
foreach (var Entry in ids)
|
||||
{
|
||||
if (Entry.lastSeenByAgent != null && Entry.lastSeenByAgent >= AgentLimit)
|
||||
{
|
||||
@@ -5237,7 +5275,7 @@ namespace C4IT.DataHistoryProvider
|
||||
if (Connectors.TryGetValue(tableConfig.ParentCluster.Origin, out var C))
|
||||
{
|
||||
var IdValues = await C.GetIds(Identity, tableConfig.ParentCluster.InformationClass, requestInfo, LogDeep + 1);
|
||||
if (IdValues != null && tableConfig.KeyColumns.Count == IdValues.Count)
|
||||
if (IdValues != null && tableConfig.KeyColumns.Count == IdValues.Count)
|
||||
{
|
||||
var Filters = new Dictionary<string, object>();
|
||||
for (int i = 0; i < IdValues.Count; i++)
|
||||
@@ -5357,22 +5395,16 @@ namespace C4IT.DataHistoryProvider
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<cF4sdConnectorIds> getConnectorIds(enumFasdInformationClass infoClass, cF4sdIdentityEntry Identity, CancellationToken Token, cF4sdWebRequestInfo requestInfo, int LogDeep, bool WithLocalAccounts = false)
|
||||
private async Task<cF4sdConnectorIds> getConnectorIdsFromDb(enumFasdInformationClass infoClass, cF4sdIdentityEntry Identity, CancellationToken Token, cF4sdWebRequestInfo requestInfo, int LogDeep, bool WithLocalAccounts = false)
|
||||
{
|
||||
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;
|
||||
|
||||
int apiError = 0;
|
||||
|
||||
try
|
||||
{
|
||||
if (infoClass == enumFasdInformationClass.Ticket)
|
||||
return new cF4sdConnectorIds() { Id = Identity.Id, infoClass = enumFasdInformationClass.Ticket };
|
||||
if (infoClass == enumFasdInformationClass.VirtualSession)
|
||||
return new cF4sdConnectorIds() { Id = Identity.Id, infoClass = enumFasdInformationClass.VirtualSession };
|
||||
if (infoClass == enumFasdInformationClass.MobileDevice)
|
||||
return new cF4sdConnectorIds() { Id = Identity.Id, infoClass = enumFasdInformationClass.MobileDevice };
|
||||
|
||||
int apiError = 0;
|
||||
|
||||
if (!DataHistorySqlHelper.GetWellKnownSqlStatement($"GetConnectorIdsFrom{infoClass}Id", out var Query))
|
||||
return null;
|
||||
@@ -5516,6 +5548,66 @@ namespace C4IT.DataHistoryProvider
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
private async Task<cF4sdConnectorIds> getConnectorIds(enumFasdInformationClass infoClass, cF4sdIdentityEntry Identity, CancellationToken Token, cF4sdWebRequestInfo requestInfo, int LogDeep, bool WithLocalAccounts = false)
|
||||
{
|
||||
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 (infoClass == enumFasdInformationClass.Ticket)
|
||||
return new cF4sdConnectorIds() { Id = Identity.Id, infoClass = enumFasdInformationClass.Ticket };
|
||||
if (infoClass == enumFasdInformationClass.VirtualSession)
|
||||
return new cF4sdConnectorIds() { Id = Identity.Id, infoClass = enumFasdInformationClass.VirtualSession };
|
||||
if (infoClass == enumFasdInformationClass.MobileDevice)
|
||||
return new cF4sdConnectorIds() { Id = Identity.Id, infoClass = enumFasdInformationClass.MobileDevice };
|
||||
|
||||
var lstTasks = new List<Task>();
|
||||
|
||||
var _mainTask = getConnectorIdsFromDb(infoClass, Identity, Token, requestInfo, LogDeep + 1, WithLocalAccounts);
|
||||
lstTasks.Add(_mainTask);
|
||||
|
||||
var _needForeignUserInfo = false;
|
||||
if (infoClass == enumFasdInformationClass.User)
|
||||
foreach (var module in this.Connectors.Values)
|
||||
_needForeignUserInfo |= module.UseForeignUserIds();
|
||||
|
||||
Task<cForeignUserInfo> _userInfoTask = null;
|
||||
if (_needForeignUserInfo)
|
||||
{
|
||||
_userInfoTask = GetForeignUserInfoAsync(Identity.Id, Token);
|
||||
lstTasks.Add(_userInfoTask);
|
||||
}
|
||||
|
||||
|
||||
await Task.WhenAll(lstTasks);
|
||||
|
||||
var _result = _mainTask.Result;
|
||||
|
||||
if (_result == null)
|
||||
return null;
|
||||
|
||||
if (_needForeignUserInfo)
|
||||
_result.ForeignUserInfo = _userInfoTask?.Result;
|
||||
|
||||
return _result;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
@@ -6431,12 +6523,6 @@ namespace C4IT.DataHistoryProvider
|
||||
return true;
|
||||
}
|
||||
|
||||
public override async Task<List<object>> GetIds(cF4sdConnectorIds IdEntry, enumFasdInformationClass InfoClass, cF4sdWebRequestInfo requestInfo, int LogDeep)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return new List<object>() { IdEntry.Id };
|
||||
}
|
||||
|
||||
public static string getStingList(List<string> L)
|
||||
{
|
||||
if (L == null || L.Count == 0)
|
||||
@@ -6495,7 +6581,7 @@ namespace C4IT.DataHistoryProvider
|
||||
return null;
|
||||
}
|
||||
|
||||
public cCollectorStatusInfo GetCollectorStatus(cF4sdWebRequestInfo requestInfo)
|
||||
public cCollectorStatusInfo CheckCollectorStatus(cF4sdWebRequestInfo requestInfo)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
@@ -6598,11 +6684,100 @@ namespace C4IT.DataHistoryProvider
|
||||
|
||||
public HashSet<enumFasdInformationClass> GetSupportedInformationClasses() => new HashSet<enumFasdInformationClass>() { enumFasdInformationClass.User, enumFasdInformationClass.Computer };
|
||||
|
||||
public async Task<cF4sdStagedSearchResultRelations> GetRelationsAsync(IEnumerable<cF4sdIdentityEntry> ids, enumFasdInformationClass informationClass, int age, CancellationToken token = default)
|
||||
public async Task<cF4sdStagedSearchResultRelations> GetRelationsAsync(IEnumerable<cF4sdConnectorIds> ids, enumFasdInformationClass informationClass, int age, CancellationToken token = default)
|
||||
{
|
||||
List<cF4sdApiSearchResultRelation> usageRelations = await GetUsageFromOnlyAgentData(informationClass, ids.Select(id => id.Id).ToList(), age, token, null, 1);
|
||||
List<cF4sdApiSearchResultRelation> usageRelations = await GetUsageFromOnlyAgentData(ids, informationClass, age, token, null, 1);
|
||||
return new cF4sdStagedSearchResultRelations() { Relations = usageRelations };
|
||||
}
|
||||
|
||||
public void RegisterTokenValidator(cF4SDTokenRegistration.enumTokenType tokenType, cDataHistoryCollectorModule module)
|
||||
{
|
||||
_tokenValidators[tokenType] = module;
|
||||
}
|
||||
|
||||
public async override Task<int> ValidateTokenInfo(cDataHistoryCollectorTokenCache.cTokenInfo tokenInfo)
|
||||
{
|
||||
if (_tokenValidators.TryGetValue(tokenInfo.type, out var module))
|
||||
return await module.ValidateTokenInfo(tokenInfo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public class cForeignUserInfoEntry
|
||||
{
|
||||
public Guid MainID { get; set; }
|
||||
public enumDataHistoryOrigin Origin { get; set; }
|
||||
public string InstanceID { get; set; }
|
||||
public string ForeignID { get; set; }
|
||||
}
|
||||
|
||||
public class cForeignUserInfo : Dictionary<enumDataHistoryOrigin, List<cForeignUserInfoEntry>> { }
|
||||
|
||||
public async Task<cForeignUserInfo> GetForeignUserInfoAsync(Guid MainID, CancellationToken token)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
try
|
||||
{
|
||||
if (!DataHistorySqlHelper.GetWellKnownSqlStatement("GetForeignUserInfo", out var QueryGetUser))
|
||||
return null;
|
||||
|
||||
using (var Conn = new cDbConnection(Collector.mainDbConnection))
|
||||
{
|
||||
if (!Conn.IsOpen)
|
||||
{
|
||||
LogEntry($"Could not open main sql database '{Collector.mainDbConnection.Database}', aborting scan...'", LogLevels.Error);
|
||||
return null;
|
||||
}
|
||||
|
||||
var Params = new Dictionary<string, object>() { { "@ID", MainID } };
|
||||
|
||||
using (var Reader = await DataHistorySqlHelper.GetDataReaderAsync(Conn, QueryGetUser, Params, token))
|
||||
{
|
||||
if (Reader != null)
|
||||
if (Reader.HasRows)
|
||||
{
|
||||
var _retVal = new cForeignUserInfo();
|
||||
while (await Reader.ReadAsync(token))
|
||||
{
|
||||
try
|
||||
{
|
||||
var Entry = new cForeignUserInfoEntry();
|
||||
Entry.MainID = Reader.GetGuid(0);
|
||||
Entry.Origin = (enumDataHistoryOrigin)Reader.GetInt32(1);
|
||||
Entry.InstanceID = Reader.GetString(2);
|
||||
Entry.ForeignID = Reader.GetString(3);
|
||||
|
||||
if (!_retVal.TryGetValue(Entry.Origin, out var _lst))
|
||||
{
|
||||
_lst = new List<cForeignUserInfoEntry>();
|
||||
_retVal.Add(Entry.Origin, _lst);
|
||||
}
|
||||
_lst.Add(Entry);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
cLogManager.DefaultLogger.LogException(E);
|
||||
}
|
||||
}
|
||||
|
||||
return _retVal;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class cScanTimeInfo
|
||||
@@ -6736,7 +6911,13 @@ namespace C4IT.DataHistoryProvider
|
||||
public Guid tenantId { get; set; }
|
||||
public Guid intuneId { get; set; }
|
||||
public Guid azureDeviceId { get; set; }
|
||||
|
||||
public cDataHistoryCollector.cForeignUserInfo ForeignUserInfo = null;
|
||||
|
||||
[Obsolete]
|
||||
public string citrixTenantId { get; set; }
|
||||
|
||||
[Obsolete]
|
||||
public int? citrixUserId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
using System;
|
||||
using ActiveDs;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.HTTP;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MsGraph;
|
||||
using C4IT_DataHistoryProvider_Base.DataSources;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.DirectoryServices.ActiveDirectory;
|
||||
using System.DirectoryServices.Protocols;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
@@ -9,16 +17,8 @@ using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ActiveDs;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.HTTP;
|
||||
using C4IT.Logging;
|
||||
using C4IT.MsGraph;
|
||||
using C4IT_DataHistoryProvider_Base.DataSources;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
@@ -50,6 +50,7 @@ namespace C4IT.DataHistoryProvider
|
||||
public const string constMsGraphDeviceBitlockerRecoveryKey = "informationProtection/bitlocker/recoveryKeys?$filter=deviceId eq '{0}'";
|
||||
public const string constMsGraphDeviceBitlockerRecoveryKeyDetails = "informationProtection/bitlocker/recoveryKeys/{0}?$select=key";
|
||||
public const string constMsGraphDeviceLAPS = "directory/deviceLocalCredentials/{0}?$select=credentials,deviceName";
|
||||
public const string constMsGraphTAP = "users/{0}/authentication/temporaryAccessPassMethods";
|
||||
public const int constMsGraphManagedDevicePaging = 100;
|
||||
public const string constTableNameIntuneDeviceDetails = "intune-deviceInfo";
|
||||
public const string constTableNameIntuneUserDeviceCount = "intune-userDeviceCount";
|
||||
@@ -93,6 +94,7 @@ namespace C4IT.DataHistoryProvider
|
||||
private DateTime LastDomainsUpdate = DateTime.MinValue;
|
||||
private bool DomainsUpdateRunning = false;
|
||||
private Dictionary<Guid, cMsGraphBase> tenantGraphCache = new Dictionary<Guid, cMsGraphBase>();
|
||||
public bool WinAuthenticationGropsResolved { get; private set; }
|
||||
static cDataHistoryCollectorActiveDirectory()
|
||||
{
|
||||
BaseDateTime = new DateTime(1601, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
@@ -2053,13 +2055,17 @@ namespace C4IT.DataHistoryProvider
|
||||
|
||||
return true;
|
||||
}
|
||||
public async Task<cF4sdStagedSearchResultRelations> GetRelationsAsync(IEnumerable<cF4sdIdentityEntry> ids, enumFasdInformationClass informationClass, int age, CancellationToken token = default)
|
||||
|
||||
public async Task<cF4sdStagedSearchResultRelations> GetRelationsAsync(IEnumerable<cF4sdConnectorIds> ids, enumFasdInformationClass informationClass, int age, CancellationToken token = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
/*
|
||||
List<cF4sdConnectorIds> Ids = await _collector.getConnectorIdList(ids.ToList(), token, null, 0);
|
||||
List<cF4sdApiSearchResultRelation> relations = await GetUserMobileDevicesAsync(Ids, token, null);
|
||||
return new cF4sdStagedSearchResultRelations() { Relations = relations };
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -2082,14 +2088,16 @@ namespace C4IT.DataHistoryProvider
|
||||
var bMobileDeviceExists = Tables.Exists(v => v.Name == constTableNameIntuneMobileDeviceDetails && v.ParentCluster?.Origin == enumDataHistoryOrigin.Intune);
|
||||
|
||||
|
||||
if (!Identities.TryGetValue(enumFasdInformationClass.Computer, out var computer) && computer?.intuneId != Guid.Empty)
|
||||
if (!Identities.TryGetValue(enumFasdInformationClass.User, out var user) && user?.intuneId != Guid.Empty && user?.tenantId != Guid.Empty)
|
||||
bUserDeviceExists = false;
|
||||
|
||||
if (!Identities.TryGetValue(enumFasdInformationClass.Computer, out var computer) && computer?.intuneId != Guid.Empty && user?.tenantId != Guid.Empty)
|
||||
bDeviceExists = false;
|
||||
|
||||
if(!Identities.TryGetValue(enumFasdInformationClass.MobileDevice, out var mobile) && mobile?.Id != Guid.Empty)
|
||||
if (!Identities.TryGetValue(enumFasdInformationClass.MobileDevice, out var mobile) && mobile?.Id != Guid.Empty)
|
||||
bMobileDeviceExists = false;
|
||||
|
||||
if(!Identities.TryGetValue(enumFasdInformationClass.User, out var user) && user?.intuneId != Guid.Empty)
|
||||
bUserDeviceExists = false;
|
||||
|
||||
|
||||
|
||||
if (!(bDeviceExists || bMobileDeviceExists || bUserDeviceExists))
|
||||
@@ -2111,8 +2119,8 @@ namespace C4IT.DataHistoryProvider
|
||||
|
||||
}
|
||||
else
|
||||
listTasks.Add(Task.Run<List<cF4SDHealthCardRawData.cHealthCardTable>>(async () => { return await GetIntuneDeviceTableAsync(computer.intuneId, computer.tenantId, requestInfo, LogDeep + 1, Token); }));
|
||||
|
||||
listTasks.Add(Task.Run<List<cF4SDHealthCardRawData.cHealthCardTable>>(async () => { return await GetIntuneDeviceTableAsync(computer.intuneId, user.tenantId, requestInfo, LogDeep + 1, Token); }));
|
||||
|
||||
if (bMobileDeviceExists)
|
||||
if (CacheId == null && !instantly)
|
||||
{
|
||||
@@ -2237,20 +2245,22 @@ namespace C4IT.DataHistoryProvider
|
||||
if (MsGraph == null)
|
||||
return null;
|
||||
|
||||
var retVal = new cF4SDHealthCardRawData.cHealthCardTable()
|
||||
{
|
||||
Name = constTableNameIntuneDeviceDetails,
|
||||
InformationClass = enumFasdInformationClass.Computer,
|
||||
Origin = enumDataHistoryOrigin.Intune,
|
||||
IsStatic = true,
|
||||
TableType = eDataHistoryTableType.Static
|
||||
};
|
||||
|
||||
var dicVals = new Dictionary<string, object>();
|
||||
|
||||
var res = await MsGraph.RequestAsync(strUrl, UseBeta: true, retryForbidden: false);
|
||||
if (res != null)
|
||||
{
|
||||
JObject deviceInfos = res.Result;
|
||||
var retVal = new cF4SDHealthCardRawData.cHealthCardTable()
|
||||
{
|
||||
Name = constTableNameIntuneDeviceDetails,
|
||||
InformationClass = enumFasdInformationClass.Computer,
|
||||
Origin = enumDataHistoryOrigin.Intune,
|
||||
IsStatic = true,
|
||||
TableType = eDataHistoryTableType.Static
|
||||
};
|
||||
|
||||
var dicVals = new Dictionary<string, object>();
|
||||
var vals = deviceInfos.Children();
|
||||
|
||||
if (cLogManager.DefaultLogger.IsDebug) LogEntry("SpecialDebug GetIntuneMainTableAsync #3");
|
||||
@@ -2290,6 +2300,16 @@ namespace C4IT.DataHistoryProvider
|
||||
else
|
||||
{
|
||||
LogEntry($"Could not get detailed device information from intune with id {IntuneId}. Device content is empty.", LogLevels.Warning);
|
||||
foreach (var colInfo in IntuneTableDetails.Columns.Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
var _col = new cF4SDHealthCardRawData.cHealthCardTableColumn(retVal) { ColumnName = colInfo.Name, Values = new List<object>(1) { } };
|
||||
retVal.Columns[colInfo.Name] = _col;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
return new List<cF4SDHealthCardRawData.cHealthCardTable>(1) { retVal };
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
@@ -2326,17 +2346,19 @@ namespace C4IT.DataHistoryProvider
|
||||
if (cLogManager.DefaultLogger.IsDebug) LogEntry("SpecialDebug GetIntuneUserDeviceCountTableAsync #3");
|
||||
var res = await MsGraph.RequestAsync(strUrl, UseBeta: false, retryForbidden: false);
|
||||
if (cLogManager.DefaultLogger.IsDebug) LogEntry("SpecialDebug GetIntuneUserDeviceCountTableAsync #4");
|
||||
|
||||
var retVal = new cF4SDHealthCardRawData.cHealthCardTable()
|
||||
{
|
||||
Name = constTableNameIntuneUserDeviceCount,
|
||||
InformationClass = enumFasdInformationClass.User,
|
||||
Origin = enumDataHistoryOrigin.Intune,
|
||||
IsStatic = true,
|
||||
TableType = eDataHistoryTableType.Static
|
||||
};
|
||||
|
||||
if (res != null)
|
||||
{
|
||||
JObject deviceInfos = res.Result;
|
||||
var retVal = new cF4SDHealthCardRawData.cHealthCardTable()
|
||||
{
|
||||
Name = constTableNameIntuneUserDeviceCount,
|
||||
InformationClass = enumFasdInformationClass.User,
|
||||
Origin = enumDataHistoryOrigin.Intune,
|
||||
IsStatic = true,
|
||||
TableType = eDataHistoryTableType.Static
|
||||
};
|
||||
|
||||
var vals = deviceInfos.Children();
|
||||
|
||||
@@ -2405,6 +2427,16 @@ namespace C4IT.DataHistoryProvider
|
||||
else
|
||||
{
|
||||
LogEntry($"Could not get detailed DeviceCount information from intune with id {Userid}. DeviceCount content is empty.", LogLevels.Warning);
|
||||
foreach (var colInfo in IntuneTableDetails.Columns.Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
var _col = new cF4SDHealthCardRawData.cHealthCardTableColumn(retVal) { ColumnName = colInfo.Name, Values = new List<object>(1) { } };
|
||||
retVal.Columns[colInfo.Name] = _col;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
return new List<cF4SDHealthCardRawData.cHealthCardTable>(1) { retVal };
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
@@ -2437,26 +2469,25 @@ namespace C4IT.DataHistoryProvider
|
||||
var MsGraph = await GetGraphForTenantAsync(TenantId, true);
|
||||
if (MsGraph == null)
|
||||
return null;
|
||||
|
||||
var retValList = new List<cF4SDHealthCardRawData.cHealthCardDetailsTable>();
|
||||
var res = await MsGraph.RequestAsync(strUrl, UseBeta: false, retryForbidden: false);
|
||||
|
||||
var retVal = new cF4SDHealthCardRawData.cHealthCardDetailsTable()
|
||||
{
|
||||
Name = constTableNameIntuneUserDeviceCountDetail,
|
||||
Columns = IntuneTableDetails.Columns.Values.Select(v => v.Name).ToList(),
|
||||
Values = new Dictionary<int, List<object[]>>()
|
||||
|
||||
};
|
||||
|
||||
|
||||
if (res != null)
|
||||
{
|
||||
JObject deviceInfos = res.Result;
|
||||
|
||||
|
||||
var retValList = new List<cF4SDHealthCardRawData.cHealthCardDetailsTable>();
|
||||
|
||||
|
||||
var vals = deviceInfos["value"] as JArray;
|
||||
if (vals != null)
|
||||
{
|
||||
var retVal = new cF4SDHealthCardRawData.cHealthCardDetailsTable()
|
||||
{
|
||||
Name = constTableNameIntuneUserDeviceCountDetail,
|
||||
Columns = IntuneTableDetails.Columns.Values.Select(v => v.Name).ToList(),
|
||||
Values = new Dictionary<int, List<object[]>>()
|
||||
|
||||
};
|
||||
|
||||
|
||||
int index = 0;
|
||||
@@ -2488,6 +2519,8 @@ namespace C4IT.DataHistoryProvider
|
||||
else
|
||||
{
|
||||
LogEntry($"Could not get detailed DeviceCount information from intune with id {Userid}. DeviceCount content is empty.", LogLevels.Warning);
|
||||
retValList.Add(retVal);
|
||||
return retValList;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -2512,25 +2545,25 @@ namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
string userIds = string.Join(",", UserId.Where(u => !string.IsNullOrWhiteSpace(u?.intuneId.ToString())).Select(u => u.intuneId));
|
||||
|
||||
var tenantId = UserId?.FirstOrDefault(u => u?.tenantId != Guid.Empty)?.tenantId ?? Guid.Empty;
|
||||
|
||||
var tenantId = UserId?.FirstOrDefault(u => u?.tenantId != Guid.Empty)?.tenantId ?? Guid.Empty;
|
||||
|
||||
var strUrl = string.Format(constMsGraphManagedMobileDeviceList, userIds);
|
||||
|
||||
var MsGraph = await GetGraphForTenantAsync(tenantId, true);
|
||||
if (MsGraph == null)
|
||||
return null;
|
||||
|
||||
|
||||
var Result = await MsGraph.RequestListAsync(strUrl, UseBeta: false, retryForbidden: false);
|
||||
if (Result != null == Result.Count > 0)
|
||||
{
|
||||
var searchResult = new List<cF4sdApiSearchResultRelation>(Result.Count);
|
||||
|
||||
|
||||
foreach (var Entry in Result)
|
||||
{
|
||||
var endDate = DateTime.MinValue;
|
||||
if (!DateTime.TryParse(Entry.Result.lastSyncDateTime?.ToString(), out endDate))
|
||||
endDate = DateTime.UtcNow;
|
||||
|
||||
|
||||
var searchInfo = new cF4sdApiSearchResultRelation()
|
||||
{
|
||||
Type = enumF4sdSearchResultClass.MobileDevice,
|
||||
@@ -2677,6 +2710,9 @@ namespace C4IT.DataHistoryProvider
|
||||
case "GetLAPS":
|
||||
result = await GetLAPS(jsonRequest.Identities, requestInfo, CancellationToken.None);
|
||||
break;
|
||||
case "GetTAP":
|
||||
result = await GetTAP(jsonRequest.Identities, requestInfo, CancellationToken.None);
|
||||
break;
|
||||
case "GetBitlockerKeyTest":
|
||||
result = await GetBitlockerKeyTest(jsonRequest.Identities, requestInfo, CancellationToken.None);
|
||||
break;
|
||||
@@ -2688,7 +2724,7 @@ namespace C4IT.DataHistoryProvider
|
||||
}
|
||||
|
||||
public override async Task<List<string>> GetQuickActionList()
|
||||
|
||||
|
||||
{
|
||||
var HasIntuneConfig = (Collector.InfrastructureConfig.AzureTenants?.Values.Any(t => t.ScanIntuneDevices) == true);
|
||||
if (HasIntuneConfig)
|
||||
@@ -2699,8 +2735,9 @@ namespace C4IT.DataHistoryProvider
|
||||
"Get Managed Apps",
|
||||
"Get BitlockerKey",
|
||||
"Get LAPS",
|
||||
"Get TAP",
|
||||
"GetLapsKeyTest",
|
||||
};
|
||||
};
|
||||
return await Task.FromResult(quickactions);
|
||||
}
|
||||
var result = new List<string>();
|
||||
@@ -2827,6 +2864,40 @@ namespace C4IT.DataHistoryProvider
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<dynamic> GetTAP(List<cF4sdIdentityEntry> identities, cF4sdWebRequestInfo requestInfo, CancellationToken Token)
|
||||
{
|
||||
var Ids = await Collector.getConntectorIds(identities, Token, requestInfo, 1);
|
||||
if (!Ids.TryGetValue(enumFasdInformationClass.User, out var _ids))
|
||||
return null;
|
||||
|
||||
var strUrl = string.Format(constMsGraphTAP, _ids.intuneId);
|
||||
|
||||
|
||||
var MsGraph = await GetGraphForTenantAsync(_ids.tenantId, true);
|
||||
if (MsGraph == null)
|
||||
return null;
|
||||
|
||||
var IntuneConfig = Collector?.GetGlobalConfig()?.IntuneConfiguration;
|
||||
|
||||
var body = new Dictionary<string, object>()
|
||||
{
|
||||
{ "isUsableOnce", IntuneConfig?.TAPIsUsableOnce ?? cF4sdIntuneConfig.DefaultTAPIsUsableOnce},
|
||||
{ "lifetimeInMinutes", IntuneConfig?.TAPLifeTimeInMinutes ?? cF4sdIntuneConfig.DefaultTAPLifeTimeInMinutes}
|
||||
};
|
||||
|
||||
var Result = await MsGraph.RequestAsync(strUrl, UseBeta: false, eHttpMethod.post, JsonData: body, retryForbidden: false);
|
||||
if (Result != null)
|
||||
{
|
||||
var _resultJson = Result.Result as JObject;
|
||||
if (_resultJson != null)
|
||||
{
|
||||
return _resultJson;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<dynamic> GetManagedApps(List<cF4sdIdentityEntry> identities, cF4sdWebRequestInfo requestInfo, CancellationToken Token)
|
||||
{
|
||||
var Ids = await Collector.getConntectorIds(identities, Token, requestInfo, 1);
|
||||
@@ -3131,6 +3202,9 @@ namespace C4IT.DataHistoryProvider
|
||||
if (Collector.InfrastructureConfig.AzureTenants != null)
|
||||
await DoAzureScanAsync(requestInfo, LogDeep + 1, Token);
|
||||
|
||||
if (Collector.InfrastructureConfig.AzureTenants?.Values.Any(t => t.ScanIntuneDevices) == true)
|
||||
await DoScanIntuneAsync(requestInfo, LogDeep + 1, Token);
|
||||
|
||||
await Collector.SetLastScanTime("AdScan-all", DateTime.UtcNow, requestInfo, LogDeep + 1, Token);
|
||||
|
||||
return true;
|
||||
@@ -3443,7 +3517,7 @@ namespace C4IT.DataHistoryProvider
|
||||
if (Table?.ParentCluster?.Origin == enumDataHistoryOrigin.Intune)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private object ConvertToF4sdType(object objVal, enumFasdValueType ValueType)
|
||||
{
|
||||
@@ -3691,68 +3765,26 @@ namespace C4IT.DataHistoryProvider
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
if (Collector?.InfrastructureConfig?.Authorisation?.MembershipGroups?.GroupsAd == null)
|
||||
if (Collector?.InfrastructureConfig?.Authorisation?.MembershipGroups?.GroupsAd is null)
|
||||
return;
|
||||
|
||||
LogEntry("Resolving AD groups SIDs...");
|
||||
var _lstDomains = Collector.InfrastructureConfig.Authorisation.MembershipGroups.GroupsAd;
|
||||
var domains = Collector.InfrastructureConfig.Authorisation.MembershipGroups.GroupsAd.Values;
|
||||
LogEntry("Resolving AD groups SIDs finished");
|
||||
foreach (var _domain in _lstDomains.Values)
|
||||
|
||||
bool hasResolved = true;
|
||||
|
||||
foreach (cF4SDMembershipGroupsAd domain in domains)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogEntry($"Start processing domain");
|
||||
LogEntry($"Processing domain {_domain?.Domain?.FQDN}");
|
||||
|
||||
PrincipalContext PC;
|
||||
if (_domain.Domain.Credential == null)
|
||||
PC = new PrincipalContext(ContextType.Domain, _domain.Domain.FQDN);
|
||||
else
|
||||
PC = new PrincipalContext(ContextType.Domain, _domain.Domain.FQDN, _domain.Domain.Credential.User, _domain.Domain.Credential.NwCredential.Password);
|
||||
|
||||
LogEntry($"Principal context successful created");
|
||||
|
||||
foreach (var _group in _domain.Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogEntry($"Start processing group.");
|
||||
LogEntry($"Group: {_group.Name}.");
|
||||
var GI = GroupPrincipal.FindByIdentity(PC, IdentityType.SamAccountName, _group.Account);
|
||||
LogEntry($"Group principal found");
|
||||
LogEntry($"GI.SID: {GI.Sid.ToString()}");
|
||||
if (GI != null)
|
||||
if (GI.Sid != null)
|
||||
{
|
||||
_group.SID = GI.Sid.ToString();
|
||||
LogEntry($"AD group '{_group.Account}' in domain '{_domain.Domain.FQDN}' resolved. SID = {_group.SID}");
|
||||
}
|
||||
if (_group.SID == null)
|
||||
LogEntry($"Could not resolve AD group '{_group.Account}' in domain '{_domain.Domain.FQDN}'", LogLevels.Warning);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogEntry($"End processing group.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogEntry($"End processing domain");
|
||||
}
|
||||
hasResolved = hasResolved && TryProcessDomain(domain);
|
||||
}
|
||||
|
||||
WinAuthenticationGropsResolved = hasResolved;
|
||||
}
|
||||
catch (Exception E)
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(E);
|
||||
LogException(ex);
|
||||
WinAuthenticationGropsResolved = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -3760,6 +3792,80 @@ namespace C4IT.DataHistoryProvider
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryProcessDomain(cF4SDMembershipGroupsAd domain)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool hasProcessed = true;
|
||||
if (domain?.Domain is null)
|
||||
return hasProcessed;
|
||||
|
||||
LogEntry($"Start processing domain");
|
||||
string domainName = domain.Domain.FQDN;
|
||||
LogEntry($"Processing domain {domainName}");
|
||||
|
||||
PrincipalContext principalContext;
|
||||
if (domain.Domain.Credential == null)
|
||||
principalContext = new PrincipalContext(ContextType.Domain, domainName);
|
||||
else
|
||||
principalContext = new PrincipalContext(ContextType.Domain, domainName, domain.Domain.Credential.User, domain.Domain.Credential.NwCredential.Password);
|
||||
|
||||
LogEntry($"Principal context successful created");
|
||||
|
||||
foreach (var group in domain.Values)
|
||||
{
|
||||
hasProcessed = hasProcessed && TryProcessMembershipGroup(group, principalContext, domainName);
|
||||
}
|
||||
|
||||
return hasProcessed;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogEntry($"End processing domain");
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryProcessMembershipGroup(cF4SDMembershipGroupAd group, PrincipalContext principalContext, string domainName)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (group is null)
|
||||
return true;
|
||||
|
||||
LogEntry($"Start processing group.");
|
||||
LogEntry($"Group: {group.Name}.");
|
||||
var groupIdentity = GroupPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, group.Account);
|
||||
LogEntry($"Group principal found");
|
||||
LogEntry($"GI.SID: {groupIdentity.Sid}");
|
||||
|
||||
if (groupIdentity?.Sid != null)
|
||||
{
|
||||
group.SID = groupIdentity.Sid.ToString();
|
||||
LogEntry($"AD group '{group.Account}' in domain '{domainName}' resolved. SID = {group.SID}");
|
||||
}
|
||||
|
||||
if (group.SID == null)
|
||||
LogEntry($"Could not resolve AD group '{group.Account}' in domain '{domainName}'", LogLevels.Warning);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogEntry($"End processing group.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static public Guid ConvertAzureSidToGuid(string sid)
|
||||
{
|
||||
if (!sid.StartsWith("S-1-12-1-"))
|
||||
|
||||
@@ -592,7 +592,6 @@ namespace C4IT.DataHistoryProvider
|
||||
// check if wwe have a local account and process the localAccountAssignments
|
||||
if (string.IsNullOrEmpty(domain) && localAccountAssignments != null)
|
||||
{
|
||||
|
||||
var AdId = Guid.Empty;
|
||||
foreach (var localAccountAssignment in localAccountAssignments)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,16 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.Security;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT.Security;
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using static C4IT.DataHistoryProvider.cDataHistoryCollectorTokenCache;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
@@ -29,6 +34,7 @@ namespace C4IT.DataHistoryProvider
|
||||
public string secret;
|
||||
public DateTime validUntil;
|
||||
public DateTime renewUntil;
|
||||
public string IdRemote;
|
||||
|
||||
public bool IsValid()
|
||||
{
|
||||
@@ -36,6 +42,7 @@ namespace C4IT.DataHistoryProvider
|
||||
return false;
|
||||
if (validUntil < DateTime.UtcNow + TimeSpan.FromMinutes(cDataHistoryCollector.constMinutesUntilTokenIsInvalid))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -52,7 +59,8 @@ namespace C4IT.DataHistoryProvider
|
||||
name2 = name2,
|
||||
secret = _sec,
|
||||
validUntil = validUntil,
|
||||
renewUntil = renewUntil
|
||||
renewUntil = renewUntil,
|
||||
IdRemote = IdRemote
|
||||
};
|
||||
|
||||
return _ret;
|
||||
@@ -132,6 +140,9 @@ namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
dicToken.Clear();
|
||||
|
||||
var _toDelete = new List<cTokenInfo>();
|
||||
var _toUpdate = new List<cTokenInfo>();
|
||||
|
||||
using (var _reader = await DataHistorySqlHelper.GetDataReaderAsync(DbConn, Query, null, Token))
|
||||
{
|
||||
if (_reader != null)
|
||||
@@ -139,7 +150,6 @@ namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
if (_reader.HasRows)
|
||||
{
|
||||
var _toDelete = new List<cTokenInfo>();
|
||||
while (await _reader.ReadAsync())
|
||||
{
|
||||
try
|
||||
@@ -156,13 +166,22 @@ namespace C4IT.DataHistoryProvider
|
||||
_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);
|
||||
_entry.IdRemote = _reader.IsDBNull(7) ? null : _reader.GetString(7);
|
||||
|
||||
int valid = -1;
|
||||
if (_entry.IsValid())
|
||||
valid = await Collector.ValidateTokenInfo(_entry);
|
||||
|
||||
if (valid < 0)
|
||||
_toDelete.Add(_entry);
|
||||
else
|
||||
{
|
||||
if (!privInsert(_entry, false))
|
||||
_toDelete.Add(_entry);
|
||||
|
||||
if (valid > 0)
|
||||
_toUpdate.Add(_entry);
|
||||
}
|
||||
else
|
||||
_toDelete.Add(_entry);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
@@ -178,9 +197,18 @@ namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
cLogManager.DefaultLogger.LogException(E);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (_toUpdate.Count > 0)
|
||||
{
|
||||
foreach (var entry in _toUpdate)
|
||||
{
|
||||
var _secEnc = entry.secret;
|
||||
if (!HasTokenTypeLongLifetime(entry.type))
|
||||
_secEnc = cSecurePassword.Instance.Encode(entry.secret);
|
||||
await SaveToDbAsync(entry, _secEnc, requestInfo, LogDeep + 1, Token);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
@@ -204,6 +232,54 @@ namespace C4IT.DataHistoryProvider
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveToDbAsync(cTokenInfo _tokenInfo, string secEnc, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken Token)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var sqlerror = 0;
|
||||
var sqlStartTime = DateTime.UtcNow;
|
||||
|
||||
if (!DataHistorySqlHelper.GetWellKnownSqlStatement("InsertOrUpdateExternalToken", out var Query))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
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 },
|
||||
{ "IdRemote", _tokenInfo.IdRemote },
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
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); }
|
||||
@@ -229,50 +305,23 @@ namespace C4IT.DataHistoryProvider
|
||||
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
|
||||
{
|
||||
await SaveToDbAsync(_tokenInfo, _secEnc, requestInfo, LogDeep + 1, Token);
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -128,6 +128,8 @@ namespace C4IT.DataHistoryProvider
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "AD-ComputerInfo", "ad-computer", "<Table-Column Name=\"domainDns\" SourceType =\"Static\" Type=\"string\" Cardinal=\"128\"/>", "account");
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "AD-ComputerInfo", "ad-computer", "<Table-Column Name=\"domainNB\" SourceType =\"Static\" Type=\"string\" Cardinal=\"16\"/>", "account");
|
||||
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "Agent-DeviceInfo", "agnt-computer", "<Table-Column Name=\"IsPhoenixInstalled\" SourceName=\"Phoenix Installed\" Type=\"boolean\" Aggregation=\"latestValue\"/>");
|
||||
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "Agent-DeviceInfo", "agnt-computer-event-numerical", "<Table-Column Name=\"DeviceActivity\" SourceName=\"Device Activity\" Type=\"bigint\" Aggregation=\"sum\"/>");
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "Agent-DeviceInfo", "agnt-computer-event-numerical", "<Table-Column Name=\"UserActivity\" SourceName=\"User Activity\" Type=\"bigint\" Aggregation=\"sum\"/>");
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "Agent-DeviceInfo", "agnt-computer-event-numerical", "<Table-Column Name=\"ProcessorTaskManager\" SourceName=\"Task Manager % Score\" Type=\"float\" Aggregation=\"average\" LateDelivery=\"true\" />");
|
||||
@@ -248,6 +250,11 @@ namespace C4IT.DataHistoryProvider
|
||||
, "<Table Name=\"citrix-session-metrics\" Type=\"History\" Key=\"Id\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"CollectedDate\" Type=\"datetime\"/><Table-Column Name=\"IcaRttMS\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"IcaLatency\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"ClientL7Latency\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"ServerL7Latency\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"ConnectionState\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"InputBandwidthUsed\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"OutputBandwidthUsed\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"OutputBandwidthAvailable\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"Fps\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"InputFps\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"OutputFps\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"WanLatency\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"DcLatency\" Type=\"int\" Aggregation=\"average\"/></Table-Columns></Table>"
|
||||
);
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "DataCluster[@Name='citrixMetrics']"
|
||||
, "Table[@Name='citrix-connectionState-metrics']"
|
||||
, "<Table Name=\"citrix-connectionState-metrics\" Type=\"History\" Key=\"Id\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\" /><Table-Column Name=\"StartDate\" Type=\"datetime\" /><Table-Column Name=\"ConnectionState\" Type=\"int\" /><Table-Column Name=\"ConnectionCount\" Type=\"int\" /></Table-Columns></Table>");
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "DataCluster[@Name='citrixMetrics']"
|
||||
, "Table[@Name='citrix-session-details-icaRttMS']"
|
||||
@@ -277,6 +284,10 @@ namespace C4IT.DataHistoryProvider
|
||||
, "Table[@Name='citrix-session-details-inputBandwidthUsed']"
|
||||
, "<Table Name=\"citrix-session-details-inputBandwidthUsed\" Type=\"Events\" Key=\"Id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"Value\" SourceName=\"InputBandwidthUsed\" Type=\"int\"/><Table-Column Name=\"time\" SourceName=\"CollectedDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "DataCluster[@Name='citrixMetrics']"
|
||||
, "Table[@Name='citrix-session-details-outputBandwidthUsed']"
|
||||
, "<Table Name=\"citrix-session-details-outputBandwidthUsed\" Type=\"Events\" Key=\"Id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\" /><Table-Column Name=\"Value\" SourceName=\"OutputBandwidthUsed\" Type=\"int\" /><Table-Column Name=\"time\" SourceName=\"CollectedDate\" Type=\"datetime\" /></Table-Columns></Table>");
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "DataCluster[@Name='citrixMetrics']"
|
||||
@@ -317,8 +328,7 @@ namespace C4IT.DataHistoryProvider
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "DataCluster[@Name='citrixMetrics']"
|
||||
, "Table[@Name='citrix-session-machine']"
|
||||
, "<Table Name=\"citrix-session-machine\" Type=\"Static\" Key=\"Id\"><Table-Columns><Table-Column Name=\"Id\" Type=\"guid\"/><Table-Column Name=\"Name\" Type=\"string\"/><Table-Column Name=\"CatalogName\" SourceName=\"Catalog\" SourceJsonField=\"Name\" Type=\"string\" Default=\"0\"/><Table-Column Name=\"AllocationType\" SourceName=\"Catalog\" SourceJsonField=\"AllocationType\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"DesktopGroupName\" SourceName=\"DesktopGroup\" SourceJsonField=\"Name\" Type=\"string\"/><Table-Column Name=\"DnsName\" Type=\"string\"/><Table-Column Name=\"HostedMachine\" SourceName=\"HostedMachineId\" Type=\"string\"/><Table-Column Name=\"IPAddress\" Type=\"string\"/><Table-Column Name=\"WindowsConnectionSetting\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"CurrentRegistrationState\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"AgentVersion\" Type=\"string\"/><Table-Column Name=\"CurrentSessionCount\" Type=\"int\"/><Table-Column Name=\"OSType\" Type=\"string\"/><Table-Column Name=\"IsInMaintenanceMode\" Type=\"boolean\"/><Table-Column Name=\"Cpu\" SourceName=\"CurrentLoadIndex\" SourceJsonField=\"Cpu\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"Memory\" SourceName=\"CurrentLoadIndex\" SourceJsonField=\"Memory\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"Disk\" SourceName=\"CurrentLoadIndex\" SourceJsonField=\"Disk\" Type=\"int\" Default=\"0\"/></Table-Columns></Table>"
|
||||
);
|
||||
, "<Table Name=\"citrix-session-machine\" Type=\"Static\" Key=\"Id\"><Table-Columns><Table-Column Name=\"Id\" Type=\"guid\" /><Table-Column Name=\"Name\" Type=\"string\" /><Table-Column Name=\"CatalogName\" SourceName=\"Catalog\" SourceJsonField=\"Name\" Type=\"string\" Default=\"0\" /><Table-Column Name=\"AllocationType\" SourceName=\"Catalog\" SourceJsonField=\"AllocationType\" Type=\"int\" Default=\"0\" /><Table-Column Name=\"DesktopGroupName\" SourceName=\"DesktopGroup\" SourceJsonField=\"Name\" Type=\"string\" /><Table-Column Name=\"DnsName\" Type=\"string\" /><Table-Column Name=\"HostedMachine\" SourceName=\"HostedMachineId\" Type=\"string\" /><Table-Column Name=\"IPAddress\" Type=\"string\" /><Table-Column Name=\"WindowsConnectionSetting\" Type=\"int\" Default=\"0\" /><Table-Column Name=\"CurrentRegistrationState\" Type=\"int\" Default=\"0\" /><Table-Column Name=\"AgentVersion\" Type=\"string\" /><Table-Column Name=\"CurrentSessionCount\" Type=\"int\" /><Table-Column Name=\"OSType\" Type=\"string\" /><Table-Column Name=\"IsInMaintenanceMode\" Type=\"boolean\" /><Table-Column Name=\"Cpu\" SourceName=\"CurrentLoadIndex\" SourceJsonField=\"Cpu\" Type=\"int\" Default=\"0\" /><Table-Column Name=\"Memory\" SourceName=\"CurrentLoadIndex\" SourceJsonField=\"Memory\" Type=\"int\" Default=\"0\" /><Table-Column Name=\"Disk\" SourceName=\"CurrentLoadIndex\" SourceJsonField=\"Disk\" Type=\"int\" Default=\"0\" /></Table-Columns></Table>");
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "DataCluster[@Name='citrixMetrics']"
|
||||
@@ -378,19 +388,19 @@ namespace C4IT.DataHistoryProvider
|
||||
, "Table[@Name='M42Wpm-Ticket-Services']"
|
||||
);
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "DataCluster[@Name='M42Tickets']"
|
||||
, "Table[@Name='M42Wpm-Ticket-QuickCalls']"
|
||||
, "<Table Name=\"M42Wpm-Ticket-QuickCalls\" Type=\"Selection\" Key=\"id\"><Matrix42-DataQueryItems-Template EntityClassName=\"SPSQuickCallClassBase\" EntityTypeNames=\"SPSQuickCallType\" OrderBy=\"\" WhereExpression=\"Restricted = 0\" DataQueryName=\"C4IT - F4SD - Quick Calls\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Id\" Type=\"guid\"/><Table-Column Name=\"SysObjectId\" SourceName=\"Sys-ObjectId\" Type=\"guid\"/><Table-Column Name=\"SysName\" SourceName=\"Sys-Name\" Type=\"string\" Cardinal=\"50\"/><Table-Column Name=\"Name\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Subject\" Type=\"string\" Cardinal=\"1024\"/><Table-Column Name=\"Priority\" Type=\"string\" Cardinal=\"100\"/><Table-Column Name=\"Responsible\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"ResponsibleRole\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Category\" SourceName=\"Category_Value\" Type=\"guid\"/></Table-Columns></Table>"
|
||||
, "Table[@Name='M42Wpm-Ticket-Assets']"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "DataCluster[@Name='M42Tickets']"
|
||||
, "Table[@Name='M42Wpm-Ticket-QuickCalls']"
|
||||
, "<Table Name=\"M42Wpm-Ticket-QuickCalls\" Type=\"Selection\" Key=\"id\"><Matrix42-DataQueryItems-Template EntityClassName=\"SPSQuickCallClassBase\" EntityTypeNames=\"SPSQuickCallType\" OrderBy=\"\" WhereExpression=\"Restricted = 0\" DataQueryName=\"C4IT - F4SD - Quick Calls\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Id\" Type=\"guid\"/><Table-Column Name=\"SysObjectId\" SourceName=\"Sys-ObjectId\" Type=\"guid\"/><Table-Column Name=\"SysName\" SourceName=\"Sys-Name\" Type=\"string\" Cardinal=\"50\"/><Table-Column Name=\"Name\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Subject\" Type=\"string\" Cardinal=\"1024\"/><Table-Column Name=\"Priority\" Type=\"string\" Cardinal=\"100\"/><Table-Column Name=\"Responsible\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"ResponsibleRole\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Category\" SourceName=\"Category_Value\" Type=\"guid\"/></Table-Columns></Table>"
|
||||
, "Table[@Name='M42Wpm-Ticket-Assets']"
|
||||
);
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "DataCluster[@Name='M42Tickets']"
|
||||
, "Table[@Name='M42Wpm-Ticket-Categories']"
|
||||
, "<Table Name=\"M42Wpm-Ticket-Categories\" Type=\"Selection\" Key=\"id\"><Matrix42-DataQueryItems-Template EntityClassName=\"SPSScCategoryClassBase\" EntityTypeNames=\"SPSScCategoryType\" OrderBy=\"\" WhereExpression=\"Hidden = 0\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Id\" Type=\"guid\"/><Table-Column Name=\"SysObjectId\" SourceName=\"Sys-ObjectId\" Type=\"guid\"/><Table-Column Name=\"SysName\" SourceName=\"Sys-Name\" Type=\"string\" Cardinal=\"50\"/><Table-Column Name=\"Name\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"parentValue\" SourceName=\"Parent_Value\" Type=\"guid\"/><Table-Column Name=\"parent\" SourceName=\"Parent\" Type=\"string\" Cardinal=\"300\"/></Table-Columns></Table>"
|
||||
, "Table[@Name='M42Wpm-Ticket-QuickCalls']"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "DataCluster[@Name='M42Tickets']"
|
||||
, "Table[@Name='M42Wpm-Ticket-Categories']"
|
||||
, "<Table Name=\"M42Wpm-Ticket-Categories\" Type=\"Selection\" Key=\"id\"><Matrix42-DataQueryItems-Template EntityClassName=\"SPSScCategoryClassBase\" EntityTypeNames=\"SPSScCategoryType\" OrderBy=\"\" WhereExpression=\"Hidden = 0\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Id\" Type=\"guid\"/><Table-Column Name=\"SysObjectId\" SourceName=\"Sys-ObjectId\" Type=\"guid\"/><Table-Column Name=\"SysName\" SourceName=\"Sys-Name\" Type=\"string\" Cardinal=\"50\"/><Table-Column Name=\"Name\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"parentValue\" SourceName=\"Parent_Value\" Type=\"guid\"/><Table-Column Name=\"parent\" SourceName=\"Parent\" Type=\"string\" Cardinal=\"300\"/></Table-Columns></Table>"
|
||||
, "Table[@Name='M42Wpm-Ticket-QuickCalls']"
|
||||
);
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "DataCluster[@Name='M42Tickets']"
|
||||
@@ -493,83 +503,96 @@ namespace C4IT.DataHistoryProvider
|
||||
}
|
||||
|
||||
// update table 'M42Wpm-Tickets' columns
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Tickets", "<Table-Column Name=\"Urgency\" Type=\"string\" Cardinal=\"64\"/>", "AffectedUser");
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Tickets", "<Table-Column Name=\"UrgencyId\" Type=\"int\"/>", "Urgency");
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Tickets", "<Table-Column Name=\"Impact\" Type=\"string\" Cardinal=\"64\"/>", "UrgencyId");
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Tickets", "<Table-Column Name=\"ImpactId\" Type=\"int\"/>", "Impact");
|
||||
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Ticket-QuickCalls", "<Table-Column Name=\"Category\" SourceName=\"Category_Value\" Type=\"guid\" />", "ResponsibleRole");
|
||||
|
||||
var quickCallsCategoryColumn = XmlRoot.SelectSingleNode("DataCluster[@Name='M42Tickets']/Table[@Name='M42Wpm-Ticket-QuickCalls']/Table-Columns/Table-Column[@Name='Category']") as XmlElement;
|
||||
if (quickCallsCategoryColumn != null)
|
||||
{
|
||||
if (!string.Equals(quickCallsCategoryColumn.GetAttribute("SourceName"), "Category_Value", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
quickCallsCategoryColumn.SetAttribute("SourceName", "Category_Value");
|
||||
RetVal = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(quickCallsCategoryColumn.GetAttribute("Type"), "guid", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
quickCallsCategoryColumn.SetAttribute("Type", "guid");
|
||||
RetVal = true;
|
||||
}
|
||||
}
|
||||
|
||||
var quickCallsTemplate = XmlRoot.SelectSingleNode("DataCluster[@Name='M42Tickets']/Table[@Name='M42Wpm-Ticket-QuickCalls']/Matrix42-DataQueryItems-Template") as XmlElement;
|
||||
if (quickCallsTemplate != null)
|
||||
{
|
||||
if (!string.Equals(quickCallsTemplate.GetAttribute("DataQueryName"), "C4IT - F4SD - Quick Calls", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
quickCallsTemplate.SetAttribute("DataQueryName", "C4IT - F4SD - Quick Calls");
|
||||
RetVal = true;
|
||||
}
|
||||
}
|
||||
|
||||
var categoriesColumns = XmlRoot.SelectSingleNode("DataCluster[@Name='M42Tickets']/Table[@Name='M42Wpm-Ticket-Categories']/Table-Columns") as XmlElement;
|
||||
if (categoriesColumns != null)
|
||||
{
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Ticket-Categories", "<Table-Column Name=\"parentValue\" SourceName=\"Parent_Value\" Type=\"guid\" />", "Name");
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Ticket-Categories", "<Table-Column Name=\"parent\" SourceName=\"Parent\" Type=\"string\" Cardinal=\"300\" />", "parentValue");
|
||||
|
||||
var parentValueColumn = categoriesColumns.SelectSingleNode("Table-Column[@Name='parentValue']") as XmlElement;
|
||||
if (parentValueColumn != null)
|
||||
{
|
||||
if (!string.Equals(parentValueColumn.GetAttribute("SourceName"), "Parent_Value", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
parentValueColumn.SetAttribute("SourceName", "Parent_Value");
|
||||
RetVal = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(parentValueColumn.GetAttribute("Type"), "guid", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
parentValueColumn.SetAttribute("Type", "guid");
|
||||
RetVal = true;
|
||||
}
|
||||
}
|
||||
|
||||
var parentColumn = categoriesColumns.SelectSingleNode("Table-Column[@Name='parent']") as XmlElement;
|
||||
if (parentColumn != null)
|
||||
{
|
||||
if (!string.Equals(parentColumn.GetAttribute("SourceName"), "Parent", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
parentColumn.SetAttribute("SourceName", "Parent");
|
||||
RetVal = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(parentColumn.GetAttribute("Type"), "string", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
parentColumn.SetAttribute("Type", "string");
|
||||
RetVal = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(parentColumn.GetAttribute("Cardinal"), "300", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
parentColumn.SetAttribute("Cardinal", "300");
|
||||
RetVal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Tickets", "<Table-Column Name=\"Urgency\" Type=\"string\" Cardinal=\"64\"/>", "AffectedUser");
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Tickets", "<Table-Column Name=\"UrgencyId\" Type=\"int\"/>", "Urgency");
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Tickets", "<Table-Column Name=\"Impact\" Type=\"string\" Cardinal=\"64\"/>", "UrgencyId");
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Tickets", "<Table-Column Name=\"ImpactId\" Type=\"int\"/>", "Impact");
|
||||
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Ticket-QuickCalls", "<Table-Column Name=\"Category\" SourceName=\"Category_Value\" Type=\"guid\" />", "ResponsibleRole");
|
||||
|
||||
var quickCallsCategoryColumn = XmlRoot.SelectSingleNode("DataCluster[@Name='M42Tickets']/Table[@Name='M42Wpm-Ticket-QuickCalls']/Table-Columns/Table-Column[@Name='Category']") as XmlElement;
|
||||
if (quickCallsCategoryColumn != null)
|
||||
{
|
||||
if (!string.Equals(quickCallsCategoryColumn.GetAttribute("SourceName"), "Category_Value", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
quickCallsCategoryColumn.SetAttribute("SourceName", "Category_Value");
|
||||
RetVal = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(quickCallsCategoryColumn.GetAttribute("Type"), "guid", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
quickCallsCategoryColumn.SetAttribute("Type", "guid");
|
||||
RetVal = true;
|
||||
}
|
||||
}
|
||||
|
||||
var quickCallsTemplate = XmlRoot.SelectSingleNode("DataCluster[@Name='M42Tickets']/Table[@Name='M42Wpm-Ticket-QuickCalls']/Matrix42-DataQueryItems-Template") as XmlElement;
|
||||
if (quickCallsTemplate != null)
|
||||
{
|
||||
if (!string.Equals(quickCallsTemplate.GetAttribute("DataQueryName"), "C4IT - F4SD - Quick Calls", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
quickCallsTemplate.SetAttribute("DataQueryName", "C4IT - F4SD - Quick Calls");
|
||||
RetVal = true;
|
||||
}
|
||||
}
|
||||
|
||||
var categoriesColumns = XmlRoot.SelectSingleNode("DataCluster[@Name='M42Tickets']/Table[@Name='M42Wpm-Ticket-Categories']/Table-Columns") as XmlElement;
|
||||
if (categoriesColumns != null)
|
||||
{
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Ticket-Categories", "<Table-Column Name=\"parentValue\" SourceName=\"Parent_Value\" Type=\"guid\" />", "Name");
|
||||
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Ticket-Categories", "<Table-Column Name=\"parent\" SourceName=\"Parent\" Type=\"string\" Cardinal=\"300\" />", "parentValue");
|
||||
|
||||
var parentValueColumn = categoriesColumns.SelectSingleNode("Table-Column[@Name='parentValue']") as XmlElement;
|
||||
if (parentValueColumn != null)
|
||||
{
|
||||
if (!string.Equals(parentValueColumn.GetAttribute("SourceName"), "Parent_Value", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
parentValueColumn.SetAttribute("SourceName", "Parent_Value");
|
||||
RetVal = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(parentValueColumn.GetAttribute("Type"), "guid", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
parentValueColumn.SetAttribute("Type", "guid");
|
||||
RetVal = true;
|
||||
}
|
||||
}
|
||||
|
||||
var parentColumn = categoriesColumns.SelectSingleNode("Table-Column[@Name='parent']") as XmlElement;
|
||||
if (parentColumn != null)
|
||||
{
|
||||
if (!string.Equals(parentColumn.GetAttribute("SourceName"), "Parent", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
parentColumn.SetAttribute("SourceName", "Parent");
|
||||
RetVal = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(parentColumn.GetAttribute("Type"), "string", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
parentColumn.SetAttribute("Type", "string");
|
||||
RetVal = true;
|
||||
}
|
||||
|
||||
if (!string.Equals(parentColumn.GetAttribute("Cardinal"), "300", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
parentColumn.SetAttribute("Cardinal", "300");
|
||||
RetVal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var categoriesTemplate = XmlRoot.SelectSingleNode("DataCluster[@Name='M42Tickets']/Table[@Name='M42Wpm-Ticket-Categories']/Matrix42-DataQueryItems-Template") as XmlElement;
|
||||
if (categoriesTemplate != null)
|
||||
{
|
||||
var whereExpression = categoriesTemplate.GetAttribute("WhereExpression");
|
||||
var normalizedWhereExpression = Regex.Replace(whereExpression ?? string.Empty, @"\s+", string.Empty);
|
||||
if (string.IsNullOrWhiteSpace(whereExpression)
|
||||
|| string.Equals(normalizedWhereExpression, "Hidden=false", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
categoriesTemplate.SetAttribute("WhereExpression", "Hidden = 0");
|
||||
RetVal = true;
|
||||
}
|
||||
}
|
||||
|
||||
// correct the type attribute for the M42Wpm-Ticket-History table to Events
|
||||
var M42JournalItemNode = XmlRoot.SelectSingleNode("DataCluster[@Name='M42Tickets']/Table[@Name='M42Wpm-Ticket-History' and @Type!='HistoryEvents']") as XmlElement;
|
||||
@@ -2517,13 +2540,13 @@ namespace C4IT.DataHistoryProvider
|
||||
|
||||
}
|
||||
|
||||
public class cDataHistoryConfigQueryTemplateM42DataQueryItems : cDataHistoryConfigQueryTemplate
|
||||
{
|
||||
public string EntityClassName { get; private set; } = null;
|
||||
public List<string> EntityTypeNames { get; private set; } = null;
|
||||
public string OrderBy { get; private set; } = null;
|
||||
public string WhereExpression { get; private set; } = null;
|
||||
public string DataQueryName { get; private set; } = null;
|
||||
public class cDataHistoryConfigQueryTemplateM42DataQueryItems : cDataHistoryConfigQueryTemplate
|
||||
{
|
||||
public string EntityClassName { get; private set; } = null;
|
||||
public List<string> EntityTypeNames { get; private set; } = null;
|
||||
public string OrderBy { get; private set; } = null;
|
||||
public string WhereExpression { get; private set; } = null;
|
||||
public string DataQueryName { get; private set; } = null;
|
||||
|
||||
|
||||
internal cDataHistoryConfigQueryTemplateM42DataQueryItems(XmlElement XNode, cXmlParser Parser) :
|
||||
@@ -2555,11 +2578,11 @@ namespace C4IT.DataHistoryProvider
|
||||
EntityTypeNames.Add(_e2);
|
||||
}
|
||||
|
||||
OrderBy = cXmlParser.GetStringFromXmlAttribute(XNode2, "OrderBy");
|
||||
WhereExpression = cXmlParser.GetStringFromXmlAttribute(XNode2, "WhereExpression");
|
||||
DataQueryName = cXmlParser.GetStringFromXmlAttribute(XNode2, "DataQueryName");
|
||||
|
||||
Parser.LeaveElement("Matrix42-DataQueryItems-Template");
|
||||
OrderBy = cXmlParser.GetStringFromXmlAttribute(XNode2, "OrderBy");
|
||||
WhereExpression = cXmlParser.GetStringFromXmlAttribute(XNode2, "WhereExpression");
|
||||
DataQueryName = cXmlParser.GetStringFromXmlAttribute(XNode2, "DataQueryName");
|
||||
|
||||
Parser.LeaveElement("Matrix42-DataQueryItems-Template");
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
|
||||
@@ -58,292 +58,355 @@ namespace C4IT.DataHistoryProvider
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
case "OpenActivitiesExternally":
|
||||
var _openActivitiesEntry = getOpenActivitiesExternallyEntry(_item);
|
||||
if (_openActivitiesEntry != null)
|
||||
_result.Items[_openActivitiesEntry.Name] = _openActivitiesEntry;
|
||||
|
||||
var _overrideValues = getOpenActivitiesExternallyOverrides(_item, Parser);
|
||||
if (_overrideValues != null && _overrideValues.ValueList != null && _overrideValues.ValueList.Count > 0)
|
||||
_result.Items[_overrideValues.Name] = _overrideValues;
|
||||
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;
|
||||
}
|
||||
|
||||
private static cConfigHelperParameterEntry getOpenActivitiesExternallyEntry(XmlElement XNode)
|
||||
{
|
||||
var _policy = cXmlParser.GetEnumFromAttribute<enumConfigPolicy>(XNode, "Policy", enumConfigPolicy.Default);
|
||||
var _value = cXmlParser.GetStringFromXmlAttribute(XNode, "Value", String.Empty);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_value))
|
||||
return null;
|
||||
|
||||
return new cConfigHelperParameterEntry()
|
||||
{
|
||||
Name = "OpenActivitiesExternally",
|
||||
Value = _value,
|
||||
Policy = _policy.ToString(),
|
||||
};
|
||||
}
|
||||
|
||||
private cConfigHelperParameterEntry getOpenActivitiesExternallyOverrides(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 != "OpenActivityOverride")
|
||||
{
|
||||
var _msg = $"Invalid entry in F4SD-Global-Configuration.xml: {_item.Name}, should be <OpenActivityOverride/>";
|
||||
Parser.AddMessage(_item, _msg, LogLevels.Warning);
|
||||
LogEntry(_msg, LogLevels.Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
var activityType = cXmlParser.GetStringFromXmlAttribute(_item, "ActivityType", String.Empty)?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(activityType))
|
||||
{
|
||||
var _msg = $"Missing ActivityType attribute value in entry {_item.Name}";
|
||||
Parser.AddMessage(_item, _msg, LogLevels.Warning);
|
||||
LogEntry(_msg, LogLevels.Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
var valueText = cXmlParser.GetStringFromXmlAttribute(_item, "Value", String.Empty)?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(valueText))
|
||||
{
|
||||
var _msg = $"Missing Value attribute value in entry {_item.Name} ({activityType})";
|
||||
Parser.AddMessage(_item, _msg, LogLevels.Warning);
|
||||
LogEntry(_msg, LogLevels.Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
var normalizedValue = valueText.ToLowerInvariant();
|
||||
bool? parsedValue = null;
|
||||
switch (normalizedValue)
|
||||
{
|
||||
case "true":
|
||||
case "1":
|
||||
case "yes":
|
||||
parsedValue = true;
|
||||
break;
|
||||
case "false":
|
||||
case "0":
|
||||
case "no":
|
||||
parsedValue = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!parsedValue.HasValue)
|
||||
{
|
||||
var _msg = $"Invalid Value attribute value ({valueText}) in entry {_item.Name} ({activityType})";
|
||||
Parser.AddMessage(_item, _msg, LogLevels.Warning);
|
||||
LogEntry(_msg, LogLevels.Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
_result.Add($"{activityType}={(parsedValue.Value ? "true" : "false")}");
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement(_item.Name);
|
||||
}
|
||||
}
|
||||
|
||||
return new cConfigHelperParameterEntry()
|
||||
{
|
||||
Name = "OpenActivitiesExternallyOverrides",
|
||||
ValueList = _result,
|
||||
Policy = _policy.ToString()
|
||||
};
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
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;
|
||||
case "OpenActivitiesExternally":
|
||||
var _openActivitiesEntry = getOpenActivitiesExternallyEntry(_item);
|
||||
if (_openActivitiesEntry != null)
|
||||
_result.Items[_openActivitiesEntry.Name] = _openActivitiesEntry;
|
||||
|
||||
var _overrideValues = getOpenActivitiesExternallyOverrides(_item, Parser);
|
||||
if (_overrideValues != null && _overrideValues.ValueList != null && _overrideValues.ValueList.Count > 0)
|
||||
_result.Items[_overrideValues.Name] = _overrideValues;
|
||||
continue;
|
||||
case "TicketProcessing":
|
||||
var _ticketProcessingEntry = getTicketProcessingEntry(_item, Parser);
|
||||
if (_ticketProcessingEntry != null)
|
||||
_result.Items[_ticketProcessingEntry.Name] = _ticketProcessingEntry;
|
||||
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;
|
||||
}
|
||||
|
||||
private static cConfigHelperParameterEntry getTicketProcessingEntry(XmlElement XNode, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
try
|
||||
{
|
||||
var _xNodes = XNode.SelectNodes("TicketTypeProcessing");
|
||||
|
||||
var _policy = cXmlParser.GetEnumFromAttribute<enumConfigPolicy>(XNode, "Policy", enumConfigPolicy.Default);
|
||||
var _value = cXmlParser.GetEnumFromAttribute<enumTicketProcessing>(XNode, "Value", enumTicketProcessing.Both);
|
||||
|
||||
var _result = new List<string>();
|
||||
|
||||
foreach (var _xNode in _xNodes)
|
||||
{
|
||||
if (!(_xNode is XmlElement _item))
|
||||
continue;
|
||||
|
||||
Parser.EnterElement(_item.Name);
|
||||
|
||||
try
|
||||
{
|
||||
var _ticketType = cXmlParser.GetEnumFromAttribute<enumTicketType>(_item, "Type", enumTicketType.Ticket);
|
||||
var _processingValue = cXmlParser.GetEnumFromAttribute<enumTicketProcessing>(_item, "Value", enumTicketProcessing.Both);
|
||||
_result.Add(_ticketType.ToString() + "=" + _processingValue.ToString());
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement(_item.Name);
|
||||
}
|
||||
}
|
||||
|
||||
var _retVal = new cConfigHelperParameterEntry()
|
||||
{
|
||||
Name = XNode.Name,
|
||||
ValueList = _result,
|
||||
Policy = _policy.ToString()
|
||||
};
|
||||
|
||||
return _retVal;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static cConfigHelperParameterEntry getOpenActivitiesExternallyEntry(XmlElement XNode)
|
||||
{
|
||||
var _policy = cXmlParser.GetEnumFromAttribute<enumConfigPolicy>(XNode, "Policy", enumConfigPolicy.Default);
|
||||
var _value = cXmlParser.GetStringFromXmlAttribute(XNode, "Value", String.Empty);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_value))
|
||||
return null;
|
||||
|
||||
return new cConfigHelperParameterEntry()
|
||||
{
|
||||
Name = "OpenActivitiesExternally",
|
||||
Value = _value,
|
||||
Policy = _policy.ToString(),
|
||||
};
|
||||
}
|
||||
|
||||
private cConfigHelperParameterEntry getOpenActivitiesExternallyOverrides(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 != "OpenActivityOverride")
|
||||
{
|
||||
var _msg = $"Invalid entry in F4SD-Global-Configuration.xml: {_item.Name}, should be <OpenActivityOverride/>";
|
||||
Parser.AddMessage(_item, _msg, LogLevels.Warning);
|
||||
LogEntry(_msg, LogLevels.Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
var activityType = cXmlParser.GetStringFromXmlAttribute(_item, "ActivityType", String.Empty)?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(activityType))
|
||||
{
|
||||
var _msg = $"Missing ActivityType attribute value in entry {_item.Name}";
|
||||
Parser.AddMessage(_item, _msg, LogLevels.Warning);
|
||||
LogEntry(_msg, LogLevels.Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
var valueText = cXmlParser.GetStringFromXmlAttribute(_item, "Value", String.Empty)?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(valueText))
|
||||
{
|
||||
var _msg = $"Missing Value attribute value in entry {_item.Name} ({activityType})";
|
||||
Parser.AddMessage(_item, _msg, LogLevels.Warning);
|
||||
LogEntry(_msg, LogLevels.Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
var normalizedValue = valueText.ToLowerInvariant();
|
||||
bool? parsedValue = null;
|
||||
switch (normalizedValue)
|
||||
{
|
||||
case "true":
|
||||
case "1":
|
||||
case "yes":
|
||||
parsedValue = true;
|
||||
break;
|
||||
case "false":
|
||||
case "0":
|
||||
case "no":
|
||||
parsedValue = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!parsedValue.HasValue)
|
||||
{
|
||||
var _msg = $"Invalid Value attribute value ({valueText}) in entry {_item.Name} ({activityType})";
|
||||
Parser.AddMessage(_item, _msg, LogLevels.Warning);
|
||||
LogEntry(_msg, LogLevels.Warning);
|
||||
continue;
|
||||
}
|
||||
|
||||
_result.Add($"{activityType}={(parsedValue.Value ? "true" : "false")}");
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement(_item.Name);
|
||||
}
|
||||
}
|
||||
|
||||
return new cConfigHelperParameterEntry()
|
||||
{
|
||||
Name = "OpenActivitiesExternallyOverrides",
|
||||
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)
|
||||
{
|
||||
@@ -409,31 +472,31 @@ namespace C4IT.DataHistoryProvider
|
||||
, "NotesMandatory"
|
||||
, "<NotesMandatory Policy=\"Hidden\" Value=\"false\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "ShowOverview"
|
||||
, "<ShowOverview Policy=\"Hidden\" Value=\"true\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "OpenActivitiesExternally"
|
||||
, "<OpenActivitiesExternally Policy=\"Hidden\" Value=\"false\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration/OpenActivitiesExternally"
|
||||
, "OpenActivityOverride[@ActivityType='SPSActivityTypeTicket']"
|
||||
, "<OpenActivityOverride ActivityType=\"SPSActivityTypeTicket\" Value=\"false\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration/OpenActivitiesExternally"
|
||||
, "OpenActivityOverride[@ActivityType='SPSActivityTypeServiceRequest']"
|
||||
, "<OpenActivityOverride ActivityType=\"SPSActivityTypeServiceRequest\" Value=\"true\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "OverviewPollingPersonal"
|
||||
, $"<OverviewPollingPersonal Policy=\"Hidden\" Value=\"{cF4sdTicketConfig.DefaultOverviewPollingPersonal}\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "ShowOverview"
|
||||
, "<ShowOverview Policy=\"Hidden\" Value=\"true\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "OpenActivitiesExternally"
|
||||
, "<OpenActivitiesExternally Policy=\"Hidden\" Value=\"false\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration/OpenActivitiesExternally"
|
||||
, "OpenActivityOverride[@ActivityType='SPSActivityTypeTicket']"
|
||||
, "<OpenActivityOverride ActivityType=\"SPSActivityTypeTicket\" Value=\"false\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration/OpenActivitiesExternally"
|
||||
, "OpenActivityOverride[@ActivityType='SPSActivityTypeServiceRequest']"
|
||||
, "<OpenActivityOverride ActivityType=\"SPSActivityTypeServiceRequest\" Value=\"true\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "OverviewPollingPersonal"
|
||||
, $"<OverviewPollingPersonal Policy=\"Hidden\" Value=\"{cF4sdTicketConfig.DefaultOverviewPollingPersonal}\" />"
|
||||
);
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "OverviewPollingRole"
|
||||
@@ -451,8 +514,30 @@ namespace C4IT.DataHistoryProvider
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "TicketConfiguration"
|
||||
, "DisableAutomaticTimeTracking"
|
||||
, $"<DisableAutomaticTimeTracking Policy=\"Mandatory\" Value=\"{oldDisableAutomaticTimeTracking.ToString()}\" />"
|
||||
, $"<DisableAutomaticTimeTracking Policy=\"Mandatory\" Value=\"{oldDisableAutomaticTimeTracking.ToString().ToLowerInvariant()}\" />"
|
||||
);
|
||||
|
||||
if(withIntuneConfig)
|
||||
{
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, ""
|
||||
, "IntuneConfiguration"
|
||||
, "<IntuneConfiguration />"
|
||||
);
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "IntuneConfiguration"
|
||||
, "TAPLifeTimeInMinutes"
|
||||
, $"<TAPLifeTimeInMinutes Policy=\"Default\" Value=\"{cF4sdIntuneConfig.DefaultTAPLifeTimeInMinutes}\" />"
|
||||
);
|
||||
|
||||
RetVal |= DoXmlInsertElement(XmlRoot
|
||||
, "IntuneConfiguration"
|
||||
, "TAPIsUsableOnce"
|
||||
, $"<TAPIsUsableOnce Policy=\"Default\" Value=\"{cF4sdIntuneConfig.DefaultTAPIsUsableOnce}\" />"
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception E)
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
using C4IT.Configuration;
|
||||
using C4IT.FASD.Base;
|
||||
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 C4IT.DataHistoryProvider.Base.Modules.Citrix;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using static C4IT_DataHistoryProvider.cDataHistoryConfigCitrix;
|
||||
|
||||
namespace C4IT.DataHistoryProvider
|
||||
{
|
||||
@@ -32,13 +32,14 @@ namespace C4IT.DataHistoryProvider
|
||||
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 Dictionary<string, cDataHistoryAzureTenant> AzureTenants { get; private set; } = null; //ToDo: create a class for the azure configuration instead of only the tenants
|
||||
|
||||
public cF4SDAuthorisation Authorisation { get; private set; } = null;
|
||||
|
||||
@@ -81,7 +82,6 @@ namespace C4IT.DataHistoryProvider
|
||||
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);
|
||||
|
||||
@@ -102,9 +102,12 @@ namespace C4IT.DataHistoryProvider
|
||||
|
||||
string name = a["QueueName"]?.Value;
|
||||
string id = a["QueueID"]?.Value;
|
||||
Guid guid;
|
||||
Guid guid = Guid.Empty;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(name) || !Guid.TryParse(id, out guid))
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
return null;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(id) && !Guid.TryParse(id, out guid))
|
||||
return null;
|
||||
|
||||
return new cApiM42TicketQueueInfo
|
||||
|
||||
16
F4SD-Cockpit-ServerCore/DataSources/IRemoteDesktopManager.cs
Normal file
16
F4SD-Cockpit-ServerCore/DataSources/IRemoteDesktopManager.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using C4IT.FASD.Base;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.DataSources
|
||||
{
|
||||
public interface IRemoteDesktopManager<TRemoteConnectionInfo, TClientInfo, TRemoteConnectionStatus>
|
||||
{
|
||||
Task<TRemoteConnectionInfo> InitiateConnectionOfClient(TClientInfo clientInfos, bool isElevated, CancellationToken token = default);
|
||||
Task TerminateConnection(Guid connectionId);
|
||||
Task<TRemoteConnectionStatus> GetConnectionStatus(Guid connectionId);
|
||||
bool IsActive();
|
||||
Task<HealthInformation> GetHealthInfo();
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
using C4IT.FASD.Base;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using C4IT.DataHistoryProvider;
|
||||
using C4IT.FASD.Base;
|
||||
|
||||
namespace C4IT_DataHistoryProvider_Base.DataSources
|
||||
{
|
||||
public interface ISearchResultRelationProvider
|
||||
@@ -17,6 +19,6 @@ namespace C4IT_DataHistoryProvider_Base.DataSources
|
||||
/// <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);
|
||||
Task<cF4sdStagedSearchResultRelations> GetRelationsAsync(IEnumerable<cF4sdConnectorIds> ids, enumFasdInformationClass informationClass, int ageInDays, CancellationToken token = default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>C4IT_DataHistoryProvider_Base</RootNamespace>
|
||||
<RootNamespace>C4IT.DataHistoryProvider.Base</RootNamespace>
|
||||
<Configurations>Debug;Debug-Demo;Release;Release-Demo</Configurations>
|
||||
<Deterministic>false</Deterministic>
|
||||
</PropertyGroup>
|
||||
@@ -50,6 +50,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.F4SD.Base.Ticket.cs" Link="Common\C4IT.F4SD.Base.Ticket.cs" />
|
||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.F4SD.GlobalConfig.cs">
|
||||
<Link>Common\C4IT.F4SD.GlobalConfig.cs</Link>
|
||||
</Compile>
|
||||
|
||||
95
F4SD-Cockpit-ServerCore/Modules/Agent/AgentApiHandler.cs
Normal file
95
F4SD-Cockpit-ServerCore/Modules/Agent/AgentApiHandler.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using C4IT.DataHistoryProvider.Base.Modules.Agent.DTOs;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Communication.Agent;
|
||||
using C4IT.HTTP;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.Modules.Agent
|
||||
{
|
||||
internal class AgentApiHandler : cHttpApiBase
|
||||
{
|
||||
private readonly Uri _baseUrl;
|
||||
private const string _agentLoginPath = "connect/token";
|
||||
private readonly cAgentApiConfiguration _agentConfig;
|
||||
|
||||
public AgentApiHandler(cAgentApiConfiguration agentConfig) : base("Agent ID tenant", $"{agentConfig.ApiUrl}/{agentConfig.LogonUrl}")
|
||||
{
|
||||
_agentConfig = agentConfig;
|
||||
_baseUrl = new Uri(_agentConfig.LogonUrl);
|
||||
AlwaysReturnContent = true;
|
||||
}
|
||||
|
||||
private protected override async Task<bool> privLogonAsync(cOAuthLogonInfo logonInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
var postData = new List<KeyValuePair<string, string>>()
|
||||
{
|
||||
new KeyValuePair<string, string>("grant_type", "client_credentials"),
|
||||
new KeyValuePair<string, string>("client_id", logonInfo.ClientID),
|
||||
new KeyValuePair<string, string>("client_secret", logonInfo.ClientSecret)
|
||||
};
|
||||
|
||||
var formData = new FormUrlEncodedContent(postData);
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, new Uri(_baseUrl, _agentLoginPath)) { Content = formData };
|
||||
|
||||
using (var httpClient = new HttpClient())
|
||||
{
|
||||
var response = await httpClient.SendAsync(request);
|
||||
|
||||
if (response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
var responseMessage = await response.Content.ReadAsStreamAsync();
|
||||
LogEntry($"F4SD Agent Logon failed. StatusCode: {response.StatusCode}");
|
||||
LogEntry($"F4SD Agent Logon failed. Response: {responseMessage}");
|
||||
return false;
|
||||
}
|
||||
|
||||
string responseContent = await response.Content.ReadAsStringAsync();
|
||||
var logonResult = JsonConvert.DeserializeObject<cAgentApiLogonInfo>(responseContent);
|
||||
|
||||
if (logonResult.TokenType.Equals("Bearer", StringComparison.OrdinalIgnoreCase) == false)
|
||||
{
|
||||
LogEntry("F4SD Agent Access token is not of type 'Bearer'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
cAgentApiLogonInfo.Instance = logonResult;
|
||||
AccessToken = logonResult.AccessToken;
|
||||
TokenExpiresIn = DateTime.UtcNow + TimeSpan.FromSeconds(logonResult.SecondsTillTokenExpires * RelogonFactor);
|
||||
IsOnline = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task<T> Request<T>(string url, eHttpMethod httpMethod = eHttpMethod.get, object bodyData = null, CancellationToken token = default) where T : AgentApiResult
|
||||
{
|
||||
await LogonAsync(new cOAuthLogonInfo() { ClientID = _agentConfig.ClientId, ClientSecret = _agentConfig.ClientSecret, Tenant = "F4SD Agent" });
|
||||
Uri agentUrl = new Uri(_baseUrl, url);
|
||||
dynamic requestResult = await privRequestAsync(agentUrl.ToString(), httpMethod, bodyData, token: token);
|
||||
// todo handle not successfull status
|
||||
requestResult.ToObject<T>();
|
||||
string serialized = JsonConvert.SerializeObject(requestResult); // todo find better approach for casting the dynamic
|
||||
T deserialized = JsonConvert.DeserializeObject<T>(serialized);
|
||||
return deserialized;
|
||||
}
|
||||
|
||||
internal async Task Request(string url, eHttpMethod httpMethod = eHttpMethod.get, object bodyData = null)
|
||||
=> await privRequestAsync(url, httpMethod, bodyData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.Modules.Agent
|
||||
{
|
||||
public class AgentRemoteClientInfo
|
||||
{
|
||||
[JsonProperty("orgCode")]
|
||||
public int OrganisationCode { get; set; }
|
||||
|
||||
[JsonProperty("deviceCode")]
|
||||
public int DeviceCode { get; set; }
|
||||
|
||||
[JsonProperty("accountCode")]
|
||||
public int AccountCode { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using C4IT.FASD.Communication.Agent;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.Modules.Agent
|
||||
{
|
||||
public class AgentRemoteConnectionInfo : AgentApiResult
|
||||
{
|
||||
[JsonProperty("connectionId")]
|
||||
public Guid ConnectionId { get; set; }
|
||||
|
||||
[JsonProperty("phoenixServiceUrl")]
|
||||
public Uri ServiceUrl { get; set; }
|
||||
|
||||
[JsonProperty("secret")]
|
||||
public string Secret { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using C4IT.DataHistoryProvider.Base.DataSources;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.FASD.Communication.Agent;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.Modules.Agent
|
||||
{
|
||||
public class AgentRemoteDesktopManager : IRemoteDesktopManager<AgentRemoteConnectionInfo, AgentRemoteClientInfo, AgentRemoteConnectionStatusDto>
|
||||
{
|
||||
private readonly AgentApiHandler _agentApiHandler;
|
||||
|
||||
public AgentRemoteDesktopManager(cAgentApiConfiguration agentConfig)
|
||||
{
|
||||
_agentApiHandler = new AgentApiHandler(agentConfig);
|
||||
}
|
||||
|
||||
public async Task<AgentRemoteConnectionStatusDto> GetConnectionStatus(Guid connectionId)
|
||||
{
|
||||
return await _agentApiHandler.Request<AgentRemoteConnectionStatusDto>($"api/management/c4it/phoenix-connections/{connectionId}/status", HTTP.eHttpMethod.get);
|
||||
}
|
||||
|
||||
public async Task<AgentRemoteConnectionInfo> InitiateConnectionOfClient(AgentRemoteClientInfo clientInfos, bool isElevated, CancellationToken token)
|
||||
{
|
||||
string url = "api/management/c4it/phoenix-connections";
|
||||
if (isElevated)
|
||||
url += "/admin";
|
||||
|
||||
return await _agentApiHandler.Request<AgentRemoteConnectionInfo>(url, HTTP.eHttpMethod.post, clientInfos, token);
|
||||
}
|
||||
|
||||
public async Task TerminateConnection(Guid connectionId)
|
||||
{
|
||||
await _agentApiHandler.Request($"api/management/c4it/phoenix-connections/{connectionId}", HTTP.eHttpMethod.delete);
|
||||
}
|
||||
|
||||
public bool IsActive() => true;
|
||||
|
||||
public Task<HealthInformation> GetHealthInfo()
|
||||
{
|
||||
// todo Agent Server has to implement an "health" endpoint and return its result
|
||||
return Task.FromResult(new HealthInformation(HealthStatus.healthy));
|
||||
}
|
||||
}
|
||||
}
|
||||
13
F4SD-Cockpit-ServerCore/Modules/Agent/DTOs/AgentErrorDto.cs
Normal file
13
F4SD-Cockpit-ServerCore/Modules/Agent/DTOs/AgentErrorDto.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.Modules.Agent.DTOs
|
||||
{
|
||||
public class AgentErrorDto
|
||||
{
|
||||
[JsonProperty("code")]
|
||||
public string Code { get; set; }
|
||||
|
||||
[JsonProperty("message")]
|
||||
public string Message { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.Modules.Agent.DTOs
|
||||
{
|
||||
public class AgentLogonResultDto
|
||||
{
|
||||
[JsonProperty("access_token")]
|
||||
public string AccessToken { get; set; }
|
||||
|
||||
[JsonProperty("expires_in")]
|
||||
public int ExpiresIn { get; set; }
|
||||
|
||||
[JsonProperty("token_type")]
|
||||
public string TokenType { get; set; }
|
||||
|
||||
[JsonProperty("scope")]
|
||||
public string Scope { get; set; }
|
||||
|
||||
[JsonProperty("remote_ip")]
|
||||
public string RemoteIp { get; set; }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,295 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.DirectoryServices.ActiveDirectory;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
|
||||
using C4IT.DataHistoryProvider;
|
||||
using C4IT.Logging;
|
||||
using C4IT.Security;
|
||||
using C4IT.XML;
|
||||
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.DataHistoryProvider.Base.Modules.Citrix
|
||||
{
|
||||
public class cDataHistoryConfigCitrix : IConfigNodeValidation
|
||||
{
|
||||
public bool IsValid { get; private set; } = false;
|
||||
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);
|
||||
|
||||
Systems = cDataHistoryCitrixCloudTenant.LoadFromXml(XCitrix, Credentials, Parser);
|
||||
|
||||
if (Systems == null)
|
||||
Systems = new List<cDataHistoryCitrixSystem>();
|
||||
|
||||
var _onPremSystems = cDataHistoryCitrixOnPrem.LoadFromXml(XCitrix, Credentials, Parser);
|
||||
if (_onPremSystems != null)
|
||||
Systems.AddRange(_onPremSystems);
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Citrix");
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
public List<cDataHistoryCitrixSystem> Systems { get; private set; } = null; //ToDo: Check all uses of the citrix systems to implement on prem and tenant specific handling if needed
|
||||
|
||||
}
|
||||
|
||||
public abstract class cDataHistoryCitrixSystem : cConfigNodeNamed
|
||||
{
|
||||
public cCredential Credential { get; private set; } = null;
|
||||
|
||||
public Guid SiteID { get; set; } = Guid.Empty;
|
||||
|
||||
public cDataHistoryCitrixSystem(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;
|
||||
|
||||
SiteID = cXmlParser.GetGuidFromXmlAttribute(XNode, "SiteID");
|
||||
|
||||
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, null, "Credential");
|
||||
return;
|
||||
}
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class cDataHistoryCitrixCloudTenant : cDataHistoryCitrixSystem
|
||||
{
|
||||
public string Domain { get; private set; } = "";
|
||||
|
||||
public string TenantID { get; private set; } = String.Empty;
|
||||
|
||||
internal cDataHistoryCitrixCloudTenant(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser) : base(XNode, Credentials, Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
try
|
||||
{
|
||||
if (!IsValid)
|
||||
return;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
internal static List<cDataHistoryCitrixSystem> LoadFromXml(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var RetVal = new List<cDataHistoryCitrixSystem>();
|
||||
|
||||
try
|
||||
{
|
||||
var XList = XNode.SelectNodes("Citrix-Cloud-Tenant");
|
||||
if (XList != null && XList.Count > 0)
|
||||
{
|
||||
Parser.EnterElement("Citrix-Cloud-Tenant");
|
||||
try
|
||||
{
|
||||
foreach (var Entry in XList)
|
||||
{
|
||||
if (!(Entry is XmlElement XEntry))
|
||||
continue;
|
||||
|
||||
var Node = new cDataHistoryCitrixCloudTenant(XEntry, Credentials, Parser);
|
||||
if (Node.IsValid)
|
||||
RetVal.Add(Node);
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Citrix-Cloud-Tenant");
|
||||
}
|
||||
}
|
||||
|
||||
XList = XNode.SelectNodes("Citrix-OnPrem-System");
|
||||
if (XList != null && XList.Count > 0)
|
||||
{
|
||||
Parser.EnterElement("Citrix-OnPrem-System");
|
||||
try
|
||||
{
|
||||
foreach (var Entry in XList)
|
||||
{
|
||||
if (!(Entry is XmlElement XEntry))
|
||||
continue;
|
||||
|
||||
var Node = new cDataHistoryCitrixOnPrem(XEntry, Credentials, Parser);
|
||||
if (Node.IsValid)
|
||||
RetVal.Add(Node);
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Citrix-OnPrem-System");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
}
|
||||
|
||||
public class cDataHistoryCitrixOnPrem : cDataHistoryCitrixSystem
|
||||
{
|
||||
public string Server { get; private set; } = string.Empty;
|
||||
|
||||
internal cDataHistoryCitrixOnPrem(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser) : base(XNode, Credentials, Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
try
|
||||
{
|
||||
Server = cXmlParser.GetStringFromXmlAttribute(XNode, "Server");
|
||||
if (string.IsNullOrWhiteSpace(Server))
|
||||
{
|
||||
Parser.AddInvalidAttribute(XNode, null, "Server");
|
||||
return;
|
||||
}
|
||||
|
||||
IsValid = true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
internal static List<cDataHistoryCitrixSystem> LoadFromXml(XmlElement XNode, Dictionary<string, cCredential> Credentials, cXmlParser Parser)
|
||||
{
|
||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||
|
||||
var RetVal = new List<cDataHistoryCitrixSystem>();
|
||||
|
||||
try
|
||||
{
|
||||
var XList = XNode.SelectNodes("Citrix-OnPrem");
|
||||
if (XList != null && XList.Count > 0)
|
||||
{
|
||||
Parser.EnterElement("Citrix-OnPrem");
|
||||
try
|
||||
{
|
||||
foreach (var Entry in XList)
|
||||
{
|
||||
if (!(Entry is XmlElement XEntry))
|
||||
continue;
|
||||
|
||||
var Node = new cDataHistoryCitrixOnPrem(XEntry, Credentials, Parser);
|
||||
if (Node.IsValid)
|
||||
RetVal.Add(Node);
|
||||
Parser.SelectElementNext();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Parser.LeaveElement("Citrix-OnPrem");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (CM != null) LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
BIN
F4SD-Cockpit-ServerCore/Publish/F4SD-Cockpit-ServerCore.dll
Normal file
BIN
F4SD-Cockpit-ServerCore/Publish/F4SD-Cockpit-ServerCore.dll
Normal file
Binary file not shown.
@@ -11,7 +11,7 @@ namespace C4IT_DataHistoryProvider_Base.Services
|
||||
/// <summary>
|
||||
/// Triggers search for relations to given information objects.
|
||||
/// </summary>
|
||||
cF4sdStagedSearchResultRelationTaskId StartGatheringRelatedObjects(IEnumerable<cFasdApiSearchResultEntry> relatedTo, int ageInDays);
|
||||
Task<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.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.DataHistoryProvider;
|
||||
using C4IT.FASD.Base;
|
||||
using C4IT.Logging;
|
||||
using C4IT_DataHistoryProvider_Base.DataSources;
|
||||
using System;
|
||||
@@ -16,13 +17,16 @@ namespace C4IT_DataHistoryProvider_Base.Services
|
||||
private static readonly Dictionary<Guid, GatherRelatedObjectTask> _relationTasks = new Dictionary<Guid, GatherRelatedObjectTask>();
|
||||
private readonly IEnumerable<ISearchResultRelationProvider> _providers;
|
||||
|
||||
private readonly cDataHistoryCollector _collector;
|
||||
|
||||
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)
|
||||
public StagedRelationService(cDataHistoryCollector collector, IEnumerable<ISearchResultRelationProvider> providers)
|
||||
{
|
||||
_providers = providers;
|
||||
_collector = collector;
|
||||
SetupCleanupTimer();
|
||||
}
|
||||
|
||||
@@ -36,7 +40,7 @@ namespace C4IT_DataHistoryProvider_Base.Services
|
||||
_relationTaskCleanupTimer.Start();
|
||||
}
|
||||
|
||||
public cF4sdStagedSearchResultRelationTaskId StartGatheringRelatedObjects(IEnumerable<cFasdApiSearchResultEntry> relatedTo, int age)
|
||||
public async Task<cF4sdStagedSearchResultRelationTaskId> StartGatheringRelatedObjects(IEnumerable<cFasdApiSearchResultEntry> relatedTo, int age)
|
||||
{
|
||||
cF4sdStagedSearchResultRelationTaskId taskId = new cF4sdStagedSearchResultRelationTaskId();
|
||||
try
|
||||
@@ -49,12 +53,14 @@ namespace C4IT_DataHistoryProvider_Base.Services
|
||||
|
||||
List<cF4sdIdentityEntry> identities = relatedTo.Select(relation => new cF4sdIdentityEntry() { Id = relation.id, Class = relatedToInformationClass }).ToList();
|
||||
|
||||
var _ids = await _collector.getConnectorIdList(identities, CancellationToken.None, null, age);
|
||||
|
||||
foreach (var collectorModule in _providers)
|
||||
{
|
||||
taskId.PendingInformationClasses.UnionWith(collectorModule.GetSupportedInformationClasses());
|
||||
|
||||
Task<cF4sdStagedSearchResultRelations> task = Task.Run(() =>
|
||||
collectorModule.GetRelationsAsync(identities, relatedToInformationClass, age, relationTask.TokenSource.Token));
|
||||
collectorModule.GetRelationsAsync(_ids, relatedToInformationClass, age, relationTask.TokenSource.Token));
|
||||
|
||||
relationTask.RelatedObjectTasks.Add((collectorModule.GetSupportedInformationClasses(), task));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user