From 943240a2a2eb5431470fe613666440a99bb28138 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 20:32:26 +0900 Subject: [PATCH 01/28] =?UTF-8?q?[chore]=20CustomerFixture=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=20=EC=B6=94=EA=B0=80=20-=20CustomerFixture=20?= =?UTF-8?q?=EC=9D=98=20=EA=B8=B0=EB=8A=A5=EA=B3=BC=20=EB=AA=A9=EC=A0=81?= =?UTF-8?q?=EC=9D=84=20=EC=84=A4=EB=AA=85=ED=95=98=EB=8A=94=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=20=EB=AA=85=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/camp/woowak/lab/fixture/CustomerFixture.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/java/camp/woowak/lab/fixture/CustomerFixture.java b/src/test/java/camp/woowak/lab/fixture/CustomerFixture.java index 75c1ac1b..d30b2ea2 100644 --- a/src/test/java/camp/woowak/lab/fixture/CustomerFixture.java +++ b/src/test/java/camp/woowak/lab/fixture/CustomerFixture.java @@ -5,6 +5,9 @@ import camp.woowak.lab.payaccount.domain.PayAccount; import camp.woowak.lab.web.authentication.PasswordEncoder; +/** + * CustomerFixture는 Customer와 관련된 테스트에서 공통적으로 사용되는 객체를 생성하는 인터페이스입니다. + */ public interface CustomerFixture { default PayAccount createPayAccount() { return new PayAccount(); @@ -12,7 +15,8 @@ default PayAccount createPayAccount() { default Customer createCustomer(PayAccount payAccount, PasswordEncoder passwordEncoder) { try { - return new Customer("vendorName", "vendorEmail@example.com", "vendorPassword", "010-0000-0000", payAccount, + return new Customer("customerName", "customerEmail@example.com", "customerPassword", "010-0000-0000", + payAccount, passwordEncoder); } catch (InvalidCreationException e) { throw new RuntimeException(e); From c09a6a3cf2ba681dd2735a78e6dc281f2cef1c85 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 20:41:38 +0900 Subject: [PATCH 02/28] =?UTF-8?q?[test]=20SignInCustomerServiceTest=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=84=B1=EA=B3=B5,=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=8B=A4?= =?UTF-8?q?=ED=8C=A8=20-=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=97=86?= =?UTF-8?q?=EC=9D=8C,=20=ED=8C=A8=EC=8A=A4=EC=9B=8C=EB=93=9C=20=EB=B6=88?= =?UTF-8?q?=EC=9D=BC=EC=B9=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SignInCustomerServiceTest.java | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/customer/service/SignInCustomerServiceTest.java diff --git a/src/test/java/camp/woowak/lab/customer/service/SignInCustomerServiceTest.java b/src/test/java/camp/woowak/lab/customer/service/SignInCustomerServiceTest.java new file mode 100644 index 00000000..555c3dff --- /dev/null +++ b/src/test/java/camp/woowak/lab/customer/service/SignInCustomerServiceTest.java @@ -0,0 +1,81 @@ +package camp.woowak.lab.customer.service; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import camp.woowak.lab.customer.domain.Customer; +import camp.woowak.lab.customer.exception.AuthenticationException; +import camp.woowak.lab.customer.repository.CustomerRepository; +import camp.woowak.lab.customer.service.command.SignInCustomerCommand; +import camp.woowak.lab.fixture.CustomerFixture; +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.domain.TestPayAccount; +import camp.woowak.lab.web.authentication.PasswordEncoder; + +/** + * + */ +@ExtendWith(MockitoExtension.class) +public class SignInCustomerServiceTest implements CustomerFixture { + @InjectMocks + private SignInCustomerService signInCustomerService; + + @Mock + private CustomerRepository customerRepository; + + @Mock + private PasswordEncoder passwordEncoder; + + @Test + @DisplayName("로그인 성공") + void testSignIn() { + // given + PayAccount newPayAccount = new TestPayAccount(1L); + Customer customer = createCustomer(newPayAccount, passwordEncoder); + SignInCustomerCommand cmd = new SignInCustomerCommand(customer.getEmail(), customer.getPassword()); + given(customerRepository.findByEmail(customer.getEmail())).willReturn(customer); + given(passwordEncoder.matches(cmd.password(), customer.getPassword())).willReturn(true); + + // when & then + assertDoesNotThrow(() -> signInCustomerService.signIn(cmd)); + verify(customerRepository).findByEmail(customer.getEmail()); + verify(passwordEncoder).matches(cmd.password(), customer.getPassword()); + } + + @Test + @DisplayName("로그인 실패 - 이메일 없음") + void testSignInFailEmailNotFound() { + // given + PayAccount newPayAccount = new TestPayAccount(1L); + Customer customer = createCustomer(newPayAccount, passwordEncoder); + SignInCustomerCommand cmd = new SignInCustomerCommand("InvalidCustomer@email.com", customer.getPassword()); + given(customerRepository.findByEmail(cmd.email())).willReturn(null); + + // when & then + assertThrows(AuthenticationException.class, () -> signInCustomerService.signIn(cmd)); + verify(customerRepository).findByEmail(cmd.email()); + } + + @Test + @DisplayName("로그인 실패 - 패스워드 불일치") + void testSignInFail() { + // given + PayAccount newPayAccount = new TestPayAccount(1L); + Customer customer = createCustomer(newPayAccount, passwordEncoder); + SignInCustomerCommand cmd = new SignInCustomerCommand(customer.getEmail(), customer.getPassword()); + given(customerRepository.findByEmail(customer.getEmail())).willReturn(customer); + given(passwordEncoder.matches(cmd.password(), customer.getPassword())).willReturn(false); + + // when & then + assertThrows(AuthenticationException.class, () -> signInCustomerService.signIn(cmd)); + verify(customerRepository).findByEmail(customer.getEmail()); + verify(passwordEncoder).matches(cmd.password(), customer.getPassword()); + } +} From 1251252a45c09f9a938c0af098964a025f0f0cd4 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 20:45:23 +0900 Subject: [PATCH 03/28] =?UTF-8?q?[feat]=20SignInCustomerService=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20SignInCustomerService.signIn=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EC=97=86=EC=9D=8C=EA=B3=BC=20=ED=8C=A8=EC=8A=A4=EC=9B=8C?= =?UTF-8?q?=EB=93=9C=20=EB=B6=88=EC=9D=BC=EC=B9=98=EB=A5=BC=20=EA=B0=99?= =?UTF-8?q?=EC=9D=B4=20=EC=B2=98=EB=A6=AC=ED=95=98=EB=A9=B4=EC=84=9C=20?= =?UTF-8?q?=EB=B3=B4=EC=95=88=20=EA=B0=95=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SignInCustomerService.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java diff --git a/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java b/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java new file mode 100644 index 00000000..473168e2 --- /dev/null +++ b/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java @@ -0,0 +1,27 @@ +package camp.woowak.lab.customer.service; + +import org.springframework.stereotype.Service; + +import camp.woowak.lab.customer.domain.Customer; +import camp.woowak.lab.customer.exception.AuthenticationException; +import camp.woowak.lab.customer.repository.CustomerRepository; +import camp.woowak.lab.customer.service.command.SignInCustomerCommand; +import camp.woowak.lab.web.authentication.PasswordEncoder; + +@Service +public class SignInCustomerService { + private final CustomerRepository customerRepository; + private final PasswordEncoder passwordEncoder; + + public SignInCustomerService(CustomerRepository customerRepository, PasswordEncoder passwordEncoder) { + this.customerRepository = customerRepository; + this.passwordEncoder = passwordEncoder; + } + + public void signIn(SignInCustomerCommand cmd) { + Customer byEmail = customerRepository.findByEmail(cmd.email()); + if (byEmail == null || !passwordEncoder.matches(cmd.password(), byEmail.getPassword())) { + throw new AuthenticationException("Invalid email or password"); + } + } +} From c61a434f32d959e9f37b6de045a8a1fea08ce000 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 20:45:55 +0900 Subject: [PATCH 04/28] =?UTF-8?q?[feat]=20SignInCustomerCommand=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20=EA=B5=AC=EB=A7=A4=EC=9E=90=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=EC=97=90=20=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20email,=20password=20=ED=95=84=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../customer/service/command/SignInCustomerCommand.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/customer/service/command/SignInCustomerCommand.java diff --git a/src/main/java/camp/woowak/lab/customer/service/command/SignInCustomerCommand.java b/src/main/java/camp/woowak/lab/customer/service/command/SignInCustomerCommand.java new file mode 100644 index 00000000..31dde74c --- /dev/null +++ b/src/main/java/camp/woowak/lab/customer/service/command/SignInCustomerCommand.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.customer.service.command; + +public record SignInCustomerCommand( + String email, + String password +) { +} From 43d5329c45fab99af44a518bf5106c26802f0014 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 20:46:43 +0900 Subject: [PATCH 05/28] =?UTF-8?q?[feat]=20CustomerRepository.findByEmail?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20-=20=EA=B5=AC=EB=A7=A4=EC=9E=90=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=8B=9C=20=EA=B5=AC=EB=A7=A4?= =?UTF-8?q?=EC=9E=90=20=EA=B2=80=EC=83=89=EC=97=90=20=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20findByEmail=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/customer/repository/CustomerRepository.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java b/src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java index 9b8e9bc4..0b9a3c16 100644 --- a/src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java +++ b/src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java @@ -7,4 +7,5 @@ @Repository public interface CustomerRepository extends JpaRepository { + Customer findByEmail(String email); } From fb7ba6a404bacc9c9aec6393ed3c958a52b65710 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 20:47:20 +0900 Subject: [PATCH 06/28] =?UTF-8?q?[feat]=20AuthenticationException=20-=20?= =?UTF-8?q?=EA=B5=AC=EB=A7=A4=EC=9E=90=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=8B=A4=ED=8C=A8=20=EC=8B=9C=20=EC=9D=B8=EC=A6=9D=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/customer/exception/AuthenticationException.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/customer/exception/AuthenticationException.java diff --git a/src/main/java/camp/woowak/lab/customer/exception/AuthenticationException.java b/src/main/java/camp/woowak/lab/customer/exception/AuthenticationException.java new file mode 100644 index 00000000..c30fb925 --- /dev/null +++ b/src/main/java/camp/woowak/lab/customer/exception/AuthenticationException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.customer.exception; + +public class AuthenticationException extends RuntimeException { + public AuthenticationException(String message) { + super(message); + } +} From 01cfcdfacc17c02f5f7e10e62db08db54c0e3437 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 21:02:05 +0900 Subject: [PATCH 07/28] =?UTF-8?q?[test]=20CustomerControllerTest.signIn=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20CustomerControllerTest.testSignInCusto?= =?UTF-8?q?mer:=20=EA=B5=AC=EB=A7=A4=EC=9E=90=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=84=B1=EA=B3=B5=20?= =?UTF-8?q?-=20CustomerControllerTest.testSignInCustomerFail:=20=EA=B5=AC?= =?UTF-8?q?=EB=A7=A4=EC=9E=90=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=8B=A4=ED=8C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/web/api/CustomerControllerTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java b/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java index 0799d428..11978749 100644 --- a/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java @@ -16,8 +16,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; +import camp.woowak.lab.customer.exception.AuthenticationException; import camp.woowak.lab.customer.exception.DuplicateEmailException; +import camp.woowak.lab.customer.service.SignInCustomerService; import camp.woowak.lab.customer.service.SignUpCustomerService; +import camp.woowak.lab.web.dto.request.SignInCustomerRequest; import camp.woowak.lab.web.dto.request.SignUpCustomerRequest; import camp.woowak.lab.web.error.ErrorCode; @@ -31,6 +34,9 @@ class CustomerControllerTest { @MockBean private SignUpCustomerService signUpCustomerService; + @MockBean + private SignInCustomerService signInCustomerService; + @Autowired private ObjectMapper objectMapper; @@ -212,4 +218,33 @@ void testSignUpCustomerWithDuplicateEmail() throws Exception { .andExpect(jsonPath("$.code").value(ErrorCode.AUTH_DUPLICATE_EMAIL.getCode())) .andExpect(jsonPath("$.message").value(ErrorCode.AUTH_DUPLICATE_EMAIL.getMessage())); } + + @Test + @DisplayName("구매자 로그인 테스트 - 성공") + void testSignInCustomer() throws Exception { + // given + SignInCustomerRequest request = new SignInCustomerRequest("customer@email.com", "password123"); + willDoNothing().given(signInCustomerService).signIn(any()); + + // when & then + mockMvc.perform(post("/customers/sign-in") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isOk()); + } + + @Test + @DisplayName("구매자 로그인 테스트 - 로그인 실패 시") + void testSignInCustomerFail() throws Exception { + // given + SignInCustomerRequest request = new SignInCustomerRequest + ("Invalid@email.com", "InvalidPassword123"); + willThrow(new AuthenticationException("Invalid email or password")).given(signInCustomerService).signIn(any()); + + // when & then + mockMvc.perform(post("/customers/sign-in") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()); + } } \ No newline at end of file From d56b5331f115980ddef8f9c62793fe213440a6e9 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 21:04:27 +0900 Subject: [PATCH 08/28] =?UTF-8?q?[feat]=20CustomerController.signIn=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20=EA=B5=AC=EB=A7=A4=EC=9E=90=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=84=B1=EA=B3=B5=20=EC=8B=9C=20?= =?UTF-8?q?OK=20=EB=B0=98=ED=99=98=20-=20=EA=B5=AC=EB=A7=A4=EC=9E=90=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=8B=A4=ED=8C=A8=20=EC=8B=9C=20?= =?UTF-8?q?BadRequest=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/web/api/CustomerController.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/java/camp/woowak/lab/web/api/CustomerController.java b/src/main/java/camp/woowak/lab/web/api/CustomerController.java index 498070b0..afbfd093 100644 --- a/src/main/java/camp/woowak/lab/web/api/CustomerController.java +++ b/src/main/java/camp/woowak/lab/web/api/CustomerController.java @@ -7,8 +7,12 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import camp.woowak.lab.customer.exception.AuthenticationException; +import camp.woowak.lab.customer.service.SignInCustomerService; import camp.woowak.lab.customer.service.SignUpCustomerService; +import camp.woowak.lab.customer.service.command.SignInCustomerCommand; import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; +import camp.woowak.lab.web.dto.request.SignInCustomerRequest; import camp.woowak.lab.web.dto.request.SignUpCustomerRequest; import camp.woowak.lab.web.dto.response.ApiResponse; import camp.woowak.lab.web.error.ErrorCode; @@ -17,9 +21,12 @@ @RestController public class CustomerController { private final SignUpCustomerService signUpCustomerService; + private final SignInCustomerService signInCustomerService; - public CustomerController(SignUpCustomerService signUpCustomerService) { + public CustomerController(SignUpCustomerService signUpCustomerService, + SignInCustomerService signInCustomerService) { this.signUpCustomerService = signUpCustomerService; + this.signInCustomerService = signInCustomerService; } @PostMapping("/customers") @@ -36,4 +43,15 @@ public ResponseEntity signUp(@Valid @RequestBody SignUpCustomerRequest reques } return ResponseEntity.created(URI.create("/customers/" + registeredId)).build(); } + + @PostMapping("/customers/sign-in") + public ResponseEntity signIn(@RequestBody SignInCustomerRequest request) { + try { + signInCustomerService.signIn(new SignInCustomerCommand(request.email(), request.password())); + } catch (AuthenticationException e) { + return ResponseEntity.badRequest().body(ApiResponse.error(ErrorCode.AUTH_INVALID_CREDENTIALS)); + } + // TODO: JWT 토큰 발급 + return ResponseEntity.ok().build(); + } } From 627be32adaaf3dbc3b6ea8c22a6bcd69871af8ba Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 21:04:50 +0900 Subject: [PATCH 09/28] =?UTF-8?q?[feat]=20ErrorCode.AUTH=5FINVALID=5FCREDE?= =?UTF-8?q?NTIALS=20-=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=8B=A4=ED=8C=A8?= =?UTF-8?q?=20=EC=8B=9C=20ErrorCode=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/camp/woowak/lab/web/error/ErrorCode.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/camp/woowak/lab/web/error/ErrorCode.java b/src/main/java/camp/woowak/lab/web/error/ErrorCode.java index 53b0e82e..0913ef92 100644 --- a/src/main/java/camp/woowak/lab/web/error/ErrorCode.java +++ b/src/main/java/camp/woowak/lab/web/error/ErrorCode.java @@ -2,8 +2,8 @@ public enum ErrorCode { AUTH_DUPLICATE_EMAIL("a1", "이미 가입된 이메일 입니다."), - SIGNUP_INVALID_REQUEST("s1", "잘못된 요청입니다."); - + SIGNUP_INVALID_REQUEST("s1", "잘못된 요청입니다."), + AUTH_INVALID_CREDENTIALS("a2", "이메일 또는 비밀번호가 올바르지 않습니다."); private final String code; private final String message; From 2395f85d1172a08f6c796020f992f672e91c6fd3 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 21:06:07 +0900 Subject: [PATCH 10/28] =?UTF-8?q?[feat]=20SignInCustomerRequest=20-=20?= =?UTF-8?q?=EA=B5=AC=EB=A7=A4=EC=9E=90=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20SignInCustomerRequest=20?= =?UTF-8?q?=EC=9D=B4=EB=A9=94=EC=9D=BC,=20=ED=8C=A8=EC=8A=A4=EC=9B=8C?= =?UTF-8?q?=EB=93=9C=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/web/dto/request/SignInCustomerRequest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/dto/request/SignInCustomerRequest.java diff --git a/src/main/java/camp/woowak/lab/web/dto/request/SignInCustomerRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/SignInCustomerRequest.java new file mode 100644 index 00000000..bdcbeaa9 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/dto/request/SignInCustomerRequest.java @@ -0,0 +1,10 @@ +package camp.woowak.lab.web.dto.request; + +/** + * 이메일 비밀번호 조건을 알 수 없도록 모든 요청을 받을 수 있도록 구현 + */ +public record SignInCustomerRequest( + String email, + String password +) { +} From 97d206bb4ed01bf2dba9ae28bdc37153f5d392df Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 13:53:24 +0900 Subject: [PATCH 11/28] =?UTF-8?q?[feat]=20CustomerAuthenticationException?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=20-=20=EA=B5=AC=EB=A7=A4=EC=9E=90=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=8B=A4=ED=8C=A8=20=EC=8B=9C=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/customer/exception/AuthenticationException.java | 7 ------- .../exception/CustomerAuthenticationException.java | 9 +++++++++ 2 files changed, 9 insertions(+), 7 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/customer/exception/AuthenticationException.java create mode 100644 src/main/java/camp/woowak/lab/customer/exception/CustomerAuthenticationException.java diff --git a/src/main/java/camp/woowak/lab/customer/exception/AuthenticationException.java b/src/main/java/camp/woowak/lab/customer/exception/AuthenticationException.java deleted file mode 100644 index c30fb925..00000000 --- a/src/main/java/camp/woowak/lab/customer/exception/AuthenticationException.java +++ /dev/null @@ -1,7 +0,0 @@ -package camp.woowak.lab.customer.exception; - -public class AuthenticationException extends RuntimeException { - public AuthenticationException(String message) { - super(message); - } -} diff --git a/src/main/java/camp/woowak/lab/customer/exception/CustomerAuthenticationException.java b/src/main/java/camp/woowak/lab/customer/exception/CustomerAuthenticationException.java new file mode 100644 index 00000000..9d6edb8c --- /dev/null +++ b/src/main/java/camp/woowak/lab/customer/exception/CustomerAuthenticationException.java @@ -0,0 +1,9 @@ +package camp.woowak.lab.customer.exception; + +import camp.woowak.lab.common.exception.UnauthorizedException; + +public class CustomerAuthenticationException extends UnauthorizedException { + public CustomerAuthenticationException(String message) { + super(CustomerErrorCode.AUTHENTICATION_FAILED, message); + } +} From 915b6b43c7aa1b1bd8c05bf20fdcd93404b5a0c0 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 13:53:47 +0900 Subject: [PATCH 12/28] =?UTF-8?q?[feat]=20CustomerErrorCode.AUTHENTICATION?= =?UTF-8?q?=5FFAILED=20=EA=B5=AC=ED=98=84=20-=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=A4=ED=8C=A8=20=EC=8B=9C=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/customer/exception/CustomerErrorCode.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java b/src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java index 7ad34f6c..64917ca0 100644 --- a/src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java +++ b/src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java @@ -4,7 +4,8 @@ public enum CustomerErrorCode implements ErrorCode { INVALID_CREATION(400, "C1", "잘못된 요청입니다."), - DUPLICATE_EMAIL(400, "C2", "이미 존재하는 이메일입니다."); + DUPLICATE_EMAIL(400, "C2", "이미 존재하는 이메일입니다."), + AUTHENTICATION_FAILED(401, "C3", "이메일 또는 비밀번호가 올바르지 않습니다."); private final int status; private final String errorCode; From 9f9434b8b39062efbdeeb5338743428bfe62a2de Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 13:55:00 +0900 Subject: [PATCH 13/28] =?UTF-8?q?[feat]=20SignInCustomerService.signIn=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=20=EB=B6=84=EA=B8=B0=20-=20=EC=9D=B4?= =?UTF-8?q?=EB=A9=94=EC=9D=BC=EC=9D=B4=20=EC=A1=B4=EC=9E=AC=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=A7=80=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=EA=B0=80=20=EC=A1=B4=EC=9E=AC=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=A7=80=20=EC=84=9C=EB=B2=84?= =?UTF-8?q?=20=EC=8B=9C=EC=A0=90=EC=97=90=EC=84=9C=20=EB=AA=85=ED=99=95?= =?UTF-8?q?=ED=9E=88=20=EA=B5=AC=EB=B6=84=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/customer/service/SignInCustomerService.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java b/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java index 473168e2..8fe442ef 100644 --- a/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java +++ b/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java @@ -3,7 +3,7 @@ import org.springframework.stereotype.Service; import camp.woowak.lab.customer.domain.Customer; -import camp.woowak.lab.customer.exception.AuthenticationException; +import camp.woowak.lab.customer.exception.CustomerAuthenticationException; import camp.woowak.lab.customer.repository.CustomerRepository; import camp.woowak.lab.customer.service.command.SignInCustomerCommand; import camp.woowak.lab.web.authentication.PasswordEncoder; @@ -20,8 +20,10 @@ public SignInCustomerService(CustomerRepository customerRepository, PasswordEnco public void signIn(SignInCustomerCommand cmd) { Customer byEmail = customerRepository.findByEmail(cmd.email()); - if (byEmail == null || !passwordEncoder.matches(cmd.password(), byEmail.getPassword())) { - throw new AuthenticationException("Invalid email or password"); + if (byEmail == null) { + throw new CustomerAuthenticationException("invalid email"); + } else if (!passwordEncoder.matches(cmd.password(), byEmail.getPassword())) { + throw new CustomerAuthenticationException("password not matched"); } } } From f812c5b2fa838853c443e1d06d7e4ca3cdf4e18e Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 13:55:30 +0900 Subject: [PATCH 14/28] =?UTF-8?q?[feat]=20UnauthorizedException=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=B6=94=EA=B0=80=20-=20Unauthor?= =?UTF-8?q?izedException(ErroCode,=20String)=20=EC=83=9D=EC=84=B1=EC=9E=90?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/common/exception/UnauthorizedException.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/camp/woowak/lab/common/exception/UnauthorizedException.java b/src/main/java/camp/woowak/lab/common/exception/UnauthorizedException.java index ba2e1237..b68755c7 100644 --- a/src/main/java/camp/woowak/lab/common/exception/UnauthorizedException.java +++ b/src/main/java/camp/woowak/lab/common/exception/UnauthorizedException.java @@ -4,4 +4,8 @@ public class UnauthorizedException extends HttpStatusException { public UnauthorizedException(ErrorCode errorCode) { super(errorCode); } + + public UnauthorizedException(ErrorCode errorCode, String message) { + super(errorCode, message); + } } From 2bee2775e1be7b7bb7c0733ec0e08a0156ede14e Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 13:56:09 +0900 Subject: [PATCH 15/28] =?UTF-8?q?[fix]=20AuthenticationException=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/customer/service/SignInCustomerServiceTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/camp/woowak/lab/customer/service/SignInCustomerServiceTest.java b/src/test/java/camp/woowak/lab/customer/service/SignInCustomerServiceTest.java index 555c3dff..12a03c26 100644 --- a/src/test/java/camp/woowak/lab/customer/service/SignInCustomerServiceTest.java +++ b/src/test/java/camp/woowak/lab/customer/service/SignInCustomerServiceTest.java @@ -11,7 +11,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import camp.woowak.lab.customer.domain.Customer; -import camp.woowak.lab.customer.exception.AuthenticationException; +import camp.woowak.lab.customer.exception.CustomerAuthenticationException; import camp.woowak.lab.customer.repository.CustomerRepository; import camp.woowak.lab.customer.service.command.SignInCustomerCommand; import camp.woowak.lab.fixture.CustomerFixture; @@ -59,7 +59,7 @@ void testSignInFailEmailNotFound() { given(customerRepository.findByEmail(cmd.email())).willReturn(null); // when & then - assertThrows(AuthenticationException.class, () -> signInCustomerService.signIn(cmd)); + assertThrows(CustomerAuthenticationException.class, () -> signInCustomerService.signIn(cmd)); verify(customerRepository).findByEmail(cmd.email()); } @@ -74,7 +74,7 @@ void testSignInFail() { given(passwordEncoder.matches(cmd.password(), customer.getPassword())).willReturn(false); // when & then - assertThrows(AuthenticationException.class, () -> signInCustomerService.signIn(cmd)); + assertThrows(CustomerAuthenticationException.class, () -> signInCustomerService.signIn(cmd)); verify(customerRepository).findByEmail(customer.getEmail()); verify(passwordEncoder).matches(cmd.password(), customer.getPassword()); } From a9fe4a5d47edd119ce9623630253f566bf59763a Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 14:32:29 +0900 Subject: [PATCH 16/28] =?UTF-8?q?[docs]=20SignInCustomerService=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=EB=AA=85=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/customer/service/SignInCustomerService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java b/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java index 8fe442ef..bff322dc 100644 --- a/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java +++ b/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java @@ -23,6 +23,9 @@ public void signIn(SignInCustomerCommand cmd) { if (byEmail == null) { throw new CustomerAuthenticationException("invalid email"); } else if (!passwordEncoder.matches(cmd.password(), byEmail.getPassword())) { + /** + * @throws CustomerAuthenticationException 이메일이 존재하지 않거나 비밀번호가 일치하지 않으면 + */ throw new CustomerAuthenticationException("password not matched"); } } From 50f41937e8a510f6dde51a066840dbf4807edeff Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 14:33:28 +0900 Subject: [PATCH 17/28] =?UTF-8?q?[feat]=20SignInCustomerService.signIn=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=20=EA=B0=92=20=EB=B3=80=EA=B2=BD=20-=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=90=9C=20=EA=B5=AC=EB=A7=A4?= =?UTF-8?q?=EC=9E=90=EC=9D=98=20UUID=20=EB=A5=BC=20=EC=A0=84=EB=8B=AC?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/customer/service/SignInCustomerService.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java b/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java index bff322dc..e2eb6385 100644 --- a/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java +++ b/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java @@ -1,5 +1,7 @@ package camp.woowak.lab.customer.service; +import java.util.UUID; + import org.springframework.stereotype.Service; import camp.woowak.lab.customer.domain.Customer; @@ -18,15 +20,16 @@ public SignInCustomerService(CustomerRepository customerRepository, PasswordEnco this.passwordEncoder = passwordEncoder; } - public void signIn(SignInCustomerCommand cmd) { - Customer byEmail = customerRepository.findByEmail(cmd.email()); - if (byEmail == null) { - throw new CustomerAuthenticationException("invalid email"); - } else if (!passwordEncoder.matches(cmd.password(), byEmail.getPassword())) { /** * @throws CustomerAuthenticationException 이메일이 존재하지 않거나 비밀번호가 일치하지 않으면 */ + public UUID signIn(SignInCustomerCommand cmd) { + Customer byEmail = customerRepository.findByEmail(cmd.email()) + .orElseThrow(() -> new CustomerAuthenticationException("email not found")); + if (byEmail.validatePassword(cmd.password(), passwordEncoder)) { throw new CustomerAuthenticationException("password not matched"); } + + return byEmail.getId(); } } From 070fba7f78b53f840321bf7645c78564ceddd30a Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 14:34:10 +0900 Subject: [PATCH 18/28] =?UTF-8?q?[refactor]=20SignInCustomerRequest=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/dto/request/{ => customer}/SignInCustomerRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/camp/woowak/lab/web/dto/request/{ => customer}/SignInCustomerRequest.java (78%) diff --git a/src/main/java/camp/woowak/lab/web/dto/request/SignInCustomerRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/customer/SignInCustomerRequest.java similarity index 78% rename from src/main/java/camp/woowak/lab/web/dto/request/SignInCustomerRequest.java rename to src/main/java/camp/woowak/lab/web/dto/request/customer/SignInCustomerRequest.java index bdcbeaa9..cc12e435 100644 --- a/src/main/java/camp/woowak/lab/web/dto/request/SignInCustomerRequest.java +++ b/src/main/java/camp/woowak/lab/web/dto/request/customer/SignInCustomerRequest.java @@ -1,4 +1,4 @@ -package camp.woowak.lab.web.dto.request; +package camp.woowak.lab.web.dto.request.customer; /** * 이메일 비밀번호 조건을 알 수 없도록 모든 요청을 받을 수 있도록 구현 From 8b53a130d6a2d3932121fb0628c8acebec6fd9d5 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 14:34:36 +0900 Subject: [PATCH 19/28] =?UTF-8?q?[feat]=20CustomerRepository.findByEmail?= =?UTF-8?q?=20=EB=B0=98=ED=99=98=EA=B0=92=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/customer/repository/CustomerRepository.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java b/src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java index f44d17be..615781b0 100644 --- a/src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java +++ b/src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java @@ -1,9 +1,11 @@ package camp.woowak.lab.customer.repository; +import java.util.Optional; + import org.springframework.data.jpa.repository.JpaRepository; import camp.woowak.lab.customer.domain.Customer; public interface CustomerRepository extends JpaRepository { - Customer findByEmail(String email); + Optional findByEmail(String email); } From dc6f58185ebc2f92e56b24f55a4be99185adb0a1 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 14:34:56 +0900 Subject: [PATCH 20/28] =?UTF-8?q?[feat]=20Customer=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=9D=B8=EC=A6=9D=20=EC=A3=BC=EC=B2=B4=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/camp/woowak/lab/customer/domain/Customer.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/camp/woowak/lab/customer/domain/Customer.java b/src/main/java/camp/woowak/lab/customer/domain/Customer.java index 4bf75642..0dc706e0 100644 --- a/src/main/java/camp/woowak/lab/customer/domain/Customer.java +++ b/src/main/java/camp/woowak/lab/customer/domain/Customer.java @@ -46,4 +46,8 @@ public Customer(String name, String email, String password, String phone, PayAcc this.phone = phone; this.payAccount = payAccount; } + + public boolean validatePassword(String password, PasswordEncoder passwordEncoder) { + return passwordEncoder.matches(password, this.password); + } } From c89d828281f3edb94cb38b9e1986f58f3c0ec976 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 14:36:22 +0900 Subject: [PATCH 21/28] =?UTF-8?q?[test]=20CustomerApiController.login=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80=20-=20Customer?= =?UTF-8?q?ApiControllerTest.testLoginCustomer:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=84=B1=EA=B3=B5=20=EC=8B=9C=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20-=20CustomerApiControllerTest.testLoginFail:=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=8B=A4=ED=8C=A8=20=EC=8B=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../customer/CustomerApiControllerTest.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/test/java/camp/woowak/lab/web/api/customer/CustomerApiControllerTest.java b/src/test/java/camp/woowak/lab/web/api/customer/CustomerApiControllerTest.java index d303ac00..f7113717 100644 --- a/src/test/java/camp/woowak/lab/web/api/customer/CustomerApiControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/customer/CustomerApiControllerTest.java @@ -3,25 +3,37 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.BDDMockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import java.util.UUID; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.mockito.BDDMockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; import com.fasterxml.jackson.databind.ObjectMapper; +import camp.woowak.lab.customer.exception.CustomerAuthenticationException; import camp.woowak.lab.customer.exception.CustomerErrorCode; import camp.woowak.lab.customer.exception.DuplicateEmailException; +import camp.woowak.lab.customer.service.SignInCustomerService; import camp.woowak.lab.customer.service.SignUpCustomerService; +import camp.woowak.lab.customer.service.command.SignInCustomerCommand; +import camp.woowak.lab.web.authentication.LoginCustomer; +import camp.woowak.lab.web.dto.request.customer.SignInCustomerRequest; import camp.woowak.lab.web.dto.request.customer.SignUpCustomerRequest; +import camp.woowak.lab.web.resolver.session.SessionConst; +import jakarta.servlet.http.HttpSession; @WebMvcTest(CustomerApiController.class) @MockBean(JpaMetamodelMappingContext.class) @@ -33,6 +45,9 @@ class CustomerApiControllerTest { @MockBean private SignUpCustomerService signUpCustomerService; + @MockBean + private SignInCustomerService signInCustomerService; + @Autowired private ObjectMapper objectMapper; @@ -215,4 +230,48 @@ void testSignUpCustomerWithDuplicateEmail() throws Exception { .andExpect(jsonPath("$.errorCode").value(CustomerErrorCode.DUPLICATE_EMAIL.getErrorCode())) .andExpect(jsonPath("$.detail").value(CustomerErrorCode.DUPLICATE_EMAIL.getMessage())); } + + @Test + @DisplayName("구매자 로그인 테스트") + void testLoginCustomer() throws Exception { + UUID fakeCustomerId = UUID.randomUUID(); + BDDMockito.given(signInCustomerService.signIn(BDDMockito.any(SignInCustomerCommand.class))) + .willReturn(fakeCustomerId); + + // when + ResultActions actions = mockMvc.perform( + post("/customers/login") + .content(new ObjectMapper().writeValueAsString( + new SignInCustomerRequest("customer@email.com", "validPassword"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isNoContent()) + .andExpect(jsonPath("$.status").value(HttpStatus.NO_CONTENT.value())) + .andExpect(result -> { + HttpSession session = result.getRequest().getSession(); + LoginCustomer loginCustomer = (LoginCustomer)session.getAttribute(SessionConst.SESSION_CUSTOMER_KEY); + Assertions.assertNotNull(loginCustomer); + Assertions.assertEquals(loginCustomer.getId(), fakeCustomerId); + }) + .andDo(print()); + } + + @Test + @DisplayName("구매자 로그인 테스트 - 로그인 실패") + void testLoginFail() throws Exception { + // given + SignInCustomerCommand command = new SignInCustomerCommand("email", "password"); + given(signInCustomerService.signIn(command)).willThrow(new CustomerAuthenticationException("invalid email")); + + // when & then + mockMvc.perform(post("/customers/login") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(new SignInCustomerRequest("email", "password")))) + .andExpect(status().isUnauthorized()) + .andExpect(jsonPath("$.errorCode").value(CustomerErrorCode.AUTHENTICATION_FAILED.getErrorCode())); + } + } From 945e0ca5844ae006de8296d2e67b1be745220619 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 14:37:01 +0900 Subject: [PATCH 22/28] =?UTF-8?q?[feat]=20CustomerApiController.login=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=ED=9B=84=20session=20=EC=97=90=20LoginCus?= =?UTF-8?q?tomer=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/customer/CustomerApiController.java | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/camp/woowak/lab/web/api/customer/CustomerApiController.java b/src/main/java/camp/woowak/lab/web/api/customer/CustomerApiController.java index 4097e2f5..58a9f51b 100644 --- a/src/main/java/camp/woowak/lab/web/api/customer/CustomerApiController.java +++ b/src/main/java/camp/woowak/lab/web/api/customer/CustomerApiController.java @@ -1,24 +1,36 @@ package camp.woowak.lab.web.api.customer; +import java.util.UUID; + import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; +import camp.woowak.lab.customer.service.SignInCustomerService; import camp.woowak.lab.customer.service.SignUpCustomerService; +import camp.woowak.lab.customer.service.command.SignInCustomerCommand; import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; +import camp.woowak.lab.web.authentication.LoginCustomer; +import camp.woowak.lab.web.dto.request.customer.SignInCustomerRequest; import camp.woowak.lab.web.dto.request.customer.SignUpCustomerRequest; +import camp.woowak.lab.web.dto.response.customer.SignInCustomerResponse; import camp.woowak.lab.web.dto.response.customer.SignUpCustomerResponse; +import camp.woowak.lab.web.resolver.session.SessionConst; import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; import jakarta.validation.Valid; @RestController public class CustomerApiController { private final SignUpCustomerService signUpCustomerService; + private final SignInCustomerService signInCustomerService; - public CustomerApiController(SignUpCustomerService signUpCustomerService) { + public CustomerApiController(SignUpCustomerService signUpCustomerService, + SignInCustomerService signInCustomerService) { this.signUpCustomerService = signUpCustomerService; + this.signInCustomerService = signInCustomerService; } @PostMapping("/customers") @@ -34,4 +46,16 @@ public SignUpCustomerResponse signUp(@Valid @RequestBody SignUpCustomerRequest r return new SignUpCustomerResponse(registeredId); } + + @PostMapping("/customers/login") + @ResponseStatus(HttpStatus.NO_CONTENT) + public SignInCustomerResponse login(@RequestBody SignInCustomerRequest request, HttpSession session) { + SignInCustomerCommand command = new SignInCustomerCommand(request.email(), request.password()); + + UUID customerId = signInCustomerService.signIn(command); + + session.setAttribute(SessionConst.SESSION_CUSTOMER_KEY, new LoginCustomer(customerId)); + + return new SignInCustomerResponse(); + } } From f8c279359581724e36c8ebd6d6414f63139a6894 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 14:37:27 +0900 Subject: [PATCH 23/28] =?UTF-8?q?[feat]=20CustomerExceptionHandler.handleC?= =?UTF-8?q?ustomerAuthenticationException=20=EC=B6=94=EA=B0=80=20-=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=8B=A4=ED=8C=A8=20=EC=8B=9C=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/web/api/customer/CustomerExceptionHandler.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/camp/woowak/lab/web/api/customer/CustomerExceptionHandler.java b/src/main/java/camp/woowak/lab/web/api/customer/CustomerExceptionHandler.java index e7fb2482..c5daf1b0 100644 --- a/src/main/java/camp/woowak/lab/web/api/customer/CustomerExceptionHandler.java +++ b/src/main/java/camp/woowak/lab/web/api/customer/CustomerExceptionHandler.java @@ -8,6 +8,7 @@ import camp.woowak.lab.common.advice.DomainExceptionHandler; import camp.woowak.lab.common.exception.BadRequestException; +import camp.woowak.lab.customer.exception.CustomerAuthenticationException; import camp.woowak.lab.customer.exception.DuplicateEmailException; import camp.woowak.lab.customer.exception.InvalidCreationException; import lombok.extern.slf4j.Slf4j; @@ -40,4 +41,13 @@ public ProblemDetail handleDuplicateEmailException(DuplicateEmailException e) { problemDetail.setProperty("errorCode", e.errorCode().getErrorCode()); return problemDetail; } + + @ExceptionHandler({CustomerAuthenticationException.class}) + @ResponseStatus(HttpStatus.UNAUTHORIZED) + public ProblemDetail handleCustomerAuthenticationException(CustomerAuthenticationException e) { + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.UNAUTHORIZED, + e.errorCode().getMessage()); + problemDetail.setProperty("errorCode", e.errorCode().getErrorCode()); + return problemDetail; + } } From ec02019bd09ab858c13aa27fcfe2219ccf3880e3 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 14:38:03 +0900 Subject: [PATCH 24/28] =?UTF-8?q?[feat]=20SignInCustomerResponse=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20CustomerApiController.login=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=EA=B0=92=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/web/dto/response/customer/SignInCustomerResponse.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/dto/response/customer/SignInCustomerResponse.java diff --git a/src/main/java/camp/woowak/lab/web/dto/response/customer/SignInCustomerResponse.java b/src/main/java/camp/woowak/lab/web/dto/response/customer/SignInCustomerResponse.java new file mode 100644 index 00000000..934fc442 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/dto/response/customer/SignInCustomerResponse.java @@ -0,0 +1,4 @@ +package camp.woowak.lab.web.dto.response.customer; + +public record SignInCustomerResponse() { +} From bc21f9b0724293d9d43493bb84ac4767e82bd653 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 14:46:44 +0900 Subject: [PATCH 25/28] =?UTF-8?q?[refactor]=20CustomerErrorCode=20Status?= =?UTF-8?q?=20=EC=B2=98=EB=A6=AC=20-=20=EA=B8=B0=EC=A1=B4=20400=20?= =?UTF-8?q?=EB=A1=9C=20=EA=B4=80=EB=A6=AC=ED=95=98=EB=8D=98=20Status=20?= =?UTF-8?q?=EB=A5=BC=20HttpStatus=20=EB=A5=BC=20=EC=9D=B4=EC=9A=A9?= =?UTF-8?q?=ED=95=B4=20=EA=B4=80=EB=A6=AC=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/customer/exception/CustomerErrorCode.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java b/src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java index 64917ca0..8b575767 100644 --- a/src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java +++ b/src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java @@ -1,17 +1,19 @@ package camp.woowak.lab.customer.exception; +import org.springframework.http.HttpStatus; + import camp.woowak.lab.common.exception.ErrorCode; public enum CustomerErrorCode implements ErrorCode { - INVALID_CREATION(400, "C1", "잘못된 요청입니다."), - DUPLICATE_EMAIL(400, "C2", "이미 존재하는 이메일입니다."), - AUTHENTICATION_FAILED(401, "C3", "이메일 또는 비밀번호가 올바르지 않습니다."); + INVALID_CREATION(HttpStatus.BAD_REQUEST, "C1", "잘못된 요청입니다."), + DUPLICATE_EMAIL(HttpStatus.BAD_REQUEST, "C2", "이미 존재하는 이메일입니다."), + AUTHENTICATION_FAILED(HttpStatus.UNAUTHORIZED, "C3", "이메일 또는 비밀번호가 올바르지 않습니다."); - private final int status; + private final HttpStatus status; private final String errorCode; private final String message; - CustomerErrorCode(int status, String errorCode, String message) { + CustomerErrorCode(HttpStatus status, String errorCode, String message) { this.status = status; this.errorCode = errorCode; this.message = message; @@ -19,7 +21,7 @@ public enum CustomerErrorCode implements ErrorCode { @Override public int getStatus() { - return status; + return status.value(); } @Override From ea691e9c8e10e92d9916d760c0bac2cc711d7ae3 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 15:01:38 +0900 Subject: [PATCH 26/28] =?UTF-8?q?[fix]=20SignInCustomerService.signIn=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95=20-=20=EB=B9=84?= =?UTF-8?q?=EB=B0=80=EB=B2=88=ED=98=B8=EA=B0=80=20=EC=9D=BC=EC=B9=98?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=84=20=EB=95=8C=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EB=8D=98=EC=A7=80=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/customer/service/SignInCustomerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java b/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java index e2eb6385..82b6f85f 100644 --- a/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java +++ b/src/main/java/camp/woowak/lab/customer/service/SignInCustomerService.java @@ -26,7 +26,7 @@ public SignInCustomerService(CustomerRepository customerRepository, PasswordEnco public UUID signIn(SignInCustomerCommand cmd) { Customer byEmail = customerRepository.findByEmail(cmd.email()) .orElseThrow(() -> new CustomerAuthenticationException("email not found")); - if (byEmail.validatePassword(cmd.password(), passwordEncoder)) { + if (!byEmail.validatePassword(cmd.password(), passwordEncoder)) { throw new CustomerAuthenticationException("password not matched"); } From 2b8fbff321ff316a9b9815aad80009ef4293ab38 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 15:02:11 +0900 Subject: [PATCH 27/28] =?UTF-8?q?[fix]=20CustomerRepository.findByEmail=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=EA=B0=92=20=EB=B3=80=EA=B2=BD=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EC=88=98=EC=A0=95=20-=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=EA=B0=92=EC=9D=84=20Optional=20=EB=A1=9C=20=EB=9E=A9?= =?UTF-8?q?=ED=95=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/customer/service/SignInCustomerServiceTest.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/java/camp/woowak/lab/customer/service/SignInCustomerServiceTest.java b/src/test/java/camp/woowak/lab/customer/service/SignInCustomerServiceTest.java index 12a03c26..80e33a26 100644 --- a/src/test/java/camp/woowak/lab/customer/service/SignInCustomerServiceTest.java +++ b/src/test/java/camp/woowak/lab/customer/service/SignInCustomerServiceTest.java @@ -3,6 +3,8 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.BDDMockito.*; +import java.util.Optional; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -40,7 +42,7 @@ void testSignIn() { PayAccount newPayAccount = new TestPayAccount(1L); Customer customer = createCustomer(newPayAccount, passwordEncoder); SignInCustomerCommand cmd = new SignInCustomerCommand(customer.getEmail(), customer.getPassword()); - given(customerRepository.findByEmail(customer.getEmail())).willReturn(customer); + given(customerRepository.findByEmail(customer.getEmail())).willReturn(Optional.of(customer)); given(passwordEncoder.matches(cmd.password(), customer.getPassword())).willReturn(true); // when & then @@ -56,7 +58,7 @@ void testSignInFailEmailNotFound() { PayAccount newPayAccount = new TestPayAccount(1L); Customer customer = createCustomer(newPayAccount, passwordEncoder); SignInCustomerCommand cmd = new SignInCustomerCommand("InvalidCustomer@email.com", customer.getPassword()); - given(customerRepository.findByEmail(cmd.email())).willReturn(null); + given(customerRepository.findByEmail(cmd.email())).willReturn(Optional.empty()); // when & then assertThrows(CustomerAuthenticationException.class, () -> signInCustomerService.signIn(cmd)); @@ -70,7 +72,7 @@ void testSignInFail() { PayAccount newPayAccount = new TestPayAccount(1L); Customer customer = createCustomer(newPayAccount, passwordEncoder); SignInCustomerCommand cmd = new SignInCustomerCommand(customer.getEmail(), customer.getPassword()); - given(customerRepository.findByEmail(customer.getEmail())).willReturn(customer); + given(customerRepository.findByEmail(customer.getEmail())).willReturn(Optional.of(customer)); given(passwordEncoder.matches(cmd.password(), customer.getPassword())).willReturn(false); // when & then From 6dbf9e428f73a866e4b8e0ac5160274f87b34893 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Thu, 15 Aug 2024 15:21:23 +0900 Subject: [PATCH 28/28] =?UTF-8?q?[refactor]=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EC=B6=9C=20-=20ProblemDetail=20?= =?UTF-8?q?=EB=A5=BC=20=EC=83=9D=EC=84=B1=ED=95=98=EB=8A=94=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EA=B0=80=20=EA=B2=B9=EC=B3=90=EC=84=9C=20private=20?= =?UTF-8?q?=EB=A9=94=EC=86=8C=EB=93=9C=EB=A1=9C=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/customer/CustomerExceptionHandler.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/main/java/camp/woowak/lab/web/api/customer/CustomerExceptionHandler.java b/src/main/java/camp/woowak/lab/web/api/customer/CustomerExceptionHandler.java index c5daf1b0..ecf63b99 100644 --- a/src/main/java/camp/woowak/lab/web/api/customer/CustomerExceptionHandler.java +++ b/src/main/java/camp/woowak/lab/web/api/customer/CustomerExceptionHandler.java @@ -8,6 +8,7 @@ import camp.woowak.lab.common.advice.DomainExceptionHandler; import camp.woowak.lab.common.exception.BadRequestException; +import camp.woowak.lab.common.exception.HttpStatusException; import camp.woowak.lab.customer.exception.CustomerAuthenticationException; import camp.woowak.lab.customer.exception.DuplicateEmailException; import camp.woowak.lab.customer.exception.InvalidCreationException; @@ -23,10 +24,7 @@ public class CustomerExceptionHandler extends ResponseEntityExceptionHandler { @ExceptionHandler({InvalidCreationException.class}) @ResponseStatus(HttpStatus.BAD_REQUEST) public ProblemDetail handleBadRequestException(BadRequestException e) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, - e.errorCode().getErrorCode()); - problemDetail.setProperty("errorCode", e.errorCode().getErrorCode()); - return problemDetail; + return getProblemDetail(e, HttpStatus.BAD_REQUEST); } /** @@ -36,17 +34,17 @@ public ProblemDetail handleBadRequestException(BadRequestException e) { @ExceptionHandler({DuplicateEmailException.class}) @ResponseStatus(HttpStatus.CONFLICT) public ProblemDetail handleDuplicateEmailException(DuplicateEmailException e) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, - e.errorCode().getMessage()); - problemDetail.setProperty("errorCode", e.errorCode().getErrorCode()); - return problemDetail; + return getProblemDetail(e, HttpStatus.CONFLICT); } @ExceptionHandler({CustomerAuthenticationException.class}) @ResponseStatus(HttpStatus.UNAUTHORIZED) public ProblemDetail handleCustomerAuthenticationException(CustomerAuthenticationException e) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.UNAUTHORIZED, - e.errorCode().getMessage()); + return getProblemDetail(e, HttpStatus.UNAUTHORIZED); + } + + private ProblemDetail getProblemDetail(HttpStatusException e, HttpStatus status) { + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(status, e.errorCode().getMessage()); problemDetail.setProperty("errorCode", e.errorCode().getErrorCode()); return problemDetail; }