diff --git a/F4SDM42WebApi/C4ITF4SDM42WebApi.dll.host.config b/F4SDM42WebApi/C4ITF4SDM42WebApi.dll.host.config index eb4eb95..1a32a56 100644 --- a/F4SDM42WebApi/C4ITF4SDM42WebApi.dll.host.config +++ b/F4SDM42WebApi/C4ITF4SDM42WebApi.dll.host.config @@ -2,12 +2,7 @@ - - - - - diff --git a/F4SDM42WebApi/DependencyRegistrator.cs b/F4SDM42WebApi/DependencyRegistrator.cs deleted file mode 100644 index b1c8a05..0000000 --- a/F4SDM42WebApi/DependencyRegistrator.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Web.Http; -using System.Web.Http.Description; - -using Matrix42.Hosting.Contracts; - -namespace C4IT.F4SD.Properties -{ - public sealed class DependencyRegistrator : DependencyRegistratorBase, IDependencyRegistrator - { - public void Register(IDependencyContainer container, IDependencyResolver resolver) - { - container.RegisterSingletonType((Type _) => new ApiExplorer(new HttpConfiguration())); - } - } -} diff --git a/F4SDM42WebApi/F4SD - M42WebApi.csproj b/F4SDM42WebApi/F4SD - M42WebApi.csproj index 2bcc94e..80c5320 100644 --- a/F4SDM42WebApi/F4SD - M42WebApi.csproj +++ b/F4SDM42WebApi/F4SD - M42WebApi.csproj @@ -13,7 +13,7 @@ false 6673a25d-33d6-4072-91d9-abed4be1a966 C4ITF4SD*.* - 1.4.0.8 + 1.4.0.9 true @@ -46,6 +46,10 @@ M42Libraries\26.1\Matrix42.Pandora.Contracts.dll false + + M42Libraries\26.1\Matrix42.Persistence.Contracts.dll + false + M42Libraries\26.1\Matrix42.Services.Description.Contracts.dll false @@ -62,10 +66,6 @@ M42Libraries\26.1\System.Net.Http.Formatting.dll false - - M42Libraries\26.1\System.Web.Http.dll - false - M42Libraries\26.1\update4u.SPS.DataLayer.dll false @@ -82,7 +82,6 @@ - diff --git a/F4SDM42WebApi/F4SDHelperService.cs b/F4SDM42WebApi/F4SDHelperService.cs index 49f7cc8..1807523 100644 --- a/F4SDM42WebApi/F4SDHelperService.cs +++ b/F4SDM42WebApi/F4SDHelperService.cs @@ -1931,7 +1931,7 @@ namespace C4IT.F4SD { await Task.Delay(0); List journalEntries = new List(); - var entries = F4SDM42WebApiController.defaultInstance._journalService.GetJournalList(activityEOID, false, 0, 50, "{2}", 120); + var entries = F4SDM42WebApiController.defaultInstance.GetJournalService().GetJournalList(activityEOID, false, 0, 50, "{2}", 120); LogEntry($"{entries.Length} Journal entries found for ObjectID={activityEOID}", LogLevels.Debug); for (int i = 0; i < entries.Length; i++) { @@ -2618,18 +2618,6 @@ namespace C4IT.F4SD retVal.User = m42Users[0]; - var user = F4SDM42WebApiController.defaultInstance._userProfile.GetInteractiveUserInfo(retVal.User.Id); - if (user != null) - { - retVal.User.Id = user.Id; - retVal.User.Currency = user.Currency; - retVal.User.Email = user.Email; - retVal.User.FirstName = user.FirstName; - retVal.User.LastName = user.LastName; - retVal.User.Phone = user.Phone; - retVal.User.Photo = user.Photo; - } - retVal.Roles = await getRoleMembershipById(retVal.User.Id); retVal.User.IsAdmin = retVal.Roles?.Where(i => i.Id == Administrators).FirstOrDefault() != null; return retVal; diff --git a/F4SDM42WebApi/F4SDM42WebApiController.cs b/F4SDM42WebApi/F4SDM42WebApiController.cs index 7cb47f2..196e3bd 100644 --- a/F4SDM42WebApi/F4SDM42WebApiController.cs +++ b/F4SDM42WebApi/F4SDM42WebApiController.cs @@ -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(); + } + + private IEnumerationProvider GetEnumerationProvider() + { + return GetRequiredService(); + } + + private T GetRequiredService() where T : class + { + var service = _resolver.TryGet(); + if (service != null) + return service; + + throw new InvalidOperationException($"Required Matrix42 service is not registered: {typeof(T).FullName}"); + } + [Route("getDirectLinkCreateTicket"), HttpGet] public async Task getDirectLinkCreateTicket(string sid = "", string assetname = "") { @@ -277,7 +296,7 @@ namespace C4IT.F4SD public async Task 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 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() + .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() + .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() + .FirstOrDefault(column => string.Equals(column.ColumnName, columnName, StringComparison.OrdinalIgnoreCase)) + ?.ColumnName; + } + + private static string FindNumericColumn(DataTable dataTable) + { + var excludedNames = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Hidden", + "Position", + "StateGroup" + }; + + return dataTable.Columns.Cast() + .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 ParseQueues(string queues) { return (queues ?? string.Empty)