Files
C4IT-F4SD-Collector/F4SD-Cockpit-ServerCore/DataHistoryCollectorM42Wpm.cs
2026-02-04 09:35:40 +01:00

4127 lines
188 KiB
C#

using C4IT.F4SD.SupportCaseProtocoll.Models;
using C4IT.FASD.Base;
using C4IT.Logging;
using C4IT.Matrix42.WebClient;
using C4IT.XML;
using C4IT_DataHistoryProvider_Base.DataSources;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using static C4IT.FASD.Base.cF4SDHealthCardRawData;
using static C4IT.Logging.cLogManager;
using static C4IT.Matrix42.WebClient.cM42WebClient;
namespace C4IT.DataHistoryProvider
{
public class cDataHistoryCollectorM42Wpm : cDataHistoryCollectorModule, ISearchResultRelationProvider
{
public const string constConnectorName = "Matrix42 WPM conntector";
public const string constLicenseId = "9CE1A6BE-6A0C-4A27-94A5-44AB997B8E62";
private const string constUrlIsAlive = "m42Services/api/c4itf4sdwebapi/isalive";
private const string constUrlGetTickets = "m42Services/api/c4itf4sdwebapi/getticketlist?sid={0}&hours={1}&queueoption={2}";
private const string constUrlGetTicketsQueuesParam = "&queues={0}";
private const string constUrlGetTicketDetails = "m42Services/api/c4itf4sdwebapi/getticketdetails?objectid={0}";
private const string constUrlGetTicketHistory = "m42Services/api/c4itf4sdwebapi/gettickethistory?objectid={0}";
private const string constUrlGetCreateTicket = "m42Services/api/c4itf4sdwebapi/getdirectlinkcreateticket?sid={0}{1}";
private const string constUrlGetCreateTicketAssetParam = "&assetname={0}";
private const string constUrlUpdateSolution = "m42Services/api/c4itf4sdwebapi/updateactivitysolution/{0}/";
private const string constUrlGetPickupValues = "m42Services/api/c4itf4sdwebapi/getpickup/{0}?group={1}";
private const string constUrlGetRoleMeberships = "m42services/api/c4itf4sdwebapi/getrolememberships/?sid={0}";
private const string constUrlGetTicketOverviewCounts = "m42Services/api/c4itf4sdwebapi/getticketoverviewcounts?sid={0}&scope={1}&keys={2}";
private const string constUrlGetTicketOverviewCountsByRoles = "m42Services/api/c4itf4sdwebapi/getticketoverviewcountsbyroles";
private const string constUrlGetTicketOverviewRelations = "m42Services/api/c4itf4sdwebapi/getticketoverviewrelations?sid={0}&scope={1}&key={2}&count={3}";
private const string constUrlGetDataQueryRelationItems = "m42Services/api/dataquery/relationitems";
private const string constUrlGetDataQueryRelationItemsCount = "m42Services/api/dataquery/relationitems/count";
private const string constUrlCreateTicket = "m42Services/api/ticket/create?activitytype={0}";
private const string constUrlActivityGetQuickCallTemplateInfo = "m42Services/api/activity/quickcalltemplateinfo/{0}";
private const string constUrlCreateJournalEntry = "m42Services/api/journal/Add";
private const string constUrlFragmentsGetList = "m42Services/api/data/fragments/{0}?where={1}&columns={2}&pagesize={3}&pagenumber={4}&sort={5}";
private const string constUrlObjectsGetObject = "m42Services/api/data/objects/{0}/{1}?full={2}";
private const string constUrlObjectsUpdateObject = "m42Services/api/data/objects/{0}?full={1}";
private const string constUrlTicketClose = "m42Services/api/ticket/close";
private const string constUrlActivityPause = "m42Services/api/activity/Pause";
private const string constUrlActivityForward = "m42Services/api/activity/Forward";
private const string constUrlActivityTrackWorkingTime = "m42Services/api/activity/trackworkingtime";
private const string constUrlTicketTransform = "m42Services/api/ticket/transform";
private const string constUrlActivityReopen = "m42Services/api/activity/reopen";
private const string constUrlGenerateApiTokenForMe = "m42Services/api/apitoken/generateapitokenforme";
private const string constUrlGenerateAccessTokenFromApiToken = "m42Services/api/apitoken/generateaccesstokenfromapitoken";
public const string constTableNameTicketDetails = "M42Wpm-Tickets";
public const string constTableNameTicketHistory = "M42Wpm-Ticket-History";
public const string constTableNameUserTicket = "M42Wpm-User-NewTicket";
private readonly cM42WebClient WebClient = null;
private Dictionary<string, cM42WebClient> dicWebClients = new Dictionary<string, cM42WebClient>();
private readonly Timer onlineTimer = null;
private bool IsOnline = false;
private Dictionary<WebClientCacheIndex, WebClientCacheEntry> UserWebClientCache = new Dictionary<WebClientCacheIndex, WebClientCacheEntry>();
private readonly object _ticketOverviewCacheLock = new object();
private readonly Dictionary<string, TicketOverviewCountCacheEntry> _ticketOverviewPersonalCache = new Dictionary<string, TicketOverviewCountCacheEntry>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<Guid, TicketOverviewCountCacheEntry> _ticketOverviewRoleCache = new Dictionary<Guid, TicketOverviewCountCacheEntry>();
private readonly Dictionary<string, TicketOverviewRoleListCacheEntry> _ticketOverviewRoleListCache = new Dictionary<string, TicketOverviewRoleListCacheEntry>(StringComparer.OrdinalIgnoreCase);
private readonly cDataHistoryCollector _collector;
private static class _OnlineCheckCriticalSection
{
public static SemaphoreSlim Semaphore = new SemaphoreSlim(1, 1);
}
private static class _LanguageDicWebClientCriticalSection
{
public static SemaphoreSlim Semaphore = new SemaphoreSlim(1, 1);
}
private struct WebClientCacheIndex
{
public Guid Id;
public string Language;
}
private class WebClientCacheEntry
{
public cM42WebClient WebClient;
public DateTime LastUsed;
public DateTime ValidUntil;
}
private sealed class TicketOverviewCountCacheEntry
{
public Dictionary<string, int> Counts { get; set; } = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
public DateTime ExpiresAtUtc { get; set; }
}
private sealed class TicketOverviewRoleListCacheEntry
{
public List<Guid> RoleIds { get; set; } = new List<Guid>();
public DateTime ExpiresAtUtc { get; set; }
}
private sealed class TicketOverviewCountsByRolesRequest
{
public string Sid { get; set; }
public List<Guid> RoleGuids { get; set; } = new List<Guid>();
public List<string> Keys { get; set; } = new List<string>();
}
private sealed class TicketOverviewCountsByRolesResponse
{
[JsonProperty("countsByRole")]
public Dictionary<string, Dictionary<string, int>> CountsByRole { get; set; }
= new Dictionary<string, Dictionary<string, int>>(StringComparer.OrdinalIgnoreCase);
}
public class cM42ApiTokenModel
{
public string ApiToken { get; set; }
public string Name { get; set; }
public bool? Enabled { get; set; }
public DateTime? ValidUntil { get; set; }
public string UserId { get; set; }
}
private class cApiTokenRequestModelBase
{
public string Name { get; set; }
public int ExpirationDays { get; set; }
}
public cDataHistoryCollectorM42Wpm(cDataHistoryCollector Collector) : base(Collector, enumDataHistoryOrigin.M42Wpm, constConnectorName, constLicenseId)
{
if (Collector.InfrastructureConfig.M42Wpm.Server == null)
return;
_collector = Collector;
WebClient = new cM42WebClient(Collector.InfrastructureConfig.M42Wpm.Server);
if (Collector.autoConnectionCheck)
onlineTimer = new Timer(onlineTimerCallback, null, 0, 30000);
}
private async Task<cM42WebClient> GetWebClient(cF4sdWebRequestInfo requestInfo, CancellationToken Token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
if (cLogManager.DefaultLogger.IsDebug)
LogEntry($"M42 webclient culture: {requestInfo?.Culture?.TextInfo?.CultureName}", LogLevels.Debug);
if (requestInfo?.Culture == null)
{
if (cLogManager.DefaultLogger.IsDebug) LogEntry($"M42 webclient requested with no culture", LogLevels.Debug);
return WebClient;
}
await _LanguageDicWebClientCriticalSection.Semaphore.WaitAsync(Token);
try
{
var _lang = requestInfo.Culture.TextInfo.CultureName;
if (dicWebClients.TryGetValue(_lang, out var client))
{
if (cLogManager.DefaultLogger.IsDebug) LogEntry($"M42 webclient request returned with culture: {client?.UserLanguage}", LogLevels.Debug);
return client;
}
client = new cM42WebClient(Collector.InfrastructureConfig.M42Wpm.Server, _lang);
var resLogon = await client.LogonWithApiKeyAsync(Collector.InfrastructureConfig.M42Wpm.Credential.NwCredential.Password);
if (resLogon == cM42WebClient.eReason.ok)
{
dicWebClients[_lang] = client;
if (cLogManager.DefaultLogger.IsDebug) LogEntry($"M42 webclient request returned with culture: {client?.UserLanguage}", LogLevels.Debug);
return client;
}
else
{
LogEntry($"Could not logon to M42 server with culture {_lang}. Reason: {resLogon}", LogLevels.Warning);
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
_LanguageDicWebClientCriticalSection.Semaphore.Release();
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
if (cLogManager.DefaultLogger.IsDebug) LogEntry($"M42 webclient requested return with no culture.", LogLevels.Debug);
return WebClient;
}
private async Task<cM42WebClient> GetUserWebClient(cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken Token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
lock (requestInfo)
if (requestInfo?.M42WebClient != null)
return requestInfo.M42WebClient;
if (requestInfo?.userInfo?.Id is null)
return null;
var _lang = requestInfo.Culture?.TextInfo?.CultureName;
if (_lang == null)
_lang = "en-Us";
var _index = new WebClientCacheIndex() { Id = requestInfo.userInfo.Id, Language = _lang };
lock (UserWebClientCache)
{
if (UserWebClientCache.TryGetValue(_index, out var _cacheEntry) && _cacheEntry.ValidUntil < DateTime.UtcNow + TimeSpan.FromMinutes(cDataHistoryCollector.constMinutesUntilTokenIsInvalid))
{
_cacheEntry.LastUsed = DateTime.UtcNow;
lock (requestInfo)
requestInfo.M42WebClient = _cacheEntry.WebClient;
return _cacheEntry.WebClient;
}
}
if (Collector.TokenCache == null)
return null;
var _tokenInfo = await Collector.TokenCache.GetAsync(requestInfo.userInfo.Id, cF4SDTokenRegistration.enumTokenType.M42Bearer, requestInfo, LogDeep + 1);
if (_tokenInfo == null || !_tokenInfo.IsValid())
return null;
var client = new cM42WebClient(Collector.InfrastructureConfig.M42Wpm.Server, _lang);
client.SetBearerToken(_tokenInfo.secret);
var _reason = await client.Open();
if (_reason == eReason.ok)
{
lock (UserWebClientCache)
{
UserWebClientCache[_index] = new WebClientCacheEntry() { WebClient = client, LastUsed = DateTime.UtcNow, ValidUntil = _tokenInfo.validUntil };
}
lock (requestInfo)
requestInfo.M42WebClient = client;
return client;
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return null;
}
private void CleanupUserWebCache()
{
lock (UserWebClientCache)
{
var _del = new List<WebClientCacheIndex>();
foreach (var _entry in UserWebClientCache)
if (_entry.Value.LastUsed < DateTime.UtcNow - TimeSpan.FromMinutes(10) || _entry.Value.ValidUntil < DateTime.UtcNow)
_del.Add(_entry.Key);
foreach (var entry in _del)
UserWebClientCache.Remove(entry);
}
}
public override async Task<bool> DoScanAsync(bool Always, bool Rescan, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken Token, bool EnhancedDebug = 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 (Collector.M42WpmCollector is null)
return false;
Collector.DoProcessUiMessage(0, "");
if (!Always)
{
var scanInfo = await Collector.M42WpmCollector.GetScanTimeInfoAsync(requestInfo, LogDeep + 1, Token);
if (scanInfo?.LastScan is DateTime _lastScan && scanInfo?.NextScan is DateTime _nextScan)
{
if (_lastScan >= _nextScan)
{
Collector.DoProcessUiMessage(0, $"currently no scan needed for M42 api token cleanup, lastScan={_lastScan} (UTC), nextScan={_nextScan} (UTC)");
return false;
}
}
}
await CleanupApiTokensAsync(Token);
if (Token.IsCancellationRequested)
return false;
await Collector.SetLastScanTime("M42Scan-CleanupToken", DateTime.UtcNow, requestInfo, LogDeep + 1, Token);
return true;
}
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 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 override async Task<cScanTimeInfo> GetScanTimeInfoAsync(cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken Token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var scanTiming = new cDataHistoryScanTiming()
{
IsValid = true,
Interval = TimeSpan.FromDays(1),
Offset = TimeSpan.FromHours(1),
Timezone = TimeZoneInfo.Local
};
return await GetScanTimeInfoAsync(scanTiming, "M42Scan-CleanupToken", requestInfo, LogDeep + 1, Token);
}
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<bool> CheckLogonAsync(bool force, CancellationToken Token)
{
if (!force && WebClient.BearerToken != null)
return true;
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
if (Collector.InfrastructureConfig.M42Wpm == null)
return false;
Collector.DoProcessUiMessage(0, "");
Collector.DoProcessUiMessage(0, $"Start estabishing M42 WPM connection to server {Collector.InfrastructureConfig.M42Wpm.Server}...");
var resLogon = await WebClient.LogonWithApiKeyAsync(Collector.InfrastructureConfig.M42Wpm.Credential.NwCredential.Password);
if (resLogon == cM42WebClient.eReason.ok)
{
Collector.DoProcessUiMessage(0, "...M42 WPN connection established successful.");
StartOnlineValidation();
return true;
}
Collector.DoProcessUiMessage(1, $"Logon failed: {resLogon}");
}
catch (Exception E)
{
LogException(E);
}
finally
{
Collector.DoProcessUiMessage(0, "");
if (CM != null) LogMethodEnd(CM);
}
Collector.DoProcessUiMessage(0, "Error: Could not connect to M42 WPM.");
return false;
}
public async Task<bool> ValidateConnectionAsync(bool forceLogon, CancellationToken Token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
await _OnlineCheckCriticalSection.Semaphore.WaitAsync(Token);
try
{
var CheckResult = true;
if (!IsOnline || forceLogon)
CheckResult = await CheckLogonAsync(true, Token);
if (CheckResult)
{
var resWeb = await WebClient.HttpEnh.GetAsync(constUrlIsAlive, Token);
CheckResult = resWeb != null && resWeb.IsSuccessStatusCode;
if (forceLogon)
{
if (CheckResult)
Collector.DoProcessUiMessage(0, "...F4SD web api 'is alive' is reachable.");
else
Collector.DoProcessUiMessage(0, "Error: F4SD web api 'is alive' is not reachable. Maybe F4SD support is not installed or wrong version.", LogLevels.Error);
}
}
IsOnline = CheckResult;
if (onlineTimer != null)
onlineTimer.Change(30000, 60000);
return IsOnline;
}
catch (Exception E)
{
LogException(E);
}
finally
{
_OnlineCheckCriticalSection.Semaphore.Release();
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return false;
}
private enumTicketStatus ConvertM42TicketCode(int M42TicketStatus)
{
try
{
switch (M42TicketStatus)
{
case 200:
return enumTicketStatus.New;
case 201:
case 202:
return enumTicketStatus.InProgress;
case 203:
return enumTicketStatus.OnHold;
case 204:
return enumTicketStatus.Closed;
}
}
catch (Exception E)
{
LogException(E);
}
return enumTicketStatus.Unknown;
}
public async Task<List<cF4SDTicketSummary>> GetTicketsFromSid(cF4sdConnectorIds UserId, CancellationToken Token, cF4sdWebRequestInfo requestInfo)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
if (!await CheckOnline())
return null;
var objSid = new SecurityIdentifier(UserId.sid, 0);
var strSid = objSid.ToString();
var queueOption = (int)Collector.InfrastructureConfig.M42Wpm.ActivityQueueFilterOption;
var strUrl = string.Format(constUrlGetTickets,
strSid,
Collector.InfrastructureConfig.M42Wpm.ClosedTicketHistory,
queueOption);
if (queueOption != 0)
{
var encodedQueues = string.Join("|",
Collector.InfrastructureConfig.M42Wpm.ActivityQueues.Select(q =>
string.Format("{0}:{1}",
HttpUtility.UrlEncode(q.QueueName),
HttpUtility.UrlEncode(q.QueueID.ToString())
)
)
);
strUrl += string.Format(constUrlGetTicketsQueuesParam, encodedQueues);
}
var _wc = await GetWebClient(requestInfo, Token);
var res = await _wc.HttpEnh.GetAsync(strUrl);
if (res.IsSuccessStatusCode)
{
var strJson = await res.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(strJson))
{
var ticketInfoList = JsonConvert.DeserializeObject<List<cF4SDTicketSummary>>(strJson);
if (!(ticketInfoList?.Count > 0))
return null;
foreach (var Entry in ticketInfoList)
Entry.UserId = UserId.Id;
return ticketInfoList;
}
}
StartOnlineValidation();
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return null;
}
public async Task<List<cF4sdApiSearchResultRelation>> getTicketUsage(List<cF4sdConnectorIds> lstTicketIds, CancellationToken Token, cF4sdWebRequestInfo requestInfo, int LogDeep)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var lstTasks = new List<Task<List<cF4SDTicketSummary>>>();
foreach (var Entry in lstTicketIds)
lstTasks.Add(GetTicketsFromSid(Entry, Token, requestInfo));
var result = await Task.WhenAll(lstTasks);
if (result == null)
return null;
var retVal = new Dictionary<string, cF4SDTicketSummary>();
foreach (var Entry in result)
if (Entry != null)
{
foreach (var Entry2 in Entry)
{
if (Entry2.IsPrimaryAccount)
retVal[Entry2.Name] = Entry2;
else if (!retVal.ContainsKey(Entry2.Name))
retVal.Add(Entry2.Name, Entry2);
}
}
if (retVal.Count > 0)
{
var ticketResult = new List<cF4sdApiSearchResultRelation>(retVal.Count);
foreach (var Entry in retVal.Values)
{
var Infos = new Dictionary<string, string>()
{
{ "Summary", Entry.Summary },
{ "ActivityType", Entry.ActivityType },
{ "Status", Entry.Status },
{ "StatusId", ConvertM42TicketCode(Entry.StatusId).ToString() },
{ "Asset", Entry.AssetName },
{ "ServiceName", Entry.ServiceName },
{ "ServiceId", Entry.ServiceId.ToString() },
{ "AssetType", Entry.AssetCIName }
};
var ticketInfo = new cF4sdApiSearchResultRelation()
{
Type = enumF4sdSearchResultClass.Ticket,
Name = Entry.Name,
DisplayName = Entry.Name,
id = Entry.TicketObjectId,
Status = enumF4sdSearchResultStatus.Active,
Infos = Infos,
Identities = new cF4sdIdentityList()
{
new cF4sdIdentityEntry(){ Class = enumFasdInformationClass.User, Id = Entry.UserId},
new cF4sdIdentityEntry(){ Class = enumFasdInformationClass.Ticket, Id = Entry.TicketObjectId}
}
};
ticketResult.Add(ticketInfo);
}
return ticketResult;
}
}
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 TimeSpan GetTicketOverviewCacheDuration(bool useRoleScope)
{
var ticketConfig = Collector?.GetGlobalConfig()?.TicketConfiguration;
var minutes = useRoleScope
? ticketConfig?.OverviewPollingRole ?? cF4sdTicketConfig.DefaultOverviewPollingRole
: ticketConfig?.OverviewPollingPersonal ?? cF4sdTicketConfig.DefaultOverviewPollingPersonal;
if (minutes < 1)
minutes = 1;
return TimeSpan.FromMinutes(minutes);
}
private bool TryGetTicketOverviewPersonalCache(string sid, DateTime now, out Dictionary<string, int> counts)
{
counts = null;
if (string.IsNullOrWhiteSpace(sid))
return false;
lock (_ticketOverviewCacheLock)
{
if (_ticketOverviewPersonalCache.TryGetValue(sid, out var entry))
{
if (entry.ExpiresAtUtc > now)
{
counts = new Dictionary<string, int>(entry.Counts, StringComparer.OrdinalIgnoreCase);
return true;
}
_ticketOverviewPersonalCache.Remove(sid);
}
}
return false;
}
private bool TryGetTicketOverviewRoleCache(Guid roleId, DateTime now, out Dictionary<string, int> counts)
{
counts = null;
if (roleId == Guid.Empty)
return false;
lock (_ticketOverviewCacheLock)
{
if (_ticketOverviewRoleCache.TryGetValue(roleId, out var entry))
{
if (entry.ExpiresAtUtc > now)
{
counts = new Dictionary<string, int>(entry.Counts, StringComparer.OrdinalIgnoreCase);
return true;
}
_ticketOverviewRoleCache.Remove(roleId);
}
}
return false;
}
private void SetTicketOverviewPersonalCache(string sid, Dictionary<string, int> counts, DateTime expiresAtUtc)
{
if (string.IsNullOrWhiteSpace(sid))
return;
lock (_ticketOverviewCacheLock)
{
_ticketOverviewPersonalCache[sid] = new TicketOverviewCountCacheEntry
{
Counts = new Dictionary<string, int>(counts ?? new Dictionary<string, int>(), StringComparer.OrdinalIgnoreCase),
ExpiresAtUtc = expiresAtUtc
};
}
}
private void SetTicketOverviewRoleCache(Guid roleId, Dictionary<string, int> counts, DateTime expiresAtUtc)
{
if (roleId == Guid.Empty)
return;
lock (_ticketOverviewCacheLock)
{
_ticketOverviewRoleCache[roleId] = new TicketOverviewCountCacheEntry
{
Counts = new Dictionary<string, int>(counts ?? new Dictionary<string, int>(), StringComparer.OrdinalIgnoreCase),
ExpiresAtUtc = expiresAtUtc
};
}
}
private bool TryGetTicketOverviewRoleIdsFromCache(string sid, DateTime now, out List<Guid> roleIds)
{
roleIds = null;
if (string.IsNullOrWhiteSpace(sid))
return false;
lock (_ticketOverviewCacheLock)
{
if (_ticketOverviewRoleListCache.TryGetValue(sid, out var entry))
{
if (entry.ExpiresAtUtc > now)
{
roleIds = new List<Guid>(entry.RoleIds);
return true;
}
_ticketOverviewRoleListCache.Remove(sid);
}
}
return false;
}
private void SetTicketOverviewRoleIdsCache(string sid, IEnumerable<Guid> roleIds, DateTime expiresAtUtc)
{
if (string.IsNullOrWhiteSpace(sid))
return;
var normalized = (roleIds ?? Enumerable.Empty<Guid>())
.Where(id => id != Guid.Empty)
.Distinct()
.ToList();
lock (_ticketOverviewCacheLock)
{
_ticketOverviewRoleListCache[sid] = new TicketOverviewRoleListCacheEntry
{
RoleIds = normalized,
ExpiresAtUtc = expiresAtUtc
};
}
}
private async Task<List<Guid>> GetTicketOverviewRoleIdsAsync(string sid, DateTime now, TimeSpan ttl, CancellationToken token)
{
if (TryGetTicketOverviewRoleIdsFromCache(sid, now, out var cached))
return cached;
var userInfo = await GetM42UserInfoAsync(sid, token);
var roles = userInfo?.Roles ?? new List<M42UserUserInfo.M42Role>();
var roleIds = roles
.Where(r => r != null && r.Id != Guid.Empty)
.Select(r => r.Id)
.Distinct()
.ToList();
SetTicketOverviewRoleIdsCache(sid, roleIds, now.Add(ttl));
return roleIds;
}
private async Task<Dictionary<Guid, Dictionary<string, int>>> FetchTicketOverviewCountsByRolesAsync(
IEnumerable<Guid> roleIds,
IReadOnlyCollection<string> requestedKeys,
cF4sdWebRequestInfo requestInfo,
int logDeep,
CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(logDeep, CM, requestInfo.id, requestInfo.created); }
var startTime = DateTime.UtcNow;
try
{
var roleList = (roleIds ?? Enumerable.Empty<Guid>())
.Where(id => id != Guid.Empty)
.Distinct()
.ToList();
if (roleList.Count == 0)
return new Dictionary<Guid, Dictionary<string, int>>();
var request = new TicketOverviewCountsByRolesRequest
{
Sid = requestInfo?.userInfo?.AdSid,
RoleGuids = roleList,
Keys = requestedKeys?.Where(k => !string.IsNullOrWhiteSpace(k)).ToList() ?? new List<string>()
};
var jsonBody = JsonConvert.SerializeObject(request, Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
var wc = await GetWebClient(requestInfo, token);
var res = await wc.HttpEnh.PostAsync(constUrlGetTicketOverviewCountsByRoles, content, token);
if (token.IsCancellationRequested)
return new Dictionary<Guid, Dictionary<string, int>>();
if (res?.IsSuccessStatusCode == true)
{
var json = await res.Content.ReadAsStringAsync();
if (!string.IsNullOrWhiteSpace(json))
{
var response = JsonConvert.DeserializeObject<TicketOverviewCountsByRolesResponse>(json);
if (response?.CountsByRole != null)
{
var result = new Dictionary<Guid, Dictionary<string, int>>();
foreach (var entry in response.CountsByRole)
{
if (!Guid.TryParse(entry.Key, out var roleId) || roleId == Guid.Empty)
continue;
var counts = entry.Value ?? new Dictionary<string, int>();
result[roleId] = new Dictionary<string, int>(counts, StringComparer.OrdinalIgnoreCase);
}
return result;
}
}
}
StartOnlineValidation();
}
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 new Dictionary<Guid, Dictionary<string, int>>();
}
private Dictionary<string, int> SumTicketOverviewCounts(IEnumerable<Dictionary<string, int>> sources)
{
var result = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
if (sources == null)
return result;
foreach (var counts in sources)
{
if (counts == null)
continue;
foreach (var kvp in counts)
{
if (string.IsNullOrWhiteSpace(kvp.Key))
continue;
result[kvp.Key] = result.TryGetValue(kvp.Key, out var existing)
? existing + kvp.Value
: kvp.Value;
}
}
return result;
}
private Dictionary<string, int> FilterTicketOverviewCounts(Dictionary<string, int> counts, IReadOnlyCollection<string> requestedKeys)
{
if (counts == null)
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
if (requestedKeys == null || requestedKeys.Count == 0)
return new Dictionary<string, int>(counts, StringComparer.OrdinalIgnoreCase);
var filtered = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
foreach (var key in requestedKeys)
{
if (string.IsNullOrWhiteSpace(key))
continue;
filtered[key] = counts.TryGetValue(key, out var value) ? value : 0;
}
return filtered;
}
private async Task<Dictionary<string, int>> FetchTicketOverviewCountsAsync(
string sid,
string scope,
IReadOnlyCollection<string> requestedKeys,
cF4sdWebRequestInfo requestInfo,
CancellationToken token)
{
try
{
var keyParam = requestedKeys != null && requestedKeys.Count > 0
? HttpUtility.UrlEncode(string.Join(",", requestedKeys))
: null;
var url = string.Format(constUrlGetTicketOverviewCounts, HttpUtility.UrlEncode(sid), scope, keyParam ?? string.Empty);
if (string.IsNullOrWhiteSpace(keyParam))
{
url = $"m42Services/api/c4itf4sdwebapi/getticketoverviewcounts?sid={HttpUtility.UrlEncode(sid)}&scope={scope}";
}
var wc = await GetWebClient(requestInfo, token);
var res = await wc.HttpEnh.GetAsync(url, token);
if (token.IsCancellationRequested)
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
if (res?.IsSuccessStatusCode == true)
{
var json = await res.Content.ReadAsStringAsync();
if (!string.IsNullOrWhiteSpace(json))
{
var root = JsonConvert.DeserializeObject<JObject>(json);
var countsToken = root?["counts"] as JObject;
var counts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
if (countsToken != null)
{
foreach (var prop in countsToken.Properties())
{
if (prop?.Name == null)
continue;
var value = prop.Value?.Type == JTokenType.Integer
? prop.Value.Value<int>()
: int.TryParse(prop.Value?.ToString(), out var parsed) ? parsed : 0;
counts[prop.Name] = value;
}
}
return counts;
}
}
StartOnlineValidation();
}
catch (Exception E)
{
LogException(E);
}
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
}
public async Task<Dictionary<string, int>> GetTicketOverviewCountsAsync(IEnumerable<string> keys, bool useRoleScope, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken Token)
{
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 (!await CheckOnline())
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
var sid = requestInfo?.userInfo?.AdSid;
if (string.IsNullOrWhiteSpace(sid))
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
var normalizedKeys = (keys ?? Enumerable.Empty<string>())
.Where(k => !string.IsNullOrWhiteSpace(k))
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
var now = DateTime.UtcNow;
var ttl = GetTicketOverviewCacheDuration(useRoleScope);
if (!useRoleScope)
{
if (TryGetTicketOverviewPersonalCache(sid, now, out var cachedPersonal))
return FilterTicketOverviewCounts(cachedPersonal, normalizedKeys);
var counts = await FetchTicketOverviewCountsAsync(sid, "personal", normalizedKeys, requestInfo, Token);
if (Token.IsCancellationRequested)
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
SetTicketOverviewPersonalCache(sid, counts, now.Add(ttl));
return FilterTicketOverviewCounts(counts, normalizedKeys);
}
var roleIds = await GetTicketOverviewRoleIdsAsync(sid, now, ttl, Token);
if (roleIds == null || roleIds.Count == 0)
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
var countsByRole = new Dictionary<Guid, Dictionary<string, int>>();
var missingRoles = new List<Guid>();
foreach (var roleId in roleIds)
{
if (TryGetTicketOverviewRoleCache(roleId, now, out var cachedRole))
{
countsByRole[roleId] = cachedRole;
}
else
{
missingRoles.Add(roleId);
}
}
if (missingRoles.Count > 0)
{
var fetched = await FetchTicketOverviewCountsByRolesAsync(missingRoles, normalizedKeys, requestInfo, LogDeep + 1, Token);
var expiresAt = DateTime.UtcNow.Add(ttl);
foreach (var roleId in missingRoles)
{
if (!fetched.TryGetValue(roleId, out var roleCounts))
roleCounts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
SetTicketOverviewRoleCache(roleId, roleCounts, expiresAt);
countsByRole[roleId] = roleCounts;
}
}
var summed = SumTicketOverviewCounts(countsByRole.Values);
return FilterTicketOverviewCounts(summed, normalizedKeys);
}
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 new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
}
public async Task<List<cF4sdApiSearchResultRelation>> GetTicketOverviewRelationsAsync(string key, bool useRoleScope, int count, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken Token)
{
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 (!await CheckOnline())
return new List<cF4sdApiSearchResultRelation>();
if (string.IsNullOrWhiteSpace(key))
return new List<cF4sdApiSearchResultRelation>();
var sid = requestInfo?.userInfo?.AdSid;
if (string.IsNullOrWhiteSpace(sid))
return new List<cF4sdApiSearchResultRelation>();
var scope = useRoleScope ? "role" : "personal";
var url = string.Format(
constUrlGetTicketOverviewRelations,
HttpUtility.UrlEncode(sid),
scope,
HttpUtility.UrlEncode(key),
Math.Max(0, count)
);
var wc = await GetWebClient(requestInfo, Token);
var res = await wc.HttpEnh.GetAsync(url, Token);
if (Token.IsCancellationRequested)
return new List<cF4sdApiSearchResultRelation>();
if (res?.IsSuccessStatusCode == true)
{
var json = await res.Content.ReadAsStringAsync();
if (!string.IsNullOrWhiteSpace(json))
{
var relations = JsonConvert.DeserializeObject<List<cF4sdApiSearchResultRelation>>(json);
if (relations != null)
{
await EnsureTicketOverviewRelationIdentitiesAsync(relations, requestInfo, LogDeep + 1, Token);
return relations;
}
}
}
StartOnlineValidation();
}
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 new List<cF4sdApiSearchResultRelation>();
}
private async Task EnsureTicketOverviewRelationIdentitiesAsync(
List<cF4sdApiSearchResultRelation> relations,
cF4sdWebRequestInfo requestInfo,
int logDeep,
CancellationToken token)
{
if (relations == null)
return;
foreach (var relation in relations)
{
if (token.IsCancellationRequested || relation == null)
return;
var identities = relation.Identities ?? new cF4sdIdentityList();
relation.Identities = identities;
if (!identities.Any(i => i.Class == enumFasdInformationClass.Ticket) && relation.id != Guid.Empty)
{
identities.Add(new cF4sdIdentityEntry
{
Class = enumFasdInformationClass.Ticket,
Id = relation.id
});
}
if (relation.Infos == null)
relation.Infos = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
if (!relation.Infos.ContainsKey("Sids") && relation.Infos.TryGetValue("UserSid", out var userSid) && !string.IsNullOrWhiteSpace(userSid))
relation.Infos["Sids"] = userSid;
Guid userId = Guid.Empty;
if (relation.Infos.Count > 0)
{
if (relation.Infos.TryGetValue("Sids", out var sidsValue))
{
var sids = sidsValue?.Split(',')
.Select(v => v.Trim())
.Where(v => !string.IsNullOrWhiteSpace(v))
.ToList();
if (sids != null && sids.Count > 0)
{
var resolved = await Collector.UserSearchBySidsAsync(sids, token, requestInfo, logDeep + 1);
var user = resolved?.Values?.FirstOrDefault()?.FirstOrDefault();
if (user?.Result != null)
userId = user.Result.id;
}
}
if (userId == Guid.Empty && relation.Infos.TryGetValue("UserAccount", out var userAccount))
{
relation.Infos.TryGetValue("UserDomain", out var userDomain);
if (!string.IsNullOrWhiteSpace(userAccount))
{
var resolved = await Collector.GetUserIdFromAccountAsync(userAccount, userDomain, requestInfo, logDeep + 1, token);
if (resolved.HasValue)
userId = resolved.Value;
}
}
if (userId == Guid.Empty)
{
if (relation.Infos.TryGetValue("UserId", out var userIdString) ||
relation.Infos.TryGetValue("UserGuid", out userIdString) ||
relation.Infos.TryGetValue("UserIdentityId", out userIdString))
{
Guid.TryParse(userIdString, out userId);
}
}
}
if (userId == Guid.Empty)
continue;
identities.RemoveAll(i => i.Class == enumFasdInformationClass.User);
identities.Add(new cF4sdIdentityEntry
{
Class = enumFasdInformationClass.User,
Id = userId
});
relation.Infos["UserId"] = userId.ToString();
relation.Infos["UserGuid"] = userId.ToString();
}
}
public override async Task<List<cF4SDHealthCardRawData.cHealthCardTable>> GetTableResultsVirtualAsync(List<cDataHistoryConfigTable> Tables, Dictionary<enumFasdInformationClass, cF4sdConnectorIds> Identities, DateTime RefTime, int MaxAge, bool instantly, Guid? CacheId, CancellationToken Token, cF4sdWebRequestInfo requestInfo, int LogDeep)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
if (!await CheckOnline())
return null;
var bMainExists = Tables.Exists(v => v.Name == constTableNameTicketDetails && v.ParentCluster?.Origin == enumDataHistoryOrigin.M42Wpm);
var bHistoryExists = Tables.Exists(v => v.Name == constTableNameTicketHistory && v.ParentCluster?.Origin == enumDataHistoryOrigin.M42Wpm);
var bUserInfoExists = Tables.Exists(v => v.Name == constTableNameUserTicket && v.ParentCluster?.Origin == enumDataHistoryOrigin.M42Wpm);
var bPickupsExists = Tables.Exists(v => v.ParentCluster?.Origin == enumDataHistoryOrigin.M42Wpm && v.SubTables?.Count == 1 && v.SubTables.Values.First().Template is cDataHistoryConfigQueryTemplateM42Pickup);
if (!bMainExists && !bHistoryExists && !bUserInfoExists && !bPickupsExists)
return null;
if (!Identities.TryGetValue(enumFasdInformationClass.Ticket, out var idTicket))
{
bMainExists = false;
bHistoryExists = false;
}
if (!bMainExists && !bHistoryExists && !bUserInfoExists && !bPickupsExists)
return null;
var listTasks = new List<Task<List<cF4SDHealthCardRawData.cHealthCardTable>>>(2);
if (bMainExists && CacheId == null)
listTasks.Add(Task.Run<List<cF4SDHealthCardRawData.cHealthCardTable>>(async () => { return await GetTicketMainTableAsync(idTicket.Id, requestInfo, LogDeep + 1, Token); }));
if (bHistoryExists && (instantly || CacheId != null))
listTasks.Add(Task.Run<List<cF4SDHealthCardRawData.cHealthCardTable>>(async () => { return await GetTicketHistoryTableAsync(idTicket.Id, requestInfo, LogDeep + 1, Token); }));
if (bUserInfoExists && (CacheId == null))
listTasks.Add(Task.Run<List<cF4SDHealthCardRawData.cHealthCardTable>>(async () => { return await GetUserTicketAsync(Identities, Token, requestInfo, LogDeep + 1); }));
if (bPickupsExists && (instantly || CacheId != null))
{
foreach (var _table in Tables)
{
if (_table.ParentCluster?.Origin != enumDataHistoryOrigin.M42Wpm)
continue;
if (!(_table.SubTables.Values.First()?.Template is cDataHistoryConfigQueryTemplateM42Pickup))
continue;
listTasks.Add(Task.Run<List<cF4SDHealthCardRawData.cHealthCardTable>>(async () => { return await GetUserPickupValuesAsync(_table, requestInfo, LogDeep + 1, Token); }));
}
}
var arrRes = await Task.WhenAll(listTasks.ToArray());
var retVal = new List<cF4SDHealthCardRawData.cHealthCardTable>();
foreach (var Entry in arrRes)
if (Entry != null)
retVal.AddRange(Entry);
// add the incomplete tables
if (CacheId == null)
{
if (bHistoryExists)
retVal.Add(new cF4SDHealthCardRawData.cHealthCardTable()
{
Name = constTableNameTicketHistory,
InformationClass = enumFasdInformationClass.Ticket,
Origin = enumDataHistoryOrigin.M42Wpm,
IsIncomplete = true
});
foreach (var _table in Tables)
{
if (_table.ParentCluster?.Origin != enumDataHistoryOrigin.M42Wpm)
continue;
if (!(_table.SubTables.Values.First()?.Template is cDataHistoryConfigQueryTemplateM42Pickup))
continue;
retVal.Add(new cF4SDHealthCardRawData.cHealthCardTable()
{
Name = _table.Name,
InformationClass = _table.ParentCluster.InformationClass,
Origin = _table.ParentCluster.Origin,
IsIncomplete = true
});
}
}
if (retVal.Count == 0)
return null;
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<List<cF4SDHealthCardRawData.cHealthCardTable>> GetTicketMainTableAsync(Guid TicketId, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken Token)
{
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 (!Collector.ClusterConfig.Tables.TryGetValue(constTableNameTicketDetails, out var M42TableDetails))
return null;
var strUrl = string.Format(constUrlGetTicketDetails, TicketId);
var _wc = await GetWebClient(requestInfo, Token);
var res = await _wc.HttpEnh.GetAsync(strUrl);
if (cLogManager.DefaultLogger.IsDebug) LogEntry("SpecialDebug GetTicketMainTableAsync #1");
if (res?.IsSuccessStatusCode == true)
{
var strJson = await res.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(strJson))
{
if (cLogManager.DefaultLogger.IsDebug) LogEntry("SpecialDebug GetTicketMainTableAsync #2");
JObject ticketInfos = JsonConvert.DeserializeObject<JObject>(strJson);
var retVal = new cF4SDHealthCardRawData.cHealthCardTable()
{
Name = constTableNameTicketDetails,
InformationClass = enumFasdInformationClass.Ticket,
Origin = enumDataHistoryOrigin.M42Wpm,
IsStatic = true,
TableType = eDataHistoryTableType.Static
};
var dicVals = new Dictionary<string, object>();
var vals = ticketInfos.Children();
if (cLogManager.DefaultLogger.IsDebug) LogEntry("SpecialDebug GetTicketMainTableAsync #3");
foreach (var token in vals)
{
try
{
if (token is JProperty prop)
if (prop.Value is JValue val)
dicVals[prop.Name] = val.Value;
}
catch (Exception E)
{
LogEntry($"Error getting M42 ticket detail property '{token.Path}'", LogLevels.Error);
LogException(E);
}
}
if (cLogManager.DefaultLogger.IsDebug) LogEntry("SpecialDebug GetTicketMainTableAsync #4");
foreach (var colInfo in M42TableDetails.Columns.Values)
{
try
{
if (!dicVals.TryGetValue(colInfo.SourceName, out var objVal))
objVal = null;
objVal = ConvertToF4sdType(objVal, colInfo.ValueType);
var _col = new cF4SDHealthCardRawData.cHealthCardTableColumn(retVal) { ColumnName = colInfo.Name, Values = new List<object>(1) { objVal } };
if (colInfo.IsWritable && colInfo.SourceName == "SolutionHtml")
_col.IsWritable = true;
retVal.Columns[colInfo.Name] = _col;
}
catch { }
}
if (cLogManager.DefaultLogger.IsDebug) LogEntry("SpecialDebug GetTicketMainTableAsync #5");
return new List<cF4SDHealthCardRawData.cHealthCardTable>(1) { retVal };
}
else
{
LogEntry($"Could not get detailed ticket information for ticket wit id {TicketId}. Ticket content is empty.", LogLevels.Warning);
}
}
else
{
cLogManager.DefaultLogger.LogHttpResponseMessage(res, $"Could not get detailed ticket information for ticket wit id {TicketId}.", LogLevels.Warning);
}
if (cLogManager.DefaultLogger.IsDebug) LogEntry("SpecialDebug GetTicketMainTableAsync #6");
StartOnlineValidation();
if (cLogManager.DefaultLogger.IsDebug) LogEntry("SpecialDebug GetTicketMainTableAsync #7");
}
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 object ConvertToF4sdType(object objVal, enumFasdValueType ValueType)
{
try
{
if (objVal != null)
{
switch (ValueType)
{
case enumFasdValueType.INT:
return cF4SDHealthCardRawData.GetInteger(objVal);
case enumFasdValueType.GUID:
return cXmlParser.GetGuidFromString(objVal.ToString());
case enumFasdValueType.BOOLEAN:
if (objVal == null) return false;
if (objVal is bool) return (bool)objVal;
if (objVal is int) return (int)objVal != 0;
if (objVal is string) return bool.TryParse((string)objVal, out bool result) ? result : ((string)objVal == "1");
return false; // Standardrückgabewert, falls keine Bedingung zutrifft
case enumFasdValueType.DATETIME:
DateTime? dt = null;
if (objVal is DateTime _dt)
dt = _dt;
else
{
if (DateTime.TryParse(objVal.ToString(), out _dt))
dt = _dt;
}
if (dt is DateTime _dt2)
{
if (_dt2 == new DateTime(1, 1, 1, 0, 0, 0))
dt = null;
}
return dt;
default:
return objVal.ToString();
}
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
}
return null;
}
private async Task<List<cF4SDHealthCardRawData.cHealthCardTable>> GetTicketHistoryTableAsync(Guid TicketId, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken Token)
{
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 (!Collector.ClusterConfig.Tables.TryGetValue(constTableNameTicketHistory, out var M42TableDetails))
return null;
var strUrl = string.Format(constUrlGetTicketHistory, TicketId);
var _wc = await GetWebClient(requestInfo, Token);
var res = await _wc.HttpEnh.GetAsync(strUrl);
if (res?.IsSuccessStatusCode == true)
{
var strJson = await res.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(strJson))
{
JContainer ticketInfos = JsonConvert.DeserializeObject<JContainer>(strJson);
var retVal = new cF4SDHealthCardRawData.cHealthCardTable()
{
Name = constTableNameTicketHistory,
InformationClass = enumFasdInformationClass.Ticket,
Origin = enumDataHistoryOrigin.M42Wpm,
IsStatic = false,
TableType = eDataHistoryTableType.HistoryEvents
};
var hLength = ticketInfos.Count;
retVal.Columns = new Dictionary<string, cF4SDHealthCardRawData.cHealthCardTableColumn>(M42TableDetails.Columns.Count);
foreach (var colInfo in M42TableDetails.Columns.Values)
{
retVal.Columns[colInfo.Name] = new cF4SDHealthCardRawData.cHealthCardTableColumn(retVal)
{
ColumnName = colInfo.Name,
Values = new List<object>(hLength)
};
}
foreach (var Entry in ticketInfos)
{
var dicVals = new Dictionary<string, object>();
var vals = Entry.Children();
foreach (var token in vals)
{
try
{
if (token is JProperty prop)
if (prop.Value is JValue val)
dicVals[prop.Name] = val.Value;
}
catch (Exception E)
{
LogEntry($"Error getting M42 ticket detail property '{token.Path}'", LogLevels.Error);
LogException(E);
}
}
foreach (var col in M42TableDetails.Columns.Values)
{
if (!retVal.Columns.TryGetValue(col.Name, out var dataCol))
continue;
if (dicVals.TryGetValue(col.SourceName, out var _val))
{
_val = ConvertToF4sdType(_val, col.ValueType);
dataCol.Values.Add(_val);
}
else
dataCol.Values.Add(null);
}
}
return new List<cF4SDHealthCardRawData.cHealthCardTable>(1) { retVal };
}
}
StartOnlineValidation();
}
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<List<cF4SDHealthCardRawData.cHealthCardTable>> GetUserTicketAsync(Dictionary<enumFasdInformationClass, cF4sdConnectorIds> Identities, CancellationToken Token, cF4sdWebRequestInfo requestInfo, int LogDeep)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
// get table definition
if (!Collector.ClusterConfig.Tables.TryGetValue(constTableNameUserTicket, out var tableConfig))
return null;
// get the user sid
if (!Identities.TryGetValue(enumFasdInformationClass.User, out var idUser))
return null;
var strSid = new SecurityIdentifier(idUser.sid, 0).ToString();
// get the asset name, if computer is in Identities
if (!Identities.TryGetValue(enumFasdInformationClass.Computer, out var idComuter))
idComuter = null;
// create the api url
var strOpt = "";
if (idComuter != null && !string.IsNullOrEmpty(idComuter.name))
strOpt = string.Format(constUrlGetCreateTicketAssetParam, HttpUtility.UrlEncode(idComuter.name));
var strUrl = string.Format(constUrlGetCreateTicket, HttpUtility.UrlEncode(strSid), strOpt);
// call the api
var _wc = await GetWebClient(requestInfo, Token);
var res = await _wc.HttpEnh.GetAsync(strUrl);
if (res?.IsSuccessStatusCode == true)
{
var strJson = await res.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(strJson))
{
// construct the result
JObject ticketInfos = JsonConvert.DeserializeObject<JObject>(strJson);
var retVal = new cF4SDHealthCardRawData.cHealthCardTable()
{
Name = constTableNameUserTicket,
InformationClass = enumFasdInformationClass.User,
Origin = enumDataHistoryOrigin.M42Wpm,
IsStatic = true,
TableType = eDataHistoryTableType.Static
};
var dicVals = new Dictionary<string, object>();
var vals = ticketInfos.Children();
foreach (var token in vals)
{
try
{
if (token is JProperty prop)
if (prop.Value is JValue val)
dicVals[prop.Name] = val.Value;
}
catch (Exception E)
{
LogEntry($"Error getting M42 ticket detail property '{token.Path}'", LogLevels.Error);
LogException(E);
}
}
foreach (var colInfo in tableConfig.Columns.Values)
{
try
{
object objVal = null;
if (colInfo.Name == "id")
objVal = idUser.sid;
else if (!dicVals.TryGetValue(colInfo.SourceName, out objVal))
objVal = null;
objVal = ConvertToF4sdType(objVal, colInfo.ValueType);
retVal.Columns[colInfo.Name] = new cF4SDHealthCardRawData.cHealthCardTableColumn(retVal) { ColumnName = colInfo.Name, Values = new List<object>(1) { objVal } };
}
catch { }
}
return new List<cF4SDHealthCardRawData.cHealthCardTable>(1) { retVal };
}
}
StartOnlineValidation();
}
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<List<cF4SDHealthCardRawData.cHealthCardTable>> GetUserPickupValuesAsync(cDataHistoryConfigTable TableConfig, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken Token)
{
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 (!(TableConfig?.SubTables.Count > 0))
return null;
if (!(TableConfig.SubTables.Values.First().Template is cDataHistoryConfigQueryTemplateM42Pickup _template))
return null;
// create the api url
var colInfo = new List<string>();
foreach (var _colInfo in TableConfig.Columns.Values)
{
colInfo.Add(_colInfo.SourceName);
}
var columns = string.Join(",", colInfo);
var where = _template.FilteredGroup == -1 ? "" : string.Format("StateGroup = '{0}'", _template.FilteredGroup);
var _strUrl = string.Format(constUrlFragmentsGetList, _template.PickupName, where, columns, string.Empty, string.Empty, string.Empty);
_strUrl = RemoveEmptyQueryParameters(_strUrl);
// call the api
var _wc = await GetWebClient(requestInfo, Token);
var res = await _wc.HttpEnh.GetAsync(_strUrl);
if (res?.IsSuccessStatusCode == true)
{
var strJson = await res.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(strJson))
{
// construct the result
JArray PickupResult = JsonConvert.DeserializeObject<JArray>(strJson);
var retVal = new cF4SDHealthCardRawData.cHealthCardTable()
{
Name = TableConfig.Name,
InformationClass = enumFasdInformationClass.User,
Origin = enumDataHistoryOrigin.M42Wpm,
IsStatic = true,
TableType = eDataHistoryTableType.Static
};
var _dicColInfo = new Dictionary<string, cDataHistoryConfigColumnBase>(TableConfig.Columns.Count);
var _dicIndex = new Dictionary<string, int>(TableConfig.Columns.Count);
var _lstResultCols = new List<cHealthCardTableColumn>(TableConfig.Columns.Count);
var _idxPosition = -1;
var _idxName = -1;
var _i = 0;
foreach (var _colInfo in TableConfig.Columns.Values)
{
var _col = new cF4SDHealthCardRawData.cHealthCardTableColumn(retVal) { ColumnName = _colInfo.Name };
retVal.Columns[_colInfo.Name] = _col;
_dicColInfo[_colInfo.SourceName] = _colInfo;
_dicIndex[_colInfo.SourceName] = _i;
_lstResultCols.Add(_col);
if (_colInfo.SourceName == "Position")
_idxPosition = _i;
if (_colInfo.SourceName == "DisplayString")
_idxName = _i;
_i++;
}
var _result = new List<object[]>();
foreach (var _row in PickupResult)
{
var _s = _row.ToString();
try
{
// get the row values from JSON result
var IdsValid = true;
var _resultRow = new object[TableConfig.Columns.Count];
_resultRow.Initialize();
foreach (var _col in _row)
{
if (_col is JProperty prop)
if (prop.Value is JValue val)
{
if (_dicColInfo.TryGetValue(prop.Name, out var _colInfo))
if (_dicIndex.TryGetValue(prop.Name, out var _idx))
{
var objVal = ConvertToF4sdType(val.Value, _colInfo.ValueType);
if (TableConfig.KeyColumns.Contains(_colInfo))
if (objVal == null || objVal is string _str && _str == string.Empty)
IdsValid = false;
_resultRow[_idx] = objVal;
}
}
}
if (!IdsValid)
continue;
_result.Add(_resultRow);
}
catch (Exception E)
{
LogEntry($"Error getting M42 pickup values for tale {TableConfig.Name} at '{_row}'", LogLevels.Error);
LogException(E);
}
}
// sort the result
switch (_template.Sorting)
{
case cDataHistoryConfigQueryTemplateM42Pickup.enumSorting.byPosition:
if (_idxPosition >= 0)
try
{
_result.Sort((x, y) =>
{
var xVal = x[_idxPosition];
var yVal = y[_idxPosition];
// Wenn x null ist und y nicht, soll y zuerst kommen (x ist also größer)
if (xVal == null && yVal != null) return 1;
// Wenn y null ist und x nicht, soll x zuerst kommen (x ist also kleiner)
if (xVal != null && yVal == null) return -1;
// Wenn beide null sind, sind sie gleich
if (xVal == null && yVal == null) return 0;
// Wenn keines der beiden null ist, normal vergleichen
return ((Int32)xVal).CompareTo((Int32)yVal);
});
}
catch { }
break;
case cDataHistoryConfigQueryTemplateM42Pickup.enumSorting.byName:
if (_idxName >= 0)
try
{
_result.Sort((x, y) => ((string)(x[_idxName])).CompareTo((string)(y[_idxName])));
}
catch { }
break;
}
// put the result into the result colums
foreach (var _entry in _result)
{
for (int _idx = 0; _idx < TableConfig.Columns.Count; _idx++)
{
var _col = _lstResultCols[_idx];
_col.Values.Add(_entry[_idx]);
}
}
return new List<cF4SDHealthCardRawData.cHealthCardTable>(1) { retVal };
}
}
StartOnlineValidation();
}
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;
}
public override bool CheckIfLateDelivery(cDataHistoryConfigTable Table)
{
if (Table.Name == constTableNameTicketHistory)
return true;
if (Table.SubTables?.First().Value?.Template is cDataHistoryConfigQueryTemplateM42Pickup)
return true;
return false;
}
public override async Task<bool> WritePropertyAsync(cF4SDWriteParameters PropertiesToWrite, cF4sdWebRequestInfo requestInfo, CancellationToken Token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
if (PropertiesToWrite.TableName != constTableNameTicketDetails)
return false;
if (PropertiesToWrite.Values.Count != 1)
return false;
if (!Collector.ClusterConfig.Tables.TryGetValue(constTableNameTicketDetails, out var tableConfig))
return false;
if (!tableConfig.Columns.TryGetValue(PropertiesToWrite.Values.First().Key, out var colInfo))
return false;
if (!colInfo.IsWritable)
return false;
var strSolution = JsonConvert.SerializeObject(PropertiesToWrite.Values.First().Value.ToString());
var _content = new StringContent(strSolution);
var _url = string.Format(constUrlUpdateSolution, HttpUtility.UrlEncode(PropertiesToWrite.id.ToString()));
var _wc = await GetWebClient(requestInfo, Token);
var res = await _wc.HttpEnh.PostAsync(_url, _content, Token);
if (res?.IsSuccessStatusCode == true)
return true;
StartOnlineValidation();
return false;
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return false;
}
private async void onlineTimerCallback(object state)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
CleanupUserWebCache();
await ValidateConnectionAsync(false, CancellationToken.None);
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
}
private void StartOnlineValidation()
{
if (Collector?.autoConnectionCheck == true)
_ = Task.Run(() => ValidateConnectionAsync(false, CancellationToken.None));
}
public async Task<bool> CheckOnline()
{
await _OnlineCheckCriticalSection.Semaphore.WaitAsync();
try
{
return IsOnline;
}
catch (Exception E)
{
LogException(E);
}
finally
{
_OnlineCheckCriticalSection.Semaphore.Release();
}
return false;
}
public async Task<M42UserUserInfo> GetM42UserInfoAsync(string userSid, CancellationToken Token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
var strUrl = string.Format(constUrlGetRoleMeberships, userSid);
var res = await WebClient.HttpEnh.GetAsync(strUrl, Token);
if (Token.IsCancellationRequested)
return null;
if (res?.IsSuccessStatusCode == true)
{
var strJson = await res.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(strJson))
{
var _userInfo = JsonConvert.DeserializeObject<M42UserUserInfo>(strJson);
if (_userInfo?.User != null && _userInfo.User.Id != Guid.Empty)
return _userInfo;
}
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return null;
}
private async Task<List<string>> GetUserRoles(Guid UserId, CancellationToken Token, string ReportTag = null, bool logDetailed = false)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
var _QueryRelationInfo = new cM42DataQueryRelationInfo2()
{
EntityClassName = "SPSUserClassBase",
EntityTypeName = "SPSSecurityTypeRole",
FragmentId = UserId,
columns = "Name",
pageSize = 0,
RelationName = "MemberOf"
};
var _json = JsonConvert.SerializeObject(_QueryRelationInfo);
var _content = new StringContent(_json, Encoding.UTF8, "application/json");
var _res = await WebClient.HttpEnh.PostAsync(constUrlGetDataQueryRelationItems, _content, Token);
if (_res.IsSuccessStatusCode)
{
var _strResult = await _res.Content.ReadAsStringAsync();
if (string.IsNullOrEmpty(_strResult))
return null;
List<JObject> _roles = JsonConvert.DeserializeObject<List<JObject>>(_strResult);
var _retVal = new List<string>();
foreach (var _roleEntry in _roles)
{
var _vals = _roleEntry.Children();
foreach (var _val in _vals)
{
try
{
if (_val is JProperty prop)
{
if (prop.Name == "Name")
{
var _propGroupName = prop.Value;
if (prop.Value is JValue _jVal && _jVal.Value != null)
{
var _groupName = _jVal.Value.ToString();
_retVal.Add(_groupName);
}
}
}
}
catch (Exception E)
{
LogException(E);
}
}
}
if (_retVal.Count > 0)
return _retVal;
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return null;
}
private async Task<List<cF4SDMembershipGroup>> GetF4SDRoles(Guid UserId, CancellationToken Token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
var _M42UserInfoRoles = await GetUserRoles(UserId, Token);
if (_M42UserInfoRoles != null && _M42UserInfoRoles.Count > 0)
{
var _M42Memberships = Collector?.InfrastructureConfig?.Authorisation?.MembershipGroups?.GroupsM42;
var _resMembershipGroups = new List<cF4SDMembershipGroup>();
if (_M42Memberships != null)
{
foreach (var _membership in Collector.InfrastructureConfig.Authorisation.MembershipGroups.GroupsM42.Values)
{
foreach (var _M42Role in _M42UserInfoRoles)
{
if (_M42Role.ToLowerInvariant() == _membership.RoleName.ToLowerInvariant())
if (!_resMembershipGroups.Contains(_membership))
_resMembershipGroups.Add(_membership);
}
}
}
return _resMembershipGroups;
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return null;
}
public async Task AddM42UserInfosAsync(cF4sdUserInfo userInfo, CancellationToken Token, cF4sdWebRequestInfo requestInfo, int LogDeep)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
// set M42 Logon to possible
if (userInfo.possibleLogons == null)
userInfo.possibleLogons = new List<enumAdditionalAuthentication>();
if (!userInfo.possibleLogons.Contains(enumAdditionalAuthentication.M42WinLogon))
userInfo.possibleLogons.Add(enumAdditionalAuthentication.M42WinLogon);
// check, if the ad sid can be found in M42
var _M42UserInfo = await GetM42UserInfoAsync(userInfo.AdSid, Token);
if (Token.IsCancellationRequested)
return;
// if yes, set M42 for an addidional automatic logon possibility
if (_M42UserInfo?.User != null)
{
if (userInfo.additionalLogons == null)
userInfo.additionalLogons = new List<enumAdditionalAuthentication>();
if (!userInfo.additionalLogons.Contains(enumAdditionalAuthentication.M42WinLogon))
userInfo.additionalLogons.Add(enumAdditionalAuthentication.M42WinLogon);
}
// check, if we have already a valid token for the user
if (Collector.TokenCache != null)
{
// get the api token from token cache
cM42UserInfoResult m42UserInfo = null;
var _res = await Collector.TokenCache.GetAsync(userInfo.Id, cF4SDTokenRegistration.enumTokenType.M42Api, requestInfo, LogDeep + 1);
if (_res != null && _res.IsValid())
{
// check the api token, if it's still valid
var _m42 = new cM42WebClient(Collector.InfrastructureConfig.M42Wpm.Server, UseSSL: true);
var _m42Reason = await _m42.LogonWithApiKeyAsync(_res.secret, Token);
if (_m42Reason == eReason.ok && _m42.BearerToken != null)
{
// get the user info
m42UserInfo = await _m42.GetUserInfoAsync();
// save the new bearer token to token cache
var TokenRegistration = new cF4SDTokenRegistration()
{
TokenType = cF4SDTokenRegistration.enumTokenType.M42Bearer,
UserId = userInfo.Id,
Secret = _m42.BearerToken
};
// set the new bearer token into the token cache
await Collector.TokenCache.SetAsync(TokenRegistration, GetTokenValidityPeriod(_m42.BearerLifeTime), Token, requestInfo, LogDeep + 1);
if (Token.IsCancellationRequested)
return;
// set the valid until info
if (userInfo.ValidLogonsUntil == null)
userInfo.ValidLogonsUntil = new Dictionary<enumAdditionalAuthentication, cF4SDTokenValidityPeriod>();
userInfo.ValidLogonsUntil[enumAdditionalAuthentication.M42WinLogon] = cF4SDTokenValidityPeriod.Create(_res.validUntil, _res.renewUntil);
}
}
else
{
// check, if there is a valid bearer token for M42
_res = await Collector.TokenCache.GetAsync(userInfo.Id, cF4SDTokenRegistration.enumTokenType.M42Bearer, requestInfo, LogDeep + 1);
if (_res != null && _res.IsValid())
{
// if yes, get the user info
var _m42 = new cM42WebClient(Collector.InfrastructureConfig.M42Wpm.Server, UseSSL: true);
_m42.SetBearerToken(_res.secret);
var _res2 = await _m42.Open();
if (_res2 == eReason.ok)
{
m42UserInfo = await _m42.GetUserInfoAsync();
// set the valid until info
if (userInfo.ValidLogonsUntil == null)
userInfo.ValidLogonsUntil = new Dictionary<enumAdditionalAuthentication, cF4SDTokenValidityPeriod>();
userInfo.ValidLogonsUntil[enumAdditionalAuthentication.M42WinLogon] = cF4SDTokenValidityPeriod.Create(_res.validUntil, _res.renewUntil);
}
}
}
// get the role memberships relatet to the M42 roles
if (m42UserInfo?.User?.Id != null)
{
var _F4SDRoles = await GetF4SDRoles((Guid)m42UserInfo.User.Id, Token);
if (_F4SDRoles?.Count > 0)
Collector.AddRolesByMembership(userInfo, _F4SDRoles);
return;
}
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (cPerformanceLogger.IsActive && requestInfo != null) { cPerformanceLogger.LogPerformanceEnd(LogDeep, CM, requestInfo.id, requestInfo.created, _startTime); }
if (CM != null) LogMethodEnd(CM);
}
}
public override async Task<Int64> GetSelectionTableResultCountAsync(cDataHistoryConfigTable Table, List<cF4sdIdentityEntry> Identities, string search, cF4sdWebRequestInfo requestInfo, CancellationToken Token, bool resetFilter = false, List<string> filterParams = null)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
if (!(Table.SubTables.Values.First().Template is cDataHistoryConfigQueryTemplateM42DataQueryItems _template))
return -1;
if (string.IsNullOrEmpty(search))
search = "";
string _whereExpr = null;
if (!resetFilter && !string.IsNullOrEmpty(_template.WhereExpression))
{
if (filterParams != null && filterParams.Count > 0)
_whereExpr = string.Format(_template.WhereExpression, filterParams.ToArray());
else
_whereExpr = _template.WhereExpression;
}
var _cols = Table.KeyColumns.First().SourceName;
var _QueryRelationInfo = new cM42DataQueryRelationInfo()
{
EntityClassName = _template.EntityClassName,
EntityTypeName = string.Join(",", _template.EntityTypeNames),
search = search,
WhereExpression = _whereExpr,
pageSize = 0,
page = 0,
totalCounted = true,
columns = _cols
};
var _json = JsonConvert.SerializeObject(_QueryRelationInfo);
var _content = new StringContent(_json, Encoding.UTF8, "application/json");
var _wc = await GetWebClient(requestInfo, Token);
var res = await _wc.HttpEnh.PostAsync(constUrlGetDataQueryRelationItemsCount, _content);
if (res.IsSuccessStatusCode)
{
var _strResult = await res.Content.ReadAsStringAsync();
if (Int64.TryParse(_strResult, out var count))
{
return count;
}
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return -1;
}
public override async Task<cF4SDHealthCardRawData.cHealthCardTable> GetSelectionTableResultAsync(cDataHistoryConfigTable Table, List<cF4sdIdentityEntry> Identities, string search, int PageSize, int Page, cF4sdWebRequestInfo requestInfo, CancellationToken Token, bool resetFilter = false, List<string> filterParams = null)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
if (!(Table.SubTables.Values.First().Template is cDataHistoryConfigQueryTemplateM42DataQueryItems _template))
return null;
if (string.IsNullOrEmpty(search))
search = "";
string _whereExpr = null;
if (!resetFilter && !string.IsNullOrEmpty(_template.WhereExpression))
{
if (filterParams != null && filterParams.Count > 0)
_whereExpr = string.Format(_template.WhereExpression, filterParams.ToArray());
else
_whereExpr = _template.WhereExpression;
}
var _cols = Table.KeyColumns.First().SourceName;
var _QueryRelationInfo = new cM42DataQueryRelationInfo()
{
EntityClassName = _template.EntityClassName,
EntityTypeName = string.Join(",", _template.EntityTypeNames),
WhereExpression = _whereExpr,
search = search,
pageSize = PageSize,
page = Page,
columns = _cols
};
var _json = JsonConvert.SerializeObject(_QueryRelationInfo);
var _content = new StringContent(_json, Encoding.UTF8, "application/json");
var _wc = await GetWebClient(requestInfo, Token);
var res = await _wc.HttpEnh.PostAsync(constUrlGetDataQueryRelationItems, _content, Token);
if (res.IsSuccessStatusCode)
{
var _strResult = await res.Content.ReadAsStringAsync();
if (string.IsNullOrEmpty(_strResult))
return null;
List<JObject> ticketInfos = JsonConvert.DeserializeObject<List<JObject>>(_strResult);
var _valueCount = ticketInfos.Count;
var retVal = new cF4SDHealthCardRawData.cHealthCardTable()
{
Name = Table.Name,
InformationClass = Table.ParentCluster.InformationClass,
Origin = Table.ParentCluster.Origin,
IsStatic = false,
TableType = Table.Type
};
var _dicColInfo = Table.Columns.ToDictionary(v => v.Value.SourceName, v => v.Value);
foreach (var colInfo in Table.Columns.Values)
{
retVal.Columns[colInfo.Name] = new cF4SDHealthCardRawData.cHealthCardTableColumn(retVal) { ColumnName = colInfo.Name, Values = new List<object>(_valueCount) };
}
foreach (var _entry in ticketInfos)
{
var _vals = _entry.Children();
var _maxCount = 0;
foreach (var _token in _vals)
{
try
{
if (_token is JProperty prop)
if (!string.IsNullOrEmpty(prop.Name) && prop.Value is JValue _val)
{
var _value = _val.Value;
if (!_dicColInfo.TryGetValue(prop.Name, out var _colInfo))
continue;
if (!retVal.Columns.TryGetValue(_colInfo.Name, out var _colData))
continue;
_value = ConvertToF4sdType(_value, _colInfo.ValueType);
_colData.Values.Add(_value);
_maxCount = Math.Max(_maxCount, _colData.Values.Count);
}
}
catch (Exception E)
{
LogEntry($"Error getting M42 ticket detail property '{_token?.Path}'", LogLevels.Error);
LogException(E);
}
}
foreach (var _colData in retVal.Columns.Values)
{
while (_colData.Values.Count < _maxCount)
_colData.Values.Add(null);
}
}
return retVal;
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return null;
}
private cF4SDTokenValidityPeriod GetTokenValidityPeriod(DateTime validUntil)
{
var _renew = validUntil - TimeSpan.FromSeconds(Math.Max(0, (validUntil - DateTime.UtcNow).TotalSeconds * 2 / 10));
return cF4SDTokenValidityPeriod.Create(validUntil, _renew);
}
public override async Task<cF4SdUserInfoChange> ValidateTokenAsync(cF4SDTokenRegistration TokenRegistration, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken Token)
{
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 (TokenRegistration?.TokenType is cF4SDTokenRegistration.enumTokenType.M42Bearer &&
!string.IsNullOrEmpty(Collector?.InfrastructureConfig?.M42Wpm.Server) &&
!string.IsNullOrEmpty(TokenRegistration?.Secret)
)
{
var _M42UserInfo = await cM42WebClient.LogonBearer(Collector.InfrastructureConfig.M42Wpm.Server, TokenRegistration.Secret, Token, UseSSL: true, LogDetailed: true);
if (Token.IsCancellationRequested)
return null;
if (_M42UserInfo != null)
{
if (_M42UserInfo.BearerValidUntil > DateTime.UtcNow && TokenRegistration.AutoCreatePermanent && _M42UserInfo.User?.Id != null)
{
var _res2 = await CreateApiToken(TokenRegistration, _M42UserInfo, Token, requestInfo, LogDeep + 1);
if (Token.IsCancellationRequested)
return null;
if (_res2 < DateTime.UtcNow)
return null;
}
// user info & f4sd token aktualisieren
var _validityPeriod = GetTokenValidityPeriod(_M42UserInfo.BearerValidUntil);
var Roles = new List<string>();
if (_M42UserInfo?.User?.Id != null)
{
var _F4SDRoles = await GetF4SDRoles((Guid)_M42UserInfo.User.Id, Token);
if (_F4SDRoles?.Count > 0)
Collector.AddRolesByMembership(Roles, _F4SDRoles, requestInfo?.userInfo?.Name);
}
var _retVal = new cF4SdUserInfoChange()
{
ValidLogonsUntil = new Dictionary<enumAdditionalAuthentication, cF4SDTokenValidityPeriod> { { enumAdditionalAuthentication.M42WinLogon, _validityPeriod } },
Roles = Roles
};
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 class cM42IdResult
{
public Guid Id { get; set; }
public string Name { get; set; }
}
private async Task<DateTime> CreateApiToken(cF4SDTokenRegistration TokenRegistration, cM42UserInfoResult UserInfo, CancellationToken Token, cF4sdWebRequestInfo requestInfo, int LogDeep)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
// obtain token name
var tokenName = $"F4SD_{UserInfo.User.LastName ?? ""}_{UserInfo.User.FirstName ?? ""}_{UserInfo.User.Id}";
// create M42 web client
var _m42 = new cM42WebClient(Collector.InfrastructureConfig.M42Wpm.Server, UseSSL: true);
_m42.SetBearerToken(UserInfo.BearerToken);
var _resOpen = await _m42.Open();
if (_resOpen != eReason.ok)
return DateTime.MinValue;
// check if token alsready exist
var _strListToken = await _m42.GetFragmentListAsync("PLSTSApiTokenBase", Token, $"Name='{tokenName}'");
if (!string.IsNullOrEmpty(_strListToken))
{
// remove all existing tokens with corresponding name
var lstIds = JsonConvert.DeserializeObject<List<cM42IdResult>>(_strListToken);
foreach (var objId in lstIds)
{
var _delRequest = new Dictionary<Guid, string>()
{
{ objId.Id, "PLSTSApiTokenType" }
};
await _m42.DeleteObjectsAsync("F4SD Cockpit", _delRequest, Token);
if (Token.IsCancellationRequested)
return DateTime.MinValue;
}
}
// create token generation request
var tokenRequest = new cApiTokenRequestModelBase()
{
Name = tokenName,
ExpirationDays = (int)(Collector?.InfrastructureConfig?.M42Wpm?.ApiLifetime ?? cDataHistoryConfigM42Wpm.enumApiTokenLifetime.days30)
};
// generate token
var strJson = JsonConvert.SerializeObject(tokenRequest);
var CO = new StringContent(strJson, Encoding.UTF8, "application/json");
var _resPost = await _m42.Http.PostAsync(constUrlGenerateApiTokenForMe, CO);
if (Token.IsCancellationRequested)
return DateTime.MinValue;
var _content = await _resPost.Content.ReadAsStringAsync();
if (Token.IsCancellationRequested)
return DateTime.MinValue;
if (_resPost.IsSuccessStatusCode)
{
var _tokenModel = JsonConvert.DeserializeObject<cM42ApiTokenModel>(_content);
if (!string.IsNullOrEmpty(_tokenModel?.ApiToken) && _tokenModel?.ValidUntil >= DateTime.UtcNow)
{
var _validUntil = (DateTime)_tokenModel.ValidUntil;
var _renewUntil = _validUntil - TimeSpan.FromDays(1);
var _tr = new cF4SDTokenRegistration()
{
TokenType = cF4SDTokenRegistration.enumTokenType.M42Api,
UserId = TokenRegistration.UserId,
Name = _tokenModel?.Name,
Secret = _tokenModel.ApiToken,
AutoCreatePermanent = false
};
await Collector.TokenCache.SetAsync(_tr, cF4SDTokenValidityPeriod.Create(_validUntil, _renewUntil), Token, requestInfo, LogDeep + 1);
if (Token.IsCancellationRequested)
return DateTime.MinValue;
return _validUntil;
}
}
}
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 DateTime.MinValue;
}
public async Task<string> CreateM42TicketAsync(cApiM42Ticket ticketInfo, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var _webClient = await GetUserWebClient(requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested || _webClient == null) return null;
var userFragmentListTask = GetFragmentListAsync(new cDataFragmentsParams
{
Columns = "ID",
Ddname = "SPSUserClassBase",
Pagenumber = 0,
Pagesize = 10,
Where = string.Format("T(SPSCommonClassbase).State = 2023 AND Accounts.T(SPSAccountClassAD).ADCn = '{0}'", ticketInfo.User)
}, requestInfo, LogDeep + 1, token);
List<Task> tasksToAwait = new List<Task> { userFragmentListTask };
Task<dynamic> assetFragmentListTask = null;
if (!ticketInfo.AffectedAsset.Equals("RemoveAffectedAssetEntry", StringComparison.InvariantCultureIgnoreCase) && !string.IsNullOrEmpty(ticketInfo.AffectedAsset))
{
assetFragmentListTask = GetFragmentListAsync(new cDataFragmentsParams
{
Columns = "ID",
Ddname = "SPSAssetClassBase",
Pagenumber = 0,
Pagesize = 10,
Where = string.Format("T(SPSCommonClassbase).State = 710 AND T(SPSComputerClassBase).Name = '{0}'", ticketInfo.AffectedAsset)
}, requestInfo, LogDeep + 1, token);
tasksToAwait.Add(assetFragmentListTask);
}
Task<dynamic> quickCallFragmentListTask = null;
if (ticketInfo.Quickcall.HasValue && ticketInfo.Quickcall.Value != Guid.Empty)
{
quickCallFragmentListTask = GetQuickCallTemplateInfoAsync(ticketInfo.Quickcall.Value, requestInfo, LogDeep + 1, token);
tasksToAwait.Add(quickCallFragmentListTask);
}
else
{
LogEntry($"No quick call set to create new ticket.", LogLevels.Error);
return null;
}
// Warte auf alle gestarteten Tasks
await Task.WhenAll(tasksToAwait);
var fragments = userFragmentListTask.Result;
var idAsString = "";
Guid? assetId = null;
var assetNotFound = false;
if (assetFragmentListTask != null)
{
var assetFragments = assetFragmentListTask.Result;
if (token.IsCancellationRequested) return null;
if (assetFragments == null || assetFragments.Count == 0)
{
assetNotFound = true;
}
else
{
idAsString = (string)assetFragments?[0]?.ID;
if (Guid.TryParse(idAsString, out Guid assetIdTemp))
{
assetId = assetIdTemp;
}
else
assetNotFound = true;
}
}
idAsString = (string)fragments?[0]?.ID;
if (!Guid.TryParse(idAsString, out Guid userID))
{
LogEntry($"No initiating user found with state active (710) and AD Common Name: {ticketInfo.User}", LogLevels.Error);
return null;
}
Guid? requestCategoryId = ticketInfo.Category;
if (requestCategoryId.HasValue && requestCategoryId.Value == Guid.Empty)
{
requestCategoryId = null;
}
var ticketInfo2 = new cM42TicketInfo()
{
Subject = ticketInfo.Summary,
DescriptionHTML = ticketInfo.DescriptionHtml,
SolutionHTML = ticketInfo.SolutionHtml,
User = userID,
Asset = assetId,
Service = ticketInfo.AffectedService,
Template = ticketInfo.Quickcall,
Category = requestCategoryId,
EntryBy = 20500
};
var quickCallFragments = quickCallFragmentListTask?.Result;
if (quickCallFragments != null)
{
var quickCallData = quickCallFragments;
if (int.TryParse((string)quickCallData?.Impact, out int impact))
ticketInfo2.Impact = impact;
if (int.TryParse((string)quickCallData?.Urgency, out int urgency))
ticketInfo2.Urgency = urgency;
if (int.TryParse((string)quickCallData?.EntryBy, out int entryBy))
ticketInfo2.EntryBy = entryBy;
if (int.TryParse((string)quickCallData?.ErrorType, out int errorType))
ticketInfo2.ErrorType = errorType;
if (int.TryParse((string)quickCallData?.Priority, out int priority))
ticketInfo2.Priority = priority;
if (Guid.TryParse((string)quickCallData?.RecipientRole, out Guid recipientRole))
ticketInfo2.ResponsibleRole = recipientRole;
if (Guid.TryParse((string)quickCallData?.RecipientID, out Guid recipient))
ticketInfo2.ResponsibleUser = recipient;
if (Guid.TryParse((string)quickCallData?.Asset, out Guid asset))
ticketInfo2.Asset = ticketInfo2.Asset ?? asset;
if (Guid.TryParse((string)quickCallData?.Service, out Guid service))
ticketInfo2.Service = ticketInfo2.Service ?? service;
if (!ticketInfo2.Category.HasValue && Guid.TryParse((string)quickCallData?.Category, out Guid category))
ticketInfo2.Category = category;
if (bool.TryParse((string)quickCallData?.NotifyResponsible, out bool notifyResponsible))
ticketInfo2.NotifyResponsible = notifyResponsible;
if (int.TryParse((string)quickCallData?.Classification, out int Classification))
ticketInfo2.Classification = Classification;
}
var _jsonContent = JsonConvert.SerializeObject(ticketInfo2, Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var _content = new StringContent(_jsonContent, Encoding.UTF8, "application/json");
var url = string.Format(constUrlCreateTicket, ticketInfo2.Classification);
var response = await _webClient.HttpEnh.PostAsync(url, _content, token);
if (token.IsCancellationRequested) return null;
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
Guid TicketId = Guid.TryParse(json?.Trim('"'), out TicketId) ? TicketId : Guid.Empty;
await AddWorkingTimesAsync(TicketId, ticketInfo.workTimes, requestInfo, LogDeep + 1, token);
cCreateJournalEntryInfo journalEntry = null;
if (assetNotFound)
{
string assetNotFoundText = "";
if (ticketInfo.AdditionalValues.TryGetValue("Dialog.CloseCase.AssetNotFoundInMatrix42", out object valueObj))
{
assetNotFoundText = valueObj as string;
}
if (!string.IsNullOrEmpty(assetNotFoundText))
{
journalEntry = new cCreateJournalEntryInfo()
{
Comments = string.Format(assetNotFoundText, ticketInfo.AffectedAsset),
ObjectId = TicketId,
EntryType = 0
};
await CreateM42JournalAsync(journalEntry, requestInfo, LogDeep + 1, token);
}
}
journalEntry = new cCreateJournalEntryInfo()
{
Comments = ticketInfo.CopyTemplates,
ObjectId = TicketId,
EntryType = 20600
};
await CreateM42JournalAsync(journalEntry, requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested) return null;
try
{
if (ticketInfo.SupportCaseProtocollEntries != null)
{
await ProtocollSupportCaseProtocollEntries(ticketInfo.SupportCaseProtocollEntries, TicketId, requestInfo, LogDeep, token);
}
else if (ticketInfo.QuickActionHistory != null)
{
await ProtocollSupportCaseQuickActionHistory(ticketInfo.QuickActionHistory, TicketId, requestInfo, LogDeep, token);
}
if (token.IsCancellationRequested)
return null;
}
catch (TaskCanceledException)
{
return null;
}
ticketInfo.Ticket = TicketId;
await UpdateM42TicketUnreadAsync(ticketInfo, requestInfo, LogDeep + 1, token);
return TicketId.ToString();
}
}
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 ProtocollSupportCaseProtocollEntries(List<ProtocollEntryBase> supportCaseProtocollEntries, Guid ticketId, cF4sdWebRequestInfo requestInfo, int logDeep, CancellationToken token)
{
foreach (var protocollEntry in supportCaseProtocollEntries)
{
if (!(protocollEntry is QuickActionProtocollEntry entry))
continue;
cCreateJournalEntryInfo _entry = null;
switch (entry.ResultCode)
{
case -1:
case 1:
case 0:
var entryType = entry.WasRunningOnAffectedDevice ? 20602 : 20601;
_entry = new cCreateJournalEntryInfo()
{
Comments = "",
ObjectId = ticketId,
EntryType = entryType,
Parameters = new List<cCreateJournalEntryInfo.Parameter>() { new cCreateJournalEntryInfo.Parameter()
{
Name = "result",
Value = entry.HtmlContent ?? entry.MeasureValues ?? entry.ErrorMessage
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "quickActionName",
Value = entry.Name
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "QuickActionId",
Value = entry.Id
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "quickActionExecutionType",
Value = entry.ExecutionTypeId
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "ExecutionTime",
Value = entry.Time
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "AffectedDeviceName",
Value = entry.AffectedDeviceName
},}
};
break;
default:
break;
}
if (_entry != null)
{
await CreateM42JournalAsync(_entry, requestInfo, logDeep + 1, token);
if (token.IsCancellationRequested) return;
}
}
}
private async Task ProtocollSupportCaseQuickActionHistory(List<cQuickActionResult> quickActionHistory, Guid ticketId, cF4sdWebRequestInfo requestInfo, int logDeep, CancellationToken token)
{
foreach (var entry in quickActionHistory)
{
cCreateJournalEntryInfo _entry = null;
switch (entry.ResultCode)
{
case -1:
case 1:
case 0:
var entryType = entry.wasRunningOnAffectedDevice ? 20602 : 20601;
_entry = new cCreateJournalEntryInfo()
{
Comments = "",
ObjectId = ticketId,
EntryType = entryType,
Parameters = new List<cCreateJournalEntryInfo.Parameter>() { new cCreateJournalEntryInfo.Parameter()
{
Name = "result",
Value = entry.Output ?? entry.MeasureValues ?? entry.ErrorMessage
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "quickActionName",
Value = entry.QuickActionName
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "QuickActionId",
Value = entry.QuickActionId
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "quickActionExecutionType",
Value = entry.QuickActionExecutionType
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "ExecutionTime",
Value = entry.ExecutionTime
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "AffectedDeviceName",
Value = entry.AffectedDeviceName
},}
};
break;
default:
break;
}
if (_entry != null)
{
await CreateM42JournalAsync(_entry, requestInfo, logDeep + 1, token);
if (token.IsCancellationRequested) return;
}
}
}
public async Task<string> UpdateM42TicketAsync(cApiM42Ticket ticketInfo, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var _webClient = await GetUserWebClient(requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested || _webClient == null) return null;
string activityType = "SPSActivityTypeIncident";
if (ticketInfo.AdditionalValues.TryGetValue("ActivityType", out object value) && value is string stringValue)
{
activityType = stringValue;
}
var url = string.Format(constUrlObjectsUpdateObject, activityType, false);
var ticketID = (Guid)ticketInfo.Ticket;
var ticket = await GetObjectAsync(activityType, ticketID, false, requestInfo, LogDeep + 1, token);
if (ticketInfo.Quickcall.HasValue && ticketInfo.Quickcall.Value != Guid.Empty)
{
ticket["SPSActivityClassIncident"]["Quickcall"] = ticketInfo.Quickcall.Value;
}
if (ticketInfo.Category.HasValue && ticketInfo.Category.Value != Guid.Empty)
{
ticket["SPSActivityClassIncident"]["Category"] = ticketInfo.Category.Value;
}
if (ticketInfo.AffectedService.HasValue && ticketInfo.AffectedService.Value == Guid.Empty)
{
ticket["SPSActivityClassBase"]["Service"] = null;
}
else if (ticketInfo.AffectedService.HasValue && ticketInfo.AffectedService.Value != Guid.Empty)
ticket["SPSActivityClassBase"]["Service"] = ticketInfo.AffectedService.Value;
var createAssetNotFoundJournalEntry = false;
if (ticketInfo.AffectedAsset.Equals("RemoveAffectedAssetEntry", StringComparison.InvariantCultureIgnoreCase))
{
ticket["SPSActivityClassIncident"]["Asset"] = null;
}
else if (!string.IsNullOrEmpty(ticketInfo.AffectedAsset))
{
var assetNotFound = true;
Guid? assetId = null;
var assetFragments = await GetFragmentListAsync(new cDataFragmentsParams()
{
Columns = "ID",
Ddname = "SPSAssetClassBase",
Pagenumber = 0,
Pagesize = 10,
Where = string.Format("T(SPSCommonClassbase).State = 710 AND T(SPSComputerClassBase).Name = '{0}'", ticketInfo.AffectedAsset)
}, requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested) return null;
if (assetFragments == null || assetFragments.Count == 0)
{
assetNotFound = true;
}
else
{
var idAsString = (string)assetFragments?[0]?.ID;
if (Guid.TryParse(idAsString, out Guid assetIdTemp))
{
assetId = assetIdTemp;
assetNotFound = false;
}
else
{
assetNotFound = true;
}
}
if (assetNotFound)
{
createAssetNotFoundJournalEntry = true;
}
if (assetId != null)
{
ticket["SPSActivityClassBase"]["AffectedAsset"] = assetId;
}
}
ticket["SPSActivityClassBase"]["Subject"] = ticketInfo.Summary;
var _jsonContent = JsonConvert.SerializeObject(ticket, Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var _content = new StringContent(_jsonContent, Encoding.UTF8, "application/json");
var response = await _webClient.HttpEnh.PutAsync(url, _content, token);
if (token.IsCancellationRequested) return null;
if (response.IsSuccessStatusCode)
{
await AddWorkingTimesAsync(ticketID, ticketInfo.workTimes, requestInfo, LogDeep + 1, token);
cCreateJournalEntryInfo _entry = null;
if (createAssetNotFoundJournalEntry)
{
string assetNotFoundText = "";
if (ticketInfo.AdditionalValues.TryGetValue("Dialog.CloseCase.AssetNotFoundInMatrix42", out object valueObj))
{
assetNotFoundText = valueObj as string;
}
if (!string.IsNullOrEmpty(assetNotFoundText))
{
_entry = new cCreateJournalEntryInfo()
{
Comments = string.Format(assetNotFoundText, ticketInfo.AffectedAsset),
ObjectId = ticketID,
EntryType = 0
};
await CreateM42JournalAsync(_entry, requestInfo, LogDeep + 1, token);
}
}
// Case Notes as Journal Entry
if (!string.IsNullOrEmpty(ticketInfo.DescriptionHtml))
{
_entry = new cCreateJournalEntryInfo()
{
Comments = ticketInfo.DescriptionHtml,
ObjectId = ticketID,
EntryType = 20603,
};
await CreateM42JournalAsync(_entry, requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested) return null;
}
// CopyTemplates as Journal Entry
if (!string.IsNullOrEmpty(ticketInfo.CopyTemplates))
{
_entry = new cCreateJournalEntryInfo()
{
Comments = ticketInfo.CopyTemplates,
ObjectId = ticketID,
EntryType = 20604
};
await CreateM42JournalAsync(_entry, requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested) return null;
}
if (ticketInfo.SupportCaseProtocollEntries != null)
{
foreach (var protocollEntry in ticketInfo.SupportCaseProtocollEntries)
{
if (!(protocollEntry is QuickActionProtocollEntry entry))
continue;
switch (entry.ResultCode)
{
case -1:
case 1:
case 0:
var entryType = entry.WasRunningOnAffectedDevice ? 20602 : 20601;
_entry = new cCreateJournalEntryInfo()
{
Comments = "",
ObjectId = ticketID,
EntryType = entryType,
Parameters = new List<cCreateJournalEntryInfo.Parameter>() { new cCreateJournalEntryInfo.Parameter()
{
Name = "result",
Value = entry.HtmlContent ?? entry.MeasureValues ?? entry.ErrorMessage
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "quickActionName",
Value = entry.Name
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "QuickActionId",
Value = entry.Id
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "quickActionExecutionType",
Value = entry.ExecutionTypeId
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "ExecutionTime",
Value = entry.Time
},
new cCreateJournalEntryInfo.Parameter()
{
Name = "AffectedDeviceName",
Value = entry.AffectedDeviceName
},}
};
break;
default:
break;
}
if (_entry != null)
{
await CreateM42JournalAsync(_entry, requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested) return null;
}
}
}
await UpdateM42TicketUnreadAsync(ticketInfo, requestInfo, LogDeep + 1, token);
return string.Empty;
}
}
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;
}
public async Task<string> UpdateM42TicketUnreadAsync(cApiM42Ticket ticketInfo, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var _webClient = await GetUserWebClient(requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested || _webClient == null) return null;
string activityType = "SPSActivityTypeIncident";
if (ticketInfo.AdditionalValues.TryGetValue("ActivityType", out object value) && value is string stringValue)
{
activityType = stringValue;
}
var url = string.Format(constUrlObjectsUpdateObject, activityType, false);
var ticketID = (Guid)ticketInfo.Ticket;
var ticket = await GetObjectAsync(activityType, ticketID, false, requestInfo, LogDeep + 1, token);
if (ticket != null)
{
ticket["SPSActivityClassBase"]["NewInformationReceived"] = 0;
var _jsonContent = JsonConvert.SerializeObject(ticket, Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var _content = new StringContent(_jsonContent, Encoding.UTF8, "application/json");
var response = await _webClient.HttpEnh.PutAsync(url, _content, token);
if (token.IsCancellationRequested) return null;
if (response.IsSuccessStatusCode)
{
await Collector.ReportTicketAsync(ticketInfo, requestInfo, LogDeep + 1, token);
return string.Empty;
}
}
}
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;
}
public async Task<string> CloseM42TicketAsync(cApiM42Ticket ticketInfo, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var _webClient = await GetUserWebClient(requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested || _webClient == null) return null;
var ticketId = Guid.Empty;
if (ticketInfo.Ticket == null || ticketInfo.Ticket.HasValue && ticketInfo.Ticket.Equals(Guid.Empty))
{
var res = await CreateM42TicketAsync(ticketInfo, requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested) return null;
if (!string.IsNullOrEmpty(res))
{
Guid.TryParse(res, out ticketId);
}
}
else
{
await UpdateM42TicketAsync(ticketInfo, requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested) return null;
ticketId = (Guid)ticketInfo.Ticket;
}
bool isTicket = false;
if (ticketInfo.AdditionalValues.TryGetValue("IsTicket", out object value) && value is bool boolValue)
{
isTicket = boolValue;
if (isTicket)
{
await TransformM42TicketAsync(ticketInfo, requestInfo, LogDeep + 1, token);
}
}
var url = constUrlTicketClose;
var ticket = new cApiM42TicketClosureInfo()
{
ObjectIds = new List<Guid>() { ticketId },
Comments = ticketInfo.SolutionHtml,
ErrorType = (int)ticketInfo.ErrorType == -1 ? null : ticketInfo.ErrorType,
Reason = 408,
};
var _jsonContent = JsonConvert.SerializeObject(ticket, Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var _content = new StringContent(_jsonContent, Encoding.UTF8, "application/json");
var response = await _webClient.HttpEnh.PostAsync(url, _content, token);
if (token.IsCancellationRequested) return null;
if (response.IsSuccessStatusCode)
{
ticketInfo.Ticket = ticketInfo.Ticket != null && ticketInfo.Ticket != Guid.Empty ? ticketInfo.Ticket : ticketId;
await UpdateM42TicketUnreadAsync(ticketInfo, requestInfo, LogDeep + 1, token);
return string.Empty;
}
}
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;
}
public async Task<bool> AddWorkingTimesAsync(Guid TicketEOID, Dictionary<string, object> workTimes, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken token)
{
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 (Collector == null) return false;
var globalConfig = Collector.GetGlobalConfig();
var timeTrackingDisabled = globalConfig.TicketConfiguration.DisableAutomaticTimeTracking;
if (timeTrackingDisabled)
return false;
var _webClient = await GetUserWebClient(requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested || _webClient == null) return false;
if (token.IsCancellationRequested) return false;
var fragments = await GetFragmentListAsync(new cDataFragmentsParams()
{
Columns = "ID, TypeID",
Ddname = "SPSCommonClassBase",
Pagenumber = 0,
Pagesize = 10,
Where = string.Format("[Expression-ObjectId] = '{0}'", TicketEOID)
}, requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested) return false;
var idAsString = "";
Guid? typeId = null;
if (fragments != null)
{
idAsString = (string)fragments?[0]?.ID;
if (Guid.TryParse(idAsString, out Guid typeIdTemp))
{
typeId = typeIdTemp;
}
}
string description = default;
DateTime startTime = default;
DateTime endTime = default;
TimeSpan bruttoWorkingTime = default;
int nettoWorkingTime = 0;
TimeSpan totalPausedTime = default;
if (workTimes.TryGetValue("Description", out object tempDescription) && tempDescription is string)
{
description = (string)tempDescription;
}
if (workTimes.TryGetValue("StartTime", out object tempStartTime) && tempStartTime is DateTime)
{
startTime = (DateTime)tempStartTime;
}
if (workTimes.TryGetValue("EndTime", out object tempEndTime) && tempEndTime is DateTime)
{
endTime = (DateTime)tempEndTime;
}
if (workTimes.TryGetValue("BruttoWorkingTime", out object tempBruttoWorkingTime) && tempBruttoWorkingTime is TimeSpan)
{
bruttoWorkingTime = (TimeSpan)tempBruttoWorkingTime;
}
if (workTimes.TryGetValue("NettoWorkingTime", out object tempNettoWorkingTime) && tempNettoWorkingTime is double)
{
nettoWorkingTime = (int)Math.Round((double)tempNettoWorkingTime / 60);
}
if (workTimes.TryGetValue("TotalPausedTime", out object tempTotalPausedTime) && tempTotalPausedTime is TimeSpan)
{
totalPausedTime = (TimeSpan)tempTotalPausedTime;
}
var requestBody = new cApiM42TicketAddWorkingTimesInfo()
{
ObjectIds = new List<Guid>() { TicketEOID },
Begin = startTime,
End = endTime,
TypeId = typeId,
ActivityType = 4,
Minutes = nettoWorkingTime <= 0 ? 1 : nettoWorkingTime,
Description = description
};
var url = constUrlActivityTrackWorkingTime;
var _jsonContent = JsonConvert.SerializeObject(requestBody, Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var _content = new StringContent(_jsonContent, Encoding.UTF8, "application/json");
var response = await _webClient.HttpEnh.PostAsync(url, _content, token);
if (token.IsCancellationRequested) return false;
if (response.IsSuccessStatusCode)
{
return true;
}
}
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 false;
}
public async Task<string> TransformM42TicketAsync(cApiM42Ticket ticketInfo, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var _webClient = await GetUserWebClient(requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested || _webClient == null) return null;
var ticketId = Guid.Empty;
if (ticketInfo.Ticket == null || ticketInfo.Ticket.HasValue && ticketInfo.Ticket.Equals(Guid.Empty))
return null;
else
ticketId = ticketInfo.Ticket.Value;
var url = constUrlTicketTransform;
var ticket = new cM42TransformTicketInfo()
{
ObjectIds = new List<Guid>() { ticketId },
SourceTypeName = "SPSActivityTypeTicket",
TargetTypeName = "SPSActivityTypeIncident"
};
var _jsonContent = JsonConvert.SerializeObject(ticket, Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var _content = new StringContent(_jsonContent, Encoding.UTF8, "application/json");
var response = await _webClient.HttpEnh.PostAsync(url, _content, token);
if (token.IsCancellationRequested) return null;
if (response.IsSuccessStatusCode)
{
await Collector.ReportTicketAsync(ticketInfo, requestInfo, LogDeep + 1, token);
return string.Empty;
}
}
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;
}
public async Task<dynamic> GetQuickCallTemplateInfoAsync(Guid quickCallId, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var _webClient = await GetUserWebClient(requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested || _webClient == null) return null;
if (quickCallId.Equals(Guid.Empty))
return null;
var url = string.Format(constUrlActivityGetQuickCallTemplateInfo, quickCallId);
var response = await _webClient.HttpEnh.GetAsync(url, token);
if (token.IsCancellationRequested) return null;
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject(json);
}
}
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;
}
public async Task<string> ReopenM42TicketAsync(cApiM42Ticket ticketInfo, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var _webClient = await GetUserWebClient(requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested || _webClient == null) return null;
var ticketId = Guid.Empty;
if (ticketInfo.Ticket == null || ticketInfo.Ticket.HasValue && ticketInfo.Ticket.Equals(Guid.Empty))
return null;
else
ticketId = ticketInfo.Ticket.Value;
var url = constUrlActivityReopen;
string ReopenReasonText = "";
if (ticketInfo.AdditionalValues.TryGetValue("Dialog.CloseCase.ReopenReasonText", out object valueObj))
{
ReopenReasonText = valueObj as string;
}
var ticket = new cM42ReopenTicketInfo()
{
ObjectIds = new List<Guid>() { ticketId },
Reason = ReopenReasonText,
};
var _jsonContent = JsonConvert.SerializeObject(ticket, Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var _content = new StringContent(_jsonContent, Encoding.UTF8, "application/json");
var response = await _webClient.HttpEnh.PostAsync(url, _content, token);
if (token.IsCancellationRequested) return null;
if (response.IsSuccessStatusCode)
{
//await Collector.ReportTicketAsync(ticketInfo, requestInfo, LogDeep + 1, token).ConfigureAwait(false);
return string.Empty;
}
}
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;
}
public async Task<string> PauseM42TicketAsync(cApiM42Ticket ticketInfo, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var _webClient = await GetUserWebClient(requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested || _webClient == null) return null;
var ticketId = Guid.Empty;
if (ticketInfo.Ticket == null || ticketInfo.Ticket.HasValue && ticketInfo.Ticket.Equals(Guid.Empty))
{
var res = await CreateM42TicketAsync(ticketInfo, requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested) return null;
if (!string.IsNullOrEmpty(res))
{
Guid.TryParse(res, out ticketId);
}
}
else
{
await UpdateM42TicketAsync(ticketInfo, requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested) return null;
ticketId = (Guid)ticketInfo.Ticket;
}
bool isTicket = false;
if (ticketInfo.AdditionalValues.TryGetValue("IsTicket", out object value) && value is bool boolValue)
{
isTicket = boolValue;
if (isTicket)
{
await TransformM42TicketAsync(ticketInfo, requestInfo, LogDeep + 1, token);
}
}
var url = constUrlActivityPause;
var ticket = new cApiM42TicketPauseInfo()
{
ObjectIds = new List<Guid>() { ticketId },
Comments = ticketInfo.Comment,
ReminderDate = (DateTime)ticketInfo.ReminderDate,
NotEscalateWhilePaused = (bool)ticketInfo.DoNotEscalateWhilePaused,
Reason = (int)ticketInfo.Reason
};
var _jsonContent = JsonConvert.SerializeObject(ticket, Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var _content = new StringContent(_jsonContent, Encoding.UTF8, "application/json");
var response = await _webClient.HttpEnh.PostAsync(url, _content, token);
if (token.IsCancellationRequested) return null;
if (response.IsSuccessStatusCode)
{
ticketInfo.Ticket = ticketInfo.Ticket != null && ticketInfo.Ticket != Guid.Empty ? ticketInfo.Ticket : ticketId;
await UpdateM42TicketUnreadAsync(ticketInfo, requestInfo, LogDeep + 1, token);
return string.Empty;
}
}
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;
}
public async Task<string> ForwardM42TicketAsync(cApiM42Ticket ticketInfo, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var _webClient = await GetUserWebClient(requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested || _webClient == null) return null;
var ticketId = Guid.Empty;
if (ticketInfo.Ticket == null || ticketInfo.Ticket.HasValue && ticketInfo.Ticket.Equals(Guid.Empty))
{
var res = await CreateM42TicketAsync(ticketInfo, requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested) return null;
if (!string.IsNullOrEmpty(res))
{
Guid.TryParse(res, out ticketId);
}
}
else
{
await UpdateM42TicketAsync(ticketInfo, requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested) return null;
ticketId = (Guid)ticketInfo.Ticket;
}
var url = constUrlActivityForward;
var ticket = new cApiM42TicketForwardInfo()
{
Tickets = new List<cApiM42TicketForwardInfo.cTicket>() { new cApiM42TicketForwardInfo.cTicket() {
Item1 = "SPSActivityTypeIncident",
Item2 = ticketId
}},
Comments = ticketInfo.Comment,
RoleId = ticketInfo.ResponsibleRole,
UserId = ticketInfo.ResponsiblePerson,
};
var _jsonContent = JsonConvert.SerializeObject(ticket, Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var _content = new StringContent(_jsonContent, Encoding.UTF8, "application/json");
var response = await _webClient.HttpEnh.PostAsync(url, _content, token);
if (token.IsCancellationRequested) return null;
if (response.IsSuccessStatusCode)
{
ticketInfo.Ticket = ticketInfo.Ticket != null && ticketInfo.Ticket != Guid.Empty ? ticketInfo.Ticket : ticketId;
await UpdateM42TicketUnreadAsync(ticketInfo, requestInfo, LogDeep + 1, token);
return string.Empty;
}
}
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;
}
public async Task<String> CreateM42JournalAsync(cCreateJournalEntryInfo journalEntryInfo, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var _webClient = await GetUserWebClient(requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested || _webClient == null) return null;
var _jsonContent = JsonConvert.SerializeObject(journalEntryInfo, Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var _content = new StringContent(_jsonContent, Encoding.UTF8, "application/json");
var response = await _webClient.HttpEnh.PostAsync(constUrlCreateJournalEntry, _content, token);
if (token.IsCancellationRequested) return null;
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
if (token.IsCancellationRequested) return null;
return json;
}
}
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;
}
public static string GetFragmentUrlWithParameters(cDataFragmentsParams parameters)
{
return string.Format(constUrlFragmentsGetList,
parameters.Ddname,
Uri.EscapeDataString(parameters.Where), // Ensure proper URI encoding
parameters.Columns,
parameters.Pagesize,
parameters.Pagenumber,
parameters.Sort);
}
public async Task CleanupApiTokensAsync(CancellationToken Token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (WebClient is null)
return;
try
{
var _strFilter = (DateTime.UtcNow - TimeSpan.FromHours(24)).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss");
_strFilter = string.Format("Name like 'F4SD_%' and ValidUntil < '{0}'", _strFilter);
var _strListToken = await WebClient.GetFragmentListAsync("PLSTSApiTokenBase", Token, Where: _strFilter, Columns: "ID,Name");
if (Token.IsCancellationRequested)
return;
if (!string.IsNullOrEmpty(_strListToken))
{
// remove all existing tokens with corresponding name
var lstIds = JsonConvert.DeserializeObject<List<cM42IdResult>>(_strListToken);
foreach (var objId in lstIds)
{
if (string.IsNullOrEmpty(objId.Name))
continue;
if (objId.Name.Length < 37)
continue;
var _strGuid = objId.Name.Substring(objId.Name.Length - 37, 37);
if (!_strGuid.StartsWith("_"))
continue;
_strGuid = _strGuid.Remove(0, 1);
if (!Guid.TryParse(_strGuid, out _))
continue;
var _delRequest = new Dictionary<Guid, string>()
{
{ objId.Id, "PLSTSApiTokenType" }
};
await WebClient.DeleteObjectsAsync("F4SD Cockpit", _delRequest, Token);
if (Token.IsCancellationRequested)
return;
}
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
}
public override async Task<cF4SDAdditionalUserInfo> GetAdditionalUserInfo(enumAdditionalAuthentication Type, cF4sdWebRequestInfo RequestInfo, int LogDeep, CancellationToken Token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
if (Type != enumAdditionalAuthentication.M42WinLogon)
return null;
if (RequestInfo?.userInfo?.Id is null)
return null;
var _uc = await Collector.TokenCache.GetAsync(RequestInfo.userInfo.Id, cF4SDTokenRegistration.enumTokenType.M42Bearer, RequestInfo, LogDeep + 1);
if (_uc == null) return null;
var _m42 = new cM42WebClient(Collector.InfrastructureConfig.M42Wpm.Server, UseSSL: true);
_m42.SetBearerToken(_uc.secret);
var _m42Reason = await _m42.Open();
if (_m42Reason == eReason.ok && _m42.BearerToken != null)
{
var m42UserInfo = await _m42.GetUserInfoAsync();
if (m42UserInfo?.User != null)
{
var _retVal = new cF4SDAdditionalUserInfo()
{
internalID = m42UserInfo.User.Id.ToString(),
Name = m42UserInfo.User.LastName + ", " + m42UserInfo.User.FirstName,
Type = enumAdditionalAuthentication.M42WinLogon,
ValidUntil = _uc.validUntil
};
return _retVal;
}
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return null;
}
public async Task<dynamic> GetFragmentListAsync(cDataFragmentsParams fragmentsParams, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var _webClient = await GetUserWebClient(requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested || _webClient == null)
return null;
var response = await _webClient.HttpEnh.GetAsync(GetFragmentUrlWithParameters(fragmentsParams), token);
if (token.IsCancellationRequested) return null;
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject(json);
}
}
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;
}
public async Task<dynamic> GetObjectAsync(string ci, Guid id, bool full, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (cPerformanceLogger.IsActive && requestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, requestInfo.id, requestInfo.created); }
var _startTime = DateTime.UtcNow;
try
{
var _webClient = await GetUserWebClient(requestInfo, LogDeep + 1, token);
if (token.IsCancellationRequested || _webClient == null)
return null;
var url = string.Format(constUrlObjectsGetObject, ci, id, full);
var response = await _webClient.HttpEnh.GetAsync(url, token);
if (token.IsCancellationRequested) return null;
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
if (token.IsCancellationRequested) return null;
return JsonConvert.DeserializeObject(json);
}
}
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;
}
static string RemoveEmptyQueryParameters(string url)
{
var uri = new Uri("http://dummy.com/" + url);
var queryParts = HttpUtility.ParseQueryString(uri.Query);
var newQuery = "";
foreach (string key in queryParts.AllKeys)
{
if (!string.IsNullOrEmpty(queryParts[key]))
{
newQuery += string.IsNullOrEmpty(newQuery) ? "?" : "&";
newQuery += $"{key}={queryParts[key]}";
}
}
string cleanedUrl = uri.AbsolutePath.Substring(1) + newQuery;
return cleanedUrl;
}
public HashSet<enumFasdInformationClass> GetSupportedInformationClasses() => new HashSet<enumFasdInformationClass>() { enumFasdInformationClass.Ticket };
public async Task<cF4sdStagedSearchResultRelations> GetRelationsAsync(IEnumerable<cF4sdIdentityEntry> ids, enumFasdInformationClass informationClass, int age, CancellationToken token = default)
{
try
{
List<cF4sdConnectorIds> ticketIds = await _collector.getConnectorIdList(ids.ToList(), token, null, 0);
List<cF4sdApiSearchResultRelation> relations = await getTicketUsage(ticketIds, token, null, 0);
return new cF4sdStagedSearchResultRelations() { Relations = relations };
}
catch (Exception ex)
{
LogException(ex);
}
return null;
}
}
public class cDataFragmentsParams
{
public string Ddname { get; set; }
public string Where { get; set; }
public string Columns { get; set; }
public int Pagesize { get; set; }
public int Pagenumber { get; set; }
public string Sort { get; set; }
}
public class cCreateJournalEntryInfo
{
public Guid ObjectId { get; set; }
public Guid TypeId { get; set; }
public bool Publish { get; set; }
public string Comments { get; set; }
public int EntryType { get; set; }
public Guid Creator { get; set; }
public bool VisibleInPortal { get; set; }
public List<Guid> FileIds { get; set; }
public List<Parameter> Parameters { get; set; }
public class Parameter
{
public string Name { get; set; }
public object Value { get; set; }
public string Format { get; set; }
public bool IsCurrency { get; set; }
}
}
public class cM42TransformTicketInfo
{
public Guid? Category { get; set; } = null;
public Guid? Sla { get; set; } = null;
public Guid? RecipientRole { get; set; } = null;
public string SourceTypeName { get; set; } = null;
public string TargetTypeName { get; set; } = null;
public List<Guid> ObjectIds { get; set; } = new List<Guid>();
public bool? UpdateFavoriteView { get; set; } = null;
public bool? RaiseCoRuTypeInsertEvent { get; set; } = null;
}
public class cM42ReopenTicketInfo
{
public string Reason { get; set; } = null;
public List<Guid> ObjectIds { get; set; } = new List<Guid>();
}
public class cM42TicketInfo
{
public JournalEntryData EntryData { get; set; }
public Guid? Asset { get; set; } = null;
public Guid? AffectedAsset { get; set; } = null;
public Guid? AffectedService { get; set; } = null;
public string UserReachableAt { get; set; } = null;
public int EntryBy { get; set; } = 0;
public int Classification { get; set; } = 0;
public Guid? QueueProfile { get; set; } = null;
public Guid? Template { get; set; } = null;
public Guid? Category { get; set; } = null;
public string Subject { get; set; } = null;
public string Description { get; set; } = null;
public string DescriptionHTML { get; set; } = null;
public string Solution { get; set; } = null;
public string SolutionHTML { get; set; } = null;
public int ActivityAction { get; set; } = 0;
public int TaskType { get; set; } = 0;
public int ErrorType { get; set; } = 0;
public int State { get; set; } = 0;
public int Priority { get; set; } = 0;
public int Impact { get; set; } = 0;
public int Urgency { get; set; } = 0;
public Guid? User { get; set; } = null;
public Guid? ResponsibleUser { get; set; } = null;
public Guid? ResponsibleRole { get; set; } = null;
public Guid? Service { get; set; } = null;
public Guid? SLA { get; set; } = null;
public string TicketNumber { get; set; } = null;
public DateTime Deadline { get; set; } = DateTime.UtcNow;
public bool NotifyResponsible { get; set; } = false;
public int NotificationMode { get; set; } = 0;
public bool CloseOnTasksCompletion { get; set; } = false;
public Guid? WorkflowId { get; set; } = null;
public List<Guid> RelatedUsers { get; set; } = new List<Guid>();
public List<Guid> RelatedServices { get; set; } = new List<Guid>();
public List<Guid> SimpleServiceForms { get; set; } = new List<Guid>();
public List<Guid> ConfigurationItems { get; set; } = new List<Guid>();
public List<Guid> RelatedTasks { get; set; } = new List<Guid>();
public List<Guid> RelatedAssets { get; set; } = new List<Guid>();
public List<Guid> RelatedIncidents { get; set; } = new List<Guid>();
public List<Guid> RelatedProblems { get; set; } = new List<Guid>();
public bool NewInformationReceived { get; set; } = false;
public bool SkipSettingOwner { get; set; } = false;
public bool RecalculateResponsibleRole { get; set; } = false;
public List<ExtraProperty> ExtraProperties { get; set; } = new List<ExtraProperty>();
}
public class JournalEntryData
{
public Guid? ObjectId { get; set; } = null;
public Guid? TypeId { get; set; } = null;
public bool Publish { get; set; } = false;
public string Comments { get; set; } = null;
public int EntryType { get; set; } = 0;
public Guid? Creator { get; set; } = null;
public bool VisibleInPortal { get; set; } = false;
public List<Parameter> Parameters { get; set; } = new List<Parameter>();
public bool SkipRaiseCoRuEvent { get; set; } = false;
}
public class Parameter
{
public bool IsPortalMode { get; set; } = false;
public bool IsExportMode { get; set; } = false;
public string Name { get; set; } = null;
}
public class ExtraProperty
{
public string Name { get; set; } = null;
public object Value { get; set; } = null;
}
}
public class cM42DataQueryRelationInfo
{
public int ClientTimeOffset { get; set; } = 0;
public string EntityClassName { get; set; }
public string EntityTypeName { get; set; }
public string AddedRelations { get; set; } = "";
public string RemovedRelations { get; set; } = "";
public string WhereExpression { get; set; } = "";
public cM42QueryFilterGroup AdditionalFilter { get; set; } = new cM42QueryFilterGroup();
public int pageSize { get; set; } = 20;
public int page { get; set; } = 0;
public bool totalCounted { get; set; } = false;
public string search { get; set; } = "";
public string orderBy { get; set; } = "";
public string columns { get; set; }
}
public class cM42DataQueryRelationInfo2
{
public int ClientTimeOffset { get; set; } = 0;
public string EntityClassName { get; set; }
public string EntityTypeName { get; set; }
public string AddedRelations { get; set; } = "";
public string RemovedRelations { get; set; } = "";
public string WhereExpression { get; set; } = "";
public cM42QueryFilterGroup AdditionalFilter { get; set; } = new cM42QueryFilterGroup();
public int pageSize { get; set; } = 0;
public int page { get; set; } = 0;
public string search { get; set; } = "";
public string orderBy { get; set; } = "";
public string columns { get; set; }
public string RelationName { get; set; }
public Guid FragmentId { get; set; }
public bool Archived { get; set; } = false;
public string Filters { get; set; } = "";
}
public class cM42QueryFilterGroup
{
public cM42QueryFilterCondition[] Conditions { get; set; } = new cM42QueryFilterCondition[0];
public cM42QueryFilterGroup[] Groups { get; set; } = new cM42QueryFilterGroup[0];
public int LogicalOperator { get; set; } = 1;
}
public class cM42QueryFilterCondition
{
public int Operator { get; set; }
public string Property { get; set; }
public string[] Value { get; set; }
public bool IsExpression { get; set; }
public bool DenyWildcard { get; set; }
}
public class cF4SDTicketSummary
{
public Guid TicketObjectId { get; set; }
public string Name { get; set; }
public string ActivityType { get; set; }
public string Summary { get; set; }
public string Sid { get; set; }
public string Status { get; set; }
public int StatusId { get; set; }
public string AssetCIName { get; set; }
public string AssetName { get; set; }
public string ServiceName { get; set; }
public Guid ServiceId { get; set; }
public bool IsPrimaryAccount { get; set; }
public Guid UserId { get; set; }
}
public class M42UserUserInfo
{
public class M42User
{
public Guid Id { get; set; } = Guid.Empty;
public Guid ObjectId { get; set; }
public string Name { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Photo { get; set; }
public string Phone { get; set; }
public string Currency { get; set; }
public string Locale { get; set; }
public int LanguageId { get; set; }
public bool IsAdmin { get; set; }
public int State { get; set; }
public string StateDisp { get; set; }
}
public class M42Role
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public M42User User { get; set; }
public List<M42Role> Roles { get; set; }
}