Skip to content

Commit

Permalink
change remove-global-app to be remove-app (#751)
Browse files Browse the repository at this point in the history
Co-authored-by: Jossilainen <[email protected]>
  • Loading branch information
Jossilainen and Jossilainen authored Sep 18, 2024
1 parent 342661b commit 0871598
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 43 deletions.
5 changes: 5 additions & 0 deletions .changeset/pr-751-2076327141.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

---
"fusion-project-portal": patch
---
Delete app now removes an app from a portal even if the app is contextual or global
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

namespace Equinor.ProjectExecutionPortal.Application.Commands.Portals.RemoveGlobalAppFromPortal;

public class RemoveGlobalAppFromPortalCommand : IRequest
public class RemoveAppFromPortalCommand : IRequest
{
public RemoveGlobalAppFromPortalCommand(Guid portalId, string appKey)
public RemoveAppFromPortalCommand(Guid portalId, string appKey)
{
PortalId = portalId;
AppKey = appKey;
Expand All @@ -17,7 +17,7 @@ public RemoveGlobalAppFromPortalCommand(Guid portalId, string appKey)
public Guid PortalId { get; }
public string AppKey { get; }

public class Handler : IRequestHandler<RemoveGlobalAppFromPortalCommand>
public class Handler : IRequestHandler<RemoveAppFromPortalCommand>
{
private readonly IReadWriteContext _readWriteContext;

Expand All @@ -26,22 +26,19 @@ public Handler(IReadWriteContext readWriteContext)
_readWriteContext = readWriteContext;
}

public async Task Handle(RemoveGlobalAppFromPortalCommand command, CancellationToken cancellationToken)
public async Task Handle(RemoveAppFromPortalCommand command, CancellationToken cancellationToken)
{
var portalApp = await _readWriteContext.Set<PortalApp>()
var portalApps = await _readWriteContext.Set<PortalApp>()
.Include(x => x.OnboardedApp)
.FirstOrDefaultAsync(x =>
x.PortalId == command.PortalId
&& x.OnboardedContextId == null
&& x.OnboardedApp.AppKey == command.AppKey,
cancellationToken);

if (portalApp == null)
.Where(x => x.PortalId == command.PortalId && x.OnboardedApp.AppKey == command.AppKey)
.ToListAsync(cancellationToken);

if (!portalApps.Any())
{
throw new NotFoundException(nameof(PortalApp), command.AppKey);
}

_readWriteContext.Set<PortalApp>().Remove(portalApp);
_readWriteContext.Set<PortalApp>().RemoveRange(portalApps);

await _readWriteContext.SaveChangesAsync(cancellationToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,6 @@ public async Task<ActionResult<Guid>> AddPortalApp([FromRoute] Guid portalId, Gu
[ProducesResponseType(typeof(void), StatusCodes.Status400BadRequest)]
public async Task<ActionResult> RemovePortalApp([FromRoute] Guid portalId, [FromRoute] string appKey)
{
// TODO: Removing global should come with a warning. E.g highlight affected contexts
var request = new ApiRemovePortalAppRequest();

try
Expand All @@ -342,7 +341,6 @@ public async Task<ActionResult> RemovePortalApp([FromRoute] Guid portalId, [From
[ProducesResponseType(typeof(void), StatusCodes.Status400BadRequest)]
public async Task<ActionResult> RemovePortalApp([FromRoute] Guid portalId, Guid contextId, [FromRoute] string appKey)
{
// TODO: Removing global should come with a warning. E.g highlight affected contexts
var request = new ApiRemovePortalAppRequest();

try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ public RemoveContextAppFromPortalCommand ToCommand(Guid portalId, Guid contextId
return new RemoveContextAppFromPortalCommand(portalId, contextId, appKey);
}

public RemoveGlobalAppFromPortalCommand ToCommand(Guid portalId, string appKey)
public RemoveAppFromPortalCommand ToCommand(Guid portalId, string appKey)
{
return new RemoveGlobalAppFromPortalCommand(portalId, appKey);
return new RemoveAppFromPortalCommand(portalId, appKey);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,100 @@ public async Task Delete_PortalWithApps_AsAdministrator_ShouldReturnForbidden()
Assert.IsNotNull(deletedPortal);
}

[TestMethod]
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);

// Ensure the portal has apps
var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextData.InitialSeedData.JcaContextId, UserType.Administrator, HttpStatusCode.OK);

Assert.IsNotNull(apps);
Assert.IsTrue(apps.Count > 0);

var appToDelete = apps.First();

// Act
var response = await DeletePortalApp(portalToTest.Id, appToDelete.Key, UserType.Administrator);

// Assert
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);

// Verify the app is actually deleted
var deletedApp = await AssertGetPortalApp(portalToTest.Id, appToDelete.Key, UserType.Authenticated, HttpStatusCode.NotFound);
Assert.IsNull(deletedApp);
}

[TestMethod]
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);

// Ensure the portal has apps
var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextData.InitialSeedData.JcaContextId, UserType.Authenticated, HttpStatusCode.OK);

Assert.IsNotNull(apps);
Assert.IsTrue(apps.Count > 0);

var appToDelete = apps.First();

// Act
var response = await DeletePortalApp(portalToTest!.Id,appToDelete.Key, UserType.Authenticated);

// Assert
Assert.AreEqual(HttpStatusCode.Forbidden, response.StatusCode);
}

[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);

// Ensure the portal has apps
var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextData.InitialSeedData.JcaContextId, UserType.Authenticated, HttpStatusCode.OK);

Assert.IsNotNull(apps);
Assert.IsTrue(apps.Count > 0);

var appToDelete = apps.First();

// Act
var response = await DeletePortalApp(portalToTest.Id!, appToDelete.Key, UserType.Anonymous);

// Assert
Assert.AreEqual(HttpStatusCode.Unauthorized, response.StatusCode);
}

#region Helpers

private static async Task<ApiPortalApp?> AssertGetPortalApp(Guid portalId, string appKey, UserType userType, HttpStatusCode expectedStatusCode)
{
// Act
var response = await GetPortalApp(portalId, appKey, userType);
var content = await response.Content.ReadAsStringAsync();
var app = JsonConvert.DeserializeObject<ApiPortalApp>(content);

// Assert
Assert.AreEqual(expectedStatusCode, response.StatusCode);

if (response.StatusCode != HttpStatusCode.OK)
{
return null;
}

Assert.IsNotNull(content);
AssertHelpers.AssertPortalAppValues(app);

return app;
}

private static async Task<IList<ApiPortal>?> AssertGetAllPortals(UserType userType, HttpStatusCode expectedStatusCode)
{
// Act
Expand Down Expand Up @@ -494,6 +586,32 @@ public async Task Delete_PortalWithApps_AsAdministrator_ShouldReturnForbidden()
return portalConfiguration;
}

private static async Task<IList<ApiPortalApp>?> AssertGetAppsForPortal(Guid portalId, Guid? contextId, UserType userType, HttpStatusCode expectedStatusCode)
{
// Act
var response = await GetAppsForPortal(portalId, contextId, userType);
var content = await response.Content.ReadAsStringAsync();
var apps = JsonConvert.DeserializeObject<IList<ApiPortalApp>>(content);

// Assert
Assert.AreEqual(expectedStatusCode, response.StatusCode);

if (response.StatusCode != HttpStatusCode.OK)
{
return apps;
}

Assert.IsNotNull(content);
Assert.IsNotNull(apps);

foreach (var app in apps)
{
AssertHelpers.AssertPortalAppValues(app);
}

return apps;
}

private static async Task<HttpResponseMessage> CreatePortal(UserType userType, ApiCreatePortalRequest createdPortal)
{
var serializePayload = JsonConvert.SerializeObject(createdPortal);
Expand Down Expand Up @@ -527,32 +645,6 @@ private static async Task<HttpResponseMessage> UpdatePortalConfiguration(UserTyp
return response;
}

private static async Task<IList<ApiPortalApp>?> AssertGetAppsForPortal(Guid portalId, Guid? contextId, UserType userType, HttpStatusCode expectedStatusCode)
{
// Act
var response = await GetAppsForPortal(portalId, contextId, userType);
var content = await response.Content.ReadAsStringAsync();
var apps = JsonConvert.DeserializeObject<IList<ApiPortalApp>>(content);

// Assert
Assert.AreEqual(expectedStatusCode, response.StatusCode);

if (response.StatusCode != HttpStatusCode.OK)
{
return apps;
}

Assert.IsNotNull(content);
Assert.IsNotNull(apps);

foreach (var app in apps)
{
AssertHelpers.AssertPortalAppValues(app);
}

return apps;
}

private static async Task<HttpResponseMessage> GetAllPortals(UserType userType)
{
var client = TestFactory.Instance.GetHttpClient(userType);
Expand Down Expand Up @@ -604,6 +696,24 @@ private static async Task<HttpResponseMessage> DeletePortal(Guid portalId, UserT
return response;
}

private static async Task<HttpResponseMessage> GetPortalApp(Guid portalId, string appKey, UserType userType)
{
var route = $"{Route}{portalId}/onboarded-apps/{appKey}";
var client = TestFactory.Instance.GetHttpClient(userType);
var response = await client.GetAsync(route);

return response;
}

private static async Task<HttpResponseMessage> DeletePortalApp(Guid portalId, string appId, UserType userType)
{
var route = $"{Route}/{portalId}/apps/{appId}";
var client = TestFactory.Instance.GetHttpClient(userType);
var response = await client.DeleteAsync(route);

return response;
}

#endregion Helpers
}
}

0 comments on commit 0871598

Please sign in to comment.