diff --git a/scm-webapp/src/main/java/sonia/scm/api/InvalidFormatExceptionMapper.java b/scm-webapp/src/main/java/sonia/scm/api/InvalidFormatExceptionMapper.java new file mode 100644 index 0000000000..97dd96a23a --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/InvalidFormatExceptionMapper.java @@ -0,0 +1,59 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api; + +import com.fasterxml.jackson.databind.exc.InvalidFormatException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import sonia.scm.api.v2.resources.ErrorDto; +import sonia.scm.web.VndMediaType; + +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; +import java.util.Collections; + +@Provider +public class InvalidFormatExceptionMapper implements ExceptionMapper { + + private static final Logger LOG = LoggerFactory.getLogger(InvalidFormatExceptionMapper.class); + + private static final String ERROR_CODE = "2qRyyaVcJ1"; + + @Override + public Response toResponse(InvalidFormatException exception) { + LOG.trace("got invalid format in json: {}", exception.getMessage()); + ErrorDto errorDto = new ErrorDto(); + errorDto.setMessage("invalid format in json content: " + exception.getMessage()); + errorDto.setContext(Collections.emptyList()); + errorDto.setErrorCode(ERROR_CODE); + errorDto.setTransactionId(MDC.get("transaction_id")); + return Response.status(Response.Status.BAD_REQUEST) + .entity(errorDto) + .type(VndMediaType.ERROR_TYPE) + .build(); + } +} diff --git a/scm-webapp/src/main/resources/locales/de/plugins.json b/scm-webapp/src/main/resources/locales/de/plugins.json index 8c5c88e0f8..314dac3de4 100644 --- a/scm-webapp/src/main/resources/locales/de/plugins.json +++ b/scm-webapp/src/main/resources/locales/de/plugins.json @@ -215,6 +215,10 @@ "8nRuFzjss1": { "displayName": "Fehler beim Löschen falscher Downloads", "description": "Ein fehlerhaft heruntergeladenes Plugin konnte nicht gelöscht werden. Bitte prüfen Sie die Server Logs und löschen die Datei manuell." + }, + "2qRyyaVcJ1": { + "displayName": "Ungültig formatiertes Element", + "description": "Die Eingabe beinhaltete unfültige Formate. Bitte prüfen Sie die Server Logs für genauere Informationen." } }, "namespaceStrategies": { diff --git a/scm-webapp/src/main/resources/locales/en/plugins.json b/scm-webapp/src/main/resources/locales/en/plugins.json index 998e796bac..fba82da650 100644 --- a/scm-webapp/src/main/resources/locales/en/plugins.json +++ b/scm-webapp/src/main/resources/locales/en/plugins.json @@ -215,6 +215,10 @@ "8nRuFzjss1": { "displayName": "Error while cleaning up failed plugin", "description": "A failed plugin download could not be removed correctly. Please check the server log and remove the plugin manually." + }, + "2qRyyaVcJ1": { + "displayName": "Invalid format in element", + "description": "The input had some invalid formats. Please check the server log for further information." } }, "namespaceStrategies": { diff --git a/scm-webapp/src/test/java/sonia/scm/api/InvalidFormatExceptionMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/InvalidFormatExceptionMapperTest.java new file mode 100644 index 0000000000..c06da77c92 --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/api/InvalidFormatExceptionMapperTest.java @@ -0,0 +1,74 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.api; + +import org.jboss.resteasy.mock.MockDispatcherFactory; +import org.jboss.resteasy.mock.MockHttpRequest; +import org.jboss.resteasy.mock.MockHttpResponse; +import org.jboss.resteasy.spi.Dispatcher; +import org.junit.jupiter.api.Test; + +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; + +import static org.assertj.core.api.Assertions.assertThat; + +class InvalidFormatExceptionMapperTest { + + @Test + void shouldMapInvalidFormatExceptionDueToInvalidEnum() throws URISyntaxException, UnsupportedEncodingException { + Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + dispatcher.getRegistry().addSingletonResource(new SimpleResource()); + dispatcher.getProviderFactory().registerProvider(InvalidFormatExceptionMapper.class); + + MockHttpRequest request = MockHttpRequest + .post("/") + .contentType("application/json") + .content("{\"e\": \"NONE\"}".getBytes()); + MockHttpResponse response = new MockHttpResponse(); + + dispatcher.invoke(request, response); + + assertThat(response.getStatus()).isEqualTo(400); + assertThat(response.getContentAsString()).contains("2qRyyaVcJ1"); + } + + @Path("/") + static class SimpleResource { + @POST + public void post(ObjectWithEnum o) { + } + } + + static class ObjectWithEnum { + public Enum e; + } + + enum Enum { + ONE, TWO + } +}