From 4f048d12e06e1c195c94b3e64edd5cbb12310500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 00:02:48 +0900 Subject: [PATCH 01/17] =?UTF-8?q?[feat]=20=EA=B4=80=EB=A0=A8=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/konkuk/thip/common/exception/code/ErrorCode.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java index 289a5d5ce..bd548538a 100644 --- a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java +++ b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java @@ -66,7 +66,9 @@ public enum ErrorCode implements ResponseCode { * 100000 : room error */ ROOM_NOT_FOUND(HttpStatus.NOT_FOUND, 100000, "존재하지 않는 ROOM 입니다."), - + ROOM_PASSWORD_MISMATCH(HttpStatus.BAD_REQUEST, 100001, "비밀번호가 일치하지 않습니다."), + ROOM_PASSWORD_NOT_REQUIRED(HttpStatus.BAD_REQUEST, 100002, "공개방은 비밀번호가 필요하지 않습니다."), + ROOM_RECRUITMENT_PERIOD_EXPIRED(HttpStatus.BAD_REQUEST, 100003, "모집기간이 만료된 방입니다."), /** * 110000 : vote error */ From 1ce9609435205ad116c9f3e0da38b149c34cc673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 00:03:01 +0900 Subject: [PATCH 02/17] =?UTF-8?q?[feat]=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=EA=B4=80=EB=A0=A8=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/konkuk/thip/room/domain/Room.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/main/java/konkuk/thip/room/domain/Room.java b/src/main/java/konkuk/thip/room/domain/Room.java index f4bb359b1..5aa6f7ebb 100644 --- a/src/main/java/konkuk/thip/room/domain/Room.java +++ b/src/main/java/konkuk/thip/room/domain/Room.java @@ -2,11 +2,15 @@ import konkuk.thip.common.entity.BaseDomainEntity; import konkuk.thip.common.entity.StatusType; +import konkuk.thip.common.exception.BusinessException; +import konkuk.thip.common.exception.code.ErrorCode; import lombok.Getter; import lombok.experimental.SuperBuilder; import java.time.LocalDate; +import static konkuk.thip.common.exception.code.ErrorCode.*; + @Getter @SuperBuilder public class Room extends BaseDomainEntity { @@ -40,4 +44,33 @@ public boolean isExpired() { public void updateRoomPercentage(double roomPercentage) { this.roomPercentage = roomPercentage; } + + public void verifyPassword(String password) { + + // 모집기간 만료 체크 + LocalDate deadline = this.startDate.minusDays(1); + if (isRecruitmentPeriodExpired()) { + String message = String.format("모집기간(%s까지)이 만료된 방에는 참여할 수 없습니다.", deadline); + throw new BusinessException( + ErrorCode.ROOM_RECRUITMENT_PERIOD_EXPIRED, new IllegalArgumentException(message) + ); + } + + // 공개방일 경우 비밀번호 입력 요청 예외 처리 + if (this.isPublic()) { + throw new BusinessException(ROOM_PASSWORD_NOT_REQUIRED); + } + + //비밀번호 해싱 로직 추가되면 해싱 해제 하고 검증하는 로직추가 + if (this.password == null || !this.password.toString().equals(password)) { + throw new BusinessException(ROOM_PASSWORD_MISMATCH); + } + } + + public boolean isRecruitmentPeriodExpired() { + LocalDate today = LocalDate.now(); + // 모집 마감일: startDate.minusDays(1) + return today.isAfter(this.startDate.minusDays(1)); + } + } From eaed72a2dc3f736178c8d2114d044ef1b44a6eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 00:03:12 +0900 Subject: [PATCH 03/17] =?UTF-8?q?[feat]=20=EB=B9=84=EA=B3=B5=EA=B0=9C=20?= =?UTF-8?q?=EB=B0=A9=20=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=EA=B2=80=EC=A6=9D=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=EC=9E=91=EC=84=B1=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/in/web/RoomQueryController.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java b/src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java index 6c9e1216c..a07e0974d 100644 --- a/src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java +++ b/src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java @@ -1,10 +1,26 @@ package konkuk.thip.room.adapter.in.web; +import jakarta.validation.Valid; +import konkuk.thip.common.dto.BaseResponse; +import konkuk.thip.common.security.annotation.UserId; +import konkuk.thip.room.adapter.in.web.request.RoomVerifyPasswordRequest; +import konkuk.thip.room.application.port.in.RoomVerifyPasswordUseCase; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequiredArgsConstructor public class RoomQueryController { + private final RoomVerifyPasswordUseCase roomVerifyPasswordUseCase; + + //비공개 방 비밀번호 입력 검증 + @PostMapping("/rooms/{roomId}/password") + public BaseResponse verifyRoomPassword(@UserId final Long userId, + @PathVariable("roomId") final Long roomId, + @Valid @RequestBody final RoomVerifyPasswordRequest roomVerifyPasswordRequest + ) { + return BaseResponse.ok(roomVerifyPasswordUseCase.verifyRoomPassword(roomVerifyPasswordRequest.toQuery(userId,roomId))); + } + } From b8313b44a2717407884a124b8d2be30cf9d39a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 00:03:38 +0900 Subject: [PATCH 04/17] =?UTF-8?q?[feat]=20=EC=BF=BC=EB=A6=AC=20dto=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/port/in/dto/RoomVerifyPasswordQuery.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/konkuk/thip/room/application/port/in/dto/RoomVerifyPasswordQuery.java diff --git a/src/main/java/konkuk/thip/room/application/port/in/dto/RoomVerifyPasswordQuery.java b/src/main/java/konkuk/thip/room/application/port/in/dto/RoomVerifyPasswordQuery.java new file mode 100644 index 000000000..fa1129256 --- /dev/null +++ b/src/main/java/konkuk/thip/room/application/port/in/dto/RoomVerifyPasswordQuery.java @@ -0,0 +1,8 @@ +package konkuk.thip.room.application.port.in.dto; + +public record RoomVerifyPasswordQuery( + Long userId, + Long roomId, + String password +) { +} From 6677793a66a8a1e44b3cb1517a5d826c0468eb54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 00:03:46 +0900 Subject: [PATCH 05/17] =?UTF-8?q?[feat]=20request=20dto=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/RoomVerifyPasswordRequest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/konkuk/thip/room/adapter/in/web/request/RoomVerifyPasswordRequest.java diff --git a/src/main/java/konkuk/thip/room/adapter/in/web/request/RoomVerifyPasswordRequest.java b/src/main/java/konkuk/thip/room/adapter/in/web/request/RoomVerifyPasswordRequest.java new file mode 100644 index 000000000..7918d9ad1 --- /dev/null +++ b/src/main/java/konkuk/thip/room/adapter/in/web/request/RoomVerifyPasswordRequest.java @@ -0,0 +1,19 @@ +package konkuk.thip.room.adapter.in.web.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import konkuk.thip.room.application.port.in.dto.RoomVerifyPasswordQuery; + +public record RoomVerifyPasswordRequest( + + @NotBlank(message = "비밀번호는 필수입니다.") + @Pattern(regexp = "\\d{4}", message = "비밀번호는 숫자 4자리여야 합니다.") + String password +) { + public RoomVerifyPasswordQuery toQuery(Long userId,Long roomId) { + return new RoomVerifyPasswordQuery( + userId, + roomId, + password); + } +} From 8ed9260216072d56c40da9ef42ad1636550657b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 00:04:03 +0900 Subject: [PATCH 06/17] =?UTF-8?q?[feat]=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=9E=91=EC=84=B1=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/RoomVerifyPasswordService.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/java/konkuk/thip/room/application/service/RoomVerifyPasswordService.java diff --git a/src/main/java/konkuk/thip/room/application/service/RoomVerifyPasswordService.java b/src/main/java/konkuk/thip/room/application/service/RoomVerifyPasswordService.java new file mode 100644 index 000000000..419d33df1 --- /dev/null +++ b/src/main/java/konkuk/thip/room/application/service/RoomVerifyPasswordService.java @@ -0,0 +1,33 @@ +package konkuk.thip.room.application.service; + +import konkuk.thip.room.application.port.in.RoomVerifyPasswordUseCase; +import konkuk.thip.room.application.port.in.dto.RoomVerifyPasswordQuery; +import konkuk.thip.room.application.port.out.RoomCommandPort; +import konkuk.thip.room.domain.Room; +import konkuk.thip.user.application.port.out.UserCommandPort; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class RoomVerifyPasswordService implements RoomVerifyPasswordUseCase { + + private final UserCommandPort userCommandPort; + private final RoomCommandPort roomCommandPort; + + @Override + public Void verifyRoomPassword(RoomVerifyPasswordQuery query) { + + //유저 검증 + userCommandPort.findById(query.userId()); + + //방 검증 + Room room = roomCommandPort.findById(query.roomId()); + + //도메인에서 비밀번호 검증 로직 수행 + room.verifyPassword(query.password()); + return null; + } +} From faac3a442e9fab029f29bfe3c79ee401590e4f77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 00:04:14 +0900 Subject: [PATCH 07/17] =?UTF-8?q?[feat]=20=EC=9C=A0=EC=A6=88=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=EC=9E=91=EC=84=B1=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../konkuk/thip/room/application/port/in/DummyUseCase.java | 5 ----- .../application/port/in/RoomVerifyPasswordUseCase.java | 7 +++++++ 2 files changed, 7 insertions(+), 5 deletions(-) delete mode 100644 src/main/java/konkuk/thip/room/application/port/in/DummyUseCase.java create mode 100644 src/main/java/konkuk/thip/room/application/port/in/RoomVerifyPasswordUseCase.java diff --git a/src/main/java/konkuk/thip/room/application/port/in/DummyUseCase.java b/src/main/java/konkuk/thip/room/application/port/in/DummyUseCase.java deleted file mode 100644 index 62b144647..000000000 --- a/src/main/java/konkuk/thip/room/application/port/in/DummyUseCase.java +++ /dev/null @@ -1,5 +0,0 @@ -package konkuk.thip.room.application.port.in; - -public interface DummyUseCase { - -} diff --git a/src/main/java/konkuk/thip/room/application/port/in/RoomVerifyPasswordUseCase.java b/src/main/java/konkuk/thip/room/application/port/in/RoomVerifyPasswordUseCase.java new file mode 100644 index 000000000..975f4d00f --- /dev/null +++ b/src/main/java/konkuk/thip/room/application/port/in/RoomVerifyPasswordUseCase.java @@ -0,0 +1,7 @@ +package konkuk.thip.room.application.port.in; + +import konkuk.thip.room.application.port.in.dto.RoomVerifyPasswordQuery; + +public interface RoomVerifyPasswordUseCase { + Void verifyRoomPassword(RoomVerifyPasswordQuery query); +} From 89973ee7e306b128c81c8688f792e4d5acc5208c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 00:04:29 +0900 Subject: [PATCH 08/17] =?UTF-8?q?[test]=20=ED=86=B5=ED=95=A9=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1=20(#5?= =?UTF-8?q?4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/web/RoomVerifyPasswordAPITest.java | 231 ++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordAPITest.java diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordAPITest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordAPITest.java new file mode 100644 index 000000000..88039e804 --- /dev/null +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordAPITest.java @@ -0,0 +1,231 @@ +package konkuk.thip.room.adapter.in.web; + +import com.fasterxml.jackson.databind.ObjectMapper; +import konkuk.thip.book.adapter.out.jpa.BookJpaEntity; +import konkuk.thip.book.adapter.out.persistence.BookJpaRepository; +import konkuk.thip.room.adapter.in.web.request.RoomVerifyPasswordRequest; +import konkuk.thip.room.adapter.out.jpa.CategoryJpaEntity; +import konkuk.thip.room.adapter.out.persistence.CategoryJpaRepository; +import konkuk.thip.user.adapter.out.jpa.AliasJpaEntity; +import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; +import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.adapter.out.persistence.AliasJpaRepository; +import konkuk.thip.user.adapter.out.persistence.UserJpaRepository; +import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; +import konkuk.thip.room.adapter.out.persistence.RoomJpaRepository; +import org.junit.jupiter.api.AfterEach; +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.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; + + +import java.time.LocalDate; + +import static konkuk.thip.common.exception.code.ErrorCode.*; +import static org.hamcrest.Matchers.containsString; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@SpringBootTest +@ActiveProfiles("test") +@AutoConfigureMockMvc(addFilters = false) +@DisplayName("[통합] 비공개 방 비밀번호 입력 검증 api 통합 테스트") +class RoomVerifyPasswordAPITest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private UserJpaRepository userJpaRepository; + + @Autowired + private AliasJpaRepository aliasJpaRepository; + + @Autowired + private BookJpaRepository bookJpaRepository; + + @Autowired + private CategoryJpaRepository categoryJpaRepository; + + @Autowired + private RoomJpaRepository roomJpaRepository; + + @Autowired + private ObjectMapper objectMapper; + + private Long userId; + private Long privateRoomId; + private Long publicRoomId; + + @BeforeEach + void setUp() { + + AliasJpaEntity alias = aliasJpaRepository.save(AliasJpaEntity.builder() + .value("책벌레") + .color("blue") + .imageUrl("http://image.url") + .build()); + + UserJpaEntity user = userJpaRepository.save(UserJpaEntity.builder() + .oauth2Id("kakao_432708231") + .nickname("User1") + .imageUrl("https://avatar1.jpg") + .role(UserRole.USER) + .aliasForUserJpaEntity(alias) + .build()); + + BookJpaEntity book = bookJpaRepository.save(BookJpaEntity.builder() + .isbn("1234567890123") + .title("테스트책") + .imageUrl("https://image.url") + .authorName("저자") + .publisher("출판사") + .description("설명") + .bestSeller(false) + .build()); + userId = user.getUserId(); + + CategoryJpaEntity categoryJpaEntity = categoryJpaRepository.save(CategoryJpaEntity.builder() + .value("소설") + .aliasForCategoryJpaEntity(alias) + .build()); + + // 비공개 방 저장 (비밀번호: 1234) + RoomJpaEntity privateRoom = roomJpaRepository.save( + RoomJpaEntity.builder() + .bookJpaEntity(book) + .categoryJpaEntity(categoryJpaEntity) + .title("비공개방") + .description("비공개방입니다") + .isPublic(false) + .password(1234) + .startDate(LocalDate.now().plusDays(1)) + .endDate(LocalDate.now().plusDays(5)) + .recruitCount(3) + .build() + ); + privateRoomId = privateRoom.getRoomId(); + + // 공개 방 저장 + RoomJpaEntity publicRoom = roomJpaRepository.save( + RoomJpaEntity.builder() + .bookJpaEntity(book) + .categoryJpaEntity(categoryJpaEntity) + .title("공개방") + .description("공개방입니다") + .isPublic(true) + .password(null) + .startDate(LocalDate.now().plusDays(1)) + .endDate(LocalDate.now().plusDays(5)) + .recruitCount(3) + .build() + ); + publicRoomId = publicRoom.getRoomId(); + } + + @AfterEach + void tearDown() { + roomJpaRepository.deleteAll(); + bookJpaRepository.deleteAll(); + userJpaRepository.deleteAll(); + categoryJpaRepository.deleteAll(); + aliasJpaRepository.deleteAll(); + } + + @Test + @DisplayName("모집기간이 만료되지 않은 비공개 방의 비밀번호 입력 검증에 [성공]한다") + void verifyRoomPassword_success() throws Exception { + + // given + RoomVerifyPasswordRequest request = new RoomVerifyPasswordRequest("1234"); + + //when & then + mockMvc.perform(post("/rooms/{roomId}/password", privateRoomId) + .requestAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + ) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.isSuccess").value(true)); + } + + @Test + @DisplayName("모집기간이 만료되지 않은 비공개 방의 비밀번호 입력 검증 [실패]시 400 Bad Request 반환") + void verifyRoomPassword_mismatch() throws Exception { + + // given + RoomVerifyPasswordRequest request = new RoomVerifyPasswordRequest("9999"); + + //when & then + mockMvc.perform(post("/rooms/{roomId}/password", privateRoomId) + .requestAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + ) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.isSuccess").value(false)) + .andExpect(jsonPath("$.code").value(ROOM_PASSWORD_MISMATCH.getCode())) + .andExpect(jsonPath("$.message" , containsString("비밀번호가 일치하지 않습니다."))); + } + + @Test + @DisplayName("[모집기간이 만료된] 비공개 방에 비밀번호 입력 검증 시 400 Bad Request 반환") + void verifyRoomPassword_recruitmentPeriodExpired() throws Exception { + + // given + // 모집기간: startDate.minusDays(1) 이전이면 만료 + // startDate를 오늘로 설정해 모집기간이 이미 지난 상태로 저장 + RoomJpaEntity expiredRoom = roomJpaRepository.save( + RoomJpaEntity.builder() + .bookJpaEntity(bookJpaRepository.findAll().get(0)) + .categoryJpaEntity(categoryJpaRepository.findAll().get(0)) + .title("모집만료방") + .description("모집기간이 만료된 방입니다") + .isPublic(false) + .password(1234) + .startDate(LocalDate.now()) // 오늘 시작이므로 모집기간은 어제까지 + .endDate(LocalDate.now().plusDays(5)) + .recruitCount(3) + .build() + ); + Long expiredRoomId = expiredRoom.getRoomId(); + + RoomVerifyPasswordRequest request = new RoomVerifyPasswordRequest("1234"); + + //when & then + mockMvc.perform(post("/rooms/{roomId}/password", expiredRoomId) + .requestAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + ) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.isSuccess").value(false)) + .andExpect(jsonPath("$.code").value(ROOM_RECRUITMENT_PERIOD_EXPIRED.getCode())) + .andExpect(jsonPath("$.message", containsString(("모집기간이 만료된 방입니다.")))); + } + + @Test + @DisplayName("[공개방]에 비밀번호 입력 검증 시 400 Bad Request 반환") + void verifyRoomPassword_publicRoom() throws Exception { + + // given + RoomVerifyPasswordRequest request = new RoomVerifyPasswordRequest("1234"); + + //when & then + mockMvc.perform(post("/rooms/{roomId}/password", publicRoomId) + .requestAttr("userId", userId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + ) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.isSuccess").value(false)) + .andExpect(jsonPath("$.code").value(ROOM_PASSWORD_NOT_REQUIRED.getCode())) + .andExpect(jsonPath("$.message", containsString("공개방은 비밀번호가 필요하지 않습니다"))); + } +} \ No newline at end of file From d0a53610d7efc814c1c5ca45671ec94b98e0c0eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 00:04:50 +0900 Subject: [PATCH 09/17] =?UTF-8?q?[test]=20=EB=8B=A8=EC=9C=84=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1=20?= =?UTF-8?q?(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/RoomVerifyPasswordControllerTest.java | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordControllerTest.java diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordControllerTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordControllerTest.java new file mode 100644 index 000000000..4e996f0b1 --- /dev/null +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordControllerTest.java @@ -0,0 +1,96 @@ +package konkuk.thip.room.adapter.in.web; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.DisplayName; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.HashMap; +import java.util.Map; + +import static konkuk.thip.common.exception.code.ErrorCode.API_INVALID_PARAM; +import static org.hamcrest.Matchers.containsString; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +@SpringBootTest +@ActiveProfiles("test") +@AutoConfigureMockMvc(addFilters = false) +@DisplayName("[단위] 비공개 방 비밀번호 입력 api controller 단위 테스트") +class RoomVerifyPasswordControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + private Map buildValidRequest() { + Map request = new HashMap<>(); + request.put("userId", 1L); + request.put("roomId", 1L); + request.put("password", "1234"); + return request; + } + + private void assertBad(Map req, String msg) throws Exception { + mockMvc.perform(post("/rooms/{roomId}/password", req.get("roomId")) + .requestAttr("userId", req.get("userId")) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(req))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.code").value(API_INVALID_PARAM.getCode())) + .andExpect(jsonPath("$.message", containsString(msg))); + } + + @Nested + @DisplayName("비밀번호 검증") + class PasswordValidation { + @Test + @DisplayName("비밀번호가 4자리 숫자가 아닐 때 400 error") + void invalid_password() throws Exception { + Map req = buildValidRequest(); + req.put("password", "12ab"); + assertBad(req, "비밀번호는 숫자 4자리여야 합니다."); + } + + @Test + @DisplayName("비밀번호가 4자리가 아닐 때 400 error") + void short_password() throws Exception { + Map req = buildValidRequest(); + req.put("password", "123"); + assertBad(req, "비밀번호는 숫자 4자리여야 합니다."); + } + + @Test + @DisplayName("비밀번호가 빈 값일 때 400 error") + void blank_password() throws Exception { + Map req = buildValidRequest(); + req.put("password", ""); + assertBad(req, "파라미터 값 중 유효하지 않은 값이 있습니다. 비밀번호는 필수입니다."); } + } + + @Nested + @DisplayName("roomId 검증") + class RoomIdValidation { + @Test + @DisplayName("roomId가 없을 때 400 error") + void missing_roomId() throws Exception { + Map req = buildValidRequest(); + req.remove("roomId"); + mockMvc.perform(post("/rooms//password") + .requestAttr("userId", req.get("userId")) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(req))) + .andExpect(status().is4xxClientError()); + } + } +} From 77453012cd51ed64b359d5a272fbfa5dcf84d4f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 00:05:04 +0900 Subject: [PATCH 10/17] =?UTF-8?q?[remove]=20=EB=8D=94=EB=AF=B8=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=82=AD=EC=A0=9C=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../room/adapter/in/web/request/DummyRequest.java | 7 ------- .../thip/room/application/port/in/dto/DummyQuery.java | 9 --------- .../thip/room/application/service/RoomService.java | 11 ----------- 3 files changed, 27 deletions(-) delete mode 100644 src/main/java/konkuk/thip/room/adapter/in/web/request/DummyRequest.java delete mode 100644 src/main/java/konkuk/thip/room/application/port/in/dto/DummyQuery.java delete mode 100644 src/main/java/konkuk/thip/room/application/service/RoomService.java diff --git a/src/main/java/konkuk/thip/room/adapter/in/web/request/DummyRequest.java b/src/main/java/konkuk/thip/room/adapter/in/web/request/DummyRequest.java deleted file mode 100644 index 2e023b5fa..000000000 --- a/src/main/java/konkuk/thip/room/adapter/in/web/request/DummyRequest.java +++ /dev/null @@ -1,7 +0,0 @@ -package konkuk.thip.room.adapter.in.web.request; - -import lombok.Getter; - -@Getter -public class DummyRequest { -} diff --git a/src/main/java/konkuk/thip/room/application/port/in/dto/DummyQuery.java b/src/main/java/konkuk/thip/room/application/port/in/dto/DummyQuery.java deleted file mode 100644 index f60120b60..000000000 --- a/src/main/java/konkuk/thip/room/application/port/in/dto/DummyQuery.java +++ /dev/null @@ -1,9 +0,0 @@ -package konkuk.thip.room.application.port.in.dto; - -import lombok.Builder; -import lombok.Getter; - -@Builder -@Getter -public class DummyQuery { -} diff --git a/src/main/java/konkuk/thip/room/application/service/RoomService.java b/src/main/java/konkuk/thip/room/application/service/RoomService.java deleted file mode 100644 index d0621a5c5..000000000 --- a/src/main/java/konkuk/thip/room/application/service/RoomService.java +++ /dev/null @@ -1,11 +0,0 @@ -package konkuk.thip.room.application.service; - -import konkuk.thip.room.application.port.in.DummyUseCase; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class RoomService implements DummyUseCase { - -} From dc75c47cc3b919390fe0d72aa5bb2b39c82b2bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 01:03:11 +0900 Subject: [PATCH 11/17] =?UTF-8?q?[fix]=20=ED=95=B4=EC=8B=B1=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=B9=BC=EB=9F=BC=EC=A0=9C=EC=95=BD=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java b/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java index 5426f28e2..9deb47ef8 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java +++ b/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java @@ -28,7 +28,6 @@ public class RoomJpaEntity extends BaseJpaEntity { @Column(name = "is_public", nullable = false) private boolean isPublic; - @Column(length = 4) private String password; @Builder.Default From 1084ac6e72fc5665ad5ac51d4a13abeebc930a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 01:03:28 +0900 Subject: [PATCH 12/17] =?UTF-8?q?[feat]=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/konkuk/thip/room/domain/Room.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/konkuk/thip/room/domain/Room.java b/src/main/java/konkuk/thip/room/domain/Room.java index 6392fe1e3..503bdf83c 100644 --- a/src/main/java/konkuk/thip/room/domain/Room.java +++ b/src/main/java/konkuk/thip/room/domain/Room.java @@ -12,7 +12,7 @@ import java.time.LocalDate; -import static konkuk.thip.common.exception.code.ErrorCode.INVALID_ROOM_CREATE; +import static konkuk.thip.common.exception.code.ErrorCode.*; @Getter @SuperBuilder @@ -114,7 +114,7 @@ public boolean matchesPassword(String rawPassword) { return PASSWORD_ENCODER.matches(rawPassword, this.hashedPassword); } - public void verifyPassword(String password) { + public void verifyPassword(String rawPassword) { // 모집기간 만료 체크 LocalDate deadline = this.startDate.minusDays(1); @@ -130,8 +130,8 @@ ErrorCode.ROOM_RECRUITMENT_PERIOD_EXPIRED, new IllegalArgumentException(message) throw new BusinessException(ROOM_PASSWORD_NOT_REQUIRED); } - //비밀번호 해싱 로직 추가되면 해싱 해제 하고 검증하는 로직추가 - if (this.password == null || !this.password.toString().equals(password)) { + //비밀번호 검증 + if (!matchesPassword(rawPassword)) { throw new BusinessException(ROOM_PASSWORD_MISMATCH); } } From c6eeb851296d4840119f464444893cac3ae01006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 01:15:14 +0900 Subject: [PATCH 13/17] =?UTF-8?q?[test]=20Book=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=8B=A8=EC=9C=84=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/web/RoomVerifyPasswordAPITest.java | 8 +- .../konkuk/thip/room/domain/RoomTest.java | 89 ++++++++++++++++++- 2 files changed, 94 insertions(+), 3 deletions(-) diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordAPITest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordAPITest.java index 88039e804..00147c327 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordAPITest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordAPITest.java @@ -21,6 +21,8 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; @@ -59,6 +61,8 @@ class RoomVerifyPasswordAPITest { @Autowired private ObjectMapper objectMapper; + private static final PasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder(); + private Long userId; private Long privateRoomId; private Long publicRoomId; @@ -104,7 +108,7 @@ void setUp() { .title("비공개방") .description("비공개방입니다") .isPublic(false) - .password(1234) + .password(PASSWORD_ENCODER.encode("1234")) .startDate(LocalDate.now().plusDays(1)) .endDate(LocalDate.now().plusDays(5)) .recruitCount(3) @@ -188,7 +192,7 @@ void verifyRoomPassword_recruitmentPeriodExpired() throws Exception { .title("모집만료방") .description("모집기간이 만료된 방입니다") .isPublic(false) - .password(1234) + .password(PASSWORD_ENCODER.encode("1234")) .startDate(LocalDate.now()) // 오늘 시작이므로 모집기간은 어제까지 .endDate(LocalDate.now().plusDays(5)) .recruitCount(3) diff --git a/src/test/java/konkuk/thip/room/domain/RoomTest.java b/src/test/java/konkuk/thip/room/domain/RoomTest.java index fd11dd10e..756e507ab 100644 --- a/src/test/java/konkuk/thip/room/domain/RoomTest.java +++ b/src/test/java/konkuk/thip/room/domain/RoomTest.java @@ -1,6 +1,8 @@ package konkuk.thip.room.domain; +import konkuk.thip.common.exception.BusinessException; import konkuk.thip.common.exception.InvalidStateException; +import konkuk.thip.common.exception.code.ErrorCode; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -9,8 +11,9 @@ import java.time.LocalDate; import static org.junit.jupiter.api.Assertions.*; +import static org.springframework.test.util.ReflectionTestUtils.setField; -@DisplayName("Room 단위 테스트") +@DisplayName("[단위] Room 단위 테스트") class RoomTest { private static final PasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder(); @@ -152,4 +155,88 @@ void matchesPassword_no_password() { ); assertFalse(room.matchesPassword("0000")); } + + @Test + @DisplayName("isRecruitmentPeriodExpired: 모집기간이 만료되지 않은 경우 false 반환") + void isRecruitmentPeriodExpired_not_expired() { + Room room = Room.withoutId( + "제목", "설명", false, "1234", + LocalDate.now().plusDays(3), LocalDate.now().plusDays(10), 5, 123L, 456L + ); + assertFalse(room.isRecruitmentPeriodExpired()); + } + + @Test + @DisplayName("isRecruitmentPeriodExpired: 모집기간이 오늘이 마감일인 경우 false 반환") + void isRecruitmentPeriodExpired_deadline_today() { + LocalDate start = LocalDate.now().plusDays(1); + Room room = Room.withoutId( + "제목", "설명", false, "1234", + start, start.plusDays(10), 5, 123L, 456L + ); + // 오늘이 모집마감일(startDate.minusDays(1))이면 false + assertFalse(room.isRecruitmentPeriodExpired()); + } + + @Test + @DisplayName("isRecruitmentPeriodExpired: 모집기간이 이미 만료된 경우 true 반환") + void isRecruitmentPeriodExpired_expired() { + LocalDate start = LocalDate.now().plusDays(1); + Room room = Room.withoutId( + "제목", "설명", false, "1234", + start, start.plusDays(10), 5, 123L, 456L + ); + // 오늘이 startDate.minusDays(1)보다 이후면 true + assertTrue(room.isRecruitmentPeriodExpired()); + } + + @Test + @DisplayName("verifyPassword: 모집기간 만료 시 BusinessException(ROOM_RECRUITMENT_PERIOD_EXPIRED) 발생") + void verifyPassword_recruitmentPeriodExpired() { + LocalDate startExpired = today.plusDays(2); + Room room = Room.withoutId( + "제목", "설명", false, "1234", + startExpired, END, 5, 123L, 456L + ); + setField(room, "startDate", today); // 모집기간 만료 상태를 강제로 만든 후 검증 + BusinessException ex = assertThrows(BusinessException.class, + () -> room.verifyPassword("1234")); + assertEquals(ErrorCode.ROOM_RECRUITMENT_PERIOD_EXPIRED, ex.getErrorCode()); + assertTrue(ex.getCause().getMessage().contains("모집기간")); + } + + @Test + @DisplayName("verifyPassword: 공개방에 비밀번호 입력 시 BusinessException(ROOM_PASSWORD_NOT_REQUIRED) 발생") + void verifyPassword_publicRoom() { + Room room = Room.withoutId( + "제목", "설명", true, null, + START, END, 5, 123L, 456L + ); + BusinessException ex = assertThrows(BusinessException.class, + () -> room.verifyPassword("1234")); + assertEquals(ErrorCode.ROOM_PASSWORD_NOT_REQUIRED, ex.getErrorCode()); + } + + @Test + @DisplayName("verifyPassword: 비밀번호 불일치 시 BusinessException(ROOM_PASSWORD_MISMATCH) 발생") + void verifyPassword_passwordMismatch() { + Room room = Room.withoutId( + "제목", "설명", false, "1234", + START, END, 5, 123L, 456L + ); + BusinessException ex = assertThrows(BusinessException.class, + () -> room.verifyPassword("0000")); + assertEquals(ErrorCode.ROOM_PASSWORD_MISMATCH, ex.getErrorCode()); + } + + @Test + @DisplayName("verifyPassword: 모집기간 내, 비공개방, 비밀번호 일치 시 예외 발생하지 않음") + void verifyPassword_success() { + Room room = Room.withoutId( + "제목", "설명", false, "1234", + START, END, 5, 123L, 456L + ); + assertDoesNotThrow(() -> room.verifyPassword("1234")); + } + } From 19702a12bdf73950bd329798c97fa5639096c84e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 01:28:26 +0900 Subject: [PATCH 14/17] =?UTF-8?q?[test]=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/konkuk/thip/room/domain/RoomTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/konkuk/thip/room/domain/RoomTest.java b/src/test/java/konkuk/thip/room/domain/RoomTest.java index 756e507ab..1c90e1910 100644 --- a/src/test/java/konkuk/thip/room/domain/RoomTest.java +++ b/src/test/java/konkuk/thip/room/domain/RoomTest.java @@ -186,7 +186,7 @@ void isRecruitmentPeriodExpired_expired() { "제목", "설명", false, "1234", start, start.plusDays(10), 5, 123L, 456L ); - // 오늘이 startDate.minusDays(1)보다 이후면 true + setField(room, "startDate", today); // 모집기간 만료 상태를 강제로 만든 후 검증 assertTrue(room.isRecruitmentPeriodExpired()); } From b18479823dd3541ea00995e7bbf964e2631cf9de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 01:47:04 +0900 Subject: [PATCH 15/17] =?UTF-8?q?[test]=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/web/RoomVerifyPasswordControllerTest.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordControllerTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordControllerTest.java index 4e996f0b1..93e710d1e 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordControllerTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordControllerTest.java @@ -9,14 +9,17 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; + import java.util.HashMap; import java.util.Map; import static konkuk.thip.common.exception.code.ErrorCode.API_INVALID_PARAM; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.hamcrest.Matchers.anyOf; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -54,8 +57,9 @@ private void assertBad(Map req, String msg) throws Exception { @Nested @DisplayName("비밀번호 검증") class PasswordValidation { + @Test - @DisplayName("비밀번호가 4자리 숫자가 아닐 때 400 error") + @DisplayName("숫자로 구성되지 않았을 때 400 error") void invalid_password() throws Exception { Map req = buildValidRequest(); req.put("password", "12ab"); @@ -63,7 +67,7 @@ void invalid_password() throws Exception { } @Test - @DisplayName("비밀번호가 4자리가 아닐 때 400 error") + @DisplayName("4자리 숫자 아닐 때 400 error") void short_password() throws Exception { Map req = buildValidRequest(); req.put("password", "123"); @@ -71,11 +75,12 @@ void short_password() throws Exception { } @Test - @DisplayName("비밀번호가 빈 값일 때 400 error") - void blank_password() throws Exception { + @DisplayName("빈 문자열일 때 400 error") + void blank_description() throws Exception { Map req = buildValidRequest(); req.put("password", ""); - assertBad(req, "파라미터 값 중 유효하지 않은 값이 있습니다. 비밀번호는 필수입니다."); } + assertBad(req, "비밀번호는 필수입니다."); + } } @Nested From 70df261abd7e1ac7ddd96ce7337ed1f9b5f7b2f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 01:47:14 +0900 Subject: [PATCH 16/17] =?UTF-8?q?[test]=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../room/adapter/in/web/RoomVerifyPasswordControllerTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordControllerTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordControllerTest.java index 93e710d1e..e19882bbe 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordControllerTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomVerifyPasswordControllerTest.java @@ -14,12 +14,10 @@ import java.util.Map; import static konkuk.thip.common.exception.code.ErrorCode.API_INVALID_PARAM; -import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.hamcrest.Matchers.anyOf; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; From c0feed8637a680f4fbe1a2fb43ae80d72ba72445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=ED=9D=AC=EC=A7=84?= Date: Wed, 9 Jul 2025 20:10:42 +0900 Subject: [PATCH 17/17] =?UTF-8?q?[refactor]=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=EC=95=88=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/room/adapter/in/web/RoomQueryController.java | 6 ++---- .../adapter/in/web/request/RoomVerifyPasswordRequest.java | 3 +-- .../application/port/in/dto/RoomVerifyPasswordQuery.java | 1 - .../room/application/service/RoomVerifyPasswordService.java | 5 ----- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java b/src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java index a07e0974d..841aaeae9 100644 --- a/src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java +++ b/src/main/java/konkuk/thip/room/adapter/in/web/RoomQueryController.java @@ -2,7 +2,6 @@ import jakarta.validation.Valid; import konkuk.thip.common.dto.BaseResponse; -import konkuk.thip.common.security.annotation.UserId; import konkuk.thip.room.adapter.in.web.request.RoomVerifyPasswordRequest; import konkuk.thip.room.application.port.in.RoomVerifyPasswordUseCase; import lombok.RequiredArgsConstructor; @@ -16,11 +15,10 @@ public class RoomQueryController { //비공개 방 비밀번호 입력 검증 @PostMapping("/rooms/{roomId}/password") - public BaseResponse verifyRoomPassword(@UserId final Long userId, - @PathVariable("roomId") final Long roomId, + public BaseResponse verifyRoomPassword(@PathVariable("roomId") final Long roomId, @Valid @RequestBody final RoomVerifyPasswordRequest roomVerifyPasswordRequest ) { - return BaseResponse.ok(roomVerifyPasswordUseCase.verifyRoomPassword(roomVerifyPasswordRequest.toQuery(userId,roomId))); + return BaseResponse.ok(roomVerifyPasswordUseCase.verifyRoomPassword(roomVerifyPasswordRequest.toQuery(roomId))); } } diff --git a/src/main/java/konkuk/thip/room/adapter/in/web/request/RoomVerifyPasswordRequest.java b/src/main/java/konkuk/thip/room/adapter/in/web/request/RoomVerifyPasswordRequest.java index 7918d9ad1..b97ca1647 100644 --- a/src/main/java/konkuk/thip/room/adapter/in/web/request/RoomVerifyPasswordRequest.java +++ b/src/main/java/konkuk/thip/room/adapter/in/web/request/RoomVerifyPasswordRequest.java @@ -10,9 +10,8 @@ public record RoomVerifyPasswordRequest( @Pattern(regexp = "\\d{4}", message = "비밀번호는 숫자 4자리여야 합니다.") String password ) { - public RoomVerifyPasswordQuery toQuery(Long userId,Long roomId) { + public RoomVerifyPasswordQuery toQuery(Long roomId) { return new RoomVerifyPasswordQuery( - userId, roomId, password); } diff --git a/src/main/java/konkuk/thip/room/application/port/in/dto/RoomVerifyPasswordQuery.java b/src/main/java/konkuk/thip/room/application/port/in/dto/RoomVerifyPasswordQuery.java index fa1129256..aeb35aa5f 100644 --- a/src/main/java/konkuk/thip/room/application/port/in/dto/RoomVerifyPasswordQuery.java +++ b/src/main/java/konkuk/thip/room/application/port/in/dto/RoomVerifyPasswordQuery.java @@ -1,7 +1,6 @@ package konkuk.thip.room.application.port.in.dto; public record RoomVerifyPasswordQuery( - Long userId, Long roomId, String password ) { diff --git a/src/main/java/konkuk/thip/room/application/service/RoomVerifyPasswordService.java b/src/main/java/konkuk/thip/room/application/service/RoomVerifyPasswordService.java index 419d33df1..88ead3713 100644 --- a/src/main/java/konkuk/thip/room/application/service/RoomVerifyPasswordService.java +++ b/src/main/java/konkuk/thip/room/application/service/RoomVerifyPasswordService.java @@ -4,7 +4,6 @@ import konkuk.thip.room.application.port.in.dto.RoomVerifyPasswordQuery; import konkuk.thip.room.application.port.out.RoomCommandPort; import konkuk.thip.room.domain.Room; -import konkuk.thip.user.application.port.out.UserCommandPort; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -14,15 +13,11 @@ @Transactional(readOnly = true) public class RoomVerifyPasswordService implements RoomVerifyPasswordUseCase { - private final UserCommandPort userCommandPort; private final RoomCommandPort roomCommandPort; @Override public Void verifyRoomPassword(RoomVerifyPasswordQuery query) { - //유저 검증 - userCommandPort.findById(query.userId()); - //방 검증 Room room = roomCommandPort.findById(query.roomId());