From 892d638a15b309d5e60b4f05b40c593535ad532a Mon Sep 17 00:00:00 2001 From: Jostein Date: Fri, 12 Jul 2024 12:31:08 +0200 Subject: [PATCH] add response types for portal-controller --- .../AddContextAppToPortalCommand.cs | 2 +- .../AddContextTypeToPortalCommand.cs | 2 +- .../CreatePortal/CreatePortalCommand.cs | 3 +- .../Controllers/PortalController.cs | 107 ++++++++++++++---- 4 files changed, 90 insertions(+), 24 deletions(-) diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/AddContextAppToPortal/AddContextAppToPortalCommand.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/AddContextAppToPortal/AddContextAppToPortalCommand.cs index 169db0d66..454eb1069 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/AddContextAppToPortal/AddContextAppToPortalCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/AddContextAppToPortal/AddContextAppToPortalCommand.cs @@ -37,7 +37,7 @@ public async Task Handle(AddContextAppToPortalCommand command, Cancellatio if (fusionContext == null) { - throw new InvalidActionException($"Cannot add app '{command.AppKey} to '{command.PortalId}'. Missing context parameter."); + throw new InvalidOperationException($"Cannot add app '{command.AppKey} to '{command.PortalId}'. Missing context parameter."); } var onboardedContext = await _readWriteContext.Set() 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 099e22058..d3a6ea13b 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/AddContextTypeToPortal/AddContextTypeToPortalCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/AddContextTypeToPortal/AddContextTypeToPortalCommand.cs @@ -54,7 +54,7 @@ public async Task Handle(AddContextTypeToPortalCommand command, Cancellati if (contextType == null) { - throw new InvalidActionException($"context-type: {command.Type} is not supported"); + throw new InvalidOperationException($"context-type: {command.Type} is not supported"); } portalWithAllContextTypes.AddContextType(contextType); 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 0f55de184..77dff862b 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/CreatePortal/CreatePortalCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/CreatePortal/CreatePortalCommand.cs @@ -1,5 +1,6 @@ using Equinor.ProjectExecutionPortal.Application.Helpers; using Equinor.ProjectExecutionPortal.Application.Services.ContextTypeService; +using Equinor.ProjectExecutionPortal.Domain.Common.Exceptions; using Equinor.ProjectExecutionPortal.Domain.Entities; using Equinor.ProjectExecutionPortal.Infrastructure; using MediatR; @@ -43,7 +44,7 @@ public async Task Handle(CreatePortalCommand command, CancellationToken ca var slug = SlugHelper.Sluggify(command.Name); var portal = new Portal(slug, command.Name, command.ShortName, command.SubText, command.Description, command.Order, command.Icon); - + portal.AddContextTypes(await _contextTypeService.GetContextTypesByContextTypeKey(command.ContextTypes, cancellationToken)); await _readWriteContext.Set().AddAsync(portal, cancellationToken); diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/PortalController.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/PortalController.cs index b91badb51..6c1adedf0 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/PortalController.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/Controllers/PortalController.cs @@ -1,4 +1,5 @@ -using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortal; +using System.Net.Mime; +using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortal; using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortalApps; using Equinor.ProjectExecutionPortal.Application.Queries.Portals.GetPortals; using Equinor.ProjectExecutionPortal.Domain.Common.Exceptions; @@ -26,6 +27,8 @@ public async Task>> Portals() } [HttpGet("{portalId:guid}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] public async Task> Portal([FromRoute] Guid portalId) { var portalWithAppsDto = await Mediator.Send(new GetPortalQuery(portalId)); @@ -40,6 +43,12 @@ public async Task> Portal([FromRoute] Guid portalId) [HttpPost("")] [Authorize(Policy = Policies.ProjectPortal.Admin)] + [Consumes(MediaTypeNames.Application.Json)] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(void), StatusCodes.Status400BadRequest)] public async Task> CreatePortal([FromBody] ApiCreatePortalRequest request) { try @@ -64,6 +73,12 @@ public async Task> CreatePortal([FromBody] ApiCreatePortalReq [HttpPut("{portalId:guid}")] [Authorize(Policy = Policies.ProjectPortal.Admin)] + [Consumes(MediaTypeNames.Application.Json)] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(void), StatusCodes.Status400BadRequest)] public async Task> UpdatePortal([FromRoute] Guid portalId, [FromBody] ApiUpdatePortalRequest request) { try @@ -84,6 +99,12 @@ public async Task> UpdatePortal([FromRoute] Guid portalId, [F [HttpPut("{portalId:guid}/setAsDefault")] [Authorize(Policy = Policies.ProjectPortal.Admin)] + [Consumes(MediaTypeNames.Application.Json)] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(void), StatusCodes.Status400BadRequest)] public async Task> SetPortalAsDefault([FromRoute] Guid portalId) { var request = new ApiSetPortalAsDefaultRequest(); @@ -107,6 +128,8 @@ public async Task> SetPortalAsDefault([FromRoute] Guid portal // Apps [HttpGet("{portalId:guid}/apps")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] public async Task>> PortalApps([FromRoute] Guid portalId) { //TODO: improve error handling @@ -125,6 +148,8 @@ public async Task>> PortalApps([FromRoute] Guid } [HttpGet("{portalId:guid}/contexts/{contextId:guid}/apps")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] public async Task>> PortalApps([FromRoute] Guid portalId, [FromRoute] Guid contextId) { //TODO: improve error handling @@ -140,6 +165,13 @@ public async Task>> PortalApps([FromRoute] Guid [HttpPost("{portalId:guid}/apps")] [Authorize(Policy = Policies.ProjectPortal.Admin)] + [Consumes(MediaTypeNames.Application.Json)] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(void), StatusCodes.Status409Conflict)] + [ProducesResponseType(typeof(void), StatusCodes.Status400BadRequest)] public async Task> AddPortalApp([FromRoute] Guid portalId, [FromBody] ApiAddGlobalAppToPortalRequest request) { try @@ -152,7 +184,7 @@ public async Task> AddPortalApp([FromRoute] Guid portalId, [F } catch (InvalidActionException ex) { - return FusionApiError.InvalidOperation("500", ex.Message); + return FusionApiError.ResourceExists(request.AppKey, ex.Message, ex); } catch (Exception) { @@ -164,31 +196,45 @@ public async Task> AddPortalApp([FromRoute] Guid portalId, [F [HttpPost("{portalId:guid}/contexts/{contextId}/apps")] [Authorize(Policy = Policies.ProjectPortal.Admin)] + [Consumes(MediaTypeNames.Application.Json)] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(void), StatusCodes.Status409Conflict)] + [ProducesResponseType(typeof(void), StatusCodes.Status400BadRequest)] public async Task> AddPortalApp([FromRoute] Guid portalId, Guid contextId, [FromBody] ApiAddContextAppToPortalRequest request) { - - try - { - await Mediator.Send(request.ToCommand(portalId, contextId)); - } - catch (NotFoundException ex) - { - return FusionApiError.NotFound(portalId, ex.Message); - } - catch (InvalidActionException ex) - { - return FusionApiError.InvalidOperation("500", ex.Message); - } - catch (Exception) - { + try + { + await Mediator.Send(request.ToCommand(portalId, contextId)); + } + catch (NotFoundException ex) + { + return FusionApiError.NotFound(portalId, ex.Message); + } + catch (InvalidOperationException ex) + { + return FusionApiError.InvalidOperation("400", ex.Message); + } + catch (InvalidActionException ex) + { + return FusionApiError.ResourceExists(request.AppKey, ex.Message, ex); + } + catch (Exception) + { return FusionApiError.InvalidOperation("500", "An error occurred while adding portal app"); - } + } - return Ok(); + return Ok(); } [HttpDelete("{portalId:guid}/apps/{appKey}")] [Authorize(Policy = Policies.ProjectPortal.Admin)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(void), StatusCodes.Status400BadRequest)] public async Task RemovePortalApp([FromRoute] Guid portalId, [FromRoute] string appKey) { // TODO: Removing global should come with a warning. E.g highlight affected contexts @@ -212,6 +258,10 @@ public async Task RemovePortalApp([FromRoute] Guid portalId, [From [HttpDelete("{portalId:guid}/contexts/{contextId:guid}/apps/{appKey}")] [Authorize(Policy = Policies.ProjectPortal.Admin)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(void), StatusCodes.Status400BadRequest)] public async Task RemovePortalApp([FromRoute] Guid portalId, Guid contextId, [FromRoute] string appKey) { // TODO: Removing global should come with a warning. E.g highlight affected contexts @@ -236,6 +286,13 @@ public async Task RemovePortalApp([FromRoute] Guid portalId, Guid //ContextTypes [HttpPost("{portalId:guid}/context-type")] [Authorize(Policy = Policies.ProjectPortal.Admin)] + [Consumes(MediaTypeNames.Application.Json)] + [Produces(MediaTypeNames.Application.Json)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(void), StatusCodes.Status409Conflict)] + [ProducesResponseType(typeof(void), StatusCodes.Status400BadRequest)] public async Task> AddContextType([FromRoute] Guid portalId, [FromBody] ApiAddContextTypeToPortalRequest request) { try @@ -248,7 +305,11 @@ public async Task> AddContextType([FromRoute] Guid portalId, } catch (InvalidActionException ex) { - return FusionApiError.InvalidOperation("500", ex.Message); + return FusionApiError.ResourceExists(request.Type, ex.Message, ex); + } + catch (InvalidOperationException ex) + { + return FusionApiError.InvalidOperation("400", ex.Message); } catch (Exception) { @@ -260,6 +321,10 @@ public async Task> AddContextType([FromRoute] Guid portalId, [HttpDelete("{portalId:guid}/context-type/{contextType}")] [Authorize(Policy = Policies.ProjectPortal.Admin)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(void), StatusCodes.Status400BadRequest)] public async Task RemoveContextType([FromRoute] Guid portalId, [FromRoute] string contextType) { var request = new ApiRemovePortalContextType(); @@ -273,7 +338,7 @@ public async Task RemoveContextType([FromRoute] Guid portalId, [Fr } catch (InvalidActionException ex) { - return FusionApiError.InvalidOperation("500", ex.Message); + return FusionApiError.InvalidOperation("400", ex.Message); } catch (Exception) {