Skip to content

Validate reusable parameter #39

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

Merged
merged 3 commits into from
Apr 20, 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
29 changes: 0 additions & 29 deletions src/main/java/com/apiflows/model/Parameter.java
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;
}

}
93 changes: 60 additions & 33 deletions src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,14 @@ List<String> 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");
}
}
Expand Down Expand Up @@ -208,12 +211,12 @@ List<String> validateStep(Step step, String workflowId ) {
return errors;
}

List<String> validateParameter(Parameter parameter, String workflowId, String componentName ) {
List<String> validateParameter(Parameter parameter, String workflowId, String componentName) {
List<String> 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 + "]";
Expand All @@ -222,37 +225,57 @@ List<String> validateParameter(Parameter parameter, String workflowId, String co

List<String> 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<String> validateReusableParameter(Parameter parameter, String workflowId, String componentName ) {

String source;

if(workflowId != null) {
source = "Workflow[" + workflowId + "]";
} else {
source = "Component[" + componentName + "]";
}

List<String> 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;
}
Expand Down Expand Up @@ -561,4 +584,8 @@ public boolean isValidJsonPointer(String jsonPointerString) {
return ret;
}

boolean isRuntimeExpression(String name) {
return name.startsWith("$");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ List<Operation> getOperations(String openapi) {

ParseOptions options = new ParseOptions();
options.setResolve(true);

SwaggerParseResult parseResult = null;

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand All @@ -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() {
Expand Down
45 changes: 16 additions & 29 deletions src/test/resources/1.0.0/pet-coupons.workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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