diff --git a/src/main/java/gaji/service/config/SecurityConfig.java b/src/main/java/gaji/service/config/SecurityConfig.java index 8c42003b..1bdc3bed 100644 --- a/src/main/java/gaji/service/config/SecurityConfig.java +++ b/src/main/java/gaji/service/config/SecurityConfig.java @@ -32,7 +32,8 @@ public class SecurityConfig { private final RefreshRepository refreshRepository; private static final String[] AUTH_WHITELIST = { "/oauth2/**", "/swagger-ui/**", "/api-docs", "/swagger-ui-custom.html", - "/v3/api-docs/**", "/api-docs/**", "/swagger-ui.html", "/reissue", "/", "/my" + "/v3/api-docs/**", "/api-docs/**", "/swagger-ui.html", "/reissue", "/", "/my", + "/api/**" }; @Bean diff --git a/src/main/java/gaji/service/domain/post/repository/PostQueryDslRepository.java b/src/main/java/gaji/service/domain/post/repository/PostQueryDslRepository.java index 904cb31c..dc2ebda5 100644 --- a/src/main/java/gaji/service/domain/post/repository/PostQueryDslRepository.java +++ b/src/main/java/gaji/service/domain/post/repository/PostQueryDslRepository.java @@ -1,12 +1,15 @@ package gaji.service.domain.post.repository; +import com.querydsl.core.Tuple; import gaji.service.domain.enums.SortType; import gaji.service.domain.enums.PostStatusEnum; import gaji.service.domain.enums.PostTypeEnum; import gaji.service.domain.post.entity.Post; +import gaji.service.domain.user.entity.User; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; +import java.time.LocalDateTime; public interface PostQueryDslRepository { @@ -21,5 +24,6 @@ Slice findAllFetchJoinWithUser(Integer lastPopularityScore, Pageable pageable); Post findByIdFetchJoinWithUser(Long postId); + Slice findAllPostsByUser(User user, LocalDateTime CursorDateTime, Pageable pageable, PostTypeEnum type); } diff --git a/src/main/java/gaji/service/domain/post/repository/PostQueryDslRepositoryImpl.java b/src/main/java/gaji/service/domain/post/repository/PostQueryDslRepositoryImpl.java index af44de4a..3e833679 100644 --- a/src/main/java/gaji/service/domain/post/repository/PostQueryDslRepositoryImpl.java +++ b/src/main/java/gaji/service/domain/post/repository/PostQueryDslRepositoryImpl.java @@ -1,5 +1,6 @@ package gaji.service.domain.post.repository; +import com.querydsl.core.Tuple; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -9,12 +10,14 @@ import gaji.service.domain.enums.PostStatusEnum; import gaji.service.domain.enums.PostTypeEnum; import gaji.service.domain.post.entity.Post; +import gaji.service.domain.user.entity.User; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.domain.SliceImpl; import org.springframework.stereotype.Repository; +import java.time.LocalDateTime; import java.util.List; import static gaji.service.domain.post.entity.QPost.post; @@ -72,6 +75,20 @@ public Post findByIdFetchJoinWithUser(Long postId) { .fetchOne(); } + @Override + public Slice findAllPostsByUser(User user, LocalDateTime cursorDateTime, Pageable pageable, PostTypeEnum type) { + List userPosts = jpaQueryFactory.select(post.id, post.user, post.title, post.body, post.type, post.status, post.hit, post.likeCnt, post.createdAt) + .from(post) + .where(post.user.eq(user), (postTypeEq(type)) + ,(post.createdAt.before(cursorDateTime)) + ) + .orderBy(post.createdAt.desc()) + .limit(pageable.getPageSize() + 1) + .fetch(); + + return checkLastPage(pageable, userPosts); + } + private BooleanExpression postIdEq(Long postId) { return post.id.eq(postId); } @@ -108,7 +125,7 @@ private BooleanExpression ltHit(Integer lastHit) { return (lastHit != null) ? post.hit.lt(lastHit) : null; } - private Slice checkLastPage(Pageable pageable, List postList) { + private Slice checkLastPage(Pageable pageable, List postList) { boolean hasNext = false; // (조회한 결과 개수 > 요청한 페이지 사이즈) 이면 뒤에 데이터가 더 존재함 diff --git a/src/main/java/gaji/service/domain/user/converter/UserConverter.java b/src/main/java/gaji/service/domain/user/converter/UserConverter.java index 54b8936e..c081972c 100644 --- a/src/main/java/gaji/service/domain/user/converter/UserConverter.java +++ b/src/main/java/gaji/service/domain/user/converter/UserConverter.java @@ -1,9 +1,12 @@ package gaji.service.domain.user.converter; import com.querydsl.core.Tuple; +import gaji.service.domain.enums.PostTypeEnum; +import gaji.service.domain.post.entity.QPost; import gaji.service.domain.room.entity.QRoom; import gaji.service.domain.user.entity.User; import gaji.service.domain.user.web.dto.UserResponseDTO; +import gaji.service.global.converter.DateConverter; import org.springframework.data.domain.Slice; import java.util.List; @@ -44,4 +47,39 @@ public static UserResponseDTO.GetRoomListDTO toGetRoomListDTO(Slice roomL .hasNext(roomList.hasNext()) .build(); } + + public static UserResponseDTO.GetPostDTO toGetPostDTO(Tuple tuple) { + return UserResponseDTO.GetPostDTO.builder() + .postId(tuple.get(QPost.post.id)) + .title(tuple.get(QPost.post.title)) + .body(tuple.get(QPost.post.body)) + .type(tuple.get(QPost.post.type)) + .status(tuple.get(QPost.post.status)) + .userId(tuple.get(QPost.post.user.id)) + .nickname(tuple.get(QPost.post.user.nickname)) + .profileImagePth(tuple.get(QPost.post.user.profileImagePth)) + .createdAt(DateConverter.convertToRelativeTimeFormat(tuple.get(QPost.post.createdAt))) + .viewCnt(tuple.get(QPost.post.hit)) + .likeCnt(tuple.get(QPost.post.likeCnt)) + .build(); + } + + public static UserResponseDTO.GetPostListDTO toGetPostListDTO(Slice postList, PostTypeEnum type) { + List getPostDTOList = postList.stream() + .map(UserConverter::toGetPostDTO) + .collect(Collectors.toList()); + + return UserResponseDTO.GetPostListDTO.builder() + .postList(getPostDTOList) + .hasNext(postList.hasNext()) + .build(); + } + + public static UserResponseDTO.GetUserDetailDTO toGetUserDetailDTO(User user) { + return UserResponseDTO.GetUserDetailDTO.builder() + .userId(user.getId()) + .nickname(user.getNickname()) + .profileImagePth(user.getProfileImagePth()) + .build(); + } } diff --git a/src/main/java/gaji/service/domain/user/service/UserQueryService.java b/src/main/java/gaji/service/domain/user/service/UserQueryService.java index 14dea5eb..be2d2a88 100644 --- a/src/main/java/gaji/service/domain/user/service/UserQueryService.java +++ b/src/main/java/gaji/service/domain/user/service/UserQueryService.java @@ -2,16 +2,19 @@ import com.querydsl.core.Tuple; +import gaji.service.domain.enums.PostTypeEnum; import gaji.service.domain.enums.RoomTypeEnum; import gaji.service.domain.user.entity.User; import org.springframework.data.domain.Slice; import java.time.LocalDate; +import java.time.LocalDateTime; public interface UserQueryService { boolean existUserById(Long userId); User findUserById(Long userId); Slice getUserRoomList(Long userId, LocalDate cursorDate, Long cursorId, RoomTypeEnum type, int size); - + User getUserDetail(Long userId); + Slice getUserPostList(Long userId, LocalDateTime cursorDateTime, PostTypeEnum type, int size); } diff --git a/src/main/java/gaji/service/domain/user/service/UserQueryServiceImpl.java b/src/main/java/gaji/service/domain/user/service/UserQueryServiceImpl.java index 5dabc569..76e27377 100644 --- a/src/main/java/gaji/service/domain/user/service/UserQueryServiceImpl.java +++ b/src/main/java/gaji/service/domain/user/service/UserQueryServiceImpl.java @@ -1,7 +1,9 @@ package gaji.service.domain.user.service; import com.querydsl.core.Tuple; +import gaji.service.domain.enums.PostTypeEnum; import gaji.service.domain.enums.RoomTypeEnum; +import gaji.service.domain.post.repository.PostJpaRepository; import gaji.service.domain.room.repository.RoomCustomRepository; import gaji.service.domain.user.code.UserErrorStatus; import gaji.service.domain.user.entity.User; @@ -14,6 +16,7 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; +import java.time.LocalDateTime; @Service @RequiredArgsConstructor @@ -22,6 +25,7 @@ public class UserQueryServiceImpl implements UserQueryService { private final UserRepository userRepository; private final RoomCustomRepository roomCustomRepository; + private final PostJpaRepository postJpaRepository; @Override public boolean existUserById(Long userId) { @@ -34,6 +38,12 @@ public User findUserById(Long userId) { .orElseThrow(() -> new RestApiException(UserErrorStatus._USER_NOT_FOUND)); } + @Override + public User getUserDetail(Long userId) { + User user = findUserById(userId); + return user; + } + @Override public Slice getUserRoomList(Long userId, LocalDate cursorDate, Long cursorId, RoomTypeEnum type, int size) { User user = userRepository.findById(userId) @@ -55,4 +65,18 @@ public Slice getUserRoomList(Long userId, LocalDate cursorDate, Long curs return roomList; } + + @Override + public Slice getUserPostList(Long userId, LocalDateTime cursorDateTime, PostTypeEnum type, int size) { + User user = findUserById(userId); + + cursorDateTime = cursorDateTime == null ? LocalDateTime.now() : cursorDateTime; + type = type == null ? PostTypeEnum.PROJECT : type; + + PageRequest pageRequest = PageRequest.of(0, size); + + Slice postList = postJpaRepository.findAllPostsByUser(user, cursorDateTime, pageRequest, type); + + return postList; + } } diff --git a/src/main/java/gaji/service/domain/user/web/controller/UserRestController.java b/src/main/java/gaji/service/domain/user/web/controller/UserRestController.java index 80a9b2f1..e045657c 100644 --- a/src/main/java/gaji/service/domain/user/web/controller/UserRestController.java +++ b/src/main/java/gaji/service/domain/user/web/controller/UserRestController.java @@ -1,6 +1,7 @@ package gaji.service.domain.user.web.controller; import com.querydsl.core.Tuple; +import gaji.service.domain.enums.PostTypeEnum; import gaji.service.domain.enums.RoomTypeEnum; import gaji.service.domain.user.converter.UserConverter; import gaji.service.domain.user.entity.User; @@ -16,6 +17,7 @@ import org.springframework.web.bind.annotation.*; import java.time.LocalDate; +import java.time.LocalDateTime; @RestController @RequestMapping("/api/users") @@ -66,5 +68,21 @@ public BaseResponse getUserRoomList(@PathVariabl return BaseResponse.onSuccess(UserConverter.toGetRoomListDTO(userRoomList)); } + @GetMapping("/{userId}") + public BaseResponse getUserDetail(@RequestHeader(value = "Authorization", required = false) String authorizationHeader, + @PathVariable("userId") Long userId) { + + User user = userQueryService.getUserDetail(userId); + return BaseResponse.onSuccess(UserConverter.toGetUserDetailDTO(user)); + } + + @GetMapping("/posts/{userId}") + public BaseResponse getUserPostList(@PathVariable Long userId, + @RequestParam(value = "cursorDate",required = false) LocalDateTime cursorDateTime, + @RequestParam(value = "type", required = false) PostTypeEnum type, + @RequestParam(defaultValue = "10") int size) { + Slice userPostList = userQueryService.getUserPostList(userId, cursorDateTime, type, size); + return BaseResponse.onSuccess(UserConverter.toGetPostListDTO(userPostList, type)); + } } diff --git a/src/main/java/gaji/service/domain/user/web/dto/UserResponseDTO.java b/src/main/java/gaji/service/domain/user/web/dto/UserResponseDTO.java index 51bed26d..5baae4e5 100644 --- a/src/main/java/gaji/service/domain/user/web/dto/UserResponseDTO.java +++ b/src/main/java/gaji/service/domain/user/web/dto/UserResponseDTO.java @@ -1,7 +1,8 @@ package gaji.service.domain.user.web.dto; +import gaji.service.domain.enums.PostStatusEnum; +import gaji.service.domain.enums.PostTypeEnum; import gaji.service.domain.enums.UserActive; -import gaji.service.domain.post.entity.Post; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -21,15 +22,6 @@ public static class CancleResultDTO { UserActive userActive; } - @Builder - @Getter - @NoArgsConstructor - @AllArgsConstructor - public static class GetPostsResultDTO { - Long userId; - List postIds; - } - @Builder @Getter @NoArgsConstructor @@ -59,6 +51,43 @@ public static class GetRoomListDTO { List roomList; boolean hasNext; } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class GetPostDTO { + Long postId; + Long userId; + String title; + String body; + PostTypeEnum type; + PostStatusEnum status; + String nickname; + String profileImagePth; + String createdAt; + int viewCnt; + int likeCnt; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class GetPostListDTO { + List postList; + boolean hasNext; + } + + @Getter + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class GetUserDetailDTO { + Long userId; + String nickname; + String profileImagePth; + } }