diff --git a/.changeset/pr-811-2107089113.md b/.changeset/pr-811-2107089113.md new file mode 100644 index 000000000..6d781f829 --- /dev/null +++ b/.changeset/pr-811-2107089113.md @@ -0,0 +1,9 @@ + +--- +"fusion-project-portal": major +--- +- **BREAKING CHANGE**: Migrate from the deprecated Fusion Portal API (for apps) to the new and separate Fusion Apps API. +This results in breaking changes in the API contract. The reason for this is model changes in the new Fusion Apps API. And we prefer modelling 1-1 as best as possible instead of introducing remapping etc. on our end. +- **BREAKING CHANGE**: Removal of the Fusion Portal Proxy. We no longer provide endpoints for this on the API. All calls to get bundles and app information from Fusion shall go through the ClientBackend +- Fixed more tests +- Refactoring has been done in multiple locations diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Cache/CacheManager.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Cache/CacheManager.cs index ae86aebce..5a8eac961 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Cache/CacheManager.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Cache/CacheManager.cs @@ -45,7 +45,7 @@ private static TimeSpan GetExpirationTime(CacheDuration duration, long expiratio CacheDuration.Hours => TimeSpan.FromHours(expiration), CacheDuration.Minutes => TimeSpan.FromMinutes(expiration), CacheDuration.Seconds => TimeSpan.FromSeconds(expiration), - _ => throw new NotImplementedException($"Unknown {nameof(CacheDuration)}: {duration}"), + _ => throw new Exception($"Unknown {nameof(CacheDuration)}: {duration}"), }; private class CacheClock : ISystemClock diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Cache/FusionAppsCache.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Cache/FusionAppsCache.cs index 410966a55..110142f5e 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Cache/FusionAppsCache.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Cache/FusionAppsCache.cs @@ -1,25 +1,25 @@ -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps; -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models; +using Fusion.Integration.Apps.Abstractions.Abstractions; +using Fusion.Integration.Apps.Abstractions.Models; namespace Equinor.ProjectExecutionPortal.Application.Cache; public class FusionAppsCache : IFusionAppsCache { private readonly ICacheManager _cacheManager; - private readonly IFusionPortalApiService _fusionPortalApiService; + private readonly IAppsClient _fusionAppsClient; - public FusionAppsCache(ICacheManager cacheManager, IFusionPortalApiService fusionPortalApiService) + public FusionAppsCache(ICacheManager cacheManager, IAppsClient fusionAppsClient) { _cacheManager = cacheManager; - _fusionPortalApiService = fusionPortalApiService; + _fusionAppsClient = fusionAppsClient; } - public async Task> GetFusionApps() + public async Task> GetFusionApps() { return await _cacheManager.GetOrCreateAsync("FUSION_APP", async () => { - var fusionApps = await _fusionPortalApiService.TryGetFusionPortalApps(); + var fusionApps = await _fusionAppsClient.GetAppsAsync(); return fusionApps.ToList(); }, @@ -27,10 +27,10 @@ public async Task> GetFusionApps() 60); } - public async Task GetFusionApp(string appKey) + public async Task GetFusionApp(string appKey) { return await _cacheManager.GetOrCreateAsync("FUSION_APP", - async () => await _fusionPortalApiService.TryGetFusionPortalApp(appKey), + async () => await _fusionAppsClient.GetAppAsync(appKey), CacheDuration.Minutes, 60); } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Cache/IFusionAppsCache.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Cache/IFusionAppsCache.cs index b124db12a..f59bd739b 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Cache/IFusionAppsCache.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Cache/IFusionAppsCache.cs @@ -1,10 +1,10 @@ -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models; +using Fusion.Integration.Apps.Abstractions.Models; namespace Equinor.ProjectExecutionPortal.Application.Cache; public interface IFusionAppsCache { - Task> GetFusionApps(); + Task> GetFusionApps(); - Task GetFusionApp(string appKey); + Task GetFusionApp(string appKey); } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/ContextTypes/AddContextType/AddContextTypeCommand.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/ContextTypes/AddContextType/AddContextTypeCommand.cs index bf1d6baac..1700d09b4 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/ContextTypes/AddContextType/AddContextTypeCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/ContextTypes/AddContextType/AddContextTypeCommand.cs @@ -39,7 +39,7 @@ public async Task Handle(AddContextTypeCommand command, CancellationToken if (!FusionContextType.IsValid(command.ContextTypeKey)) { throw new NotFoundException($"ContextType: {command.ContextTypeKey} is not a valid Context type"); - }; + } var contextType = new ContextType(command.ContextTypeKey); diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/ContextTypes/RemoveContextType/RemoveContextTypeCommand.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/ContextTypes/RemoveContextType/RemoveContextTypeCommand.cs index 7aa4de398..5fcabb6ac 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/ContextTypes/RemoveContextType/RemoveContextTypeCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/ContextTypes/RemoveContextType/RemoveContextTypeCommand.cs @@ -1,5 +1,4 @@ -using System.Data; -using Equinor.ProjectExecutionPortal.Domain.Common.Exceptions; +using Equinor.ProjectExecutionPortal.Domain.Common.Exceptions; using Equinor.ProjectExecutionPortal.Domain.Entities; using Equinor.ProjectExecutionPortal.Infrastructure; using MediatR; @@ -15,7 +14,7 @@ public RemoveContextTypeCommand(string contextTypeKey) } public string ContextTypeKey { get; } - + public class Handler : IRequestHandler { private readonly IReadWriteContext _readWriteContext; @@ -27,19 +26,19 @@ public Handler(IReadWriteContext readWriteContext) public async Task Handle(RemoveContextTypeCommand command, CancellationToken cancellationToken) { - var entity = await _readWriteContext.Set() + var entity = await _readWriteContext.Set() .Include(x => x.OnboardedApps) .Include(x => x.Portals) .FirstOrDefaultAsync(x => x.ContextTypeKey == command.ContextTypeKey, cancellationToken); if (entity == null) { - throw new NotFoundException(nameof(ContextType) ,command.ContextTypeKey); + throw new NotFoundException(nameof(ContextType), command.ContextTypeKey); } if (entity.Portals.Any()) { - throw new InvalidActionException("Cannot remove context type. Context type is used by portals"); + throw new InvalidActionException("Cannot remove context type. Context type is used by portals"); } if (entity.OnboardedApps.Any()) @@ -50,7 +49,6 @@ public async Task Handle(RemoveContextTypeCommand command, CancellationToken can _readWriteContext.Set().Remove(entity); await _readWriteContext.SaveChangesAsync(cancellationToken); - } } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/OnboardApp/OnboardAppCommand.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/OnboardApp/OnboardAppCommand.cs index 470e2ab95..1195c6be7 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/OnboardApp/OnboardAppCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/OnboardApp/OnboardAppCommand.cs @@ -1,5 +1,5 @@ -using Equinor.ProjectExecutionPortal.Application.Services.AppService; -using Equinor.ProjectExecutionPortal.Application.Services.ContextTypeService; +using Equinor.ProjectExecutionPortal.Application.Services.ContextTypeService; +using Equinor.ProjectExecutionPortal.Application.Services.FusionAppsService; using Equinor.ProjectExecutionPortal.Domain.Common.Exceptions; using Equinor.ProjectExecutionPortal.Domain.Entities; using Equinor.ProjectExecutionPortal.Infrastructure; @@ -22,19 +22,19 @@ public OnboardAppCommand(string appKey, IList? contextTypes) public class Handler : IRequestHandler { private readonly IReadWriteContext _readWriteContext; - private readonly IAppService _appService; + private readonly IFusionAppsService _fusionAppsService; private readonly IContextTypeService _contextTypeService; - public Handler(IReadWriteContext readWriteContext, IAppService appService, IContextTypeService contextTypeService) + public Handler(IReadWriteContext readWriteContext, IFusionAppsService fusionAppsService, IContextTypeService contextTypeService) { _readWriteContext = readWriteContext; - _appService = appService; + _fusionAppsService = fusionAppsService; _contextTypeService = contextTypeService; } public async Task Handle(OnboardAppCommand command, CancellationToken cancellationToken) { - if (!await _appService.FusionAppExist(command.AppKey, cancellationToken)) + if (!await _fusionAppsService.FusionAppExist(command.AppKey, cancellationToken)) { throw new NotFoundException($"Could not locate app '{command.AppKey}' in Fusion."); } @@ -49,10 +49,10 @@ public async Task Handle(OnboardAppCommand command, CancellationToken canc } var onboardedApp = new OnboardedApp(command.AppKey); - + try { - onboardedApp.AddContextTypes(await _contextTypeService.GetContextTypesByContextTypeKey(command.ContextTypes, cancellationToken)); + onboardedApp.AddContextTypes(await _contextTypeService.GetAllowedContextTypesByKeys(command.ContextTypes, cancellationToken)); } catch (InvalidActionException ex) { diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/UpdateOnboardedApp/UpdateOnboardedAppCommand.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/UpdateOnboardedApp/UpdateOnboardedAppCommand.cs index bc2c94675..845dd1999 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/UpdateOnboardedApp/UpdateOnboardedAppCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/UpdateOnboardedApp/UpdateOnboardedAppCommand.cs @@ -42,7 +42,7 @@ public async Task Handle(UpdateOnboardedAppCommand command, CancellationTo try { - entity.AddContextTypes(await _contextTypeService.GetContextTypesByContextTypeKey(command.ContextTypes, cancellationToken)); + entity.AddContextTypes(await _contextTypeService.GetAllowedContextTypesByKeys(command.ContextTypes, cancellationToken)); } catch (InvalidActionException ex) { diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/AddContextTypeToPortal/AddContextTypeToPortalCommand.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/AddContextTypeToPortal/AddContextTypeToPortalCommand.cs index d3a6ea13b..1fbf3b8ef 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/AddContextTypeToPortal/AddContextTypeToPortalCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/AddContextTypeToPortal/AddContextTypeToPortalCommand.cs @@ -1,5 +1,4 @@ -using Equinor.ProjectExecutionPortal.Application.Services.ContextTypeService; -using Equinor.ProjectExecutionPortal.Domain.Common.Exceptions; +using Equinor.ProjectExecutionPortal.Domain.Common.Exceptions; using Equinor.ProjectExecutionPortal.Domain.Entities; using Equinor.ProjectExecutionPortal.Infrastructure; using MediatR; @@ -22,12 +21,10 @@ public AddContextTypeToPortalCommand(Guid portalId, string type) public class Handler : IRequestHandler { private readonly IReadWriteContext _readWriteContext; - private readonly IContextTypeService _contextTypeService; - public Handler(IReadWriteContext readWriteContext, IContextTypeService contextTypeService) + public Handler(IReadWriteContext readWriteContext) { _readWriteContext = readWriteContext; - _contextTypeService = contextTypeService; } public async Task Handle(AddContextTypeToPortalCommand command, CancellationToken cancellationToken) diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/CreatePortal/CreatePortalCommand.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/CreatePortal/CreatePortalCommand.cs index 5a047035e..73820066d 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/CreatePortal/CreatePortalCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/CreatePortal/CreatePortalCommand.cs @@ -42,7 +42,7 @@ public async Task Handle(CreatePortalCommand command, CancellationToken ca var portal = new Portal(slug, command.Name, command.ShortName, command.SubText, command.Description, command.Icon); - portal.AddContextTypes(await _contextTypeService.GetContextTypesByContextTypeKey(command.ContextTypes, cancellationToken)); + portal.AddContextTypes(await _contextTypeService.GetAllowedContextTypesByKeys(command.ContextTypes, cancellationToken)); await _readWriteContext.Set().AddAsync(portal, cancellationToken); diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/UpdatePortal/UpdatePortalCommand.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/UpdatePortal/UpdatePortalCommand.cs index 10d39732b..fb21af211 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/UpdatePortal/UpdatePortalCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/UpdatePortal/UpdatePortalCommand.cs @@ -55,7 +55,7 @@ public async Task Handle(UpdatePortalCommand command, CancellationToken ca entity.Update(slug, command.Name, command.ShortName, command.SubText, command.Description, command.Icon); - entity.AddContextTypes(await _contextTypeService.GetContextTypesByContextTypeKey(command.ContextTypes, cancellationToken)); + entity.AddContextTypes(await _contextTypeService.GetAllowedContextTypesByKeys(command.ContextTypes, cancellationToken)); await _readWriteContext.SaveChangesAsync(cancellationToken); diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Equinor.ProjectExecutionPortal.Application.csproj b/backend/src/Equinor.ProjectExecutionPortal.Application/Equinor.ProjectExecutionPortal.Application.csproj index 34500566f..00226a933 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Equinor.ProjectExecutionPortal.Application.csproj +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Equinor.ProjectExecutionPortal.Application.csproj @@ -8,13 +8,13 @@ - + + - diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/GetOnboardedApp/GetOnboardedAppQuery.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/GetOnboardedApp/GetOnboardedAppQuery.cs index 59737040b..e7ef4597f 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/GetOnboardedApp/GetOnboardedAppQuery.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/GetOnboardedApp/GetOnboardedAppQuery.cs @@ -44,7 +44,7 @@ public Handler(IReadWriteContext context, IMapper mapper, IAppService appService var onboardedApp = _mapper.Map(entity); - await _appService.EnrichAppWithFusionAppData(onboardedApp, cancellationToken); + await _appService.EnrichWithFusionAppData(onboardedApp, cancellationToken); return onboardedApp; } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/GetOnboardedApps/GetOnboardedAppsQuery.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/GetOnboardedApps/GetOnboardedAppsQuery.cs index e512e6900..87b4a322e 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/GetOnboardedApps/GetOnboardedAppsQuery.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/GetOnboardedApps/GetOnboardedAppsQuery.cs @@ -35,7 +35,7 @@ public async Task> Handle(GetOnboardedAppsQuery request, var onboardedApps = _mapper.Map, List>(entity); - await _appService.EnrichAppsWithFusionAppData(onboardedApps, cancellationToken); + await _appService.EnrichWithFusionAppData(onboardedApps, cancellationToken); return onboardedApps; } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/OnboardedAppDto.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/OnboardedAppDto.cs index 7aad27559..bcffda304 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/OnboardedAppDto.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/OnboardedAppDto.cs @@ -1,44 +1,22 @@ using Equinor.ProjectExecutionPortal.Application.Infrastructure.Mappings; using Equinor.ProjectExecutionPortal.Application.Queries.ContextTypes; -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models; +using Fusion.Integration.Apps.Abstractions.Models; namespace Equinor.ProjectExecutionPortal.Application.Queries.OnboardedApps; -public enum FusionPortalAppInformationAmount -{ - Minimal, - All -} - public class OnboardedAppDto : IMapFrom { public Guid Id { get; set; } - public string AppKey { get; set; } - public FusionPortalAppInformation? AppInformation { get; set; } - public IList ContextTypes { get; set; } + public string? AppKey { get; set; } + public string? DisplayName { get; set; } + public string? Description { get; set; } + public App? AppInformation { get; set; } + public IList ContextTypes { get; set; } = new List(); - public void SupplyWithFusionData(FusionPortalAppInformation appInformation, FusionPortalAppInformationAmount amount) + public void SupplyWithFusionData(App app) { - switch (amount) - { - case FusionPortalAppInformationAmount.All: - AppInformation = appInformation; - break; - - case FusionPortalAppInformationAmount.Minimal: - var appInfo = new FusionPortalAppInformation - { - Key = appInformation.Key, - Name = appInformation.Name, - Description = appInformation.Description - }; - - AppInformation = appInfo; - - break; - - default: - throw new ArgumentOutOfRangeException(nameof(amount), amount, null); - } + DisplayName = app.DisplayName; + Description = app.Description; + AppInformation = app; } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedContexts/GetOnboardedContext/GetOnboardedContextByExternalIdContextTypeQuery.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedContexts/GetOnboardedContext/GetOnboardedContextByExternalIdContextTypeQuery.cs index 980dc6352..aefca5719 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedContexts/GetOnboardedContext/GetOnboardedContextByExternalIdContextTypeQuery.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedContexts/GetOnboardedContext/GetOnboardedContextByExternalIdContextTypeQuery.cs @@ -15,8 +15,8 @@ public GetOnboardedContextByExternalIdContextTypeQuery(string externalId, string ContextType = contextType; } - public string ExternalId { get; } = null!; - public string ContextType { get; } = null!; + public string ExternalId { get; } + public string ContextType { get; } public class Handler : IRequestHandler { diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalAppKeys/GetContextualAndGlobalAppKeysByPortalAndContextQuery.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalAppKeys/GetContextualAndGlobalAppKeysByPortalAndContextQuery.cs new file mode 100644 index 000000000..6617137cb --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalAppKeys/GetContextualAndGlobalAppKeysByPortalAndContextQuery.cs @@ -0,0 +1,65 @@ +using Equinor.ProjectExecutionPortal.Application.Services.ContextService; +using Equinor.ProjectExecutionPortal.Domain.Common.Exceptions; +using Equinor.ProjectExecutionPortal.Domain.Entities; +using Equinor.ProjectExecutionPortal.Domain.Infrastructure; +using Equinor.ProjectExecutionPortal.Infrastructure; +using MediatR; +using Microsoft.EntityFrameworkCore; + +namespace Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalAppKeys; + +public class GetContextualAndGlobalAppKeysByPortalAndContextQuery : QueryBase> +{ + public GetContextualAndGlobalAppKeysByPortalAndContextQuery(Guid portalId, Guid contextId) + { + PortalId = portalId; + ContextId = contextId; + } + + public Guid PortalId { get; } + public Guid ContextId { get; } + + public class Handler : IRequestHandler> + { + private readonly IReadWriteContext _readWriteContext; + + private readonly IContextService _contextService; + + public Handler(IReadWriteContext readWriteContext, IContextService contextService) + { + _readWriteContext = readWriteContext; + + _contextService = contextService; + } + + public async Task> Handle(GetContextualAndGlobalAppKeysByPortalAndContextQuery request, CancellationToken cancellationToken) + { + var fusionContext = await _contextService.GetFusionContext(request.ContextId, cancellationToken); + + if (fusionContext == null) + { + throw new NotFoundException($"Invalid context-id: {request.ContextId}"); + } + + var portalWithContextualAndGlobalApps = await _readWriteContext.Set() + .AsNoTracking() + .Include(portal => portal.Apps + .Where(app => app.OnboardedContext == null || (app.OnboardedContext.ExternalId == fusionContext.ExternalId && app.OnboardedContext.Type == fusionContext.Type.Name))) + .ThenInclude(app => app.OnboardedApp) + .ThenInclude(app => app.ContextTypes) + .FirstOrDefaultAsync(x => x.Id == request.PortalId, cancellationToken); + + if (portalWithContextualAndGlobalApps == null) + { + throw new NotFoundException(nameof(Portal), request.PortalId); + } + + var contextualAndGlobalPortalAppKeys = portalWithContextualAndGlobalApps.Apps + .Where(apps => apps.OnboardedApp.ContextTypes.Count == 0 || apps.OnboardedApp.ContextTypes.Any(m => m.ContextTypeKey == fusionContext.Type.Name)) + .Select(app => app.OnboardedApp.AppKey) + .ToList(); + + return contextualAndGlobalPortalAppKeys; + } + } +} diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalAppKeys/GetGlobalAppKeysForPortalQuery.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalAppKeys/GetGlobalAppKeysForPortalQuery.cs new file mode 100644 index 000000000..b51662f51 --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalAppKeys/GetGlobalAppKeysForPortalQuery.cs @@ -0,0 +1,51 @@ +using Equinor.ProjectExecutionPortal.Domain.Common.Exceptions; +using Equinor.ProjectExecutionPortal.Domain.Entities; +using Equinor.ProjectExecutionPortal.Domain.Infrastructure; +using Equinor.ProjectExecutionPortal.Infrastructure; +using MediatR; +using Microsoft.EntityFrameworkCore; + +namespace Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalAppKeys; + +public class GetGlobalAppKeysForPortalQuery : QueryBase> +{ + public GetGlobalAppKeysForPortalQuery(Guid portalId) + { + PortalId = portalId; + } + + public Guid PortalId { get; } + + public class Handler : IRequestHandler> + { + private readonly IReadWriteContext _readWriteContext; + + public Handler(IReadWriteContext readWriteContext) + { + _readWriteContext = readWriteContext; + } + + public async Task> Handle(GetGlobalAppKeysForPortalQuery request, CancellationToken cancellationToken) + { + var portalWithGlobalApps = await _readWriteContext.Set() + .AsNoTracking() + .Include(portal => portal.Apps + .Where(app => app.OnboardedContext == null)) + .ThenInclude(portalApp => portalApp.OnboardedApp) + .ThenInclude(app => app.ContextTypes) + .FirstOrDefaultAsync(x => x.Id == request.PortalId, cancellationToken); + + if (portalWithGlobalApps == null) + { + throw new NotFoundException(nameof(Portal), request.PortalId); + } + + var globalPortalAppKeys = portalWithGlobalApps.Apps + .Select(app => app.OnboardedApp.AppKey) + .Distinct() + .ToList(); + + return globalPortalAppKeys; + } + } +} diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalApps/GetPortalAppsWithContextAndGlobalAppsByContextIdQuery.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalApps/GetContextualAndGlobalAppsByPortalAndContextQuery.cs similarity index 73% rename from backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalApps/GetPortalAppsWithContextAndGlobalAppsByContextIdQuery.cs rename to backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalApps/GetContextualAndGlobalAppsByPortalAndContextQuery.cs index ca57e0bdc..4cf29ae2c 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalApps/GetPortalAppsWithContextAndGlobalAppsByContextIdQuery.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalApps/GetContextualAndGlobalAppsByPortalAndContextQuery.cs @@ -10,10 +10,9 @@ namespace Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalApps; -public class GetPortalAppsWithContextAndGlobalAppsByContextIdQuery : QueryBase> +public class GetContextualAndGlobalAppsByPortalAndContextQuery : QueryBase> { - - public GetPortalAppsWithContextAndGlobalAppsByContextIdQuery(Guid portalId, Guid contextId) + public GetContextualAndGlobalAppsByPortalAndContextQuery(Guid portalId, Guid contextId) { PortalId = portalId; ContextId = contextId; @@ -22,7 +21,7 @@ public GetPortalAppsWithContextAndGlobalAppsByContextIdQuery(Guid portalId, Guid public Guid PortalId { get; } public Guid ContextId { get; } - public class Handler : IRequestHandler> + public class Handler : IRequestHandler> { private readonly IReadWriteContext _readWriteContext; private readonly IAppService _appService; @@ -37,14 +36,13 @@ public Handler(IReadWriteContext readWriteContext, IAppService appService, IMapp _contextService = contextService; } - public async Task> Handle(GetPortalAppsWithContextAndGlobalAppsByContextIdQuery request, CancellationToken cancellationToken) + public async Task> Handle(GetContextualAndGlobalAppsByPortalAndContextQuery request, CancellationToken cancellationToken) { - //TODO: Improve error handling var fusionContext = await _contextService.GetFusionContext(request.ContextId, cancellationToken); if (fusionContext == null) { - throw new InvalidActionException($"Invalid context-id: {request.ContextId}"); + throw new NotFoundException($"Invalid context-id: {request.ContextId}"); } var portal = await _readWriteContext.Set() @@ -56,14 +54,14 @@ public Handler(IReadWriteContext readWriteContext, IAppService appService, IMapp if (portal == null) { - return null; + throw new NotFoundException(nameof(Portal), request.PortalId); } var portalApps = portal.Apps.Where(apps => apps.OnboardedApp.ContextTypes.Count == 0 || apps.OnboardedApp.ContextTypes.Any(m => m.ContextTypeKey == fusionContext.Type.Name)).ToList(); - + var portalAppsDto = _mapper.Map, List>(portalApps); - - await _appService.EnrichAppsWithAllFusionAppData(portalAppsDto.Select(portalAppDto => portalAppDto.OnboardedApp).ToList(), cancellationToken); + + await _appService.EnrichWithFusionAppData(portalAppsDto.Select(portalAppDto => portalAppDto.OnboardedApp).ToList(), cancellationToken); return portalAppsDto; } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalApps/GetGlobalAppsForPortalQuery.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalApps/GetGlobalAppsForPortalQuery.cs new file mode 100644 index 000000000..97b93000d --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalApps/GetGlobalAppsForPortalQuery.cs @@ -0,0 +1,60 @@ +using AutoMapper; +using Equinor.ProjectExecutionPortal.Application.Services.AppService; +using Equinor.ProjectExecutionPortal.Domain.Common.Exceptions; +using Equinor.ProjectExecutionPortal.Domain.Entities; +using Equinor.ProjectExecutionPortal.Domain.Infrastructure; +using Equinor.ProjectExecutionPortal.Infrastructure; +using MediatR; +using Microsoft.EntityFrameworkCore; + +namespace Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalApps; + +public class GetGlobalAppsForPortalQuery : QueryBase> +{ + public GetGlobalAppsForPortalQuery(Guid portalId) + { + PortalId = portalId; + } + + public Guid PortalId { get; } + + public class Handler : IRequestHandler> + { + private readonly IReadWriteContext _readWriteContext; + private readonly IAppService _appService; + private readonly IMapper _mapper; + + public Handler(IReadWriteContext readWriteContext, IAppService appService, IMapper mapper) + { + _readWriteContext = readWriteContext; + _appService = appService; + _mapper = mapper; + } + + public async Task> Handle(GetGlobalAppsForPortalQuery request, CancellationToken cancellationToken) + { + var portalWithGlobalApps = await _readWriteContext.Set() + .AsNoTracking() + .Include(portal => portal.Apps + .Where(app => app.OnboardedContext == null)) + .ThenInclude(portalApp => portalApp.OnboardedApp) + .ThenInclude(app => app.ContextTypes) + .FirstOrDefaultAsync(x => x.Id == request.PortalId, cancellationToken); + + if (portalWithGlobalApps == null) + { + throw new NotFoundException(nameof(Portal), request.PortalId); + } + + var globalPortalApps = portalWithGlobalApps.Apps + .DistinctBy(x => x.OnboardedApp.Id) + .ToList(); + + var globalPortalAppsDto = _mapper.Map, List>(globalPortalApps); + + await _appService.EnrichWithFusionAppData(globalPortalAppsDto.Select(portalAppDto => portalAppDto.OnboardedApp).ToList(), cancellationToken); + + return globalPortalAppsDto; + } + } +} diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalApps/GetPortalAppsQuery.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalApps/GetPortalAppsQuery.cs deleted file mode 100644 index 13805fc42..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalApps/GetPortalAppsQuery.cs +++ /dev/null @@ -1,54 +0,0 @@ -using AutoMapper; -using Equinor.ProjectExecutionPortal.Application.Services.AppService; -using Equinor.ProjectExecutionPortal.Domain.Entities; -using Equinor.ProjectExecutionPortal.Domain.Infrastructure; -using Equinor.ProjectExecutionPortal.Infrastructure; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalApps; - -public class GetPortalAppsQuery : QueryBase -{ - public GetPortalAppsQuery(Guid portalId) - { - PortalId = portalId; - } - - public Guid PortalId { get; } - - public class Handler : IRequestHandler - { - private readonly IReadWriteContext _readWriteContext; - private readonly IAppService _appService; - private readonly IMapper _mapper; - - public Handler(IReadWriteContext readWriteContext, IAppService appService, IMapper mapper) - { - _readWriteContext = readWriteContext; - _appService = appService; - _mapper = mapper; - } - - public async Task Handle(GetPortalAppsQuery request, CancellationToken cancellationToken) - { - var portal = await _readWriteContext.Set() - .AsNoTracking() - .Include(portal => portal.Apps) - .ThenInclude(portalApp => portalApp.OnboardedApp) - .ThenInclude(app => app.ContextTypes) - .FirstOrDefaultAsync(x => x.Id == request.PortalId, cancellationToken); - - if (portal == null) - { - return null; - } - - var portalDto = _mapper.Map(portal); - - await _appService.EnrichAppsWithAllFusionAppData(portalDto.Apps.Select(portalAppDto => portalAppDto.OnboardedApp).ToList(), cancellationToken); - - return portalDto; - } - } -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApp/GetPortalOnboardedAppQuery.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApp/GetPortalOnboardedAppQuery.cs index c6b2681da..8c8c0c5b5 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApp/GetPortalOnboardedAppQuery.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApp/GetPortalOnboardedAppQuery.cs @@ -63,7 +63,7 @@ public Handler(IReadWriteContext readWriteContext, IAppService appService, IPort await _portalService.SetAppAsActiveInPortal(portalOnboardedAppDto, cancellationToken); - await _appService.EnrichAppWithFusionAppData(portalOnboardedAppDto.OnboardedApp, cancellationToken); + await _appService.EnrichWithFusionAppData(portalOnboardedAppDto.OnboardedApp, cancellationToken); return portalOnboardedAppDto; } @@ -75,9 +75,9 @@ public Handler(IReadWriteContext readWriteContext, IAppService appService, IPort if (onboardedApp != null) { - var portalOnboardedAppNotActive = await _portalService.GetPortalOnboardedAppNotActive(onboardedApp, cancellationToken); + var portalOnboardedAppNotActive = _portalService.GetPortalOnboardedAppNotActive(onboardedApp, cancellationToken); - await _appService.EnrichAppWithFusionAppData(portalOnboardedAppNotActive.OnboardedApp, cancellationToken); + await _appService.EnrichWithFusionAppData(portalOnboardedAppNotActive.OnboardedApp, cancellationToken); return portalOnboardedAppNotActive; } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApps/GetPortalOnboardedAppsQuery.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApps/GetPortalOnboardedAppsQuery.cs index 378702ac1..3b87c9d57 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApps/GetPortalOnboardedAppsQuery.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApps/GetPortalOnboardedAppsQuery.cs @@ -1,5 +1,4 @@ -using AutoMapper; -using Equinor.ProjectExecutionPortal.Application.Services.AppService; +using Equinor.ProjectExecutionPortal.Application.Services.AppService; using Equinor.ProjectExecutionPortal.Application.Services.PortalService; using Equinor.ProjectExecutionPortal.Domain.Entities; using Equinor.ProjectExecutionPortal.Domain.Infrastructure; @@ -9,26 +8,24 @@ namespace Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalOnboardedApps; -public class GetPortalOnboardedAppsQuery(Guid portalId) : QueryBase> +public class GetPortalOnboardedAppsQuery(Guid portalId) : QueryBase> { public Guid PortalId { get; } = portalId; - public class Handler : IRequestHandler> + public class Handler : IRequestHandler> { private readonly IReadWriteContext _readWriteContext; private readonly IAppService _appService; private readonly IPortalService _portalService; - private readonly IMapper _mapper; - public Handler(IReadWriteContext readWriteContext, IAppService appService, IPortalService portalService, IMapper mapper) + public Handler(IReadWriteContext readWriteContext, IAppService appService, IPortalService portalService) { _readWriteContext = readWriteContext; _appService = appService; _portalService = portalService; - _mapper = mapper; } - public async Task> Handle(GetPortalOnboardedAppsQuery request, CancellationToken cancellationToken) + public async Task> Handle(GetPortalOnboardedAppsQuery request, CancellationToken cancellationToken) { var portal = await _readWriteContext.Set() .AsNoTracking() @@ -40,7 +37,7 @@ public Handler(IReadWriteContext readWriteContext, IAppService appService, IPort if (portal == null) { - return new List(); + return new List(); } var onboardedApps = await _readWriteContext.Set() @@ -48,10 +45,10 @@ public Handler(IReadWriteContext readWriteContext, IAppService appService, IPort .Include(onboardedApp => onboardedApp.ContextTypes) .ToListAsync(cancellationToken); - var portalOnboardedAppsDto = await _portalService.CombinePortalAppsWithOnboardedApps(portal, onboardedApps, cancellationToken); + var portalOnboardedAppsDto = _portalService.CombinePortalAppsWithOnboardedApps(portal, onboardedApps, cancellationToken); + + await _appService.EnrichWithFusionAppData(portalOnboardedAppsDto.Select(portalAppDto => portalAppDto.OnboardedApp).ToList(), cancellationToken); - await _appService.EnrichAppsWithAllFusionAppData(portalOnboardedAppsDto.Select(portalAppDto => portalAppDto.OnboardedApp).ToList(), cancellationToken); - return portalOnboardedAppsDto; } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/PortalOnboardedAppDto.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/PortalOnboardedAppDto.cs index 2d88c2095..5d8e14d3f 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/PortalOnboardedAppDto.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/PortalOnboardedAppDto.cs @@ -10,6 +10,5 @@ public class PortalOnboardedAppDto : IMapFrom public bool IsActive { get; set; } = false; public bool IsGlobal { get; set; } public bool IsContextual { get; set; } - } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/AppService/AppService.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/AppService/AppService.cs index dc97bd5ca..00da04286 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/AppService/AppService.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/AppService/AppService.cs @@ -1,100 +1,59 @@ -using Equinor.ProjectExecutionPortal.Application.Cache; -using Equinor.ProjectExecutionPortal.Application.Queries.OnboardedApps; -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps; -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models; +using Equinor.ProjectExecutionPortal.Application.Queries.OnboardedApps; +using Equinor.ProjectExecutionPortal.Application.Services.FusionAppsService; +using Fusion.Integration.Apps.Abstractions.Models; namespace Equinor.ProjectExecutionPortal.Application.Services.AppService { public class AppService : IAppService { - private readonly IFusionAppsCache _fusionAppsCache; - private readonly IFusionPortalApiService _fusionPortalApiService; + private readonly IFusionAppsService _fusionAppsService; - public AppService(IFusionAppsCache fusionAppsCache, IFusionPortalApiService fusionPortalApiService) + public AppService(IFusionAppsService fusionAppsService) { - _fusionAppsCache = fusionAppsCache; - _fusionPortalApiService = fusionPortalApiService; + _fusionAppsService = fusionAppsService; } - public async Task FusionAppExist(string appKey, CancellationToken cancellationToken) + public async Task EnrichWithFusionAppData(OnboardedAppDto onboardedApp, CancellationToken cancellationToken) { - var fusionApps = await _fusionAppsCache.GetFusionApps(); - - return fusionApps.Any(app => app.Key == appKey); - } - - public async Task> GetFusionApps() - { - return await _fusionAppsCache.GetFusionApps(); - } - - public async Task GetFusionApp(string appKey) - { - return await _fusionAppsCache.GetFusionApp(appKey); - } - - public async Task GetFusionAppConfig(string appKey) - { - return await _fusionPortalApiService.TryGetFusionPortalAppConfig(appKey); - } - - public async Task EnrichAppWithFusionAppData(OnboardedAppDto onboardedApp, CancellationToken cancellationToken) - { - var fusionApp = await GetFusionApp(onboardedApp.AppKey); - - if (fusionApp != null) + if (onboardedApp.AppKey == null) { - onboardedApp.SupplyWithFusionData(fusionApp, FusionPortalAppInformationAmount.All); + return onboardedApp; } - return onboardedApp; - } - - public async Task> EnrichAppsWithFusionAppData(IList onboardedApps, CancellationToken cancellationToken) - { - var fusionApps = await GetFusionApps(); + var fusionApp = await _fusionAppsService.GetFusionApp(onboardedApp.AppKey); - foreach (var onboardedAppDto in onboardedApps) + if (fusionApp != null) { - CombineAppWithFusionAppData(onboardedAppDto, fusionApps, false); + onboardedApp.SupplyWithFusionData(fusionApp); } - return onboardedApps; + return onboardedApp; } - public async Task> EnrichAppsWithAllFusionAppData(IList onboardedApps, CancellationToken cancellationToken) + public async Task> EnrichWithFusionAppData(IList onboardedApps, CancellationToken cancellationToken) { - var fusionApps = await GetFusionApps(); + var fusionApps = await _fusionAppsService.GetFusionApps(); - foreach (var onboardedAppDto in onboardedApps) + foreach (var onboardedApp in onboardedApps) { - CombineAppWithFusionAppData(onboardedAppDto, fusionApps, true); + CombineAppWithFusionAppData(onboardedApp, fusionApps); } return onboardedApps; } - private static void CombineAppWithFusionAppData(OnboardedAppDto? onboardedAppDto, IEnumerable fusionApps, bool? allFusionData) + private static void CombineAppWithFusionAppData(OnboardedAppDto? onboardedApp, IEnumerable fusionApps) { - if (onboardedAppDto == null) + if (onboardedApp?.AppKey == null) { return; } - var fusionApp = fusionApps.FirstOrDefault(x => string.Equals(x.Key, onboardedAppDto.AppKey, StringComparison.CurrentCultureIgnoreCase)); + var fusionApp = fusionApps.FirstOrDefault(fusionApp => string.Equals(fusionApp.AppKey, onboardedApp.AppKey, StringComparison.CurrentCultureIgnoreCase)); - if (fusionApp != null) { - switch (allFusionData) - { - case true: - onboardedAppDto.SupplyWithFusionData(fusionApp, FusionPortalAppInformationAmount.All); - break; - case false: - onboardedAppDto.SupplyWithFusionData(fusionApp, FusionPortalAppInformationAmount.Minimal); - break; - } + onboardedApp.SupplyWithFusionData(fusionApp); } } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/AppService/IAppService.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/AppService/IAppService.cs index 6f212dda8..462a35a7c 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/AppService/IAppService.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/AppService/IAppService.cs @@ -1,24 +1,11 @@ using Equinor.ProjectExecutionPortal.Application.Queries.OnboardedApps; -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models; namespace Equinor.ProjectExecutionPortal.Application.Services.AppService { public interface IAppService { - Task FusionAppExist(string appKey, CancellationToken cancellationToken); + Task EnrichWithFusionAppData(OnboardedAppDto onboardedApp, CancellationToken cancellationToken); - Task> GetFusionApps(); - - Task GetFusionApp(string appKey); - - Task GetFusionAppConfig(string appKey); - - Task EnrichAppWithFusionAppData(OnboardedAppDto onboardedApp, CancellationToken cancellationToken); - - Task> EnrichAppsWithFusionAppData(IList apps, CancellationToken cancellationToken); - - Task> EnrichAppsWithAllFusionAppData(IList apps, CancellationToken cancellationToken); - - + Task> EnrichWithFusionAppData(IList apps, CancellationToken cancellationToken); } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextTypeService/ContextTypeService.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextTypeService/ContextTypeService.cs index fdba7db3f..80c9691d0 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextTypeService/ContextTypeService.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextTypeService/ContextTypeService.cs @@ -13,16 +13,16 @@ public ContextTypeService(IReadWriteContext readWriteContext) { _readWriteContext = readWriteContext; } - public async Task> GetContextTypesByContextTypeKey(IList contextTypeKeys, CancellationToken cancellationToken) - { + public async Task> GetAllowedContextTypesByKeys(IList contextTypeKeys, CancellationToken cancellationToken) + { if (contextTypeKeys.Count == 0) { return new List(); } - var availableContextTypes = await _readWriteContext.Set().ToListAsync(); - + var availableContextTypes = await _readWriteContext.Set().ToListAsync(cancellationToken); + var invalidContextTypes = contextTypeKeys.FirstOrDefault(key => !availableContextTypes.Select(contextType => contextType.ContextTypeKey).Contains(key)); if (invalidContextTypes != null) @@ -32,7 +32,6 @@ public async Task> GetContextTypesByContextTypeKey(IList contextTypeKeys.Select(key => key).Contains(contextType.ContextTypeKey)).ToList(); - return addContextTypes.ToList(); } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextTypeService/IContextTypeService.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextTypeService/IContextTypeService.cs index e4d56ba30..4c0415171 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextTypeService/IContextTypeService.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextTypeService/IContextTypeService.cs @@ -1,10 +1,9 @@ -using Equinor.ProjectExecutionPortal.Application.Queries.ContextTypes; -using Equinor.ProjectExecutionPortal.Domain.Entities; +using Equinor.ProjectExecutionPortal.Domain.Entities; namespace Equinor.ProjectExecutionPortal.Application.Services.ContextTypeService { public interface IContextTypeService { - Task> GetContextTypesByContextTypeKey(IList contextTypeKeys, CancellationToken cancellationToken); + Task> GetAllowedContextTypesByKeys(IList contextTypeKeys, CancellationToken cancellationToken); } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/FusionAppsService/FusionAppsService.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/FusionAppsService/FusionAppsService.cs new file mode 100644 index 000000000..bb300acc7 --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/FusionAppsService/FusionAppsService.cs @@ -0,0 +1,40 @@ +using Equinor.ProjectExecutionPortal.Application.Cache; +using Fusion.Integration.Apps.Abstractions.Abstractions; +using Fusion.Integration.Apps.Abstractions.Models; + +namespace Equinor.ProjectExecutionPortal.Application.Services.FusionAppsService +{ + public class FusionAppsService : IFusionAppsService + { + private readonly IFusionAppsCache _fusionAppsCache; + private readonly IAppsClient _fusionAppsClient; + + public FusionAppsService(IFusionAppsCache fusionAppsCache, IAppsClient fusionAppsClient) + { + _fusionAppsCache = fusionAppsCache; + _fusionAppsClient = fusionAppsClient; + } + + public async Task FusionAppExist(string appKey, CancellationToken cancellationToken) + { + var fusionApps = await _fusionAppsCache.GetFusionApps(); + + return fusionApps.Any(app => app.AppKey == appKey); + } + + public async Task> GetFusionApps() + { + return await _fusionAppsCache.GetFusionApps(); + } + + public async Task GetFusionApp(string appKey) + { + return await _fusionAppsCache.GetFusionApp(appKey); + } + + public async Task GetFusionAppConfig(string appKey) + { + return await _fusionAppsClient.GetAppConfig(appKey, new TagNameIdentifier("latest")); + } + } +} diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/FusionAppsService/IFusionAppsService.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/FusionAppsService/IFusionAppsService.cs new file mode 100644 index 000000000..a7bf1f33c --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/FusionAppsService/IFusionAppsService.cs @@ -0,0 +1,15 @@ +using Fusion.Integration.Apps.Abstractions.Models; + +namespace Equinor.ProjectExecutionPortal.Application.Services.FusionAppsService +{ + public interface IFusionAppsService + { + Task FusionAppExist(string appKey, CancellationToken cancellationToken); + + Task> GetFusionApps(); + + Task GetFusionApp(string appKey); + + Task GetFusionAppConfig(string appKey); + } +} diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/PortalService/IPortalService.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/PortalService/IPortalService.cs index 2c5ef279e..e007ed7e1 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/PortalService/IPortalService.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/PortalService/IPortalService.cs @@ -5,10 +5,12 @@ namespace Equinor.ProjectExecutionPortal.Application.Services.PortalService { public interface IPortalService { - Task> SetAppsAsActiveInPortal(IList apps, CancellationToken cancellationToken); Task SetAppAsActiveInPortal(PortalOnboardedAppDto app, CancellationToken cancellationToken); - Task> CombinePortalAppsWithOnboardedApps(Portal portal, IList onboardedApps, CancellationToken cancellationToken); - Task GetPortalOnboardedAppNotActive(OnboardedApp onboardedApp, CancellationToken cancellationToken); + + IList CombinePortalAppsWithOnboardedApps(Portal portal, IList onboardedApps, CancellationToken cancellationToken); + + PortalOnboardedAppDto GetPortalOnboardedAppNotActive(OnboardedApp onboardedApp, CancellationToken cancellationToken); + Task EnrichPortalAppWithContextIds(PortalOnboardedAppDto portalOnboardedAppDto, IList contextIds, CancellationToken cancellationToken); } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/PortalService/PortalService.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/PortalService/PortalService.cs index e5602f55c..04fd40ff2 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/PortalService/PortalService.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/PortalService/PortalService.cs @@ -6,27 +6,27 @@ namespace Equinor.ProjectExecutionPortal.Application.Services.PortalService { public class PortalService : IPortalService - { + { private readonly IMapper _mapper; public PortalService(IMapper mapper) { _mapper = mapper; } - public async Task> CombinePortalAppsWithOnboardedApps(Portal portal, IList onboardedApps, CancellationToken cancellationToken) - { + public IList CombinePortalAppsWithOnboardedApps(Portal portal, IList onboardedApps, CancellationToken cancellationToken) + { var portalAppsDto = _mapper.Map, List>(GetDistinctPortalApps(portal.Apps.ToList())); - await SetAppsAsActiveInPortal(portalAppsDto, cancellationToken); + SetAppsAsActiveInPortal(portalAppsDto); var onBoardedAppsNotActiveInPortal = GetOnBoardedAppsNotActiveInPortal(portal, onboardedApps); portalAppsDto.AddRange(onBoardedAppsNotActiveInPortal); return portalAppsDto.OrderBy(x => x.OnboardedApp?.AppKey).ToList(); - } + public async Task EnrichPortalAppWithContextIds(PortalOnboardedAppDto portalOnboardedAppDto, IList contextIds, CancellationToken cancellationToken) { portalOnboardedAppDto.ContextIds = contextIds.ToList(); @@ -36,7 +36,7 @@ public async Task EnrichPortalAppWithContextIds(PortalOnb return portalOnboardedAppDto; } - public async Task GetPortalOnboardedAppNotActive(OnboardedApp onboardedApp, CancellationToken cancellationToken) + public PortalOnboardedAppDto GetPortalOnboardedAppNotActive(OnboardedApp onboardedApp, CancellationToken cancellationToken) { return new PortalOnboardedAppDto() { @@ -45,29 +45,29 @@ public async Task GetPortalOnboardedAppNotActive(Onboarde }; } - public async Task> SetAppsAsActiveInPortal(IList apps, CancellationToken cancellationToken) - { - foreach (var app in apps) - { - app.IsActive = true; - } - await Task.CompletedTask; - return apps; - } - public async Task SetAppAsActiveInPortal(PortalOnboardedAppDto app, CancellationToken cancellationToken) { app.IsActive = true; - + await Task.CompletedTask; + return app; } - private List GetDistinctPortalApps(List portalApps) + private static void SetAppsAsActiveInPortal(IList apps) + { + foreach (var app in apps) + { + app.IsActive = true; + } + } + + private static List GetDistinctPortalApps(List portalApps) { var distinctPortalApps = portalApps.GroupBy(app => app.OnboardedApp.Id) .Select(group => group.First()) .ToList(); + return distinctPortalApps; } @@ -89,11 +89,11 @@ private List GetOnBoardedAppsNotActiveInPortal(Portal por OnboardedApp = _mapper.Map(onBoardedApp), IsActive = false }).ToList(); - } - private bool IsContextualPortal(Portal portal) + + private static bool IsContextualPortal(Portal portal) { - return portal.ContextTypes.Count != 0; + return portal.ContextTypes.Count > 0; } } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/ContextType.cs b/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/ContextType.cs index d5f76a584..2ed5a5037 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/ContextType.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/ContextType.cs @@ -19,6 +19,5 @@ public ContextType(string contextTypeKey) public IReadOnlyCollection Portals => _portals.AsReadOnly(); public IReadOnlyCollection OnboardedApps => _onboardedApps.AsReadOnly(); - } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/Portal.cs b/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/Portal.cs index 5f29e537d..b4426168d 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/Portal.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/Portal.cs @@ -50,11 +50,6 @@ public void Update(string key, string name, string shortName, string subText, st Icon = icon; } - private static PortalConfiguration CreateDefaultPortalConfiguration() - { - return new PortalConfiguration(null,null, null); - } - public void AddApp(PortalApp app) { _apps.Add(app); @@ -113,4 +108,9 @@ public bool HasAppForAnyContexts(Guid onboardedAppId) return HasApp(onboardedAppId) && _apps.Any(portalApp => portalApp.IsContextual); } + + private static PortalConfiguration CreateDefaultPortalConfiguration() + { + return new PortalConfiguration(null, null, null); + } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/FusionPortalApiService.cs b/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/FusionPortalApiService.cs deleted file mode 100644 index fdb9b9c3f..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/FusionPortalApiService.cs +++ /dev/null @@ -1,100 +0,0 @@ -using Equinor.ProjectExecutionPortal.Domain.Interfaces; -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models; -using Equinor.ProjectExecutionPortal.FusionPortalApi.Client; -using Microsoft.Extensions.Options; - -namespace Equinor.ProjectExecutionPortal.FusionPortalApi.Apps; - -public class FusionPortalApiService : IFusionPortalApiService -{ - private readonly Uri _baseAddress; - private readonly string _apiVersion; - private readonly IBearerTokenFusionPortalApiClient _fusionPortalApiClient; - private readonly IAuthenticator _authenticator; - - public FusionPortalApiService( - IBearerTokenFusionPortalApiClient fusionPortalApiClient, - IOptionsMonitor options, - IAuthenticator authenticator) - { - _fusionPortalApiClient = fusionPortalApiClient; - _authenticator = authenticator; - _baseAddress = new Uri(options.CurrentValue.BaseAddress); - _apiVersion = options.CurrentValue.ApiVersion; - } - - public async Task> TryGetFusionPortalApps() - { - var url = $"{_baseAddress}/api/apps/" + - $"?api-version={_apiVersion}"; - - var oldAuthType = _authenticator.AuthenticationType; - _authenticator.AuthenticationType = AuthenticationType.AsApplication; - - try - { - return await _fusionPortalApiClient.TryQueryAndDeserializeAsync>(url); - } - finally - { - _authenticator.AuthenticationType = oldAuthType; - } - } - - public async Task TryGetFusionPortalApp(string appKey) - { - var url = $"{_baseAddress}/api/apps/" + - $"{appKey}" + - $"?api-version={_apiVersion}"; - - var oldAuthType = _authenticator.AuthenticationType; - _authenticator.AuthenticationType = AuthenticationType.AsApplication; - - try - { - return await _fusionPortalApiClient.TryQueryAndDeserializeAsync(url); - } - finally - { - _authenticator.AuthenticationType = oldAuthType; - } - } - - public async Task TryGetFusionPortalAppConfig(string appKey) - { - var url = $"{_baseAddress}/api/apps/" + - $"{appKey}/config" + - $"?api-version={_apiVersion}"; - - var oldAuthType = _authenticator.AuthenticationType; - _authenticator.AuthenticationType = AuthenticationType.AsApplication; - - try - { - return await _fusionPortalApiClient.TryQueryAndDeserializeAsync(url); - } - finally - { - _authenticator.AuthenticationType = oldAuthType; - } - } - - public async Task TryGetFusionPortalAppBundle(string appKey) - { - var url = $"{_baseAddress}/scripts/apps/" + - $"{appKey}" + - $"?api-version={_apiVersion}"; - - var oldAuthType = _authenticator.AuthenticationType; - _authenticator.AuthenticationType = AuthenticationType.AsApplication; - - try - { - return await _fusionPortalApiClient.TryQueryAsByteArrayAsync(url); - } - finally - { - _authenticator.AuthenticationType = oldAuthType; - } - } -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/IFusionPortalApiService.cs b/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/IFusionPortalApiService.cs deleted file mode 100644 index 29d4358d3..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/IFusionPortalApiService.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models; - -namespace Equinor.ProjectExecutionPortal.FusionPortalApi.Apps; - -public interface IFusionPortalApiService -{ - Task> TryGetFusionPortalApps(); - - Task TryGetFusionPortalApp(string appKey); - - Task TryGetFusionPortalAppConfig(string appKey); - - Task TryGetFusionPortalAppBundle(string appKey); -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionAppEnvironmentConfig.cs b/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionAppEnvironmentConfig.cs deleted file mode 100644 index 5d085eccc..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionAppEnvironmentConfig.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models -{ - public class FusionAppEnvironmentConfig - { - [JsonPropertyName("environment")] - public object Environment { get; set; } = new (); - - [JsonPropertyName("endpoints")] - public Dictionary Endpoints { get; set; } = new(); - - [JsonPropertyName("tag")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string? Tag { get; set; } - - [JsonPropertyName("invalidConfig")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public bool? InvalidConfig { get; set; } - - [JsonPropertyName("error")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string? Error { get; set; } - } -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionPortalAppInformation.cs b/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionPortalAppInformation.cs deleted file mode 100644 index 0f48b56ad..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionPortalAppInformation.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models; - -public class FusionPortalAppInformation -{ - [JsonPropertyName("key")] - public string Key { get; set; } - - [JsonPropertyName("name")] - public string Name { get; set; } - - [JsonPropertyName("version")] - public string? Version { get; set; } - - [JsonPropertyName("shortName")] - public string? ShortName { get; set; } - - [JsonPropertyName("description")] - public string Description { get; set; } - - [JsonPropertyName("publishedDate")] - public string? PublishedDate { get; set; } - - [JsonPropertyName("tags")] - public string[] Tags { get; set; } - - [JsonPropertyName("hide")] - public bool? Hide { get; set; } - - [JsonPropertyName("order")] - public int Order { get; set; } - - [JsonPropertyName("type")] - public string? Type { get; set; } - - [JsonPropertyName("accentColor")] - public string? AccentColor { get; set; } - - [JsonPropertyName("icon")] - public string? Icon { get; set; } - - [JsonPropertyName("categoryId")] - public Guid? CategoryId { get; set; } - - [JsonPropertyName("category")] - public FusionPortalAppInformationCategory? Category { get; set; } - - [JsonPropertyName("owners")] - public Guid[] Owners { get; set; } - - [JsonPropertyName("admins")] - public FusionPortalAppInformationAdmin[] Admins { get; set; } - - [JsonPropertyName("healthChecks")] - public FusionPortalHealthCheck[] HealthChecks { get; set; } - - [JsonPropertyName("requiredRoles")] - public FusionPortalRole[] RequiredRoles { get; set; } -} - -public class FusionPortalAppInformationCategory -{ - [JsonPropertyName("id")] - public Guid Id { get; set; } - - [JsonPropertyName("name")] - public string Name { get; set; } - - [JsonPropertyName("color")] - public string Color { get; set; } - - [JsonPropertyName("defaultIcon")] - public string DefaultIcon { get; set; } -} - -public class FusionPortalAppInformationAdmin -{ - [JsonPropertyName("azureUniqueId")] - public Guid AzureUniqueId { get; set; } - - [JsonPropertyName("fusionRole")] - public string FusionRole { get; set; } - - [JsonPropertyName("profile")] - public FusionPortalProfile Profile { get; set; } -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionPortalHealthCheck.cs b/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionPortalHealthCheck.cs deleted file mode 100644 index f5605b8fc..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionPortalHealthCheck.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models -{ - public class FusionPortalHealthCheck - { - [JsonPropertyName("url")] - public string Url { get; set; } - } -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionPortalProfile.cs b/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionPortalProfile.cs deleted file mode 100644 index 124b86b95..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionPortalProfile.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models -{ - public class FusionPortalProfile - { - [JsonPropertyName("name")] - public string Name { get; set; } - - [JsonPropertyName("upn")] - public string Upn { get; set; } - - [JsonPropertyName("mail")] - public string Mail { get; set; } - - [JsonPropertyName("applicationId")] - public Guid ApplicationId { get; set; } - - [JsonPropertyName("type")] - public string Type { get; set; } - } -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionPortalRole.cs b/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionPortalRole.cs deleted file mode 100644 index 5aba4da90..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Apps/Models/FusionPortalRole.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models -{ - public class FusionPortalRole - { - [JsonPropertyName("fusionRole")] - public string FusionRole { get; set; } - - [JsonPropertyName("azureAdGroupId")] - public Guid AzureAdGroupId { get; set; } - } -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Client/FusionPortalApiClient.cs b/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Client/FusionPortalApiClient.cs deleted file mode 100644 index f48eab5b1..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Client/FusionPortalApiClient.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Diagnostics; -using System.Net; -using System.Net.Http.Headers; -using System.Text.Json; -using Equinor.ProjectExecutionPortal.Domain.Interfaces; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace Equinor.ProjectExecutionPortal.FusionPortalApi.Client; - -public class FusionPortalApiClient : IBearerTokenFusionPortalApiClient -{ - private readonly IHttpClientFactory _httpClientFactory; - private readonly IBearerTokenProvider _bearerTokenProvider; - private readonly ILogger _logger; - private readonly IOptionsMonitor _options; - - public FusionPortalApiClient( - IHttpClientFactory httpClientFactory, - IBearerTokenProvider bearerTokenProvider, - ILogger logger, - IOptionsMonitor options) - { - _httpClientFactory = httpClientFactory; - _bearerTokenProvider = bearerTokenProvider; - _logger = logger; - _options = options; - } - - public async Task TryQueryAndDeserializeAsync(string url) => await QueryAndDeserializeAsync(url, true); - - public async Task QueryAndDeserializeAsync(string url) => await QueryAndDeserializeAsync(url, false); - - private async Task QueryAndDeserializeAsync(string url, bool tryGet) - { - if (string.IsNullOrEmpty(url)) - { - throw new ArgumentNullException(nameof(url)); - } - - if (url.Length > 2000) - { - throw new ArgumentException("url exceed max 2000 characters", nameof(url)); - } - - var httpClient = await CreateHttpClientAsync(); - - var stopWatch = Stopwatch.StartNew(); - var response = await httpClient.GetAsync(url); - stopWatch.Stop(); - - var msg = $"{stopWatch.Elapsed.TotalSeconds}s elapsed when requesting '{url}'. Status: {response.StatusCode}"; - if (!response.IsSuccessStatusCode) - { - if (tryGet && response.StatusCode == HttpStatusCode.NotFound) - { - _logger.LogWarning(msg); - return default; - } - _logger.LogError(msg); - throw new Exception($"Requesting '{url}' was unsuccessful. Status={response.StatusCode}"); - } - - _logger.LogInformation(msg); - var jsonResult = await response.Content.ReadAsStringAsync(); - var result = JsonSerializer.Deserialize(jsonResult); - return result; - } - - public async Task TryQueryAsByteArrayAsync(string url) - { - if (string.IsNullOrEmpty(url)) - { - throw new ArgumentNullException(nameof(url)); - } - - if (url.Length > 2000) - { - throw new ArgumentException("url exceed max 2000 characters", nameof(url)); - } - - var httpClient = await CreateHttpClientAsync(); - - var stopWatch = Stopwatch.StartNew(); - var response = await httpClient.GetAsync(url); - stopWatch.Stop(); - - var msg = $"{stopWatch.Elapsed.TotalSeconds}s elapsed when requesting '{url}'. Status: {response.StatusCode}"; - - if (!response.IsSuccessStatusCode) - { - if (response.StatusCode == HttpStatusCode.NotFound) - { - _logger.LogWarning(msg); - return default; - } - _logger.LogError(msg); - throw new Exception($"Requesting '{url}' was unsuccessful. Status={response.StatusCode}"); - } - - _logger.LogInformation(msg); - - return await response.Content.ReadAsByteArrayAsync(); - } - - private async ValueTask CreateHttpClientAsync() - { - var httpClient = _httpClientFactory.CreateClient(); - var bearerToken = await _bearerTokenProvider.GetBearerTokenAsync(_options.CurrentValue.Scope); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken); - return httpClient; - } -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Client/IBearerTokenFusionPortalApiClient.cs b/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Client/IBearerTokenFusionPortalApiClient.cs deleted file mode 100644 index 9e32fb5db..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Client/IBearerTokenFusionPortalApiClient.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Equinor.ProjectExecutionPortal.FusionPortalApi.Client; - -public interface IBearerTokenFusionPortalApiClient -{ - Task TryQueryAndDeserializeAsync(string url); - - Task QueryAndDeserializeAsync(string url); - - Task TryQueryAsByteArrayAsync(string url); -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Equinor.ProjectExecutionPortal.FusionPortalApi.csproj b/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Equinor.ProjectExecutionPortal.FusionPortalApi.csproj deleted file mode 100644 index 6b7d49d7f..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/Equinor.ProjectExecutionPortal.FusionPortalApi.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - - - - - - diff --git a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/FusionPortalApiOptions.cs b/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/FusionPortalApiOptions.cs deleted file mode 100644 index 9f17aa2a7..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.FusionPortalApi/FusionPortalApiOptions.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Equinor.ProjectExecutionPortal.FusionPortalApi; - -public class FusionPortalApiOptions -{ - public string BaseAddress { get; set; } - public string Scope { get; set; } - public string ApiVersion { get; set; } -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/EntityConfigurations/ContextTypeConfiguration.cs b/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/EntityConfigurations/ContextTypeConfiguration.cs index bec9d1574..a6fccef48 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/EntityConfigurations/ContextTypeConfiguration.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/EntityConfigurations/ContextTypeConfiguration.cs @@ -19,7 +19,6 @@ public void Configure(EntityTypeBuilder builder) builder.Property(t => t.ContextTypeKey) .HasMaxLength(ContextType.ContextTypeKeyLengthMax) .IsRequired(); - } } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/BundleController.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/BundleController.cs deleted file mode 100644 index 2f001d12b..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/BundleController.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; - -namespace Equinor.ProjectExecutionPortal.WebApi.Controllers -{ - //[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - [ApiVersion("0.1")] - [Route("api/bundles")] - [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] - public class BundleController : ApiControllerBase - { - [AllowAnonymous] - [HttpGet("{appKey}")] - [HttpGet("{appKey}.js")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] - public async Task FusionPortalAppBundle([FromServices] IFusionPortalApiService fusionPortalApiService, [FromRoute] string appKey) - { - try - { - var appBundle = await fusionPortalApiService.TryGetFusionPortalAppBundle(appKey); - - return File(appBundle, "application/javascript"); - } - catch (Exception ex) - { - return FusionApiError.NotFound(appKey, ex.Message); - } - } - } -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/ContextTypeController.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/ContextTypeController.cs index 4cb2e33d1..a1f1e2fff 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/ContextTypeController.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/ContextTypeController.cs @@ -1,5 +1,4 @@ -using System.Data; -using System.Net.Mime; +using System.Net.Mime; using Equinor.ProjectExecutionPortal.Application.Queries.ContextTypes.GetContextTypes; using Equinor.ProjectExecutionPortal.Domain.Common.Exceptions; using Equinor.ProjectExecutionPortal.WebApi.Authorization; @@ -8,8 +7,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 - namespace Equinor.ProjectExecutionPortal.WebApi.Controllers { [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/FusionController.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/FusionController.cs index a98e664c3..76df922bc 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/FusionController.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/FusionController.cs @@ -1,18 +1,18 @@ -using Equinor.ProjectExecutionPortal.Application.Services.AppService; -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models; +using Equinor.ProjectExecutionPortal.Application.Services.FusionAppsService; using Fusion.Integration; +using Fusion.Integration.Apps.Abstractions.Models; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace Equinor.ProjectExecutionPortal.WebApi.Controllers { + // TODO: This controller should be removed and replaced with the ClientBackend proxy [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] [ApiVersion("0.1")] [Route("api/fusion")] public class FusionController : ApiControllerBase { - [HttpGet("context/{externalId}/type/{contextType}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] @@ -38,9 +38,9 @@ public ActionResult> GetAllFusionContextTypes() } [HttpGet("apps")] - public async Task>> GetAllFusionApps([FromServices] IAppService appService) + public async Task>> GetAllFusionApps([FromServices] IFusionAppsService fusionAppsService) { - var apps = await appService.GetFusionApps(); + var apps = await fusionAppsService.GetFusionApps(); return Ok(apps.ToList()); } @@ -48,9 +48,9 @@ public async Task>> GetAllFusionA [HttpGet("apps/{appKey}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] - public async Task> GetFusionApp([FromRoute] string appKey, [FromServices] IAppService appService) + public async Task> GetFusionApp([FromRoute] string appKey, [FromServices] IFusionAppsService fusionAppsService) { - var fusionApp = await appService.GetFusionApp(appKey); + var fusionApp = await fusionAppsService.GetFusionApp(appKey); return fusionApp == null ? FusionApiError.NotFound(appKey, "Could not find fusion app") : Ok(fusionApp); } @@ -58,9 +58,9 @@ public async Task>> GetAllFusionA [HttpGet("apps/{appKey}/config")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] - public async Task> GetFusionAppConfig([FromRoute] string appKey, [FromServices] IAppService appService) + public async Task> GetFusionAppConfig([FromRoute] string appKey, [FromServices] IFusionAppsService fusionAppsService) { - var appConfig = await appService.GetFusionAppConfig(appKey); + var appConfig = await fusionAppsService.GetFusionAppConfig(appKey); return appConfig == null ? FusionApiError.NotFound(appKey, "Could not locate config for the specified appKey") : Ok(appConfig); } diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/OnboardedAppController.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/OnboardedAppController.cs index 11aa9edd3..9bba960be 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/OnboardedAppController.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/OnboardedAppController.cs @@ -27,7 +27,7 @@ public async Task>> OnboardedApps() [HttpGet("{appKey}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] - public async Task> OnboardedApp([FromRoute] string appKey) + public async Task> OnboardedApp([FromRoute] string appKey) { var onboardedAppDto = await Mediator.Send(new GetOnboardedAppQuery(appKey)); @@ -36,7 +36,7 @@ public async Task> OnboardedApp([FromRoute] string return FusionApiError.NotFound(appKey, "Could not find onboarded app"); } - return new ApiOnboardedApp(onboardedAppDto); + return new ApiOnboardedAppExpanded(onboardedAppDto); } [HttpPost("")] @@ -169,7 +169,7 @@ public async Task> AddContextType([FromRoute] string appKey, return Ok(); } - + [HttpDelete("{appKey}/context-type/{contextType}")] [Authorize(Policy = Policies.ProjectPortal.Admin)] [ProducesResponseType(StatusCodes.Status200OK)] diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/PortalController.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/PortalController.cs index b76868bdd..8988d0963 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/PortalController.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/PortalController.cs @@ -1,5 +1,6 @@ using System.Net.Mime; using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortal; +using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalAppKeys; using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalApps; using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalConfiguration; using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalOnboardedApp; @@ -171,27 +172,7 @@ public async Task RemovePortalApp([FromRoute] Guid portalId) return Ok(); } - // Apps - - [HttpGet("{portalId:guid}/apps")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] - public async Task>> PortalApps([FromRoute] Guid portalId) - { - //TODO: improve error handling - var portalAppsDto = await Mediator.Send(new GetPortalAppsQuery(portalId)); - - if (portalAppsDto == null) - { - return FusionApiError.NotFound(portalId, "Could not find portal with id"); - - } - - var portalApps = portalAppsDto.Apps.DistinctBy(x => x.OnboardedApp.Id); - - return Ok(portalApps.Select(x => new ApiPortalApp(x)).ToList()); - - } + // Onboarded Apps [HttpGet("{portalId:guid}/onboarded-apps")] [ProducesResponseType(StatusCodes.Status200OK)] @@ -205,8 +186,7 @@ public async Task>> PortalOnboardedApps return FusionApiError.NotFound(portalId, "Could not find portal with id"); } - return Ok(portalOnboardedAppsDto.Select(x => new ApiPortalOnboardedApp(x)).ToList()); - + return Ok(portalOnboardedAppsDto.Select(onboardedAppDto => new ApiPortalOnboardedApp(onboardedAppDto)).ToList()); } [HttpGet("{portalId:guid}/onboarded-apps/{appKey}")] @@ -222,7 +202,73 @@ public async Task> PortalOnboardedApp([FromR } return new ApiPortalOnboardedApp(portalOnboardedAppDto); + } + + // App Keys + [HttpGet("{portalId:guid}/appkeys")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + public async Task>> PortalAppKeys([FromRoute] Guid portalId) + { + try + { + var portalGlobalAppKeys = await Mediator.Send(new GetGlobalAppKeysForPortalQuery(portalId)); + + return Ok(portalGlobalAppKeys); + } + catch (NotFoundException ex) + { + return FusionApiError.NotFound(portalId, ex.Message); + } + catch (Exception) + { + return FusionApiError.InvalidOperation("500", "An error occurred"); + } + } + + [HttpGet("{portalId:guid}/contexts/{contextId:guid}/appkeys")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + public async Task>> PortalAppKeys([FromRoute] Guid portalId, [FromRoute] Guid contextId) + { + try + { + var portalContextualAppKeys = await Mediator.Send(new GetContextualAndGlobalAppKeysByPortalAndContextQuery(portalId, contextId)); + + return Ok(portalContextualAppKeys); + } + catch (NotFoundException ex) + { + return FusionApiError.NotFound(portalId, ex.Message); + } + catch (Exception) + { + return FusionApiError.InvalidOperation("500", "An error occurred"); + } + } + + // Apps + + [HttpGet("{portalId:guid}/apps")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + public async Task>> PortalApps([FromRoute] Guid portalId) + { + try + { + var portalAppsDto = await Mediator.Send(new GetGlobalAppsForPortalQuery(portalId)); + + return Ok(portalAppsDto.Select(portalAppDto => new ApiPortalApp(portalAppDto)).ToList()); + } + catch (NotFoundException ex) + { + return FusionApiError.NotFound(portalId, ex.Message); + } + catch (Exception) + { + return FusionApiError.InvalidOperation("500", "An error occurred"); + } } [HttpGet("{portalId:guid}/contexts/{contextId:guid}/apps")] @@ -230,15 +276,20 @@ public async Task> PortalOnboardedApp([FromR [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] public async Task>> PortalApps([FromRoute] Guid portalId, [FromRoute] Guid contextId) { - //TODO: improve error handling - var portalAppsDto = await Mediator.Send(new GetPortalAppsWithContextAndGlobalAppsByContextIdQuery(portalId, contextId)); + try + { + var portalAppsDto = await Mediator.Send(new GetContextualAndGlobalAppsByPortalAndContextQuery(portalId, contextId)); - if (portalAppsDto == null) + return Ok(portalAppsDto.Select(portalAppDto => new ApiPortalApp(portalAppDto)).ToList()); + } + catch (NotFoundException ex) { - return FusionApiError.NotFound(portalId, "Could not find portal with id"); + return FusionApiError.NotFound(portalId, ex.Message); + } + catch (Exception) + { + return FusionApiError.InvalidOperation("500", "An error occurred"); } - - return Ok(portalAppsDto.Select(x => new ApiPortalApp(x)).ToList()); } [HttpPost("{portalId:guid}/apps")] @@ -272,7 +323,7 @@ public async Task> AddPortalApp([FromRoute] Guid portalId, [F return Ok(); } - [HttpPost("{portalId:guid}/contexts/{contextId}/apps")] + [HttpPost("{portalId:guid}/contexts/{contextId:guid}/apps")] [Authorize(Policy = Policies.ProjectPortal.Admin)] [Consumes(MediaTypeNames.Application.Json)] [Produces(MediaTypeNames.Application.Json)] @@ -297,11 +348,11 @@ public async Task> AddPortalApp([FromRoute] Guid portalId, Gu } catch (InvalidActionException ex) { - return FusionApiError.ResourceExists(request.AppKey, ex.Message, ex); + return FusionApiError.ResourceExists(request.AppKey, ex.Message, ex); } catch (Exception) { - return FusionApiError.InvalidOperation("500", "An error occurred while adding portal app"); + return FusionApiError.InvalidOperation("500", "An error occurred while adding portal app"); } return Ok(); @@ -359,7 +410,7 @@ public async Task RemovePortalApp([FromRoute] Guid portalId, Guid return Ok(); } - //ContextTypes + // ContextTypes [HttpPost("{portalId:guid}/context-type")] [Authorize(Policy = Policies.ProjectPortal.Admin)] [Consumes(MediaTypeNames.Application.Json)] @@ -394,7 +445,7 @@ public async Task> AddContextType([FromRoute] Guid portalId, return Ok(); } - + [HttpDelete("{portalId:guid}/context-type/{contextType}")] [Authorize(Policy = Policies.ProjectPortal.Admin)] [ProducesResponseType(StatusCodes.Status200OK)] diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/DiModules/ApplicationIntegrationsModule.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/DiModules/ApplicationIntegrationsModule.cs deleted file mode 100644 index 6029d4537..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/DiModules/ApplicationIntegrationsModule.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps; -using Equinor.ProjectExecutionPortal.FusionPortalApi.Client; - -namespace Equinor.ProjectExecutionPortal.WebApi.DiModules; - -public static class ApplicationIntegrationsModule -{ - public static void AddApplicationIntegrationsModule(this IServiceCollection services) - { - services.AddScoped(); - services.AddScoped(); - } -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/DiModules/ApplicationModule.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/DiModules/ApplicationModule.cs index 0e947637c..5eaa4cb07 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/DiModules/ApplicationModule.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/DiModules/ApplicationModule.cs @@ -4,7 +4,6 @@ using Equinor.ProjectExecutionPortal.Domain.Common.Events.Common; using Equinor.ProjectExecutionPortal.Domain.Common.Time; using Equinor.ProjectExecutionPortal.Domain.Interfaces; -using Equinor.ProjectExecutionPortal.FusionPortalApi; using Equinor.ProjectExecutionPortal.Infrastructure; using Equinor.ProjectExecutionPortal.WebApi.AssetProxy; using Equinor.ProjectExecutionPortal.WebApi.Authentication; @@ -28,7 +27,6 @@ public static void AddApplicationModules(this IServiceCollection services, IConf services.Configure(configuration.GetSection("CacheOptions")); services.Configure(configuration.GetSection("Authenticator")); - services.Configure(configuration.GetSection("FusionPortalApi")); services.Configure(configuration.GetSection("AssetProxy")); services.AddAuthorization(options => diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/DiModules/ApplicationServicesModule.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/DiModules/ApplicationServicesModule.cs index 69e38e934..b8af2ac9f 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/DiModules/ApplicationServicesModule.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/DiModules/ApplicationServicesModule.cs @@ -1,6 +1,7 @@ using Equinor.ProjectExecutionPortal.Application.Services.AppService; using Equinor.ProjectExecutionPortal.Application.Services.ContextService; using Equinor.ProjectExecutionPortal.Application.Services.ContextTypeService; +using Equinor.ProjectExecutionPortal.Application.Services.FusionAppsService; using Equinor.ProjectExecutionPortal.Application.Services.PortalService; namespace Equinor.ProjectExecutionPortal.WebApi.DiModules; @@ -10,6 +11,7 @@ public static class ApplicationServicesModule public static void AddApplicationServicesModules(this IServiceCollection services) { services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Equinor.ProjectExecutionPortal.WebApi.csproj b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Equinor.ProjectExecutionPortal.WebApi.csproj index 683e24ac9..dc3f16543 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Equinor.ProjectExecutionPortal.WebApi.csproj +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Equinor.ProjectExecutionPortal.WebApi.csproj @@ -11,7 +11,8 @@ - + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -22,7 +23,6 @@ - diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Program.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Program.cs index 039318c34..c5a516570 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Program.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Program.cs @@ -4,6 +4,7 @@ using Equinor.ProjectExecutionPortal.WebApi.Middleware; using FluentValidation.AspNetCore; using Fusion.Integration; +using Fusion.Integration.Apps.Configuration; using Fusion.Integration.Http; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; @@ -53,6 +54,7 @@ var environment = builder.Configuration.GetValue("Fusion:Environment" ?? "ci"); f.UseServiceInformation("Fusion.Project.Portal", environment); f.UseDefaultEndpointResolver(environment); + f.AddAppsClient(); f.UseDefaultTokenProvider(opts => { opts.ClientId = builder.Configuration.GetValue("AzureAd:ClientId"); @@ -128,7 +130,6 @@ builder.Services.AddApplicationModules(builder.Configuration); builder.Services.AddApplicationServicesModules(); -builder.Services.AddApplicationIntegrationsModule(); builder.Services.AddCacheModules(); var app = builder.Build(); diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/ContextType/ApiContextType.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/ContextType/ApiContextType.cs index fe0b5b74c..4a39ab1ca 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/ContextType/ApiContextType.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/ContextType/ApiContextType.cs @@ -4,7 +4,8 @@ namespace Equinor.ProjectExecutionPortal.WebApi.ViewModels.ContextType { public class ApiContextType { - public ApiContextType() { } + public ApiContextType() + { } public ApiContextType(ContextTypeDto contextTypeDto) { @@ -12,7 +13,5 @@ public ApiContextType(ContextTypeDto contextTypeDto) } public string Type { get; set; } - - } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/FusionApp/ApiFusionApp.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/FusionApp/ApiFusionApp.cs new file mode 100644 index 000000000..0309e5a5d --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/FusionApp/ApiFusionApp.cs @@ -0,0 +1,31 @@ +using Fusion.Integration.Apps.Abstractions.Models; + +namespace Equinor.ProjectExecutionPortal.WebApi.ViewModels.FusionApp; + +public class ApiFusionApp +{ + public ApiFusionApp() + { } + + public ApiFusionApp(App fusionApp) + { + AppKey = fusionApp.AppKey; + DisplayName = fusionApp.DisplayName; + Description = fusionApp.Description; + Type = fusionApp.Type; + IsPinned = fusionApp.IsPinned; + TemplateSource = fusionApp.TemplateSource; + Category = fusionApp.Category != null ? new ApiFusionAppCategory(fusionApp.Category) : null; + Build = fusionApp.Build != null ? new ApiFusionAppVersion(fusionApp.Build) : null; + } + + public string AppKey { get; set; } + public string DisplayName { get; set; } + public string? Description { get; set; } + public string? Type { get; set; } + public string? Version { get; set; } + public bool? IsPinned { get; set; } + public string? TemplateSource { get; set; } + public ApiFusionAppCategory? Category { get; set; } + public ApiFusionAppVersion? Build { get; set; } +} diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/FusionApp/ApiFusionAppCategory.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/FusionApp/ApiFusionAppCategory.cs new file mode 100644 index 000000000..251444522 --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/FusionApp/ApiFusionAppCategory.cs @@ -0,0 +1,27 @@ +using Fusion.Integration.Apps.Abstractions.Models; + +namespace Equinor.ProjectExecutionPortal.WebApi.ViewModels.FusionApp +{ + public class ApiFusionAppCategory + { + public ApiFusionAppCategory() + { } + + public ApiFusionAppCategory(AppCategory fusionAppCategory) + { + Id = fusionAppCategory.Id; + Name = fusionAppCategory.Name; + DisplayName = fusionAppCategory.DisplayName; + Color = fusionAppCategory.Color; + DefaultIcon = fusionAppCategory.DefaultIcon; + SortOrder = fusionAppCategory.SortOrder; + } + + public Guid Id { get; set; } + public string Name { get; set; } + public string DisplayName { get; set; } + public string Color { get; set; } + public string DefaultIcon { get; set; } + public short SortOrder { get; set; } + } +} diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/FusionApp/ApiFusionAppVersion.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/FusionApp/ApiFusionAppVersion.cs new file mode 100644 index 000000000..3ab3837cc --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/FusionApp/ApiFusionAppVersion.cs @@ -0,0 +1,27 @@ +using Fusion.Integration.Apps.Abstractions.Models; + +namespace Equinor.ProjectExecutionPortal.WebApi.ViewModels.FusionApp +{ + public class ApiFusionAppVersion + { + public ApiFusionAppVersion() + { } + + public ApiFusionAppVersion(AppVersion fusionAppVersion) + { + Version = fusionAppVersion.Version; + EntryPoint = fusionAppVersion.EntryPoint; + Tags = fusionAppVersion.Tags; + Tag = fusionAppVersion.Tag; + AssetPath = fusionAppVersion.AssetPath; + ConfigUrl = fusionAppVersion.ConfigUrl; + } + + public string Version { get; set; } + public string EntryPoint { get; set; } + public List? Tags { get; set; } + public string? Tag { get; set; } + public string? AssetPath { get; set; } + public string? ConfigUrl { get; set; } + } +} diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiFusionPortalAppInformation.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiFusionPortalAppInformation.cs deleted file mode 100644 index c1a2a6433..000000000 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiFusionPortalAppInformation.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models; - -namespace Equinor.ProjectExecutionPortal.WebApi.ViewModels.OnboardedApp; - -public class ApiFusionPortalAppInformation -{ - public ApiFusionPortalAppInformation() - { } - - public ApiFusionPortalAppInformation(FusionPortalAppInformation fusionAppInformation) - { - Key = fusionAppInformation.Key; - Name = fusionAppInformation.Name; - Version = fusionAppInformation.Version; - ShortName = fusionAppInformation.ShortName; - Description = fusionAppInformation.Description; - PublishedDate = fusionAppInformation.PublishedDate; - Tags = fusionAppInformation.Tags; - Hide = fusionAppInformation.Hide; - Order = fusionAppInformation.Order; - Type = fusionAppInformation.Type; - AccentColor = fusionAppInformation.AccentColor; - Icon = fusionAppInformation.Icon; - CategoryId = fusionAppInformation.CategoryId; - Category = fusionAppInformation.Category = fusionAppInformation.Category; - } - - public string Key { get; set; } = null!; - public string Name { get; set; } = null!; - public string? Version { get; set; } - public string? ShortName { get; set; } - public string? Description { get; set; } - public string? PublishedDate { get; set; } - public string[] Tags { get; set; } = null!; - public bool? Hide { get; set; } - public int Order { get; set; } - public string? Type { get; set; } - public string? AccentColor { get; set; } - public string? Icon { get; set; } - public Guid? CategoryId { get; set; } - public FusionPortalAppInformationCategory? Category { get; set; } - public Guid[] Owners { get; set; } - public FusionPortalAppInformationAdmin[] Admins { get; set; } - public FusionPortalHealthCheck[] HealthChecks { get; set; } - public FusionPortalRole[] RequiredRoles { get; set; } -} diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiOnboardedApp.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiOnboardedApp.cs index 0f0216beb..f26e0cba7 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiOnboardedApp.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiOnboardedApp.cs @@ -1,5 +1,6 @@ using Equinor.ProjectExecutionPortal.Application.Queries.OnboardedApps; using Equinor.ProjectExecutionPortal.WebApi.ViewModels.ContextType; +using Equinor.ProjectExecutionPortal.WebApi.ViewModels.FusionApp; namespace Equinor.ProjectExecutionPortal.WebApi.ViewModels.OnboardedApp { @@ -12,19 +13,36 @@ public ApiOnboardedApp(OnboardedAppDto onboardedAppDto) { Id = onboardedAppDto.Id; AppKey = onboardedAppDto.AppKey; - Name = onboardedAppDto.AppInformation?.Name; + Name = onboardedAppDto.AppInformation?.DisplayName; Description = onboardedAppDto.AppInformation?.Description; Contexts = onboardedAppDto.ContextTypes.Select(x => new ApiContextType(x)).ToList(); ContextTypes = onboardedAppDto.ContextTypes.Select(x => x.ContextTypeKey).ToList(); - AppInformation = onboardedAppDto.AppInformation != null ? new ApiFusionPortalAppInformation(onboardedAppDto.AppInformation) : null; } public Guid Id { get; set; } - public string AppKey { get; set; } = null!; + public string AppKey { get; set; } public string? Name { get; set; } public string? Description { get; set; } - public IList Contexts { get; set; } - public IList ContextTypes { get; set; } - public ApiFusionPortalAppInformation? AppInformation { get; set; } + public IList Contexts { get; set; } = new List(); + public IList ContextTypes { get; set; } = new List(); + } + + public class ApiOnboardedAppExpanded : ApiOnboardedApp + { + public ApiOnboardedAppExpanded() + { } + + public ApiOnboardedAppExpanded(OnboardedAppDto onboardedAppDto) + { + Id = onboardedAppDto.Id; + AppKey = onboardedAppDto.AppKey; + Name = onboardedAppDto.AppInformation?.DisplayName; + Description = onboardedAppDto.AppInformation?.Description; + Contexts = onboardedAppDto.ContextTypes.Select(x => new ApiContextType(x)).ToList(); + ContextTypes = onboardedAppDto.ContextTypes.Select(x => x.ContextTypeKey).ToList(); + AppInformation = onboardedAppDto.AppInformation != null ? new ApiFusionApp(onboardedAppDto.AppInformation) : null; + } + + public ApiFusionApp? AppInformation { get; set; } } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/PortalApp/ApiPortalApp.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/PortalApp/ApiPortalApp.cs index 28c37a707..33fb29494 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/PortalApp/ApiPortalApp.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/PortalApp/ApiPortalApp.cs @@ -1,6 +1,6 @@ using Equinor.ProjectExecutionPortal.Application.Queries.Portals; using Equinor.ProjectExecutionPortal.WebApi.ViewModels.ContextType; -using Equinor.ProjectExecutionPortal.WebApi.ViewModels.OnboardedApp; +using Equinor.ProjectExecutionPortal.WebApi.ViewModels.FusionApp; namespace Equinor.ProjectExecutionPortal.WebApi.ViewModels.PortalApp { @@ -14,11 +14,11 @@ public ApiPortalApp(PortalAppDto portalAppDto) { Key = portalAppDto.OnboardedApp.AppKey; ContextTypes = portalAppDto.OnboardedApp.ContextTypes.Select(x => new ApiContextType(x)).ToList(); - AppManifest = portalAppDto.OnboardedApp.AppInformation != null ? new ApiFusionPortalAppInformation(portalAppDto.OnboardedApp.AppInformation) : null; + AppManifest = portalAppDto.OnboardedApp.AppInformation != null ? new ApiFusionApp(portalAppDto.OnboardedApp.AppInformation) : null; } public string Key { get; set; } public IList ContextTypes { get; set; } - public ApiFusionPortalAppInformation? AppManifest { get; set; } + public ApiFusionApp? AppManifest { get; set; } } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/PortalApp/ApiPortalOnboardedApp.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/PortalApp/ApiPortalOnboardedApp.cs index ce444baa9..16abccf8a 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/PortalApp/ApiPortalOnboardedApp.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/PortalApp/ApiPortalOnboardedApp.cs @@ -1,23 +1,22 @@ -using Equinor.ProjectExecutionPortal.Application.Queries.OnboardedApps; -using Equinor.ProjectExecutionPortal.Application.Queries.Portals; -using Equinor.ProjectExecutionPortal.WebApi.ViewModels.OnboardedApp; -using ApiContextType = Equinor.ProjectExecutionPortal.WebApi.ViewModels.ContextType.ApiContextType; +using Equinor.ProjectExecutionPortal.Application.Queries.Portals; +using Equinor.ProjectExecutionPortal.WebApi.ViewModels.FusionApp; namespace Equinor.ProjectExecutionPortal.WebApi.ViewModels.PortalApp { public class ApiPortalOnboardedApp { - public ApiPortalOnboardedApp() { } + public ApiPortalOnboardedApp() + { } public ApiPortalOnboardedApp(PortalOnboardedAppDto portalOnboardedAppDto) { Key = portalOnboardedAppDto.OnboardedApp.AppKey; ContextTypes = portalOnboardedAppDto.OnboardedApp.ContextTypes.Select(x => x.ContextTypeKey).ToList(); - AppManifest = portalOnboardedAppDto.OnboardedApp.AppInformation != null ? new ApiFusionPortalAppInformation(portalOnboardedAppDto.OnboardedApp.AppInformation) : null; ContextIds = portalOnboardedAppDto.ContextIds; IsActive = portalOnboardedAppDto.IsActive; IsGlobal = portalOnboardedAppDto.IsGlobal; IsContextual = portalOnboardedAppDto.IsContextual; + AppManifest = portalOnboardedAppDto.OnboardedApp.AppInformation != null ? new ApiFusionApp(portalOnboardedAppDto.OnboardedApp.AppInformation) : null; } public string Key { get; set; } @@ -26,6 +25,6 @@ public ApiPortalOnboardedApp(PortalOnboardedAppDto portalOnboardedAppDto) public bool IsActive { get; set; } public bool IsGlobal { get; set; } public bool IsContextual { get; set; } - public ApiFusionPortalAppInformation? AppManifest { get; set; } + public ApiFusionApp? AppManifest { get; set; } } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/appsettings.json b/backend/src/Equinor.ProjectExecutionPortal.WebApi/appsettings.json index 38610c46a..5d946601e 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/appsettings.json +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/appsettings.json @@ -16,11 +16,6 @@ "ClientId": "guid", // AppReg key for Swagger Client for this app "Scope": "access_as_user" }, - "FusionPortalApi": { - "BaseAddress": "", - "Scope": "", - "ApiVersion": "v1.0" - }, "Fusion": { "Environment": "ci" }, diff --git a/backend/src/Equinor.ProjectExecutionPortal.sln b/backend/src/Equinor.ProjectExecutionPortal.sln index cd405fdd1..b3c135dd6 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.sln +++ b/backend/src/Equinor.ProjectExecutionPortal.sln @@ -1,6 +1,5 @@  Microsoft Visual Studio Solution File, Format Version 12.00 - # Visual Studio Version 17 VisualStudioVersion = 17.3.32825.248 MinimumVisualStudioVersion = 10.0.40219.1 @@ -27,8 +26,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{1E2C7897 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Equinor.ProjectExecutionPortal.Tests.WebApi", "tests\Equinor.ProjectExecutionPortal.Tests.WebApi\Equinor.ProjectExecutionPortal.Tests.WebApi.csproj", "{9147F23E-3BA7-4978-A8BC-658F17FC3428}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Equinor.ProjectExecutionPortal.FusionPortalApi", "Equinor.ProjectExecutionPortal.FusionPortalApi\Equinor.ProjectExecutionPortal.FusionPortalApi.csproj", "{70EE80AF-7EF4-484D-9220-B006217D0773}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -55,10 +52,6 @@ Global {9147F23E-3BA7-4978-A8BC-658F17FC3428}.Debug|Any CPU.Build.0 = Debug|Any CPU {9147F23E-3BA7-4978-A8BC-658F17FC3428}.Release|Any CPU.ActiveCfg = Release|Any CPU {9147F23E-3BA7-4978-A8BC-658F17FC3428}.Release|Any CPU.Build.0 = Release|Any CPU - {70EE80AF-7EF4-484D-9220-B006217D0773}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {70EE80AF-7EF4-484D-9220-B006217D0773}.Debug|Any CPU.Build.0 = Debug|Any CPU - {70EE80AF-7EF4-484D-9220-B006217D0773}.Release|Any CPU.ActiveCfg = Release|Any CPU - {70EE80AF-7EF4-484D-9220-B006217D0773}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/ContextTypeData.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/ContextTypeData.cs index 59c54fb93..030a676af 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/ContextTypeData.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/ContextTypeData.cs @@ -1,24 +1,23 @@ using Equinor.ProjectExecutionPortal.Domain.Entities; -using Fusion.Integration; namespace Equinor.ProjectExecutionPortal.Tests.WebApi.Data { internal class ContextTypeData { - public class InitialSeedData + public class InitialDbSeedData { - public static ContextType ContextType1 = new(ValidData.ProjectMasterContextTypeKey); - public static ContextType ContextType2 = new(ValidData.FacilityContextTypeKey); + public static ContextType ContextType1 = new(ValidContextTypes.ProjectMasterContextTypeKey); + public static ContextType ContextType2 = new(ValidContextTypes.FacilityContextTypeKey); } - public class ValidData + public class ValidContextTypes { public static string ProjectMasterContextTypeKey = "ProjectMaster"; public static string FacilityContextTypeKey = "Facility"; public static string ContractContextTypeKey = "Contract"; } - public class InvalidData + public class InvalidContextTypes { public static string InvalidContextTypeKey = "SuperContext"; } diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/FusionAppApiData.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/FusionAppApiData.cs new file mode 100644 index 000000000..bd5cf6f9e --- /dev/null +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/FusionAppApiData.cs @@ -0,0 +1,73 @@ +using Fusion.Integration.Apps.Abstractions.Models; + +namespace Equinor.ProjectExecutionPortal.Tests.WebApi.Data +{ + internal class FusionAppApiData + { + public static App MeetingsFusion => new() + { + AppKey = "meetings", + DisplayName = "Meetings", + Description = "Some description" + }; + + public static App ReviewsFusion => new() + { + AppKey = "reviews", + DisplayName = "Reviews", + Description = "Some description" + }; + + public static App TasksFusion => new() + { + AppKey = "tasks", + DisplayName = "Tasks", + Description = "Some description" + }; + + public static App OneEquinorFusion => new() + { + AppKey = "one-equinor", + DisplayName = "One Equinor", + Description = "Some description" + }; + + public static App HandoverGardenFusion => new() + { + AppKey = "handover-garden", + DisplayName = "Handover Garden", + Description = "Some description" + }; + + public static App WorkOrderGardenFusion => new() + { + AppKey = "workorder-garden", + DisplayName = "Workorder Garden", + Description = "Some description" + }; + + public static App TestFusion => new() + { + AppKey = "test-app", + DisplayName = "A test app", + Description = "Some description" + }; + + public static App TestToBeOffboardedFusion => new() + { + AppKey = "app-to-be-offboarded", + DisplayName = "An app to be offboarded by onboarded app tests", + Description = "Some description" + }; + + public static App NonExistentApp => new() + { + AppKey = "i-do-not-exist-in-fusion", + DisplayName = "i-do-not-exist-in-fusion", + Description = "i-do-not-exist-in-fusion" + }; + + public static List ValidFusionApps => + [MeetingsFusion, ReviewsFusion, TasksFusion, OneEquinorFusion, HandoverGardenFusion, WorkOrderGardenFusion, TestFusion, TestToBeOffboardedFusion]; + } +} diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/FusionContextApiData.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/FusionContextApiData.cs new file mode 100644 index 000000000..4e37daea6 --- /dev/null +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/FusionContextApiData.cs @@ -0,0 +1,51 @@ +using Fusion.Integration; + +namespace Equinor.ProjectExecutionPortal.Tests.WebApi.Data +{ + internal class FusionContextApiData + { + public static string JcaContextExternalId = "fc5ffcbc-392f-4d7e-bb14-79a006579337"; + public static Guid JcaContextId = new("94dd5f4d-17f1-4312-bf75-ad75f4d9572c"); + public static string OgpContextExternalId = "91dd6653-a364-40c7-af26-7af516d66c42"; + public static Guid OgpContextId = new("ce31b83a-b6cd-4267-89f3-db308edf721e"); + public static string MongstadContextExternalId = "09206ca3-02ac-4c65-adbf-caa7b66364ea"; + public static Guid MongstadContextId = new("4CB78175-46CF-41A3-58DB-08DC74C80D40"); + public static string InvalidContextExternalId = "11111111-1111-1111-1111-111111111111"; + public static Guid InvalidContextId = new("11111111-1111-1111-1111-111111111111"); + + public static FusionContext JcaFusionContext => new() + { + Id = JcaContextId, + IsActive = true, + ExternalId = JcaContextExternalId, + Title = "Johan Castberg", + Type = FusionContextType.ProjectMaster, + Value = null!, + Source = null + }; + + public static FusionContext OgpFusionContext => new() + { + Id = OgpContextId, + IsActive = true, + ExternalId = OgpContextExternalId, + Title = "Oseberg", + Type = FusionContextType.ProjectMaster, + Value = null!, + Source = null + }; + + public static FusionContext MongstadFusionContext => new() + { + Id = MongstadContextId, + IsActive = true, + ExternalId = MongstadContextExternalId, + Title = "Mongstad WWTP", + Type = FusionContextType.ProjectMaster, + Value = null!, + Source = null + }; + + public static List ValidFusionContexts => [JcaFusionContext, OgpFusionContext, MongstadFusionContext]; + } +} diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/FusionContextData.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/FusionContextData.cs deleted file mode 100644 index 5efe93381..000000000 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/FusionContextData.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Fusion.Integration; - -namespace Equinor.ProjectExecutionPortal.Tests.WebApi.Data -{ - internal class FusionContextData - { - public class InitialSeedData - { - public static string JcaContextExternalId = "fc5ffcbc-392f-4d7e-bb14-79a006579337"; - public static Guid JcaContextId = new Guid("94dd5f4d-17f1-4312-bf75-ad75f4d9572c"); - public static string OgpContextExternalId = "91dd6653-a364-40c7-af26-7af516d66c42"; - public static Guid OgpContextId = new Guid("ce31b83a-b6cd-4267-89f3-db308edf721e"); - public static string InvalidContextExternalId = "11111111-1111-1111-1111-111111111111"; - public static Guid InvalidContextId = new Guid("11111111-1111-1111-1111-111111111111"); - public static string ContextType = "ProjectMaster"; - } - - public static FusionContext JcaFusionContext => new() - { - Id = new Guid("94dd5f4d-17f1-4312-bf75-ad75f4d9572c"), - IsActive = true, - ExternalId = InitialSeedData.JcaContextExternalId, - Title = "Johan Castberg", - Type = FusionContextType.ProjectMaster, - Value = null!, - Source = null - }; - - public static FusionContext OgpFusionContext => new() - { - Id = new Guid("11115f4d-17f1-4312-bf75-ad75f4d9572c"), - IsActive = true, - ExternalId = InitialSeedData.OgpContextExternalId, - Title = "Oseberg", - Type = FusionContextType.ProjectMaster, - Value = null!, - Source = null - }; - - public static List ValidFusionContexts => new() - { - JcaFusionContext, OgpFusionContext - }; - } -} diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/FusionPortalAppData.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/FusionPortalAppData.cs deleted file mode 100644 index c930e1a9d..000000000 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/FusionPortalAppData.cs +++ /dev/null @@ -1,108 +0,0 @@ -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models; - -namespace Equinor.ProjectExecutionPortal.Tests.WebApi.Data -{ - internal class FusionPortalAppData - { - public static List ValidFusionApps => new() - { - new FusionPortalAppInformation - { - Key = "meetings", - Name = "Meetings", - Version = null, - ShortName = "Meetings", - Description = "Some description", - PublishedDate = null, - Type = null, - AccentColor = null, - Icon = null - }, - new FusionPortalAppInformation - { - Key = "reviews", - Name = "Reviews", - Version = null, - ShortName = "Reviews", - Description = "Some description", - PublishedDate = null, - Type = null, - AccentColor = null, - Icon = null - }, - new FusionPortalAppInformation - { - Key = "tasks", - Name = "Tasks", - Version = null, - ShortName = "Tasks", - Description = "Some description", - PublishedDate = null, - Type = null, - AccentColor = null, - Icon = null - }, - new FusionPortalAppInformation - { - Key = "one-equinor", - Name = "One Equinor", - Version = null, - ShortName = "One Equinor", - Description = "Some description", - PublishedDate = null, - Type = null, - AccentColor = null, - Icon = null - }, - new FusionPortalAppInformation - { - Key = "handover-garden", - Name = "Handover Garden", - Version = null, - ShortName = "Handover", - Description = "Some description", - PublishedDate = null, - Type = null, - AccentColor = null, - Icon = null - }, - new FusionPortalAppInformation - { - Key = "workorder-garden", - Name = "Workorder Garden", - Version = null, - ShortName = "Workorder", - Description = "Some description", - PublishedDate = null, - Type = null, - AccentColor = null, - Icon = null - }, - new FusionPortalAppInformation - { - Key = "test-app", - Name = "A test app", - Version = null, - ShortName = "TestApp", - Description = "Some description", - PublishedDate = null, - Type = null, - AccentColor = null, - Icon = null - }, - new FusionPortalAppInformation - { - Key = "app-to-be-removed", - Name = "An app to be deleted by tests", - Version = null, - ShortName = "DeleteApp", - Description = "Some description", - PublishedDate = null, - Type = null, - AccentColor = null, - Icon = null - } - }; - } - -} diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/OnboardedAppData.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/OnboardedAppData.cs index 94a754b47..2857f4a84 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/OnboardedAppData.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/OnboardedAppData.cs @@ -4,7 +4,7 @@ namespace Equinor.ProjectExecutionPortal.Tests.WebApi.Data { internal class OnboardedAppData { - public class InitialSeedData + public class InitialDbSeedData { public static OnboardedApp MeetingsApp = new("meetings"); public static OnboardedApp ReviewsApp = new("reviews"); diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/OnboardedContextData.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/OnboardedContextData.cs index 3adf43798..46b98f6c4 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/OnboardedContextData.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/OnboardedContextData.cs @@ -4,10 +4,10 @@ namespace Equinor.ProjectExecutionPortal.Tests.WebApi.Data { internal class OnboardedContextData { - public class InitialSeedData + public class InitialDbSeedData { - public static OnboardedContext JcaContext = new(FusionContextData.InitialSeedData.JcaContextExternalId, FusionContextData.InitialSeedData.ContextType, "desc"); - public static OnboardedContext OgpContext = new(FusionContextData.InitialSeedData.OgpContextExternalId, FusionContextData.InitialSeedData.ContextType, "desc"); + public static OnboardedContext JcaContext = new(FusionContextApiData.JcaContextExternalId, ContextTypeData.ValidContextTypes.ProjectMasterContextTypeKey, "desc"); + public static OnboardedContext OgpContext = new(FusionContextApiData.OgpContextExternalId, ContextTypeData.ValidContextTypes.ProjectMasterContextTypeKey, "desc"); } } } diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/PortalConfigurationData.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/PortalConfigurationData.cs new file mode 100644 index 000000000..6cc985782 --- /dev/null +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/PortalConfigurationData.cs @@ -0,0 +1,16 @@ +using Equinor.ProjectExecutionPortal.Domain.Entities; + +namespace Equinor.ProjectExecutionPortal.Tests.WebApi.Data +{ + internal class PortalConfigurationData + { + public class InitialDbSeedData + { + public static PortalConfiguration GenericPortalConfiguration = new( + "routerConfig", + "extensionConfig", + "environmentConfig" + ); + } + } +} diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/PortalData.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/PortalData.cs index 3c2f78c0d..1bcf82902 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/PortalData.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/PortalData.cs @@ -4,11 +4,24 @@ namespace Equinor.ProjectExecutionPortal.Tests.WebApi.Data { internal class PortalData { - public class InitialSeedData + public class InitialDbSeedData { - public static Portal Portal1 = new("portfolio-management", "Portfolio Management", "< DG 3", "Here you can find all the tools that you need", "A description",""); - public static Portal Portal2 = new("project-execution", "Project Execution", "DG 3 - DG 4", "Go to this phase to work with projects that are beyond DG3", "A description", ""); - public static Portal Portal3 = new("another-phase", "Another phase", "DG X", "Some other sub text", "A description", ""); + public static Portal PortfolioManagement = new( + "portfolio-management", + "Portfolio Management", + "< DG 3", + "Here you can find all the tools that you need", + "A description", + "" + ); + + public static Portal ProjectExecution = new("project-execution", + "Project Execution", + "DG 3 - DG 4", + "Go to this phase to work with projects that are beyond DG3", + "A description", + "" + ); } } } diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/AssertHelpers.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/AssertHelpers.cs index 4dc3db614..683e78430 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/AssertHelpers.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/AssertHelpers.cs @@ -35,6 +35,8 @@ public static void AssertPortalConfigurationValues(ApiPortalConfiguration? porta if (!acceptNullValues) { Assert.IsNotNull(portalConfiguration.Router); + Assert.IsNotNull(portalConfiguration.Extension); + Assert.IsNotNull(portalConfiguration.Environment); } } diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/ContextTypeControllerTests.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/ContextTypeControllerTests.cs index 023de8ea6..6da4d6564 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/ContextTypeControllerTests.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/ContextTypeControllerTests.cs @@ -61,7 +61,7 @@ public async Task Add_Valid_ContextType_AsAdministratorUser_ShouldReturnCreated( var payload = new ApiAddContextTypeRequest { - Type = ContextTypeData.ValidData.ContractContextTypeKey + Type = ContextTypeData.ValidContextTypes.ContractContextTypeKey }; // Act @@ -83,7 +83,7 @@ public async Task Add_Valid_ContextType_AsAuthenticatedUser_ShouldReturnForbidde // Arrange var payload = new ApiAddContextTypeRequest { - Type = ContextTypeData.ValidData.ContractContextTypeKey + Type = ContextTypeData.ValidContextTypes.ContractContextTypeKey }; // Act @@ -99,7 +99,7 @@ public async Task Add_Valid_ContextType_AsAnonymousUser_ShouldReturnUnauthorized // Arrange var payload = new ApiAddContextTypeRequest { - Type = ContextTypeData.ValidData.ContractContextTypeKey + Type = ContextTypeData.ValidContextTypes.ContractContextTypeKey }; // Act @@ -115,7 +115,7 @@ public async Task Add_NonExistent_ContextType_AsAdministratorUser_ShouldReturnNo // Arrange var payload = new ApiAddContextTypeRequest { - Type = ContextTypeData.InvalidData.InvalidContextTypeKey + Type = ContextTypeData.InvalidContextTypes.InvalidContextTypeKey }; // Act @@ -131,7 +131,7 @@ public async Task Add_Duplicate_ContextType_AsAdministratorUser_ShouldReturnConf // Arrange var payload = new ApiAddContextTypeRequest { - Type = ContextTypeData.InitialSeedData.ContextType1.ContextTypeKey + Type = ContextTypeData.InitialDbSeedData.ContextType1.ContextTypeKey }; // Act @@ -145,7 +145,7 @@ public async Task Add_Duplicate_ContextType_AsAdministratorUser_ShouldReturnConf public async Task Remove_ContextType_WithoutPortals_AsAdministratorUser_ShouldReturnOk() { // Arrange - var payload = ContextTypeData.InitialSeedData.ContextType2.ContextTypeKey; + var payload = ContextTypeData.InitialDbSeedData.ContextType2.ContextTypeKey; // Act var getAllBefore = await AssertGetAllContextTypes(UserType.Administrator, HttpStatusCode.OK); @@ -166,7 +166,7 @@ public async Task Remove_ContextType_WithoutPortals_AsAdministratorUser_ShouldRe public async Task Remove_ContextType_WithPortals_AsAdministratorUser_ShouldReturnBadRequest() { // Arrange - var payload = ContextTypeData.InitialSeedData.ContextType1.ContextTypeKey; + var payload = ContextTypeData.InitialDbSeedData.ContextType1.ContextTypeKey; // Act var getAllBefore = await AssertGetAllContextTypes(UserType.Administrator, HttpStatusCode.OK); @@ -184,7 +184,7 @@ public async Task Remove_ContextType_WithPortals_AsAdministratorUser_ShouldRetur public async Task Remove_ContextType_AsAuthenticatedUser_ShouldReturnForbidden() { // Arrange - var existingContextTypeKey = ContextTypeData.InitialSeedData.ContextType1.ContextTypeKey; + var existingContextTypeKey = ContextTypeData.InitialDbSeedData.ContextType1.ContextTypeKey; // Act var getAllBefore = await AssertGetAllContextTypes(UserType.Administrator, HttpStatusCode.OK); @@ -202,7 +202,7 @@ public async Task Remove_ContextType_AsAuthenticatedUser_ShouldReturnForbidden() public async Task Remove_ContextType_AsAnonymousUser_ShouldReturnUnauthorized() { // Arrange - var existingContextTypeKey = ContextTypeData.InitialSeedData.ContextType1.ContextTypeKey; + var existingContextTypeKey = ContextTypeData.InitialDbSeedData.ContextType1.ContextTypeKey; // Act var getAllBefore = await AssertGetAllContextTypes(UserType.Administrator, HttpStatusCode.OK); diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/OnboardedAppControllerTests.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/OnboardedAppControllerTests.cs index 4d259b51d..c88e3f19a 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/OnboardedAppControllerTests.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/OnboardedAppControllerTests.cs @@ -52,7 +52,7 @@ public async Task Get_OnboardedApps_AsAnonymous_ShouldReturnUnauthorized() public async Task Get_OnboardedApp_AsAuthenticatedUser_ShouldReturnOk() { // Act - var onboardedApp = await AssertGetOnboardedApp(OnboardedAppData.InitialSeedData.MeetingsApp.AppKey, UserType.Authenticated, HttpStatusCode.OK); + var onboardedApp = await AssertGetOnboardedApp(OnboardedAppData.InitialDbSeedData.MeetingsApp.AppKey, UserType.Authenticated, HttpStatusCode.OK); // Assert Assert.IsNotNull(onboardedApp); @@ -64,7 +64,7 @@ public async Task Get_OnboardedApp_AsAuthenticatedUser_ShouldReturnOk() public async Task Get_OnboardedApp_AsAdministratorUser_ShouldReturnOk() { // Act - var onboardedApp = await AssertGetOnboardedApp(OnboardedAppData.InitialSeedData.MeetingsApp.AppKey, UserType.Administrator, HttpStatusCode.OK); + var onboardedApp = await AssertGetOnboardedApp(OnboardedAppData.InitialDbSeedData.MeetingsApp.AppKey, UserType.Administrator, HttpStatusCode.OK); // Assert Assert.IsNotNull(onboardedApp); @@ -76,7 +76,7 @@ public async Task Get_OnboardedApp_AsAdministratorUser_ShouldReturnOk() public async Task Get_OnboardedApp_AsAnonymous_ShouldReturnUnauthorized() { // Act - var onboardedApp = await AssertGetOnboardedApp(OnboardedAppData.InitialSeedData.MeetingsApp.AppKey, UserType.Anonymous, HttpStatusCode.Unauthorized); + var onboardedApp = await AssertGetOnboardedApp(OnboardedAppData.InitialDbSeedData.MeetingsApp.AppKey, UserType.Anonymous, HttpStatusCode.Unauthorized); // Assert Assert.IsNull(onboardedApp); @@ -91,8 +91,8 @@ public async Task Add_Valid_OnboardedApp_AsAdministratorUser_ShouldReturnOk() var payload = new ApiOnboardAppRequest { - AppKey = "test-app", - ContextTypes = new List() { "ProjectMaster" } + AppKey = FusionAppApiData.TestFusion.AppKey, + ContextTypes = new List { ContextTypeData.ValidContextTypes.ProjectMasterContextTypeKey } }; // Act @@ -114,7 +114,7 @@ public async Task Add_Valid_OnboardedApp_AsAuthenticatedUser_ShouldReturnForbidd // Arrange var payload = new ApiOnboardAppRequest { - AppKey = "test-app", + AppKey = FusionAppApiData.TestFusion.AppKey }; // Act @@ -130,7 +130,7 @@ public async Task Add_Valid_OnboardedApp_AsAnonymousUser_ShouldReturnUnauthorize // Arrange var payload = new ApiOnboardAppRequest { - AppKey = "test-app", + AppKey = FusionAppApiData.TestFusion.AppKey }; // Act @@ -140,21 +140,20 @@ public async Task Add_Valid_OnboardedApp_AsAnonymousUser_ShouldReturnUnauthorize Assert.AreEqual(HttpStatusCode.Unauthorized, response.StatusCode); } - [Ignore] // TODO: Mock service must accept dynamic values [TestMethod] public async Task Add_Invalid_OnboardedApp_AsAdministratorUser_ShouldThrowExeption() { // Arrange var payload = new ApiOnboardAppRequest { - AppKey = "i-do-not-exist-in-fusion" + AppKey = FusionAppApiData.NonExistentApp.AppKey }; // Act var response = await AddOnboardedApp(UserType.Administrator, payload); // Assert - Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode); + Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode); } [TestMethod] @@ -163,7 +162,7 @@ public async Task Add_Duplicate_OnboardedApp_AsAdministratorUser_ShouldThrowExce // Arrange var payload = new ApiOnboardAppRequest { - AppKey = OnboardedAppData.InitialSeedData.OrgChartApp.AppKey + AppKey = OnboardedAppData.InitialDbSeedData.OrgChartApp.AppKey }; // Act @@ -182,7 +181,7 @@ public async Task Update_OnboardedApp_AsAdministratorUser_ShouldReturnOk() var payload = new ApiUpdateOnboardedAppRequest { - ContextTypes = new List() { } + ContextTypes = new List() }; // Act @@ -204,7 +203,7 @@ public async Task Update_OnboardedApp_AsAuthenticatedUser_ShouldReturnForbidden( var payload = new ApiUpdateOnboardedAppRequest(); // Act - var response = await UpdateOnboardedApp(UserType.Authenticated, payload, "some-app-key"); + var response = await UpdateOnboardedApp(UserType.Authenticated, payload, OnboardedAppData.InitialDbSeedData.OrgChartApp.AppKey); // Assert Assert.AreEqual(HttpStatusCode.Forbidden, response.StatusCode); @@ -217,7 +216,7 @@ public async Task Update_OnboardedApp_AsAnonymousUser_ShouldReturnUnauthorized() var payload = new ApiUpdateOnboardedAppRequest(); // Act - var response = await UpdateOnboardedApp(UserType.Anonymous, payload, "some-app-key"); + var response = await UpdateOnboardedApp(UserType.Anonymous, payload, OnboardedAppData.InitialDbSeedData.OrgChartApp.AppKey); // Assert Assert.AreEqual(HttpStatusCode.Unauthorized, response.StatusCode); @@ -230,8 +229,8 @@ public async Task Remove_OnboardedApp_AsAdministratorUser_ShouldReturnOk() var payload = new ApiOnboardAppRequest { - AppKey = "app-to-be-removed", - ContextTypes = new List() { "ProjectMaster" } + AppKey = FusionAppApiData.TestToBeOffboardedFusion.AppKey, + ContextTypes = new List() { ContextTypeData.ValidContextTypes.ProjectMasterContextTypeKey } }; // Act @@ -256,7 +255,7 @@ public async Task Remove_OnboardedApp_AsAdministratorUser_ShouldReturnOk() public async Task Remove_OnboardedApp_AsAuthenticatedUser_ShouldReturnForbidden() { // Arrange - var existingOnboardedAppKey = OnboardedAppData.InitialSeedData.OrgChartApp.AppKey; + var existingOnboardedAppKey = OnboardedAppData.InitialDbSeedData.OrgChartApp.AppKey; // Act var removeResponse = await RemoveOnboardedApp(UserType.Authenticated, existingOnboardedAppKey); @@ -269,7 +268,7 @@ public async Task Remove_OnboardedApp_AsAuthenticatedUser_ShouldReturnForbidden( public async Task Remove_OnboardedApp_AsAnonymousUser_ShouldReturnUnauthorized() { // Arrange - var existingOnboardedAppKey = OnboardedAppData.InitialSeedData.OrgChartApp.AppKey; + var existingOnboardedAppKey = OnboardedAppData.InitialDbSeedData.OrgChartApp.AppKey; // Act var removeResponse = await RemoveOnboardedApp(UserType.Anonymous, existingOnboardedAppKey); diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/OnboardedContextControllerTests.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/OnboardedContextControllerTests.cs index 898df2f73..f7b57c374 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/OnboardedContextControllerTests.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/OnboardedContextControllerTests.cs @@ -56,9 +56,9 @@ public async Task Add_Valid_OnboardedContext_AsAdministratorUser_ShouldReturnOk( var payload = new ApiOnboardContextRequest { - ExternalId = OnboardedContextData.InitialSeedData.OgpContext.ExternalId, - Type = OnboardedContextData.InitialSeedData.OgpContext.Type, - Description = "Description from test method" + ExternalId = FusionContextApiData.MongstadFusionContext.ExternalId!, + Type = FusionContextApiData.MongstadFusionContext.Type, + Description = "Some sort of very detailed description" }; // Act @@ -80,9 +80,9 @@ public async Task Add_Valid_OnboardedContext_AsAuthenticatedUser_ShouldReturnFor // Arrange var payload = new ApiOnboardContextRequest { - ExternalId = OnboardedContextData.InitialSeedData.JcaContext.ExternalId, - Type = OnboardedContextData.InitialSeedData.JcaContext.Type, - Description = "Description from test method" + ExternalId = FusionContextApiData.MongstadFusionContext.ExternalId!, + Type = FusionContextApiData.MongstadFusionContext.Type, + Description = "Some sort of very detailed description" }; // Act @@ -98,9 +98,9 @@ public async Task Add_Valid_OnboardedContext_AsAnonymousUser_ShouldReturnUnautho // Arrange var payload = new ApiOnboardContextRequest { - ExternalId = OnboardedContextData.InitialSeedData.JcaContext.ExternalId, - Type = OnboardedContextData.InitialSeedData.JcaContext.Type, - Description = "Description from test method" + ExternalId = FusionContextApiData.MongstadFusionContext.ExternalId!, + Type = FusionContextApiData.MongstadFusionContext.Type, + Description = "Some sort of very detailed description" }; // Act @@ -116,7 +116,7 @@ public async Task Add_NonExistent_OnboardedContext_AsAdministratorUser_ShouldThr // Arrange var payload = new ApiOnboardContextRequest { - ExternalId = "1337olol-392f-4d7e-bb14-79a006571337", + ExternalId = FusionContextApiData.InvalidContextExternalId, Type = "tanteSofie", Description = "A non-existent context" }; @@ -134,8 +134,8 @@ public async Task Add_Duplicate_OnboardedContext_AsAdministratorUser_ShouldThrow // Arrange var payload = new ApiOnboardContextRequest { - ExternalId = OnboardedContextData.InitialSeedData.JcaContext.ExternalId, - Type = OnboardedContextData.InitialSeedData.JcaContext.Type, + ExternalId = OnboardedContextData.InitialDbSeedData.JcaContext.ExternalId, + Type = OnboardedContextData.InitialDbSeedData.JcaContext.Type, Description = "Description from test method" }; @@ -146,34 +146,30 @@ public async Task Add_Duplicate_OnboardedContext_AsAdministratorUser_ShouldThrow Assert.AreEqual(HttpStatusCode.Conflict, addDuplicateResponse.StatusCode); } - [Ignore] //TODO: Need to resolve id to delete [TestMethod] public async Task Remove_OnboardedContext_AsAdministratorUser_ShouldReturnOk() { // Arrange - var payload = OnboardedContextData.InitialSeedData.OgpContext.Id; + var ogpExternalContextId = OnboardedContextData.InitialDbSeedData.OgpContext.ExternalId; // Act - var getAll = await AssertGetAllOnboardedContexts(UserType.Administrator, HttpStatusCode.OK); - var totalCount = getAll?.Count; + var getAllBeforeRemoval = await AssertGetAllOnboardedContexts(UserType.Administrator, HttpStatusCode.OK); + var payload = getAllBeforeRemoval!.First(x => x.ExternalId == ogpExternalContextId); - var removeResponse = await RemoveOnboardedContext(UserType.Administrator, payload); + var removeResponse = await RemoveOnboardedContext(UserType.Administrator, payload.Id); var getAllAfterRemoval = await AssertGetAllOnboardedContexts(UserType.Administrator, HttpStatusCode.OK); - var totalCountAfterRemoval = getAllAfterRemoval?.Count; // Assert - Assert.IsNotNull(totalCount); - Assert.IsNotNull(totalCountAfterRemoval); Assert.AreEqual(HttpStatusCode.OK, removeResponse.StatusCode); - Assert.AreEqual(totalCount - 1, totalCountAfterRemoval); + Assert.AreEqual(getAllBeforeRemoval?.Count - 1, getAllAfterRemoval?.Count); } [TestMethod] public async Task Remove_OnboardedContext_AsAuthenticatedUser_ShouldReturnForbidden() { // Arrange - var existingOnboardedContextExternalId = OnboardedContextData.InitialSeedData.JcaContext.Id; + var existingOnboardedContextExternalId = OnboardedContextData.InitialDbSeedData.JcaContext.Id; // Act var removeResponse = await RemoveOnboardedContext(UserType.Authenticated, existingOnboardedContextExternalId); @@ -186,7 +182,7 @@ public async Task Remove_OnboardedContext_AsAuthenticatedUser_ShouldReturnForbid public async Task Remove_OnboardedContext_AsAnonymousUser_ShouldReturnUnauthorized() { // Arrange - var existingOnboardedContextExternalId = OnboardedContextData.InitialSeedData.JcaContext.Id; + var existingOnboardedContextExternalId = OnboardedContextData.InitialDbSeedData.JcaContext.Id; // Act var removeResponse = await RemoveOnboardedContext(UserType.Anonymous, existingOnboardedContextExternalId); diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/PortalControllerTests.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/PortalControllerTests.cs index d0ce7ea80..d6d0cd0b5 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/PortalControllerTests.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/PortalControllerTests.cs @@ -77,7 +77,7 @@ public async Task Create_Portal_AsAdministratorUser_ShouldReturnOk() ShortName = "Created short name", Subtext = "Created subtext", Icon = "Created icon", - ContextTypes = new List { "ProjectMaster" } + ContextTypes = new List { ContextTypeData.ValidContextTypes.ProjectMasterContextTypeKey } }; // Act @@ -139,7 +139,7 @@ public async Task Update_Portal_AsAdministratorUser_ShouldReturnOk() ShortName = "Updated short name", Subtext = "Updated subtext", Icon = "Updated icon", - ContextTypes = new List { "ProjectMaster" } + ContextTypes = new List { ContextTypeData.ValidContextTypes.ProjectMasterContextTypeKey } }; // Act @@ -251,7 +251,6 @@ public async Task Update_PortalConfiguration_AsAdministratorUser_ShouldReturnOk( Environment = environmentData }; - // Act var response = await UpdatePortalConfiguration(UserType.Administrator, payload, portalToTest.Id); @@ -261,13 +260,12 @@ public async Task Update_PortalConfiguration_AsAdministratorUser_ShouldReturnOk( Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); Assert.AreNotEqual(payload.Router, theOneToUpdate!.Router); Assert.AreEqual(payload.Router, theOneAfterUpdate!.Router); - + Assert.AreNotEqual(payload.Extension, theOneToUpdate.Extension); Assert.AreEqual(payload.Extension, theOneAfterUpdate.Extension); Assert.AreNotEqual(payload.Environment, theOneToUpdate.Environment); Assert.AreEqual(payload.Environment, theOneAfterUpdate.Environment); - } [TestMethod] @@ -296,51 +294,92 @@ public async Task Update_PortalConfiguration_AsAnonymousUser_ShouldReturnUnautho Assert.AreEqual(HttpStatusCode.Unauthorized, response.StatusCode); } - [Ignore] // TODO: Need to perform clean up after each test + [TestMethod] + public async Task Get_OnlyGlobalAppKeysForPortal_WithoutContext_AsAuthenticatedUser_ShouldReturnOk() + { + // Arrange + var portals = await AssertGetAllPortals(UserType.Authenticated, HttpStatusCode.OK); + var portalToTest = portals?.SingleOrDefault(x => x.Key == PortalData.InitialDbSeedData.ProjectExecution.Key); + + // Act + var apps = await AssertGetAppKeysForPortal(portalToTest!.Id, null, UserType.Authenticated, HttpStatusCode.OK); + + // Assert + Assert.IsNotNull(apps); + Assert.AreEqual(4, apps.Count); + } + + [TestMethod] + public async Task Get_BothGlobalAndContextAppKeysForPortal_WithValidContext_AsAuthenticatedUser_ShouldReturnOk() + { + // Arrange + var portals = await AssertGetAllPortals(UserType.Authenticated, HttpStatusCode.OK); + var portalToTest = portals?.SingleOrDefault(x => x.Key == PortalData.InitialDbSeedData.ProjectExecution.Key); + + // Act + var apps = await AssertGetAppKeysForPortal(portalToTest!.Id, FusionContextApiData.JcaContextId, UserType.Authenticated, HttpStatusCode.OK); + + // Assert + Assert.IsNotNull(apps); + Assert.AreEqual(6, apps.Count); + } + + [TestMethod] + public async Task Get_BothGlobalAndContextAppKeysForPortal_WithInvalidContext_AsAuthenticatedUser_ShouldReturn404() + { + // Arrange + var portals = await AssertGetAllPortals(UserType.Authenticated, HttpStatusCode.OK); + var portalToTest = portals?.SingleOrDefault(x => x.Key == PortalData.InitialDbSeedData.ProjectExecution.Key); + + // Act + var response = await GetAppKeysForPortal(portalToTest!.Id, FusionContextApiData.InvalidContextId, UserType.Authenticated); + + // Assert + Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode); + } + [TestMethod] public async Task Get_OnlyGlobalAppsForPortal_WithoutContext_AsAuthenticatedUser_ShouldReturnOk() { // Arrange var portals = await AssertGetAllPortals(UserType.Authenticated, HttpStatusCode.OK); - var portalToTest = portals?.FirstOrDefault(); + var portalToTest = portals?.SingleOrDefault(x => x.Key == PortalData.InitialDbSeedData.ProjectExecution.Key); // Act var apps = await AssertGetAppsForPortal(portalToTest!.Id, null, UserType.Authenticated, HttpStatusCode.OK); // Assert Assert.IsNotNull(apps); - Assert.AreEqual(apps.Count, 2); + Assert.AreEqual(4, apps.Count); } - [Ignore]// TODO: Need to perform clean up after each test - [TestMethod] // Limitation: Invalid context not currently tested + [TestMethod] public async Task Get_BothGlobalAndContextAppsForPortal_WithValidContext_AsAuthenticatedUser_ShouldReturnOk() { // Arrange var portals = await AssertGetAllPortals(UserType.Authenticated, HttpStatusCode.OK); - var portalToTest = portals?.SingleOrDefault(x => x.Key == PortalData.InitialSeedData.Portal2.Key); + var portalToTest = portals?.SingleOrDefault(x => x.Key == PortalData.InitialDbSeedData.ProjectExecution.Key); // Act - var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextData.InitialSeedData.JcaContextId, UserType.Authenticated, HttpStatusCode.OK); + var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextApiData.JcaContextId, UserType.Authenticated, HttpStatusCode.OK); // Assert Assert.IsNotNull(apps); - Assert.AreEqual(apps.Count, 6); + Assert.AreEqual(6, apps.Count); } - [Ignore] [TestMethod] public async Task Get_BothGlobalAndContextAppsForPortal_WithInvalidContext_AsAuthenticatedUser_ShouldReturn404() { // Arrange var portals = await AssertGetAllPortals(UserType.Authenticated, HttpStatusCode.OK); - var portalToTest = portals?.FirstOrDefault(); + var portalToTest = portals?.SingleOrDefault(x => x.Key == PortalData.InitialDbSeedData.ProjectExecution.Key); // Act - var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextData.InitialSeedData.InvalidContextId, UserType.Authenticated, HttpStatusCode.OK); + var response = await GetAppsForPortal(portalToTest!.Id, FusionContextApiData.InvalidContextId, UserType.Authenticated); // Assert - // TODO Fusion 404 returned + Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode); } [TestMethod] @@ -351,7 +390,7 @@ public async Task Get_AppsForNonExistentPortal_AsAuthenticatedUser_ShouldReturnN Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode); } - + [TestMethod] public async Task Get_AppsForPortal_WithoutContext_AsAnonymousUser_ShouldReturnUnauthorized() { @@ -366,14 +405,13 @@ public async Task Get_AppsForPortal_WithoutContext_AsAnonymousUser_ShouldReturnU public async Task Get_AppsForPortal_WithValidContext_AsAnonymousUser_ShouldReturnUnauthorized() { // Act - var apps = await AssertGetAppsForPortal(Guid.NewGuid(), FusionContextData.InitialSeedData.JcaContextId, UserType.Anonymous, HttpStatusCode.Unauthorized); + var apps = await AssertGetAppsForPortal(Guid.NewGuid(), FusionContextApiData.JcaContextId, UserType.Anonymous, HttpStatusCode.Unauthorized); // Assert Assert.IsNull(apps); } [TestMethod] - [Ignore] public async Task Get_PortalOnboardedApps_AsAuthenticatedUser_ShouldReturnOk() { // Arrange @@ -387,7 +425,7 @@ public async Task Get_PortalOnboardedApps_AsAuthenticatedUser_ShouldReturnOk() Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); var content = await response.Content.ReadAsStringAsync(); - var apps = JsonConvert.DeserializeObject>(content); + var apps = JsonConvert.DeserializeObject>(content); Assert.IsNotNull(apps); Assert.IsTrue(apps.Count > 0); @@ -412,7 +450,7 @@ public async Task Delete_Portal_AsAdministrator_ShouldReturnOk() var theOneCreatedToBeDeleted = getAllAfterCreation!.Last(); // Act - var response = await DeletePortal(theOneCreatedToBeDeleted!.Id, UserType.Administrator); + var response = await DeletePortal(theOneCreatedToBeDeleted.Id, UserType.Administrator); // Assert Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); @@ -427,10 +465,10 @@ public async Task Delete_PortalWithApps_AsAdministrator_ShouldReturnForbidden() { // Arrange var portals = await AssertGetAllPortals(UserType.Administrator, HttpStatusCode.OK); - var portalToDelete = portals?.SingleOrDefault(x => x.Key == PortalData.InitialSeedData.Portal2.Key); + var portalToDelete = portals?.SingleOrDefault(x => x.Key == PortalData.InitialDbSeedData.ProjectExecution.Key); // Ensure the portal has apps - var apps = await AssertGetAppsForPortal(portalToDelete!.Id, FusionContextData.InitialSeedData.JcaContextId, UserType.Administrator, HttpStatusCode.OK); + var apps = await AssertGetAppsForPortal(portalToDelete!.Id, FusionContextApiData.JcaContextId, UserType.Administrator, HttpStatusCode.OK); Assert.IsNotNull(apps); Assert.IsTrue(apps.Count > 0); @@ -451,10 +489,10 @@ public async Task Delete_PortalApp_AsAdministrator_ShouldReturnOk() { // Arrange var portals = await AssertGetAllPortals(UserType.Administrator, HttpStatusCode.OK); - var portalToTest = portals?.SingleOrDefault(x => x.Key == PortalData.InitialSeedData.Portal2.Key); + var portalToTest = portals?.SingleOrDefault(x => x.Key == PortalData.InitialDbSeedData.ProjectExecution.Key); // Ensure the portal has apps - var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextData.InitialSeedData.JcaContextId, UserType.Administrator, HttpStatusCode.OK); + var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextApiData.JcaContextId, UserType.Administrator, HttpStatusCode.OK); Assert.IsNotNull(apps); Assert.IsTrue(apps.Count > 0); @@ -477,10 +515,10 @@ public async Task Delete_PortalApp_AsAuthenticatedUser_ShouldReturnForbidden() { // Arrange var portals = await AssertGetAllPortals(UserType.Authenticated, HttpStatusCode.OK); - var portalToTest = portals?.SingleOrDefault(x => x.Key == PortalData.InitialSeedData.Portal2.Key); + var portalToTest = portals?.SingleOrDefault(x => x.Key == PortalData.InitialDbSeedData.ProjectExecution.Key); // Ensure the portal has apps - var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextData.InitialSeedData.JcaContextId, UserType.Authenticated, HttpStatusCode.OK); + var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextApiData.JcaContextId, UserType.Authenticated, HttpStatusCode.OK); Assert.IsNotNull(apps); Assert.IsTrue(apps.Count > 0); @@ -488,7 +526,7 @@ public async Task Delete_PortalApp_AsAuthenticatedUser_ShouldReturnForbidden() var appToDelete = apps.First(); // Act - var response = await DeletePortalApp(portalToTest!.Id,appToDelete.Key, UserType.Authenticated); + var response = await DeletePortalApp(portalToTest.Id, appToDelete.Key, UserType.Authenticated); // Assert Assert.AreEqual(HttpStatusCode.Forbidden, response.StatusCode); @@ -497,13 +535,12 @@ public async Task Delete_PortalApp_AsAuthenticatedUser_ShouldReturnForbidden() [TestMethod] public async Task Delete_PortalApp_AsAnonymousUser_ShouldReturnUnauthorized() { - // Arrange // Arrange var portals = await AssertGetAllPortals(UserType.Authenticated, HttpStatusCode.OK); - var portalToTest = portals?.SingleOrDefault(x => x.Key == PortalData.InitialSeedData.Portal2.Key); + var portalToTest = portals?.SingleOrDefault(x => x.Key == PortalData.InitialDbSeedData.ProjectExecution.Key); // Ensure the portal has apps - var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextData.InitialSeedData.JcaContextId, UserType.Authenticated, HttpStatusCode.OK); + var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextApiData.JcaContextId, UserType.Authenticated, HttpStatusCode.OK); Assert.IsNotNull(apps); Assert.IsTrue(apps.Count > 0); @@ -511,7 +548,7 @@ public async Task Delete_PortalApp_AsAnonymousUser_ShouldReturnUnauthorized() var appToDelete = apps.First(); // Act - var response = await DeletePortalApp(portalToTest.Id!, appToDelete.Key, UserType.Anonymous); + var response = await DeletePortalApp(portalToTest.Id, appToDelete.Key, UserType.Anonymous); // Assert Assert.AreEqual(HttpStatusCode.Unauthorized, response.StatusCode); @@ -561,7 +598,7 @@ public async Task Delete_PortalApp_AsAnonymousUser_ShouldReturnUnauthorized() foreach (var portal in portals) { AssertHelpers.AssertPortalValues(portal); - Assert.AreEqual(portal.Apps.Count, 0); // No relational data should be included in this request + Assert.AreEqual(0, portal.Apps.Count); // No relational data should be included in this request } return portals; @@ -585,7 +622,7 @@ public async Task Delete_PortalApp_AsAnonymousUser_ShouldReturnUnauthorized() Assert.IsNotNull(content); AssertHelpers.AssertPortalValues(portal); AssertHelpers.AssertPortalConfigurationValues(portal!.Configuration, acceptNullValues: true); - Assert.AreEqual(portal.Apps.Count, 0); // No relational data should be included in this request + Assert.AreEqual(0, portal.Apps.Count); // No relational data should be included in this request return portal; } @@ -607,11 +644,38 @@ public async Task Delete_PortalApp_AsAnonymousUser_ShouldReturnUnauthorized() Assert.IsNotNull(content); Assert.IsNotNull(portalConfiguration); - AssertHelpers.AssertPortalConfigurationValues(portalConfiguration, acceptNullValues: true); + AssertHelpers.AssertPortalConfigurationValues(portalConfiguration, acceptNullValues: false); return portalConfiguration; } + private static async Task?> AssertGetAppKeysForPortal(Guid portalId, Guid? contextId, UserType userType, HttpStatusCode expectedStatusCode) + { + // Act + var response = await GetAppKeysForPortal(portalId, contextId, userType); + var content = await response.Content.ReadAsStringAsync(); + var appKeys = JsonConvert.DeserializeObject>(content); + + // Assert + Assert.AreEqual(expectedStatusCode, response.StatusCode); + + if (response.StatusCode != HttpStatusCode.OK) + { + return appKeys; + } + + Assert.IsNotNull(content); + Assert.IsNotNull(appKeys); + + foreach (var appKey in appKeys) + { + Assert.IsNotNull(appKey); + Assert.IsInstanceOfType(appKey); + } + + return appKeys; + } + private static async Task?> AssertGetAppsForPortal(Guid portalId, Guid? contextId, UserType userType, HttpStatusCode expectedStatusCode) { // Act @@ -695,6 +759,15 @@ private static async Task GetPortalConfiguration(Guid porta return response; } + private static async Task GetAppKeysForPortal(Guid portalId, Guid? contextId, UserType userType) + { + var route = contextId != null ? $"{Route}/{portalId}/contexts/{contextId}/appkeys" : $"{Route}/{portalId}/appkeys"; + var client = TestFactory.Instance.GetHttpClient(userType); + var response = await client.GetAsync(route); + + return response; + } + private static async Task GetAppsForPortal(Guid portalId, Guid? contextId, UserType userType) { var route = contextId != null ? $"{Route}/{portalId}/contexts/{contextId}/apps" : $"{Route}/{portalId}/apps"; diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Misc/ApplicationDbContextExtension.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Misc/ApplicationDbContextExtension.cs index b7acdc0f2..0b89a1181 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Misc/ApplicationDbContextExtension.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Misc/ApplicationDbContextExtension.cs @@ -32,16 +32,21 @@ private static void SeedPortal(DbContext dbContext) { // Create portals - var portalWithoutApps = PortalData.InitialSeedData.Portal1; - var portalWithApps = PortalData.InitialSeedData.Portal2; + var portalWithoutApps = PortalData.InitialDbSeedData.PortfolioManagement; + var portalWithApps = PortalData.InitialDbSeedData.ProjectExecution; dbContext.AddRange(portalWithoutApps, portalWithApps); dbContext.SaveChanges(); + // Add portal configuration + + portalWithoutApps.Configuration.Update(PortalConfigurationData.InitialDbSeedData.GenericPortalConfiguration.Router, PortalConfigurationData.InitialDbSeedData.GenericPortalConfiguration.Extension, PortalConfigurationData.InitialDbSeedData.GenericPortalConfiguration.Environment); + portalWithApps.Configuration.Update(PortalConfigurationData.InitialDbSeedData.GenericPortalConfiguration.Router, PortalConfigurationData.InitialDbSeedData.GenericPortalConfiguration.Extension, PortalConfigurationData.InitialDbSeedData.GenericPortalConfiguration.Environment); + // Add context types - var contextTypeProjectMaster = ContextTypeData.InitialSeedData.ContextType1; - var contextTypeFacility = ContextTypeData.InitialSeedData.ContextType2; + var contextTypeProjectMaster = ContextTypeData.InitialDbSeedData.ContextType1; + var contextTypeFacility = ContextTypeData.InitialDbSeedData.ContextType2; // Connect portal with a context type portalWithApps.AddContextType(contextTypeProjectMaster); @@ -51,12 +56,12 @@ private static void SeedPortal(DbContext dbContext) // Add onboarded apps - var meetingsApp = OnboardedAppData.InitialSeedData.MeetingsApp; - var reviewsApp = OnboardedAppData.InitialSeedData.ReviewsApp; - var tasksApp = OnboardedAppData.InitialSeedData.TasksApp; - var orgChartApp = OnboardedAppData.InitialSeedData.OrgChartApp; - var handoverGardenApp = OnboardedAppData.InitialSeedData.HandoverGardenApp; - var workOrderGardenApp = OnboardedAppData.InitialSeedData.WorkOrderGardenApp; + var meetingsApp = OnboardedAppData.InitialDbSeedData.MeetingsApp; + var reviewsApp = OnboardedAppData.InitialDbSeedData.ReviewsApp; + var tasksApp = OnboardedAppData.InitialDbSeedData.TasksApp; + var orgChartApp = OnboardedAppData.InitialDbSeedData.OrgChartApp; + var handoverGardenApp = OnboardedAppData.InitialDbSeedData.HandoverGardenApp; + var workOrderGardenApp = OnboardedAppData.InitialDbSeedData.WorkOrderGardenApp; // Add apps @@ -65,9 +70,10 @@ private static void SeedPortal(DbContext dbContext) // Add onboarded contexts - var jcaContext = OnboardedContextData.InitialSeedData.JcaContext; + var jcaContext = OnboardedContextData.InitialDbSeedData.JcaContext; + var ogpContext = OnboardedContextData.InitialDbSeedData.OgpContext; - dbContext.AddRange(jcaContext); + dbContext.AddRange(jcaContext, ogpContext); dbContext.SaveChanges(); // Add apps to portal diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/TestFactory.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/TestFactory.cs index 722c2b1bb..4c4a8e4eb 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/TestFactory.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/TestFactory.cs @@ -1,11 +1,11 @@ -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps; -using Equinor.ProjectExecutionPortal.FusionPortalApi.Apps.Models; -using Equinor.ProjectExecutionPortal.Infrastructure; +using Equinor.ProjectExecutionPortal.Infrastructure; using Equinor.ProjectExecutionPortal.Tests.WebApi.Data; using Equinor.ProjectExecutionPortal.Tests.WebApi.Misc; using Equinor.ProjectExecutionPortal.Tests.WebApi.Setup; using Equinor.ProjectExecutionPortal.WebApi.Authorization; using Fusion.Integration; +using Fusion.Integration.Apps.Abstractions.Abstractions; +using Fusion.Integration.Apps.Abstractions.Models; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; @@ -26,8 +26,8 @@ public sealed class TestFactory : WebApplicationFactory private readonly string _configPath; private readonly List _teardownList = new(); private readonly List _disposables = new(); - private readonly Mock _fusionPortalApiServiceMock = new(); private readonly Mock _fusionContextResolverMock = new(); + private readonly Mock _fusionAppsClientMock = new(); public static Dictionary TestUsersDictionary = new(); private static TestFactory? _sInstance; private static readonly object _sPadlock = new(); @@ -107,8 +107,8 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) services.PostConfigureAll(jwtBearerOptions => jwtBearerOptions.ForwardAuthenticate = IntegrationTestAuthHandler.TestAuthenticationScheme); - services.AddScoped(_ => _fusionPortalApiServiceMock.Object); services.AddScoped(_ => _fusionContextResolverMock.Object); + services.AddScoped(_ => _fusionAppsClientMock.Object); }); builder.ConfigureServices(services => @@ -198,22 +198,26 @@ private static string GetTestLocalDbConnectionString(string projectDir) private void SetupServiceMock() { - _fusionPortalApiServiceMock.Setup(service => service.TryGetFusionPortalApps()) - .Returns(Task.FromResult(FusionPortalAppData.ValidFusionApps as IList)); + _fusionAppsClientMock.Setup(service => service.GetAppsAsync(default)) + .Returns(Task.FromResult>(FusionAppApiData.ValidFusionApps)); - _fusionPortalApiServiceMock.Setup(service => service.TryGetFusionPortalApp(It.IsAny())) - .Returns(Task.FromResult(FusionPortalAppData.ValidFusionApps.FirstOrDefault())); + _fusionAppsClientMock.Setup(service => service.GetAppAsync(It.IsAny(), default)) + .Returns((string appKey, CancellationToken token) => + { + return Task.FromResult(FusionAppApiData.ValidFusionApps.FirstOrDefault(x => x.AppKey == appKey))!; + }); _fusionContextResolverMock.Setup(service => service.ResolveContextAsync(It.IsAny(), It.IsAny())) .Returns((ContextIdentifier contextIdentifier, FusionContextType type) => { - return Task.FromResult(FusionContextData.ValidFusionContexts.FirstOrDefault(x => x.ExternalId == contextIdentifier.Identifier)); + return Task.FromResult(FusionContextApiData.ValidFusionContexts.FirstOrDefault(x => x.ExternalId == contextIdentifier.Identifier)); }); - _fusionContextResolverMock.Setup(service => service.GetContextAsync(It.IsAny())).Returns((Guid contextId) => - { - return Task.FromResult(FusionContextData.ValidFusionContexts.First(x => x.Id == contextId)); - }); + _fusionContextResolverMock.Setup(service => service.GetContextAsync(It.IsAny())) + .Returns((Guid contextId) => + { + return Task.FromResult(FusionContextApiData.ValidFusionContexts.FirstOrDefault(x => x.Id == contextId))!; + }); } private void SetupTestUsers() diff --git a/radixconfig.yaml b/radixconfig.yaml index 9220d7800..28d0ad497 100644 --- a/radixconfig.yaml +++ b/radixconfig.yaml @@ -32,8 +32,6 @@ spec: AzureAd__ClientId: "" Authenticator__ProjectPortalApiClientId: "" Swagger__ClientId: "" - FusionPortalApi__BaseAddress: "" - FusionPortalApi__Scope: "" AssetProxy__FusionPortalUrl: "" AssetProxy__FusionPeopleUrl: "" AssetProxy__TokenScope: ""