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 <[email protected]>
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;
+ }
}