From f5cff82e1ff3ae0aa04cee31d9515a71e3c06415 Mon Sep 17 00:00:00 2001 From: Shulpov Victor Date: Sat, 11 Nov 2023 03:07:47 +0700 Subject: [PATCH] refactor: user controller method, dto classes --- .../validators/UserValidator.java | 2 +- .../spots_app/comments/CommentController.java | 14 +- .../spots_app/comments/CommentDto.java | 40 +----- .../comments/utils/CommentDtoConverter.java | 26 ++++ .../image_infos/ImageInfoController.java | 2 +- .../image_infos/dto/ImageInfoDto.java | 3 +- .../utils/ImageInfoDtoConverter.java | 34 +++++ .../spot_user_infos/SpotUserController.java | 2 +- .../spots_app/spots/SpotController.java | 2 +- .../spots_app/users/UserController.java | 74 +++++------ .../spots_app/users/dto/MainUserInfoDto.java | 31 +++++ .../shulpov/spots_app/users/dto/UserDto.java | 122 ------------------ .../spots_app/users/dto/UserFullInfoDto.java | 48 +++++++ .../users/dto/UserWithoutSpotsDto.java | 25 ---- .../exception/UserNotFoundException.java | 10 ++ .../users/{ => services}/UserService.java | 35 ++++- .../users/utils/UserDtoConverter.java | 34 +++++ .../shulpov/spots_app/utils/DtoConverter.java | 101 +-------------- .../java/com/shulpov/spots_app/AuthTests.java | 2 +- 19 files changed, 274 insertions(+), 333 deletions(-) create mode 100644 src/main/java/com/shulpov/spots_app/comments/utils/CommentDtoConverter.java create mode 100644 src/main/java/com/shulpov/spots_app/image_infos/utils/ImageInfoDtoConverter.java create mode 100644 src/main/java/com/shulpov/spots_app/users/dto/MainUserInfoDto.java delete mode 100644 src/main/java/com/shulpov/spots_app/users/dto/UserDto.java create mode 100644 src/main/java/com/shulpov/spots_app/users/dto/UserFullInfoDto.java delete mode 100644 src/main/java/com/shulpov/spots_app/users/dto/UserWithoutSpotsDto.java create mode 100644 src/main/java/com/shulpov/spots_app/users/exception/UserNotFoundException.java rename src/main/java/com/shulpov/spots_app/users/{ => services}/UserService.java (64%) create mode 100644 src/main/java/com/shulpov/spots_app/users/utils/UserDtoConverter.java diff --git a/src/main/java/com/shulpov/spots_app/authentication_management/validators/UserValidator.java b/src/main/java/com/shulpov/spots_app/authentication_management/validators/UserValidator.java index cb47deb..31cd67f 100644 --- a/src/main/java/com/shulpov/spots_app/authentication_management/validators/UserValidator.java +++ b/src/main/java/com/shulpov/spots_app/authentication_management/validators/UserValidator.java @@ -1,6 +1,6 @@ package com.shulpov.spots_app.authentication_management.validators; -import com.shulpov.spots_app.users.UserService; +import com.shulpov.spots_app.users.services.UserService; import com.shulpov.spots_app.users.models.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/shulpov/spots_app/comments/CommentController.java b/src/main/java/com/shulpov/spots_app/comments/CommentController.java index 060a45d..2b7e1c5 100644 --- a/src/main/java/com/shulpov/spots_app/comments/CommentController.java +++ b/src/main/java/com/shulpov/spots_app/comments/CommentController.java @@ -1,8 +1,8 @@ package com.shulpov.spots_app.comments; +import com.shulpov.spots_app.comments.utils.CommentDtoConverter; import com.shulpov.spots_app.users.models.User; -import com.shulpov.spots_app.users.UserService; -import com.shulpov.spots_app.utils.DtoConverter; +import com.shulpov.spots_app.users.services.UserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; @@ -30,13 +30,15 @@ public class CommentController { private final CommentService commentService; private final UserService userService; private final Logger logger = LoggerFactory.getLogger(CommentController.class); - private final DtoConverter dtoConverter; + + private final CommentDtoConverter commentDtoConverter; @Autowired - public CommentController(CommentService commentService, @Lazy UserService userService, @Lazy DtoConverter dtoConverter) { + public CommentController( + CommentService commentService, @Lazy UserService userService, CommentDtoConverter commentDtoConverter) { this.commentService = commentService; this.userService = userService; - this.dtoConverter = dtoConverter; + this.commentDtoConverter = commentDtoConverter; } @Operation( @@ -96,6 +98,6 @@ public Map deleteById(@PathVariable Long commentId, Principal pr @GetMapping("/get-by-spot-id/{spotId}") public List getBySpotId(@PathVariable Long spotId) { logger.atInfo().log("/get-by-spot-id/{}", spotId); - return commentService.findByCommentedSpotId(spotId).stream().map(dtoConverter::commentToDto).toList(); + return commentService.findByCommentedSpotId(spotId).stream().map(commentDtoConverter::commentToDto).toList(); } } diff --git a/src/main/java/com/shulpov/spots_app/comments/CommentDto.java b/src/main/java/com/shulpov/spots_app/comments/CommentDto.java index b9bf8b8..4f63ee9 100644 --- a/src/main/java/com/shulpov/spots_app/comments/CommentDto.java +++ b/src/main/java/com/shulpov/spots_app/comments/CommentDto.java @@ -1,11 +1,15 @@ package com.shulpov.spots_app.comments; -import com.shulpov.spots_app.users.dto.UserWithoutSpotsDto; +import com.shulpov.spots_app.users.dto.MainUserInfoDto; import jakarta.validation.constraints.Size; +import lombok.Getter; +import lombok.Setter; import org.apache.logging.log4j.core.config.plugins.validation.constraints.NotBlank; import java.util.Date; +@Getter +@Setter public class CommentDto { private Long id; @@ -15,37 +19,5 @@ public class CommentDto { private Date uploadDate; - private UserWithoutSpotsDto commentatorDto; - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public Date getUploadDate() { - return uploadDate; - } - - public void setUploadDate(Date uploadDate) { - this.uploadDate = uploadDate; - } - - public UserWithoutSpotsDto getCommentatorDto() { - return commentatorDto; - } - - public void setCommentatorDto(UserWithoutSpotsDto commentatorDto) { - this.commentatorDto = commentatorDto; - } + private MainUserInfoDto commentatorDto; } diff --git a/src/main/java/com/shulpov/spots_app/comments/utils/CommentDtoConverter.java b/src/main/java/com/shulpov/spots_app/comments/utils/CommentDtoConverter.java new file mode 100644 index 0000000..d52136e --- /dev/null +++ b/src/main/java/com/shulpov/spots_app/comments/utils/CommentDtoConverter.java @@ -0,0 +1,26 @@ +package com.shulpov.spots_app.comments.utils; + +import com.shulpov.spots_app.comments.Comment; +import com.shulpov.spots_app.comments.CommentDto; +import com.shulpov.spots_app.users.dto.MainUserInfoDto; +import com.shulpov.spots_app.users.utils.UserDtoConverter; +import org.modelmapper.ModelMapper; +import org.springframework.stereotype.Component; + +@Component +public class CommentDtoConverter { + private final ModelMapper modelMapper; + private final UserDtoConverter userDtoConverter; + + public CommentDtoConverter(ModelMapper modelMapper, UserDtoConverter userDtoConverter) { + this.modelMapper = modelMapper; + this.userDtoConverter = userDtoConverter; + } + + public CommentDto commentToDto(Comment comment) { + CommentDto dto = modelMapper.map(comment, CommentDto.class); + MainUserInfoDto mainUserInfoDto = userDtoConverter.userToUserMainInfoDto(comment.getCommentator()); + dto.setCommentatorDto(mainUserInfoDto); + return dto; + } +} diff --git a/src/main/java/com/shulpov/spots_app/image_infos/ImageInfoController.java b/src/main/java/com/shulpov/spots_app/image_infos/ImageInfoController.java index 18830ec..2eb6183 100644 --- a/src/main/java/com/shulpov/spots_app/image_infos/ImageInfoController.java +++ b/src/main/java/com/shulpov/spots_app/image_infos/ImageInfoController.java @@ -2,7 +2,7 @@ import com.shulpov.spots_app.image_infos.models.ImageInfo; import com.shulpov.spots_app.users.models.User; -import com.shulpov.spots_app.users.UserService; +import com.shulpov.spots_app.users.services.UserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; diff --git a/src/main/java/com/shulpov/spots_app/image_infos/dto/ImageInfoDto.java b/src/main/java/com/shulpov/spots_app/image_infos/dto/ImageInfoDto.java index 277a572..e1d16c9 100644 --- a/src/main/java/com/shulpov/spots_app/image_infos/dto/ImageInfoDto.java +++ b/src/main/java/com/shulpov/spots_app/image_infos/dto/ImageInfoDto.java @@ -1,8 +1,9 @@ package com.shulpov.spots_app.image_infos.dto; +import java.io.Serializable; import java.util.Date; -public class ImageInfoDto { +public class ImageInfoDto implements Serializable { private Long id; private String url; diff --git a/src/main/java/com/shulpov/spots_app/image_infos/utils/ImageInfoDtoConverter.java b/src/main/java/com/shulpov/spots_app/image_infos/utils/ImageInfoDtoConverter.java new file mode 100644 index 0000000..e7e733d --- /dev/null +++ b/src/main/java/com/shulpov/spots_app/image_infos/utils/ImageInfoDtoConverter.java @@ -0,0 +1,34 @@ +package com.shulpov.spots_app.image_infos.utils; + +import com.shulpov.spots_app.image_infos.dto.ImageInfoDto; +import com.shulpov.spots_app.image_infos.models.ImageInfo; +import com.shulpov.spots_app.utils.ImageUtil; +import org.modelmapper.ModelMapper; +import org.springframework.stereotype.Component; + +@Component +public class ImageInfoDtoConverter { + private final ModelMapper modelMapper; + + public ImageInfoDtoConverter(ModelMapper modelMapper) { + this.modelMapper = modelMapper; + } + + /** + * Конвертор класса ImageInfo в класс ImageInfoDto + */ + public ImageInfoDto imageInfoToDto(ImageInfo imageInfo) throws NullPointerException { + ImageInfoDto dto = modelMapper.map(imageInfo, ImageInfoDto.class); + + if(imageInfo.getPhotographedUser() != null) { + String url = ImageUtil.getUserImageDownloadUrl(imageInfo.getId()); + dto.setUrl(url); + } else if(imageInfo.getPhotographedSpot() != null) { + String url = ImageUtil.getSpotImageDownloadUrl(imageInfo.getId()); + dto.setUrl(url); + } else { + throw new NullPointerException("Invalid image info object (user and spot are null)"); + } + return dto; + } +} diff --git a/src/main/java/com/shulpov/spots_app/spot_user_infos/SpotUserController.java b/src/main/java/com/shulpov/spots_app/spot_user_infos/SpotUserController.java index dc99429..59ebf96 100644 --- a/src/main/java/com/shulpov/spots_app/spot_user_infos/SpotUserController.java +++ b/src/main/java/com/shulpov/spots_app/spot_user_infos/SpotUserController.java @@ -6,7 +6,7 @@ import com.shulpov.spots_app.spots.models.Spot; import com.shulpov.spots_app.users.models.User; import com.shulpov.spots_app.spots.SpotService; -import com.shulpov.spots_app.users.UserService; +import com.shulpov.spots_app.users.services.UserService; import com.shulpov.spots_app.utils.DtoConverter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; diff --git a/src/main/java/com/shulpov/spots_app/spots/SpotController.java b/src/main/java/com/shulpov/spots_app/spots/SpotController.java index 86b51ec..7db207c 100644 --- a/src/main/java/com/shulpov/spots_app/spots/SpotController.java +++ b/src/main/java/com/shulpov/spots_app/spots/SpotController.java @@ -5,7 +5,7 @@ import com.shulpov.spots_app.spots.dto.SpotDto; import com.shulpov.spots_app.spots.models.Spot; import com.shulpov.spots_app.users.models.User; -import com.shulpov.spots_app.users.UserService; +import com.shulpov.spots_app.users.services.UserService; import com.shulpov.spots_app.utils.DtoConverter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; diff --git a/src/main/java/com/shulpov/spots_app/users/UserController.java b/src/main/java/com/shulpov/spots_app/users/UserController.java index 3aeda78..4e0a73d 100644 --- a/src/main/java/com/shulpov/spots_app/users/UserController.java +++ b/src/main/java/com/shulpov/spots_app/users/UserController.java @@ -1,70 +1,61 @@ package com.shulpov.spots_app.users; -import com.shulpov.spots_app.users.dto.UserDto; +import com.shulpov.spots_app.responses.ErrorMessageResponse; +import com.shulpov.spots_app.users.dto.MainUserInfoDto; +import com.shulpov.spots_app.users.exception.UserNotFoundException; import com.shulpov.spots_app.users.models.User; -import com.shulpov.spots_app.utils.DtoConverter; +import com.shulpov.spots_app.users.services.UserService; +import io.jsonwebtoken.JwtException; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.Map; import java.util.Optional; @RestController -@RequestMapping("/api/v1") +@RequestMapping("/api/v1/user") @Tag(name="Контроллер пользователя", description="Позволяет получать информацию о пользователе и удалять аккаунт") public class UserController { private final UserService userService; - private final DtoConverter dtoConverter; private final Logger logger = LoggerFactory.getLogger(UserController.class); @Autowired - public UserController(UserService userService, @Lazy DtoConverter dtoConverter) { + public UserController(UserService userService) { this.userService = userService; - this.dtoConverter = dtoConverter; } @Operation( summary = "Получение полной информации о пользователе", description = "Позволяет получить полную информацию о пользователе", - security = @SecurityRequirement(name = "accessTokenAuth") + security = @SecurityRequirement(name = "accessTokenAuth"), + responses = { + @ApiResponse(responseCode = "200", description = "Данные пользователя успешно получены", + content = { @Content(mediaType = "application/json", + schema = @Schema(implementation = MainUserInfoDto.class)) } + ), + @ApiResponse(responseCode = "400", description = "Пользователь не был найден или получены ошибки JWT", + content = { @Content(mediaType = "application/json", + schema = @Schema(implementation = ErrorMessageResponse.class)) } + )} ) - @GetMapping("/user") - public ResponseEntity getAuthUser() { - logger.atInfo().log("GET /user"); - String email; - try { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - UserDetails userDetails = (UserDetails) authentication.getPrincipal(); - email = userDetails.getUsername(); - } catch (UsernameNotFoundException e) { - logger.atInfo().log("GET /user email={} not found"); - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); - } - Optional userOpt = userService.findByEmail(email); - - if(userOpt.isPresent()) { - logger.atInfo().log("principle exists"); - User user = userOpt.get(); - - return new ResponseEntity<>(dtoConverter.userToDto(user), HttpStatus.OK); - } - - logger.atInfo().log("GET /user email={} not found", email); - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + @GetMapping("/info") + public ResponseEntity getAuthUser( + @Parameter(description = "access token") + @RequestHeader("Authorization") String accessToken) { + return ResponseEntity.ok(userService.getMainInfoByAccessToken(accessToken)); } @Operation( @@ -72,7 +63,7 @@ public ResponseEntity getAuthUser() { description = "Позволяет удалить своего пользователя по токену", security = @SecurityRequirement(name = "accessTokenAuth") ) - @DeleteMapping("/user") + @DeleteMapping("") public Map deleteUser() { logger.atInfo().log("DELETE /user"); Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); @@ -101,4 +92,13 @@ public Map deleteUser() { logger.atError().log("email={} not found", email); return Map.of("error", "Пользователь не найден"); } + + /** + * Обработчик ошибки ненайденного пользователя или Jwt + * @param e исключение, содержащее текст ошибки + */ + @ExceptionHandler({UserNotFoundException.class, JwtException.class}) + private ResponseEntity handleJwtExceptionException(Exception e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorMessageResponse(e.getMessage())); + } } diff --git a/src/main/java/com/shulpov/spots_app/users/dto/MainUserInfoDto.java b/src/main/java/com/shulpov/spots_app/users/dto/MainUserInfoDto.java new file mode 100644 index 0000000..9598a34 --- /dev/null +++ b/src/main/java/com/shulpov/spots_app/users/dto/MainUserInfoDto.java @@ -0,0 +1,31 @@ +package com.shulpov.spots_app.users.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.shulpov.spots_app.image_infos.dto.ImageInfoDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.util.Date; +import java.util.List; + +@Setter +@Getter +public class MainUserInfoDto { + @Schema(description = "Имя пользователя", example = "Alex") + private String name; + + @Schema(description = "Почта пользователя", example = "alex_green@gmail.com") + private String email; + + @Schema(description = "Номер телефона пользователя", example = "89005553535") + private String phoneNumber; + + @Schema(description = "Дата рождения пользователя", example = "2000-07-15") + private Date birthday; + + @Schema(description = "Дата регистрации пользователя", example = "2022-07-15") + private Date regDate; + + @JsonProperty("imageInfoList") + private List imageInfoDtoList; +} diff --git a/src/main/java/com/shulpov/spots_app/users/dto/UserDto.java b/src/main/java/com/shulpov/spots_app/users/dto/UserDto.java deleted file mode 100644 index 1dd8ec1..0000000 --- a/src/main/java/com/shulpov/spots_app/users/dto/UserDto.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.shulpov.spots_app.users.dto; - -import com.shulpov.spots_app.image_infos.dto.ImageInfoDto; -import com.shulpov.spots_app.spots.dto.SpotDto; -import jakarta.validation.constraints.Email; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; - -import java.io.Serializable; -import java.util.Date; -import java.util.List; - -public class UserDto implements Serializable { - @NotEmpty(message = "Имя не должен быть пустым") - @Size(min = 2, max = 30, message = "Длина имени должна быть от 2 до 30 символов") - protected String name; - - @NotNull(message = "Email не должен быть пустой") - @Email(message = "Email должен быть валидным") - @Size(min = 5, max = 50, message = "Длина почты должна быть от 5 до 50 символов") - protected String email; - - @NotEmpty(message = "Номер не должен быть пустым") - protected String phoneNumber; - - @NotNull(message = "Дата дня рождения не должна быть пустой") - protected Date birthday; - - protected Date regDate; - - @NotNull(message = "Пароль не должен быть пустой") - @Size(min = 6, max = 50, message = "Длина пароля должна быть от 6 до 50 символов") - protected String password; - - protected List imageInfoDtoList; - - protected List createdSpots; - - protected List likedSpotIds; - - protected List favoriteSpotIds; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getPhoneNumber() { - return phoneNumber; - } - - public void setPhoneNumber(String phoneNumber) { - this.phoneNumber = phoneNumber; - } - - public Date getBirthday() { - return birthday; - } - - public void setBirthday(Date birthday) { - this.birthday = birthday; - } - - public Date getRegDate() { - return regDate; - } - - public void setRegDate(Date regDate) { - this.regDate = regDate; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public List getImageInfoDtoList() { - return imageInfoDtoList; - } - public void setImageInfoDtoList(List imageInfoDtoList) { - this.imageInfoDtoList = imageInfoDtoList; - } - - public List getCreatedSpots() { - return createdSpots; - } - - public void setCreatedSpots(List createdSpots) { - this.createdSpots = createdSpots; - } - - public List getLikedSpotIds() { - return likedSpotIds; - } - - public void setLikedSpotIds(List likedSpotIds) { - this.likedSpotIds = likedSpotIds; - } - - public List getFavoriteSpotIds() { - return favoriteSpotIds; - } - - public void setFavoriteSpotIds(List favoriteSpotIds) { - this.favoriteSpotIds = favoriteSpotIds; - } -} diff --git a/src/main/java/com/shulpov/spots_app/users/dto/UserFullInfoDto.java b/src/main/java/com/shulpov/spots_app/users/dto/UserFullInfoDto.java new file mode 100644 index 0000000..d03c74e --- /dev/null +++ b/src/main/java/com/shulpov/spots_app/users/dto/UserFullInfoDto.java @@ -0,0 +1,48 @@ +package com.shulpov.spots_app.users.dto; + +import com.shulpov.spots_app.image_infos.dto.ImageInfoDto; +import com.shulpov.spots_app.spots.dto.SpotDto; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +@Getter +@Setter +public class UserFullInfoDto implements Serializable { + @NotEmpty(message = "Имя не должен быть пустым") + @Size(min = 2, max = 30, message = "Длина имени должна быть от 2 до 30 символов") + private String name; + + @NotNull(message = "Email не должен быть пустой") + @Email(message = "Email должен быть валидным") + @Size(min = 5, max = 50, message = "Длина почты должна быть от 5 до 50 символов") + private String email; + + @NotEmpty(message = "Номер не должен быть пустым") + private String phoneNumber; + + @NotNull(message = "Дата дня рождения не должна быть пустой") + private Date birthday; + + private Date regDate; + + @NotNull(message = "Пароль не должен быть пустой") + @Size(min = 6, max = 50, message = "Длина пароля должна быть от 6 до 50 символов") + private String password; + + private List imageInfoDtoList; + + private List createdSpots; + + private List likedSpotIds; + + private List favoriteSpotIds; + +} diff --git a/src/main/java/com/shulpov/spots_app/users/dto/UserWithoutSpotsDto.java b/src/main/java/com/shulpov/spots_app/users/dto/UserWithoutSpotsDto.java deleted file mode 100644 index d614824..0000000 --- a/src/main/java/com/shulpov/spots_app/users/dto/UserWithoutSpotsDto.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.shulpov.spots_app.users.dto; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.shulpov.spots_app.spots.dto.SpotDto; - -import java.util.List; - - -//TODO переделать наследование, чтобы у наследника не урезался функционал, а добавлялся -public class UserWithoutSpotsDto extends UserDto{ - public UserWithoutSpotsDto(UserDto userDto) { - this.name = userDto.getName(); - this.birthday = userDto.getBirthday(); - this.email = userDto.getEmail(); - this.phoneNumber = userDto.getPhoneNumber(); - this.regDate = userDto.getRegDate(); - this.password = userDto.getPassword(); - this.imageInfoDtoList = userDto.getImageInfoDtoList(); - this.likedSpotIds = userDto.getLikedSpotIds(); - this.favoriteSpotIds = userDto.getFavoriteSpotIds(); - } - - @JsonIgnore - private List createdSpots; -} diff --git a/src/main/java/com/shulpov/spots_app/users/exception/UserNotFoundException.java b/src/main/java/com/shulpov/spots_app/users/exception/UserNotFoundException.java new file mode 100644 index 0000000..f70a88f --- /dev/null +++ b/src/main/java/com/shulpov/spots_app/users/exception/UserNotFoundException.java @@ -0,0 +1,10 @@ +package com.shulpov.spots_app.users.exception; + +/** + * Исключение того, что пользователь не найден + */ +public class UserNotFoundException extends RuntimeException { + public UserNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/com/shulpov/spots_app/users/UserService.java b/src/main/java/com/shulpov/spots_app/users/services/UserService.java similarity index 64% rename from src/main/java/com/shulpov/spots_app/users/UserService.java rename to src/main/java/com/shulpov/spots_app/users/services/UserService.java index cbd1926..2f6d2d9 100644 --- a/src/main/java/com/shulpov/spots_app/users/UserService.java +++ b/src/main/java/com/shulpov/spots_app/users/services/UserService.java @@ -1,7 +1,13 @@ -package com.shulpov.spots_app.users; +package com.shulpov.spots_app.users.services; +import com.shulpov.spots_app.authentication_management.services.JwtService; import com.shulpov.spots_app.image_infos.ImageInfoService; +import com.shulpov.spots_app.users.UserRepository; +import com.shulpov.spots_app.users.dto.MainUserInfoDto; +import com.shulpov.spots_app.users.exception.UserNotFoundException; import com.shulpov.spots_app.users.models.User; +import com.shulpov.spots_app.users.utils.UserDtoConverter; +import io.jsonwebtoken.JwtException; import org.hibernate.Hibernate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,33 +26,34 @@ public class UserService { private final Logger logger = LoggerFactory.getLogger(UserService.class); private final ImageInfoService imageInfoService; + private final JwtService jwtService; private final UserRepository userRepository; + private final UserDtoConverter userDtoConverter; + @Autowired - public UserService(ImageInfoService imageInfoService, UserRepository userRepository) { + public UserService(ImageInfoService imageInfoService, JwtService jwtService, UserRepository userRepository, UserDtoConverter userDtoConverter) { this.imageInfoService = imageInfoService; + this.jwtService = jwtService; this.userRepository = userRepository; + this.userDtoConverter = userDtoConverter; } - //Найти пользователя по id public Optional findById(Long id) { logger.atInfo().log("findById id={}", id); return userRepository.findById(id); } - //Найти пользователя по email public Optional findByEmail(String email) { logger.atInfo().log("findByEmail email={}", email); return userRepository.findByEmail(email); } - //Найти пользователя по имени public Optional findByName(String name) { logger.atInfo().log("findByName name={}", name); return userRepository.findByName(name); } - //Удалить пользователя по id @Transactional(rollbackFor = IOException.class) public Boolean deleteById(Long id) { logger.atInfo().log("deleteById id={}", id); @@ -71,10 +78,24 @@ public Boolean deleteById(Long id) { return false; } - //Найти пользователя по номеру телефона public Optional findByPhoneNumber(String phoneNumber) { logger.atInfo().log("findByPhoneNumber phoneNumber={}", phoneNumber); return userRepository.findByPhoneNumber(phoneNumber); } + public MainUserInfoDto getMainInfoByAccessToken(String accessToken) throws UserNotFoundException, JwtException { + Optional userOpt = getByAccessToken(accessToken); + if (userOpt.isEmpty()) { + throw new UserNotFoundException("User not found"); + } + return userDtoConverter.userToUserMainInfoDto(userOpt.get()); + } + + /** + * Получить пользователя по его access токену + */ + private Optional getByAccessToken(String accessToken) throws JwtException { + String email = jwtService.extractEmail(accessToken); + return userRepository.findByEmail(email); + } } diff --git a/src/main/java/com/shulpov/spots_app/users/utils/UserDtoConverter.java b/src/main/java/com/shulpov/spots_app/users/utils/UserDtoConverter.java new file mode 100644 index 0000000..5d2f165 --- /dev/null +++ b/src/main/java/com/shulpov/spots_app/users/utils/UserDtoConverter.java @@ -0,0 +1,34 @@ +package com.shulpov.spots_app.users.utils; + +import com.shulpov.spots_app.image_infos.utils.ImageInfoDtoConverter; +import com.shulpov.spots_app.users.dto.MainUserInfoDto; +import com.shulpov.spots_app.users.models.User; +import org.modelmapper.ModelMapper; +import org.springframework.stereotype.Component; + + +/** + * Компонент, помогающий конвертировать модели класса User в DTO и обратно. + * @author Victor Shulpov "vshulpov@gmail.com" + */ +@Component +public class UserDtoConverter { + private final ModelMapper modelMapper; + private final ImageInfoDtoConverter imageInfoDtoConverter; + + public UserDtoConverter(ModelMapper modelMapper, ImageInfoDtoConverter imageInfoDtoConverter) { + this.modelMapper = modelMapper; + this.imageInfoDtoConverter = imageInfoDtoConverter; + } + + /** + * Конвертор класса User в класс MainUserInfoDto + * @param user класс пользователя + * @return класс DTO пользователя с основными свойствами пользователя + */ + public MainUserInfoDto userToUserMainInfoDto(User user) { + MainUserInfoDto dto = modelMapper.map(user, MainUserInfoDto.class); + dto.setImageInfoDtoList(user.getImageInfos().stream().map(imageInfoDtoConverter::imageInfoToDto).toList()); + return dto; + } +} diff --git a/src/main/java/com/shulpov/spots_app/utils/DtoConverter.java b/src/main/java/com/shulpov/spots_app/utils/DtoConverter.java index d00b3b9..c4d9b46 100644 --- a/src/main/java/com/shulpov/spots_app/utils/DtoConverter.java +++ b/src/main/java/com/shulpov/spots_app/utils/DtoConverter.java @@ -1,10 +1,8 @@ package com.shulpov.spots_app.utils; -import com.shulpov.spots_app.comments.Comment; -import com.shulpov.spots_app.comments.CommentDto; import com.shulpov.spots_app.dto.*; -import com.shulpov.spots_app.image_infos.models.ImageInfo; import com.shulpov.spots_app.image_infos.dto.ImageInfoDto; +import com.shulpov.spots_app.image_infos.utils.ImageInfoDtoConverter; import com.shulpov.spots_app.locations.dto.CityDto; import com.shulpov.spots_app.locations.dto.CountryDto; import com.shulpov.spots_app.locations.dto.RegionDto; @@ -25,10 +23,6 @@ import com.shulpov.spots_app.spot_user_infos.SpotUserService; import com.shulpov.spots_app.spots.models.Spot; import com.shulpov.spots_app.spots.dto.SpotDto; -import com.shulpov.spots_app.users.authorization.Role; -import com.shulpov.spots_app.users.models.User; -import com.shulpov.spots_app.users.dto.UserDto; -import com.shulpov.spots_app.users.dto.UserWithoutSpotsDto; import org.modelmapper.ModelMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,75 +39,30 @@ /** * Класс, помогающий конвертировать модели в их DTO и обратно. Класс-@Component. * @author Victor Shulpov "vshulpov@gmail.com" - * @version 1.0 - * @since 1.0 */ @Component public class DtoConverter { - private final Logger logger = LoggerFactory.getLogger(DtoConverter.class); - /** Компонент маппинга классов */ private final ModelMapper modelMapper; - /** Сервис типов помещений */ + private final ImageInfoDtoConverter imageInfoDtoConverter; private final SpaceTypeService spaceTypeService; - /** Сервис типов спотов */ private final SpotTypeService spotTypeService; - /** Сервис типов спорта */ private final SportTypeService sportTypeService; - /** Сервис управления данными между пользователями и спотами */ private final SpotUserService spotUserService; - /** - * Конструктор компонента - * @param modelMapper компонент маппинга классов - * @param spaceTypeService сервис типов помещений - * @param spotTypeService сервис типов спотов - * @param sportTypeService сервис типов спорта - * @param spotUserService сервис управления данными между пользователями и спотами - */ - @Autowired - public DtoConverter(@Lazy ModelMapper modelMapper, @Lazy SpaceTypeService spaceTypeService, + public DtoConverter(@Lazy ModelMapper modelMapper, ImageInfoDtoConverter imageInfoDtoConverter, @Lazy SpaceTypeService spaceTypeService, @Lazy SpotTypeService spotTypeService, @Lazy SportTypeService sportTypeService, SpotUserService spotUserService) { this.modelMapper = modelMapper; + this.imageInfoDtoConverter = imageInfoDtoConverter; this.spaceTypeService = spaceTypeService; this.spotTypeService = spotTypeService; this.sportTypeService = sportTypeService; this.spotUserService = spotUserService; } - /** - * Конвертор класса User в класс UserDto - * @param user класс пользователя - * @return класс DTO пользователя - */ - public UserDto userToDto(User user) { - logger.atInfo().log("userToDto id: {}, name: {}", user.getId(), user.getName()); - UserDto dto = modelMapper.map(user, UserDto.class); - dto.setImageInfoDtoList(user.getImageInfos().stream().map(this::imageInfoToDto).toList()); - dto.setCreatedSpots(user.getCreatedSpots().stream().map(this::spotToDto).toList()); - dto.setLikedSpotIds(spotUserService.getLikedSpotUsers(user).stream() - .map(ss -> ss.getPostedSpot().getId()).toList()); - dto.setFavoriteSpotIds(spotUserService.getFavoriteSpotUsers(user).stream() - .map(ss -> ss.getPostedSpot().getId()).toList()); - return dto; - } - - /** - * Конвертор класса UserDto в класс User - * @param dto класс DTO пользователя - * @return класс пользователя - */ - public User dtoToNewUser(UserDto dto) { - logger.atInfo().log("dtoToNewUser name: {}", dto.getName()); - User user = modelMapper.map(dto, User.class); - user.setRegDate(new Date(System.currentTimeMillis())); - user.setRole(Role.USER); - return user; - } - /** * Конвертор класса SpotDto в класс Spot * @param dto класс DTO создаваемого спота @@ -166,7 +115,7 @@ public SpotDto spotToDto(Spot spot) { dto.setSpaceTypeId(spot.getSpaceType().getId()); //инф о картинках List imageInfoDtoList = spot.getImageInfos().stream() - .map(this::imageInfoToDto).toList(); + .map(imageInfoDtoConverter::imageInfoToDto).toList(); dto.setImageInfoDtoList(imageInfoDtoList); //кол-во избранных Integer favoriteNum = spotUserService.getFavoriteNumber(spot); @@ -178,30 +127,6 @@ public SpotDto spotToDto(Spot spot) { return dto; } - /** - * Конвертор класса ImageInfo в класс ImageInfoDto - * @param imageInfo класс информации об изображении - * @return класс DTO информации об изображении - */ - public ImageInfoDto imageInfoToDto(ImageInfo imageInfo) throws NullPointerException { - logger.atInfo().log("imageInfoToDto id: {}, genName: {}", imageInfo.getId(), imageInfo.getGenName()); - ImageInfoDto dto = modelMapper.map(imageInfo, ImageInfoDto.class); - - if(imageInfo.getPhotographedUser() != null) { - String url = ImageUtil.getUserImageDownloadUrl(imageInfo.getId()); - dto.setUrl(url); - logger.atInfo().log("imageInfoToDto image for user, user_id={}", imageInfo.getPhotographedUser().getId()); - } else if(imageInfo.getPhotographedSpot() != null) { - String url = ImageUtil.getSpotImageDownloadUrl(imageInfo.getId()); - dto.setUrl(url); - logger.atInfo().log("imageInfoToDto image for spot, spot_id={}", imageInfo.getPhotographedSpot().getId()); - } else { - logger.atInfo().log("Invalid image info object (user and spot are null)"); - throw new NullPointerException("Invalid image info object (user and spot are null)"); - } - return dto; - } - /** * Конвертор класса SportType в класс SportTypeDto * @param sportType класс типа спорта @@ -232,19 +157,6 @@ public SpaceTypeDto spaceTypeToDto(SpaceType spaceType) { return modelMapper.map(spaceType, SpaceTypeDto.class); } - /** - * Конвертор класса Comment в класс CommentDto - * @param comment класс комментария - * @return класс DTO комментария - */ - public CommentDto commentToDto(Comment comment) { - logger.atInfo().log("commentToDto id={}", comment.getId()); - CommentDto dto = modelMapper.map(comment, CommentDto.class); - UserDto userDto = userToDto(comment.getCommentator()); - dto.setCommentatorDto(new UserWithoutSpotsDto(userDto)); - return dto; - } - /** * Конвертор класса SpotUser в класс SpotUserDto * @param spotUser класс данных между спотами и пользователями @@ -282,7 +194,6 @@ public FieldErrorDto fieldErrorToDto(FieldError fieldError) { * @return класс DTO класса страны */ public CountryDto countryToDto(Country country) { - // TODO дописать логгер return modelMapper.map(country, CountryDto.class); } @@ -292,7 +203,6 @@ public CountryDto countryToDto(Country country) { * @return класс DTO класса региона */ public RegionDto regionToDto(Region region) { - // TODO дописать логгер return modelMapper.map(region, RegionDto.class); } @@ -302,7 +212,6 @@ public RegionDto regionToDto(Region region) { * @return класс DTO класса города */ public CityDto cityToDto(City city) { - // TODO дописать логгер return modelMapper.map(city, CityDto.class); } } diff --git a/src/test/java/com/shulpov/spots_app/AuthTests.java b/src/test/java/com/shulpov/spots_app/AuthTests.java index 7af5c31..4ec826d 100644 --- a/src/test/java/com/shulpov/spots_app/AuthTests.java +++ b/src/test/java/com/shulpov/spots_app/AuthTests.java @@ -7,7 +7,7 @@ import com.shulpov.spots_app.authentication_management.tokens.TokenService; import com.shulpov.spots_app.db_cleaner.DBCleaner; import com.shulpov.spots_app.responses.ErrorMessageResponse; -import com.shulpov.spots_app.users.UserService; +import com.shulpov.spots_app.users.services.UserService; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll;