From 0978e3c9207f50067a89e93859d648149ba6164f Mon Sep 17 00:00:00 2001 From: Beppe Catanese Date: Sat, 20 Apr 2024 12:30:08 +0200 Subject: [PATCH 1/3] Remove unused code --- .../java/com/apiflows/model/Parameter.java | 29 ------------------- .../parser/source/OperationBinder.java | 1 - 2 files changed, 30 deletions(-) diff --git a/src/main/java/com/apiflows/model/Parameter.java b/src/main/java/com/apiflows/model/Parameter.java index 3d4b39c..c3ab864 100644 --- a/src/main/java/com/apiflows/model/Parameter.java +++ b/src/main/java/com/apiflows/model/Parameter.java @@ -7,9 +7,7 @@ public class Parameter { private String name; private String in; private String value; - private String target; private String style; - private String $ref = null; @JsonProperty("name") public String getName() { @@ -38,15 +36,6 @@ public void setValue(String value) { this.value = value; } - @JsonProperty("target") - public String getTarget() { - return target; - } - - public void setTarget(String target) { - this.target = target; - } - public String getStyle() { return style; } @@ -55,14 +44,6 @@ public void setStyle(String style) { this.style = style; } - public String get$ref() { - return $ref; - } - - public void set$ref(String $ref) { - this.$ref = $ref; - } - public Parameter name(String name) { this.name = name; return this; @@ -78,19 +59,9 @@ public Parameter value(String value) { return this; } - public Parameter target(String target) { - this.target = target; - return this; - } - public Parameter style(String style) { this.style = style; return this; } - public Parameter $ref(String $ref) { - this.$ref = $ref; - return this; - } - } diff --git a/src/main/java/com/apiflows/parser/source/OperationBinder.java b/src/main/java/com/apiflows/parser/source/OperationBinder.java index d5bfeb2..983434b 100644 --- a/src/main/java/com/apiflows/parser/source/OperationBinder.java +++ b/src/main/java/com/apiflows/parser/source/OperationBinder.java @@ -58,7 +58,6 @@ List getOperations(String openapi) { ParseOptions options = new ParseOptions(); options.setResolve(true); - SwaggerParseResult parseResult = null; try { From 8086474e0834837c1ed1ba30e0c2ec03663edfd0 Mon Sep 17 00:00:00 2001 From: Beppe Catanese Date: Sat, 20 Apr 2024 12:30:31 +0200 Subject: [PATCH 2/3] Add validation of Reusable Parameter Object --- .../parser/OpenAPIWorkflowValidator.java | 93 ++++++++++++------- .../parser/OpenAPIWorkflowValidatorTest.java | 23 ++++- 2 files changed, 82 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java b/src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java index d016a0f..d51a64a 100644 --- a/src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java +++ b/src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java @@ -171,11 +171,14 @@ List validateStep(Step step, String workflowId ) { if(step.getParameters() != null) { for(Parameter parameter : step.getParameters()) { - errors.addAll(validateParameter(parameter, workflowId, null)); - - if(step.getWorkflowId() != null) { - // when the step in context specifies a workflowId the parameter IN must be defined - if(parameter.getIn() == null) { + if(isRuntimeExpression(parameter.getName())) { + errors.addAll(validateReusableParameter(parameter, workflowId, null)); + } else { + errors.addAll(validateParameter(parameter, workflowId, null)); + } + if(step.getWorkflowId() == null) { + // when the step in context is NOT a workflowId the parameter IN must be defined + if(!isRuntimeExpression(parameter.getName()) && parameter.getIn() == null) { errors.add("'Workflow[" + workflowId + "]' parameter IN must be defined"); } } @@ -208,12 +211,12 @@ List validateStep(Step step, String workflowId ) { return errors; } - List validateParameter(Parameter parameter, String workflowId, String componentName ) { + List validateParameter(Parameter parameter, String workflowId, String componentName) { List SUPPORTED_VALUES = Arrays.asList("path", "query", "header", "cookie", "body", "workflow"); String source; - if(workflowId != null) { + if (workflowId != null) { source = "Workflow[" + workflowId + "]"; } else { source = "Component[" + componentName + "]"; @@ -222,37 +225,57 @@ List validateParameter(Parameter parameter, String workflowId, String co List errors = new ArrayList<>(); - if(parameter.get$ref() != null) { - // Reference object - // check is URI - } else { - // Parameter object - String name = parameter.getName(); + // Parameter object + String name = parameter.getName(); - if(name == null) { - errors.add(source + " parameter has no name"); - } - if(parameter.getIn() != null) { - if(!SUPPORTED_VALUES.contains(parameter.getIn())) { - if(name != null) { - errors.add(source + "parameter " + name + " type (" + parameter.getIn() + ") is invalid"); - } else { - errors.add(source + " parameter type (" + parameter.getIn() + ") is invalid"); - } - } - } - if(parameter.getValue() == null) { - if(name != null) { - errors.add(source + " parameter " + name + " has no value"); + if (name == null) { + errors.add(source + " parameter has no name"); + } + if (parameter.getIn() != null) { + if (!SUPPORTED_VALUES.contains(parameter.getIn())) { + if (name != null) { + errors.add(source + "parameter " + name + " in (" + parameter.getIn() + ") is invalid"); } else { - errors.add(source + " parameter has no value"); + errors.add(source + " parameter in (" + parameter.getIn() + ") is invalid"); } } - if(parameter.getTarget() != null) { - if(!isValidJsonPointer(parameter.getTarget())) { - errors.add(source + " parameter " + name + " target is not a valid Json Pointer"); - } + } + if (parameter.getValue() == null) { + if (name != null) { + errors.add(source + " parameter " + name + " has no value"); + } else { + errors.add(source + " parameter has no value"); + } + } + if(isRuntimeExpression(parameter.getName())) { + errors.add(source + " parameter " + name + " is a Reusable Parameter object"); + } + + return errors; + } + + List validateReusableParameter(Parameter parameter, String workflowId, String componentName ) { + + String source; + + if(workflowId != null) { + source = "Workflow[" + workflowId + "]"; + } else { + source = "Component[" + componentName + "]"; + } + + List errors = new ArrayList<>(); + + if(isRuntimeExpression(parameter.getName())) { + // Reusable Parameter object + String name = parameter.getName(); + + if(parameter.getIn() != null) { + errors.add(source + "parameter " + name + " in (" + parameter.getIn() + ") should not be provided for a Reusable Parameter Object"); } + + // TODO: check reusable parameter exists in Components + } return errors; } @@ -561,4 +584,8 @@ public boolean isValidJsonPointer(String jsonPointerString) { return ret; } + boolean isRuntimeExpression(String name) { + return name.startsWith("$"); + } + } diff --git a/src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java b/src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java index 3175a86..22f85b1 100644 --- a/src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java +++ b/src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java @@ -188,7 +188,7 @@ void validateStepWithoutInAttribute() { Step step = new Step() .stepId("step-one") .description("First step in the workflow") - .workflowId("workflow-id-2"); + .operationId("op-id-2"); step.addParameter(new Parameter() .name("param") .value("value")); @@ -198,6 +198,27 @@ void validateStepWithoutInAttribute() { assertEquals(1, validator.validateStep(step, worklowId).size()); } + @Test + void validateReusableParameter() { + Parameter parameter = new Parameter() + .name("$components.parameters.page") + .value("1"); + String worklowId = "q1"; + + assertEquals(0, validator.validateReusableParameter(parameter, worklowId, null).size()); + } + + @Test + void validateReusableParameterWithInAttribute() { + Parameter parameter = new Parameter() + .name("$components.parameters.page") + .value("1") + .in("query"); + String worklowId = "q1"; + + // error: must not define IN attribute + assertEquals(1, validator.validateReusableParameter(parameter, worklowId, null).size()); + } @Test void validateParameter() { From 39241bdbed2fcfc972e4d7cae306bd3dd271c45d Mon Sep 17 00:00:00 2001 From: Beppe Catanese Date: Sat, 20 Apr 2024 12:30:50 +0200 Subject: [PATCH 3/3] Update Petstore sample file --- .../resources/1.0.0/pet-coupons.workflow.yaml | 45 +++++++------------ 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/src/test/resources/1.0.0/pet-coupons.workflow.yaml b/src/test/resources/1.0.0/pet-coupons.workflow.yaml index 612f8fa..73a4e39 100644 --- a/src/test/resources/1.0.0/pet-coupons.workflow.yaml +++ b/src/test/resources/1.0.0/pet-coupons.workflow.yaml @@ -47,10 +47,8 @@ workflows: workflowId: place-order parameters: - name: pet_id - in: body value: $steps.find-pet.outputs.my_pet_id - name: coupon_code - in: body value: $steps.find-coupons.outputs.my_coupon_code successCriteria: - condition: $statusCode == 200 @@ -72,9 +70,9 @@ workflows: - name: status in: query value: "available" - - $ref: '#/components/parameters/page' + - name: $components.parameters.page value: 1 - - $ref: '#/components/parameters/pageSize' + - name: $components.parameters.pageSize value: 10 successCriteria: - condition: $statusCode == 200 @@ -84,7 +82,6 @@ workflows: workflowId: place-order parameters: - name: pet_id - in: body value: $steps.find-pet.outputs.my_pet_id successCriteria: - condition: $statusCode == 200 @@ -113,26 +110,14 @@ workflows: steps: - stepId: place-order operationId: placeOrder - parameters: - - name: pet_id - in: body - target: /petId - value: $inputs.pet_id - - name: coupon_code - in: body - target: /couponCode - value: $inputs.coupon_code - - name: quantity - in: body - value: $inputs.quantity - - name: status - in: body - target: /status - value: "placed" - - name: complete - in: body - target: /complete - value: false + requestBody: + contentType: application/json + payload: + petId: $inputs.pet_id + quantity: $inputs.quantity + couponCode: $inputs.coupon_code + status: placed + complete: false successCriteria: - condition: $statusCode == 200 outputs: @@ -161,8 +146,10 @@ components: description: Indicates the domain name of the store where the customer is browsing or buying pets, e.g. "pets.example.com" or "pets.example.co.uk". parameters: page: - type: integer - format: int32 + name: page + in: query + value: 1 pageSize: - type: integer - format: int32 + name: pageSize + in: query + value: 100 \ No newline at end of file