diff --git a/.changeset/pr-744-2069530352.md b/.changeset/pr-744-2069530352.md new file mode 100644 index 000000000..2ceb323e2 --- /dev/null +++ b/.changeset/pr-744-2069530352.md @@ -0,0 +1,6 @@ + +--- +"fusion-project-portal": patch +--- +Endpoint for Apps activated on portal combined with available apps for portal. +Endpoint for Portal-app with reference to contextIds. diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApp/GetPortalOnboardedAppQuery.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApp/GetPortalOnboardedAppQuery.cs new file mode 100644 index 000000000..c6b2681da --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApp/GetPortalOnboardedAppQuery.cs @@ -0,0 +1,89 @@ +using AutoMapper; +using Equinor.ProjectExecutionPortal.Application.Services.AppService; +using Equinor.ProjectExecutionPortal.Application.Services.ContextService; +using Equinor.ProjectExecutionPortal.Application.Services.PortalService; +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.GetPortalOnboardedApp; + +public class GetPortalOnboardedAppQuery(Guid portalId, string appKey) : QueryBase +{ + public Guid PortalId { get; } = portalId; + public string AppKey { get; } = appKey; + + public class Handler : IRequestHandler + { + private readonly IReadWriteContext _readWriteContext; + private readonly IAppService _appService; + private readonly IPortalService _portalService; + private readonly IContextService _contextService; + private readonly IMapper _mapper; + + public Handler(IReadWriteContext readWriteContext, IAppService appService, IPortalService portalService, IContextService contextService, IMapper mapper) + { + _readWriteContext = readWriteContext; + _appService = appService; + _portalService = portalService; + _contextService = contextService; + _mapper = mapper; + } + + public async Task Handle(GetPortalOnboardedAppQuery request, CancellationToken cancellationToken) + { + var portal = await _readWriteContext.Set() + .AsNoTracking() + .Include(portal => portal.ContextTypes) + .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 portalApps = portal.Apps.Where(app => app.OnboardedApp.AppKey == request.AppKey).ToList(); + + if (portalApps.Any()){ + + var onboardedContexts = await _readWriteContext.Set() + .AsNoTracking() + .ToListAsync(cancellationToken); + + var portalContextIds = await _contextService.GetFusionContextIds(onboardedContexts.Where(context => portalApps.Any(app => app.OnboardedContextId == context.Id)).ToList(), cancellationToken); + + var portalOnboardedAppDto = _mapper.Map(portalApps.First()); + + await _portalService.EnrichPortalAppWithContextIds(portalOnboardedAppDto, portalContextIds, cancellationToken); + + await _portalService.SetAppAsActiveInPortal(portalOnboardedAppDto, cancellationToken); + + await _appService.EnrichAppWithFusionAppData(portalOnboardedAppDto.OnboardedApp, cancellationToken); + + return portalOnboardedAppDto; + } + + var onboardedApp = await _readWriteContext.Set() + .AsNoTracking() + .Include(onboardedApp => onboardedApp.ContextTypes) + .FirstOrDefaultAsync(x => x.AppKey == request.AppKey, cancellationToken); + + if (onboardedApp != null) + { + var portalOnboardedAppNotActive = await _portalService.GetPortalOnboardedAppNotActive(onboardedApp, cancellationToken); + + await _appService.EnrichAppWithFusionAppData(portalOnboardedAppNotActive.OnboardedApp, cancellationToken); + + return portalOnboardedAppNotActive; + } + + return null; + } + + } +} diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApps/GetPortalOnboardedAppsQuery.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApps/GetPortalOnboardedAppsQuery.cs new file mode 100644 index 000000000..378702ac1 --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortalOnboardedApps/GetPortalOnboardedAppsQuery.cs @@ -0,0 +1,58 @@ +using AutoMapper; +using Equinor.ProjectExecutionPortal.Application.Services.AppService; +using Equinor.ProjectExecutionPortal.Application.Services.PortalService; +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.GetPortalOnboardedApps; + +public class GetPortalOnboardedAppsQuery(Guid portalId) : QueryBase> +{ + public Guid PortalId { get; } = portalId; + + 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) + { + _readWriteContext = readWriteContext; + _appService = appService; + _portalService = portalService; + _mapper = mapper; + } + + public async Task> Handle(GetPortalOnboardedAppsQuery request, CancellationToken cancellationToken) + { + var portal = await _readWriteContext.Set() + .AsNoTracking() + .Include(portal => portal.ContextTypes) + .Include(portal => portal.Apps) + .ThenInclude(portalApp => portalApp.OnboardedApp) + .ThenInclude(app => app.ContextTypes) + .FirstOrDefaultAsync(x => x.Id == request.PortalId, cancellationToken); + + if (portal == null) + { + return new List(); + } + + var onboardedApps = await _readWriteContext.Set() + .AsNoTracking() + .Include(onboardedApp => onboardedApp.ContextTypes) + .ToListAsync(cancellationToken); + + var portalOnboardedAppsDto = await _portalService.CombinePortalAppsWithOnboardedApps(portal, onboardedApps, 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 new file mode 100644 index 000000000..2d88c2095 --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/PortalOnboardedAppDto.cs @@ -0,0 +1,15 @@ +using Equinor.ProjectExecutionPortal.Application.Infrastructure.Mappings; +using Equinor.ProjectExecutionPortal.Application.Queries.OnboardedApps; + +namespace Equinor.ProjectExecutionPortal.Application.Queries.Portals +{ + public class PortalOnboardedAppDto : IMapFrom + { + public OnboardedAppDto? OnboardedApp { get; set; } + public List ContextIds { get; set; } = []; + 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/IAppService.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/AppService/IAppService.cs index f5910c3e0..6f212dda8 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/AppService/IAppService.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/AppService/IAppService.cs @@ -18,5 +18,7 @@ public interface IAppService Task> EnrichAppsWithFusionAppData(IList apps, CancellationToken cancellationToken); Task> EnrichAppsWithAllFusionAppData(IList apps, CancellationToken cancellationToken); + + } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextService/ContextService.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextService/ContextService.cs index b0fdc5d65..10fa95451 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextService/ContextService.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextService/ContextService.cs @@ -1,4 +1,5 @@ using Equinor.ProjectExecutionPortal.Application.Queries.OnboardedContexts; +using Equinor.ProjectExecutionPortal.Domain.Entities; using Fusion.Integration; namespace Equinor.ProjectExecutionPortal.Application.Services.ContextService @@ -48,5 +49,23 @@ public async Task GetFusionContext(Guid contextId, CancellationTo return context; } + + public async Task> GetFusionContextIds(IList contexts, CancellationToken cancellationToken) + { + var contextIds = new List(); + + foreach (var context in contexts) + { + var contextIdentifier = ContextIdentifier.FromExternalId(context.ExternalId); + var fusionContext = await _fusionContextResolver.ResolveContextAsync(contextIdentifier); + + if (fusionContext != null) + { + contextIds.Add(fusionContext.Id); + } + } + + return contextIds; + } } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextService/IContextService.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextService/IContextService.cs index 4e80e6fca..03597c71c 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextService/IContextService.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/ContextService/IContextService.cs @@ -1,4 +1,5 @@ using Equinor.ProjectExecutionPortal.Application.Queries.OnboardedContexts; +using Equinor.ProjectExecutionPortal.Domain.Entities; using Fusion.Integration; namespace Equinor.ProjectExecutionPortal.Application.Services.ContextService @@ -8,5 +9,6 @@ public interface IContextService Task EnrichContextWithFusionContextData(OnboardedContextDto context, CancellationToken cancellationToken); Task> EnrichContextsWithFusionContextData(IList contexts, CancellationToken cancellationToken); Task GetFusionContext(Guid contextId, CancellationToken cancellationToken); + Task> GetFusionContextIds(IList contexts, CancellationToken cancellationToken); } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Services/PortalService/IPortalService.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/PortalService/IPortalService.cs new file mode 100644 index 000000000..2c5ef279e --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/PortalService/IPortalService.cs @@ -0,0 +1,14 @@ +using Equinor.ProjectExecutionPortal.Application.Queries.Portals; +using Equinor.ProjectExecutionPortal.Domain.Entities; + +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); + 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 new file mode 100644 index 000000000..e5602f55c --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Services/PortalService/PortalService.cs @@ -0,0 +1,99 @@ +using AutoMapper; +using Equinor.ProjectExecutionPortal.Application.Queries.OnboardedApps; +using Equinor.ProjectExecutionPortal.Application.Queries.Portals; +using Equinor.ProjectExecutionPortal.Domain.Entities; + +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) + { + + var portalAppsDto = _mapper.Map, List>(GetDistinctPortalApps(portal.Apps.ToList())); + + await SetAppsAsActiveInPortal(portalAppsDto, cancellationToken); + + 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(); + + await Task.CompletedTask; + + return portalOnboardedAppDto; + } + + public async Task GetPortalOnboardedAppNotActive(OnboardedApp onboardedApp, CancellationToken cancellationToken) + { + return new PortalOnboardedAppDto() + { + OnboardedApp = _mapper.Map(onboardedApp), + IsActive = false + }; + } + + 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) + { + var distinctPortalApps = portalApps.GroupBy(app => app.OnboardedApp.Id) + .Select(group => group.First()) + .ToList(); + return distinctPortalApps; + } + + private List GetOnBoardedAppsNotActiveInPortal(Portal portal, IList onboardedApps) + { + var onBoardedAppsNotActiveInPortal = IsContextualPortal(portal) ? + onboardedApps + .Where(onboardedApp => + portal.Apps.All(portalAppDto => portalAppDto.OnboardedApp.Id != onboardedApp.Id) && + (onboardedApp.ContextTypes.Count == 0 || + onboardedApp.ContextTypes.Any(m => portal.ContextTypes.Any(n => n.ContextTypeKey == m.ContextTypeKey)))) + .ToList() : + onboardedApps + .Where(onboardedApp => portal.Apps.All(portalAppDto => portalAppDto.OnboardedApp.Id != onboardedApp.Id)) + .ToList(); + + return onBoardedAppsNotActiveInPortal.Select(onBoardedApp => new PortalOnboardedAppDto() + { + OnboardedApp = _mapper.Map(onBoardedApp), + IsActive = false + }).ToList(); + + } + private bool IsContextualPortal(Portal portal) + { + return portal.ContextTypes.Count != 0; + } + } +} diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/PortalController.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/PortalController.cs index fdf70e41f..5387eebdd 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/PortalController.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/PortalController.cs @@ -2,6 +2,8 @@ using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortal; using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalApps; using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalConfiguration; +using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalOnboardedApp; +using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalOnboardedApps; using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortals; using Equinor.ProjectExecutionPortal.Domain.Common.Exceptions; using Equinor.ProjectExecutionPortal.WebApi.Authorization; @@ -191,6 +193,38 @@ public async Task>> PortalApps([FromRoute] Guid } + [HttpGet("{portalId:guid}/onboarded-apps")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + public async Task>> PortalOnboardedApps([FromRoute] Guid portalId) + { + var portalOnboardedAppsDto = await Mediator.Send(new GetPortalOnboardedAppsQuery(portalId)); + + if (!portalOnboardedAppsDto.Any()) + { + return FusionApiError.NotFound(portalId, "Could not find portal with id"); + } + + return Ok(portalOnboardedAppsDto.Select(x => new ApiPortalOnboardedApp(x)).ToList()); + + } + + [HttpGet("{portalId:guid}/onboarded-apps/{appKey}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + public async Task> PortalOnboardedApp([FromRoute] Guid portalId, string appKey) + { + var portalOnboardedAppDto = await Mediator.Send(new GetPortalOnboardedAppQuery(portalId, appKey)); + + if (portalOnboardedAppDto == null) + { + return FusionApiError.NotFound(portalId, "Could not find portal with id or appkey is invalid"); + } + + return new ApiPortalOnboardedApp(portalOnboardedAppDto); + + } + [HttpGet("{portalId:guid}/contexts/{contextId:guid}/apps")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/DiModules/ApplicationServicesModule.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/DiModules/ApplicationServicesModule.cs index e6bfd3767..69e38e934 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.PortalService; namespace Equinor.ProjectExecutionPortal.WebApi.DiModules; @@ -11,5 +12,6 @@ public static void AddApplicationServicesModules(this IServiceCollection service services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/PortalApp/ApiPortalApp.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/PortalApp/ApiPortalApp.cs index a47d81fc3..28c37a707 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 ApiContextType = Equinor.ProjectExecutionPortal.WebApi.ViewModels.ContextType.ApiContextType; namespace Equinor.ProjectExecutionPortal.WebApi.ViewModels.PortalApp { diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/PortalApp/ApiPortalOnboardedApp.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/PortalApp/ApiPortalOnboardedApp.cs new file mode 100644 index 000000000..ce444baa9 --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/PortalApp/ApiPortalOnboardedApp.cs @@ -0,0 +1,31 @@ +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; + +namespace Equinor.ProjectExecutionPortal.WebApi.ViewModels.PortalApp +{ + public class 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; + } + + public string Key { get; set; } + public IList ContextTypes { get; set; } + public IList ContextIds { get; set; } + public bool IsActive { get; set; } + public bool IsGlobal { get; set; } + public bool IsContextual { get; set; } + public ApiFusionPortalAppInformation? AppManifest { get; set; } + } +} 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 360008a88..023de8ea6 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/ContextTypeControllerTests.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/ContextTypeControllerTests.cs @@ -20,7 +20,7 @@ public async Task Get_ContextTypes_AsAuthenticatedUser_ShouldReturnOk() var contextTypes = await AssertGetAllContextTypes(UserType.Authenticated, HttpStatusCode.OK); // Assert - Assert.IsTrue(contextTypes.Count == 2); + Assert.IsTrue(contextTypes.Count > 0); foreach (var contextType in contextTypes) { @@ -35,7 +35,7 @@ public async Task Get_ContextTypes_AsAdministratorUser_ShouldReturnOk() var contextTypes = await AssertGetAllContextTypes(UserType.Administrator, HttpStatusCode.OK); // Assert - Assert.IsTrue(contextTypes.Count == 2); + Assert.IsTrue(contextTypes.Count > 0); foreach (var contextType in contextTypes) { @@ -159,6 +159,7 @@ public async Task Remove_ContextType_WithoutPortals_AsAdministratorUser_ShouldRe Assert.IsNotNull(getAllBefore.Count); Assert.IsNotNull(getAllAfterRemoval.Count); Assert.AreEqual(getAllBefore.Count - 1, getAllAfterRemoval.Count); + } [TestMethod] 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 b0cdfbdc4..9595ee238 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/PortalControllerTests.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/PortalControllerTests.cs @@ -325,7 +325,7 @@ public async Task Get_AppsForNonExistentPortal_AsAuthenticatedUser_ShouldReturnN Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode); } - + [TestMethod] public async Task Get_AppsForPortal_WithoutContext_AsAnonymousUser_ShouldReturnUnauthorized() { @@ -346,6 +346,27 @@ public async Task Get_AppsForPortal_WithValidContext_AsAnonymousUser_ShouldRetur Assert.IsNull(apps); } + [TestMethod] + [Ignore] + public async Task Get_PortalOnboardedApps_AsAuthenticatedUser_ShouldReturnOk() + { + // Arrange + var portals = await AssertGetAllPortals(UserType.Authenticated, HttpStatusCode.OK); + var portalToTest = portals!.First(); + + // Act + var response = await GetPortalOnboardedApps(portalToTest.Id, UserType.Authenticated); + + // Assert + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + + var content = await response.Content.ReadAsStringAsync(); + var apps = JsonConvert.DeserializeObject>(content); + + Assert.IsNotNull(apps); + Assert.IsTrue(apps.Count > 0); + } + [TestMethod] public async Task Delete_Portal_AsAdministrator_ShouldReturnOk() { @@ -565,6 +586,15 @@ private static async Task GetAppsForPortal(Guid portalId, G return response; } + private static async Task GetPortalOnboardedApps(Guid portalId, UserType userType) + { + var route = $"{Route}/{portalId}/onboarded-apps"; + var client = TestFactory.Instance.GetHttpClient(userType); + var response = await client.GetAsync(route); + + return response; + } + private static async Task DeletePortal(Guid portalId, UserType userType) { var route = $"{Route}/{portalId}";