Add provider-aware activity filter API

This commit is contained in:
Drechsler, Meik
2026-07-23 11:09:14 +02:00
parent af679472db
commit 083fdf01dc
11 changed files with 728 additions and 74 deletions

View File

@@ -0,0 +1,63 @@
using System.Collections.Generic;
using System;
using System.Threading;
using System.Threading.Tasks;
using C4IT.FASD.Base;
using C4IT.Logging;
using static C4IT.Logging.cLogManager;
namespace C4IT.F4SD
{
public partial class F4SDHelperService
{
private static readonly AsyncLocal<cActivityFilterPolicy> currentActivityFilters =
new AsyncLocal<cActivityFilterPolicy>();
private sealed class ActivityFilterScope : IDisposable
{
private readonly cActivityFilterPolicy previous;
public ActivityFilterScope(cActivityFilterPolicy filters)
{
previous = currentActivityFilters.Value;
currentActivityFilters.Value = filters;
}
public void Dispose()
{
currentActivityFilters.Value = previous;
}
}
internal IDisposable BeginActivityFilterScope(cActivityFilterPolicy filters)
{
return new ActivityFilterScope(filters);
}
internal async Task<string> ApplyActivityFiltersAsync(string baseFilter, cActivityFilterPolicy policy)
{
var result = await ActivityFilterCompiler.CompileAsync(policy ?? currentActivityFilters.Value, null);
if (!result.Success)
{
LogEntry($"Activity filter rejected (fail closed): {result.Error}", LogLevels.Error);
return null;
}
return string.IsNullOrWhiteSpace(result.Clause)
? baseFilter
: $"({baseFilter}) AND ({result.Clause})";
}
internal cTicketActivityFilterCapabilities GetActivityFilterCapabilities()
{
return new cTicketActivityFilterCapabilities
{
Provider = ActivityFilterCompiler.ProviderName,
CommonFields = new List<string> { ActivityFilterCompiler.AssignmentGroupField },
ProviderFields = new List<string> { ActivityFilterCompiler.QueueField }
};
}
}
}

View File

@@ -54,8 +54,10 @@
<ItemGroup>
<Compile Include="cM42LogEntry.cs" />
<Compile Include="ActivityFilterService.cs" />
<Compile Include="F4SDHelperService.cs" />
<Compile Include="F4SDM42WebApiController.cs" />
<Compile Include="..\..\Shared\ActivityFilterCompiler.cs"><Link>Shared\ActivityFilterCompiler.cs</Link></Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="..\..\SharedAssemblyInfo.cs"><Link>Properties\SharedAssemblyInfo.cs</Link></Compile>
</ItemGroup>

View File

