From 76cd81a731bbda3dea2f55689218f9eeabfb4b02 Mon Sep 17 00:00:00 2001 From: Art Date: Tue, 28 Sep 2021 13:35:18 +0300 Subject: [PATCH] 27.2. Modified UserService to validate that user exists when `getDefaultProfileImage` method is invoked (#27) --- .../backend/exception/ExceptionHandling.java | 9 ++- .../backend/repository/UserRepository.java | 2 + .../backend/service/UserServiceImpl.java | 6 ++ .../controller/UserResourceUnSecureTest.java | 66 ++++++++++++++++--- 4 files changed, 72 insertions(+), 11 deletions(-) diff --git a/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/exception/ExceptionHandling.java b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/exception/ExceptionHandling.java index 041f597..f726ee8 100644 --- a/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/exception/ExceptionHandling.java +++ b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/exception/ExceptionHandling.java @@ -15,6 +15,7 @@ import org.springframework.validation.BindException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; import org.springframework.web.multipart.MaxUploadSizeExceededException; import org.springframework.web.servlet.NoHandlerFoundException; @@ -65,7 +66,8 @@ public class ExceptionHandling { @ExceptionHandler({ EmailExistsException.class, UsernameExistsException.class, EmailNotFoundException.class, UserNotFoundException.class, - MaxUploadSizeExceededException.class, NotAnImageFileException.class + MaxUploadSizeExceededException.class, NotAnImageFileException.class, + IllegalArgumentException.class }) public ResponseEntity badRequestExceptionHandler(Exception exception) { return createHttpResponse(BAD_REQUEST, exception.getMessage()); @@ -104,6 +106,11 @@ public class ExceptionHandling { return createHttpResponse(BAD_REQUEST, message); } + @ExceptionHandler({MethodArgumentTypeMismatchException.class}) + public ResponseEntity validationExceptionHandler(MethodArgumentTypeMismatchException exception) { + return createHttpResponse(BAD_REQUEST, exception.getCause().getMessage()); + } + @ExceptionHandler(NoResultException.class) public ResponseEntity notFoundException(NoResultException exception) { log.error(exception.getMessage()); diff --git a/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/repository/UserRepository.java b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/repository/UserRepository.java index 88eeb6f..48eee50 100644 --- a/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/repository/UserRepository.java +++ b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/repository/UserRepository.java @@ -16,6 +16,8 @@ public interface UserRepository extends JpaRepository { Boolean existsByEmail(String email); + Boolean existsByUserId(UUID userId); + Optional findByUserId(UUID userId); } diff --git a/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/service/UserServiceImpl.java b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/service/UserServiceImpl.java index b750a11..0edf303 100644 --- a/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/service/UserServiceImpl.java +++ b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/service/UserServiceImpl.java @@ -44,6 +44,7 @@ import static org.springframework.http.MediaType.*; public class UserServiceImpl implements UserService { public static final String USERNAME_NOT_FOUND_MSG = "User with username `%s` not found"; + public static final String USER_NOT_FOUND_MSG = "User not found"; public static final String USERNAME_EXISTS_MSG = "Username `%s` is already taken. Please select another one"; public static final String EMAIL_NOT_FOUND_MSG = "User with email `%s` not found"; public static final String EMAIL_EXISTS_MSG = "User with email `%s` is already registered"; @@ -278,6 +279,11 @@ public class UserServiceImpl implements UserService { @Override public byte[] getDefaultProfileImage(UUID userId) { + + if (!userRepository.existsByUserId(userId)) { + throw new UserNotFoundException(USER_NOT_FOUND_MSG); + } + // "https://robohash.org/11951691-d373-4126-bef2-84d157a6546b" RequestEntity requestEntity = RequestEntity .get("/{userId}", userId) diff --git a/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/controller/UserResourceUnSecureTest.java b/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/controller/UserResourceUnSecureTest.java index 3b68fd6..c563ff8 100644 --- a/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/controller/UserResourceUnSecureTest.java +++ b/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/controller/UserResourceUnSecureTest.java @@ -17,7 +17,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.mock.web.MockMultipartFile; @@ -38,6 +37,7 @@ import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.within; import static org.springframework.http.HttpStatus.*; +import static org.springframework.http.MediaType.*; @Slf4j @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -496,6 +496,8 @@ class UserResourceUnSecureTest extends BaseUserTest { //given long usersCount = userRepository.count(); + long DEFAULT_PAGEABLE_SIZE = 20; + usersCount = Math.min(DEFAULT_PAGEABLE_SIZE, usersCount); //when var responseEntity = restTemplate.exchange("/user", HttpMethod.GET, null, UserPage.class); @@ -581,7 +583,7 @@ class UserResourceUnSecureTest extends BaseUserTest { //when var requestEntity = RequestEntity.put("/user/{username}/profileImage", username) - .contentType(MediaType.MULTIPART_FORM_DATA) + .contentType(MULTIPART_FORM_DATA) .body(body); var responseEntity = restTemplate .exchange(requestEntity, User.class); @@ -623,7 +625,7 @@ class UserResourceUnSecureTest extends BaseUserTest { //when var requestEntity = RequestEntity.put("/user/{username}/profileImage", username) - .contentType(MediaType.MULTIPART_FORM_DATA) + .contentType(MULTIPART_FORM_DATA) .body(body); var responseEntity = restTemplate .exchange(requestEntity, HttpResponse.class); @@ -660,7 +662,7 @@ class UserResourceUnSecureTest extends BaseUserTest { //when RequestEntity requestEntity = RequestEntity.get("/user/{username}/image/profile", username) - .accept(MediaType.IMAGE_JPEG) + .accept(IMAGE_JPEG) .build(); var responseEntity = restTemplate.exchange(requestEntity, new ParameterizedTypeReference() { }); @@ -681,7 +683,7 @@ class UserResourceUnSecureTest extends BaseUserTest { //when RequestEntity requestEntity = RequestEntity.get("/user/{username}/image/profile", absentUsername) - .accept(MediaType.IMAGE_JPEG, MediaType.APPLICATION_JSON) + .accept(IMAGE_JPEG, APPLICATION_JSON) .build(); var responseEntity = restTemplate.exchange(requestEntity, HttpResponse.class); @@ -704,7 +706,7 @@ class UserResourceUnSecureTest extends BaseUserTest { //when RequestEntity requestEntity = RequestEntity.get("/user/{username}/image/profile", username) - .accept(MediaType.IMAGE_JPEG, MediaType.APPLICATION_JSON) + .accept(IMAGE_JPEG, APPLICATION_JSON) .build(); var responseEntity = restTemplate.exchange(requestEntity, HttpResponse.class); @@ -730,7 +732,7 @@ class UserResourceUnSecureTest extends BaseUserTest { //when RequestEntity requestEntity = RequestEntity.get(profileImageUrl) - .accept(MediaType.IMAGE_JPEG) + .accept(IMAGE_JPEG) .build(); var responseEntity = restTemplate.exchange(requestEntity, new ParameterizedTypeReference() { }); @@ -750,7 +752,7 @@ class UserResourceUnSecureTest extends BaseUserTest { //when RequestEntity requestEntity = RequestEntity.get("/user/image/profile/{userId}", userId) - .accept(MediaType.IMAGE_JPEG) + .accept(IMAGE_JPEG) .build(); var responseEntity = restTemplate.exchange(requestEntity, new ParameterizedTypeReference() { }); @@ -761,10 +763,54 @@ class UserResourceUnSecureTest extends BaseUserTest { assertThat(responseEntity.getBody()).hasSizeGreaterThan(52); } + @Test + void getDefaultProfileImage_absentUUID() { + + //given + UUID userId = UUID.randomUUID(); + + //when + RequestEntity requestEntity = RequestEntity.get("/user/image/profile/{userId}", userId) + .accept(IMAGE_JPEG, APPLICATION_JSON) + .build(); + var responseEntity = restTemplate.exchange(requestEntity, HttpResponse.class); + + //then + log.debug("Response Entity: {}", responseEntity); + assertThat(responseEntity.getStatusCode()).isEqualTo(BAD_REQUEST); + assertThat(responseEntity.getBody()) + .isNotNull() + .hasNoNullFieldsOrProperties() + .hasFieldOrPropertyWithValue("httpStatus", BAD_REQUEST) + .hasFieldOrPropertyWithValue("message", "User not found"); + } + + @Test + void getDefaultProfileImage_not_a_UUID() { + + //given + String userId = "not_a_UUID"; + + //when + RequestEntity requestEntity = RequestEntity.get("/user/image/profile/{userId}", userId) + .accept(IMAGE_JPEG, APPLICATION_JSON) + .build(); + var responseEntity = restTemplate.exchange(requestEntity, HttpResponse.class); + + //then + log.debug("Response Entity: {}", responseEntity); + assertThat(responseEntity.getStatusCode()).isEqualTo(BAD_REQUEST); + assertThat(responseEntity.getBody()) + .isNotNull() + .hasNoNullFieldsOrProperties() + .hasFieldOrPropertyWithValue("httpStatus", BAD_REQUEST) + .hasFieldOrPropertyWithValue("message", "Invalid UUID string: " + userId); + } + private void uploadProfileImage(String username) throws IOException { MultipartFile profileImage = new MockMultipartFile("profileImage", "test.jpg", - MediaType.IMAGE_JPEG_VALUE, ("Spring Framework" + UUID.randomUUID()).getBytes()); + IMAGE_JPEG_VALUE, ("Spring Framework" + UUID.randomUUID()).getBytes()); MultiValueMap body = new LinkedMultiValueMap<>(); @@ -772,7 +818,7 @@ class UserResourceUnSecureTest extends BaseUserTest { //when var requestEntity = RequestEntity.put("/user/{username}/profileImage", username) - .contentType(MediaType.MULTIPART_FORM_DATA) + .contentType(MULTIPART_FORM_DATA) .body(body); var responseEntity = restTemplate .exchange(requestEntity, User.class);