From 3cc535fd0caae41f2322052ac5a8b1c17d5ea98e Mon Sep 17 00:00:00 2001 From: ayalaben Date: Tue, 24 Jul 2018 12:16:38 +0300 Subject: Workflow Version Validation Change-Id: Ibb72aeed314f39f4c3c29f270a3fe5982d399ea5 Issue-ID: SDC-1518 Signed-off-by: ayalaben --- .../sdc/workflow/SpringBootWebApplication.java | 1 + .../workflow/api/WorkflowVersionController.java | 18 +++++-- .../CustomizedResponseEntityExceptionHandler.java | 13 +++++ .../api/validator/WorkflowVersionValidator.java | 61 ++++++++++++++++++++++ .../persistence/types/ParameterEntity.java | 6 +++ .../sdc/workflow/persistence/types/Workflow.java | 7 ++- 6 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/validator/WorkflowVersionValidator.java diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/SpringBootWebApplication.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/SpringBootWebApplication.java index d14ad095..0feafd2a 100644 --- a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/SpringBootWebApplication.java +++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/SpringBootWebApplication.java @@ -33,4 +33,5 @@ public class SpringBootWebApplication { public ConfigurableServletWebServerFactory webServerFactory() { return new JettyServletWebServerFactory(); } + } diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java index d5b94a1b..91995bd0 100644 --- a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java +++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java @@ -35,8 +35,12 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.validation.Validator; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -53,11 +57,19 @@ import org.springframework.web.multipart.MultipartFile; public class WorkflowVersionController { private final WorkflowVersionManager workflowVersionManager; + private Validator validator; + + @InitBinder + private void initBinder(WebDataBinder binder) { + binder.addValidators(validator); + } @Autowired public WorkflowVersionController( - @Qualifier("workflowVersionManager") WorkflowVersionManager workflowVersionManager) { + @Qualifier("workflowVersionManager") WorkflowVersionManager workflowVersionManager, + @Qualifier("workflowVersionValidator") Validator validator ) { this.workflowVersionManager = workflowVersionManager; + this.validator = validator; } @GetMapping @@ -71,7 +83,7 @@ public class WorkflowVersionController { @PostMapping @ApiOperation("Create workflow version") - public ResponseEntity create(@RequestBody WorkflowVersion version, + public ResponseEntity create(@RequestBody @Validated WorkflowVersion version, @PathVariable("workflowId") String workflowId, @RequestParam(value = "baseVersionId", required = false) String baseVersionId, @RequestHeader(USER_ID_HEADER_PARAM) String user) { @@ -88,7 +100,7 @@ public class WorkflowVersionController { @PutMapping("/{versionId}") @ApiOperation("Update workflow version") - public void update(@RequestBody WorkflowVersion version, @PathVariable("workflowId") String workflowId, + public void update(@RequestBody @Validated WorkflowVersion version, @PathVariable("workflowId") String workflowId, @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER_PARAM) String user) { version.setId(versionId); workflowVersionManager.update(workflowId, version); diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/exceptionshandlers/CustomizedResponseEntityExceptionHandler.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/exceptionshandlers/CustomizedResponseEntityExceptionHandler.java index c8cae361..ca6111df 100644 --- a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/exceptionshandlers/CustomizedResponseEntityExceptionHandler.java +++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/exceptionshandlers/CustomizedResponseEntityExceptionHandler.java @@ -31,6 +31,8 @@ import org.onap.sdc.workflow.services.exceptions.VersionStateModificationExcepti import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -59,6 +61,17 @@ public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExce return new ResponseEntity<>(exception.getMessage(), BAD_REQUEST); } + //For workflowVersionValidator exception + @Override + protected final ResponseEntity handleMethodArgumentNotValid(final MethodArgumentNotValidException e, + final HttpHeaders headers, + final HttpStatus status, + final WebRequest request) { + + FieldError result = e.getBindingResult().getFieldError(); + return new ResponseEntity<>(result.getDefaultMessage(), BAD_REQUEST); + } + //For missing header exceptions @Override public ResponseEntity handleServletRequestBindingException(ServletRequestBindingException ex, diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/validator/WorkflowVersionValidator.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/validator/WorkflowVersionValidator.java new file mode 100644 index 00000000..03101042 --- /dev/null +++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/validator/WorkflowVersionValidator.java @@ -0,0 +1,61 @@ +/* + * 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.api.validator; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import org.onap.sdc.workflow.persistence.types.ParameterEntity; +import org.onap.sdc.workflow.persistence.types.WorkflowVersion; +import org.springframework.stereotype.Component; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + + +@Component("workflowVersionValidator") +public class WorkflowVersionValidator implements Validator{ + + @Override + public boolean supports(Class aClass) { + return WorkflowVersion.class.equals(aClass); + } + + @Override + public void validate(Object o, Errors errors) { + + WorkflowVersion workflowVersion = (WorkflowVersion) o; + Collection inputs = workflowVersion.getInputs(); + Collection outputs = workflowVersion.getOutputs(); + + if(containsDuplicates(inputs)){ + errors.rejectValue("inputs", "duplicateName", new Object[] {inputs}, "Input name must be unique"); + } + + if(containsDuplicates(outputs)){ + errors.rejectValue("outputs", "duplicateName", new Object[] {outputs}, "Output name must be unique"); + } + } + + private boolean containsDuplicates(Collection parameters){ + if(Objects.isNull(parameters) || parameters.size() < 2 ) { + return false; + } + Set testSet = new HashSet<>(); + return parameters.stream().anyMatch(s -> !testSet.add(s.getName())); + } +} diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/ParameterEntity.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/ParameterEntity.java index 4b57ba71..7c957d85 100644 --- a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/ParameterEntity.java +++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/ParameterEntity.java @@ -16,13 +16,19 @@ package org.onap.sdc.workflow.persistence.types; +import javax.validation.constraints.Pattern; import lombok.Data; +import javax.validation.constraints.NotNull; @Data public class ParameterEntity { private String id; + @NotNull(message = "Parameter name may not be null") + @Pattern(regexp = "[A-Za-z0-9_]*", message = "The field must contain only letters, digits and underscores") private String name; + @NotNull private ParameterType type; + @NotNull private boolean mandatory; } diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/Workflow.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/Workflow.java index 31f949fc..72e62778 100644 --- a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/Workflow.java +++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/persistence/types/Workflow.java @@ -20,13 +20,18 @@ package org.onap.sdc.workflow.persistence.types; import java.util.Collection; import java.util.Set; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; import lombok.Data; + @Data public class Workflow { private String id; - @NotNull + @NotNull(message = "Workflow name may not be null") + @Size(min = 6, max = 30, message = "The field must be at least 6 characters, and less than 30 characters") + @Pattern(regexp = "[A-Za-z0-9_]*", message = "The field must contain only letters, digits and underscores") private String name; private String description; private Set versionStates; -- cgit 1.2.3-korg