@@ -29,7 +29,7 @@ using static C4IT.Logging.cLogManager;
namespace C4IT.F4SD
{
public class F4SDHelperService
public partial class F4SDHelperService
{
private static Guid SPSUserClassBaseID = SPSDataEngineSchemaReader.ClassGetIDFromName("SPSUserClassBase");
private static Guid SPSAccountClassBaseID = SPSDataEngineSchemaReader.ClassGetIDFromName("SPSAccountClassBase");
@@ -166,6 +166,9 @@ namespace C4IT.F4SD
var tickets = new List<cF4SDTicketSummary>();
var activityFilter = GetActivityFilter(userSid, hours, ticketAndServiceRequestEnabled(), queueoption, queues);
activityFilter = await ApplyActivityFiltersAsync(activityFilter, null);
if (string.IsNullOrWhiteSpace(activityFilter))
return new List<cF4SDTicketSummary>();
LogEntry($"ASql Filter: {activityFilter}");
var activityTable = FragmentRequestBase.SimpleLoad(SPSActivityClassBaseID,
@@ -279,6 +282,9 @@ namespace C4IT.F4SD
var tickets = new List<cF4SDTicketSummary>();
var activityFilter = GetActivityFilter(userId, hours, ticketAndServiceRequestEnabled(), queueoption, queues);
activityFilter = await ApplyActivityFiltersAsync(activityFilter, null);
if (string.IsNullOrWhiteSpace(activityFilter))
return new List<cF4SDTicketSummary>();
LogEntry($"ASql Filter: {activityFilter}");
var activityTable = FragmentRequestBase.SimpleLoad(SPSActivityClassBaseID,
@@ -982,6 +988,7 @@ namespace C4IT.F4SD
var roleIds = await ResolveTicketOverviewRoleIdsAsync(sid, null);
var filter = BuildTicketOverviewFilterForRoleIds(roleIds, null, queueoption, queues);
filter = await ApplyActivityFiltersAsync(filter, null);
if (string.IsNullOrWhiteSpace(filter))
return new List<TicketOverviewEntry>();
@@ -1015,6 +1022,7 @@ namespace C4IT.F4SD
var roleIds = await ResolveTicketOverviewRoleIdsAsync(userId, null);
var filter = BuildTicketOverviewFilterForRoleIds(roleIds, null, queueoption, queues);
filter = await ApplyActivityFiltersAsync(filter, null);
if (string.IsNullOrWhiteSpace(filter))
return new List<TicketOverviewEntry>();
@@ -1044,6 +1052,7 @@ namespace C4IT.F4SD
await Task.Delay(0);
var filter = BuildTicketOverviewFilterForRoleIds(roleIds, null, queueoption, queues);
filter = await ApplyActivityFiltersAsync(filter, null);
return await LoadTicketOverviewEntriesByFilter(filter);
}
catch (Exception E)
@@ -1195,11 +1204,12 @@ namespace C4IT.F4SD
{
var recipientFilter = $"Recipient.Accounts.T(SPSAccountClassAd).Sid = '{Escape(sid)}'";
filter += $" AND ({recipientFilter})";
return filter;
return await ApplyActivityFiltersAsync(filter, null);
}
var roleIds = await ResolveTicketOverviewRoleIdsAsync(sid, null);
return BuildTicketOverviewFilterForRoleIds(roleIds, filter);
filter = BuildTicketOverviewFilterForRoleIds(roleIds, filter);
return await ApplyActivityFiltersAsync(filter, null);
}
private async Task<string> BuildTicketOverviewFilterAsync(
@@ -1214,11 +1224,12 @@ namespace C4IT.F4SD
{
var recipientFilter = $"Recipient = '{Escape(userId.ToString("D"))}'";
filter += $" AND ({recipientFilter})";
return filter;
return await ApplyActivityFiltersAsync(filter, null);
}
var roleIds = await ResolveTicketOverviewRoleIdsAsync(userId, null);
return BuildTicketOverviewFilterForRoleIds(roleIds, filter);
filter = BuildTicketOverviewFilterForRoleIds(roleIds, filter);
return await ApplyActivityFiltersAsync(filter, null);
}
private string BuildTicketOverviewBaseFilter(int queueoption, List<cApiM42TicketQueueInfo> queues)

View File

@@ -138,6 +138,26 @@ namespace C4IT.F4SD
);
}
[Route("v2/getTicketList"), HttpPost]
public async Task<List<cF4SDTicketSummary>> getTicketListV2([FromBody] cTicketActivityListRequest request)
{
using (_f4stHelperService.BeginActivityFilterScope(request?.Filters))
{
if (request?.UserId != Guid.Empty)
return await _f4stHelperService.getTicketListByUser(
request.UserId,
request.Hours,
0,
new List<cApiM42TicketQueueInfo>()) ?? new List<cF4SDTicketSummary>();
return await _f4stHelperService.getTicketListByUser(
request?.Sid ?? string.Empty,
request?.Hours ?? 0,
0,
new List<cApiM42TicketQueueInfo>()) ?? new List<cF4SDTicketSummary>();
}
}
[Route("getTicketDetails"), HttpGet]
public async Task<F4SDHelperService.cF4SDTicket> getTicketDetails(Guid objectId)
@@ -193,6 +213,29 @@ namespace C4IT.F4SD
return await _f4stHelperService.getTicketOverviewCounts(userId, scope, parsedKeys, queueoption, decodedQueues);
}
[Route("v2/getTicketOverviewCounts"), HttpPost]
public async Task<F4SDHelperService.TicketOverviewCountsResult> getTicketOverviewCountsV2(
[FromBody] cTicketOverviewFilterRequest request)
{
using (_f4stHelperService.BeginActivityFilterScope(request?.Filters))
{
if (request?.UserId != Guid.Empty)
return await _f4stHelperService.getTicketOverviewCounts(
request.UserId,
request.Scope,
request.Keys,
0,
new List<cApiM42TicketQueueInfo>()) ?? new F4SDHelperService.TicketOverviewCountsResult();
return await _f4stHelperService.getTicketOverviewCounts(
request?.Sid ?? string.Empty,
request?.Scope ?? "personal",
request?.Keys ?? new List<string>(),
0,
new List<cApiM42TicketQueueInfo>()) ?? new F4SDHelperService.TicketOverviewCountsResult();
}
}
[Obsolete]
[Route("getTicketOverviewCountsByRoles"), HttpPost]
public async Task<F4SDHelperService.TicketOverviewCountsByRoleResult> getTicketOverviewCountsByRoles([FromBody] TicketOverviewCountsByRolesRequest request)
@@ -269,6 +312,37 @@ namespace C4IT.F4SD
return await _f4stHelperService.getTicketOverviewRelations(userId, scope, key, count, queueoption, decodedQueues);
}
[Route("v2/getTicketOverviewRelations"), HttpPost]
public async Task<List<F4SDHelperService.TicketOverviewRelationDto>> getTicketOverviewRelationsV2(
[FromBody] cTicketOverviewFilterRequest request)
{
using (_f4stHelperService.BeginActivityFilterScope(request?.Filters))
{
if (request?.UserId != Guid.Empty)
return await _f4stHelperService.getTicketOverviewRelations(
request.UserId,
request.Scope,
request.Key,
request.Count,
0,
new List<cApiM42TicketQueueInfo>()) ?? new List<F4SDHelperService.TicketOverviewRelationDto>();
return await _f4stHelperService.getTicketOverviewRelations(
request?.Sid ?? string.Empty,
request?.Scope ?? "personal",
request?.Key ?? string.Empty,
request?.Count ?? 0,
0,
new List<cApiM42TicketQueueInfo>()) ?? new List<F4SDHelperService.TicketOverviewRelationDto>();
}
}
[Route("v2/getActivityFilterCapabilities"), HttpGet]
public cTicketActivityFilterCapabilities getActivityFilterCapabilitiesV2()
{
return _f4stHelperService.GetActivityFilterCapabilities();
}
/*
[Route("updateActivitySolution/{objectId}"), HttpPost]