diff --git a/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/controller/UserResource.java b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/controller/UserResource.java index 0b5824c..eb2cd5d 100644 --- a/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/controller/UserResource.java +++ b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/controller/UserResource.java @@ -23,6 +23,7 @@ import org.springframework.web.multipart.MultipartFile; import javax.validation.Valid; import java.io.IOException; +import java.util.UUID; import static org.springframework.http.HttpStatus.OK; @@ -93,7 +94,7 @@ public class UserResource { @DeleteMapping("{userId}") @PreAuthorize("hasAuthority('user:delete')") - public HttpResponse deleteUser(@PathVariable String userId) { + public HttpResponse deleteUser(@PathVariable UUID userId) { userService.deleteUser(userId); return HttpResponse.builder() .httpStatusCode(OK.value()) @@ -114,12 +115,12 @@ public class UserResource { } @GetMapping(path = "image/profile/{userId}/{filename}", produces = MediaType.IMAGE_JPEG_VALUE) - public byte[] getProfileImageByUserId(@PathVariable String userId, @PathVariable String filename) throws IOException { + public byte[] getProfileImageByUserId(@PathVariable UUID userId, @PathVariable String filename) throws IOException { return userService.getImageByUserId(userId, filename); } @GetMapping(path = "image/profile/{userId}", produces = MediaType.IMAGE_JPEG_VALUE) - public byte[] getDefaultProfileImage(@PathVariable String userId) { + public byte[] getDefaultProfileImage(@PathVariable UUID userId) { return userService.getDefaultProfileImage(userId); } diff --git a/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/domain/User.java b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/domain/User.java index 0c8d610..4cb3641 100644 --- a/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/domain/User.java +++ b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/domain/User.java @@ -2,13 +2,12 @@ package net.shyshkin.study.fullstack.supportportal.backend.domain; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; +import org.hibernate.annotations.Type; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import javax.persistence.*; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.UUID; @Entity @@ -27,7 +26,9 @@ public class User implements Serializable { @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private Long id; - private String userId; + @Type(type="org.hibernate.type.UUIDCharType") + @Column(length = 36, columnDefinition = "varchar(255)", updatable = false, nullable = false ) + private UUID userId; private String firstName; private String lastName; private String username; 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 d10882a..88eeb6f 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 @@ -4,6 +4,7 @@ import net.shyshkin.study.fullstack.supportportal.backend.domain.User; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; +import java.util.UUID; public interface UserRepository extends JpaRepository { @@ -15,6 +16,6 @@ public interface UserRepository extends JpaRepository { Boolean existsByEmail(String email); - Optional findByUserId(String userId); + Optional findByUserId(UUID userId); } diff --git a/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/service/UserService.java b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/service/UserService.java index b296db5..be3a0e3 100644 --- a/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/service/UserService.java +++ b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/service/UserService.java @@ -8,6 +8,7 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.util.UUID; public interface UserService extends UserDetailsService { @@ -23,7 +24,7 @@ public interface UserService extends UserDetailsService { User updateUser(String username, UserDto userDto); - void deleteUser(String userId); + void deleteUser(UUID userId); void resetPassword(String email); @@ -31,7 +32,7 @@ public interface UserService extends UserDetailsService { byte[] getProfileImage(String username) throws IOException; - byte[] getImageByUserId(String userId, String filename) throws IOException; + byte[] getImageByUserId(UUID userId, String filename) throws IOException; - byte[] getDefaultProfileImage(String userId); + byte[] getDefaultProfileImage(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 778ad27..b750a11 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 @@ -102,17 +102,17 @@ public class UserServiceImpl implements UserService { return addNewUser(newUserDto); } - private String generateDefaultProfileImageUrl(String userId) { + private String generateDefaultProfileImageUrl(UUID userId) { return ServletUriComponentsBuilder.fromCurrentContextPath() .path(DEFAULT_USER_IMAGE_PATH) - .pathSegment(userId) + .pathSegment(userId.toString()) .toUriString(); } - private String generateProfileImageUrl(String userId) { + private String generateProfileImageUrl(UUID userId) { return ServletUriComponentsBuilder.fromCurrentContextPath() .path(DEFAULT_USER_IMAGE_PATH) - .pathSegment(userId) + .pathSegment(userId.toString()) .pathSegment(USER_IMAGE_FILENAME) .toUriString(); } @@ -121,8 +121,8 @@ public class UserServiceImpl implements UserService { return RandomStringUtils.randomAscii(10); } - private String generateUserId() { - return UUID.randomUUID().toString(); + private UUID generateUserId() { + return UUID.randomUUID(); } @Override @@ -182,7 +182,7 @@ public class UserServiceImpl implements UserService { throw new NotAnImageFileException(profileImage.getOriginalFilename() + " is not an image file. Please upload an image"); } - Path userFolder = Paths.get(USER_FOLDER, user.getUserId()); + Path userFolder = Paths.get(USER_FOLDER, user.getUserId().toString()); try { if (Files.notExists(userFolder)) { Files.createDirectories(userFolder); @@ -200,7 +200,7 @@ public class UserServiceImpl implements UserService { private void deleteProfileImageFolder(User user) { - Path userFolder = Paths.get(USER_FOLDER, user.getUserId()); + Path userFolder = Paths.get(USER_FOLDER, user.getUserId().toString()); try { FileSystemUtils.deleteRecursively(userFolder); } catch (IOException exception) { @@ -232,7 +232,7 @@ public class UserServiceImpl implements UserService { } @Override - public void deleteUser(String userId) { + public void deleteUser(UUID userId) { User userToBeDeleted = userRepository .findByUserId(userId) .orElseThrow(() -> new UserNotFoundException("User was not found")); @@ -270,14 +270,14 @@ public class UserServiceImpl implements UserService { } @Override - public byte[] getImageByUserId(String userId, String filename) throws IOException { + public byte[] getImageByUserId(UUID userId, String filename) throws IOException { Path userProfileImagePath = Paths - .get(USER_FOLDER, userId, filename); + .get(USER_FOLDER, userId.toString(), filename); return Files.readAllBytes(userProfileImagePath); } @Override - public byte[] getDefaultProfileImage(String userId) { + public byte[] getDefaultProfileImage(UUID userId) { // "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/common/BaseUserTest.java b/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/common/BaseUserTest.java index 79f829d..537f7f2 100644 --- a/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/common/BaseUserTest.java +++ b/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/common/BaseUserTest.java @@ -27,7 +27,7 @@ public abstract class BaseUserTest { protected static User user; protected User createRandomUser() { - String userId = UUID.randomUUID().toString(); + UUID userId = UUID.randomUUID(); return User.builder() .email(FAKER.bothify("????##@example.com")) .firstName(FAKER.name().firstName()) @@ -58,11 +58,11 @@ public abstract class BaseUserTest { .build(); } - private String generateProfileImageUrl(String userId) { + private String generateProfileImageUrl(UUID userId) { return UriComponentsBuilder .fromUriString("http://localhost:8080") .path(DEFAULT_USER_IMAGE_PATH) - .pathSegment(userId) + .pathSegment(userId.toString()) // .pathSegment(USER_IMAGE_FILENAME) .toUriString(); } diff --git a/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/controller/UserResourceTest.java b/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/controller/UserResourceTest.java index 797badb..e5c5f33 100644 --- a/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/controller/UserResourceTest.java +++ b/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/controller/UserResourceTest.java @@ -576,7 +576,7 @@ class UserResourceTest extends BaseUserTest { .satisfies(u -> assertThat(u.getProfileImageUrl()).endsWith(String.format("/user/image/profile/%s/avatar.jpg", u.getUserId()))); User createdUser = responseEntity.getBody(); - Path path = Path.of(FileConstant.USER_FOLDER, createdUser.getUserId(), FileConstant.USER_IMAGE_FILENAME); + Path path = Path.of(FileConstant.USER_FOLDER, createdUser.getUserId().toString(), FileConstant.USER_IMAGE_FILENAME); log.debug("Path of created file: {}", path); assertThat(Files.exists(path)).isTrue(); assertThat(Files.getLastModifiedTime(path).toInstant()).isCloseTo(Instant.now(), within(1, ChronoUnit.SECONDS)); @@ -634,7 +634,7 @@ class UserResourceTest extends BaseUserTest { .satisfies(u -> assertThat(u.getProfileImageUrl()).endsWith(String.format("/user/image/profile/%s/avatar.jpg", u.getUserId()))); User createdUser = responseEntity.getBody(); - Path path = Path.of(FileConstant.USER_FOLDER, createdUser.getUserId(), FileConstant.USER_IMAGE_FILENAME); + Path path = Path.of(FileConstant.USER_FOLDER, createdUser.getUserId().toString(), FileConstant.USER_IMAGE_FILENAME); log.debug("Path of created file: {}", path); assertThat(Files.exists(path)).isTrue(); assertThat(Files.getLastModifiedTime(path).toInstant()).isCloseTo(Instant.now(), within(1, ChronoUnit.SECONDS)); @@ -657,7 +657,7 @@ class UserResourceTest extends BaseUserTest { superAdmin.setAuthorities(Role.ROLE_SUPER_ADMIN.getAuthorities()); String token = jwtTokenProvider.generateJwtToken(new UserPrincipal(superAdmin)); - String userId = user.getUserId(); + UUID userId = user.getUserId(); //when var requestEntity = RequestEntity.delete("/user/{userId}", userId) @@ -682,7 +682,7 @@ class UserResourceTest extends BaseUserTest { User roleUser = createRandomUser(); String token = jwtTokenProvider.generateJwtToken(new UserPrincipal(roleUser)); - String userId = user.getUserId(); + UUID userId = user.getUserId(); //when var requestEntity = RequestEntity.delete("/user/{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 3cc32df..3b68fd6 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 @@ -8,6 +8,7 @@ import net.shyshkin.study.fullstack.supportportal.backend.domain.HttpResponse; import net.shyshkin.study.fullstack.supportportal.backend.domain.Role; import net.shyshkin.study.fullstack.supportportal.backend.domain.User; import net.shyshkin.study.fullstack.supportportal.backend.domain.dto.UserDto; +import net.shyshkin.study.fullstack.supportportal.backend.repository.UserRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -48,6 +49,9 @@ class UserResourceUnSecureTest extends BaseUserTest { @Autowired TestRestTemplate restTemplate; + @Autowired + UserRepository userRepository; + @Nested class AddNewUserTests { @@ -490,6 +494,9 @@ class UserResourceUnSecureTest extends BaseUserTest { @Test void getAllUsers() { + //given + long usersCount = userRepository.count(); + //when var responseEntity = restTemplate.exchange("/user", HttpMethod.GET, null, UserPage.class); @@ -499,7 +506,7 @@ class UserResourceUnSecureTest extends BaseUserTest { assertThat(responseEntity.getBody()) .isNotNull(); assertThat(responseEntity.getBody().getContent()) - .hasSizeGreaterThan(2); + .hasSize(Math.toIntExact(usersCount)); } } @@ -594,7 +601,7 @@ class UserResourceUnSecureTest extends BaseUserTest { .hasFieldOrPropertyWithValue("role", user.getRole()) .satisfies(u -> assertThat(u.getProfileImageUrl()).endsWith(String.format("/user/image/profile/%s/avatar.jpg", user.getUserId()))); - Path path = Path.of(FileConstant.USER_FOLDER, user.getUserId(), FileConstant.USER_IMAGE_FILENAME); + Path path = Path.of(FileConstant.USER_FOLDER, user.getUserId().toString(), FileConstant.USER_IMAGE_FILENAME); log.debug("Path of created file: {}", path); assertThat(Files.exists(path)).isTrue(); assertThat(Files.getLastModifiedTime(path).toInstant()).isCloseTo(Instant.now(), within(100, ChronoUnit.MILLIS)); @@ -739,7 +746,7 @@ class UserResourceUnSecureTest extends BaseUserTest { void getDefaultProfileImage_correct() throws IOException { //given - String userId = user.getUserId(); + UUID userId = user.getUserId(); //when RequestEntity requestEntity = RequestEntity.get("/user/image/profile/{userId}", userId) @@ -785,7 +792,7 @@ class UserResourceUnSecureTest extends BaseUserTest { .hasFieldOrPropertyWithValue("role", user.getRole()) .satisfies(u -> assertThat(u.getProfileImageUrl()).endsWith(String.format("/user/image/profile/%s/avatar.jpg", user.getUserId()))); - Path path = Path.of(FileConstant.USER_FOLDER, user.getUserId(), FileConstant.USER_IMAGE_FILENAME); + Path path = Path.of(FileConstant.USER_FOLDER, user.getUserId().toString(), FileConstant.USER_IMAGE_FILENAME); log.debug("Path of created file: {}", path); assertThat(Files.exists(path)).isTrue(); assertThat(Files.getLastModifiedTime(path).toInstant()).isCloseTo(Instant.now(), within(200, ChronoUnit.MILLIS)); diff --git a/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/service/UserServiceTest.java b/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/service/UserServiceTest.java index 22b7e42..8d039dd 100644 --- a/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/service/UserServiceTest.java +++ b/support-portal-backend/src/test/java/net/shyshkin/study/fullstack/supportportal/backend/service/UserServiceTest.java @@ -125,7 +125,7 @@ class UserServiceTest extends BaseUserTest { userService.updateProfileImage(username, multipartFile); //then - Path path = Path.of(FileConstant.USER_FOLDER, user.getUserId(), FileConstant.USER_IMAGE_FILENAME); + Path path = Path.of(FileConstant.USER_FOLDER, user.getUserId().toString(), FileConstant.USER_IMAGE_FILENAME); log.debug("Path of created file: {}", path); assertThat(Files.exists(path)).isTrue(); assertThat(Files.getLastModifiedTime(path).toInstant()).isCloseTo(Instant.now(), within(100, ChronoUnit.MILLIS));