Skip to content

Commit

Permalink
feat: getMapping의 PathVariable 변경으로 접속할 수 있는 가능성 삭제
Browse files Browse the repository at this point in the history
  • Loading branch information
l2yujw committed Dec 7, 2024
1 parent 976049f commit f81e221
Show file tree
Hide file tree
Showing 13 changed files with 81 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public enum ErrorStatus {
REPLY_LETTER_VALIDATION_ERROR(HttpStatus.BAD_REQUEST, "REPLY_LETTER4001"),
INVALID_LETTER_TYPE(HttpStatus.BAD_REQUEST, "LETTER_TYPE4000"),
DUPLICATE_REPLY_LETTER(HttpStatus.BAD_REQUEST, "REPLY_LETTER4002"),
LETTER_AUTHOR_MISMATCH(HttpStatus.BAD_REQUEST, "LETTER4004"),
UNAUTHORIZED_LETTER_ACCESS(HttpStatus.UNAUTHORIZED, "LETTER4010"),

// 추천 에러
TEMP_RECOMMENDATIONS_NOT_FOUND(HttpStatus.NOT_FOUND, "TEMP_RECOMMENDATIONS_4040"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import postman.bottler.letter.dto.response.LetterRecommendHeadersResponseDTO;
import postman.bottler.letter.exception.InvalidLetterRequestException;
import postman.bottler.letter.service.DeleteManagerService;
import postman.bottler.letter.service.LetterBoxService;
import postman.bottler.letter.service.LetterService;
import postman.bottler.letter.utiil.ValidationUtil;
import postman.bottler.user.auth.CustomUserDetails;
Expand All @@ -40,6 +41,7 @@ public class LetterController {
private final LetterKeywordService letterKeywordService;
private final ValidationUtil validationUtil;
private final RedisLetterService redisLetterService;
private final LetterBoxService letterBoxService;

@Operation(
summary = "키워드 편지 생성",
Expand Down Expand Up @@ -77,6 +79,7 @@ public ApiResponse<String> deleteLetter(
public ApiResponse<LetterDetailResponseDTO> getLetter(
@PathVariable Long letterId, @AuthenticationPrincipal CustomUserDetails userDetails
) {
letterBoxService.validateLetterInUserBox(letterId, userDetails.getUserId());
List<String> keywords = letterKeywordService.getKeywords(letterId);
LetterDetailResponseDTO result = letterService.getLetterDetail(letterId, keywords, userDetails.getUserId());
return ApiResponse.onSuccess(result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import postman.bottler.letter.exception.InvalidPageRequestException;
import postman.bottler.letter.exception.InvalidReplyLetterRequestException;
import postman.bottler.letter.service.DeleteManagerService;
import postman.bottler.letter.service.LetterBoxService;
import postman.bottler.letter.service.ReplyLetterService;
import postman.bottler.letter.utiil.ValidationUtil;
import postman.bottler.user.auth.CustomUserDetails;
Expand All @@ -40,6 +41,7 @@ public class ReplyLetterController {
private final ReplyLetterService letterReplyService;
private final DeleteManagerService deleteManagerService;
private final ValidationUtil validationUtil;
private final LetterBoxService letterBoxService;

@Operation(
summary = "키워드 편지 생성",
Expand Down Expand Up @@ -70,6 +72,7 @@ public ApiResponse<PageResponseDTO<ReplyLetterHeadersResponseDTO>> getReplyForLe
BindingResult bindingResult,
@AuthenticationPrincipal CustomUserDetails userDetails
) {
letterBoxService.validateLetterInUserBox(letterId, userDetails.getUserId());
validatePageRequest(bindingResult);
Page<ReplyLetterHeadersResponseDTO> result =
letterReplyService.getReplyLetterHeadersById(letterId, pageRequestDTO, userDetails.getUserId());
Expand All @@ -82,8 +85,10 @@ public ApiResponse<PageResponseDTO<ReplyLetterHeadersResponseDTO>> getReplyForLe
)
@GetMapping("/detail/{replyLetterId}")
public ApiResponse<ReplyLetterResponseDTO> getReplyLetter(
@PathVariable Long replyLetterId
@PathVariable Long replyLetterId,
@AuthenticationPrincipal CustomUserDetails userDetails
) {
letterBoxService.validateLetterInUserBox(replyLetterId, userDetails.getUserId());
ReplyLetterResponseDTO result = letterReplyService.getReplyLetterDetail(replyLetterId);
return ApiResponse.onSuccess(result);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package postman.bottler.letter.exception;

public class LetterAuthorMismatchException extends RuntimeException {
public LetterAuthorMismatchException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
import static postman.bottler.global.response.code.ErrorStatus.INVALID_SORT_FIELD;
import static postman.bottler.global.response.code.ErrorStatus.LETTER_ACCESS_DENIED;
import static postman.bottler.global.response.code.ErrorStatus.LETTER_ALREADY_SAVED;
import static postman.bottler.global.response.code.ErrorStatus.LETTER_AUTHOR_MISMATCH;
import static postman.bottler.global.response.code.ErrorStatus.LETTER_DELETE_VALIDATION_ERROR;
import static postman.bottler.global.response.code.ErrorStatus.LETTER_NOT_FOUND;
import static postman.bottler.global.response.code.ErrorStatus.LETTER_UNKNOWN_VALIDATION_ERROR;
import static postman.bottler.global.response.code.ErrorStatus.LETTER_VALIDATION_ERROR;
import static postman.bottler.global.response.code.ErrorStatus.PAGINATION_VALIDATION_ERROR;
import static postman.bottler.global.response.code.ErrorStatus.REPLY_LETTER_VALIDATION_ERROR;
import static postman.bottler.global.response.code.ErrorStatus.TEMP_RECOMMENDATIONS_NOT_FOUND;
import static postman.bottler.global.response.code.ErrorStatus.UNAUTHORIZED_LETTER_ACCESS;

import java.util.Map;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -114,4 +116,19 @@ public ResponseEntity<ApiResponse<String>> handleInvalidLetterTypeException(
.status(TEMP_RECOMMENDATIONS_NOT_FOUND.getHttpStatus())
.body(ApiResponse.onFailure(TEMP_RECOMMENDATIONS_NOT_FOUND.getCode(), e.getMessage(), null));
}

@ExceptionHandler(LetterAuthorMismatchException.class)
public ResponseEntity<ApiResponse<String>> handleLetterAuthorMismatchException(LetterAuthorMismatchException e) {
return ResponseEntity
.status(LETTER_AUTHOR_MISMATCH.getHttpStatus())
.body(ApiResponse.onFailure(LETTER_AUTHOR_MISMATCH.getCode(), e.getMessage(), null));
}

@ExceptionHandler(UnauthorizedLetterAccessException.class)
public ResponseEntity<ApiResponse<String>> handleUnauthorizedLetterAccessException(
UnauthorizedLetterAccessException e) {
return ResponseEntity
.status(UNAUTHORIZED_LETTER_ACCESS.getHttpStatus())
.body(ApiResponse.onFailure(UNAUTHORIZED_LETTER_ACCESS.getCode(), e.getMessage(), null));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package postman.bottler.letter.exception;

public class UnauthorizedLetterAccessException extends RuntimeException {
public UnauthorizedLetterAccessException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,11 @@ public void saveAll(List<LetterBox> letterBoxes) {

jdbcTemplate.batchUpdate(sql, params);
}

public boolean existsByUserIdAndLetterId(Long letterId, Long userId) {
String sql = "SELECT COUNT(*) FROM letter_box WHERE user_id = ? AND letter_id = ?";

Integer count = jdbcTemplate.queryForObject(sql, Integer.class, userId, letterId);
return count > 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ public List<Long> getReceivedLettersById(Long userId) {
return letterBoxQueryRepository.getReceivedLettersById(userId);
}

@Override
public boolean existsByLetterIdAndUserId(Long letterId, Long userId) {
return letterBoxJdbcRepository.existsByUserIdAndLetterId(letterId, userId);
}

private List<LetterHeadersResponseDTO> fetchLetters(Long userId, BoxType boxType, Pageable pageable) {
return letterBoxQueryRepository.fetchLetters(userId, boxType, pageable);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ private void processGroupedLetters(Map<LetterType, Map<BoxType, List<Long>>> gro
Map<BoxType, List<Long>> letterBoxMap = groupedByTypeAndBox.get(LetterType.LETTER);
if (letterBoxMap.containsKey(BoxType.SEND)) {
List<Long> letterIds = letterBoxMap.get(BoxType.SEND);
letterService.deleteLetters(letterIds);
letterService.deleteLetters(letterIds, userId);
letterKeywordService.markKeywordsAsDeleted(letterIds);
letterBoxService.deleteByIdsAndType(letterIds, LetterType.LETTER, BoxType.UNKNOWN);
}
Expand All @@ -65,7 +65,7 @@ private void processGroupedLetters(Map<LetterType, Map<BoxType, List<Long>>> gro
Map<BoxType, List<Long>> replyLetterBoxMap = groupedByTypeAndBox.get(LetterType.REPLY_LETTER);
if (replyLetterBoxMap.containsKey(BoxType.SEND)) {
List<Long> replyLetterIds = replyLetterBoxMap.get(BoxType.SEND);
replyLetterService.deleteReplyLetters(replyLetterIds);
replyLetterService.deleteReplyLetters(replyLetterIds, userId);
letterBoxService.deleteByIdsAndType(replyLetterIds, LetterType.REPLY_LETTER, BoxType.UNKNOWN);
}
if (replyLetterBoxMap.containsKey(BoxType.RECEIVE)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ public interface LetterBoxRepository {
void deleteByConditionAndUserId(List<Long> letterIds, LetterType letterType, BoxType boxType, Long userId);

List<Long> getReceivedLettersById(Long userId);

boolean existsByLetterIdAndUserId(Long letterId, Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import postman.bottler.letter.dto.LetterBoxDTO;
import postman.bottler.letter.dto.request.PageRequestDTO;
import postman.bottler.letter.dto.response.LetterHeadersResponseDTO;
import postman.bottler.letter.exception.UnauthorizedLetterAccessException;

@Slf4j
@Service
Expand Down Expand Up @@ -55,4 +56,11 @@ public List<Long> getLettersByUserId(Long userId) {
return letterBoxRepository.getReceivedLettersById(userId);
}

@Transactional(readOnly = true)
public void validateLetterInUserBox(Long letterId, Long userId) {
boolean isLetterInUserBox = letterBoxRepository.existsByLetterIdAndUserId(letterId, userId);
if (!isLetterInUserBox) {
throw new UnauthorizedLetterAccessException("사용자가 해당 편지에 접근할 권한이 없습니다.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import postman.bottler.letter.dto.request.LetterRequestDTO;
import postman.bottler.letter.dto.response.LetterDetailResponseDTO;
import postman.bottler.letter.dto.response.LetterRecommendHeadersResponseDTO;
import postman.bottler.letter.exception.LetterAuthorMismatchException;
import postman.bottler.letter.exception.LetterNotFoundException;
import postman.bottler.user.service.UserService;

Expand All @@ -35,7 +36,12 @@ public Letter createLetter(LetterRequestDTO letterRequestDTO, Long userId) {
}

@Transactional
public void deleteLetters(List<Long> letterIds) {
public void deleteLetters(List<Long> letterIds, Long userId) {
letterIds.forEach(letterId -> {
if (!findLetter(letterId).getUserId().equals(userId)) {
throw new LetterAuthorMismatchException("요청자와 작성자가 일치하지 않습니다.");
}
});
letterRepository.deleteByIds(letterIds);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import postman.bottler.letter.dto.response.ReplyLetterHeadersResponseDTO;
import postman.bottler.letter.dto.response.ReplyLetterResponseDTO;
import postman.bottler.letter.exception.DuplicateReplyLetterException;
import postman.bottler.letter.exception.LetterAuthorMismatchException;
import postman.bottler.letter.exception.LetterNotFoundException;
import postman.bottler.reply.dto.ReplyType;

Expand Down Expand Up @@ -80,10 +81,13 @@ public ReplyLetterResponseDTO getReplyLetterDetail(Long replyLetterId) {
}

@Transactional
public void deleteReplyLetters(List<Long> letterIds) {
for (Long letterId : letterIds) {
deleteRecentReply(letterId);
}
public void deleteReplyLetters(List<Long> letterIds, Long userId) {
letterIds.forEach(letterId -> {
if (!findReplyLetter(letterId).getSenderId().equals(userId)) {
throw new LetterAuthorMismatchException("요청자와 작성자가 일치하지 않습니다.");
}
});
letterIds.forEach(this::deleteRecentReply);
replyLetterRepository.deleteByIds(letterIds);
}

Expand Down

0 comments on commit f81e221

Please sign in to comment.