Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: 응원톡 무한 스크롤 방식 리팩토링 및 호스트 검증 AOP로 변경 #290

Merged
merged 2 commits into from
Feb 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,28 @@
import band.gosrock.api.comment.model.request.CreateCommentRequest;
import band.gosrock.api.comment.model.response.CreateCommentResponse;
import band.gosrock.api.comment.model.response.RetrieveCommentCountResponse;
import band.gosrock.api.comment.model.response.RetrieveCommentListResponse;
import band.gosrock.api.comment.model.response.RetrieveCommentDTO;
import band.gosrock.api.comment.model.response.RetrieveRandomCommentResponse;
import band.gosrock.api.comment.service.CreateCommentUseCase;
import band.gosrock.api.comment.service.DeleteCommentUseCase;
import band.gosrock.api.comment.service.RetrieveCommentCountUseCase;
import band.gosrock.api.comment.service.RetrieveCommentUseCase;
import band.gosrock.api.comment.service.RetrieveRandomCommentUseCase;
import band.gosrock.api.common.slice.SliceResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@SecurityRequirement(name = "access-token")
Expand Down Expand Up @@ -52,9 +55,10 @@ public CreateCommentResponse postComment(

@Operation(summary = "응원글을 조회합니다.")
@GetMapping
public RetrieveCommentListResponse getComments(
@PathVariable Long eventId, @RequestParam(required = false) Long lastId) {
return retrieveCommentUseCase.execute(eventId, lastId);
public SliceResponse<RetrieveCommentDTO> getComments(
@PathVariable Long eventId,
@ParameterObject @PageableDefault(size = 10) Pageable pageable) {
return retrieveCommentUseCase.execute(eventId, pageable);
}

@Operation(summary = "[어드민 기능] 응원글을 삭제합니다.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
import band.gosrock.api.comment.model.request.CreateCommentRequest;
import band.gosrock.api.comment.model.response.CreateCommentResponse;
import band.gosrock.api.comment.model.response.RetrieveCommentCountResponse;
import band.gosrock.api.comment.model.response.RetrieveCommentListResponse;
import band.gosrock.api.comment.model.response.RetrieveCommentDTO;
import band.gosrock.api.comment.model.response.RetrieveRandomCommentResponse;
import band.gosrock.api.common.slice.SliceResponse;
import band.gosrock.common.annotation.Mapper;
import band.gosrock.domain.domains.comment.adaptor.CommentAdaptor;
import band.gosrock.domain.domains.comment.domain.Comment;
Expand All @@ -32,10 +33,11 @@ public CreateCommentResponse toCreateCommentResponse(Comment comment, User user)
}

@Transactional(readOnly = true)
public RetrieveCommentListResponse toRetrieveCommentListResponse(
public SliceResponse<RetrieveCommentDTO> toRetrieveCommentListResponse(
CommentCondition commentCondition, Long currentUserId) {
Slice<Comment> comments = commentAdaptor.searchComment(commentCondition);
return RetrieveCommentListResponse.of(comments, currentUserId);
return SliceResponse.of(
comments.map(comment -> toRetrieveCommentDTO(comment, currentUserId)));
}

@Transactional(readOnly = true)
Expand All @@ -50,4 +52,8 @@ public RetrieveCommentCountResponse toRetrieveCommentCountResponse(Long commentC
public RetrieveRandomCommentResponse toRetrieveRandomCommentResponse(Comment comment) {
return RetrieveRandomCommentResponse.of(comment);
}

private RetrieveCommentDTO toRetrieveCommentDTO(Comment comment, Long currentUserId) {
return RetrieveCommentDTO.of(comment, currentUserId);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package band.gosrock.api.comment.service;

import static band.gosrock.api.common.aop.hostRole.FindHostFrom.EVENT_ID;
import static band.gosrock.api.common.aop.hostRole.HostQualification.MANAGER;

import band.gosrock.api.comment.mapper.CommentMapper;
import band.gosrock.api.common.UserUtils;
import band.gosrock.api.common.aop.hostRole.HostRolesAllowed;
import band.gosrock.common.annotation.UseCase;
import band.gosrock.domain.domains.comment.domain.Comment;
import band.gosrock.domain.domains.comment.service.CommentDomainService;
Expand All @@ -23,10 +26,8 @@ public class DeleteCommentUseCase {
private final CommentDomainService commentDomainService;

@Transactional
@HostRolesAllowed(role = MANAGER, findHostFrom = EVENT_ID)
public void execute(Long eventId, Long commentId) {
Long currentUserId = userUtils.getCurrentUserId();
// 권한 검사
eventService.checkEventHost(currentUserId, eventId);
Comment comment = commentMapper.retrieveComment(commentId);
commentDomainService.deleteComment(comment, eventId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@


import band.gosrock.api.comment.mapper.CommentMapper;
import band.gosrock.api.comment.model.response.RetrieveCommentListResponse;
import band.gosrock.api.comment.model.response.RetrieveCommentDTO;
import band.gosrock.api.common.UserUtils;
import band.gosrock.api.common.slice.SliceResponse;
import band.gosrock.common.annotation.UseCase;
import band.gosrock.domain.domains.comment.dto.condition.CommentCondition;
import band.gosrock.domain.domains.event.adaptor.EventAdaptor;
import band.gosrock.domain.domains.event.domain.Event;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;

@UseCase
@RequiredArgsConstructor
Expand All @@ -20,10 +22,10 @@ public class RetrieveCommentUseCase {

private final UserUtils userUtils;

public RetrieveCommentListResponse execute(Long eventId, Long lastId) {
public SliceResponse<RetrieveCommentDTO> execute(Long eventId, Pageable pageable) {
Event event = eventAdaptor.findById(eventId);
Long currentUserId = userUtils.getCurrentUserId();
CommentCondition commentCondition = new CommentCondition(event.getId(), lastId);
CommentCondition commentCondition = new CommentCondition(event.getId(), pageable);
return commentMapper.toRetrieveCommentListResponse(commentCondition, currentUserId);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package band.gosrock.api.issuedTicket.service;

import static band.gosrock.api.common.aop.hostRole.FindHostFrom.EVENT_ID;
import static band.gosrock.api.common.aop.hostRole.HostQualification.MANAGER;

import band.gosrock.api.common.UserUtils;
import band.gosrock.api.common.aop.hostRole.HostRolesAllowed;
import band.gosrock.api.issuedTicket.mapper.IssuedTicketMapper;
import band.gosrock.common.annotation.UseCase;
import band.gosrock.domain.common.vo.IssuedTicketInfoVo;
Expand All @@ -18,9 +21,8 @@ public class EntranceIssuedTicketUseCase {

private final UserUtils userUtils;

@HostRolesAllowed(role = MANAGER, findHostFrom = EVENT_ID)
public IssuedTicketInfoVo execute(Long eventId, Long issuedTicketId) {
Long currentUserId = userUtils.getCurrentUserId();
return issuedTicketDomainService.processingEntranceIssuedTicket(
eventId, currentUserId, issuedTicketId);
return issuedTicketDomainService.processingEntranceIssuedTicket(eventId, issuedTicketId);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package band.gosrock.api.issuedTicket.service;

import static band.gosrock.api.common.aop.hostRole.FindHostFrom.EVENT_ID;
import static band.gosrock.api.common.aop.hostRole.HostQualification.MANAGER;

import band.gosrock.api.config.security.SecurityUtils;
import band.gosrock.api.common.aop.hostRole.HostRolesAllowed;
import band.gosrock.api.issuedTicket.dto.response.RetrieveIssuedTicketListResponse;
import band.gosrock.api.issuedTicket.mapper.IssuedTicketMapper;
import band.gosrock.common.annotation.UseCase;
Expand All @@ -22,11 +24,9 @@ public class ReadIssuedTicketsUseCase {
* 발급된 티켓 리스트 가져오기 API 일단 유즈케이스에 트랜잭션 걸어서 처리 IssuedTicket에 걸린 event와 user를 연관관계 매핑 없이 조회하려할 때
* 로직이 너무 복잡해짐 => 일단 연관관계 매핑 걸어두고 나중에 QueryDsl 설정 들어오면 바꿔야 할 듯 => QueryDsl 추가 완료
*/
@HostRolesAllowed(role = MANAGER, findHostFrom = EVENT_ID)
public RetrieveIssuedTicketListResponse execute(
Long page, Long eventId, String userName, String phoneNumber) {
Long currentUserId = SecurityUtils.getCurrentUserId();
// 조회 유저 권한 인증
eventService.checkEventHost(currentUserId, eventId);
return issuedTicketMapper.toIssuedTicketPageResponse(
page, new IssuedTicketCondition(eventId, userName, phoneNumber));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
import band.gosrock.domain.domains.comment.exception.CommentNotFoundException;
import band.gosrock.domain.domains.comment.repository.CommentRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;

@Adaptor
@RequiredArgsConstructor
Expand All @@ -22,8 +20,7 @@ public Comment save(Comment comment) {
}

public Slice<Comment> searchComment(CommentCondition commentCondition) {
PageRequest pageRequest = PageRequest.of(0, 20, Sort.by("createdAt").ascending());
return commentRepository.searchToPage(commentCondition, pageRequest);
return commentRepository.searchToPage(commentCondition);
}

public Comment queryComment(Long commentId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.data.domain.Pageable;

@Getter
@AllArgsConstructor
public class CommentCondition {

private Long eventId;

private Long lastId;
private Pageable pageable;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@

import band.gosrock.domain.domains.comment.domain.Comment;
import band.gosrock.domain.domains.comment.dto.condition.CommentCondition;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;

public interface CommentCustomRepository {

Slice<Comment> searchToPage(CommentCondition commentCondition, Pageable pageable);
Slice<Comment> searchToPage(CommentCondition commentCondition);

Long countComment(Long eventId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static band.gosrock.domain.domains.comment.domain.QComment.comment;
import static band.gosrock.domain.domains.user.domain.QUser.user;

import band.gosrock.domain.common.util.SliceUtil;
import band.gosrock.domain.domains.comment.domain.Comment;
import band.gosrock.domain.domains.comment.domain.CommentStatus;
import band.gosrock.domain.domains.comment.dto.condition.CommentCondition;
Expand All @@ -15,9 +16,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import org.springframework.data.support.PageableExecutionUtils;

@RequiredArgsConstructor
Expand All @@ -26,42 +25,42 @@ public class CommentCustomRepositoryImpl implements CommentCustomRepository {
private final JPAQueryFactory queryFactory;

@Override
public Slice<Comment> searchToPage(CommentCondition commentCondition, Pageable pageable) {
public Slice<Comment> searchToPage(CommentCondition commentCondition) {
List<Comment> comments =
queryFactory
.selectFrom(comment)
.leftJoin(comment.user, user)
.fetchJoin()
.where(
eventIdEq(commentCondition.getEventId()),
lastIdLessThan(commentCondition.getLastId()),
comment.commentStatus.eq(CommentStatus.ACTIVE))
.orderBy(comment.id.desc())
.limit(pageable.getPageSize() + 1)
.offset(commentCondition.getPageable().getOffset())
.limit(commentCondition.getPageable().getPageSize() + 1)
.fetch();

return checkLastPage(pageable, comments);
return SliceUtil.valueOf(comments, commentCondition.getPageable());
}

private BooleanExpression eventIdEq(Long eventId) {
return eventId == null ? null : comment.eventId.eq(eventId);
}

private BooleanExpression lastIdLessThan(Long lastId) {
return lastId == null ? null : comment.id.lt(lastId);
}

private Slice<Comment> checkLastPage(Pageable pageable, List<Comment> comments) {

boolean hasNext = false;

if (comments.size() > pageable.getPageSize()) {
hasNext = true;
comments.remove(pageable.getPageSize());
}

return new SliceImpl<>(comments, pageable, hasNext);
}
// private BooleanExpression lastIdLessThan(Long lastId) {
// return lastId == null ? null : comment.id.lt(lastId);
// }
//
// private Slice<Comment> checkLastPage(Pageable pageable, List<Comment> comments) {
//
// boolean hasNext = false;
//
// if (comments.size() > pageable.getPageSize()) {
// hasNext = true;
// comments.remove(pageable.getPageSize());
// }
//
// return new SliceImpl<>(comments, pageable, hasNext);
// }

@Override
public Long countComment(Long eventId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,9 @@ public void withdrawIssuedTicket(Long itemId, List<IssuedTicket> issuedTickets)
}

@Transactional
public IssuedTicketInfoVo processingEntranceIssuedTicket(
Long eventId, Long currentUserId, Long issuedTicketId) {
public IssuedTicketInfoVo processingEntranceIssuedTicket(Long eventId, Long issuedTicketId) {
IssuedTicket issuedTicket = issuedTicketAdaptor.queryIssuedTicket(issuedTicketId);
issuedTicketValidator.validIssuedTicketEventIdEqualEvent(issuedTicket, eventId);
issuedTicketValidator.validCanModifyIssuedTicketUser(issuedTicket, currentUserId);
issuedTicket.entrance();
return issuedTicket.toIssuedTicketInfoVo();
}
Expand Down