Add generic ticket activity filters
This commit is contained in:
@@ -302,9 +302,12 @@
|
|||||||
<Compile Include="..\F4SD-Cockpit-ServerCore\DataSources\IRemoteDesktopManager.cs">
|
<Compile Include="..\F4SD-Cockpit-ServerCore\DataSources\IRemoteDesktopManager.cs">
|
||||||
<Link>DataSources\IRemoteDesktopManager.cs</Link>
|
<Link>DataSources\IRemoteDesktopManager.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\F4SD-Cockpit-ServerCore\DataSources\ISearchResultRelationProvider.cs">
|
<Compile Include="..\F4SD-Cockpit-ServerCore\DataSources\ISearchResultRelationProvider.cs">
|
||||||
<Link>DataSources\ISearchResultRelationProvider.cs</Link>
|
<Link>DataSources\ISearchResultRelationProvider.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\F4SD-Cockpit-ServerCore\DataSources\ITicketActivityProvider.cs">
|
||||||
|
<Link>DataSources\ITicketActivityProvider.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\F4SD-Cockpit-ServerCore\F4SDConfigGlobalParametersXml.cs">
|
<Compile Include="..\F4SD-Cockpit-ServerCore\F4SDConfigGlobalParametersXml.cs">
|
||||||
<Link>F4SDConfigGlobalParametersXml.cs</Link>
|
<Link>F4SDConfigGlobalParametersXml.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -381,4 +384,4 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Error Condition="!Exists('..\packages\System.ValueTuple.4.6.1\build\net471\System.ValueTuple.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\System.ValueTuple.4.6.1\build\net471\System.ValueTuple.targets'))" />
|
<Error Condition="!Exists('..\packages\System.ValueTuple.4.6.1\build\net471\System.ValueTuple.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\System.ValueTuple.4.6.1\build\net471\System.ValueTuple.targets'))" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -24,6 +24,22 @@
|
|||||||
<TicketTypeProcessing Type="UnclassifiedTicket" Value="intern" />
|
<TicketTypeProcessing Type="UnclassifiedTicket" Value="intern" />
|
||||||
<TicketTypeProcessing Type="Incident" Value="intern" />
|
<TicketTypeProcessing Type="Incident" Value="intern" />
|
||||||
</TicketProcessing>
|
</TicketProcessing>
|
||||||
|
<ActivityFilters>
|
||||||
|
<Filter Provider="Matrix42" Field="Queue" Enabled="false" Match="include" EmptyHandling="include">
|
||||||
|
<Value ID="2a7e8099-3d57-f011-1988-00155d320605" Name="HR" />
|
||||||
|
<Value ID="2a7a8099-3d47-f011-1988-00155d320505" Name="FM" />
|
||||||
|
</Filter>
|
||||||
|
<Filter Field="AssignmentGroup" Enabled="false" Match="include" EmptyHandling="exclude">
|
||||||
|
<Value ID="0a76de08-136c-764a-b410-5610e8076712" Name="HR Service Desk Agent" />
|
||||||
|
<Value ID="0b76de08-8668-a026-b410-5610e8076f95" Name="HR-Manager" />
|
||||||
|
<Value ID="0a76de08-d589-4c94-b410-5610e8076919" Name="HR-Spezialist" />
|
||||||
|
<Value ID="e87dde08-235c-04e5-b410-562b64035575" Name="Facility-Koordinator" />
|
||||||
|
</Filter>
|
||||||
|
<Filter Provider="Matrix42" Field="Workspace" Enabled="false" Match="include" EmptyHandling="exclude">
|
||||||
|
<Value ID="1676de08-27f3-550c-b410-5610e807aa02" Name="HR Service Management" />
|
||||||
|
<Value ID="ed7dde08-199e-c27b-b410-562b64037aa1" Name="Gebäudemanagement" />
|
||||||
|
</Filter>
|
||||||
|
</ActivityFilters>
|
||||||
<OverviewPollingPersonal Policy="Mandatory" Value="10" />
|
<OverviewPollingPersonal Policy="Mandatory" Value="10" />
|
||||||
<OverviewPollingRole Policy="Mandatory" Value="5" />
|
<OverviewPollingRole Policy="Mandatory" Value="5" />
|
||||||
</TicketConfiguration>
|
</TicketConfiguration>
|
||||||
|
|||||||
@@ -132,6 +132,21 @@
|
|||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:simpleType name="ActivityFilterMatchEnum">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="include"/>
|
||||||
|
<xs:enumeration value="exclude"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="ActivityFilterEmptyHandlingEnum">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="include"/>
|
||||||
|
<xs:enumeration value="exclude"/>
|
||||||
|
<xs:enumeration value="only"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
<xs:element name="TicketConfiguration">
|
<xs:element name="TicketConfiguration">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:all>
|
<xs:all>
|
||||||
@@ -182,6 +197,30 @@
|
|||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name="ActivityFilters" minOccurs="0" maxOccurs="1">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="Filter" minOccurs="0" maxOccurs="unbounded">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="Value" minOccurs="0" maxOccurs="unbounded">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name="ID" type="xs:string" use="optional"/>
|
||||||
|
<xs:attribute name="Name" type="xs:string" use="optional"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="Provider" type="xs:string" use="optional"/>
|
||||||
|
<xs:attribute name="Field" type="xs:string" use="required"/>
|
||||||
|
<xs:attribute name="Enabled" type="xs:boolean" use="optional" default="false"/>
|
||||||
|
<xs:attribute name="Match" type="ActivityFilterMatchEnum" use="optional" default="exclude"/>
|
||||||
|
<xs:attribute name="EmptyHandling" type="ActivityFilterEmptyHandlingEnum" use="optional" default="include"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
<xs:element name="TicketProcessing" minOccurs="0" maxOccurs="1">
|
<xs:element name="TicketProcessing" minOccurs="0" maxOccurs="1">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
|
|||||||
@@ -82,15 +82,11 @@
|
|||||||
</Azure-Tenant>
|
</Azure-Tenant>
|
||||||
<!--<Azure-Tenant Domain="sd0024.onmicrosoft.com" TenantID="07362148-410e-4636-a9cb-795fba1a5452" Credential="AzureAccess_Dieter"/>-->
|
<!--<Azure-Tenant Domain="sd0024.onmicrosoft.com" TenantID="07362148-410e-4636-a9cb-795fba1a5452" Credential="AzureAccess_Dieter"/>-->
|
||||||
</Azure-AD>
|
</Azure-AD>
|
||||||
<Matrix42-WPM Server="srvwsm001.imagoverum.com" Credential="M42API-Demo-26-1" ClosedTicketHistory="9999" DisplayName="M42 Demo server (imagoverum)" ApiTokenLifetime ="30 days" ActivityQueueFilter="showAll">
|
<Matrix42-WPM Server="srvwsm001.imagoverum.com" Credential="M42API-Demo-26-1" ClosedTicketHistory="9999" DisplayName="M42 Demo server (imagoverum)" ApiTokenLifetime ="30 days">
|
||||||
<Matrix42-Ticket DisableAutomaticTimeTracking="1"
|
<Matrix42-Ticket DisableAutomaticTimeTracking="1"
|
||||||
ShowDocumentCaseDialog="ifRequired"/>
|
ShowDocumentCaseDialog="ifRequired"/>
|
||||||
<DisplayName Lang="DE">M42 Demo Server (Imagoverum)</DisplayName>
|
<DisplayName Lang="DE">M42 Demo Server (Imagoverum)</DisplayName>
|
||||||
<Queues>
|
</Matrix42-WPM>
|
||||||
<Queue QueueName="HR" QueueID="2a7e8099-3d57-f011-1988-00155d320605" />
|
|
||||||
<Queue QueueName="FM" QueueID="2a7a8099-3d47-f011-1988-00155d320505" />
|
|
||||||
</Queues>
|
|
||||||
</Matrix42-WPM>
|
|
||||||
<!--<Matrix42-WPM Server="m42server.imagoverum.com" Credential="M42API-Demo-Dieter" ClosedTicketHistory="9999"/>-->
|
<!--<Matrix42-WPM Server="m42server.imagoverum.com" Credential="M42API-Demo-Dieter" ClosedTicketHistory="9999"/>-->
|
||||||
<Nexthink>
|
<Nexthink>
|
||||||
<Scan-Timing ScanInterval="24:00" ScanOffset="00:10" Timezone="W. Europe Standard Time"/>
|
<Scan-Timing ScanInterval="24:00" ScanOffset="00:10" Timezone="W. Europe Standard Time"/>
|
||||||
|
|||||||
@@ -276,7 +276,8 @@ namespace C4IT.DataHistoryProvider
|
|||||||
public readonly Dictionary<enumDataHistoryOrigin, cDataHistoryCollectorModule> Connectors = new Dictionary<enumDataHistoryOrigin, cDataHistoryCollectorModule>();
|
public readonly Dictionary<enumDataHistoryOrigin, cDataHistoryCollectorModule> Connectors = new Dictionary<enumDataHistoryOrigin, cDataHistoryCollectorModule>();
|
||||||
public readonly cDataHistoryCollectorActiveDirectory ActiveDirectory = null;
|
public readonly cDataHistoryCollectorActiveDirectory ActiveDirectory = null;
|
||||||
public readonly cDataHistoryCollectorClientAgent F4sdAgent = null;
|
public readonly cDataHistoryCollectorClientAgent F4sdAgent = null;
|
||||||
public cDataHistoryCollectorM42Wpm M42WpmCollector { get; private set; } = null;
|
public cDataHistoryCollectorM42Wpm M42WpmCollector { get; private set; } = null;
|
||||||
|
public ITicketActivityProvider TicketActivityProvider { get; private set; } = null;
|
||||||
public cDataHistoryCollectorNxql NxqlCollector { get; private set; } = null;
|
public cDataHistoryCollectorNxql NxqlCollector { get; private set; } = null;
|
||||||
public cDataHistoryCollectorCitrix CitrixCollector { get; private set; } = null;
|
public cDataHistoryCollectorCitrix CitrixCollector { get; private set; } = null;
|
||||||
//public cDataHistoryCollectorEmpirum EmpirumCollector { get; private set; } = null;
|
//public cDataHistoryCollectorEmpirum EmpirumCollector { get; private set; } = null;
|
||||||
@@ -409,10 +410,12 @@ namespace C4IT.DataHistoryProvider
|
|||||||
|
|
||||||
GlobalParametersConfigFile = _cfgGlobalParameters;
|
GlobalParametersConfigFile = _cfgGlobalParameters;
|
||||||
|
|
||||||
GlobalConfig = new cF4sdGlobalConfig(regPath: null);
|
GlobalConfig = new cF4sdGlobalConfig(regPath: null);
|
||||||
if (GlobalParametersConfigFile.Parameters != null)
|
if (GlobalParametersConfigFile.Parameters != null)
|
||||||
GlobalConfig.Load(CentralParameters: GlobalParametersConfigFile.Parameters);
|
GlobalConfig.Load(CentralParameters: GlobalParametersConfigFile.Parameters);
|
||||||
}
|
GlobalConfig.TicketConfiguration.ActivityFilters =
|
||||||
|
GlobalParametersConfigFile.ActivityFilters ?? new cActivityFilterPolicy();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -514,8 +517,9 @@ namespace C4IT.DataHistoryProvider
|
|||||||
if (cF4SDLicense.Instance?.Modules != null)
|
if (cF4SDLicense.Instance?.Modules != null)
|
||||||
if (cF4SDLicense.Instance.Modules.ContainsKey(_M42WpmCollector.LicenseId))
|
if (cF4SDLicense.Instance.Modules.ContainsKey(_M42WpmCollector.LicenseId))
|
||||||
{
|
{
|
||||||
M42WpmCollector = _M42WpmCollector;
|
M42WpmCollector = _M42WpmCollector;
|
||||||
Connectors.Add(enumDataHistoryOrigin.M42Wpm, M42WpmCollector);
|
TicketActivityProvider = _M42WpmCollector;
|
||||||
|
Connectors.Add(enumDataHistoryOrigin.M42Wpm, M42WpmCollector);
|
||||||
RegisterSearchRelationProvider(_M42WpmCollector);
|
RegisterSearchRelationProvider(_M42WpmCollector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
@@ -31,14 +32,17 @@ using static C4IT.Matrix42.WebClient.cM42WebClient;
|
|||||||
|
|
||||||
namespace C4IT.DataHistoryProvider
|
namespace C4IT.DataHistoryProvider
|
||||||
{
|
{
|
||||||
public class cDataHistoryCollectorM42Wpm : cDataHistoryCollectorModule, ISearchResultRelationProvider
|
public class cDataHistoryCollectorM42Wpm : cDataHistoryCollectorModule, ISearchResultRelationProvider, ITicketActivityProvider
|
||||||
{
|
{
|
||||||
public const string constConnectorName = "Matrix42 WPM conntector";
|
public const string constConnectorName = "Matrix42 WPM conntector";
|
||||||
public const string constLicenseId = "9CE1A6BE-6A0C-4A27-94A5-44AB997B8E62";
|
public const string constLicenseId = "9CE1A6BE-6A0C-4A27-94A5-44AB997B8E62";
|
||||||
|
|
||||||
private const string constUrlIsAlive = "m42Services/api/c4itf4sdwebapi/isalive";
|
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 constUrlGetTickets = "m42Services/api/c4itf4sdwebapi/getticketlist?sid={0}&hours={1}&queueoption={2}";
|
||||||
private const string constUrlGetTicketsQueuesParam = "&queues={0}";
|
private const string constUrlGetTicketsQueuesParam = "&queues={0}";
|
||||||
|
private const string constUrlGetTicketsV2 = "m42Services/api/c4itf4sdwebapi/v2/getticketlist";
|
||||||
|
private const string constUrlGetTicketOverviewCountsV2 = "m42Services/api/c4itf4sdwebapi/v2/getticketoverviewcounts";
|
||||||
|
private const string constUrlGetTicketOverviewRelationsV2 = "m42Services/api/c4itf4sdwebapi/v2/getticketoverviewrelations";
|
||||||
private const string constUrlGetTicketDetails = "m42Services/api/c4itf4sdwebapi/getticketdetails?objectid={0}";
|
private const string constUrlGetTicketDetails = "m42Services/api/c4itf4sdwebapi/getticketdetails?objectid={0}";
|
||||||
private const string constUrlGetTicketHistory = "m42Services/api/c4itf4sdwebapi/gettickethistory?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 constUrlGetCreateTicket = "m42Services/api/c4itf4sdwebapi/getdirectlinkcreateticket?sid={0}{1}";
|
||||||
@@ -687,24 +691,33 @@ namespace C4IT.DataHistoryProvider
|
|||||||
if (!await CheckOnline())
|
if (!await CheckOnline())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var objSid = new SecurityIdentifier(UserId.sid, 0);
|
var objSid = new SecurityIdentifier(UserId.sid, 0);
|
||||||
var strSid = objSid.ToString();
|
var strSid = objSid.ToString();
|
||||||
var queueOption = (int)Collector.InfrastructureConfig.M42Wpm.ActivityQueueFilterOption;
|
var _wc = await GetWebClient(requestInfo, Token);
|
||||||
var strUrl = string.Format(constUrlGetTickets,
|
var request = new cTicketActivityListRequest
|
||||||
strSid,
|
{
|
||||||
Collector.InfrastructureConfig.M42Wpm.ClosedTicketHistory,
|
Sid = strSid,
|
||||||
queueOption);
|
Hours = Collector.InfrastructureConfig.M42Wpm.ClosedTicketHistory,
|
||||||
|
Filters = GetActivityFilters()
|
||||||
if (queueOption != 0)
|
};
|
||||||
{
|
var res = await PostJsonAsync(_wc, constUrlGetTicketsV2, request, Token);
|
||||||
var encodedQueues = GetEncodedActivityQueues();
|
if (res?.StatusCode == HttpStatusCode.NotFound)
|
||||||
if (!string.IsNullOrWhiteSpace(encodedQueues))
|
{
|
||||||
strUrl += string.Format(constUrlGetTicketsQueuesParam, encodedQueues);
|
if (!TryGetLegacyQueueFilter(out var queueOption, out var encodedQueues))
|
||||||
}
|
{
|
||||||
|
LogEntry("The activity filter policy requires the v2 ticket API; legacy fallback was rejected (fail closed).", LogLevels.Warning);
|
||||||
var _wc = await GetWebClient(requestInfo, Token);
|
return null;
|
||||||
var res = await _wc.HttpEnh.GetAsync(strUrl);
|
}
|
||||||
if (res.IsSuccessStatusCode)
|
var strUrl = string.Format(
|
||||||
|
constUrlGetTickets,
|
||||||
|
strSid,
|
||||||
|
Collector.InfrastructureConfig.M42Wpm.ClosedTicketHistory,
|
||||||
|
queueOption);
|
||||||
|
if (!string.IsNullOrWhiteSpace(encodedQueues))
|
||||||
|
strUrl += string.Format(constUrlGetTicketsQueuesParam, encodedQueues);
|
||||||
|
res = await _wc.HttpEnh.GetAsync(strUrl);
|
||||||
|
}
|
||||||
|
if (res?.IsSuccessStatusCode == true)
|
||||||
{
|
{
|
||||||
var strJson = await res.Content.ReadAsStringAsync();
|
var strJson = await res.Content.ReadAsStringAsync();
|
||||||
if (!string.IsNullOrEmpty(strJson))
|
if (!string.IsNullOrEmpty(strJson))
|
||||||
@@ -1093,12 +1106,76 @@ namespace C4IT.DataHistoryProvider
|
|||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetActivityQueueOption()
|
private int GetActivityQueueOption()
|
||||||
{
|
{
|
||||||
return (int)Collector.InfrastructureConfig.M42Wpm.ActivityQueueFilterOption;
|
return (int)Collector.InfrastructureConfig.M42Wpm.ActivityQueueFilterOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetEncodedActivityQueues()
|
private cActivityFilterPolicy GetActivityFilters()
|
||||||
|
{
|
||||||
|
return Collector?.GetGlobalConfig()?.TicketConfiguration?.ActivityFilters
|
||||||
|
?? new cActivityFilterPolicy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryGetLegacyQueueFilter(out int queueOption, out string encodedQueues)
|
||||||
|
{
|
||||||
|
queueOption = 0;
|
||||||
|
encodedQueues = null;
|
||||||
|
var activeFilters = (GetActivityFilters()?.Filters ?? new List<cActivityFilter>())
|
||||||
|
.Where(entry => entry?.Enabled == true)
|
||||||
|
.ToList();
|
||||||
|
if (activeFilters.Count == 0)
|
||||||
|
return true;
|
||||||
|
if (activeFilters.Count != 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var activityFilter = activeFilters[0];
|
||||||
|
if (!string.Equals(activityFilter.Provider, "Matrix42", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| !string.Equals(activityFilter.Field, "Queue", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| activityFilter.Match != enumActivityFilterMatch.include
|
||||||
|
|| activityFilter.EmptyHandling == enumActivityFilterEmptyHandling.only)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
queueOption = activityFilter.EmptyHandling == enumActivityFilterEmptyHandling.include ? 1 : 2;
|
||||||
|
var values = (activityFilter.Values ?? new List<cActivityFilterValue>())
|
||||||
|
.Where(value => value != null)
|
||||||
|
.Select(value =>
|
||||||
|
{
|
||||||
|
if (Guid.TryParse(value.ID, out var id) && id != Guid.Empty)
|
||||||
|
return ":" + HttpUtility.UrlEncode(id.ToString("D"));
|
||||||
|
return string.IsNullOrWhiteSpace(value.Name)
|
||||||
|
? null
|
||||||
|
: HttpUtility.UrlEncode(value.Name.Trim());
|
||||||
|
})
|
||||||
|
.Where(value => !string.IsNullOrWhiteSpace(value))
|
||||||
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToList();
|
||||||
|
if (values.Count == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
encodedQueues = string.Join("|", values);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Task<HttpResponseMessage> PostJsonAsync(
|
||||||
|
cM42WebClient webClient,
|
||||||
|
string url,
|
||||||
|
object request,
|
||||||
|
CancellationToken token)
|
||||||
|
{
|
||||||
|
var json = JsonConvert.SerializeObject(
|
||||||
|
request,
|
||||||
|
Formatting.None,
|
||||||
|
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||||
|
return webClient.HttpEnh.PostAsync(
|
||||||
|
url,
|
||||||
|
new StringContent(json, Encoding.UTF8, "application/json"),
|
||||||
|
token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetEncodedActivityQueues()
|
||||||
{
|
{
|
||||||
var queues = Collector.InfrastructureConfig.M42Wpm.ActivityQueues;
|
var queues = Collector.InfrastructureConfig.M42Wpm.ActivityQueues;
|
||||||
if (queues == null || queues.Count == 0)
|
if (queues == null || queues.Count == 0)
|
||||||
@@ -1140,28 +1217,36 @@ namespace C4IT.DataHistoryProvider
|
|||||||
string scope,
|
string scope,
|
||||||
IReadOnlyCollection<string> requestedKeys,
|
IReadOnlyCollection<string> requestedKeys,
|
||||||
cF4sdWebRequestInfo requestInfo,
|
cF4sdWebRequestInfo requestInfo,
|
||||||
CancellationToken token)
|
CancellationToken token)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var urlBuilder = new StringBuilder(constUrlGetTicketOverviewCounts);
|
var wc = await GetWebClient(requestInfo, token);
|
||||||
urlBuilder.Append("?sid=").Append(HttpUtility.UrlEncode(sid));
|
var request = new cTicketOverviewFilterRequest
|
||||||
urlBuilder.Append("&scope=").Append(HttpUtility.UrlEncode(scope ?? string.Empty));
|
{
|
||||||
|
Sid = sid,
|
||||||
if (requestedKeys != null && requestedKeys.Count > 0)
|
Scope = scope,
|
||||||
{
|
Keys = requestedKeys?.ToList() ?? new List<string>(),
|
||||||
urlBuilder.Append("&keys=").Append(HttpUtility.UrlEncode(string.Join(",", requestedKeys)));
|
Filters = GetActivityFilters()
|
||||||
}
|
};
|
||||||
|
var res = await PostJsonAsync(wc, constUrlGetTicketOverviewCountsV2, request, token);
|
||||||
var queueOption = GetActivityQueueOption();
|
if (res?.StatusCode == HttpStatusCode.NotFound)
|
||||||
var encodedQueues = queueOption != 0 ? GetEncodedActivityQueues() : null;
|
{
|
||||||
AppendQueueFilterQuery(urlBuilder, queueOption, encodedQueues);
|
if (!TryGetLegacyQueueFilter(out var queueOption, out var encodedQueues))
|
||||||
|
{
|
||||||
var url = urlBuilder.ToString();
|
LogEntry("The activity filter policy requires the v2 overview API; legacy fallback was rejected (fail closed).", LogLevels.Warning);
|
||||||
var wc = await GetWebClient(requestInfo, token);
|
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||||
var res = await wc.HttpEnh.GetAsync(url, token);
|
}
|
||||||
if (token.IsCancellationRequested)
|
var urlBuilder = new StringBuilder(constUrlGetTicketOverviewCounts);
|
||||||
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
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);
|
||||||
|
|
||||||
if (res?.IsSuccessStatusCode == true)
|
if (res?.IsSuccessStatusCode == true)
|
||||||
{
|
{
|
||||||
@@ -1227,64 +1312,12 @@ namespace C4IT.DataHistoryProvider
|
|||||||
if (string.IsNullOrWhiteSpace(sid))
|
if (string.IsNullOrWhiteSpace(sid))
|
||||||
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var normalizedKeys = (keys ?? Enumerable.Empty<string>())
|
var normalizedKeys = (keys ?? Enumerable.Empty<string>())
|
||||||
.Where(k => !string.IsNullOrWhiteSpace(k))
|
.Where(k => !string.IsNullOrWhiteSpace(k))
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
.ToList();
|
.ToList();
|
||||||
var now = DateTime.UtcNow;
|
var scope = useRoleScope ? "role" : "personal";
|
||||||
var ttl = GetTicketOverviewCacheDuration(useRoleScope);
|
return await FetchTicketOverviewCountsAsync(sid, scope, normalizedKeys, requestInfo, Token);
|
||||||
|
|
||||||
if (!useRoleScope)
|
|
||||||
{
|
|
||||||
// process thr personal scope
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// process the role scope
|
|
||||||
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)
|
catch (Exception E)
|
||||||
{
|
{
|
||||||
@@ -1314,26 +1347,37 @@ namespace C4IT.DataHistoryProvider
|
|||||||
return new List<cF4sdApiSearchResultRelation>();
|
return new List<cF4sdApiSearchResultRelation>();
|
||||||
|
|
||||||
var sid = requestInfo?.userInfo?.AdSid;
|
var sid = requestInfo?.userInfo?.AdSid;
|
||||||
if (string.IsNullOrWhiteSpace(sid))
|
if (string.IsNullOrWhiteSpace(sid))
|
||||||
return new List<cF4sdApiSearchResultRelation>();
|
return new List<cF4sdApiSearchResultRelation>();
|
||||||
|
|
||||||
var scope = useRoleScope ? "role" : "personal";
|
var scope = useRoleScope ? "role" : "personal";
|
||||||
var urlBuilder = new StringBuilder(constUrlGetTicketOverviewRelations);
|
var wc = await GetWebClient(requestInfo, Token);
|
||||||
urlBuilder.Append("?sid=").Append(HttpUtility.UrlEncode(sid));
|
var request = new cTicketOverviewFilterRequest
|
||||||
urlBuilder.Append("&scope=").Append(HttpUtility.UrlEncode(scope));
|
{
|
||||||
urlBuilder.Append("&key=").Append(HttpUtility.UrlEncode(key));
|
Sid = sid,
|
||||||
urlBuilder.Append("&count=").Append(Math.Max(0, count));
|
Scope = scope,
|
||||||
|
Key = key,
|
||||||
var queueOption = GetActivityQueueOption();
|
Count = Math.Max(0, count),
|
||||||
var encodedQueues = queueOption != 0 ? GetEncodedActivityQueues() : null;
|
Filters = GetActivityFilters()
|
||||||
AppendQueueFilterQuery(urlBuilder, queueOption, encodedQueues);
|
};
|
||||||
|
var res = await PostJsonAsync(wc, constUrlGetTicketOverviewRelationsV2, request, Token);
|
||||||
var url = urlBuilder.ToString();
|
if (res?.StatusCode == HttpStatusCode.NotFound)
|
||||||
|
{
|
||||||
var wc = await GetWebClient(requestInfo, Token);
|
if (!TryGetLegacyQueueFilter(out var queueOption, out var encodedQueues))
|
||||||
var res = await wc.HttpEnh.GetAsync(url, Token);
|
{
|
||||||
if (Token.IsCancellationRequested)
|
LogEntry("The activity filter policy requires the v2 relation API; legacy fallback was rejected (fail closed).", LogLevels.Warning);
|
||||||
return new List<cF4sdApiSearchResultRelation>();
|
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>();
|
||||||
|
|
||||||
if (res?.IsSuccessStatusCode == true)
|
if (res?.IsSuccessStatusCode == true)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Linq;
|
||||||
using System.Xml;
|
using System.Reflection;
|
||||||
|
using System.Security;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
@@ -21,7 +24,8 @@ namespace C4IT.DataHistoryProvider
|
|||||||
private const string constFileNameF4sdSchema = "F4SD-Global-Configuration.xsd";
|
private const string constFileNameF4sdSchema = "F4SD-Global-Configuration.xsd";
|
||||||
private const string constConfigRootElement = "F4SD-Global-Configuration";
|
private const string constConfigRootElement = "F4SD-Global-Configuration";
|
||||||
|
|
||||||
public cConfigHelperParameterList Parameters { get; private set; } = null;
|
public cConfigHelperParameterList Parameters { get; private set; } = null;
|
||||||
|
public cActivityFilterPolicy ActivityFilters { get; private set; } = new cActivityFilterPolicy();
|
||||||
|
|
||||||
private cDataHistoryConfigInfrastructure InfrastructureConfig = null;
|
private cDataHistoryConfigInfrastructure InfrastructureConfig = null;
|
||||||
|
|
||||||
@@ -102,12 +106,15 @@ namespace C4IT.DataHistoryProvider
|
|||||||
if (_overrideValues != null && _overrideValues.ValueList != null && _overrideValues.ValueList.Count > 0)
|
if (_overrideValues != null && _overrideValues.ValueList != null && _overrideValues.ValueList.Count > 0)
|
||||||
_result.Items[_overrideValues.Name] = _overrideValues;
|
_result.Items[_overrideValues.Name] = _overrideValues;
|
||||||
continue;
|
continue;
|
||||||
case "TicketProcessing":
|
case "TicketProcessing":
|
||||||
var _ticketProcessingEntry = getTicketProcessingEntry(_item, Parser);
|
var _ticketProcessingEntry = getTicketProcessingEntry(_item, Parser);
|
||||||
if (_ticketProcessingEntry != null)
|
if (_ticketProcessingEntry != null)
|
||||||
_result.Items[_ticketProcessingEntry.Name] = _ticketProcessingEntry;
|
_result.Items[_ticketProcessingEntry.Name] = _ticketProcessingEntry;
|
||||||
continue;
|
continue;
|
||||||
}
|
case "ActivityFilters":
|
||||||
|
ActivityFilters = getActivityFilters(_item, Parser);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (_attPolicy != null && _attValue != null && _ElementCount == 0)
|
if (_attPolicy != null && _attValue != null && _ElementCount == 0)
|
||||||
{
|
{
|
||||||
@@ -156,8 +163,89 @@ namespace C4IT.DataHistoryProvider
|
|||||||
if (CM != null) LogMethodEnd(CM);
|
if (CM != null) LogMethodEnd(CM);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _result;
|
return _result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static cActivityFilterPolicy getActivityFilters(XmlElement node, cXmlParser parser)
|
||||||
|
{
|
||||||
|
var result = new cActivityFilterPolicy();
|
||||||
|
foreach (XmlElement filterNode in node.SelectNodes("Filter").OfType<XmlElement>())
|
||||||
|
{
|
||||||
|
parser.EnterElement(filterNode.Name);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!Enum.TryParse(filterNode.GetAttribute("Match"), true, out enumActivityFilterMatch match))
|
||||||
|
match = enumActivityFilterMatch.exclude;
|
||||||
|
if (!Enum.TryParse(filterNode.GetAttribute("EmptyHandling"), true, out enumActivityFilterEmptyHandling emptyHandling))
|
||||||
|
emptyHandling = enumActivityFilterEmptyHandling.include;
|
||||||
|
|
||||||
|
var filter = new cActivityFilter
|
||||||
|
{
|
||||||
|
Provider = filterNode.GetAttribute("Provider"),
|
||||||
|
Field = filterNode.GetAttribute("Field"),
|
||||||
|
Enabled = bool.TryParse(filterNode.GetAttribute("Enabled"), out var enabled) && enabled,
|
||||||
|
Match = match,
|
||||||
|
EmptyHandling = emptyHandling
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (XmlElement valueNode in filterNode.SelectNodes("Value").OfType<XmlElement>())
|
||||||
|
{
|
||||||
|
filter.Values.Add(new cActivityFilterValue
|
||||||
|
{
|
||||||
|
ID = valueNode.GetAttribute("ID"),
|
||||||
|
Name = valueNode.GetAttribute("Name")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Filters.Add(filter);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
parser.LeaveElement(filterNode.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string getDefaultActivityFiltersXml()
|
||||||
|
{
|
||||||
|
var queueOption = InfrastructureConfig?.M42Wpm?.ActivityQueueFilterOption
|
||||||
|
?? enumActivityQueueFilterOptions.showAll;
|
||||||
|
var queues = InfrastructureConfig?.M42Wpm?.ActivityQueues
|
||||||
|
?? new List<cApiM42TicketQueueInfo>();
|
||||||
|
var enableQueueFilter = queueOption != enumActivityQueueFilterOptions.showAll && queues.Count > 0;
|
||||||
|
var emptyHandling = queueOption == enumActivityQueueFilterOptions.onlyListedQueues
|
||||||
|
? enumActivityFilterEmptyHandling.exclude
|
||||||
|
: enumActivityFilterEmptyHandling.include;
|
||||||
|
|
||||||
|
var xml = new StringBuilder();
|
||||||
|
xml.Append("<ActivityFilters>");
|
||||||
|
xml.AppendFormat(
|
||||||
|
"<Filter Provider=\"Matrix42\" Field=\"Queue\" Enabled=\"{0}\" Match=\"include\" EmptyHandling=\"{1}\">",
|
||||||
|
enableQueueFilter.ToString().ToLowerInvariant(),
|
||||||
|
emptyHandling);
|
||||||
|
foreach (var queue in queues.Where(queue => queue != null))
|
||||||
|
{
|
||||||
|
xml.AppendFormat(
|
||||||
|
"<Value ID=\"{0}\" Name=\"{1}\" />",
|
||||||
|
queue.QueueID == Guid.Empty ? string.Empty : queue.QueueID.ToString("D"),
|
||||||
|
SecurityElement.Escape(queue.QueueName ?? string.Empty));
|
||||||
|
}
|
||||||
|
xml.Append("</Filter>");
|
||||||
|
xml.Append("<Filter Field=\"AssignmentGroup\" Enabled=\"false\" Match=\"include\" EmptyHandling=\"exclude\">");
|
||||||
|
xml.Append("<Value ID=\"0a76de08-136c-764a-b410-5610e8076712\" Name=\"HR Service Desk Agent\" />");
|
||||||
|
xml.Append("<Value ID=\"0b76de08-8668-a026-b410-5610e8076f95\" Name=\"HR-Manager\" />");
|
||||||
|
xml.Append("<Value ID=\"0a76de08-d589-4c94-b410-5610e8076919\" Name=\"HR-Spezialist\" />");
|
||||||
|
xml.Append("<Value ID=\"e87dde08-235c-04e5-b410-562b64035575\" Name=\"Facility-Koordinator\" />");
|
||||||
|
xml.Append("</Filter>");
|
||||||
|
xml.Append("<Filter Provider=\"Matrix42\" Field=\"Workspace\" Enabled=\"false\" Match=\"include\" EmptyHandling=\"exclude\">");
|
||||||
|
xml.Append("<Value ID=\"1676de08-27f3-550c-b410-5610e807aa02\" Name=\"HR Service Management\" />");
|
||||||
|
xml.Append("<Value ID=\"ed7dde08-199e-c27b-b410-562b64037aa1\" Name=\"Gebäudemanagement\" />");
|
||||||
|
xml.Append("</Filter>");
|
||||||
|
xml.Append("</ActivityFilters>");
|
||||||
|
return xml.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
private cConfigHelperParameterEntry getInformationClassSearchPriority(XmlElement XNode, cXmlParser Parser)
|
private cConfigHelperParameterEntry getInformationClassSearchPriority(XmlElement XNode, cXmlParser Parser)
|
||||||
{
|
{
|
||||||
@@ -487,11 +575,16 @@ namespace C4IT.DataHistoryProvider
|
|||||||
, "ShowOverview"
|
, "ShowOverview"
|
||||||
, "<ShowOverview Policy=\"Hidden\" Value=\"true\" />"
|
, "<ShowOverview Policy=\"Hidden\" Value=\"true\" />"
|
||||||
);
|
);
|
||||||
RetVal |= DoXmlInsertElement(XmlRoot
|
RetVal |= DoXmlInsertElement(XmlRoot
|
||||||
, "TicketConfiguration"
|
, "TicketConfiguration"
|
||||||
, "TicketProcessing"
|
, "TicketProcessing"
|
||||||
, "<TicketProcessing Policy=\"Mandatory\" Value=\"both\"><TicketTypeProcessing Type=\"Ticket\" Value=\"intern\" /><TicketTypeProcessing Type=\"UnclassifiedTicket\" Value=\"intern\" /><TicketTypeProcessing Type=\"Incident\" Value=\"intern\" /></TicketProcessing>"
|
, "<TicketProcessing Policy=\"Mandatory\" Value=\"both\"><TicketTypeProcessing Type=\"Ticket\" Value=\"intern\" /><TicketTypeProcessing Type=\"UnclassifiedTicket\" Value=\"intern\" /><TicketTypeProcessing Type=\"Incident\" Value=\"intern\" /></TicketProcessing>"
|
||||||
);
|
);
|
||||||
|
RetVal |= DoXmlInsertElement(XmlRoot
|
||||||
|
, "TicketConfiguration"
|
||||||
|
, "ActivityFilters"
|
||||||
|
, getDefaultActivityFiltersXml()
|
||||||
|
);
|
||||||
RetVal |= DoXmlRemoveElement(XmlRoot
|
RetVal |= DoXmlRemoveElement(XmlRoot
|
||||||
, "TicketConfiguration"
|
, "TicketConfiguration"
|
||||||
, "OpenActivitiesExternally"
|
, "OpenActivitiesExternally"
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ namespace C4IT.DataHistoryProvider
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool InstantiateProperties(XmlElement XRoot, cXmlParser Parser)
|
public override bool InstantiateProperties(XmlElement XRoot, cXmlParser Parser)
|
||||||
{
|
{
|
||||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||||
try
|
try
|
||||||
@@ -118,9 +118,34 @@ namespace C4IT.DataHistoryProvider
|
|||||||
if (CM != null) LogMethodEnd(CM);
|
if (CM != null) LogMethodEnd(CM);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override bool DoXmlUpdates(XmlElement xmlRoot, bool withM42Config = false, bool withIntuneConfig = false, bool withMobileDeviceConfig = false, bool withCitrixConfig = false)
|
||||||
|
{
|
||||||
|
// Queue filtering moved to the provider-neutral global ActivityFilters policy.
|
||||||
|
// InstantiateProperties runs first, so the values remain available for the
|
||||||
|
// one-time migration while the obsolete XML is removed.
|
||||||
|
if (!(xmlRoot.SelectSingleNode("Matrix42-WPM") is XmlElement matrix42))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var changed = false;
|
||||||
|
if (matrix42.HasAttribute("ActivityQueueFilter"))
|
||||||
|
{
|
||||||
|
matrix42.RemoveAttribute("ActivityQueueFilter");
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var queues = matrix42.SelectSingleNode("Queues");
|
||||||
|
if (queues != null)
|
||||||
|
{
|
||||||
|
matrix42.RemoveChild(queues);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class cDataHistoryConfigDatabase : IConfigNodeValidation
|
public class cDataHistoryConfigDatabase : IConfigNodeValidation
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using C4IT.DataHistoryProvider;
|
||||||
|
using C4IT.FASD.Base;
|
||||||
|
|
||||||
|
namespace C4IT_DataHistoryProvider_Base.DataSources
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provider-neutral access to ticket-system activities used by search and overview.
|
||||||
|
/// Provider-specific filter fields remain opaque configuration values.
|
||||||
|
/// </summary>
|
||||||
|
public interface ITicketActivityProvider
|
||||||
|
{
|
||||||
|
bool TicketAndServiceRequestsEnabled { get; }
|
||||||
|
|
||||||
|
Task<List<cF4SDTicketSummary>> GetTicketsFromSid(
|
||||||
|
cF4sdConnectorIds userId,
|
||||||
|
CancellationToken token,
|
||||||
|
cF4sdWebRequestInfo requestInfo);
|
||||||
|
|
||||||
|
Task<Dictionary<string, int>> GetTicketOverviewCountsAsync(
|
||||||
|
IEnumerable<string> keys,
|
||||||
|
bool useRoleScope,
|
||||||
|
cF4sdWebRequestInfo requestInfo,
|
||||||
|
int logDeep,
|
||||||
|
CancellationToken token);
|
||||||
|
|
||||||
|
Task<List<cF4sdApiSearchResultRelation>> GetTicketOverviewRelationsAsync(
|
||||||
|
string key,
|
||||||
|
bool useRoleScope,
|
||||||
|
int count,
|
||||||
|
cF4sdWebRequestInfo requestInfo,
|
||||||
|
int logDeep,
|
||||||
|
CancellationToken token);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,22 @@
|
|||||||
<TicketTypeProcessing Type="UnclassifiedTicket" Value="intern" />
|
<TicketTypeProcessing Type="UnclassifiedTicket" Value="intern" />
|
||||||
<TicketTypeProcessing Type="Incident" Value="intern" />
|
<TicketTypeProcessing Type="Incident" Value="intern" />
|
||||||
</TicketProcessing>
|
</TicketProcessing>
|
||||||
|
<ActivityFilters>
|
||||||
|
<Filter Provider="Matrix42" Field="Queue" Enabled="false" Match="include" EmptyHandling="include">
|
||||||
|
<Value ID="2a7e8099-3d57-f011-1988-00155d320605" Name="HR" />
|
||||||
|
<Value ID="2a7a8099-3d47-f011-1988-00155d320505" Name="FM" />
|
||||||
|
</Filter>
|
||||||
|
<Filter Field="AssignmentGroup" Enabled="false" Match="include" EmptyHandling="exclude">
|
||||||
|
<Value ID="0a76de08-136c-764a-b410-5610e8076712" Name="HR Service Desk Agent" />
|
||||||
|
<Value ID="0b76de08-8668-a026-b410-5610e8076f95" Name="HR-Manager" />
|
||||||
|
<Value ID="0a76de08-d589-4c94-b410-5610e8076919" Name="HR-Spezialist" />
|
||||||
|
<Value ID="e87dde08-235c-04e5-b410-562b64035575" Name="Facility-Koordinator" />
|
||||||
|
</Filter>
|
||||||
|
<Filter Provider="Matrix42" Field="Workspace" Enabled="false" Match="include" EmptyHandling="exclude">
|
||||||
|
<Value ID="1676de08-27f3-550c-b410-5610e807aa02" Name="HR Service Management" />
|
||||||
|
<Value ID="ed7dde08-199e-c27b-b410-562b64037aa1" Name="Gebäudemanagement" />
|
||||||
|
</Filter>
|
||||||
|
</ActivityFilters>
|
||||||
<OverviewPollingPersonal Policy="Mandatory" Value="10" />
|
<OverviewPollingPersonal Policy="Mandatory" Value="10" />
|
||||||
<OverviewPollingRole Policy="Mandatory" Value="5" />
|
<OverviewPollingRole Policy="Mandatory" Value="5" />
|
||||||
</TicketConfiguration>
|
</TicketConfiguration>
|
||||||
|
|||||||
@@ -82,15 +82,11 @@
|
|||||||
</Azure-Tenant>
|
</Azure-Tenant>
|
||||||
<!--<Azure-Tenant Domain="sd0024.onmicrosoft.com" TenantID="07362148-410e-4636-a9cb-795fba1a5452" Credential="AzureAccess_Dieter"/>-->
|
<!--<Azure-Tenant Domain="sd0024.onmicrosoft.com" TenantID="07362148-410e-4636-a9cb-795fba1a5452" Credential="AzureAccess_Dieter"/>-->
|
||||||
</Azure-AD>
|
</Azure-AD>
|
||||||
<Matrix42-WPM Server="srvwsm001.imagoverum.com" Credential="M42API-Demo-26-1" ClosedTicketHistory="9999" DisplayName="M42 Demo server (imagoverum)" ApiTokenLifetime ="30 days" ActivityQueueFilter="showAll">
|
<Matrix42-WPM Server="srvwsm001.imagoverum.com" Credential="M42API-Demo-26-1" ClosedTicketHistory="9999" DisplayName="M42 Demo server (imagoverum)" ApiTokenLifetime ="30 days">
|
||||||
<Matrix42-Ticket DisableAutomaticTimeTracking="1"
|
<Matrix42-Ticket DisableAutomaticTimeTracking="1"
|
||||||
ShowDocumentCaseDialog="ifRequired"/>
|
ShowDocumentCaseDialog="ifRequired"/>
|
||||||
<DisplayName Lang="DE">M42 Demo Server (Imagoverum)</DisplayName>
|
<DisplayName Lang="DE">M42 Demo Server (Imagoverum)</DisplayName>
|
||||||
<Queues>
|
</Matrix42-WPM>
|
||||||
<Queue QueueName="HR" QueueID="2a7e8099-3d57-f011-1988-00155d320605" />
|
|
||||||
<Queue QueueName="FM" QueueID="2a7a8099-3d47-f011-1988-00155d320505" />
|
|
||||||
</Queues>
|
|
||||||
</Matrix42-WPM>
|
|
||||||
<!--<Matrix42-WPM Server="m42server.imagoverum.com" Credential="M42API-Demo-Dieter" ClosedTicketHistory="9999"/>-->
|
<!--<Matrix42-WPM Server="m42server.imagoverum.com" Credential="M42API-Demo-Dieter" ClosedTicketHistory="9999"/>-->
|
||||||
<Nexthink>
|
<Nexthink>
|
||||||
<Scan-Timing ScanInterval="24:00" ScanOffset="00:10" Timezone="W. Europe Standard Time"/>
|
<Scan-Timing ScanInterval="24:00" ScanOffset="00:10" Timezone="W. Europe Standard Time"/>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace FasdWebService.Controllers
|
|||||||
return Ok(new TicketOverviewCountsResult());
|
return Ok(new TicketOverviewCountsResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
var collector = WebApiApplication.Collector?.M42WpmCollector;
|
var collector = WebApiApplication.Collector?.TicketActivityProvider;
|
||||||
if (collector == null)
|
if (collector == null)
|
||||||
{
|
{
|
||||||
return Ok(new TicketOverviewCountsResult());
|
return Ok(new TicketOverviewCountsResult());
|
||||||
@@ -95,7 +95,7 @@ namespace FasdWebService.Controllers
|
|||||||
return Ok(new List<cF4sdApiSearchResultRelation>());
|
return Ok(new List<cF4sdApiSearchResultRelation>());
|
||||||
}
|
}
|
||||||
|
|
||||||
var collector = WebApiApplication.Collector?.M42WpmCollector;
|
var collector = WebApiApplication.Collector?.TicketActivityProvider;
|
||||||
if (collector == null)
|
if (collector == null)
|
||||||
{
|
{
|
||||||
return Ok(new List<cF4sdApiSearchResultRelation>());
|
return Ok(new List<cF4sdApiSearchResultRelation>());
|
||||||
|
|||||||
@@ -24,6 +24,22 @@
|
|||||||
<TicketTypeProcessing Type="UnclassifiedTicket" Value="intern" />
|
<TicketTypeProcessing Type="UnclassifiedTicket" Value="intern" />
|
||||||
<TicketTypeProcessing Type="Incident" Value="intern" />
|
<TicketTypeProcessing Type="Incident" Value="intern" />
|
||||||
</TicketProcessing>
|
</TicketProcessing>
|
||||||
|
<ActivityFilters>
|
||||||
|
<Filter Provider="Matrix42" Field="Queue" Enabled="false" Match="include" EmptyHandling="include">
|
||||||
|
<Value ID="2a7e8099-3d57-f011-1988-00155d320605" Name="HR" />
|
||||||
|
<Value ID="2a7a8099-3d47-f011-1988-00155d320505" Name="FM" />
|
||||||
|
</Filter>
|
||||||
|
<Filter Field="AssignmentGroup" Enabled="false" Match="include" EmptyHandling="exclude">
|
||||||
|
<Value ID="0a76de08-136c-764a-b410-5610e8076712" Name="HR Service Desk Agent" />
|
||||||
|
<Value ID="0b76de08-8668-a026-b410-5610e8076f95" Name="HR-Manager" />
|
||||||
|
<Value ID="0a76de08-d589-4c94-b410-5610e8076919" Name="HR-Spezialist" />
|
||||||
|
<Value ID="e87dde08-235c-04e5-b410-562b64035575" Name="Facility-Koordinator" />
|
||||||
|
</Filter>
|
||||||
|
<Filter Provider="Matrix42" Field="Workspace" Enabled="false" Match="include" EmptyHandling="exclude">
|
||||||
|
<Value ID="1676de08-27f3-550c-b410-5610e807aa02" Name="HR Service Management" />
|
||||||
|
<Value ID="ed7dde08-199e-c27b-b410-562b64037aa1" Name="Gebäudemanagement" />
|
||||||
|
</Filter>
|
||||||
|
</ActivityFilters>
|
||||||
<OverviewPollingPersonal Policy="Mandatory" Value="10" />
|
<OverviewPollingPersonal Policy="Mandatory" Value="10" />
|
||||||
<OverviewPollingRole Policy="Mandatory" Value="5" />
|
<OverviewPollingRole Policy="Mandatory" Value="5" />
|
||||||
</TicketConfiguration>
|
</TicketConfiguration>
|
||||||
|
|||||||
@@ -132,6 +132,21 @@
|
|||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:simpleType name="ActivityFilterMatchEnum">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="include"/>
|
||||||
|
<xs:enumeration value="exclude"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="ActivityFilterEmptyHandlingEnum">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:enumeration value="include"/>
|
||||||
|
<xs:enumeration value="exclude"/>
|
||||||
|
<xs:enumeration value="only"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
<xs:element name="TicketConfiguration">
|
<xs:element name="TicketConfiguration">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:all>
|
<xs:all>
|
||||||
@@ -182,6 +197,30 @@
|
|||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name="ActivityFilters" minOccurs="0" maxOccurs="1">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="Filter" minOccurs="0" maxOccurs="unbounded">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="Value" minOccurs="0" maxOccurs="unbounded">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name="ID" type="xs:string" use="optional"/>
|
||||||
|
<xs:attribute name="Name" type="xs:string" use="optional"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="Provider" type="xs:string" use="optional"/>
|
||||||
|
<xs:attribute name="Field" type="xs:string" use="required"/>
|
||||||
|
<xs:attribute name="Enabled" type="xs:boolean" use="optional" default="false"/>
|
||||||
|
<xs:attribute name="Match" type="ActivityFilterMatchEnum" use="optional" default="exclude"/>
|
||||||
|
<xs:attribute name="EmptyHandling" type="ActivityFilterEmptyHandlingEnum" use="optional" default="include"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
<xs:element name="TicketProcessing" minOccurs="0" maxOccurs="1">
|
<xs:element name="TicketProcessing" minOccurs="0" maxOccurs="1">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
|
|||||||
@@ -82,15 +82,11 @@
|
|||||||
</Azure-Tenant>
|
</Azure-Tenant>
|
||||||
<!--<Azure-Tenant Domain="sd0024.onmicrosoft.com" TenantID="07362148-410e-4636-a9cb-795fba1a5452" Credential="AzureAccess_Dieter"/>-->
|
<!--<Azure-Tenant Domain="sd0024.onmicrosoft.com" TenantID="07362148-410e-4636-a9cb-795fba1a5452" Credential="AzureAccess_Dieter"/>-->
|
||||||
</Azure-AD>
|
</Azure-AD>
|
||||||
<Matrix42-WPM Server="srvwsm001.imagoverum.com" Credential="M42API-Demo-26-1" ClosedTicketHistory="9999" DisplayName="M42 Demo server (imagoverum)" ApiTokenLifetime ="30 days" ActivityQueueFilter="showAll">
|
<Matrix42-WPM Server="srvwsm001.imagoverum.com" Credential="M42API-Demo-26-1" ClosedTicketHistory="9999" DisplayName="M42 Demo server (imagoverum)" ApiTokenLifetime ="30 days">
|
||||||
<Matrix42-Ticket DisableAutomaticTimeTracking="1"
|
<Matrix42-Ticket DisableAutomaticTimeTracking="1"
|
||||||
ShowDocumentCaseDialog="ifRequired"/>
|
ShowDocumentCaseDialog="ifRequired"/>
|
||||||
<DisplayName Lang="DE">M42 Demo Server (Imagoverum)</DisplayName>
|
<DisplayName Lang="DE">M42 Demo Server (Imagoverum)</DisplayName>
|
||||||
<Queues>
|
</Matrix42-WPM>
|
||||||
<Queue QueueName="HR" QueueID="2a7e8099-3d57-f011-1988-00155d320605" />
|
|
||||||
<Queue QueueName="FM" QueueID="2a7a8099-3d47-f011-1988-00155d320505" />
|
|
||||||
</Queues>
|
|
||||||
</Matrix42-WPM>
|
|
||||||
<!--<Matrix42-WPM Server="m42server.imagoverum.com" Credential="M42API-Demo-Dieter" ClosedTicketHistory="9999"/>-->
|
<!--<Matrix42-WPM Server="m42server.imagoverum.com" Credential="M42API-Demo-Dieter" ClosedTicketHistory="9999"/>-->
|
||||||
<Nexthink>
|
<Nexthink>
|
||||||
<Scan-Timing ScanInterval="24:00" ScanOffset="00:10" Timezone="W. Europe Standard Time"/>
|
<Scan-Timing ScanInterval="24:00" ScanOffset="00:10" Timezone="W. Europe Standard Time"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user