diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/EventController.java b/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/EventController.java index 3183dbe5..25628486 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/EventController.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/EventController.java @@ -4,6 +4,7 @@ import JGS.CasperEvent.domain.event.dto.ResponseDto.TotalEventDateResponseDto; import JGS.CasperEvent.domain.event.service.eventService.EventService; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -19,6 +20,8 @@ public class EventController { @GetMapping("/total") public ResponseEntity getTotalEventDate() { TotalEventDateResponseDto totalEventDateResponseDto = eventService.getTotalEventDate(); - return ResponseEntity.ok(totalEventDateResponseDto); + return ResponseEntity + .status(HttpStatus.OK) + .body(totalEventDateResponseDto); } } diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/LotteryEventController.java b/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/LotteryEventController.java index 7715f21c..58bb8abd 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/LotteryEventController.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/LotteryEventController.java @@ -74,7 +74,7 @@ public ResponseEntity postCasperBot( @ApiResponse(responseCode = "404", description = "User has not applied") }) @GetMapping("/applied") - public ResponseEntity GetLotteryParticipant(HttpServletRequest request) { + public ResponseEntity getLotteryParticipant(HttpServletRequest request) { BaseUser user = (BaseUser) request.getAttribute("user"); return ResponseEntity .status(HttpStatus.OK) diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/RushEventController.java b/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/RushEventController.java index 3ac077e1..9778934e 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/RushEventController.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/event/controller/eventController/RushEventController.java @@ -9,6 +9,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import jakarta.servlet.http.HttpServletRequest; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -26,7 +27,9 @@ public RushEventController(RushEventService rushEventService) { @ApiResponse(responseCode = "200", description = "Successfully retrieved the list of rush events.") @GetMapping public ResponseEntity getRushEventListAndServerTime() { - return ResponseEntity.ok(rushEventService.getAllRushEvents()); + return ResponseEntity + .status(HttpStatus.OK) + .body(rushEventService.getAllRushEvents()); } @Operation(summary = "응모 여부 체크", description = "해당 유저가 오늘의 이벤트에 응모했는지 여부를 조회합니다.") @@ -34,7 +37,9 @@ public ResponseEntity getRushEventListAndServerTime() @GetMapping("/applied") public ResponseEntity checkUserParticipationInRushEvent(HttpServletRequest httpServletRequest) { BaseUser user = (BaseUser) httpServletRequest.getAttribute("user"); - return ResponseEntity.ok(rushEventService.isExists(user.getId())); + return ResponseEntity + .status(HttpStatus.OK) + .body(rushEventService.isExists(user.getId())); } @Operation(summary = "선착순 이벤트 응모", description = "해당 유저가 오늘의 이벤트에 응모합니다. optionId 값이 필요합니다. optionId 값이 1이면 왼쪽 선택지, 2이면 오른쪽 선택지에 응모합니다.") @@ -48,7 +53,9 @@ public ResponseEntity applyRushEvent(HttpServletRequest httpServletRequest BaseUser user = (BaseUser) httpServletRequest.getAttribute("user"); rushEventService.apply(user, optionId); - return ResponseEntity.noContent().build(); + return ResponseEntity + .status(HttpStatus.NO_CONTENT) + .build(); } @Operation(summary = "실시간 응모 비율 조회", description = "실시간으로 변경되는 응모 비율을 조회합니다.") @@ -57,7 +64,9 @@ public ResponseEntity applyRushEvent(HttpServletRequest httpServletRequest public ResponseEntity rushEventRate(HttpServletRequest httpServletRequest) { BaseUser user = (BaseUser) httpServletRequest.getAttribute("user"); RushEventRateResponseDto rushEventRateResponseDto = rushEventService.getRushEventRate(user); - return ResponseEntity.ok(rushEventRateResponseDto); + return ResponseEntity + .status(HttpStatus.OK) + .body(rushEventRateResponseDto); } @Operation(summary = "선착순 이벤트 결과를 조회합니다.", description = "이벤트가 끝나고 나서 최종 결과를 조회합니다.") @@ -66,7 +75,9 @@ public ResponseEntity rushEventRate(HttpServletRequest public ResponseEntity rushEventResult(HttpServletRequest httpServletRequest) { BaseUser user = (BaseUser) httpServletRequest.getAttribute("user"); RushEventResultResponseDto result = rushEventService.getRushEventResult(user); - return ResponseEntity.ok(result); + return ResponseEntity + .status(HttpStatus.OK) + .body(result); } @Operation(summary = "오늘의 이벤트를 초기화합니다.", description = "오늘의 이벤트를 전부 초기화하고, 응모 여부도 전부 초기화합니다.") @@ -74,7 +85,9 @@ public ResponseEntity rushEventResult(HttpServletReq @GetMapping("/today/test") public ResponseEntity setTodayEvent() { rushEventService.setRushEvents(); - return ResponseEntity.noContent().build(); + return ResponseEntity + .status(HttpStatus.NO_CONTENT) + .build(); } @Operation(summary = "오늘의 이벤트 옵션을 조회합니다.", description = "이벤트 참여자가 이벤트에 진입했을 때 보여질 옵션 선택지 정보를 조회합니다.") @@ -82,7 +95,9 @@ public ResponseEntity setTodayEvent() { @GetMapping("/today") public ResponseEntity getTodayEvent() { MainRushEventOptionsResponseDto mainRushEventOptionsResponseDto = rushEventService.getTodayRushEventOptions(); - return ResponseEntity.ok(mainRushEventOptionsResponseDto); + return ResponseEntity + .status(HttpStatus.OK) + .body(mainRushEventOptionsResponseDto); } @Operation(summary = "옵션의 결과 Text를 조회합니다.", description = "유저가 응모를 했을 때 보여질 옵션의 상세 Text를 조회합니다.") @@ -93,6 +108,8 @@ public ResponseEntity getTodayEvent() { @GetMapping("/options/{optionId}/result") public ResponseEntity getResultOption(@PathVariable("optionId") int optionId) { ResultRushEventOptionResponseDto resultRushEventOptionResponseDto = rushEventService.getRushEventOptionResult(optionId); - return ResponseEntity.ok(resultRushEventOptionResponseDto); + return ResponseEntity + .status(HttpStatus.OK) + .body(resultRushEventOptionResponseDto); } } diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/dto/RequestDto/AdminRequestDto.java b/Server/src/main/java/JGS/CasperEvent/domain/event/dto/RequestDto/AdminRequestDto.java index 42ca19c8..77605025 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/event/dto/RequestDto/AdminRequestDto.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/event/dto/RequestDto/AdminRequestDto.java @@ -11,11 +11,11 @@ public class AdminRequestDto { @NotNull - @Schema(description = "관리자 아이디", example = "adminId", required = true) + @Schema(description = "관리자 아이디", example = "adminId") private String adminId; @NotNull - @Schema(description = "관리자 인증을 위한 비밀번호", example = "password", required = true) + @Schema(description = "관리자 인증을 위한 비밀번호", example = "password") private String password; } diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/dto/RequestDto/lotteryEventDto/CasperBotRequestDto.java b/Server/src/main/java/JGS/CasperEvent/domain/event/dto/RequestDto/lotteryEventDto/CasperBotRequestDto.java index 54706381..d7125f45 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/event/dto/RequestDto/lotteryEventDto/CasperBotRequestDto.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/event/dto/RequestDto/lotteryEventDto/CasperBotRequestDto.java @@ -17,35 +17,35 @@ public class CasperBotRequestDto { @NotNull(message = "눈 모양 값은 필수 필드입니다.") @Min(value = 0, message = "눈 모양 값이 부적절합니다.") @Max(value = 7, message = "눈 모양 값이 부적절합니다.") - @Schema(description = "눈 모양 값", example = "1", required = true) + @Schema(description = "눈 모양 값", example = "1") private Integer eyeShape; @NotNull(message = "눈 위치 값은 필수 필드입니다.") @Min(value = 0, message = "눈 위치 값이 부적절합니다.") @Max(value = 2, message = "눈 위치 값이 부적절합니다.") - @Schema(description = "눈 위치 값", example = "1", required = true) + @Schema(description = "눈 위치 값", example = "1") private Integer eyePosition; @NotNull(message = "입 모양 값은 필수 필드입니다.") @Min(value = 0, message = "입 모양 값이 부적절합니다.") @Max(value = 4, message = "입 모양 값이 부적절합니다.") - @Schema(description = "입 모양 값", example = "2", required = true) + @Schema(description = "입 모양 값", example = "2") private Integer mouthShape; @NotNull(message = "색깔 값은 필수 필드입니다.") @Min(value = 0, message = "색깔 값이 부적절합니다.") @Max(value = 17, message = "색깔 값이 부적절합니다.") - @Schema(description = "색깔 값", example = "8", required = true) + @Schema(description = "색깔 값", example = "8") private Integer color; @NotNull(message = "스티커 값은 필수 필드입니다.") @Min(value = 0, message = "스티커 값이 부적절합니다.") @Max(value = 4, message = "스티커 값이 부적절합니다.") - @Schema(description = "스티커 값", example = "1", required = true) + @Schema(description = "스티커 값", example = "1") private Integer sticker; @NotNull(message = "이름은 필수 필드입니다.") - @Schema(description = "캐스퍼 봇의 이름", example = "MyCasperBot", required = true) + @Schema(description = "캐스퍼 봇의 이름", example = "MyCasperBot") private String name; @Schema(description = "기대평", example = "캐스퍼 정말 기대되요!") diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/dto/RequestDto/lotteryEventDto/LotteryEventRequestDto.java b/Server/src/main/java/JGS/CasperEvent/domain/event/dto/RequestDto/lotteryEventDto/LotteryEventRequestDto.java index 76f1a745..334778b8 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/event/dto/RequestDto/lotteryEventDto/LotteryEventRequestDto.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/event/dto/RequestDto/lotteryEventDto/LotteryEventRequestDto.java @@ -16,22 +16,22 @@ public class LotteryEventRequestDto { @NotNull(message = "이벤트 시작 날짜를 지정하세요.") - @Schema(description = "이벤트의 시작 날짜", example = "2024-09-01", required = true) + @Schema(description = "이벤트의 시작 날짜", example = "2024-09-01") private LocalDate startDate; @NotNull(message = "이벤트 시작 시간을 지정하세요.") - @Schema(description = "이벤트의 시작 시간", example = "14:00:00", required = true) + @Schema(description = "이벤트의 시작 시간", example = "14:00:00") private LocalTime startTime; @NotNull(message = "이벤트 종료 날짜를 지정하세요.") - @Schema(description = "이벤트의 종료 날짜", example = "2024-09-30", required = true) + @Schema(description = "이벤트의 종료 날짜", example = "2024-09-30") private LocalDate endDate; @NotNull(message = "이벤트 종료 시간을 지정하세요.") - @Schema(description = "이벤트의 종료 시간", example = "18:00:00", required = true) + @Schema(description = "이벤트의 종료 시간", example = "18:00:00") private LocalTime endTime; @NotNull(message = "당첨인원 수를 지정하세요.") - @Schema(description = "당첨 인원 수", example = "10", required = true) + @Schema(description = "당첨 인원 수", example = "10") private int winnerCount; } diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/dto/ResponseDto/rushEventResponseDto/MainRushEventOptionsResponseDto.java b/Server/src/main/java/JGS/CasperEvent/domain/event/dto/ResponseDto/rushEventResponseDto/MainRushEventOptionsResponseDto.java index 6b1294c4..ed6f1489 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/event/dto/ResponseDto/rushEventResponseDto/MainRushEventOptionsResponseDto.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/event/dto/ResponseDto/rushEventResponseDto/MainRushEventOptionsResponseDto.java @@ -3,9 +3,4 @@ public record MainRushEventOptionsResponseDto(MainRushEventOptionResponseDto leftOption, MainRushEventOptionResponseDto rightOption) { - - public MainRushEventOptionsResponseDto(MainRushEventOptionResponseDto leftOption, MainRushEventOptionResponseDto rightOption) { - this.leftOption = leftOption; - this.rightOption = rightOption; - } } diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/entity/admin/Admin.java b/Server/src/main/java/JGS/CasperEvent/domain/event/entity/admin/Admin.java index 4e4d1c12..84370479 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/event/entity/admin/Admin.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/event/entity/admin/Admin.java @@ -1,13 +1,14 @@ package JGS.CasperEvent.domain.event.entity.admin; -import JGS.CasperEvent.global.entity.BaseEntity; import JGS.CasperEvent.global.entity.BaseUser; import JGS.CasperEvent.global.enums.Role; import jakarta.persistence.Entity; +import lombok.EqualsAndHashCode; import lombok.Getter; @Entity @Getter +@EqualsAndHashCode(callSuper = false) public class Admin extends BaseUser { private String password; diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/repository/CasperBotRepository.java b/Server/src/main/java/JGS/CasperEvent/domain/event/repository/CasperBotRepository.java index de81cb13..04384d07 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/event/repository/CasperBotRepository.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/event/repository/CasperBotRepository.java @@ -8,8 +8,6 @@ import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import java.util.List; - @Repository public interface CasperBotRepository extends JpaRepository { @Query("SELECT c FROM CasperBot c WHERE c.phoneNumber = :phoneNumber AND c.isDeleted = false AND c.expectation <> ''") diff --git a/Server/src/main/java/JGS/CasperEvent/domain/event/service/adminService/AdminService.java b/Server/src/main/java/JGS/CasperEvent/domain/event/service/adminService/AdminService.java index 53d24367..3fe772e5 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/event/service/adminService/AdminService.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/event/service/adminService/AdminService.java @@ -41,7 +41,6 @@ import java.time.LocalDateTime; import java.util.*; -import java.util.stream.Collectors; import static JGS.CasperEvent.global.util.RepositoryErrorHandler.findByIdOrElseThrow; @@ -59,6 +58,7 @@ public class AdminService { private final CasperBotRepository casperBotRepository; private final LotteryWinnerRepository lotteryWinnerRepository; private final RedisTemplate casperBotRedisTemplate; + private final Random random = new Random(); // 어드민 인증 public Admin verifyAdmin(AdminRequestDto adminRequestDto) { @@ -147,30 +147,28 @@ public AdminRushEventResponseDto createRushEvent(RushEventRequestDto rushEventRe RushEventOptionRequestDto leftOption = rushEventRequestDto.getLeftOptionRequestDto(); RushEventOptionRequestDto rightOption = rushEventRequestDto.getRightOptionRequestDto(); - RushOption leftRushOption = rushOptionRepository.save(new RushOption( - rushEvent, - leftOption.getMainText(), - leftOption.getSubText(), - leftOption.getResultMainText(), - leftOption.getResultSubText(), - leftOptionImgSrc, - Position.LEFT - )); - - RushOption rightRushOption = rushOptionRepository.save(new RushOption( - rushEvent, - rightOption.getMainText(), - rightOption.getSubText(), - rightOption.getResultMainText(), - rightOption.getResultSubText(), - rightOptionImgSrc, - Position.RIGHT - )); + RushOption leftRushOption = createAndSaveRushOption(rushEvent, leftOption, leftOptionImgSrc, Position.LEFT); + RushOption rightRushOption = createAndSaveRushOption(rushEvent, rightOption, rightOptionImgSrc, Position.RIGHT); rushEvent.addOption(leftRushOption, rightRushOption); return AdminRushEventResponseDto.of(rushEvent); } + public RushOption createAndSaveRushOption(RushEvent rushEvent, RushEventOptionRequestDto optionDto, String imgSrc, Position position) { + + RushOption rushOption = new RushOption( + rushEvent, + optionDto.getMainText(), + optionDto.getSubText(), + optionDto.getResultMainText(), + optionDto.getResultSubText(), + imgSrc, + position + ); + + return rushOptionRepository.save(rushOption); + } + // 선착순 이벤트 조회 public List getRushEvents() { List rushEvents = rushEventRepository.findAll(); @@ -237,8 +235,11 @@ public RushEventParticipantsListResponseDto getRushEventWinners(long rushEventId boolean isPhoneNumberEmpty = phoneNumber.isEmpty(); - int winnerOptionId = (leftSelect > rightSelect) ? 1 : (leftSelect < rightSelect) ? 2 : 0; + int winnerOptionId; + if (leftSelect > rightSelect) winnerOptionId = 1; + else if (leftSelect < rightSelect) winnerOptionId = 2; + else winnerOptionId = 0; if (!isPhoneNumberEmpty && winnerOptionId != 0) { // 전화번호와 유효한 옵션 ID가 있는 경우 @@ -340,10 +341,15 @@ public ResponseDto pickLotteryEventWinners() { List lotteryParticipants = lotteryParticipantsRepository.findIdAndAppliedCounts(); if (winnerCount >= lotteryParticipants.size()) { + Long winnerId; for (Object[] lotteryParticipant : lotteryParticipants) { + winnerId = (Long) lotteryParticipant[0]; lotteryWinnerRepository.save(new LotteryWinners( - lotteryParticipantsRepository.findById((Long) lotteryParticipant[0]).get() + lotteryParticipantsRepository.findById(winnerId).orElseThrow( + () -> new CustomException(CustomErrorCode.USER_NOT_FOUND) + ) )); + } return new ResponseDto("추첨이 완료되었습니다."); } @@ -359,7 +365,6 @@ public ResponseDto pickLotteryEventWinners() { } // Fisher-Yates Shuffle Algorithm - Random random = new Random(); for (int i = appliedParticipants.size() - 1; i > 0; i--) { int j = random.nextInt(i + 1); Long temp = appliedParticipants.get(i); @@ -375,8 +380,9 @@ public ResponseDto pickLotteryEventWinners() { } List winnersToSave = lotteryEventWinners.stream() - .map(winnerId -> new LotteryWinners(lotteryParticipantsRepository.findById(winnerId).get())) - .collect(Collectors.toList()); + .map(winnerId -> new LotteryWinners(lotteryParticipantsRepository.findById(winnerId).orElseThrow(() -> + new CustomException(CustomErrorCode.USER_NOT_FOUND) + ))).toList(); lotteryWinnerRepository.saveAll(winnersToSave); @@ -422,49 +428,74 @@ public List updateRushEvents(List rushEvents = rushEventRepository.findAll(); List rushEventResponseDtoList = new ArrayList<>(); for (RushEvent rushEvent : rushEvents) { rushEventResponseDtoList.add(AdminRushEventResponseDto.of(rushEvent)); } + return rushEventResponseDtoList; } + // 이벤트 시간 유효성 검사 + private void validateEventTimes(RushEvent rushEvent, LocalDateTime startDateTime, LocalDateTime endDateTime, LocalDateTime now) { + LocalDateTime curStartDateTime = rushEvent.getStartDateTime(); + LocalDateTime curEndDateTime = rushEvent.getEndDateTime(); + + if (!Objects.equals(curStartDateTime, startDateTime) || !Objects.equals(curEndDateTime, endDateTime)) { + checkEndTimeBeforeStartTime(startDateTime, endDateTime); + checkEventInProgress(rushEvent, startDateTime, endDateTime, now); + checkEventBeforeStartTime(startDateTime, now); + } + } + + // 현재 시간이 종료 시간보다 앞서는 경우 + private void checkEndTimeBeforeStartTime(LocalDateTime startDateTime, LocalDateTime endDateTime) { + if (endDateTime.isBefore(startDateTime)) { + throw new CustomException(CustomErrorCode.EVENT_END_TIME_BEFORE_START_TIME); + } + } + + // 이벤트가 현재 진행중인지 확인 + private void checkEventInProgress(RushEvent rushEvent, LocalDateTime startDateTime, LocalDateTime endDateTime, LocalDateTime now) { + LocalDateTime curStartDateTime = rushEvent.getStartDateTime(); + LocalDateTime curEndDateTime = rushEvent.getEndDateTime(); + + if (curStartDateTime.isBefore(now) && curEndDateTime.isAfter(now)) { + if (!curStartDateTime.equals(startDateTime)) { + throw new CustomException(CustomErrorCode.EVENT_IN_PROGRESS_CANNOT_CHANGE_START_TIME); + } + if (endDateTime.isBefore(now)) { + throw new CustomException(CustomErrorCode.EVENT_IN_PROGRESS_END_TIME_BEFORE_NOW); + } + } + } + + // 이벤트가 시작 전인지 확인 + private void checkEventBeforeStartTime(LocalDateTime startDateTime, LocalDateTime now) { + if (startDateTime.isBefore(now)) { + throw new CustomException(CustomErrorCode.EVENT_BEFORE_START_TIME); + } + } + + // 선착순 이벤트 업데이트 + private void updateRushEvent(RushEvent rushEvent, RushEventRequestDto rushEventRequestDto) { + RushOption leftOption = rushEvent.getLeftOption(); + RushOption rightOption = rushEvent.getRightOption(); + + rushEvent.updateRushEvent(rushEventRequestDto); + leftOption.updateRushOption(rushEventRequestDto.getLeftOptionRequestDto()); + rightOption.updateRushOption(rushEventRequestDto.getRightOptionRequestDto()); + } + // 선착순 이벤트 삭제 @Transactional public ResponseDto deleteRushEvent(Long rushEventId) { @@ -506,8 +537,7 @@ public LotteryEventExpectationsResponseDto getLotteryEventExpectations(int page, casperBot.getExpectation(), casperBot.getCreatedAt().toLocalDate(), casperBot.getCreatedAt().toLocalTime() - )) - .collect(Collectors.toList()); + )).toList(); // 마지막 페이지 여부 계산 boolean isLastPage = casperBotPage.isLast(); @@ -523,14 +553,13 @@ public void deleteLotteryEventExpectation(Long casperId) { () -> new CustomException(CustomErrorCode.CASPERBOT_NOT_FOUND) ); - // todo: 전체 설정에서 가져오도록 변경 final String LIST_KEY = "recentData"; // 긍정적인 문구 리스트 List positiveMessages = List.of("사랑해 캐스퍼", "캐스퍼 최고!", "캐스퍼와 함께해요!", "캐스퍼 짱!", "캐스퍼는 나의 친구!"); // 랜덤으로 긍정적인 문구 선택 - String randomPositiveMessage = positiveMessages.get(new Random().nextInt(positiveMessages.size())); + String randomPositiveMessage = positiveMessages.get(random.nextInt(positiveMessages.size())); // isDeleted = true 로 업데이트 casperBot.deleteExpectation(); @@ -555,8 +584,7 @@ public void deleteLotteryEventExpectation(Long casperId) { ); } return data; - }) - .collect(Collectors.toList()); + }).toList(); // Redis에서 현재 리스트를 삭제합니다. casperBotRedisTemplate.delete(LIST_KEY); diff --git a/Server/src/main/java/JGS/CasperEvent/domain/health/api/HealthController.java b/Server/src/main/java/JGS/CasperEvent/domain/health/api/HealthController.java index 058b61ed..ef9a7664 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/health/api/HealthController.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/health/api/HealthController.java @@ -1,5 +1,6 @@ package JGS.CasperEvent.domain.health.api; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -11,6 +12,8 @@ public class HealthController { @GetMapping public ResponseEntity health(){ - return ResponseEntity.ok().body("Server OK"); + return ResponseEntity + .status(HttpStatus.OK) + .body("Server OK"); } } diff --git a/Server/src/main/java/JGS/CasperEvent/domain/url/controller/UrlController.java b/Server/src/main/java/JGS/CasperEvent/domain/url/controller/UrlController.java index 7c206cc5..47891334 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/url/controller/UrlController.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/url/controller/UrlController.java @@ -5,7 +5,6 @@ import JGS.CasperEvent.global.entity.BaseUser; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; diff --git a/Server/src/main/java/JGS/CasperEvent/domain/url/service/UrlService.java b/Server/src/main/java/JGS/CasperEvent/domain/url/service/UrlService.java index 263c18a9..c2652818 100644 --- a/Server/src/main/java/JGS/CasperEvent/domain/url/service/UrlService.java +++ b/Server/src/main/java/JGS/CasperEvent/domain/url/service/UrlService.java @@ -7,7 +7,6 @@ import JGS.CasperEvent.global.util.AESUtils; import JGS.CasperEvent.global.util.Base62Utils; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -17,7 +16,6 @@ import javax.crypto.SecretKey; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.util.NoSuchElementException; @Service @RequiredArgsConstructor diff --git a/Server/src/main/java/JGS/CasperEvent/global/config/RedisConfig.java b/Server/src/main/java/JGS/CasperEvent/global/config/RedisConfig.java index 5b55a3f4..217c1820 100644 --- a/Server/src/main/java/JGS/CasperEvent/global/config/RedisConfig.java +++ b/Server/src/main/java/JGS/CasperEvent/global/config/RedisConfig.java @@ -1,7 +1,6 @@ package JGS.CasperEvent.global.config; import JGS.CasperEvent.domain.event.dto.ResponseDto.lotteryEventResponseDto.CasperBotResponseDto; -import JGS.CasperEvent.domain.event.dto.ResponseDto.rushEventResponseDto.RushEventResponseDto; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; @@ -25,12 +24,11 @@ public class RedisConfig { @Bean public RedisConnectionFactory redisConnectionFactory(){ RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(host, port); - LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration); - return lettuceConnectionFactory; + return new LettuceConnectionFactory(redisStandaloneConfiguration); } @Bean - public RedisTemplate CasperBotRedisTemplate(){ + public RedisTemplate casperBotRedisTemplate(){ RedisTemplate redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory()); redisTemplate.setKeySerializer(new StringRedisSerializer()); diff --git a/Server/src/main/java/JGS/CasperEvent/global/config/SecurityConfig.java b/Server/src/main/java/JGS/CasperEvent/global/config/SecurityConfig.java index 90dbf9ad..d2721d4d 100644 --- a/Server/src/main/java/JGS/CasperEvent/global/config/SecurityConfig.java +++ b/Server/src/main/java/JGS/CasperEvent/global/config/SecurityConfig.java @@ -1,11 +1,13 @@ package JGS.CasperEvent.global.config; import JGS.CasperEvent.global.util.AESUtils; +import io.jsonwebtoken.security.Keys; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.crypto.SecretKey; +import java.security.Key; @Configuration public class SecurityConfig { @@ -13,8 +15,17 @@ public class SecurityConfig { @Value("${spring.encryption.key}") private String encryptionKey; + @Value("${spring.jwt.secretKey}") + private String secretKey; + @Bean public SecretKey secretKey() { return AESUtils.stringToKey(encryptionKey); } + + @Bean + public Key jwtKey(){ + byte[] secret = secretKey.getBytes(); + return Keys.hmacShaKeyFor(secret); + } } diff --git a/Server/src/main/java/JGS/CasperEvent/global/config/WebConfig.java b/Server/src/main/java/JGS/CasperEvent/global/config/WebConfig.java index 696f0f9f..0cd3f777 100644 --- a/Server/src/main/java/JGS/CasperEvent/global/config/WebConfig.java +++ b/Server/src/main/java/JGS/CasperEvent/global/config/WebConfig.java @@ -19,10 +19,8 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - @Configuration public class WebConfig implements WebMvcConfigurer { - @Bean public FilterRegistrationBean corsFilterRegistrationBean() { FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); @@ -47,7 +45,7 @@ public UrlBasedCorsConfigurationSource corsConfigurationSource() { } @Bean - public FilterRegistrationBean verifyUserFilter(ObjectMapper mapper, UserService userService) { + public FilterRegistrationBean verifyUserFilter(ObjectMapper mapper, UserService userService) { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); filterRegistrationBean.setFilter(new VerifyUserFilter(mapper, userService)); @@ -57,7 +55,7 @@ public FilterRegistrationBean verifyUserFilter(ObjectMapper mapper, UserService } @Bean - public FilterRegistrationBean jwtFilter(JwtProvider provider, ObjectMapper mapper) { + public FilterRegistrationBean jwtFilter(JwtProvider provider, ObjectMapper mapper) { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); filterRegistrationBean.setFilter(new JwtUserFilter(provider, mapper)); @@ -67,7 +65,7 @@ public FilterRegistrationBean jwtFilter(JwtProvider provider, ObjectMapper mappe } @Bean - public FilterRegistrationBean verifyAdminFilter(ObjectMapper mapper, AdminService adminService) { + public FilterRegistrationBean verifyAdminFilter(ObjectMapper mapper, AdminService adminService) { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); @@ -78,7 +76,7 @@ public FilterRegistrationBean verifyAdminFilter(ObjectMapper mapper, AdminServic } @Bean - public FilterRegistrationBean jwtAdminFilter(JwtProvider provider, ObjectMapper mapper) { + public FilterRegistrationBean jwtAdminFilter(JwtProvider provider, ObjectMapper mapper) { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); filterRegistrationBean.setFilter(new JwtUserFilter(provider, mapper)); @@ -87,7 +85,7 @@ public FilterRegistrationBean jwtAdminFilter(JwtProvider provider, ObjectMapper return filterRegistrationBean; } @Bean - public FilterRegistrationBean jwtAuthorizationFilter(JwtProvider provider, ObjectMapper mapper) { + public FilterRegistrationBean jwtAuthorizationFilter(JwtProvider provider, ObjectMapper mapper) { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); filterRegistrationBean.setFilter(new JwtAuthorizationFilter(provider, mapper)); diff --git a/Server/src/main/java/JGS/CasperEvent/global/enums/EventStatus.java b/Server/src/main/java/JGS/CasperEvent/global/enums/EventStatus.java index 84ddd1c0..8f837d93 100644 --- a/Server/src/main/java/JGS/CasperEvent/global/enums/EventStatus.java +++ b/Server/src/main/java/JGS/CasperEvent/global/enums/EventStatus.java @@ -8,9 +8,9 @@ public enum EventStatus { DURING(2), AFTER(3); - private final int eventStatus; + private final int statusNum; - EventStatus(int eventStatus){ - this.eventStatus = eventStatus; + EventStatus(int statusNum){ + this.statusNum = statusNum; } } diff --git a/Server/src/main/java/JGS/CasperEvent/global/enums/Position.java b/Server/src/main/java/JGS/CasperEvent/global/enums/Position.java index 25c7a205..4b4e1551 100644 --- a/Server/src/main/java/JGS/CasperEvent/global/enums/Position.java +++ b/Server/src/main/java/JGS/CasperEvent/global/enums/Position.java @@ -8,15 +8,15 @@ public enum Position { LEFT(1), RIGHT(2); - private final int position; + private final int positionNum; - Position(int position) { - this.position = position; + Position(int positionNum) { + this.positionNum = positionNum; } public static Position of(int position) { for (Position pos : Position.values()) { - if (pos.getPosition() == position) { + if (pos.getPositionNum() == position) { return pos; } } diff --git a/Server/src/main/java/JGS/CasperEvent/global/jwt/util/JwtProvider.java b/Server/src/main/java/JGS/CasperEvent/global/jwt/util/JwtProvider.java index 69745bb0..d4cb645a 100644 --- a/Server/src/main/java/JGS/CasperEvent/global/jwt/util/JwtProvider.java +++ b/Server/src/main/java/JGS/CasperEvent/global/jwt/util/JwtProvider.java @@ -3,7 +3,7 @@ import JGS.CasperEvent.global.jwt.dto.Jwt; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.security.Keys; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import java.security.Key; @@ -11,9 +11,10 @@ import java.util.Map; @Component +@RequiredArgsConstructor public class JwtProvider { - public static final byte[] secret = "JaeYoungSecretKeyJaeYoungSecretKeyJaeYoungSecretKey".getBytes(); - private final Key key = Keys.hmacShaKeyFor(secret); + + private final Key jwtKey; public Jwt createJwt(Map claims) { String accessToken = createToken(claims, getExpireDateAccessToken()); @@ -26,13 +27,13 @@ private String createToken(Map claims, Date expireDate) { return Jwts.builder() .setClaims(claims) .setExpiration(expireDate) - .signWith(key) + .signWith(jwtKey) .compact(); } public Claims getClaims(String token) { return Jwts.parserBuilder() - .setSigningKey(key) + .setSigningKey(jwtKey) .build() .parseClaimsJws(token) .getBody(); diff --git a/Server/src/main/java/JGS/CasperEvent/global/service/S3Service.java b/Server/src/main/java/JGS/CasperEvent/global/service/S3Service.java index 5c574018..e0518f9a 100644 --- a/Server/src/main/java/JGS/CasperEvent/global/service/S3Service.java +++ b/Server/src/main/java/JGS/CasperEvent/global/service/S3Service.java @@ -36,7 +36,11 @@ public String upload(MultipartFile image) { } private String uploadImage(MultipartFile image) { - this.validateImageFileExtension(image.getOriginalFilename()); + String originalFilename = image.getOriginalFilename(); + if (originalFilename == null) { + throw new AmazonS3Exception("파일명이 null입니다."); + } + this.validateImageFileExtension(originalFilename); try { return this.uploadImageToS3(image); } catch (IOException e) { @@ -71,17 +75,13 @@ private String uploadImageToS3(MultipartFile image) throws IOException { metadata.setContentType("image/" + extension); metadata.setContentLength(bytes.length); - ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); - - try { + try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes)) { PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, s3FileName, byteArrayInputStream, metadata); amazonS3.putObject(putObjectRequest); + is.close(); } catch (Exception e) { throw new AmazonS3Exception("이미지 업로드에 실패했습니다."); - } finally { - byteArrayInputStream.close(); - is.close(); } return amazonS3.getUrl(bucketName, s3FileName).toString(); diff --git a/Server/src/main/java/JGS/CasperEvent/global/util/AESUtils.java b/Server/src/main/java/JGS/CasperEvent/global/util/AESUtils.java index e6bbec9d..6d91c92e 100644 --- a/Server/src/main/java/JGS/CasperEvent/global/util/AESUtils.java +++ b/Server/src/main/java/JGS/CasperEvent/global/util/AESUtils.java @@ -8,6 +8,9 @@ public class AESUtils { + private AESUtils() { + } + public static SecretKey stringToKey(String keyString) { byte[] decodedKey = keyString.getBytes(); return new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); diff --git a/Server/src/main/java/JGS/CasperEvent/global/util/Base62Utils.java b/Server/src/main/java/JGS/CasperEvent/global/util/Base62Utils.java index a32e7839..556adb2f 100644 --- a/Server/src/main/java/JGS/CasperEvent/global/util/Base62Utils.java +++ b/Server/src/main/java/JGS/CasperEvent/global/util/Base62Utils.java @@ -3,6 +3,9 @@ public class Base62Utils { private static final String BASE62_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + private Base62Utils() { + } + public static String encode(long number) { if (number == 0) return Character.toString(BASE62_CHARS.charAt(0)); diff --git a/Server/src/main/java/JGS/CasperEvent/global/util/RepositoryErrorHandler.java b/Server/src/main/java/JGS/CasperEvent/global/util/RepositoryErrorHandler.java index f4894091..6deb261d 100644 --- a/Server/src/main/java/JGS/CasperEvent/global/util/RepositoryErrorHandler.java +++ b/Server/src/main/java/JGS/CasperEvent/global/util/RepositoryErrorHandler.java @@ -5,6 +5,10 @@ import org.springframework.data.jpa.repository.JpaRepository; public class RepositoryErrorHandler { + + private RepositoryErrorHandler() { + } + public static T findByIdOrElseThrow(JpaRepository repository, ID id, CustomErrorCode customErrorCode) { return repository.findById(id).orElseThrow( () -> new EntityNotFoundException(customErrorCode.name()) diff --git a/Server/src/main/resources/application-prod.yml b/Server/src/main/resources/application-prod.yml index 4cb5173e..59c99538 100644 --- a/Server/src/main/resources/application-prod.yml +++ b/Server/src/main/resources/application-prod.yml @@ -31,6 +31,9 @@ spring: servlet: multipart: max-file-size: 10MB + jwt: + secretKey: + ${JWT_SECRET_KEY} client: diff --git a/Server/src/test/java/JGS/CasperEvent/domain/event/controller/adminController/AdminControllerTest.java b/Server/src/test/java/JGS/CasperEvent/domain/event/controller/adminController/AdminControllerTest.java index c9fbb6ef..d867cbbc 100644 --- a/Server/src/test/java/JGS/CasperEvent/domain/event/controller/adminController/AdminControllerTest.java +++ b/Server/src/test/java/JGS/CasperEvent/domain/event/controller/adminController/AdminControllerTest.java @@ -24,18 +24,22 @@ import JGS.CasperEvent.global.jwt.util.JwtProvider; import JGS.CasperEvent.global.response.ResponseDto; import com.fasterxml.jackson.databind.ObjectMapper; +import io.jsonwebtoken.security.Keys; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; +import java.security.Key; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; @@ -55,8 +59,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(value = AdminController.class) -@Import(JwtProvider.class) -public class AdminControllerTest { +class AdminControllerTest { @Autowired private MockMvc mockMvc; @Autowired @@ -100,6 +103,15 @@ public class AdminControllerTest { private RushEventParticipantResponseDto rushEventParticipantResponseDto; private RushEventParticipantsListResponseDto rushEventParticipantsListResponseDto; + @TestConfiguration + static class TestConfig{ + @Bean + public JwtProvider jwtProvider(){ + String secretKey = "mockKEymockKEymockKEymockKEymockKEymockKEymockKEy"; + byte[] secret = secretKey.getBytes(); + return new JwtProvider(Keys.hmacShaKeyFor(secret)); + } + } @BeforeEach void setUp() throws Exception { diff --git a/Server/src/test/java/JGS/CasperEvent/domain/event/controller/eventController/LotteryEventControllerTest.java b/Server/src/test/java/JGS/CasperEvent/domain/event/controller/eventController/LotteryEventControllerTest.java index 2fd50db1..3db38ba9 100644 --- a/Server/src/test/java/JGS/CasperEvent/domain/event/controller/eventController/LotteryEventControllerTest.java +++ b/Server/src/test/java/JGS/CasperEvent/domain/event/controller/eventController/LotteryEventControllerTest.java @@ -14,12 +14,15 @@ import JGS.CasperEvent.global.jwt.service.UserService; import JGS.CasperEvent.global.jwt.util.JwtProvider; import com.fasterxml.jackson.databind.ObjectMapper; +import io.jsonwebtoken.security.Keys; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; @@ -38,8 +41,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @WebMvcTest(LotteryEventController.class) -@Import(JwtProvider.class) -public class LotteryEventControllerTest { +class LotteryEventControllerTest { @Autowired private MockMvc mockMvc; @Autowired @@ -63,6 +65,16 @@ public class LotteryEventControllerTest { private LotteryParticipants lotteryParticipants; private LotteryEventResponseDto lotteryEventResponseDto; + @TestConfiguration + static class TestConfig{ + @Bean + public JwtProvider jwtProvider(){ + String secretKey = "mockKEymockKEymockKEymockKEymockKEymockKEymockKEy"; + byte[] secret = secretKey.getBytes(); + return new JwtProvider(Keys.hmacShaKeyFor(secret)); + } + } + @BeforeEach void setUp() throws Exception { this.phoneNumber = "010-0000-0000"; @@ -147,7 +159,7 @@ void postCasperBot() throws Exception { @Test @DisplayName("응모 여부 조회 성공 테스트") - void GetLotteryParticipantsSuccessTest() throws Exception { + void getLotteryParticipantsSuccessTest() throws Exception { //given given(lotteryEventService.getLotteryParticipant(user)) .willReturn(LotteryParticipantResponseDto.of(lotteryParticipants, casperBotResponse)); diff --git a/Server/src/test/java/JGS/CasperEvent/domain/event/controller/eventController/RushEventControllerTest.java b/Server/src/test/java/JGS/CasperEvent/domain/event/controller/eventController/RushEventControllerTest.java index 9d76cc87..70ef6324 100644 --- a/Server/src/test/java/JGS/CasperEvent/domain/event/controller/eventController/RushEventControllerTest.java +++ b/Server/src/test/java/JGS/CasperEvent/domain/event/controller/eventController/RushEventControllerTest.java @@ -9,12 +9,15 @@ import JGS.CasperEvent.global.error.exception.CustomException; import JGS.CasperEvent.global.jwt.service.UserService; import JGS.CasperEvent.global.jwt.util.JwtProvider; +import io.jsonwebtoken.security.Keys; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; @@ -32,8 +35,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(RushEventController.class) -@Import(JwtProvider.class) -public class RushEventControllerTest { +class RushEventControllerTest { @Autowired private MockMvc mockMvc; @@ -50,6 +52,16 @@ public class RushEventControllerTest { private String phoneNumber; private String accessToken; + @TestConfiguration + static class TestConfig{ + @Bean + public JwtProvider jwtProvider(){ + String secretKey = "mockKEymockKEymockKEymockKEymockKEymockKEymockKEy"; + byte[] secret = secretKey.getBytes(); + return new JwtProvider(Keys.hmacShaKeyFor(secret)); + } + } + @BeforeEach void setUp() throws Exception { this.phoneNumber = "010-0000-0000"; @@ -124,7 +136,7 @@ void setUp() throws Exception { @Test @DisplayName("메인화면 선착순 이벤트 전체 조회 API 테스트") - public void getRushEventListAndServerTime() throws Exception { + void getRushEventListAndServerTime() throws Exception { // when ResultActions perform = mockMvc.perform(get("/event/rush") .contentType(MediaType.APPLICATION_JSON)); @@ -144,10 +156,7 @@ public void getRushEventListAndServerTime() throws Exception { @Test @DisplayName("오늘의 선착순 이벤트 조회 API 성공 테스트") - public void getTodayEventTest() throws Exception { - // given - String accessToken = this.accessToken; - + void getTodayEventTest() throws Exception { // when ResultActions perform = mockMvc.perform(get("/event/rush/today") .header("Authorization", accessToken) @@ -165,8 +174,7 @@ public void getTodayEventTest() throws Exception { @Test @DisplayName("응모 성공 테스트 - Option ID 2") - public void applyRushEvent_Success() throws Exception { - String accessToken = this.accessToken; + void applyRushEvent_Success() throws Exception { int optionId = 2; ResultActions perform = mockMvc.perform(post("/event/rush/options/{optionId}/apply", optionId) @@ -174,13 +182,12 @@ public void applyRushEvent_Success() throws Exception { .contentType(MediaType.APPLICATION_JSON)); perform.andExpect(status().isNoContent()) // 204 No Content 응답 확인 - .andDo(print()); -} + .andDo(print()); + } @Test @DisplayName("응모 실패 테스트 - Option ID 1") - public void applyRushEvent_Failure_AlreadyApplied() throws Exception { - String accessToken = this.accessToken; + void applyRushEvent_Failure_AlreadyApplied() throws Exception { int optionId = 1; ResultActions perform = mockMvc.perform(post("/event/rush/options/{optionId}/apply", optionId) @@ -195,10 +202,8 @@ public void applyRushEvent_Failure_AlreadyApplied() throws Exception { @Test @DisplayName("선택지 결과 조회 성공 테스트") - public void getResultOptionTest() throws Exception { + void getResultOptionTest() throws Exception { // given - String accessToken = this.accessToken; - int optionId = 1; // when @@ -216,10 +221,7 @@ public void getResultOptionTest() throws Exception { @Test @DisplayName("밸런스 게임 비율 조회 API 테스트") - public void getRushEventRateTest() throws Exception { - // given - String accessToken = this.accessToken; - + void getRushEventRateTest() throws Exception { // when ResultActions perform = mockMvc.perform(get("/event/rush/balance") .header("Authorization", accessToken) @@ -235,10 +237,7 @@ public void getRushEventRateTest() throws Exception { @Test @DisplayName("밸런스 게임 최종 결과 조회 API 테스트") - public void getRushEventResultTest() throws Exception { - // given - String accessToken = this.accessToken; - + void getRushEventResultTest() throws Exception { // when ResultActions perform = mockMvc.perform(get("/event/rush/result") .header("Authorization", accessToken) diff --git a/Server/src/test/java/JGS/CasperEvent/domain/event/service/adminService/AdminServiceTest.java b/Server/src/test/java/JGS/CasperEvent/domain/event/service/adminService/AdminServiceTest.java index 56572143..dbce4256 100644 --- a/Server/src/test/java/JGS/CasperEvent/domain/event/service/adminService/AdminServiceTest.java +++ b/Server/src/test/java/JGS/CasperEvent/domain/event/service/adminService/AdminServiceTest.java @@ -114,6 +114,7 @@ void setUp() { user = spy(new BaseUser("010-0000-0000", Role.USER)); lenient().when(user.getCreatedAt()).thenReturn(LocalDateTime.of(2000, 9, 27, 0, 0, 0)); lenient().when(user.getUpdatedAt()).thenReturn(LocalDateTime.of(2000, 9, 27, 0, 0, 0)); + // 추첨 이벤트 생성 요청 DTO lotteryEventRequestDto = LotteryEventRequestDto.builder() .startDate(LocalDate.of(2000, 9, 27)) @@ -132,6 +133,7 @@ void setUp() { // 추첨 이벤트 참여자 엔티티 lotteryParticipants = spy(new LotteryParticipants(user)); + lenient().when(lotteryParticipants.getId()).thenReturn(1L); lenient().when(lotteryParticipants.getCreatedAt()).thenReturn(LocalDateTime.of(2000, 9, 27, 0, 0, 0)); lenient().when(lotteryParticipants.getUpdatedAt()).thenReturn(LocalDateTime.of(2000, 9, 27, 0, 0, 0)); @@ -236,25 +238,15 @@ void setUp() { build(); casperBot = - spy(new CasperBot(casperBotRequestDto, "010-0000-0000")); - lenient(). - when(casperBot.getCasperId()). - thenReturn(1L); - lenient(). - when(casperBot.getCreatedAt()). - thenReturn(LocalDateTime.of(2000, 9, 27, 0, 0, 0)); - lenient(). - when(casperBot.getUpdatedAt()). - thenReturn(LocalDateTime.of(2000, 9, 27, 0, 0, 0)); } @@ -270,7 +262,7 @@ void verifyAdminTest_Success() { given(adminRepository.findByIdAndPassword("adminId", "password")).willReturn(Optional.ofNullable(admin)); //when - Admin admin = adminService.verifyAdmin(adminRequestDto); + admin = adminService.verifyAdmin(adminRequestDto); //then assertThat(admin.getRole()).isEqualTo(Role.ADMIN); @@ -1021,14 +1013,21 @@ void pickLotteryEventWinners_Success() { List lotteryParticipantsList = new ArrayList<>(); for (int i = 0; i < 400; i++) { - BaseUser user = new BaseUser(String.format("010-0000-%04d", i), Role.USER); - LotteryParticipants lotteryParticipants = new LotteryParticipants(user); lotteryParticipantsList.add(lotteryParticipants); } given(lotteryEventRepository.findAll()).willReturn(lotteryEventList); given(lotteryWinnerRepository.count()).willReturn(0L); - given(lotteryParticipantsRepository.findAll()).willReturn(lotteryParticipantsList); + + List idAndAppliedCounts = new ArrayList<>(); + for (int i = 0; i < 400; i++) { + Object[] data = new Object[2]; + data[0] = (long) i; + data[1] = 2; + idAndAppliedCounts.add(data); + } + given(lotteryParticipantsRepository.findById(any())).willReturn(Optional.ofNullable(lotteryParticipants)); + given(lotteryParticipantsRepository.findIdAndAppliedCounts()).willReturn(idAndAppliedCounts); //when ResponseDto responseDto = adminService.pickLotteryEventWinners(); @@ -1049,7 +1048,13 @@ void pickLotteryEventWinners_Success_ParticipantsIsLessThanWinners() { given(lotteryEventRepository.findAll()).willReturn(lotteryEventList); given(lotteryWinnerRepository.count()).willReturn(0L); - given(lotteryParticipantsRepository.findAll()).willReturn(lotteryParticipantsList); + List idAndAppliedCounts = new ArrayList<>(); + Object[] data = new Object[2]; + data[0] = 1L; + data[1] = 2; + idAndAppliedCounts.add(data); + given(lotteryParticipantsRepository.findById(1L)).willReturn(Optional.ofNullable(lotteryParticipants)); + given(lotteryParticipantsRepository.findIdAndAppliedCounts()).willReturn(idAndAppliedCounts); //when ResponseDto responseDto = adminService.pickLotteryEventWinners(); diff --git a/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/LotteryEventServiceTest.java b/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/LotteryEventServiceTest.java index 3b223f38..589d67e6 100644 --- a/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/LotteryEventServiceTest.java +++ b/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/LotteryEventServiceTest.java @@ -64,10 +64,9 @@ class LotteryEventServiceTest { private LotteryParticipants lotteryParticipants; private CasperBotRequestDto casperBotRequestDto; private CasperBot casperBot; - private CasperBotResponseDto casperBotResponseDto; @BeforeEach - void setUp() throws Exception { + void setUp() { byte[] decodedKey = "I0EM1X1NeXKJv4Q+ifZllg==".getBytes(); SecretKey secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); ReflectionTestUtils.setField(lotteryEventService, "secretKey", secretKey); @@ -98,9 +97,6 @@ void setUp() throws Exception { // 캐스퍼 봇 엔티티 casperBot = new CasperBot(casperBotRequestDto, "010-0000-0000"); - - // 캐스퍼 봇 응답 DTO - casperBotResponseDto = CasperBotResponseDto.of(casperBot); } @Test @@ -135,7 +131,7 @@ void getLotteryParticipants_Success() { //when LotteryParticipantResponseDto lotteryParticipantResponseDto = lotteryEventService.getLotteryParticipant(user); - CasperBotResponseDto casperBot = lotteryParticipantResponseDto.casperBot(); + CasperBotResponseDto casperBotResponseDto = lotteryParticipantResponseDto.casperBot(); //then assertThat(lotteryParticipantResponseDto).isNotNull(); @@ -144,13 +140,13 @@ void getLotteryParticipants_Success() { assertThat(lotteryParticipantResponseDto.appliedCount()).isEqualTo(1); assertThat(lotteryParticipantResponseDto.casperBot()).isNotNull(); - assertThat(casperBot.eyeShape()).isEqualTo(0); - assertThat(casperBot.eyePosition()).isEqualTo(0); - assertThat(casperBot.mouthShape()).isEqualTo(0); - assertThat(casperBot.color()).isEqualTo(0); - assertThat(casperBot.sticker()).isEqualTo(0); - assertThat(casperBot.name()).isEqualTo("name"); - assertThat(casperBot.expectation()).isEqualTo("expectation"); + assertThat(casperBotResponseDto.eyeShape()).isEqualTo(0); + assertThat(casperBotResponseDto.eyePosition()).isEqualTo(0); + assertThat(casperBotResponseDto.mouthShape()).isEqualTo(0); + assertThat(casperBotResponseDto.color()).isEqualTo(0); + assertThat(casperBotResponseDto.sticker()).isEqualTo(0); + assertThat(casperBotResponseDto.name()).isEqualTo("name"); + assertThat(casperBotResponseDto.expectation()).isEqualTo("expectation"); } @Test diff --git a/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventServiceTest.java b/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventServiceTest.java index 2411c420..b4424800 100644 --- a/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventServiceTest.java +++ b/Server/src/test/java/JGS/CasperEvent/domain/event/service/eventService/RushEventServiceTest.java @@ -63,9 +63,6 @@ void getAllRushEvents() { new RushEvent() ); - List mainRushEventResponseDtoList = rushEventList.stream() - .map(MainRushEventResponseDto::of).toList(); - given(rushEventCacheService.getTodayEvent(LocalDate.now())).willReturn(todayEvent); given(rushEventRepository.findAll()).willReturn(rushEventList); @@ -75,7 +72,7 @@ void getAllRushEvents() { // then assertNotNull(allRushEvents); assertEquals(2, allRushEvents.getEvents().size()); - assertEquals(allRushEvents.getTodayEventId(), 1); + assertEquals(1, allRushEvents.getTodayEventId()); } @Test @@ -496,18 +493,6 @@ void getRushEventOptionResult2() { void getRushEventOptionResult3() { // given int optionId = 3; - RushEventResponseDto todayEvent = new RushEventResponseDto( - 1L, - LocalDateTime.now(), - LocalDateTime.now().plusDays(1), - 315, - "image-url", - "prize-description", - Set.of( - new RushEventOptionResponseDto(1L, "leftMainText", "leftSubText", "resultMainText", "resultSubText", "leftImageUrl", Position.LEFT, LocalDateTime.now(), LocalDateTime.now()), - new RushEventOptionResponseDto(2L, "rightMainText", "rightSubText", "resultMainText", "resultSubText", "rightImageUrl", Position.RIGHT, LocalDateTime.now(), LocalDateTime.now()) - ) - ); // when & then CustomException exception = assertThrows(CustomException.class, () -> diff --git a/Server/src/test/java/JGS/CasperEvent/domain/url/controller/UrlControllerTest.java b/Server/src/test/java/JGS/CasperEvent/domain/url/controller/UrlControllerTest.java index 4be90baf..c783be1e 100644 --- a/Server/src/test/java/JGS/CasperEvent/domain/url/controller/UrlControllerTest.java +++ b/Server/src/test/java/JGS/CasperEvent/domain/url/controller/UrlControllerTest.java @@ -1,6 +1,5 @@ package JGS.CasperEvent.domain.url.controller; -import JGS.CasperEvent.domain.event.dto.RequestDto.AdminRequestDto; import JGS.CasperEvent.domain.event.service.adminService.AdminService; import JGS.CasperEvent.domain.url.dto.ShortenUrlResponseDto; import JGS.CasperEvent.domain.url.service.UrlService; @@ -8,19 +7,20 @@ import JGS.CasperEvent.global.enums.Role; import JGS.CasperEvent.global.jwt.service.UserService; import JGS.CasperEvent.global.jwt.util.JwtProvider; -import JGS.CasperEvent.global.response.ResponseDto; +import io.jsonwebtoken.security.Keys; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; -import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.http.MediaType.APPLICATION_JSON; @@ -31,7 +31,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(value = UrlController.class) -@Import(JwtProvider.class) class UrlControllerTest { @Autowired private MockMvc mockMvc; @@ -55,6 +54,16 @@ void setUp() throws Exception { accessToken = getToken(phoneNumber); } + @TestConfiguration + static class TestConfig{ + @Bean + public JwtProvider jwtProvider(){ + String secretKey = "mockKEymockKEymockKEymockKEymockKEymockKEymockKEy"; + byte[] secret = secretKey.getBytes(); + return new JwtProvider(Keys.hmacShaKeyFor(secret)); + } + } + @Test @DisplayName("공유 링크 생성 테스트 - 성공") void generateShortUrlTest_Success() throws Exception { diff --git a/Server/src/test/java/JGS/CasperEvent/domain/url/service/UrlServiceTest.java b/Server/src/test/java/JGS/CasperEvent/domain/url/service/UrlServiceTest.java index f96a330c..058ab581 100644 --- a/Server/src/test/java/JGS/CasperEvent/domain/url/service/UrlServiceTest.java +++ b/Server/src/test/java/JGS/CasperEvent/domain/url/service/UrlServiceTest.java @@ -5,7 +5,9 @@ import JGS.CasperEvent.domain.url.repository.UrlRepository; import JGS.CasperEvent.global.entity.BaseUser; import JGS.CasperEvent.global.enums.Role; +import JGS.CasperEvent.global.jwt.util.JwtProvider; import JGS.CasperEvent.global.util.AESUtils; +import io.jsonwebtoken.security.Keys; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -13,6 +15,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; import org.springframework.test.util.ReflectionTestUtils; import javax.crypto.BadPaddingException; @@ -52,6 +56,16 @@ void setUp(){ } + @TestConfiguration + static class TestConfig{ + @Bean + public JwtProvider jwtProvider(){ + String secretKey = "mockKEymockKEymockKEymockKEymockKEymockKEymockKEy"; + byte[] secret = secretKey.getBytes(); + return new JwtProvider(Keys.hmacShaKeyFor(secret)); + } + } + @Test @DisplayName("단축 url 생성 테스트 - 성공") void generateShortUrlTest_Success() throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {