You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by dg...@apache.org on 2022/05/02 08:53:29 UTC
[unomi] 01/01: UNOMI-562 : remove bean validation
This is an automated email from the ASF dual-hosted git repository.
dgriffon pushed a commit to branch remove-bean-validation
in repository https://gitbox.apache.org/repos/asf/unomi.git
commit 5f09dacbd8baef32b6a5d00978f51471985bde1e
Author: David Griffon <dg...@jahia.com>
AuthorDate: Mon May 2 10:52:46 2022 +0200
UNOMI-562 : remove bean validation
---
.../resources/schemas/events/dummy-event-type.json | 43 +++++++++++++++----
.../deserializers/ContextRequestDeserializer.java | 4 +-
...ava => EventsCollectorRequestDeserializer.java} | 10 ++---
.../unomi/rest/endpoints/ContextJsonEndpoint.java | 49 ++++++++++++++--------
.../rest/endpoints/EventsCollectorEndpoint.java | 8 +++-
.../InvalidRequestException.java | 7 +++-
.../exception/InvalidRequestExceptionMapper.java | 4 +-
.../org/apache/unomi/rest/server/RestServer.java | 22 +---------
.../RetroCompatibilityParamConverterProvider.java | 7 +---
.../rest/service/impl/RestServiceUtilsImpl.java | 19 +++++----
.../rest/validation/BeanValidationService.java | 32 --------------
.../HibernateValidationProviderResolver.java | 37 ----------------
.../JAXRSBeanValidationInInterceptorOverride.java | 42 -------------------
.../validation/impl/BeanValidationServiceImpl.java | 48 ---------------------
.../request/RequestValidatorInterceptor.java | 1 +
.../rest/validation/wrapper/CookieWrapper.java | 36 ----------------
.../META-INF/cxs/schemas/contextrequestparams.json | 16 +++++++
.../resources/META-INF/cxs/schemas/cookie.json | 12 ++++++
.../cxs/schemas/eventscollectorrequest.json | 5 ++-
19 files changed, 136 insertions(+), 266 deletions(-)
diff --git a/itests/src/test/resources/schemas/events/dummy-event-type.json b/itests/src/test/resources/schemas/events/dummy-event-type.json
index 439f2f9f2..59f439abf 100644
--- a/itests/src/test/resources/schemas/events/dummy-event-type.json
+++ b/itests/src/test/resources/schemas/events/dummy-event-type.json
@@ -1,14 +1,43 @@
{
"$id": "https://unomi.apache.org/schemas/json/events/dummy_event_type/1-0-0",
"$schema": "https://json-schema.org/draft/2019-09/schema",
- "self":{
- "vendor":"org.apache.unomi",
- "name":"events/dummy_event_type",
- "format":"jsonschema",
- "target":"events",
- "version":"1-0-0"
+ "self": {
+ "vendor": "org.apache.unomi",
+ "name": "events/dummy_event_type",
+ "format": "jsonschema",
+ "target": "events",
+ "version": "1-0-0"
},
"title": "DummyEvent",
"type": "object",
- "allOf": [{ "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0" }]
+ "allOf": [
+ {
+ "$ref": "https://unomi.apache.org/schemas/json/event/1-0-0"
+ }
+ ],
+ "properties": {
+ "source": {
+ "type": "object",
+ "properties": {
+ "itemType": {
+ "type": "string"
+ },
+ "scope": {
+ "type": "string"
+ },
+ "itemId": {
+ "type": "string"
+ },
+ "properties": {
+ "type": "object",
+ "properties": {
+ "myProperty": {
+ "type": "string",
+ "maxLength": 20000
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/rest/src/main/java/org/apache/unomi/rest/deserializers/ContextRequestDeserializer.java b/rest/src/main/java/org/apache/unomi/rest/deserializers/ContextRequestDeserializer.java
index 5e5488f3b..1dcb653b8 100644
--- a/rest/src/main/java/org/apache/unomi/rest/deserializers/ContextRequestDeserializer.java
+++ b/rest/src/main/java/org/apache/unomi/rest/deserializers/ContextRequestDeserializer.java
@@ -27,7 +27,7 @@ import org.apache.unomi.api.Event;
import org.apache.unomi.api.Profile;
import org.apache.unomi.api.services.PersonalizationService;
import org.apache.unomi.api.services.SchemaService;
-import org.apache.unomi.rest.validation.request.InvalidRequestException;
+import org.apache.unomi.rest.exception.InvalidRequestException;
import java.io.IOException;
import java.util.ArrayList;
@@ -55,7 +55,7 @@ public class ContextRequestDeserializer extends StdDeserializer<ContextRequest>
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
// Validate schema on it
if (!schemaService.isValid(node, "https://unomi.apache.org/schemas/json/contextrequest/1-0-0")) {
- throw new InvalidRequestException("Invalid received data", "Invalid received data");
+ throw new InvalidRequestException("Invalid Context request object", "Invalid received data");
}
ContextRequest cr = new ContextRequest();
if (node.get("requireSegments") != null) {
diff --git a/rest/src/main/java/org/apache/unomi/rest/deserializers/EventCollectorRequestDeserializer.java b/rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java
similarity index 86%
rename from rest/src/main/java/org/apache/unomi/rest/deserializers/EventCollectorRequestDeserializer.java
rename to rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java
index 5e78fc0a9..b544f2089 100644
--- a/rest/src/main/java/org/apache/unomi/rest/deserializers/EventCollectorRequestDeserializer.java
+++ b/rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java
@@ -25,7 +25,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
import org.apache.unomi.api.Event;
import org.apache.unomi.api.EventsCollectorRequest;
import org.apache.unomi.api.services.SchemaService;
-import org.apache.unomi.rest.validation.request.InvalidRequestException;
+import org.apache.unomi.rest.exception.InvalidRequestException;
import java.io.IOException;
import java.util.ArrayList;
@@ -34,15 +34,15 @@ import java.util.List;
/**
* Custom deserializer for EventCollectorRequest that do validate the events using JSon Schema
*/
-public class EventCollectorRequestDeserializer extends StdDeserializer<EventsCollectorRequest> {
+public class EventsCollectorRequestDeserializer extends StdDeserializer<EventsCollectorRequest> {
private final SchemaService schemaService;
- public EventCollectorRequestDeserializer(SchemaService schemaRegistry) {
+ public EventsCollectorRequestDeserializer(SchemaService schemaRegistry) {
this(null, schemaRegistry);
}
- public EventCollectorRequestDeserializer(Class<EventsCollectorRequest> vc, SchemaService schemaService) {
+ public EventsCollectorRequestDeserializer(Class<EventsCollectorRequest> vc, SchemaService schemaService) {
super(vc);
this.schemaService = schemaService;
}
@@ -51,7 +51,7 @@ public class EventCollectorRequestDeserializer extends StdDeserializer<EventsCol
public EventsCollectorRequest deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
if (!schemaService.isValid(node, "https://unomi.apache.org/schemas/json/eventscollectorrequest/1-0-0")) {
- throw new InvalidRequestException("Invalid received data", "Invalid received data");
+ throw new InvalidRequestException("Invalid events collector object", "Invalid received data");
}
// Validate schema on each event
diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
index 7748b9aa9..324216586 100644
--- a/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java
@@ -18,18 +18,17 @@
package org.apache.unomi.rest.endpoints;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
import org.apache.unomi.api.*;
import org.apache.unomi.api.conditions.Condition;
-import org.apache.unomi.api.services.ConfigSharingService;
-import org.apache.unomi.api.services.EventService;
-import org.apache.unomi.api.services.PersonalizationService;
-import org.apache.unomi.api.services.PrivacyService;
-import org.apache.unomi.api.services.ProfileService;
-import org.apache.unomi.api.services.RulesService;
+import org.apache.unomi.api.services.*;
import org.apache.unomi.api.utils.ValidationPattern;
import org.apache.unomi.persistence.spi.CustomObjectMapper;
+import org.apache.unomi.rest.exception.InvalidRequestException;
import org.apache.unomi.rest.service.RestServiceUtils;
import org.apache.unomi.utils.Changes;
import org.apache.unomi.utils.HttpUtils;
@@ -94,6 +93,8 @@ public class ContextJsonEndpoint {
private ConfigSharingService configSharingService;
@Reference
private RestServiceUtils restServiceUtils;
+ @Reference
+ private SchemaService schemaService;
@OPTIONS
@Path("/context.js")
@@ -110,9 +111,9 @@ public class ContextJsonEndpoint {
@POST
@Produces(MediaType.TEXT_PLAIN)
@Path("/context.js")
- public Response contextJSAsPost(@Valid ContextRequest contextRequest,
- @QueryParam("personaId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String personaId,
- @QueryParam("sessionId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String sessionId,
+ public Response contextJSAsPost(ContextRequest contextRequest,
+ @QueryParam("personaId") String personaId,
+ @QueryParam("sessionId") String sessionId,
@QueryParam("timestamp") Long timestampAsLong, @QueryParam("invalidateProfile") boolean invalidateProfile,
@QueryParam("invalidateSession") boolean invalidateSession) throws JsonProcessingException {
return contextJSAsGet(contextRequest, personaId, sessionId, timestampAsLong, invalidateProfile, invalidateSession);
@@ -121,9 +122,9 @@ public class ContextJsonEndpoint {
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/context.js")
- public Response contextJSAsGet(@QueryParam("payload") @Valid ContextRequest contextRequest,
- @QueryParam("personaId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String personaId,
- @QueryParam("sessionId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String sessionId,
+ public Response contextJSAsGet(@QueryParam("payload") ContextRequest contextRequest,
+ @QueryParam("personaId") String personaId,
+ @QueryParam("sessionId") String sessionId,
@QueryParam("timestamp") Long timestampAsLong, @QueryParam("invalidateProfile") boolean invalidateProfile,
@QueryParam("invalidateSession") boolean invalidateSession) throws JsonProcessingException {
ContextResponse contextResponse = contextJSONAsPost(contextRequest, personaId, sessionId, timestampAsLong, invalidateProfile,
@@ -138,9 +139,9 @@ public class ContextJsonEndpoint {
@GET
@Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
@Path("/context.json")
- public ContextResponse contextJSONAsGet(@QueryParam("payload") @Valid ContextRequest contextRequest,
- @QueryParam("personaId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String personaId,
- @QueryParam("sessionId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String sessionId,
+ public ContextResponse contextJSONAsGet(@QueryParam("payload") ContextRequest contextRequest,
+ @QueryParam("personaId") String personaId,
+ @QueryParam("sessionId") String sessionId,
@QueryParam("timestamp") Long timestampAsLong, @QueryParam("invalidateProfile") boolean invalidateProfile,
@QueryParam("invalidateSession") boolean invalidateSession) {
return contextJSONAsPost(contextRequest, personaId, sessionId, timestampAsLong, invalidateProfile, invalidateSession);
@@ -149,11 +150,23 @@ public class ContextJsonEndpoint {
@POST
@Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
@Path("/context.json")
- public ContextResponse contextJSONAsPost(@Valid ContextRequest contextRequest,
- @QueryParam("personaId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String personaId,
- @QueryParam("sessionId") @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN) String sessionId,
+ public ContextResponse contextJSONAsPost(ContextRequest contextRequest,
+ @QueryParam("personaId") String personaId,
+ @QueryParam("sessionId") String sessionId,
@QueryParam("timestamp") Long timestampAsLong, @QueryParam("invalidateProfile") boolean invalidateProfile,
@QueryParam("invalidateSession") boolean invalidateSession) {
+
+ // Schema validation
+ ObjectNode paramsAsJson = JsonNodeFactory.instance.objectNode();
+ if (personaId != null) {
+ paramsAsJson.put("personaId", personaId);
+ }
+ if (sessionId != null) {
+ paramsAsJson.put("sessionId", sessionId);
+ }
+ if (!schemaService.isValid(paramsAsJson, "https://unomi.apache.org/schemas/json/contextrequestparams/1-0-0")) {
+ throw new InvalidRequestException("Invalid parameter", "Invalid received data");
+ }
Date timestamp = new Date();
if (timestampAsLong != null) {
timestamp = new Date(timestampAsLong);
diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/EventsCollectorEndpoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/EventsCollectorEndpoint.java
index 28d312a8d..11b4d8c62 100644
--- a/rest/src/main/java/org/apache/unomi/rest/endpoints/EventsCollectorEndpoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/EventsCollectorEndpoint.java
@@ -28,6 +28,7 @@ import org.apache.unomi.api.services.ConfigSharingService;
import org.apache.unomi.api.services.EventService;
import org.apache.unomi.api.services.PrivacyService;
import org.apache.unomi.api.services.ProfileService;
+import org.apache.unomi.rest.exception.InvalidRequestException;
import org.apache.unomi.rest.models.EventCollectorResponse;
import org.apache.unomi.rest.service.RestServiceUtils;
import org.apache.unomi.utils.Changes;
@@ -88,19 +89,22 @@ public class EventsCollectorEndpoint {
@GET
@Path("/eventcollector")
- public EventCollectorResponse collectAsGet(@QueryParam("payload") @NotNull @Valid EventsCollectorRequest eventsCollectorRequest,
+ public EventCollectorResponse collectAsGet(@QueryParam("payload") EventsCollectorRequest eventsCollectorRequest,
@QueryParam("timestamp") Long timestampAsString) {
return doEvent(eventsCollectorRequest, timestampAsString);
}
@POST
@Path("/eventcollector")
- public EventCollectorResponse collectAsPost(@NotNull @Valid EventsCollectorRequest eventsCollectorRequest,
+ public EventCollectorResponse collectAsPost(EventsCollectorRequest eventsCollectorRequest,
@QueryParam("timestamp") Long timestampAsLong) {
return doEvent(eventsCollectorRequest, timestampAsLong);
}
private EventCollectorResponse doEvent(EventsCollectorRequest eventsCollectorRequest, Long timestampAsLong) {
+ if (eventsCollectorRequest == null) {
+ throw new InvalidRequestException("events collector cannot be empty", "Invalid received data");
+ }
Date timestamp = new Date();
if (timestampAsLong != null) {
timestamp = new Date(timestampAsLong);
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/request/InvalidRequestException.java b/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestException.java
similarity index 83%
rename from rest/src/main/java/org/apache/unomi/rest/validation/request/InvalidRequestException.java
rename to rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestException.java
index b41a6575f..d97495e6a 100644
--- a/rest/src/main/java/org/apache/unomi/rest/validation/request/InvalidRequestException.java
+++ b/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestException.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.unomi.rest.validation.request;
+package org.apache.unomi.rest.exception;
/**
* Exception throw when the request exceed the configured limit size
@@ -26,6 +26,11 @@ public class InvalidRequestException extends RuntimeException {
*/
private final String responseMessage;
+ /**
+ * Build an invalid request
+ * @param message message in the logs. It contains detailed information
+ * @param responseMessage message in the response, sent to the browser, must be vague as possible.
+ */
public InvalidRequestException(String message, String responseMessage) {
super(message);
this.responseMessage = responseMessage;
diff --git a/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestExceptionMapper.java b/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestExceptionMapper.java
index 9dfd29e1a..c793f602f 100644
--- a/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestExceptionMapper.java
+++ b/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestExceptionMapper.java
@@ -16,7 +16,6 @@
*/
package org.apache.unomi.rest.exception;
-import org.apache.unomi.rest.validation.request.InvalidRequestException;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,7 +32,8 @@ public class InvalidRequestExceptionMapper implements ExceptionMapper<InvalidReq
@Override
public Response toResponse(InvalidRequestException exception) {
- logger.error(exception.getMessage(), exception);
+ logger.error("{} - set InvalidRequestExceptionMapper to debug level to get full error", exception.getMessage());
+ logger.debug("error", exception);
return Response.status(Response.Status.BAD_REQUEST).header("Content-Type", MediaType.TEXT_PLAIN)
.entity("Request rejected by the server because: " + exception.getResponseMessage()).build();
diff --git a/rest/src/main/java/org/apache/unomi/rest/server/RestServer.java b/rest/src/main/java/org/apache/unomi/rest/server/RestServer.java
index 2d43dcb0d..0da55b996 100644
--- a/rest/src/main/java/org/apache/unomi/rest/server/RestServer.java
+++ b/rest/src/main/java/org/apache/unomi/rest/server/RestServer.java
@@ -26,8 +26,6 @@ import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.openapi.OpenApiCustomizer;
import org.apache.cxf.jaxrs.openapi.OpenApiFeature;
import org.apache.cxf.jaxrs.security.SimpleAuthorizingFilter;
-import org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor;
-import org.apache.cxf.jaxrs.validation.JAXRSBeanValidationOutInterceptor;
import org.apache.cxf.message.Message;
import org.apache.unomi.api.ContextRequest;
import org.apache.unomi.api.EventsCollectorRequest;
@@ -37,10 +35,8 @@ import org.apache.unomi.rest.authentication.AuthenticationFilter;
import org.apache.unomi.rest.authentication.AuthorizingInterceptor;
import org.apache.unomi.rest.authentication.RestAuthenticationConfig;
import org.apache.unomi.rest.deserializers.ContextRequestDeserializer;
-import org.apache.unomi.rest.deserializers.EventCollectorRequestDeserializer;
+import org.apache.unomi.rest.deserializers.EventsCollectorRequestDeserializer;
import org.apache.unomi.rest.server.provider.RetroCompatibilityParamConverterProvider;
-import org.apache.unomi.rest.validation.JAXRSBeanValidationInInterceptorOverride;
-import org.apache.unomi.rest.validation.BeanValidationService;
import org.apache.unomi.rest.validation.request.RequestValidatorInterceptor;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
@@ -75,7 +71,6 @@ public class RestServer {
private Bus serverBus;
private RestAuthenticationConfig restAuthenticationConfig;
private List<ExceptionMapper> exceptionMappers = new ArrayList<>();
- private BeanValidationService beanValidationService;
private ConfigSharingService configSharingService;
private SchemaService schemaService;
@@ -113,11 +108,6 @@ public class RestServer {
refreshServer();
}
- @Reference(cardinality = ReferenceCardinality.MANDATORY)
- public void setBeanValidationService(BeanValidationService beanValidationService) {
- this.beanValidationService = beanValidationService;
- }
-
public void removeExceptionMapper(ExceptionMapper exceptionMapper) {
this.exceptionMappers.remove(exceptionMapper);
timeOfLastUpdate = System.currentTimeMillis();
@@ -213,7 +203,7 @@ public class RestServer {
Map<Class, StdDeserializer<?>> desers = new HashMap<>();
desers.put(ContextRequest.class, new ContextRequestDeserializer(schemaService));
- desers.put(EventsCollectorRequest.class, new EventCollectorRequestDeserializer(schemaService));
+ desers.put(EventsCollectorRequest.class, new EventsCollectorRequestDeserializer(schemaService));
// Build the server
@@ -251,14 +241,6 @@ public class RestServer {
openApiFeature.setCustomizer(customizer);
jaxrsServerFactoryBean.getFeatures().add(openApiFeature);
- // Hibernate validator config
- JAXRSBeanValidationInInterceptor beanValidationInInterceptor = new JAXRSBeanValidationInInterceptorOverride();
- JAXRSBeanValidationOutInterceptor beanValidationOutInterceptor = new JAXRSBeanValidationOutInterceptor();
- beanValidationInInterceptor.setProvider(beanValidationService.getBeanValidationProvider());
- beanValidationOutInterceptor.setProvider(beanValidationService.getBeanValidationProvider());
- inInterceptors.add(beanValidationInInterceptor);
- outInterceptors.add(beanValidationOutInterceptor);
-
// Request validator
inInterceptors.add(new RequestValidatorInterceptor(configSharingService));
diff --git a/rest/src/main/java/org/apache/unomi/rest/server/provider/RetroCompatibilityParamConverterProvider.java b/rest/src/main/java/org/apache/unomi/rest/server/provider/RetroCompatibilityParamConverterProvider.java
index d7b6f3e84..fabd37121 100644
--- a/rest/src/main/java/org/apache/unomi/rest/server/provider/RetroCompatibilityParamConverterProvider.java
+++ b/rest/src/main/java/org/apache/unomi/rest/server/provider/RetroCompatibilityParamConverterProvider.java
@@ -20,12 +20,9 @@ import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.unomi.api.ContextRequest;
import org.apache.unomi.api.EventsCollectorRequest;
-import org.apache.unomi.rest.validation.request.InvalidRequestException;
+import org.apache.unomi.rest.exception.InvalidRequestException;
-import javax.ws.rs.BadRequestException;
-import javax.ws.rs.ProcessingException;
import javax.ws.rs.ext.*;
-import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.ArrayList;
@@ -65,7 +62,7 @@ public class RetroCompatibilityParamConverterProvider implements ParamConverterP
try {
return objectMapper.readValue(factory.createParser(value), rawType);
} catch (Exception e) {
- throw new InvalidRequestException("Invalid received data", "Invalid received data");
+ throw new InvalidRequestException(String.format("Unable to deserialize object because %s", e.getMessage()), "Invalid received data");
}
}
diff --git a/rest/src/main/java/org/apache/unomi/rest/service/impl/RestServiceUtilsImpl.java b/rest/src/main/java/org/apache/unomi/rest/service/impl/RestServiceUtilsImpl.java
index 9f05bd6be..4600f0c1e 100644
--- a/rest/src/main/java/org/apache/unomi/rest/service/impl/RestServiceUtilsImpl.java
+++ b/rest/src/main/java/org/apache/unomi/rest/service/impl/RestServiceUtilsImpl.java
@@ -16,6 +16,8 @@
*/
package org.apache.unomi.rest.service.impl;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.TextNode;
import org.apache.unomi.api.Event;
import org.apache.unomi.api.Persona;
import org.apache.unomi.api.Profile;
@@ -23,9 +25,9 @@ import org.apache.unomi.api.Session;
import org.apache.unomi.api.services.ConfigSharingService;
import org.apache.unomi.api.services.EventService;
import org.apache.unomi.api.services.PrivacyService;
+import org.apache.unomi.api.services.SchemaService;
+import org.apache.unomi.rest.exception.InvalidRequestException;
import org.apache.unomi.rest.service.RestServiceUtils;
-import org.apache.unomi.rest.validation.BeanValidationService;
-import org.apache.unomi.rest.validation.wrapper.CookieWrapper;
import org.apache.unomi.utils.Changes;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@@ -36,6 +38,7 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.BadRequestException;
import java.util.Date;
import java.util.List;
@@ -47,15 +50,14 @@ public class RestServiceUtilsImpl implements RestServiceUtils {
@Reference
private ConfigSharingService configSharingService;
- @Reference
- private BeanValidationService beanValidationService;
-
@Reference
private PrivacyService privacyService;
@Reference
private EventService eventService;
+ @Reference SchemaService schemaService;
+
public String getProfileIdCookieValue(HttpServletRequest httpServletRequest) {
String cookieProfileId = null;
@@ -63,8 +65,11 @@ public class RestServiceUtilsImpl implements RestServiceUtils {
if (cookies != null) {
for (Cookie cookie : cookies) {
- if (configSharingService.getProperty("profileIdCookieName").equals(cookie.getName())) {
- beanValidationService.getBeanValidationProvider().validateBean(new CookieWrapper(cookie.getValue()));
+ final Object profileIdCookieName = configSharingService.getProperty("profileIdCookieName");
+ if (profileIdCookieName.equals(cookie.getName())) {
+ if (!schemaService.isValid(JsonNodeFactory.instance.objectNode().put("profileIdCookieName", cookie.getValue()), "https://unomi.apache.org/schemas/json/cookie/1-0-0")) {
+ throw new InvalidRequestException("Invalid profile ID format in cookie", "Invalid received data");
+ }
cookieProfileId = cookie.getValue();
}
}
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/BeanValidationService.java b/rest/src/main/java/org/apache/unomi/rest/validation/BeanValidationService.java
deleted file mode 100644
index b691fe7eb..000000000
--- a/rest/src/main/java/org/apache/unomi/rest/validation/BeanValidationService.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.unomi.rest.validation;
-
-import org.apache.cxf.validation.BeanValidationProvider;
-
-/**
- * This service is just here to provide the CXF BeanValidationProvider in the OSGI context as a service.
- */
-public interface BeanValidationService {
-
- /**
- * Get the CXF BeanValidationProvider instance
- * @return the CXF BeanValidationProvider instance
- */
- BeanValidationProvider getBeanValidationProvider();
-}
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/HibernateValidationProviderResolver.java b/rest/src/main/java/org/apache/unomi/rest/validation/HibernateValidationProviderResolver.java
deleted file mode 100644
index 485733c11..000000000
--- a/rest/src/main/java/org/apache/unomi/rest/validation/HibernateValidationProviderResolver.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.unomi.rest.validation;
-
-import static java.util.Collections.singletonList;
-import org.hibernate.validator.HibernateValidator;
-
-import javax.validation.ValidationProviderResolver;
-import javax.validation.spi.ValidationProvider;
-import java.util.List;
-
-/**
- * OSGi-friendly implementation of {@code javax.validation.ValidationProviderResolver} returning
- * {@code org.hibernate.validator.HibernateValidator} instance.
- *
- */
-public class HibernateValidationProviderResolver implements ValidationProviderResolver {
-
- @Override
- public List<ValidationProvider<?>> getValidationProviders() {
- return singletonList(new HibernateValidator());
- }
-}
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/JAXRSBeanValidationInInterceptorOverride.java b/rest/src/main/java/org/apache/unomi/rest/validation/JAXRSBeanValidationInInterceptorOverride.java
deleted file mode 100644
index 44a6d1105..000000000
--- a/rest/src/main/java/org/apache/unomi/rest/validation/JAXRSBeanValidationInInterceptorOverride.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.unomi.rest.validation;
-
-import org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor;
-import org.apache.cxf.message.Message;
-
-import java.lang.reflect.Method;
-import java.util.List;
-
-/**
- * This class allows to replace the class loader use by
- * javax.el.FactoryFinder.newInstance(FactoryFinder.java:53)
- * to allow to retrieve com.sun.el.ExpressionFactoryImpl which is present in the class loader of this module
- */
-public class JAXRSBeanValidationInInterceptorOverride extends JAXRSBeanValidationInInterceptor {
- @Override
- protected void handleValidation(final Message message, final Object resourceInstance, final Method method,
- final List<Object> arguments) {
- ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
- try {
- Thread.currentThread().setContextClassLoader(JAXRSBeanValidationInInterceptorOverride.class.getClassLoader());
- super.handleValidation(message, resourceInstance, method, arguments);
- } finally {
- Thread.currentThread().setContextClassLoader(currentContextClassLoader);
- }
- }
-}
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/impl/BeanValidationServiceImpl.java b/rest/src/main/java/org/apache/unomi/rest/validation/impl/BeanValidationServiceImpl.java
deleted file mode 100644
index 2bccc1811..000000000
--- a/rest/src/main/java/org/apache/unomi/rest/validation/impl/BeanValidationServiceImpl.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.unomi.rest.validation.impl;
-
-import org.apache.cxf.validation.BeanValidationProvider;
-import org.apache.unomi.rest.validation.HibernateValidationProviderResolver;
-import org.apache.unomi.rest.validation.BeanValidationService;
-import org.hibernate.validator.HibernateValidator;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-
-@Component(service = BeanValidationService.class)
-public class BeanValidationServiceImpl implements BeanValidationService {
- private BeanValidationProvider beanValidationProvider;
-
- @Activate
- public void activate() {
- // This is a TCCL (Thread context class loader) hack to for the javax.el.FactoryFinder to use Class.forName(className)
- // instead of tccl.loadClass(className) to load the class "com.sun.el.ExpressionFactoryImpl".
- ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
- try {
- Thread.currentThread().setContextClassLoader(null);
- HibernateValidationProviderResolver validationProviderResolver = new HibernateValidationProviderResolver();
- this.beanValidationProvider = new BeanValidationProvider(validationProviderResolver, HibernateValidator.class);
- } finally {
- Thread.currentThread().setContextClassLoader(currentContextClassLoader);
- }
- }
-
- public BeanValidationProvider getBeanValidationProvider() {
- return beanValidationProvider;
- }
-}
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/request/RequestValidatorInterceptor.java b/rest/src/main/java/org/apache/unomi/rest/validation/request/RequestValidatorInterceptor.java
index 4cc23434f..ae19c1039 100644
--- a/rest/src/main/java/org/apache/unomi/rest/validation/request/RequestValidatorInterceptor.java
+++ b/rest/src/main/java/org/apache/unomi/rest/validation/request/RequestValidatorInterceptor.java
@@ -22,6 +22,7 @@ import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.unomi.api.services.ConfigSharingService;
+import org.apache.unomi.rest.exception.InvalidRequestException;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
diff --git a/rest/src/main/java/org/apache/unomi/rest/validation/wrapper/CookieWrapper.java b/rest/src/main/java/org/apache/unomi/rest/validation/wrapper/CookieWrapper.java
deleted file mode 100644
index 6a5040eba..000000000
--- a/rest/src/main/java/org/apache/unomi/rest/validation/wrapper/CookieWrapper.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.unomi.rest.validation.wrapper;
-
-import org.apache.unomi.api.utils.ValidationPattern;
-
-import javax.validation.constraints.Pattern;
-
-/**
- * This class exists to allow to wrap a cookie value into an object and validate this object trough
- * the bean validation
- */
-public class CookieWrapper {
-
- @Pattern(regexp = ValidationPattern.TEXT_VALID_CHARACTERS_PATTERN)
- private String cookie;
-
- public CookieWrapper(String cookie) {
- this.cookie = cookie;
- }
-
-}
diff --git a/services/src/main/resources/META-INF/cxs/schemas/contextrequestparams.json b/services/src/main/resources/META-INF/cxs/schemas/contextrequestparams.json
new file mode 100644
index 000000000..6e115f3cb
--- /dev/null
+++ b/services/src/main/resources/META-INF/cxs/schemas/contextrequestparams.json
@@ -0,0 +1,16 @@
+{
+ "$id": "https://unomi.apache.org/schemas/json/contextrequestparams/1-0-0",
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "title": "ContextRequestParams",
+ "type": "object",
+ "properties": {
+ "personaId" : {
+ "type" : "string",
+ "pattern" : "^(\\w|[-_@\\.]){0,60}$"
+ },
+ "sessionId" : {
+ "type" : "string",
+ "pattern" : "^(\\w|[-_@\\.]){0,60}$"
+ }
+ }
+}
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/cxs/schemas/cookie.json b/services/src/main/resources/META-INF/cxs/schemas/cookie.json
new file mode 100644
index 000000000..1e82ada08
--- /dev/null
+++ b/services/src/main/resources/META-INF/cxs/schemas/cookie.json
@@ -0,0 +1,12 @@
+{
+ "$id": "https://unomi.apache.org/schemas/json/cookie/1-0-0",
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "title": "Cookie",
+ "type": "object",
+ "properties": {
+ "profileIdCookieName" : {
+ "type" : "string",
+ "pattern" : "^(\\w|[-_@\\.]){0,60}$"
+ }
+ }
+}
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/cxs/schemas/eventscollectorrequest.json b/services/src/main/resources/META-INF/cxs/schemas/eventscollectorrequest.json
index 39e98ff83..781ff2862 100644
--- a/services/src/main/resources/META-INF/cxs/schemas/eventscollectorrequest.json
+++ b/services/src/main/resources/META-INF/cxs/schemas/eventscollectorrequest.json
@@ -10,10 +10,11 @@
],
"properties": {
"events" : {
- "type": ["null", "array"],
+ "type": ["array"],
"items": {
"$ref": "https://unomi.apache.org/schemas/json/event/1-0-0"
- }
+ },
+ "minItems": 1
},
"sessionId" : {
"type": ["null", "string"],