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 1361c3c Improved: Updated code to bypass auth for services having
auth=false 2. Implemented ServiceValidationFilter to return various HTTP
responses based on request's context(OFBIZ-11328)
1361c3c is described below
commit 1361c3cdaf7d6756cc9abdc6c37450ef3d46f921
Author: Girish Vasmatkar <[email protected]>
AuthorDate: Sat Sep 26 14:30:47 2020 +0530
Improved: Updated code to bypass auth for services having auth=false
2. Implemented ServiceValidationFilter to return various HTTP responses
based on request's context(OFBIZ-11328)
---
.../org/apache/ofbiz/ws/rs/ConflictException.java | 38 +++++++++
.../apache/ofbiz/ws/rs/ServiceRequestFilter.java | 97 ++++++++++++++++++++++
.../ws/rs/annotation/ServiceRequestValidator.java | 33 ++++++++
.../apache/ofbiz/ws/rs/core/OFBizApiConfig.java | 2 +
.../ws/rs/resources/OFBizServiceResource.java | 6 +-
.../ofbiz/ws/rs/security/auth/APIAuthFilter.java | 29 +++++++
.../org/apache/ofbiz/ws/rs/util/RestApiUtil.java | 19 +++++
7 files changed, 223 insertions(+), 1 deletion(-)
diff --git
a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ConflictException.java
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ConflictException.java
new file mode 100644
index 0000000..4d3c6f7
--- /dev/null
+++
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ConflictException.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+
*******************************************************************************/
+package org.apache.ofbiz.ws.rs;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+/**
+ * A HTTP 409 (Conflict) exception
+ */
+public class ConflictException extends WebApplicationException {
+
+ private static final long serialVersionUID = -3002310435429546325L;
+
+ /**
+ * Construct a new ConflictException exception.
+ */
+ public ConflictException(String message) {
+ super(message, Response.Status.CONFLICT);
+ }
+
+}
diff --git
a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ServiceRequestFilter.java
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ServiceRequestFilter.java
new file mode 100644
index 0000000..9021edf
--- /dev/null
+++
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/ServiceRequestFilter.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+
*******************************************************************************/
+package org.apache.ofbiz.ws.rs;
+
+import java.io.IOException;
+
+import javax.annotation.Priority;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.service.GenericServiceException;
+import org.apache.ofbiz.service.ModelService;
+import org.apache.ofbiz.webapp.WebAppUtil;
+import org.apache.ofbiz.ws.rs.annotation.ServiceRequestValidator;
+import org.apache.ofbiz.ws.rs.util.RestApiUtil;
+
+@Provider
+@ServiceRequestValidator
+@Priority(Priorities.USER)
+public class ServiceRequestFilter implements ContainerRequestFilter {
+
+ private static final String MODULE = ServiceRequestFilter.class.getName();
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private ResourceInfo resourceInfo;
+
+ @Context
+ private HttpServletRequest httpRequest;
+
+ @Context
+ private ServletContext servletContext;
+
+ /**
+ * @param requestContext
+ * @throws IOException
+ */
+ @Override
+ public void filter(ContainerRequestContext requestContext) throws
IOException {
+ Debug.logInfo("Service request is going to get validated!", MODULE);
+ String service = (String)
RestApiUtil.extractParams(uriInfo.getPathParameters()).get("serviceName");
+ String method = requestContext.getMethod();
+ if (UtilValidate.isNotEmpty(service)) {
+ ModelService mdService = null;
+ try {
+ mdService =
WebAppUtil.getDispatcher(servletContext).getDispatchContext().getModelService(service);
+ } catch (GenericServiceException e) {
+ Debug.logError(e.getMessage(), MODULE);
+ }
+
+ if (mdService == null) {
+ throw new NotFoundException("Service '" + service + "' not
found.");
+ }
+
+ if (mdService != null && !mdService.isExport()) {
+ throw new NotFoundException("Service '" + service + "' is not
exportable.");
+ }
+
+ if (mdService != null &&
UtilValidate.isEmpty(mdService.getAction())) {
+ throw new ConflictException("Service '" + service + "' does
not have HTTP action defined.");
+ }
+
+ if (!mdService.getAction().equalsIgnoreCase(method)) {
+ throw new MethodNotAllowedException("HTTP " + method + " is
not allowed on service '" + service + "'");
+ }
+ }
+ }
+
+}
diff --git
a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/annotation/ServiceRequestValidator.java
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/annotation/ServiceRequestValidator.java
new file mode 100644
index 0000000..61a4655
--- /dev/null
+++
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/annotation/ServiceRequestValidator.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+
*******************************************************************************/
+package org.apache.ofbiz.ws.rs.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.NameBinding;
+
+@NameBinding
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE })
+public @interface ServiceRequestValidator {
+
+}
diff --git
a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
index 5eecd73..4e16d3f 100644
---
a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
+++
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
@@ -33,6 +33,7 @@ import org.apache.ofbiz.base.component.ComponentConfig;
import org.apache.ofbiz.base.component.ComponentException;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.ws.rs.ServiceRequestFilter;
import org.apache.ofbiz.ws.rs.model.ModelApi;
import org.apache.ofbiz.ws.rs.model.ModelApiReader;
import org.apache.ofbiz.ws.rs.model.ModelOperation;
@@ -57,6 +58,7 @@ public class OFBizApiConfig extends ResourceConfig {
// packages("io.swagger.v3.jaxrs2.integration.resources");
//commenting it out
// to generate customized OpenApi Spec
register(JacksonFeature.class);
+ register(ServiceRequestFilter.class);
register(MultiPartFeature.class);
if (Debug.verboseOn()) {
register(new
LoggingFeature(Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), Level.INFO,
diff --git
a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/resources/OFBizServiceResource.java
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/resources/OFBizServiceResource.java
index 6b335b6..61cb6af 100644
---
a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/resources/OFBizServiceResource.java
+++
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/resources/OFBizServiceResource.java
@@ -54,14 +54,18 @@ import org.apache.ofbiz.service.LocalDispatcher;
import org.apache.ofbiz.service.ModelService;
import org.apache.ofbiz.ws.rs.ApiServiceRequest;
import org.apache.ofbiz.ws.rs.ServiceRequestProcessor;
+import org.apache.ofbiz.ws.rs.annotation.ServiceRequestValidator;
import org.apache.ofbiz.ws.rs.response.Success;
import org.apache.ofbiz.ws.rs.security.Secured;
@Secured
-@Path("/services")
+@Path(OFBizServiceResource.BASE_PATH)
@Provider
+@ServiceRequestValidator
public class OFBizServiceResource extends OFBizResource {
+ public static final String BASE_PATH = "/services";
+
@Context
private UriInfo uriInfo;
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 a77f955..3834464 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
@@ -21,14 +21,17 @@ package org.apache.ofbiz.ws.rs.security.auth;
import java.io.IOException;
import java.util.Map;
+import javax.annotation.Priority;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Provider;
import org.apache.ofbiz.base.util.Debug;
@@ -37,9 +40,12 @@ import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.util.EntityQuery;
+import org.apache.ofbiz.service.GenericServiceException;
import org.apache.ofbiz.service.ModelService;
+import org.apache.ofbiz.webapp.WebAppUtil;
import org.apache.ofbiz.webapp.control.JWTManager;
import org.apache.ofbiz.ws.rs.common.AuthenticationScheme;
+import org.apache.ofbiz.ws.rs.resources.OFBizServiceResource;
import org.apache.ofbiz.ws.rs.security.Secured;
import org.apache.ofbiz.ws.rs.util.RestApiUtil;
@@ -48,11 +54,15 @@ import org.apache.ofbiz.ws.rs.util.RestApiUtil;
*/
@Secured
@Provider
+@Priority(Priorities.AUTHORIZATION)
public class APIAuthFilter implements ContainerRequestFilter {
private static final String MODULE = APIAuthFilter.class.getName();
@Context
+ private UriInfo uriInfo;
+
+ @Context
private ResourceInfo resourceInfo;
@Context
@@ -65,6 +75,21 @@ public class APIAuthFilter implements ContainerRequestFilter
{
*/
@Override
public void filter(ContainerRequestContext requestContext) throws
IOException {
+ if (isServiceResource()) {
+ String service = (String)
RestApiUtil.extractParams(uriInfo.getPathParameters()).get("serviceName");
+ if (UtilValidate.isNotEmpty(service)) {
+ ModelService mdService = null;
+ try {
+ mdService =
WebAppUtil.getDispatcher(servletContext).getDispatchContext().getModelService(service);
+ } catch (GenericServiceException e) {
+ Debug.logError(e.getMessage(), MODULE);
+ }
+ // Skip auth for services auth=false in service definition
+ if (mdService != null && !mdService.isAuth()) {
+ return;
+ }
+ }
+ }
String authorizationHeader =
requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
Delegator delegator = (Delegator)
servletContext.getAttribute("delegator");
if (!isTokenBasedAuthentication(authorizationHeader)) {
@@ -124,4 +149,8 @@ public class APIAuthFilter implements
ContainerRequestFilter {
return userLogin;
}
+ private boolean isServiceResource() {
+ return
OFBizServiceResource.class.isAssignableFrom(resourceInfo.getResourceClass());
+ }
+
}
diff --git
a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/util/RestApiUtil.java
b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/util/RestApiUtil.java
index 309ca53..2cbde9d 100644
--- a/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/util/RestApiUtil.java
+++ b/ofbiz-rest-impl/src/main/java/org/apache/ofbiz/ws/rs/util/RestApiUtil.java
@@ -18,10 +18,15 @@
*******************************************************************************/
package org.apache.ofbiz.ws.rs.util;
+import java.util.HashMap;
+import java.util.Map;
+
import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
+import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.ws.rs.response.Error;
import org.apache.ofbiz.ws.rs.response.Success;
@@ -49,4 +54,18 @@ public final class RestApiUtil {
Error error = new Error(statusCode, reasonPhrase, message);
return
Response.status(statusCode).type(MediaType.APPLICATION_JSON).entity(error);
}
+
+ /**
+ * @param multivaluedMap
+ * @return
+ */
+ public static Map<String, Object> extractParams(MultivaluedMap<String,
String> multivaluedMap) {
+ Map<String, Object> result = new HashMap<>();
+ multivaluedMap.forEach((name, values) -> {
+ if (UtilValidate.isNotEmpty(values)) {
+ result.put(name, (values.size() != 1) ? values :
values.get(0));
+ }
+ });
+ return result;
+ }
}