From 2bb46476744ea13c7da63878d7cc009fdb59a0f8 Mon Sep 17 00:00:00 2001 From: Colin DAMON <cdamon@ippon.fr> Date: Mon, 27 Jul 2020 16:42:44 +0200 Subject: [PATCH] Added error handling for query string --- .../primary/PouetErrorHandler.java | 15 ++++++++++ .../primary/ValidationMessage.java | 2 ++ src/main/resources/i18n/messages.properties | 2 ++ .../resources/i18n/messages_en.properties | 2 ++ .../primary/ErrorsResource.java | 3 ++ .../primary/PouetErrorHandlerIntTest.java | 28 +++++++++++++++++++ .../primary/QueryParameter.java | 18 ++++++++++++ 7 files changed, 70 insertions(+) create mode 100644 src/test/java/com/ippon/pouet/common/infrastructure/primary/QueryParameter.java diff --git a/src/main/java/com/ippon/pouet/common/infrastructure/primary/PouetErrorHandler.java b/src/main/java/com/ippon/pouet/common/infrastructure/primary/PouetErrorHandler.java index d152d50..d05bcb5 100644 --- a/src/main/java/com/ippon/pouet/common/infrastructure/primary/PouetErrorHandler.java +++ b/src/main/java/com/ippon/pouet/common/infrastructure/primary/PouetErrorHandler.java @@ -24,6 +24,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.core.AuthenticationException; +import org.springframework.validation.BindException; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; @@ -178,6 +179,20 @@ public class PouetErrorHandler extends ResponseEntityExceptionHandler { return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); } + @Override + protected ResponseEntity<Object> handleBindException( + BindException exception, + HttpHeaders headers, + HttpStatus status, + WebRequest request + ) { + List<PouetFieldError> fieldErrors = exception.getFieldErrors().stream().map(toPouetFieldError()).collect(Collectors.toList()); + + PouetError error = new PouetError(BAD_REQUEST_KEY, getMessage(BAD_REQUEST_KEY, null), fieldErrors); + + return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); + } + @ExceptionHandler public ResponseEntity<PouetError> handleBeanValidationError(ConstraintViolationException exception) { logger.debug("Bean validation error {}", exception.getMessage(), exception); diff --git a/src/main/java/com/ippon/pouet/common/infrastructure/primary/ValidationMessage.java b/src/main/java/com/ippon/pouet/common/infrastructure/primary/ValidationMessage.java index b7e0230..f8d1da3 100644 --- a/src/main/java/com/ippon/pouet/common/infrastructure/primary/ValidationMessage.java +++ b/src/main/java/com/ippon/pouet/common/infrastructure/primary/ValidationMessage.java @@ -3,6 +3,8 @@ package com.ippon.pouet.common.infrastructure.primary; public final class ValidationMessage { public static final String MANDATORY = "user.mandatory"; public static final String WRONG_FORMAT = "user.wrong-format"; + public static final String VALUE_TOO_LOW = "user.too-low"; + public static final String VALUE_TOO_HIGH = "user.too-high"; private ValidationMessage() {} } diff --git a/src/main/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties index 4be83a1..dbd8c49 100644 --- a/src/main/resources/i18n/messages.properties +++ b/src/main/resources/i18n/messages.properties @@ -29,6 +29,8 @@ pouet.error.status-exception=Une erreur {{ status }} est survenue lors du traite pouet.error.user.bad-request=Les données que vous avez saisies sont incorrectes. pouet.error.user.mandatory=Le champ est obligatoire. pouet.error.user.wrong-format=Le format n'est pas correct, il doit respecter "{{ regexp }}". +pouet.error.user.too-low=La valeur que vous avez entrée est trop petite, le minimum autorisé est {{ value }}. +pouet.error.user.too-high=La valeur que vous avez entrée est trop grande, le maximum autorisé est {{ value }}. pouet.error.user.authentication-not-authenticated=Vous devez être authentifié pour acceder à cette ressource. pouet.error.user.access-denied=Vous n'avez pas les droits suffisants pour acceder à cette ressource. pouet.error.user.e-mail-already-used=Cette adresse email est déjà utilisée dans pouet. diff --git a/src/main/resources/i18n/messages_en.properties b/src/main/resources/i18n/messages_en.properties index 519e397..e28c5af 100644 --- a/src/main/resources/i18n/messages_en.properties +++ b/src/main/resources/i18n/messages_en.properties @@ -29,6 +29,8 @@ pouet.error.status-exception=An error {{ status }} occured while handling your r pouet.error.user.bad-request=The values you entered are incorrects. pouet.error.user.mandatory=The field is mandatory. pouet.error.user.wrong-format=The format is incorrect, it has to match "{{ regexp }}". +pouet.error.user.too-low=The value you entered is too low, minimum autorized is {{ value }}. +pouet.error.user.too-high=The value you entered is too high, maximum authorized is {{ value }}. pouet.error.user.authentication-not-authenticated=You must be authenticated to access this resource. pouet.error.user.access-denied=You don't have sufficient rights to access this resource. pouet.error.user.e-mail-already-used=This email address is already used in the pouet. diff --git a/src/test/java/com/ippon/pouet/common/infrastructure/primary/ErrorsResource.java b/src/test/java/com/ippon/pouet/common/infrastructure/primary/ErrorsResource.java index 4baa1f0..57eb076 100644 --- a/src/test/java/com/ippon/pouet/common/infrastructure/primary/ErrorsResource.java +++ b/src/test/java/com/ippon/pouet/common/infrastructure/primary/ErrorsResource.java @@ -57,6 +57,9 @@ class ErrorsResource { throw new ResponseStatusException(HttpStatus.NOT_FOUND); } + @GetMapping + public void queryStringWithRangedValue(@Validated QueryParameter parameter) {} + @GetMapping("/{complicated}") public void complicatedArg( @Validated @Pattern(message = ValidationMessage.WRONG_FORMAT, regexp = "complicated") @PathVariable("complicated") String complicated diff --git a/src/test/java/com/ippon/pouet/common/infrastructure/primary/PouetErrorHandlerIntTest.java b/src/test/java/com/ippon/pouet/common/infrastructure/primary/PouetErrorHandlerIntTest.java index 12c223e..1e18521 100644 --- a/src/test/java/com/ippon/pouet/common/infrastructure/primary/PouetErrorHandlerIntTest.java +++ b/src/test/java/com/ippon/pouet/common/infrastructure/primary/PouetErrorHandlerIntTest.java @@ -111,6 +111,34 @@ class PouetErrorHandlerIntTest { .contains("Le format n'est pas correct, il doit respecter \\\"complicated\\\"."); } + @Test + public void shouldMapMinValueQueryStringBeanValidationErrors() throws Exception { + String response = mockMvc + .perform(get(errorEndpoint("?parameter=1")).header(HttpHeaders.ACCEPT_LANGUAGE, FRANCE_TAG)) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(UTF_8); + + assertThat(response) + .contains("Les données que vous avez saisies sont incorrectes.") + .contains("La valeur que vous avez entrée est trop petite, le minimum autorisé est 42."); + } + + @Test + public void shouldMapMaxValueQueryStringBeanValidationErrors() throws Exception { + String response = mockMvc + .perform(get(errorEndpoint("?parameter=100")).header(HttpHeaders.ACCEPT_LANGUAGE, FRANCE_TAG)) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(UTF_8); + + assertThat(response) + .contains("Les données que vous avez saisies sont incorrectes.") + .contains("La valeur que vous avez entrée est trop grande, le maximum autorisé est 42."); + } + @Test public void shouldMapBodyBeanValidationErrors() throws Exception { String response = mockMvc diff --git a/src/test/java/com/ippon/pouet/common/infrastructure/primary/QueryParameter.java b/src/test/java/com/ippon/pouet/common/infrastructure/primary/QueryParameter.java new file mode 100644 index 0000000..bb284b5 --- /dev/null +++ b/src/test/java/com/ippon/pouet/common/infrastructure/primary/QueryParameter.java @@ -0,0 +1,18 @@ +package com.ippon.pouet.common.infrastructure.primary; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; + +class QueryParameter { + private int parameter; + + @Min(message = ValidationMessage.VALUE_TOO_LOW, value = 42) + @Max(message = ValidationMessage.VALUE_TOO_HIGH, value = 42) + public int getParameter() { + return parameter; + } + + public void setParameter(int parameter) { + this.parameter = parameter; + } +} -- GitLab