From 3947d0edb70fc45b63651b9efd541f10fe925afd Mon Sep 17 00:00:00 2001 From: ArtemPoliakov Date: Thu, 18 Apr 2024 11:08:00 +0300 Subject: [PATCH] Updated link repository and service, controller, added javadoc --- .../urlshortener/link/Link.java | 3 +- .../urlshortener/link/LinkController.java | 65 ++++++++++--------- .../urlshortener/link/LinkInfoResponse.java | 9 ++- .../urlshortener/link/LinkRepository.java | 9 +-- .../urlshortener/link/LinkService.java | 6 +- .../urlshortener/link/LinkStatisticsDto.java | 8 ++- .../link/LinkStatisticsResponse.java | 9 ++- .../urlshortener/user/User.java | 3 +- .../urlshortener/link/LinkServiceTest.java | 28 ++++---- 9 files changed, 81 insertions(+), 59 deletions(-) diff --git a/src/main/java/com/linkurlshorter/urlshortener/link/Link.java b/src/main/java/com/linkurlshorter/urlshortener/link/Link.java index 68226ac..c7aaad6 100644 --- a/src/main/java/com/linkurlshorter/urlshortener/link/Link.java +++ b/src/main/java/com/linkurlshorter/urlshortener/link/Link.java @@ -50,6 +50,7 @@ public class Link { @Column(name = "statistics") private int statistics; @Column(name = "status") + @Builder.Default @Enumerated(EnumType.STRING) - private LinkStatus status; + private LinkStatus status = LinkStatus.ACTIVE; } diff --git a/src/main/java/com/linkurlshorter/urlshortener/link/LinkController.java b/src/main/java/com/linkurlshorter/urlshortener/link/LinkController.java index aecbf2e..51f0acc 100644 --- a/src/main/java/com/linkurlshorter/urlshortener/link/LinkController.java +++ b/src/main/java/com/linkurlshorter/urlshortener/link/LinkController.java @@ -16,7 +16,6 @@ import java.util.Comparator; import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; /** * Controller for Link-related operations such as create, delete, update and get info + statistics @@ -33,7 +32,6 @@ public class LinkController { private final LinkService linkService; private final UserService userService; - private final EntityManager entityManager; private final LinkInfoDtoMapper linkDtoMapper; /** @@ -57,7 +55,7 @@ public class LinkController { @PostMapping("/create") public ResponseEntity createLink(@RequestBody @Valid CreateLinkRequest createRequest) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - UUID userId = userService.findByEmail(authentication.getName()).getId(); + User user = userService.findByEmail(authentication.getName()); String newShortUrl = generateShortLink(); try { linkService.save( @@ -65,7 +63,7 @@ public ResponseEntity createLink(@RequestBody @Valid CreateL .longLink(createRequest.getLongLink()) .shortLink(newShortUrl) .expirationTime(LocalDateTime.now().plusDays(SHORT_LINK_LIFETIME_IN_DAYS)) - .user(entityManager.getReference(User.class, userId)) + .user(user) .build() //TODO: add validations (short link being unique etc) ); } catch (Exception e) { @@ -137,7 +135,13 @@ public ResponseEntity refreshLink(@RequestParam UUID id) throw new ForbiddenException(OPERATION_FORBIDDEN_MSG); } } - //TODO: for info and all-links-info exclude all results of status DELETED! + /** + * Retrieves information about a link using its short link. + * + * @param shortLink the short link of the link to retrieve information for + * @return a ResponseEntity containing the response object with information about the link + * @throws ForbiddenException if the authenticated user does not have rights to access the link + */ @GetMapping("/info") public ResponseEntity getInfoByShortLink(@RequestParam String shortLink) { Link link = linkService.findByShortLink(shortLink); @@ -149,37 +153,36 @@ public ResponseEntity getInfoByShortLink(@RequestParam String throw new ForbiddenException(OPERATION_FORBIDDEN_MSG); } } - + /** + * Retrieves information about all links associated with the authenticated user. + * + * @return a ResponseEntity containing the response object with information about all links for the user + */ @GetMapping("/all-links-info") public ResponseEntity getAllLinksForUser() { - try { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - User requesterUser = userService.findByEmail(authentication.getName()); - List linksDto = linkService - .findAllByUser(requesterUser) - .stream() - .map(linkDtoMapper::mapLinkToDto) - .sorted(Comparator.comparing(LinkInfoDto::getUsageStatistics).reversed()) - .collect(Collectors.toList()); - return ResponseEntity.ok(new LinkInfoResponse(linksDto, "ok")); - } catch (Exception e) { - throw new InternalServerLinkException(); - } - + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + UUID requesterUserId = userService.findByEmail(authentication.getName()).getId(); + List linksDto = linkService + .findAllByUserId(requesterUserId) + .stream() + .map(linkDtoMapper::mapLinkToDto) + .sorted(Comparator.comparing(LinkInfoDto::getUsageStatistics).reversed()) + .toList(); + return ResponseEntity.ok(new LinkInfoResponse(linksDto, "ok")); } - - //TODO: exclude all results of non-Active (or only of DELETED?) + /** + * Retrieves usage statistics for all links associated with the authenticated user. + * + * @return a ResponseEntity containing the response object with usage statistics for all links for the user, + * links are sorted in descending order + */ @GetMapping("/url-usage-top-for-user") public ResponseEntity getLinksStatsForUser() { - try { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - User requesterUser = userService.findByEmail(authentication.getName()); - List stats = linkService.getLinkUsageStatsByUserId(requesterUser.getId()); - stats.sort(Comparator.comparing(LinkStatisticsDto::getUsageStatistics).reversed()); - return ResponseEntity.ok(new LinkStatisticsResponse(stats, "ok")); - } catch (Exception e) { - throw new InternalServerLinkException(); - } + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + User requesterUser = userService.findByEmail(authentication.getName()); + List stats = linkService.getLinkUsageStatsByUserId(requesterUser.getId()); + stats.sort(Comparator.comparing(LinkStatisticsDto::getUsageStatistics).reversed()); + return ResponseEntity.ok(new LinkStatisticsResponse(stats, "ok")); } /** diff --git a/src/main/java/com/linkurlshorter/urlshortener/link/LinkInfoResponse.java b/src/main/java/com/linkurlshorter/urlshortener/link/LinkInfoResponse.java index 170c52a..933a926 100644 --- a/src/main/java/com/linkurlshorter/urlshortener/link/LinkInfoResponse.java +++ b/src/main/java/com/linkurlshorter/urlshortener/link/LinkInfoResponse.java @@ -6,7 +6,14 @@ import lombok.NoArgsConstructor; import java.util.List; - +/** + * Data transfer object (DTO) for representing a response containing link information. + * This class encapsulates a list of {@link LinkInfoDto} objects representing link information, + * along with an optional error message. + * + * @author Artem Poliakov + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor diff --git a/src/main/java/com/linkurlshorter/urlshortener/link/LinkRepository.java b/src/main/java/com/linkurlshorter/urlshortener/link/LinkRepository.java index 7ac2e54..aeeac7c 100644 --- a/src/main/java/com/linkurlshorter/urlshortener/link/LinkRepository.java +++ b/src/main/java/com/linkurlshorter/urlshortener/link/LinkRepository.java @@ -3,13 +3,9 @@ import com.linkurlshorter.urlshortener.user.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import org.springframework.transaction.annotation.Transactional; -import java.sql.Timestamp; -import java.time.LocalDateTime; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -34,9 +30,10 @@ public interface LinkRepository extends JpaRepository { */ Optional findByShortLink(String shortLink); - List findAllByUser(User user); + @Query("SELECT l from Link l WHERE l.user.id = :userId AND l.status <> 'DELETED'") + List findAllByUserId(@Param(value = "userId") UUID userId); @Query("SELECT new com.linkurlshorter.urlshortener.link.LinkStatisticsDto(l.id, l.shortLink, l.statistics)" + - " FROM Link l WHERE l.user.id = :userId") + " FROM Link l WHERE l.user.id = :userId AND l.status <> 'DELETED'") List getLinkUsageStatsForUser(@Param(value = "userId") UUID userId); } diff --git a/src/main/java/com/linkurlshorter/urlshortener/link/LinkService.java b/src/main/java/com/linkurlshorter/urlshortener/link/LinkService.java index 2e45d91..44be52c 100644 --- a/src/main/java/com/linkurlshorter/urlshortener/link/LinkService.java +++ b/src/main/java/com/linkurlshorter/urlshortener/link/LinkService.java @@ -88,11 +88,11 @@ public Link findByShortLink(String shortLink) { return link; } - public List findAllByUser(User user){ - if(Objects.isNull(user)){ + public List findAllByUserId(UUID userId){ + if(Objects.isNull(userId)){ throw new NullLinkPropertyException(); } - return linkRepository.findAllByUser(user); + return linkRepository.findAllByUserId(userId); } public List getLinkUsageStatsByUserId(UUID userId){ diff --git a/src/main/java/com/linkurlshorter/urlshortener/link/LinkStatisticsDto.java b/src/main/java/com/linkurlshorter/urlshortener/link/LinkStatisticsDto.java index 6d9fbc8..bd0c914 100644 --- a/src/main/java/com/linkurlshorter/urlshortener/link/LinkStatisticsDto.java +++ b/src/main/java/com/linkurlshorter/urlshortener/link/LinkStatisticsDto.java @@ -6,7 +6,13 @@ import lombok.NoArgsConstructor; import java.util.UUID; - +/** + * Data transfer object (DTO) for representing link statistics. + * This class encapsulates information about a link's ID, short link, and usage statistics. + * + * @author Artem Poliakov + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor diff --git a/src/main/java/com/linkurlshorter/urlshortener/link/LinkStatisticsResponse.java b/src/main/java/com/linkurlshorter/urlshortener/link/LinkStatisticsResponse.java index a96dd69..5afe0a1 100644 --- a/src/main/java/com/linkurlshorter/urlshortener/link/LinkStatisticsResponse.java +++ b/src/main/java/com/linkurlshorter/urlshortener/link/LinkStatisticsResponse.java @@ -6,7 +6,14 @@ import lombok.NoArgsConstructor; import java.util.List; - +/** + * Data transfer object (DTO) for representing a response containing statistics of links. + * This class encapsulates a list of {@link LinkStatisticsDto} objects representing link statistics, + * along with an optional error message. + * + * @author Artem Poliakov + * @version 1.0 + */ @Data @AllArgsConstructor @NoArgsConstructor diff --git a/src/main/java/com/linkurlshorter/urlshortener/user/User.java b/src/main/java/com/linkurlshorter/urlshortener/user/User.java index 4d8faa8..a4e20af 100644 --- a/src/main/java/com/linkurlshorter/urlshortener/user/User.java +++ b/src/main/java/com/linkurlshorter/urlshortener/user/User.java @@ -37,7 +37,8 @@ public class User { private String password; @Column(name = "role") @Enumerated(EnumType.STRING) - private UserRole role; + @Builder.Default + private UserRole role = UserRole.USER; @EqualsAndHashCode.Exclude @OneToMany(mappedBy = "user", cascade = {CascadeType.MERGE, CascadeType.PERSIST}) private List links; diff --git a/src/test/java/com/linkurlshorter/urlshortener/link/LinkServiceTest.java b/src/test/java/com/linkurlshorter/urlshortener/link/LinkServiceTest.java index 1130c37..5fe16ea 100644 --- a/src/test/java/com/linkurlshorter/urlshortener/link/LinkServiceTest.java +++ b/src/test/java/com/linkurlshorter/urlshortener/link/LinkServiceTest.java @@ -2,12 +2,17 @@ import com.linkurlshorter.urlshortener.user.User; import com.linkurlshorter.urlshortener.user.UserRole; +import jakarta.persistence.EntityManager; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.context.SpringBootTest; import java.time.LocalDateTime; import java.util.*; @@ -189,36 +194,31 @@ void findByShortLinkNotFoundTest() { } /** - * Test case for the {@link LinkService#findAllByUser(User)} method. + * Test case for the {@link LinkService#findAllByUserId(UUID)} method. */ @Test - void findByAllByUserTest() { - User user = User.builder() - .id(UUID.fromString("84991c79-f6a9-4b7b-b1b4-0d66c0b92c81")) - .email("test1@gmail.com") - .password("password1") - .role(UserRole.USER) - .build(); - + void findByAllByUserIdTest() { + UUID userId = UUID.fromString("84991c79-f6a9-4b7b-b1b4-0d66c0b92c81"); + User user = User.builder().id(userId).build(); List userLinks = Arrays.asList( Link.builder().id(UUID.randomUUID()).user(user).build(), Link.builder().id(UUID.randomUUID()).user(user).build(), Link.builder().id(UUID.randomUUID()).user(user).build() ); - when(linkRepository.findAllByUser(user)).thenReturn(userLinks); - List foundLinks = linkService.findAllByUser(user); + when(linkRepository.findAllByUserId(userId)).thenReturn(userLinks); + List foundLinks = linkService.findAllByUserId(userId); assertThat(foundLinks).isNotNull().isEqualTo(userLinks); - verify(linkRepository, times(1)).findAllByUser(user); + verify(linkRepository, times(1)).findAllByUserId(userId); } /** - * Test case for the {@link LinkService#findAllByUser(User)} method when the provided user is null. + * Test case for the {@link LinkService#findAllByUserId(UUID)} method when the provided user is null. */ @Test void findAllByNullUserTest() { - assertThatThrownBy(() -> linkService.findAllByUser(null)) + assertThatThrownBy(() -> linkService.findAllByUserId(null)) .isInstanceOf(NullLinkPropertyException.class); }