Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change remove-global-app to be remove-app #751

Merged
merged 8 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
}
Loading