forked from eclipse-kapua/kapua
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request eclipse-kapua#4117 from Agnul97/feature-propagate-…
…exceptions-jaxb ⚡ [REST API] Block execution on XML/JSON parsing errors and report 400 error code
- Loading branch information
Showing
9 changed files
with
234 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
...rrors/src/main/java/org/eclipse/kapua/commons/rest/errors/EclipseLinkExceptionMapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2021, 2022 Eurotech and/or its affiliates and others | ||
* | ||
* This program and the accompanying materials are made | ||
* available under the terms of the Eclipse Public License 2.0 | ||
* which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
* | ||
* Contributors: | ||
* Eurotech - initial API and implementation | ||
*******************************************************************************/ | ||
package org.eclipse.kapua.commons.rest.errors; | ||
|
||
import org.eclipse.kapua.commons.rest.model.errors.ThrowableInfo; | ||
import org.eclipse.persistence.exceptions.ConversionException; | ||
import org.eclipse.persistence.exceptions.DescriptorException; | ||
import org.eclipse.persistence.exceptions.EclipseLinkException; | ||
import org.eclipse.persistence.exceptions.XMLConversionException; | ||
|
||
import org.eclipse.persistence.exceptions.XMLMarshalException; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import javax.inject.Inject; | ||
import javax.ws.rs.core.Response; | ||
import javax.ws.rs.ext.ExceptionMapper; | ||
import javax.ws.rs.ext.Provider; | ||
|
||
@Provider | ||
public class EclipseLinkExceptionMapper implements ExceptionMapper<EclipseLinkException> { | ||
|
||
private static final Logger LOG = LoggerFactory.getLogger(EclipseLinkExceptionMapper.class); | ||
|
||
private final boolean showStackTrace; | ||
|
||
@Inject | ||
public EclipseLinkExceptionMapper(ExceptionConfigurationProvider exceptionConfigurationProvider) { | ||
this.showStackTrace = exceptionConfigurationProvider.showStackTrace(); | ||
} | ||
|
||
@Override | ||
public Response toResponse(EclipseLinkException eclipseException) { | ||
LOG.error(eclipseException.getMessage(), eclipseException); | ||
|
||
if (eclipseException instanceof ConversionException || | ||
eclipseException instanceof DescriptorException || | ||
eclipseException instanceof XMLMarshalException || | ||
eclipseException instanceof XMLConversionException) { // These are subset of EclipseLinkExceptions thrown by MOXy, so we have a problem with JAXB parsing of the XML/JSON | ||
ThrowableInfo responseError = new ThrowableInfo(Response.Status.BAD_REQUEST.getStatusCode(), eclipseException, showStackTrace); | ||
responseError.setMessage("An error occurred during the parsing of the XML/JSON. Check the correctness of its format. Details of the exception thrown: " + responseError.getMessage()); | ||
return Response | ||
.status(Response.Status.BAD_REQUEST) | ||
.entity(responseError) | ||
.build(); | ||
} else { | ||
//Generic error message for other EclipseLinkExceptions | ||
return Response | ||
.serverError() | ||
.entity(new ThrowableInfo(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), eclipseException, showStackTrace)) | ||
.build(); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
...tegration/src/test/java/org/eclipse/kapua/integration/rest/RunRestParsingRequestTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2018, 2022 Eurotech and/or its affiliates and others | ||
* | ||
* This program and the accompanying materials are made | ||
* available under the terms of the Eclipse Public License 2.0 | ||
* which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
* | ||
* Contributors: | ||
* Eurotech | ||
*******************************************************************************/ | ||
package org.eclipse.kapua.integration.rest; | ||
|
||
import io.cucumber.junit.Cucumber; | ||
import io.cucumber.junit.CucumberOptions; | ||
import org.junit.runner.RunWith; | ||
|
||
@RunWith(Cucumber.class) | ||
@CucumberOptions( | ||
features = "classpath:features/rest/parsingRequests/RestParsingRequestsContents.feature", | ||
glue = {"org.eclipse.kapua.qa.common", | ||
"org.eclipse.kapua.qa.integration.steps", | ||
"org.eclipse.kapua.service.endpoint.steps", | ||
"org.eclipse.kapua.service.account.steps", | ||
"org.eclipse.kapua.service.user.steps" | ||
}, | ||
plugin = { "pretty", | ||
"html:target/cucumber/RestCors", | ||
"json:target/RestCors_cucumber.json" | ||
}, | ||
monochrome = true) | ||
public class RunRestParsingRequestTest { | ||
} |
64 changes: 64 additions & 0 deletions
64
...tion/src/test/resources/features/rest/parsingRequests/RestParsingRequestsContents.feature
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
############################################################################### | ||
# Copyright (c) 2018, 2022 Eurotech and/or its affiliates and others | ||
# | ||
# This program and the accompanying materials are made | ||
# available under the terms of the Eclipse Public License 2.0 | ||
# which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
# | ||
# SPDX-License-Identifier: EPL-2.0 | ||
# | ||
# Contributors: | ||
# Eurotech - initial API and implementation | ||
############################################################################### | ||
@env_docker_base | ||
@rest_parsing | ||
|
||
Feature: REST API tests for parsing of requests | ||
REST API tests to verify correct responses upon parsing of wrong format fields in requests | ||
|
||
@setup | ||
Scenario: Initialize security context, then start rest-api container and dependencies | ||
Given Init Security Context | ||
And start rest-API container and dependencies with auth token TTL "10000"ms and refresh token TTL "20000"ms and cors endpoint refresh interval 5s | ||
|
||
Scenario: Creation of a device with a wrong format "status" field | ||
api back-end parser (MOXy) should spot error on the format and the mico-service should reply with 400 error code | ||
|
||
Given Server with host "127.0.0.1" on port "8081" | ||
Given An authenticated user | ||
When REST "POST" call at "/v1/_/devices" with JSON "{\"clientId\": \"wrongStatusDevice\", \"status\": \"FOOOO\"}" | ||
Then REST response code is 400 | ||
And REST response containing text "An error occurred during the parsing of the XML/JSON" | ||
|
||
Scenario: Update of "credentialService" configuration missing to include the "type" field but providing the "value" field | ||
api back-end parser (MOXy) should spot error on the format and the mico-service should reply with 400 error code | ||
Given Server with host "127.0.0.1" on port "8081" | ||
Given An authenticated user | ||
When REST "PUT" call at "/v1/_/serviceConfigurations/org.eclipse.kapua.service.authentication.credential.CredentialService" with JSON "{\"id\": \"org.eclipse.kapua.service.authentication.credential.CredentialService\", \"properties\": {\"property\": [{\"name\": \"password.minLength\", \"array\": false, \"encrypted\": false, \"value\": [\"13\"]}]}}" | ||
Then REST response code is 400 | ||
And REST response containing text "An error occurred during the parsing of the XML/JSON" | ||
And REST response containing text "Illegal 'null' value for 'property.type' for parameter: password.minLength" | ||
|
||
Scenario: Update of an user setting a wrong format "expirationDate" field | ||
api back-end parser (MOXy) should spot error on the format and the micro-service should reply with 400 error code | ||
Given Server with host "127.0.0.1" on port "8081" | ||
Given An authenticated user | ||
#now let's try to update kapua-broker with a not parsable expiration date | ||
When REST "PUT" call at "/v1/_/users/Ag" with JSON "{\"optlock\": 1, \"name\": \"kapua-broker\", \"expirationDate\": \"randomwrongvaluenotparsabledate\"}" | ||
Then REST response code is 400 | ||
And REST response containing text "An error occurred during the parsing of the XML/JSON" | ||
|
||
Scenario: Update of "credentialService" configuration missing to include the "type" field AND the "value" field | ||
api back-end parser (MOXy) should NOT spot error because we are trying to update a property with a "default" value | ||
Given Server with host "127.0.0.1" on port "8081" | ||
Given An authenticated user | ||
#the json is a huge string but basically it's a complete set of properties for the CredentialService, where the "password.minLength" property we want to set has missing "type" and "value" fields (we want to set an unlimited value for it) | ||
When REST "PUT" call at "/v1/_/serviceConfigurations/org.eclipse.kapua.service.authentication.credential.CredentialService" with JSON "{\"id\": \"org.eclipse.kapua.service.authentication.credential.CredentialService\", \"properties\": {\"property\": [{\"name\": \"lockoutPolicy.resetAfter\", \"array\": false, \"encrypted\": false, \"type\": \"Integer\", \"value\": [\"3800\"]}, {\"name\": \"password.minLength\", \"array\": false, \"encrypted\": false}, {\"name\": \"lockoutPolicy.lockDuration\", \"array\": false, \"encrypted\": false, \"type\": \"Integer\", \"value\": [\"10800\"]}, {\"name\": \"lockoutPolicy.enabled\", \"array\": false, \"encrypted\": false, \"type\": \"Boolean\", \"value\": [\"true\"]}, {\"name\": \"lockoutPolicy.maxFailures\", \"array\": false, \"encrypted\": false, \"type\": \"Integer\", \"value\": [\"3\"]}]}}" | ||
Then REST response code is 204 | ||
|
||
@teardown | ||
Scenario: Stop full docker environment | ||
Given Stop full docker environment | ||
And Clean Locator Instance | ||
|
||
|
53 changes: 53 additions & 0 deletions
53
...pi/web/src/main/java/org/eclipse/kapua/app/api/web/MoxyJsonFeatureCustomJsonProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2016, 2022 Eurotech and/or its affiliates and others | ||
* | ||
* This program and the accompanying materials are made | ||
* available under the terms of the Eclipse Public License 2.0 | ||
* which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
* | ||
* Contributors: | ||
* Eurotech - initial API and implementation | ||
*******************************************************************************/ | ||
package org.eclipse.kapua.app.api.web; | ||
|
||
import org.glassfish.jersey.internal.InternalProperties; | ||
import org.glassfish.jersey.internal.util.PropertiesHelper; | ||
import javax.ws.rs.core.Configuration; | ||
import javax.ws.rs.core.Feature; | ||
import javax.ws.rs.core.FeatureContext; | ||
import javax.ws.rs.core.MediaType; | ||
import javax.ws.rs.core.MultivaluedMap; | ||
import javax.ws.rs.ext.Provider; | ||
import javax.xml.bind.JAXBException; | ||
import javax.xml.bind.Unmarshaller; | ||
import javax.xml.bind.helpers.DefaultValidationEventHandler; | ||
import java.lang.annotation.Annotation; | ||
import java.lang.reflect.Type; | ||
|
||
public class MoxyJsonFeatureCustomJsonProvider implements Feature { | ||
//A custom feature used to set a custom moxyJsonProvider | ||
|
||
private static final String JSON_FEATURE = MoxyJsonFeatureCustomJsonProvider.class.getSimpleName(); | ||
|
||
@Override | ||
public boolean configure(final FeatureContext context) { | ||
final Configuration config = context.getConfiguration(); | ||
// Disable other JSON providers. In this way the org.glassfish.jersey.moxy.json.MoxyJsonFeature (registered as default by MOXy) will skip the registration of the default provider | ||
context.property(PropertiesHelper.getPropertyNameForRuntime(InternalProperties.JSON_FEATURE, config.getRuntimeType()), | ||
JSON_FEATURE); | ||
context.register(CustomMoxyJsonProvider.class); | ||
return true; | ||
} | ||
|
||
@Provider | ||
public static class CustomMoxyJsonProvider extends org.glassfish.jersey.moxy.json.internal.ConfigurableMoxyJsonProvider { | ||
//A custom moxyJsonProvider that sets the unmarshaller validationEventHandler to the default one. This one allows to propagate exceptions to the stack when an error is found (for example, when an exception has been thrown from one of our custom "xmlAdapters") | ||
@Override | ||
protected void preReadFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, Unmarshaller unmarshaller) throws JAXBException { | ||
super.preReadFrom(type, genericType, annotations, mediaType, httpHeaders, unmarshaller); | ||
unmarshaller.setEventHandler(new DefaultValidationEventHandler()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters