Skip to content
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

XRDDEV-2520: Support for OpenApi 3.1 for client services #1870

Merged
merged 3 commits into from
Nov 29, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@
@Component
public class OpenApiParser {

private static final String SUPPORTED_OPENAPI_MINOR_VERSION = "3.0";
private static final String SUPPORTED_OPENAPI_MINOR_VERSION_3_0 = "3.0";
private static final String SUPPORTED_OPENAPI_VERSION_3_1_0 = "3.1.0";
private static final int BUF_SIZE = 8192;
private static final long MAX_DESCRIPTION_SIZE = 10 * 1024 * 1024;
private static final ObjectMapper YAML_MAPPER = new ObjectMapper(new YAMLFactory());
Expand All @@ -72,11 +73,11 @@ public class OpenApiParser {
* Parse openapi3 description
*
* @return OpenApiParser.Result
* @throws ParsingException if parsing cannot be done
* @throws ParsingException if parsing cannot be done
* @throws UnsupportedOpenApiVersionException if the openapi version is not supported
*/
public Result parse(String urlString) throws ParsingException, UnsupportedOpenApiVersionException {
URI openApiUrl = null;
URI openApiUrl;
try {
openApiUrl = new URI(urlString);
} catch (URISyntaxException e) {
Expand Down Expand Up @@ -127,13 +128,18 @@ public Result parse(String urlString) throws ParsingException, UnsupportedOpenAp

private void verifyOpenApiVersion(JsonNode node) throws UnsupportedOpenApiVersionException {
final String openapiVersion = node.get("openapi").asText();
if (openapiVersion != null && !openapiVersion.startsWith(SUPPORTED_OPENAPI_MINOR_VERSION)) {
if (openapiVersion != null && !versionSupported(openapiVersion)) {
String errorMsg = String.format("OpenAPI version %s not supported", openapiVersion);
throw new UnsupportedOpenApiVersionException(errorMsg,
new ErrorDeviation(ERROR_UNSUPPORTED_OPENAPI_VERSION));
}
}

private boolean versionSupported(String version) {
return version.startsWith(SUPPORTED_OPENAPI_MINOR_VERSION_3_0)
|| version.equals(SUPPORTED_OPENAPI_VERSION_3_1_0);
}

private void validate(SwaggerParseResult result, URI openApiUrl) throws ParsingException {
if (result == null || result.getOpenAPI() == null) {
throw new ParsingException("Unable to parse OpenAPI description from " + openApiUrl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@

import java.net.URL;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

/**
* Unit tests for OpenAPIParser
*/
Expand All @@ -39,24 +42,42 @@ public class OpenApiParserTest {
public void shouldParseOpenApiYaml() throws OpenApiParser.ParsingException, UnsupportedOpenApiVersionException {
URL url = getClass().getResource("/openapiparser/valid.yaml");
final OpenApiParser.Result result = new TestOpenApiParser().parse(url.toString());
Assert.assertFalse(result.hasWarnings());
Assert.assertEquals("https://example.org/api", result.getBaseUrl());
assertFalse(result.hasWarnings());
assertEquals("https://example.org/api", result.getBaseUrl());
}

@Test
public void shouldParseOpenApi31Yaml() throws OpenApiParser.ParsingException, UnsupportedOpenApiVersionException {
URL url = getClass().getResource("/openapiparser/v310.yaml");
final OpenApiParser.Result result = new TestOpenApiParser().parse(url.toString());
assertFalse(result.hasWarnings());
assertEquals("https://example.org/api", result.getBaseUrl());
assertEquals(3, result.getOperations().size());
}

@Test
public void shouldHaveWarnings() throws OpenApiParser.ParsingException, UnsupportedOpenApiVersionException {
URL url = getClass().getResource("/openapiparser/warnings.yml");
final OpenApiParser.Result result = new TestOpenApiParser().parse(url.toString());
Assert.assertTrue(result.hasWarnings());
Assert.assertEquals("https://{securityserver}/r1", result.getBaseUrl());
assertEquals("https://{securityserver}/r1", result.getBaseUrl());
}

@Test
public void shouldParseOpenApiJson() throws OpenApiParser.ParsingException, UnsupportedOpenApiVersionException {
URL url = getClass().getResource("/openapiparser/valid.json");
final OpenApiParser.Result result = new TestOpenApiParser().parse(url.toString());
Assert.assertFalse(result.hasWarnings());
Assert.assertEquals("https://example.org/api", result.getBaseUrl());
assertFalse(result.hasWarnings());
assertEquals("https://example.org/api", result.getBaseUrl());
}

@Test
public void shouldParseOpenApi31Json() throws OpenApiParser.ParsingException, UnsupportedOpenApiVersionException {
URL url = getClass().getResource("/openapiparser/v310.json");
final OpenApiParser.Result result = new TestOpenApiParser().parse(url.toString());
assertFalse(result.hasWarnings());
assertEquals("https://example.org/api", result.getBaseUrl());
assertEquals(3, result.getOperations().size());
}

@Test(expected = OpenApiParser.ParsingException.class)
Expand All @@ -76,14 +97,14 @@ public void shouldFailIfDuplicateEndpoint() throws OpenApiParser.ParsingExceptio
@Test(expected = UnsupportedOpenApiVersionException.class)
public void shouldFailOnUnsupportedOpenApiVersionYaml() throws OpenApiParser.ParsingException,
UnsupportedOpenApiVersionException {
URL url = getClass().getResource("/openapiparser/v310.yaml");
URL url = getClass().getResource("/openapiparser/invalid_version.yaml");
new TestOpenApiParser().parse(url.toString());
}

@Test(expected = UnsupportedOpenApiVersionException.class)
public void shouldFailOnUnsupportedOpenApiVersionJson() throws OpenApiParser.ParsingException,
UnsupportedOpenApiVersionException {
URL url = getClass().getResource("/openapiparser/v310.json");
URL url = getClass().getResource("/openapiparser/invalid_version.json");
new TestOpenApiParser().parse(url.toString());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"openapi": "3.2.0",
"info": {
"version": "1.0",
"title": "Test"
},
"servers": [
{
"url": "https://example.org/api",
"description": "test"
}
],
"paths": {
"/test": {
"post": {
"requestBody": {
"content": {
"text/plain": {
"schema": {
"exclusiveMaximum": 50,
"exclusiveMinimum": 1.22,
"type": "number",
"contentEncoding": "double",
"contentMediaType": "text/plain"
},
"example": 3
}
},
"required": true
},
"responses": {
"200": {
"description": "OK"
}
},
"summary": "post"
},
"get": {
"responses": {
"200": {
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
},
"description": "OK"
}
},
"summary": "get"
}
},
"/file": {
"post": {
"summary": "file upload",
"requestBody": {
"content": {
"application/octet-stream": {}
}
},
"responses": {
"201": {
"description": "OK"
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
openapi: 3.1.1
servers:
- description: test
url: https://example.org/api
info:
title: Test
version: "1.0"
paths:
/test:
get:
summary: get
responses:
'200':
description: OK
content:
text/plain:
schema:
type: string
post:
summary: post
requestBody:
content:
text/plain:
schema:
exclusiveMaximum: 50
exclusiveMinimum: 1.22
type: number
contentEncoding: double
contentMediaType: text/plain
example: 3
required: true
responses:
'200':
description: OK
/file:
post:
summary: file upload
requestBody:
content:
application/octet-stream: { }
responses:
'201':
description: OK
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"openapi": "3.1.0",
"info": {
"version": 1.0,
"version": "1.0",
"title": "Test"
},
"servers": [
Expand All @@ -17,10 +17,16 @@
"content": {
"text/plain": {
"schema": {
"type": "string"
}
"exclusiveMaximum": 50,
"exclusiveMinimum": 1.22,
"type": "number",
"contentEncoding": "double",
"contentMediaType": "text/plain"
},
"example": 3
}
}
},
"required": true
},
"responses": {
"200": {
Expand All @@ -43,21 +49,21 @@
}
},
"summary": "get"
},
"get": {
}
},
"/file": {
"post": {
"summary": "file upload",
"requestBody": {
"content": {
"application/octet-stream": {}
}
},
"responses": {
"200": {
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
},
"201": {
"description": "OK"
}
},
"summary": "get"
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ servers:
url: https://example.org/api
info:
title: Test
version: 1.0
version: "1.0"
paths:
/test:
get:
Expand All @@ -23,7 +23,22 @@ paths:
content:
text/plain:
schema:
type: string
exclusiveMaximum: 50
exclusiveMinimum: 1.22
type: number
contentEncoding: double
contentMediaType: text/plain
example: 3
required: true
responses:
'200':
description: OK
/file:
post:
summary: file upload
requestBody:
content:
application/octet-stream: { }
responses:
'201':
description: OK
2 changes: 1 addition & 1 deletion src/security-server/admin-service/ui/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@
"timestamping_service_not_found": "Timestamping service not found",
"token_not_active": "Token is not active",
"token_not_found": "Token not found",
"unsupported_openapi_version": "Unsupported OpenAPI version. Only versions 3.0.x are currently supported.",
"unsupported_openapi_version": "Unsupported OpenAPI version. Only versions 3.0.x and 3.1.0 are currently supported.",
"url_already_exists": "URL already exists",
"validation_failure": "Validation failure",
"warnings_detected": "Warnings detected",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,23 @@ Feature: 0540 - SS: Client OpenApi REST services
And Services sub-tab is selected
When Service "OPENAPI3 (http://mock-server:1080/test-services/testopenapi11.yaml)" is deleted
Then Service "OPENAPI3 (http://mock-server:1080/test-services/testopenapi11.yaml)" is missing in the list

Scenario: Client service with openApi 3.1 json is added
Given Client "TestService" is opened
And Services sub-tab is selected
When Rest service dialog is opened and OpenApi spec is set to "http://mock-server:1080/test-services/testopenapi_v310.json" and service code "testOas31"
Then Dialog data is saved and success message "OpenApi3 service added" is shown
And Service "OPENAPI3 (http://mock-server:1080/test-services/testopenapi_v310.json)" is present in the list
When Service "OPENAPI3 (http://mock-server:1080/test-services/testopenapi_v310.json)" is expanded
And Service with code "testOas31" is opened
Then Service URL is "https://example.org/api", timeout is 60 and tls certificate verification is checked
When Service endpoints view is opened
Then Service endpoint with HTTP request method "GET" and path "/test" is present in the list
Then Service endpoint with HTTP request method "POST" and path "/test" is present in the list
Then Service endpoint with HTTP request method "POST" and path "/file" is present in the list

Scenario: Adding service with invalid openApi version fails
Given Client "TestService" is opened
And Services sub-tab is selected
When Rest service dialog is opened and OpenApi spec is set to "http://mock-server:1080/test-services/testopenapi_invalid_version.yaml" and service code "testOas31x"
Then Dialog data is saved and error message "Unsupported OpenAPI version. Only versions 3.0.x and 3.1.0 are currently supported." is shown
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ Feature: 0570 - SS: Client Service clients
When Service clients add subject wizard is opened
And Service clients wizard is filtered to "Test" with 5 results and subject "CS:ORG:2908758-4:Management" is selected
And Service clients subject "CS:GOV:0245437-2:test-consumer" is not selectable
And Service clients wizard services step is filtered to "" with 4 results and service "s3c2" is selected
And Service clients wizard services step is filtered to "" with 5 results and service "s3c2" is selected

And Service clients add subject wizard is opened
And Service clients wizard is filtered to "own" with 1 results and subject "CS:security-server-owners" is selected
And Service clients wizard services step is filtered to "" with 4 results and service "testOp1" is selected
And Service clients wizard services step is filtered to "" with 5 results and service "testOp1" is selected
Then Service clients list is as follows
| $memberName | $id |
| Security Server owners | CS:security-server-owners |
Expand Down
Loading
Loading