fix: lazy resolve Matrix42 services

This commit is contained in:
Meik
2026-06-26 20:23:37 +02:00
parent 10aeb625e1
commit af9d730d1d
5 changed files with 126 additions and 50 deletions

View File

@@ -5,11 +5,15 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Matrix42.Common;
using Matrix42.Contracts.Common.Security;
using Matrix42.Contracts.ServiceManagement.ServiceContracts;
using Matrix42.Hosting.Contracts;
using Matrix42.Pandora.Contracts;
using Matrix42.Persistence.Contracts;
using Matrix42.Services.Description.Contracts;
using Matrix42.WebApi.Contracts;
using Matrix42.WebApi.Contracts.OData;
@@ -33,24 +37,20 @@ namespace C4IT.F4SD
internal readonly GlobalConfigurationProvider _globalConfigurationProvider;
//public readonly IObjectService _objectService;
//public readonly IFragmentService _fragmentService;
public readonly IJournalService _journalService;
internal readonly IEntityDataService _entityDataService;
internal readonly IPandoraUserProfile _userProfile;
private readonly IDependencyResolver _resolver;
private readonly F4SDHelperService _f4stHelperService;
public string BaseUrl => Request?.RequestUri == null ? string.Empty : $"{Request.RequestUri.Scheme}://{Request.RequestUri.Host}";
public string EndpointBaseUrl => $"{BaseUrl}/m42Services/api/c4itf4sdwebapi";
public F4SDM42WebApiController(IEntityDataService entityDataService, IJournalService journalService, IPandoraUserProfile userProfile)
public F4SDM42WebApiController(IDependencyResolver resolver)
{
_resolver = resolver ?? throw new ArgumentNullException(nameof(resolver));
defaultInstance = this;
_globalConfigurationProvider = GlobalConfigurationProvider.Instance;
_f4stHelperService = new F4SDHelperService();
EnsureInitialized();
_entityDataService = entityDataService ?? throw new ArgumentNullException(nameof(entityDataService));
_journalService = journalService ?? throw new ArgumentNullException(nameof(journalService));
_userProfile = userProfile ?? throw new ArgumentNullException(nameof(userProfile));
}
private static readonly object initLock = new object();
@@ -74,6 +74,25 @@ namespace C4IT.F4SD
catch { };
}
internal IJournalService GetJournalService()
{
return GetRequiredService<IJournalService>();
}
private IEnumerationProvider GetEnumerationProvider()
{
return GetRequiredService<IEnumerationProvider>();
}
private T GetRequiredService<T>() where T : class
{
var service = _resolver.TryGet<T>();
if (service != null)
return service;
throw new InvalidOperationException($"Required Matrix42 service is not registered: {typeof(T).FullName}");
}
[Route("getDirectLinkCreateTicket"), HttpGet]
public async Task<F4SDHelperService.DirectLink> getDirectLinkCreateTicket(string sid = "", string assetname = "")
{
@@ -277,7 +296,7 @@ namespace C4IT.F4SD
public async Task<HttpResponseMessage> getPickup(string name, [FromUri] EntityEnumerationVisibilityMode mode = EntityEnumerationVisibilityMode.None, [FromUri] Int32 group = -1)
{
await Task.Delay(0);
EntityEnumeration enumerationTemp = _entityDataService.GetEnumeration(name, mode);
EntityEnumeration enumerationTemp = GetEnumeration(name, mode);
var vals = enumerationTemp.Values;
if (group > -1)
@@ -303,8 +322,11 @@ namespace C4IT.F4SD
[Route("getMyRoleMemberships"), HttpGet]
public async Task<HttpResponseMessage> getMyRoleMemberships()
{
var User = _userProfile.GetInteractiveUserInfo();
var filter = AsqlHelper.BuildInCondition("ID", new Guid[] { User.Id });
var userId = GetCurrentUserId();
if (userId == Guid.Empty)
return HttpResponseExtensions.CreateResponse(Request, HttpStatusCode.Unauthorized, "Cannot determine the interactive Matrix42 user.");
var filter = AsqlHelper.BuildInCondition("ID", new Guid[] { userId });
return HttpResponseExtensions.CreateResponse(Request, HttpStatusCode.OK, await _f4stHelperService.UserPermissionsInfo(filter));
}
@@ -371,6 +393,94 @@ namespace C4IT.F4SD
public string Queues { get; set; }
}
private EntityEnumeration GetEnumeration(string name, EntityEnumerationVisibilityMode mode)
{
var dataTable = GetEnumerationProvider().GetEnumeration(name, GetVisibilityFilter(mode));
if (dataTable == null)
throw new InvalidOperationException($"Enumeration '{name}' was not found.");
var valueColumn = FindColumn(dataTable, "Value") ?? FindNumericColumn(dataTable);
if (string.IsNullOrEmpty(valueColumn))
throw new InvalidOperationException($"Enumeration '{name}' does not contain a numeric value column.");
var displayColumn = FindColumn(dataTable, "DisplayString")
?? FindColumn(dataTable, "DisplayExpression")
?? FindColumn(dataTable, "Name")
?? valueColumn;
var hiddenColumn = FindColumn(dataTable, "Hidden");
var values = dataTable.Rows.Cast<DataRow>()
.Select(row => new EntityEnumerationValue
{
Value = ConvertHelper.ParseInt(row[valueColumn], 0),
DisplayString = Convert.ToString(row[displayColumn]),
Hidden = hiddenColumn != null && ConvertHelper.ParseInt(row[hiddenColumn], 0) == 1,
Extentions = dataTable.Columns.Cast<DataColumn>()
.ToDictionary(column => column.ColumnName, column => row[column])
})
.ToArray();
return new EntityEnumeration
{
Name = name,
Values = values
};
}
private static bool? GetVisibilityFilter(EntityEnumerationVisibilityMode mode)
{
switch (mode)
{
case EntityEnumerationVisibilityMode.Visible:
return true;
case EntityEnumerationVisibilityMode.Hidden:
return false;
default:
return null;
}
}
private static string FindColumn(DataTable dataTable, string columnName)
{
return dataTable.Columns.Cast<DataColumn>()
.FirstOrDefault(column => string.Equals(column.ColumnName, columnName, StringComparison.OrdinalIgnoreCase))
?.ColumnName;
}
private static string FindNumericColumn(DataTable dataTable)
{
var excludedNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"Hidden",
"Position",
"StateGroup"
};
return dataTable.Columns.Cast<DataColumn>()
.FirstOrDefault(column => !excludedNames.Contains(column.ColumnName) && IsNumericType(column.DataType))
?.ColumnName;
}
private static bool IsNumericType(Type type)
{
return type == typeof(byte)
|| type == typeof(short)
|| type == typeof(int)
|| type == typeof(long)
|| type == typeof(sbyte)
|| type == typeof(ushort)
|| type == typeof(uint)
|| type == typeof(ulong);
}
private static Guid GetCurrentUserId()
{
var principal = Thread.CurrentPrincipal as IM42Principal;
return principal?.InteractivePrincipal?.M42Identity?.UserFragmentID
?? principal?.M42Identity?.UserFragmentID
?? Guid.Empty;
}
private static List<cApiM42TicketQueueInfo> ParseQueues(string queues)
{
return (queues ?? string.Empty)