[ofbiz-plugins] branch trunk updated: Improved: Added default api responses for each service operation 2. Modified certain method signatures for better readability.

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[ofbiz-plugins] branch trunk updated: Improved: Added default api responses for each service operation 2. Modified certain method signatures for better readability.

grv-2
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;
+    }
 }