From 00f2f289f36dcdef8b71ad33abeea03a1e622497 Mon Sep 17 00:00:00 2001 From: vempo Date: Tue, 21 Aug 2018 16:42:26 +0300 Subject: Cenralized handling of USER_ID header Minor code style and spelling fixes. Change-Id: I07495a08d3c02276806c9043ed7dbf81ed1a9394 Issue-ID: SDC-1670 Signed-off-by: vempo --- .../onap/sdc/workflow/api/ExceptionsHandler.java | 15 ++--- .../onap/sdc/workflow/api/WorkflowController.java | 13 ++-- .../workflow/api/WorkflowVersionController.java | 29 ++++----- .../server/config/ApplicationConfigurer.java | 8 +++ .../workflow/server/resolvers/UserIdResolver.java | 71 ++++++++++++++++++++++ .../sdc/workflow/services/annotations/UserId.java | 28 +++++++++ 6 files changed, 133 insertions(+), 31 deletions(-) create mode 100644 workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/resolvers/UserIdResolver.java create mode 100644 workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/annotations/UserId.java (limited to 'workflow-designer-be/src/main/java') diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/ExceptionsHandler.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/ExceptionsHandler.java index f46d19be..642c3438 100644 --- a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/ExceptionsHandler.java +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/ExceptionsHandler.java @@ -51,7 +51,8 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep @RestController public class ExceptionsHandler extends ResponseEntityExceptionHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionsHandler.class); + private static final Logger LOG = LoggerFactory.getLogger(ExceptionsHandler.class); + private static final String LOG_MSG = "Exception was mapped to {} response"; private static final String UNEXPECTED_ERROR_MSG = "Something bad happened. Please contact support with code %s"; private static final RandomStringGenerator CODE_GENERATOR = @@ -66,15 +67,15 @@ public class ExceptionsHandler extends ResponseEntityExceptionHandler { @Override public ResponseEntity handleServletRequestBindingException(ServletRequestBindingException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { - //For missing header exceptions - LOGGER.debug(LOG_MSG, BAD_REQUEST, ex); + LOG.debug(LOG_MSG, BAD_REQUEST, ex); + // Convert Spring-generated binding exceptions into the format of an application message return new ResponseEntity<>(new ErrorResponse(ex.getMessage()), BAD_REQUEST); } @Override protected final ResponseEntity handleMethodArgumentNotValid(final MethodArgumentNotValidException exception, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { - LOGGER.debug(LOG_MSG, BAD_REQUEST, exception); + LOG.debug(LOG_MSG, BAD_REQUEST, exception); String errorMsg = exception.getBindingResult().getFieldErrors().stream() .map(DefaultMessageSourceResolvable::getDefaultMessage).findFirst() .orElse(exception.getMessage()); @@ -83,7 +84,7 @@ public class ExceptionsHandler extends ResponseEntityExceptionHandler { @ExceptionHandler(EntityNotFoundException.class) public final ResponseEntity handleNotFoundException(Exception exception) { - LOGGER.debug(LOG_MSG, NOT_FOUND, exception); + LOG.debug(LOG_MSG, NOT_FOUND, exception); return new ResponseEntity<>(new ErrorResponse(exception.getMessage()), NOT_FOUND); } @@ -92,14 +93,14 @@ public class ExceptionsHandler extends ResponseEntityExceptionHandler { VersionStateModificationException.class, VersionStatusModificationException.class, UniqueValueViolationException.class}) public final ResponseEntity handleUnprocessableEntityException(Exception exception) { - LOGGER.debug(LOG_MSG, UNPROCESSABLE_ENTITY, exception); + LOG.debug(LOG_MSG, UNPROCESSABLE_ENTITY, exception); return new ResponseEntity<>(new ErrorResponse(exception.getMessage()), UNPROCESSABLE_ENTITY); } @ExceptionHandler(Exception.class) public final ResponseEntity handleUnexpectedException(Exception exception) { UnexpectedErrorResponse response = UNEXPECTED_EXCEPTION_MAPPER.apply(exception); - LOGGER.error(response.getMessage(), exception); + LOG.error(response.getMessage(), exception); return new ResponseEntity<>(response, INTERNAL_SERVER_ERROR); } diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java index 8cc1df4e..9010fea4 100644 --- a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java @@ -19,7 +19,6 @@ package org.onap.sdc.workflow.api; import static org.onap.sdc.workflow.api.RestParams.LIMIT; import static org.onap.sdc.workflow.api.RestParams.OFFSET; import static org.onap.sdc.workflow.api.RestParams.SORT; -import static org.onap.sdc.workflow.api.RestParams.USER_ID_HEADER; import static org.onap.sdc.workflow.services.types.PagingConstants.DEFAULT_LIMIT; import static org.onap.sdc.workflow.services.types.PagingConstants.DEFAULT_OFFSET; @@ -33,6 +32,7 @@ import org.onap.sdc.workflow.api.types.Sorting; import org.onap.sdc.workflow.api.types.VersionStatesFormatter; import org.onap.sdc.workflow.services.WorkflowManager; import org.onap.sdc.workflow.services.WorkflowVersionManager; +import org.onap.sdc.workflow.services.annotations.UserId; import org.onap.sdc.workflow.services.types.Page; import org.onap.sdc.workflow.services.types.PagingRequest; import org.onap.sdc.workflow.services.types.RequestSpec; @@ -49,7 +49,6 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -85,14 +84,13 @@ public class WorkflowController { value = "Filter by workflow name")}) public Page list(@ApiIgnore String searchNameFilter, @ApiIgnore VersionStatesFormatter versionStateFilter, @ApiIgnore Paging paging, - @ApiIgnore Sorting sorting, @RequestHeader(USER_ID_HEADER) String user) { + @ApiIgnore Sorting sorting, @UserId String user) { return workflowManager.list(searchNameFilter, versionStateFilter.getVersionStates(), initRequestSpec(paging, sorting)); } @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE) @ApiOperation("Create workflow") - public ResponseEntity create(@Validated @RequestBody Workflow workflow, - @RequestHeader(USER_ID_HEADER) String user) { + public ResponseEntity create(@Validated @RequestBody Workflow workflow, @UserId String user) { return new ResponseEntity<>(workflowManager.create(workflow), HttpStatus.CREATED); } @@ -100,8 +98,7 @@ public class WorkflowController { @ApiOperation("Get workflow") public Workflow get(@PathVariable("workflowId") String workflowId, @ApiParam(value = "Expand workflow data", allowableValues = "versions") - @RequestParam(value = "expand", required = false) String expand, - @RequestHeader(USER_ID_HEADER) String user) { + @RequestParam(value = "expand", required = false) String expand, @UserId String user) { Workflow workflow = new Workflow(); workflow.setId(workflowId); Workflow retrievedWorkflow = workflowManager.get(workflow); @@ -114,7 +111,7 @@ public class WorkflowController { @PutMapping(path = "/{workflowId}", consumes = MediaType.APPLICATION_JSON_VALUE) @ApiOperation("Update workflow") public Workflow update(@RequestBody Workflow workflow, @PathVariable("workflowId") String workflowId, - @RequestHeader(USER_ID_HEADER) String user) { + @UserId String user) { workflow.setId(workflowId); workflowManager.update(workflow); return workflow; diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java index f869ce05..67bea00c 100644 --- a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java @@ -16,8 +16,6 @@ package org.onap.sdc.workflow.api; -import static org.onap.sdc.workflow.api.RestParams.USER_ID_HEADER; - import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -28,6 +26,7 @@ import org.onap.sdc.workflow.api.types.VersionStatesFormatter; import org.onap.sdc.workflow.api.types.dto.ArtifactDeliveriesRequestDto; import org.onap.sdc.workflow.persistence.types.ArtifactEntity; import org.onap.sdc.workflow.services.WorkflowVersionManager; +import org.onap.sdc.workflow.services.annotations.UserId; import org.onap.sdc.workflow.services.types.WorkflowVersion; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -43,7 +42,6 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -60,9 +58,9 @@ public class WorkflowVersionController { @Autowired public WorkflowVersionController(@Qualifier("workflowVersionManager") WorkflowVersionManager workflowVersionManager, - @Qualifier("ArtifactAssociationHandler") ArtifactAssociationService artifatcAssociationHandler) { + @Qualifier("ArtifactAssociationHandler") ArtifactAssociationService artifactAssociationHandler) { this.workflowVersionManager = workflowVersionManager; - this.associationHandler = artifatcAssociationHandler; + this.associationHandler = artifactAssociationHandler; } @GetMapping @@ -70,7 +68,7 @@ public class WorkflowVersionController { @ApiImplicitParam(name = "state", dataType = "string", paramType = "query", allowableValues = "DRAFT,CERTIFIED", value = "Filter by state") public CollectionResponse list(@PathVariable("workflowId") String workflowId, - @ApiIgnore VersionStatesFormatter stateFilter, @RequestHeader(USER_ID_HEADER) String user) { + @ApiIgnore VersionStatesFormatter stateFilter, @UserId String user) { return new CollectionResponse<>(workflowVersionManager.list(workflowId, stateFilter.getVersionStates())); } @@ -78,8 +76,7 @@ public class WorkflowVersionController { @ApiOperation("Create workflow version") public ResponseEntity create(@RequestBody @Valid WorkflowVersion version, @PathVariable("workflowId") String workflowId, - @RequestParam(value = "baseVersionId", required = false) String baseVersionId, - @RequestHeader(USER_ID_HEADER) String user) { + @RequestParam(value = "baseVersionId", required = false) String baseVersionId, @UserId String user) { WorkflowVersion createdVersion = workflowVersionManager.create(workflowId, baseVersionId, version); return new ResponseEntity<>(createdVersion, HttpStatus.CREATED); } @@ -87,14 +84,14 @@ public class WorkflowVersionController { @GetMapping("/{versionId}") @ApiOperation("Get workflow version") public WorkflowVersion get(@PathVariable("workflowId") String workflowId, - @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER) String user) { + @PathVariable("versionId") String versionId, @UserId String user) { return workflowVersionManager.get(workflowId, versionId); } @PutMapping("/{versionId}") @ApiOperation("Update workflow version") public void update(@RequestBody @Valid WorkflowVersion version, @PathVariable("workflowId") String workflowId, - @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER) String user) { + @PathVariable("versionId") String versionId, @UserId String user) { version.setId(versionId); workflowVersionManager.update(workflowId, version); } @@ -102,7 +99,7 @@ public class WorkflowVersionController { @GetMapping("/{versionId}/state") @ApiOperation("Get workflow version state") public VersionStateDto getState(@PathVariable("workflowId") String workflowId, - @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER) String user) { + @PathVariable("versionId") String versionId, @UserId String user) { return new VersionStateDto(workflowVersionManager.getState(workflowId, versionId)); } @@ -110,7 +107,7 @@ public class WorkflowVersionController { @ApiOperation("Update workflow version state") public VersionStateDto updateState(@RequestBody VersionStateDto state, @PathVariable("workflowId") String workflowId, @PathVariable("versionId") String versionId, - @RequestHeader(USER_ID_HEADER) String user) { + @UserId String user) { workflowVersionManager.updateState(workflowId, versionId, state.getName()); return new VersionStateDto(state.getName()); } @@ -119,7 +116,7 @@ public class WorkflowVersionController { @ApiOperation("upload of artifact to VF operation workflow") public ResponseEntity artifactDeliveries(@RequestBody ArtifactDeliveriesRequestDto deliveriesRequestDto, @PathVariable("workflowId") String workflowId, @PathVariable("versionId") String versionId, - @RequestHeader(USER_ID_HEADER) String user) { + @UserId String user) { return associationHandler .execute(user, deliveriesRequestDto, workflowVersionManager.getArtifact(workflowId, versionId)); } @@ -127,14 +124,14 @@ public class WorkflowVersionController { @PutMapping("/{versionId}/artifact") @ApiOperation("Create/update artifact of a version") public void uploadArtifact(@RequestBody MultipartFile fileToUpload, @PathVariable("workflowId") String workflowId, - @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER) String user) { + @PathVariable("versionId") String versionId, @UserId String user) { workflowVersionManager.uploadArtifact(workflowId, versionId, fileToUpload); } @GetMapping("/{versionId}/artifact") @ApiOperation("Download workflow version artifact") public ResponseEntity getArtifact(@PathVariable("workflowId") String workflowId, - @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER) String user) { + @PathVariable("versionId") String versionId, @UserId String user) { ArtifactEntity artifact = workflowVersionManager.getArtifact(workflowId, versionId); return ResponseEntity.ok() @@ -146,7 +143,7 @@ public class WorkflowVersionController { @DeleteMapping("/{versionId}/artifact") @ApiOperation("Delete workflow version artifact") public void deleteArtifact(@PathVariable("workflowId") String workflowId, - @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER) String user) { + @PathVariable("versionId") String versionId, @UserId String user) { workflowVersionManager.deleteArtifact(workflowId, versionId); } } diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/ApplicationConfigurer.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/ApplicationConfigurer.java index e631a12c..15df33f8 100644 --- a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/ApplicationConfigurer.java +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/ApplicationConfigurer.java @@ -16,9 +16,12 @@ package org.onap.sdc.workflow.server.config; +import java.util.List; +import org.onap.sdc.workflow.server.resolvers.UserIdResolver; import org.openecomp.sdc.logging.servlet.spring.LoggingInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -32,4 +35,9 @@ public class ApplicationConfigurer implements WebMvcConfigurer { public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loggingInterceptor); } + + @Override + public void addArgumentResolvers(List argumentResolvers) { + argumentResolvers.add(new UserIdResolver()); + } } diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/resolvers/UserIdResolver.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/resolvers/UserIdResolver.java new file mode 100644 index 00000000..80cb07a8 --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/resolvers/UserIdResolver.java @@ -0,0 +1,71 @@ +/* + * Copyright © 2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.sdc.workflow.server.resolvers; + +import static org.onap.sdc.workflow.api.RestParams.USER_ID_HEADER; + +import java.util.Objects; +import javax.servlet.http.HttpServletRequest; +import org.onap.sdc.workflow.services.annotations.UserId; +import org.springframework.core.MethodParameter; +import org.springframework.web.bind.ServletRequestBindingException; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +/** + * Resolves a user ID from an HTTP header and injects it into a parameter of type {@link String} annotated with {@link + * UserId}. The header is considered mandatory, therefore an error is returned to the client if no user ID was sent. + * + * @author evitaliy + * @since 21 Aug 2018 + */ +public class UserIdResolver implements HandlerMethodArgumentResolver { + + private static final String ERROR_MESSAGE = "Missing mandatory request header '" + USER_ID_HEADER + "'"; + + @Override + public boolean supportsParameter(MethodParameter methodParameter) { + + if (!methodParameter.hasParameterAnnotation(UserId.class)) { + return false; + } + + Class parameterType = methodParameter.getParameterType(); + if (!parameterType.equals(String.class)) { + throw new IllegalStateException("Cannot inject user ID into a parameter of type " + + parameterType.getTypeName()); + } + + return true; + } + + @Override + public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, + NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) + throws ServletRequestBindingException { + + HttpServletRequest httpServletRequest = nativeWebRequest.getNativeRequest(HttpServletRequest.class); + String userHeader = Objects.requireNonNull(httpServletRequest).getHeader(USER_ID_HEADER); + if (userHeader == null) { + throw new ServletRequestBindingException(ERROR_MESSAGE); + } + + return userHeader; + } +} \ No newline at end of file diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/annotations/UserId.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/annotations/UserId.java new file mode 100644 index 00000000..90a1a763 --- /dev/null +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/annotations/UserId.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.sdc.workflow.services.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface UserId { } -- cgit 1.2.3-korg