Use authenticated Matrix42 user IDs for ticket overview

This commit is contained in:
Drechsler, Meik
2026-07-23 18:23:08 +02:00
parent 52e74deb57
commit f8a7b32c57

View File

@@ -99,6 +99,7 @@ namespace C4IT.DataHistoryProvider
private Dictionary<WebClientCacheIndex, WebClientCacheEntry> UserWebClientCache = new Dictionary<WebClientCacheIndex, WebClientCacheEntry>();
private readonly object _ticketOverviewCacheLock = new object();
private readonly Dictionary<Guid, Guid> _ticketOverviewUserIds = new Dictionary<Guid, Guid>();
[Obsolete]
private readonly Dictionary<string, TicketOverviewCountCacheEntry> _ticketOverviewPersonalCache = new Dictionary<string, TicketOverviewCountCacheEntry>(StringComparer.OrdinalIgnoreCase);
@@ -1212,8 +1213,60 @@ namespace C4IT.DataHistoryProvider
urlBuilder.Append("&queues=").Append(encodedQueues);
}
private void CacheTicketOverviewUserId(Guid cockpitUserId, Guid matrix42UserId)
{
if (cockpitUserId == Guid.Empty || matrix42UserId == Guid.Empty)
return;
lock (_ticketOverviewCacheLock)
_ticketOverviewUserIds[cockpitUserId] = matrix42UserId;
}
private async Task<Guid> ResolveTicketOverviewUserIdAsync(
cF4sdWebRequestInfo requestInfo,
int logDeep,
CancellationToken token)
{
var cockpitUserId = requestInfo?.userInfo?.Id ?? Guid.Empty;
if (cockpitUserId == Guid.Empty)
return Guid.Empty;
lock (_ticketOverviewCacheLock)
{
if (_ticketOverviewUserIds.TryGetValue(cockpitUserId, out var cachedUserId))
return cachedUserId;
}
var sid = requestInfo?.userInfo?.AdSid;
if (!string.IsNullOrWhiteSpace(sid))
{
var userInfo = await GetM42UserInfoAsync(sid, token);
var matrix42UserId = userInfo?.User?.Id ?? Guid.Empty;
if (matrix42UserId != Guid.Empty)
{
CacheTicketOverviewUserId(cockpitUserId, matrix42UserId);
return matrix42UserId;
}
}
var userWebClient = await GetUserWebClient(requestInfo, logDeep + 1, token);
if (userWebClient != null)
{
var userInfo = await userWebClient.GetUserInfoAsync(token);
var matrix42UserId = userInfo?.User?.Id ?? Guid.Empty;
if (matrix42UserId != Guid.Empty)
{
CacheTicketOverviewUserId(cockpitUserId, matrix42UserId);
return matrix42UserId;
}
}
LogEntry($"Could not resolve a Matrix42 user ID for authenticated F4SD user {cockpitUserId}. Ticket overview request was skipped.", LogLevels.Warning);
return Guid.Empty;
}
private async Task<Dictionary<string, int>> FetchTicketOverviewCountsAsync(
string sid,
Guid userId,
string scope,
IReadOnlyCollection<string> requestedKeys,
cF4sdWebRequestInfo requestInfo,
@@ -1224,27 +1277,12 @@ namespace C4IT.DataHistoryProvider
var wc = await GetWebClient(requestInfo, token);
var request = new cTicketOverviewFilterRequest
{
Sid = sid,
UserId = userId,
Scope = scope,
Keys = requestedKeys?.ToList() ?? new List<string>(),
Filters = GetTicketFilters()
};
var res = await PostJsonAsync(wc, constUrlGetTicketOverviewCountsV2, request, token);
if (res?.StatusCode == HttpStatusCode.NotFound)
{
if (!TryGetLegacyQueueFilter(out var queueOption, out var encodedQueues))
{
LogEntry("The ticket filter policy requires the v2 overview API; legacy fallback was rejected (fail closed).", LogLevels.Warning);
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
}
var urlBuilder = new StringBuilder(constUrlGetTicketOverviewCounts);
urlBuilder.Append("?sid=").Append(HttpUtility.UrlEncode(sid));
urlBuilder.Append("&scope=").Append(HttpUtility.UrlEncode(scope ?? string.Empty));
if (requestedKeys != null && requestedKeys.Count > 0)
urlBuilder.Append("&keys=").Append(HttpUtility.UrlEncode(string.Join(",", requestedKeys)));
AppendQueueFilterQuery(urlBuilder, queueOption, encodedQueues);
res = await wc.HttpEnh.GetAsync(urlBuilder.ToString(), token);
}
if (token.IsCancellationRequested)
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
@@ -1308,8 +1346,8 @@ namespace C4IT.DataHistoryProvider
if (!await CheckOnline())
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
var sid = requestInfo?.userInfo?.AdSid;
if (string.IsNullOrWhiteSpace(sid))
var userId = await ResolveTicketOverviewUserIdAsync(requestInfo, LogDeep, Token);
if (userId == Guid.Empty)
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
var normalizedKeys = (keys ?? Enumerable.Empty<string>())
@@ -1317,7 +1355,7 @@ namespace C4IT.DataHistoryProvider
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
var scope = useRoleScope ? "role" : "personal";
return await FetchTicketOverviewCountsAsync(sid, scope, normalizedKeys, requestInfo, Token);
return await FetchTicketOverviewCountsAsync(userId, scope, normalizedKeys, requestInfo, Token);
}
catch (Exception E)
{
@@ -1346,36 +1384,21 @@ namespace C4IT.DataHistoryProvider
if (string.IsNullOrWhiteSpace(key))
return new List<cF4sdApiSearchResultRelation>();
var sid = requestInfo?.userInfo?.AdSid;
if (string.IsNullOrWhiteSpace(sid))
var userId = await ResolveTicketOverviewUserIdAsync(requestInfo, LogDeep, Token);
if (userId == Guid.Empty)
return new List<cF4sdApiSearchResultRelation>();
var scope = useRoleScope ? "role" : "personal";
var wc = await GetWebClient(requestInfo, Token);
var request = new cTicketOverviewFilterRequest
{
Sid = sid,
UserId = userId,
Scope = scope,
Key = key,
Count = Math.Max(0, count),
Filters = GetTicketFilters()
};
var res = await PostJsonAsync(wc, constUrlGetTicketOverviewRelationsV2, request, Token);
if (res?.StatusCode == HttpStatusCode.NotFound)
{
if (!TryGetLegacyQueueFilter(out var queueOption, out var encodedQueues))
{
LogEntry("The ticket filter policy requires the v2 relation API; legacy fallback was rejected (fail closed).", LogLevels.Warning);
return new List<cF4sdApiSearchResultRelation>();
}
var urlBuilder = new StringBuilder(constUrlGetTicketOverviewRelations);
urlBuilder.Append("?sid=").Append(HttpUtility.UrlEncode(sid));
urlBuilder.Append("&scope=").Append(HttpUtility.UrlEncode(scope));
urlBuilder.Append("&key=").Append(HttpUtility.UrlEncode(key));
urlBuilder.Append("&count=").Append(Math.Max(0, count));
AppendQueueFilterQuery(urlBuilder, queueOption, encodedQueues);
res = await wc.HttpEnh.GetAsync(urlBuilder.ToString(), Token);
}
if (Token.IsCancellationRequested)
return new List<cF4sdApiSearchResultRelation>();
@@ -2357,6 +2380,8 @@ namespace C4IT.DataHistoryProvider
if (Token.IsCancellationRequested)
return;
CacheTicketOverviewUserId(userInfo.Id, _M42UserInfo?.User?.Id ?? Guid.Empty);
// if yes, set M42 for an addidional automatic logon possibility
if (_M42UserInfo?.User != null)
{
@@ -2431,6 +2456,8 @@ namespace C4IT.DataHistoryProvider
// get the role memberships relatet to the M42 roles
if (m42UserInfo?.User?.Id != null)
{
CacheTicketOverviewUserId(userInfo.Id, (Guid)m42UserInfo.User.Id);
var _F4SDRoles = await GetF4SDRoles((Guid)m42UserInfo.User.Id, Token);
if (_F4SDRoles?.Count > 0)