This is an automated email from the ASF dual-hosted git repository.
grv pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/ofbiz-plugins.git The following commit(s) were added to refs/heads/trunk by this push: new 310a2a5 Improved: Added default api responses for each service operation 2. Modified certain method signatures for better readability. 310a2a5 is described below commit 310a2a58eff7cb203e4f7b25b78be23ea856aa79 Author: Girish Vasmatkar <[hidden email]> AuthorDate: Wed Sep 2 10:42:41 2020 +0530 Improved: Added default api responses for each service operation 2. Modified certain method signatures for better readability. --- .../ofbiz/ws/rs/common/AuthenticationScheme.java | 1 + .../ofbiz/ws/rs/openapi/OFBizOpenApiReader.java | 44 ++++++----- .../ofbiz/ws/rs/security/auth/APIAuthFilter.java | 5 +- .../org/apache/ofbiz/ws/rs/util/OpenApiUtil.java | 85 +++++++++++++++++++++- 4 files changed, 112 insertions(+), 23 deletions(-) diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/common/AuthenticationScheme.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/common/AuthenticationScheme.java index 7badcf7..b3d7f13 100644 --- a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/common/AuthenticationScheme.java +++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/common/AuthenticationScheme.java @@ -23,6 +23,7 @@ public enum AuthenticationScheme { BASIC("Basic"), BEARER("Bearer"); private String scheme; + public static final String REALM = "OFBiz"; AuthenticationScheme(String scheme) { this.scheme = scheme; } diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/openapi/OFBizOpenApiReader.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/openapi/OFBizOpenApiReader.java index 20b9301..c656e3b 100644 --- a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/openapi/OFBizOpenApiReader.java +++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/openapi/OFBizOpenApiReader.java @@ -26,6 +26,7 @@ import java.util.Set; import javax.servlet.ServletContext; import javax.ws.rs.HttpMethod; +import javax.ws.rs.core.Response; import org.apache.ofbiz.base.util.UtilValidate; import org.apache.ofbiz.service.DispatchContext; @@ -97,7 +98,7 @@ public final class OFBizOpenApiReader extends Reader implements OpenApiReader { if (paths == null) { paths = new Paths(); } - + addPredefinedSchemas(); ServletContext servletContext = ApiContextListener.getApplicationCntx(); LocalDispatcher dispatcher = WebAppUtil.getDispatcher(servletContext); DispatchContext context = dispatcher.getDispatchContext(); @@ -133,21 +134,10 @@ public final class OFBizOpenApiReader extends Reader implements OpenApiReader { new MediaType().schema(new Schema<>().$ref(service.getName() + "Request")))); operation.setRequestBody(request); } - - ApiResponses apiResponsesObject = new ApiResponses(); - ApiResponse successResponse = new ApiResponse().description("Success"); - Content content = new Content(); - MediaType jsonMediaType = new MediaType(); - Schema<?> refSchema = new Schema<>(); - refSchema.$ref(service.getName() + "Response"); - jsonMediaType.setSchema(refSchema); - setOutSchemaForService(service); - setInSchemaForService(service); - content.addMediaType(javax.ws.rs.core.MediaType.APPLICATION_JSON, jsonMediaType); - - apiResponsesObject.addApiResponse("200", successResponse.content(content)); + addServiceOutSchema(service); + addServiceInSchema(service); + addServiceOperationApiResponses(service, operation); setPathItemOperation(pathItemObject, service.getAction().toUpperCase(), operation); - operation.setResponses(apiResponsesObject); paths.addPathItem("/services/" + service.getName(), pathItemObject); } @@ -187,12 +177,28 @@ public final class OFBizOpenApiReader extends Reader implements OpenApiReader { } } - private void setOutSchemaForService(ModelService service) { - schemas.put(service.getName() + "Response", OpenApiUtil.getOutSchema(service)); + private void addServiceOutSchema(ModelService service) { + schemas.put("api.response." + service.getName() + ".success", OpenApiUtil.getOutSchema(service)); + } + + private void addServiceInSchema(ModelService service) { + schemas.put("api.request." + service.getName(), OpenApiUtil.getInSchema(service)); + } + + private void addPredefinedSchemas() { + OpenApiUtil.getStandardApiResponseSchemas().forEach((name, schema) -> { + schemas.put(name, schema); + }); } - private void setInSchemaForService(ModelService service) { - schemas.put(service.getName() + "Request", OpenApiUtil.getInSchema(service)); + private void addServiceOperationApiResponses(ModelService service, Operation operation) { + ApiResponses apiResponsesObject = new ApiResponses(); + ApiResponse successResponse = OpenApiUtil.buildSuccessResponse(service); + apiResponsesObject.addApiResponse(String.valueOf(Response.Status.OK.getStatusCode()), successResponse); + OpenApiUtil.getStandardApiResponses().forEach((code, response) -> { + apiResponsesObject.addApiResponse(code, response); + }); + operation.setResponses(apiResponsesObject); } } diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/security/auth/APIAuthFilter.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/security/auth/APIAuthFilter.java index d1bd212..a77f955 100644 --- a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/security/auth/APIAuthFilter.java +++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/security/auth/APIAuthFilter.java @@ -61,8 +61,6 @@ public class APIAuthFilter implements ContainerRequestFilter { @Context private ServletContext servletContext; - private static final String REALM = "OFBiz"; - /** */ @Override @@ -99,7 +97,8 @@ public class APIAuthFilter implements ContainerRequestFilter { if (!isAuthHeaderPresent) { requestContext.abortWith( RestApiUtil.errorBuilder(Response.Status.UNAUTHORIZED.getStatusCode(), Response.Status.UNAUTHORIZED.getReasonPhrase(), message) - .header(HttpHeaders.WWW_AUTHENTICATE, AuthenticationScheme.BEARER.getScheme() + " realm=\"" + REALM + "\"").build()); + .header(HttpHeaders.WWW_AUTHENTICATE, + AuthenticationScheme.BEARER.getScheme() + " realm=\"" + AuthenticationScheme.REALM + "\"").build()); } else { requestContext .abortWith(RestApiUtil.error(Response.Status.UNAUTHORIZED.getStatusCode(), Response.Status.UNAUTHORIZED.getReasonPhrase(), message)); diff --git a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/util/OpenApiUtil.java b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/util/OpenApiUtil.java index f48de44..baca19e 100644 --- a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/util/OpenApiUtil.java +++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/util/OpenApiUtil.java @@ -22,7 +22,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; + import org.apache.ofbiz.base.util.Debug; +import org.apache.ofbiz.base.util.UtilMisc; import org.apache.ofbiz.base.util.UtilValidate; import org.apache.ofbiz.entity.Delegator; import org.apache.ofbiz.entity.model.ModelEntity; @@ -30,16 +34,21 @@ import org.apache.ofbiz.entity.model.ModelField; import org.apache.ofbiz.service.ModelParam; import org.apache.ofbiz.service.ModelService; import org.apache.ofbiz.webapp.WebAppUtil; +import org.apache.ofbiz.ws.rs.common.AuthenticationScheme; import org.apache.ofbiz.ws.rs.listener.ApiContextListener; +import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.BooleanSchema; +import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.DateSchema; import io.swagger.v3.oas.models.media.IntegerSchema; import io.swagger.v3.oas.models.media.MapSchema; +import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.NumberSchema; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.media.StringSchema; +import io.swagger.v3.oas.models.responses.ApiResponse; public final class OpenApiUtil { @@ -52,6 +61,8 @@ public final class OpenApiUtil { private static final Map<String, String> CLASS_ALIAS = new HashMap<>(); private static final Map<String, Class<?>> JAVA_OPEN_API_MAP = new HashMap<>(); private static final Map<String, String> FIELD_TYPE_MAP = new HashMap<String, String>(); + private static final Map<String, ApiResponse> RESPONSES = new HashMap<>(); + private static final Map<String, Schema<?>> SCHEMAS = new HashMap<>(); static { CLASS_ALIAS.put("String", "String"); @@ -141,6 +152,68 @@ public final class OpenApiUtil { FIELD_TYPE_MAP.put("byte-array", "Byte"); FIELD_TYPE_MAP.put("blob", "Byte"); + buildApiResponseSchemas(); + buildApiResponses(); + } + + private static void buildApiResponseSchemas() { + Schema<?> unauthorized = new MapSchema().addProperties("statusCode", new IntegerSchema().description("HTTP Status Code")) + .addProperties("statusDescription", new StringSchema().description("HTTP Status Code Description")) + .addProperties("errorMessage", new StringSchema().description("Error Message")); + SCHEMAS.put("api.response.unauthorized.noheader", unauthorized); + SCHEMAS.put("api.response.unauthorized.invalidtoken", unauthorized); + SCHEMAS.put("api.response.forbidden", unauthorized); + } + + public static Map<String, ApiResponse> getStandardApiResponses() { + return RESPONSES; + } + + public static Map<String, Schema<?>> getStandardApiResponseSchemas() { + return SCHEMAS; + } + + private static void buildApiResponses() { + Map<String, Object> unauthorizedNoHeaderExample = UtilMisc.toMap("statusCode", Response.Status.UNAUTHORIZED.getStatusCode(), + "statusDescription", Response.Status.UNAUTHORIZED.getReasonPhrase(), + "errorMessage", "Unauthorized: Access is denied due to invalid or absent Authorization header."); + Map<String, Object> unauthorizedInvalidTokenExample = UtilMisc.toMap("statusCode", Response.Status.UNAUTHORIZED.getStatusCode(), + "statusDescription", Response.Status.UNAUTHORIZED.getReasonPhrase(), + "errorMessage", "Unauthorized: Access is denied due to invalid or absent Authorization header."); + Map<String, Object> forbiddenExample = UtilMisc.toMap("statusCode", Response.Status.FORBIDDEN.getStatusCode(), + "statusDescription", Response.Status.FORBIDDEN.getReasonPhrase(), + "errorMessage", "Forbidden: Insufficient rights to perform this API call."); + + final ApiResponse unauthorizedNoHeader = new ApiResponse().addHeaderObject(HttpHeaders.WWW_AUTHENTICATE, new Header() + .example(HttpHeaders.WWW_AUTHENTICATE + ": " + + AuthenticationScheme.BEARER.getScheme() + " realm=\"" + AuthenticationScheme.REALM + "\"")) + .description("Unauthorized: Access is denied due to invalid or absent Authorization header.") + .content(new Content() + .addMediaType(javax.ws.rs.core.MediaType.APPLICATION_JSON, new MediaType() + .schema(new Schema<>() + .$ref("#/components/schemas/" + "api.response.unauthorized.noheader")) + .example(unauthorizedNoHeaderExample))); + + final ApiResponse unauthorizedInvalidToken = new ApiResponse() + .description("Unauthorized: Access is denied due to invalid or absent Authorization header.") + .content(new Content() + .addMediaType(javax.ws.rs.core.MediaType.APPLICATION_JSON, new MediaType() + .schema(new Schema<>() + .$ref("#/components/schemas/" + "api.response.unauthorized.invalidtoken")) + .example(unauthorizedInvalidTokenExample))); + + final ApiResponse forbidden = new ApiResponse().addHeaderObject(HttpHeaders.WWW_AUTHENTICATE, new Header() + .example(HttpHeaders.WWW_AUTHENTICATE + ": " + + AuthenticationScheme.BEARER.getScheme() + " realm=\"" + AuthenticationScheme.REALM + "\"")) + .description("Forbidden: Insufficient rights to perform this API call.") + .content(new Content() + .addMediaType(javax.ws.rs.core.MediaType.APPLICATION_JSON, new MediaType() + .schema(new Schema<>().$ref("#/components/schemas/" + "api.response.forbidden")) + .example(forbiddenExample))); + + RESPONSES.put(String.valueOf(Response.Status.UNAUTHORIZED.getStatusCode()), unauthorizedNoHeader); + RESPONSES.put(String.valueOf(Response.Status.UNAUTHORIZED.getStatusCode()), unauthorizedInvalidToken); + RESPONSES.put(String.valueOf(Response.Status.FORBIDDEN.getStatusCode()), forbidden); } public static Class<?> getOpenApiTypeForAttributeType(String attributeType) { @@ -181,7 +254,8 @@ public final class OpenApiUtil { List<ModelParam> children = param.getChildren(); Delegator delegator = WebAppUtil.getDelegator(ApiContextListener.getApplicationCntx()); if (schema instanceof ArraySchema) { - ((ArraySchema) schema).setItems(children.size() > 0 ? getAttributeSchema(service, children.get(0)) : new StringSchema()); + ArraySchema arrSch = (ArraySchema) schema; + arrSch.setItems(children.size() > 0 ? getAttributeSchema(service, children.get(0)) : new StringSchema()); } else if (schema instanceof MapSchema) { if (isTypeGenericEntityOrGenericValue(param.getType())) { if (UtilValidate.isEmpty(param.getEntityName())) { @@ -255,4 +329,13 @@ public final class OpenApiUtil { } return dataSchema; } + + public static ApiResponse buildSuccessResponse(ModelService service) { + final ApiResponse success = new ApiResponse() + .description("Success response for the API call.") + .content(new Content() + .addMediaType(javax.ws.rs.core.MediaType.APPLICATION_JSON, new MediaType() + .schema(new Schema<>().$ref("#/components/schemas/" + "api.response." + service.getName() + ".success")))); + return success; + } } |
Free forum by Nabble | Edit this page |