From 99db493ed2b522b7d1b533b340d064ada3d7ff8e Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 16:16:52 +0900 Subject: [PATCH 001/146] =?UTF-8?q?[feat]=20Vendor=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 제약조건 설정 및 검증 로직 구현 --- .../camp/woowak/lab/vendor/domain/Vendor.java | 91 +++++++++++++++++-- .../web/authentication/PasswordEncoder.java | 7 ++ 2 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 src/main/java/camp/woowak/lab/web/authentication/PasswordEncoder.java diff --git a/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java b/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java index 41c924ce..59fc91cf 100644 --- a/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java +++ b/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java @@ -1,13 +1,92 @@ package camp.woowak.lab.vendor.domain; import camp.woowak.lab.payaccount.domain.PayAccount; -import jakarta.persistence.*; +import camp.woowak.lab.vendor.exception.InvalidCreationException; +import camp.woowak.lab.web.authentication.PasswordEncoder; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToOne; @Entity public class Vendor { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @OneToOne(fetch = FetchType.LAZY) - private PayAccount payAccount; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @Column(nullable = false, length = 50) + private String name; + @Column(unique = true, nullable = false, length = 100) + private String email; + @Column(nullable = false, length = 30) + private String password; + @Column(nullable = false, length = 30) + private String phone; + @OneToOne(fetch = FetchType.LAZY) + private PayAccount payAccount; + + protected Vendor() { + } + + public Vendor(String name, String email, String password, String phone, PayAccount payAccount, + PasswordEncoder passwordEncoder) throws InvalidCreationException { + checkName(name); + checkEmail(email); + checkPassword(password); + checkPhone(phone); + checkPayAccount(payAccount); + this.name = name; + this.email = email; + this.password = passwordEncoder.encode(password); + this.phone = phone; + this.payAccount = payAccount; + } + + public Long getId() { + return id; + } + + private void checkPayAccount(PayAccount payAccount) throws InvalidCreationException { + if (payAccount == null) { + throw new InvalidCreationException("Pay account cannot be null"); + } + } + + private void checkPhone(String phone) throws InvalidCreationException { + if (phone == null || phone.isBlank()) { + throw new InvalidCreationException("Vendor phone cannot be blank"); + } + if (phone.trim().length() > 30) { + throw new InvalidCreationException("Vendor phone cannot be longer than 30 characters"); + } + } + + private void checkPassword(String password) throws InvalidCreationException { + if (password == null || password.isBlank()) { + throw new InvalidCreationException("Vendor password cannot be blank"); + } + if (password.trim().length() > 30) { + throw new InvalidCreationException("Vendor password cannot be longer than 30 characters"); + } + } + + private void checkEmail(String email) throws InvalidCreationException { + if (email == null || email.isBlank()) { + throw new InvalidCreationException("Vendor email cannot be blank"); + } + if (email.trim().length() > 100) { + throw new InvalidCreationException("Vendor email cannot be longer than 100 characters"); + } + } + + private void checkName(String name) throws InvalidCreationException { + if (name == null || name.isBlank()) { + throw new InvalidCreationException("Vendor name cannot be blank"); + } + if (name.length() > 50) { + throw new InvalidCreationException("Vendor name cannot exceed 50 characters"); + } + } } diff --git a/src/main/java/camp/woowak/lab/web/authentication/PasswordEncoder.java b/src/main/java/camp/woowak/lab/web/authentication/PasswordEncoder.java new file mode 100644 index 00000000..b2dcb931 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/authentication/PasswordEncoder.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.web.authentication; + +public interface PasswordEncoder { + String encode(String password); + + boolean matches(String password, String encodedPassword); +} From 54ea7e9de0464206472142d11dd9ecadaf8843f9 Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 16:17:03 +0900 Subject: [PATCH 002/146] =?UTF-8?q?[fix]=20Order=20=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Order가 예약어이기 때문에 테이블 이름 변경 --- .../camp/woowak/lab/order/domain/Order.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/java/camp/woowak/lab/order/domain/Order.java b/src/main/java/camp/woowak/lab/order/domain/Order.java index 2f0a6bd7..206c0c4e 100644 --- a/src/main/java/camp/woowak/lab/order/domain/Order.java +++ b/src/main/java/camp/woowak/lab/order/domain/Order.java @@ -2,15 +2,22 @@ import camp.woowak.lab.customer.domain.Customer; import camp.woowak.lab.store.domain.Store; -import jakarta.persistence.*; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; @Entity +@Table(name = "ORDERS") public class Order { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @ManyToOne(fetch = FetchType.LAZY) - private Customer requester; - @ManyToOne(fetch = FetchType.LAZY) - private Store store; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @ManyToOne(fetch = FetchType.LAZY) + private Customer requester; + @ManyToOne(fetch = FetchType.LAZY) + private Store store; } From e7bc581dc9bd7536208915dd5fd0f9ab856e9d12 Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 16:17:43 +0900 Subject: [PATCH 003/146] =?UTF-8?q?[style]=20=EC=BD=94=EB=94=A9=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=A4=EC=85=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 개행문자를 space에서 tab으로 변경 --- .../woowak/lab/customer/domain/Customer.java | 17 ++++++++----- .../camp/woowak/lab/menu/domain/Menu.java | 17 ++++++++----- .../lab/payaccount/domain/PayAccount.java | 6 ++--- .../lab/payment/domain/PointPayment.java | 25 +++++++++++-------- .../camp/woowak/lab/store/domain/Store.java | 17 ++++++++----- 5 files changed, 51 insertions(+), 31 deletions(-) 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 d3fc6511..dcdd0fc8 100644 --- a/src/main/java/camp/woowak/lab/customer/domain/Customer.java +++ b/src/main/java/camp/woowak/lab/customer/domain/Customer.java @@ -1,13 +1,18 @@ package camp.woowak.lab.customer.domain; import camp.woowak.lab.payaccount.domain.PayAccount; -import jakarta.persistence.*; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToOne; @Entity public class Customer { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @OneToOne(fetch = FetchType.LAZY) - private PayAccount payAccount; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @OneToOne(fetch = FetchType.LAZY) + private PayAccount payAccount; } diff --git a/src/main/java/camp/woowak/lab/menu/domain/Menu.java b/src/main/java/camp/woowak/lab/menu/domain/Menu.java index efaaac92..e5985670 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/Menu.java +++ b/src/main/java/camp/woowak/lab/menu/domain/Menu.java @@ -1,13 +1,18 @@ package camp.woowak.lab.menu.domain; import camp.woowak.lab.store.domain.Store; -import jakarta.persistence.*; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; @Entity public class Menu { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @ManyToOne(fetch = FetchType.LAZY) - private Store store; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @ManyToOne(fetch = FetchType.LAZY) + private Store store; } diff --git a/src/main/java/camp/woowak/lab/payaccount/domain/PayAccount.java b/src/main/java/camp/woowak/lab/payaccount/domain/PayAccount.java index 3406a60f..cc5ff513 100644 --- a/src/main/java/camp/woowak/lab/payaccount/domain/PayAccount.java +++ b/src/main/java/camp/woowak/lab/payaccount/domain/PayAccount.java @@ -7,7 +7,7 @@ @Entity public class PayAccount { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; } diff --git a/src/main/java/camp/woowak/lab/payment/domain/PointPayment.java b/src/main/java/camp/woowak/lab/payment/domain/PointPayment.java index cee65e28..f0d46b2d 100644 --- a/src/main/java/camp/woowak/lab/payment/domain/PointPayment.java +++ b/src/main/java/camp/woowak/lab/payment/domain/PointPayment.java @@ -3,17 +3,22 @@ import camp.woowak.lab.customer.domain.Customer; import camp.woowak.lab.order.domain.Order; import camp.woowak.lab.vendor.domain.Vendor; -import jakarta.persistence.*; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; @Entity public class PointPayment { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @ManyToOne(fetch = FetchType.LAZY) - private Order order; - @ManyToOne(fetch = FetchType.LAZY) - private Customer sender; - @ManyToOne(fetch = FetchType.LAZY) - private Vendor recipient; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @ManyToOne(fetch = FetchType.LAZY) + private Order order; + @ManyToOne(fetch = FetchType.LAZY) + private Customer sender; + @ManyToOne(fetch = FetchType.LAZY) + private Vendor recipient; } diff --git a/src/main/java/camp/woowak/lab/store/domain/Store.java b/src/main/java/camp/woowak/lab/store/domain/Store.java index 9626c773..d98dfb79 100644 --- a/src/main/java/camp/woowak/lab/store/domain/Store.java +++ b/src/main/java/camp/woowak/lab/store/domain/Store.java @@ -1,13 +1,18 @@ package camp.woowak.lab.store.domain; import camp.woowak.lab.vendor.domain.Vendor; -import jakarta.persistence.*; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; @Entity public class Store { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @ManyToOne(fetch = FetchType.LAZY) - private Vendor owner; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @ManyToOne(fetch = FetchType.LAZY) + private Vendor owner; } From 82f364fe5e745cc7d814f3bbf50192fed0ebc065 Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 16:18:01 +0900 Subject: [PATCH 004/146] =?UTF-8?q?[feat]=20jpa=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `~` show-sql: 실행되는 sql 조회 `~` generate-ddl: 테스트시 테이블 자동 생성 `~` ddl-auto: 어플리케이션 생성시 생성, 종료시 삭제 `~` open-in-view: 의도하지 않은 조회 쿼리 발생 방지 --- src/main/resources/application.properties | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index cc1ad9a6..66b1c0c5 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,5 @@ spring.application.name=lab +spring.jpa.show-sql=true +spring.jpa.generate-ddl=true +spring.jpa.open-in-view=false +spring.jpa.hibernate.ddl-auto=create-drop From ed11df9ebfd6298a82e1430ef405e41094a167eb Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 16:21:40 +0900 Subject: [PATCH 005/146] [feat] SignUpVendorService MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `+` SignUpVendorCommand: 서비스 호출을 위한 command `+` NoOpPasswordEncoder: 아무런 기능을 제공하지 않는 PasswordEncoder `+` DuplicateException(및 DuplicateEmailException): unique 제약조건에 부합하지 않을 때 발생하는 예외 `+` InvalidCreationException: 기타 제약조건에 부합하지 않는 경우 발생하는 예외 --- .../repository/PayAccountRepository.java | 8 ++++ .../exception/DuplicateEmailException.java | 4 ++ .../vendor/exception/DuplicateException.java | 4 ++ .../exception/InvalidCreationException.java | 7 ++++ .../vendor/repository/VendorRepository.java | 8 ++++ .../vendor/service/SignUpVendorService.java | 42 +++++++++++++++++++ .../service/command/SignUpVendorCommand.java | 9 ++++ .../authentication/NoOpPasswordEncoder.java | 15 +++++++ .../config/AuthenticationConfig.java | 15 +++++++ 9 files changed, 112 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/payaccount/repository/PayAccountRepository.java create mode 100644 src/main/java/camp/woowak/lab/vendor/exception/DuplicateEmailException.java create mode 100644 src/main/java/camp/woowak/lab/vendor/exception/DuplicateException.java create mode 100644 src/main/java/camp/woowak/lab/vendor/exception/InvalidCreationException.java create mode 100644 src/main/java/camp/woowak/lab/vendor/repository/VendorRepository.java create mode 100644 src/main/java/camp/woowak/lab/vendor/service/SignUpVendorService.java create mode 100644 src/main/java/camp/woowak/lab/vendor/service/command/SignUpVendorCommand.java create mode 100644 src/main/java/camp/woowak/lab/web/authentication/NoOpPasswordEncoder.java create mode 100644 src/main/java/camp/woowak/lab/web/authentication/config/AuthenticationConfig.java diff --git a/src/main/java/camp/woowak/lab/payaccount/repository/PayAccountRepository.java b/src/main/java/camp/woowak/lab/payaccount/repository/PayAccountRepository.java new file mode 100644 index 00000000..1ca593af --- /dev/null +++ b/src/main/java/camp/woowak/lab/payaccount/repository/PayAccountRepository.java @@ -0,0 +1,8 @@ +package camp.woowak.lab.payaccount.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import camp.woowak.lab.payaccount.domain.PayAccount; + +public interface PayAccountRepository extends JpaRepository { +} diff --git a/src/main/java/camp/woowak/lab/vendor/exception/DuplicateEmailException.java b/src/main/java/camp/woowak/lab/vendor/exception/DuplicateEmailException.java new file mode 100644 index 00000000..e4b34724 --- /dev/null +++ b/src/main/java/camp/woowak/lab/vendor/exception/DuplicateEmailException.java @@ -0,0 +1,4 @@ +package camp.woowak.lab.vendor.exception; + +public class DuplicateEmailException extends DuplicateException { +} diff --git a/src/main/java/camp/woowak/lab/vendor/exception/DuplicateException.java b/src/main/java/camp/woowak/lab/vendor/exception/DuplicateException.java new file mode 100644 index 00000000..11599090 --- /dev/null +++ b/src/main/java/camp/woowak/lab/vendor/exception/DuplicateException.java @@ -0,0 +1,4 @@ +package camp.woowak.lab.vendor.exception; + +public abstract class DuplicateException extends Exception { +} diff --git a/src/main/java/camp/woowak/lab/vendor/exception/InvalidCreationException.java b/src/main/java/camp/woowak/lab/vendor/exception/InvalidCreationException.java new file mode 100644 index 00000000..019da917 --- /dev/null +++ b/src/main/java/camp/woowak/lab/vendor/exception/InvalidCreationException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.vendor.exception; + +public class InvalidCreationException extends Exception { + public InvalidCreationException(String message) { + super(message); + } +} diff --git a/src/main/java/camp/woowak/lab/vendor/repository/VendorRepository.java b/src/main/java/camp/woowak/lab/vendor/repository/VendorRepository.java new file mode 100644 index 00000000..8cbf9a34 --- /dev/null +++ b/src/main/java/camp/woowak/lab/vendor/repository/VendorRepository.java @@ -0,0 +1,8 @@ +package camp.woowak.lab.vendor.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import camp.woowak.lab.vendor.domain.Vendor; + +public interface VendorRepository extends JpaRepository { +} diff --git a/src/main/java/camp/woowak/lab/vendor/service/SignUpVendorService.java b/src/main/java/camp/woowak/lab/vendor/service/SignUpVendorService.java new file mode 100644 index 00000000..8db42e1d --- /dev/null +++ b/src/main/java/camp/woowak/lab/vendor/service/SignUpVendorService.java @@ -0,0 +1,42 @@ +package camp.woowak.lab.vendor.service; + +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.repository.PayAccountRepository; +import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.vendor.exception.DuplicateEmailException; +import camp.woowak.lab.vendor.exception.InvalidCreationException; +import camp.woowak.lab.vendor.repository.VendorRepository; +import camp.woowak.lab.vendor.service.command.SignUpVendorCommand; +import camp.woowak.lab.web.authentication.PasswordEncoder; + +@Service +@Transactional(rollbackFor = {InvalidCreationException.class, DuplicateEmailException.class}) +public class SignUpVendorService { + private final VendorRepository vendorRepository; + private final PayAccountRepository payAccountRepository; + private final PasswordEncoder passwordEncoder; + + public SignUpVendorService( + VendorRepository vendorRepository, PayAccountRepository payAccountRepository, PasswordEncoder passwordEncoder) { + this.vendorRepository = vendorRepository; + this.payAccountRepository = payAccountRepository; + this.passwordEncoder = passwordEncoder; + } + + public Long signUp(SignUpVendorCommand cmd) throws InvalidCreationException, DuplicateEmailException { + PayAccount newPayAccount = new PayAccount(); + payAccountRepository.save(newPayAccount); + Vendor newVendor = + new Vendor(cmd.name(), cmd.email(), cmd.password(), cmd.phone(), newPayAccount, passwordEncoder); + try { + vendorRepository.save(newVendor); + } catch (DataIntegrityViolationException e) { + throw new DuplicateEmailException(); + } + return newVendor.getId(); + } +} diff --git a/src/main/java/camp/woowak/lab/vendor/service/command/SignUpVendorCommand.java b/src/main/java/camp/woowak/lab/vendor/service/command/SignUpVendorCommand.java new file mode 100644 index 00000000..49e03095 --- /dev/null +++ b/src/main/java/camp/woowak/lab/vendor/service/command/SignUpVendorCommand.java @@ -0,0 +1,9 @@ +package camp.woowak.lab.vendor.service.command; + +public record SignUpVendorCommand( + String name, + String email, + String password, + String phone +) { +} diff --git a/src/main/java/camp/woowak/lab/web/authentication/NoOpPasswordEncoder.java b/src/main/java/camp/woowak/lab/web/authentication/NoOpPasswordEncoder.java new file mode 100644 index 00000000..3ab44bce --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/authentication/NoOpPasswordEncoder.java @@ -0,0 +1,15 @@ +package camp.woowak.lab.web.authentication; + +import java.util.Objects; + +public class NoOpPasswordEncoder implements PasswordEncoder { + @Override + public String encode(String password) { + return password; + } + + @Override + public boolean matches(String password, String encodedPassword) { + return Objects.equals(password, encodedPassword); + } +} diff --git a/src/main/java/camp/woowak/lab/web/authentication/config/AuthenticationConfig.java b/src/main/java/camp/woowak/lab/web/authentication/config/AuthenticationConfig.java new file mode 100644 index 00000000..28557cba --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/authentication/config/AuthenticationConfig.java @@ -0,0 +1,15 @@ +package camp.woowak.lab.web.authentication.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; +import camp.woowak.lab.web.authentication.PasswordEncoder; + +@Configuration +public class AuthenticationConfig { + @Bean + public PasswordEncoder passwordEncoder() { + return new NoOpPasswordEncoder(); + } +} From 03dd63c0dad0b3e181a83ed824a62cbabd43dfd2 Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 16:24:31 +0900 Subject: [PATCH 006/146] =?UTF-8?q?[feat]=20Vendor=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=EC=A0=84=EC=86=A1=20=EA=B3=84=EC=B8=B5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `+` AuthController: "/auth" 컨텍스트 처리 `+` ApiResponse: 공통 응답처리를 위한 모델 `+` ErrorCode: 공통 예외처리를 위한 코드 `+` SignUpVendorRequest: POST /auth/vendor 요청을 받는 dto --- .../woowak/lab/web/api/AuthController.java | 42 +++++++++++++++++++ .../web/dto/request/SignUpVendorRequest.java | 9 ++++ .../lab/web/dto/response/ApiResponse.java | 40 ++++++++++++++++++ .../camp/woowak/lab/web/error/ErrorCode.java | 22 ++++++++++ 4 files changed, 113 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/api/AuthController.java create mode 100644 src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java create mode 100644 src/main/java/camp/woowak/lab/web/dto/response/ApiResponse.java create mode 100644 src/main/java/camp/woowak/lab/web/error/ErrorCode.java diff --git a/src/main/java/camp/woowak/lab/web/api/AuthController.java b/src/main/java/camp/woowak/lab/web/api/AuthController.java new file mode 100644 index 00000000..933f1125 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/AuthController.java @@ -0,0 +1,42 @@ +package camp.woowak.lab.web.api; + +import java.net.URI; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import camp.woowak.lab.vendor.exception.DuplicateEmailException; +import camp.woowak.lab.vendor.exception.InvalidCreationException; +import camp.woowak.lab.vendor.service.SignUpVendorService; +import camp.woowak.lab.vendor.service.command.SignUpVendorCommand; +import camp.woowak.lab.web.dto.request.SignUpVendorRequest; +import camp.woowak.lab.web.dto.response.ApiResponse; +import camp.woowak.lab.web.error.ErrorCode; + +@RestController +@RequestMapping("/auth") +public class AuthController { + private final SignUpVendorService signUpVendorService; + + public AuthController(SignUpVendorService signUpVendorService) { + this.signUpVendorService = signUpVendorService; + } + + @PostMapping("/vendors") + public ResponseEntity signUpVendor(@RequestBody SignUpVendorRequest request) { + SignUpVendorCommand command = + new SignUpVendorCommand(request.name(), request.email(), request.password(), request.phone()); + Long registeredId; + try { + registeredId = signUpVendorService.signUp(command); + } catch (InvalidCreationException e) { + return ResponseEntity.badRequest().body(ApiResponse.error(ErrorCode.SIGNUP_INVALID_REQUEST)); + } catch (DuplicateEmailException e) { + return ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_DUPLICATE_EMAIL)); + } + return ResponseEntity.created(URI.create("/vendors/" + registeredId)).build(); + } +} diff --git a/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java new file mode 100644 index 00000000..60044894 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java @@ -0,0 +1,9 @@ +package camp.woowak.lab.web.dto.request; + +public record SignUpVendorRequest( + String name, + String email, + String password, + String phone +) { +} diff --git a/src/main/java/camp/woowak/lab/web/dto/response/ApiResponse.java b/src/main/java/camp/woowak/lab/web/dto/response/ApiResponse.java new file mode 100644 index 00000000..7f0be70f --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/dto/response/ApiResponse.java @@ -0,0 +1,40 @@ +package camp.woowak.lab.web.dto.response; + +import camp.woowak.lab.web.error.ErrorCode; + +public class ApiResponse { + private String code; + private String message; + private T data; + + private ApiResponse(String code, String message) { + this.code = code; + this.message = message; + } + + private ApiResponse(String code, String message, T data) { + this.code = code; + this.message = message; + this.data = data; + } + + public static ApiResponse ok(T data) { + return new ApiResponse<>("OK", "success", data); + } + + public static ApiResponse error(ErrorCode errorCode) { + return new ApiResponse<>(errorCode.getCode(), errorCode.getMessage()); + } + + public String getCode() { + return code; + } + + public String getMessage() { + return message; + } + + public T getData() { + return data; + } +} diff --git a/src/main/java/camp/woowak/lab/web/error/ErrorCode.java b/src/main/java/camp/woowak/lab/web/error/ErrorCode.java new file mode 100644 index 00000000..53b0e82e --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/error/ErrorCode.java @@ -0,0 +1,22 @@ +package camp.woowak.lab.web.error; + +public enum ErrorCode { + AUTH_DUPLICATE_EMAIL("a1", "이미 가입된 이메일 입니다."), + SIGNUP_INVALID_REQUEST("s1", "잘못된 요청입니다."); + + private final String code; + private final String message; + + ErrorCode(String code, String message) { + this.code = code; + this.message = message; + } + + public String getCode() { + return code; + } + + public String getMessage() { + return message; + } +} From 17a28347e709c2478ee7591b1aee4c7c505197e1 Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 16:24:59 +0900 Subject: [PATCH 007/146] =?UTF-8?q?[chore]=20.gitkeep=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/camp/woowak/lab/vendor/repository/.gitkeep | 0 src/main/java/camp/woowak/lab/vendor/service/.gitkeep | 0 src/main/java/camp/woowak/lab/web/api/.gitkeep | 0 src/main/java/camp/woowak/lab/web/authentication/.gitkeep | 0 src/main/java/camp/woowak/lab/web/dto/request/.gitkeep | 0 src/main/java/camp/woowak/lab/web/dto/response/.gitkeep | 0 6 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/vendor/repository/.gitkeep delete mode 100644 src/main/java/camp/woowak/lab/vendor/service/.gitkeep delete mode 100644 src/main/java/camp/woowak/lab/web/api/.gitkeep delete mode 100644 src/main/java/camp/woowak/lab/web/authentication/.gitkeep delete mode 100644 src/main/java/camp/woowak/lab/web/dto/request/.gitkeep delete mode 100644 src/main/java/camp/woowak/lab/web/dto/response/.gitkeep diff --git a/src/main/java/camp/woowak/lab/vendor/repository/.gitkeep b/src/main/java/camp/woowak/lab/vendor/repository/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/camp/woowak/lab/vendor/service/.gitkeep b/src/main/java/camp/woowak/lab/vendor/service/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/camp/woowak/lab/web/api/.gitkeep b/src/main/java/camp/woowak/lab/web/api/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/camp/woowak/lab/web/authentication/.gitkeep b/src/main/java/camp/woowak/lab/web/authentication/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/camp/woowak/lab/web/dto/request/.gitkeep b/src/main/java/camp/woowak/lab/web/dto/request/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/camp/woowak/lab/web/dto/response/.gitkeep b/src/main/java/camp/woowak/lab/web/dto/response/.gitkeep deleted file mode 100644 index e69de29b..00000000 From 6c2522b9ea8622b753c48dd14ca4ff0956160bc0 Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 18:29:06 +0900 Subject: [PATCH 008/146] =?UTF-8?q?[test]=20Vendor=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vendor 생성시 검증로직 테스트 코드 작성 --- .../lab/payaccount/domain/TestPayAccount.java | 14 ++ .../woowak/lab/vendor/domain/VendorTest.java | 196 ++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/payaccount/domain/TestPayAccount.java create mode 100644 src/test/java/camp/woowak/lab/vendor/domain/VendorTest.java diff --git a/src/test/java/camp/woowak/lab/payaccount/domain/TestPayAccount.java b/src/test/java/camp/woowak/lab/payaccount/domain/TestPayAccount.java new file mode 100644 index 00000000..7066928d --- /dev/null +++ b/src/test/java/camp/woowak/lab/payaccount/domain/TestPayAccount.java @@ -0,0 +1,14 @@ +package camp.woowak.lab.payaccount.domain; + +public class TestPayAccount extends PayAccount { + private Long id; + private PayAccount payAccount; + + public TestPayAccount(Long id) { + this.payAccount = payAccount; + } + + public Long getId() { + return id; + } +} diff --git a/src/test/java/camp/woowak/lab/vendor/domain/VendorTest.java b/src/test/java/camp/woowak/lab/vendor/domain/VendorTest.java new file mode 100644 index 00000000..39b77f25 --- /dev/null +++ b/src/test/java/camp/woowak/lab/vendor/domain/VendorTest.java @@ -0,0 +1,196 @@ +package camp.woowak.lab.vendor.domain; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.domain.TestPayAccount; +import camp.woowak.lab.vendor.exception.InvalidCreationException; +import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; +import camp.woowak.lab.web.authentication.PasswordEncoder; + +class VendorTest { + + private PayAccount payAccount; + private PasswordEncoder passwordEncoder; + + @BeforeEach + void setUp() { + payAccount = new TestPayAccount(1L); + passwordEncoder = new NoOpPasswordEncoder(); + } + + @Nested + @DisplayName("Vendor 생성은") + class IsConstructed { + @Nested + @DisplayName("이름이") + class NameMust { + @Test + @DisplayName("[성공] 50자까지 허용한다.") + void successWith50() { + Assertions.assertDoesNotThrow( + () -> new Vendor("aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeee", "validEmail@validEmail.com", + "validPassword", "010-0000-0000", payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] null이면 예외가 발생한다.") + void failWithNull() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor(null, "validEmail@validEmail.com", "validPassword", "010-0000-0000", payAccount, + passwordEncoder)); + } + + @Test + @DisplayName("[예외] 공란이면 예외가 발생한다.") + void failWithBlank() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor(" ", "validEmail@validEmail.com", "validPassword", "010-0000-0000", payAccount, + passwordEncoder)); + } + + @Test + @DisplayName("[예외] 50자를 초과하면 예외가 발생한다.") + void failWith51() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor("aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeef", "validEmail@validEmail.com", + "validPassword", "010-0000-0000", payAccount, passwordEncoder)); + } + } + + @Nested + @DisplayName("이메일이") + class EmailMust { + @Test + @DisplayName("[성공] 100자까지 허용한다.") + void successWith100() { + Assertions.assertDoesNotThrow( + () -> new Vendor("aaaaaaaaaa", + "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeee", + "validPassword", "010-0000-0000", payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] null이면 예외가 발생한다.") + void failWithNull() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor("aaaaaaaaaa", null, "validPassword", "010-0000-0000", payAccount, + passwordEncoder)); + } + + @Test + @DisplayName("[예외] 공란이면 예외가 발생한다.") + void failWithBlank() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor("aaaaaaaaaa", " ", "validPassword", "010-0000-0000", payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] 100자를 초과하면 예외가 발생한다.") + void failWith101() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor("aaaaaaaaaa", + "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeea", + "validPassword", "010-0000-0000", payAccount, passwordEncoder)); + } + } + + @Nested + @DisplayName("비밀번호가") + class PasswordMust { + @Test + @DisplayName("[성공] 30자까지 허용한다.") + void successWith30() { + Assertions.assertDoesNotThrow( + () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "thisstringsizeisthirtyalsnvien", + "010-0000-0000", payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] null이면 예외가 발생한다.") + void failWithNull() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", null, "010-0000-0000", payAccount, + passwordEncoder)); + } + + @Test + @DisplayName("[예외] 공란이면 예외가 발생한다.") + void failWithBlank() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", " ", "010-0000-0000", payAccount, + passwordEncoder)); + } + + @Test + @DisplayName("[예외] 30자를 초과하면 예외가 발생한다.") + void failWith31() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "thisstringsizeisthirtyonesnvien", + "010-0000-0000", payAccount, passwordEncoder)); + } + } + + @Nested + @DisplayName("전화번호가") + class PhoneMust { + @Test + @DisplayName("[성공] 30자까지 허용한다.") + void successWith30() { + Assertions.assertDoesNotThrow( + () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", + "0000000000-0000000000-00000000", + payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] null이면 예외가 발생한다.") + void failWithNull() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", null, + payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] 공란이면 예외가 발생한다.") + void failWithBlank() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", " ", + payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] 30자를 초과하면 예외가 발생한다.") + void failWith31() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", + "0000000000-0000000000-000000000", + payAccount, passwordEncoder)); + } + } + + @Nested + @DisplayName("페이계좌가") + class PayAccountMust { + @Test + @DisplayName("[성공] 있으면 성공한다.") + void successWithExist() { + Assertions.assertDoesNotThrow( + () -> new Vendor("validName", "validEmail@validEmail.com", "validPassword", "010-0000-0000", + payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] null이면 예외가 발생한다.") + void failWithNull() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", "010-0000-0000", null, + passwordEncoder)); + } + } + } +} From bcc20a3091689c9dccc4b665fb4e8ca2bbb22f53 Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 18:29:42 +0900 Subject: [PATCH 009/146] =?UTF-8?q?[test]=20Vendor=20=EB=A0=88=ED=8F=AC?= =?UTF-8?q?=EC=A7=80=ED=86=A0=EB=A6=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `+` 성공시 DB에 저장 `+` 동일한 이메일 존재시 예외 발생 --- .../woowak/lab/fixture/VendorFixture.java | 22 +++++ .../repository/VendorRepositoryTest.java | 82 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/fixture/VendorFixture.java create mode 100644 src/test/java/camp/woowak/lab/vendor/repository/VendorRepositoryTest.java diff --git a/src/test/java/camp/woowak/lab/fixture/VendorFixture.java b/src/test/java/camp/woowak/lab/fixture/VendorFixture.java new file mode 100644 index 00000000..ce05a9fb --- /dev/null +++ b/src/test/java/camp/woowak/lab/fixture/VendorFixture.java @@ -0,0 +1,22 @@ +package camp.woowak.lab.fixture; + +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.vendor.exception.InvalidCreationException; +import camp.woowak.lab.web.authentication.PasswordEncoder; + +public interface VendorFixture { + default PayAccount createPayAccount() { + return new PayAccount(); + } + + default Vendor createVendor(PayAccount payAccount, PasswordEncoder passwordEncoder) { + try { + return new Vendor("vendorName", "vendorEmail@example.com", "vendorPassword", "010-0000-0000", payAccount, + passwordEncoder); + } catch (InvalidCreationException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/test/java/camp/woowak/lab/vendor/repository/VendorRepositoryTest.java b/src/test/java/camp/woowak/lab/vendor/repository/VendorRepositoryTest.java new file mode 100644 index 00000000..173fb485 --- /dev/null +++ b/src/test/java/camp/woowak/lab/vendor/repository/VendorRepositoryTest.java @@ -0,0 +1,82 @@ +package camp.woowak.lab.vendor.repository; + +import java.util.Optional; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.dao.DataIntegrityViolationException; + +import camp.woowak.lab.fixture.VendorFixture; +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.repository.PayAccountRepository; +import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; +import camp.woowak.lab.web.authentication.PasswordEncoder; + +@DataJpaTest +class VendorRepositoryTest implements VendorFixture { + @Autowired + private VendorRepository vendorRepository; + @Autowired + private PayAccountRepository payAccountRepository; + @Autowired + private PasswordEncoder passwordEncoder; + + @TestConfiguration + static class TestContextConfiguration { + @Bean + public PasswordEncoder passwordEncoder() { + return new NoOpPasswordEncoder(); + } + } + + @AfterEach + void tearDown() { + vendorRepository.deleteAll(); + } + + @Nested + @DisplayName("Vendor 저장은") + class IsSaved { + @Test + @DisplayName("[성공] DB에 저장된다.") + void success() { + // given + PayAccount payAccount = payAccountRepository.save(createPayAccount()); + + // when + Vendor vendor = createVendor(payAccount, passwordEncoder); + Vendor savedVendor = vendorRepository.save(vendor); + Long savedVendorId = savedVendor.getId(); + vendorRepository.flush(); + + // then + Optional findVendor = vendorRepository.findById(savedVendorId); + Assertions.assertTrue(findVendor.isPresent()); + Assertions.assertEquals(savedVendorId, findVendor.get().getId()); + } + + @Test + @DisplayName("[예외] 중복된 이메일이 있으면 예외가 발생한다.") + void failWithDuplicateEmail() { + // given + PayAccount payAccount = payAccountRepository.save(createPayAccount()); + Vendor vendor = createVendor(payAccount, passwordEncoder); + vendorRepository.saveAndFlush(vendor); + + // when + PayAccount newPayAccount = payAccountRepository.save(createPayAccount()); + Vendor newVendor = createVendor(newPayAccount, passwordEncoder); + + // then + Assertions.assertThrows(DataIntegrityViolationException.class, () -> vendorRepository.save(newVendor)); + } + } +} From 17a4cc8d1319d93797031af8424c319a3dd1f8c1 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sat, 10 Aug 2024 19:59:39 +0900 Subject: [PATCH 010/146] =?UTF-8?q?[chore]=20.gitkeep=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/camp/woowak/lab/customer/domain/.gitkeep | 0 src/main/java/camp/woowak/lab/customer/repository/.gitkeep | 0 src/main/java/camp/woowak/lab/customer/service/.gitkeep | 0 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/customer/domain/.gitkeep delete mode 100644 src/main/java/camp/woowak/lab/customer/repository/.gitkeep delete mode 100644 src/main/java/camp/woowak/lab/customer/service/.gitkeep diff --git a/src/main/java/camp/woowak/lab/customer/domain/.gitkeep b/src/main/java/camp/woowak/lab/customer/domain/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/camp/woowak/lab/customer/repository/.gitkeep b/src/main/java/camp/woowak/lab/customer/repository/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/camp/woowak/lab/customer/service/.gitkeep b/src/main/java/camp/woowak/lab/customer/service/.gitkeep deleted file mode 100644 index e69de29b..00000000 From 38c81a25f69e2dddcf1510e31482e6eadd7bffca Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sat, 10 Aug 2024 20:10:36 +0900 Subject: [PATCH 011/146] =?UTF-8?q?[feat]=20PasswordEncoder=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 - NoOpPasswordEncoder: 아무런 기능을 제공하지 않는 PasswordEncoder --- .../web/authentication/NoOpPasswordEncoder.java | 15 +++++++++++++++ .../lab/web/authentication/PasswordEncoder.java | 7 +++++++ .../config/AuthenticationConfig.java | 15 +++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/authentication/NoOpPasswordEncoder.java create mode 100644 src/main/java/camp/woowak/lab/web/authentication/PasswordEncoder.java create mode 100644 src/main/java/camp/woowak/lab/web/authentication/config/AuthenticationConfig.java diff --git a/src/main/java/camp/woowak/lab/web/authentication/NoOpPasswordEncoder.java b/src/main/java/camp/woowak/lab/web/authentication/NoOpPasswordEncoder.java new file mode 100644 index 00000000..0d685015 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/authentication/NoOpPasswordEncoder.java @@ -0,0 +1,15 @@ +package camp.woowak.lab.web.authentication; + +import java.util.Objects; + +public class NoOpPasswordEncoder implements PasswordEncoder { + @Override + public String encode(String password) { + return password; + } + + @Override + public boolean matches(String password, String encodedPassword) { + return Objects.equals(password, encodedPassword); + } +} \ No newline at end of file diff --git a/src/main/java/camp/woowak/lab/web/authentication/PasswordEncoder.java b/src/main/java/camp/woowak/lab/web/authentication/PasswordEncoder.java new file mode 100644 index 00000000..d039c949 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/authentication/PasswordEncoder.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.web.authentication; + +public interface PasswordEncoder { + String encode(String password); + + boolean matches(String password, String encodedPassword); +} \ No newline at end of file diff --git a/src/main/java/camp/woowak/lab/web/authentication/config/AuthenticationConfig.java b/src/main/java/camp/woowak/lab/web/authentication/config/AuthenticationConfig.java new file mode 100644 index 00000000..4f40bd1f --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/authentication/config/AuthenticationConfig.java @@ -0,0 +1,15 @@ +package camp.woowak.lab.web.authentication.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; +import camp.woowak.lab.web.authentication.PasswordEncoder; + +@Configuration +public class AuthenticationConfig { + @Bean + public PasswordEncoder passwordEncoder() { + return new NoOpPasswordEncoder(); + } +} \ No newline at end of file From deb1f8b9934e03031fb1e299e9a86c3e980002a9 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sat, 10 Aug 2024 20:11:24 +0900 Subject: [PATCH 012/146] =?UTF-8?q?[feat]=20Vendor=20CustomException=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20DuplicateException:=20unique=20?= =?UTF-8?q?=EC=A0=9C=EC=95=BD=EC=A1=B0=EA=B1=B4=EC=97=90=20=EB=B6=80?= =?UTF-8?q?=ED=95=A9=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=84=20=EB=95=8C=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?=20InvalidCreationException:=20=EA=B8=B0=ED=83=80=20=EC=A0=9C?= =?UTF-8?q?=EC=95=BD=EC=A1=B0=EA=B1=B4=EC=97=90=20=EB=B6=80=ED=95=A9?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94=20=EC=98=88=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/customer/exception/DuplicateEmailException.java | 4 ++++ .../woowak/lab/customer/exception/DuplicateException.java | 4 ++++ .../lab/customer/exception/InvalidCreationException.java | 7 +++++++ 3 files changed, 15 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/customer/exception/DuplicateEmailException.java create mode 100644 src/main/java/camp/woowak/lab/customer/exception/DuplicateException.java create mode 100644 src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java diff --git a/src/main/java/camp/woowak/lab/customer/exception/DuplicateEmailException.java b/src/main/java/camp/woowak/lab/customer/exception/DuplicateEmailException.java new file mode 100644 index 00000000..4614a21b --- /dev/null +++ b/src/main/java/camp/woowak/lab/customer/exception/DuplicateEmailException.java @@ -0,0 +1,4 @@ +package camp.woowak.lab.customer.exception; + +public class DuplicateEmailException extends DuplicateException { +} diff --git a/src/main/java/camp/woowak/lab/customer/exception/DuplicateException.java b/src/main/java/camp/woowak/lab/customer/exception/DuplicateException.java new file mode 100644 index 00000000..a6364e76 --- /dev/null +++ b/src/main/java/camp/woowak/lab/customer/exception/DuplicateException.java @@ -0,0 +1,4 @@ +package camp.woowak.lab.customer.exception; + +public abstract class DuplicateException extends Exception { +} diff --git a/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java b/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java new file mode 100644 index 00000000..bdfc625a --- /dev/null +++ b/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.customer.exception; + +public class InvalidCreationException extends Exception { + public InvalidCreationException(String message) { + super(message); + } +} From 030a8c0d7f6ac071057c7786eb36c40079896f95 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sat, 10 Aug 2024 20:11:51 +0900 Subject: [PATCH 013/146] =?UTF-8?q?[feat]=20PayAccountRepository=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 구매자 회원가입에 필요해 미리 구현 --- .../lab/payaccount/repository/PayAccountRepository.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/payaccount/repository/PayAccountRepository.java diff --git a/src/main/java/camp/woowak/lab/payaccount/repository/PayAccountRepository.java b/src/main/java/camp/woowak/lab/payaccount/repository/PayAccountRepository.java new file mode 100644 index 00000000..6feb2c36 --- /dev/null +++ b/src/main/java/camp/woowak/lab/payaccount/repository/PayAccountRepository.java @@ -0,0 +1,8 @@ +package camp.woowak.lab.payaccount.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import camp.woowak.lab.payaccount.domain.PayAccount; + +public interface PayAccountRepository extends JpaRepository { +} \ No newline at end of file From bffe230d4ccfa30936b6a24e3f00ee114f1a5af2 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sat, 10 Aug 2024 20:13:44 +0900 Subject: [PATCH 014/146] [test] SignUpCustomerServiceTest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 구매자 회원가입 테스트 구현 - 정상 회원가입 테스트 - 중복 이메일 회원가입 불가 테스트 --- .../service/SignUpCustomerServiceTest.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java diff --git a/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java new file mode 100644 index 00000000..9727de50 --- /dev/null +++ b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java @@ -0,0 +1,56 @@ +package camp.woowak.lab.customer.service; + +import static org.junit.jupiter.api.Assertions.*; + +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.context.SpringBootTest; + +import camp.woowak.lab.customer.domain.Customer; +import camp.woowak.lab.customer.exception.DuplicateEmailException; +import camp.woowak.lab.customer.exception.InvalidCreationException; +import camp.woowak.lab.customer.repository.CustomerRepository; +import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; + +@SpringBootTest +class SignUpCustomerServiceTest { + + @Autowired + SignUpCustomerService signUpCustomerService; + + @Autowired + CustomerRepository customerRepository; + + @BeforeEach + void setUp() { + customerRepository.deleteAll(); + } + + @Test + @DisplayName("구매자 회원가입 테스트") + void testSignUp() throws InvalidCreationException, DuplicateEmailException { + SignUpCustomerCommand cmd = new SignUpCustomerCommand("name", "email", "password", "phone"); + + Long id = signUpCustomerService.signUp(cmd); + + Customer customer = customerRepository.findById(id).orElseThrow(); + + assertEquals("name", customer.getName()); + assertEquals("email", customer.getEmail()); + assertEquals("password", customer.getPassword()); + assertEquals("phone", customer.getPhone()); + } + + @Test + @DisplayName("구매자 이메일 중복 회원가입 테스트") + void testSignUpWithExistingEmail() { + SignUpCustomerCommand cmd = new SignUpCustomerCommand("name", "email", "password", "phone"); + + assertThrows(DuplicateEmailException.class, () -> { + signUpCustomerService.signUp(cmd); + signUpCustomerService.signUp(cmd); + }); + } +} \ No newline at end of file From 0313777234372f5d903d4d70ecfc12a24bcef0fb Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sat, 10 Aug 2024 20:14:54 +0900 Subject: [PATCH 015/146] =?UTF-8?q?[feat]=20Customer=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=EC=A1=B0=EA=B1=B4=EC=97=90=20=EB=A7=9E?= =?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 - 이름, 이메일, 비밀번호, 전화번호 필드 추가 - 필드 검증 메서드 추가 --- .../woowak/lab/customer/domain/Customer.java | 91 +++++++++++++++++-- 1 file changed, 85 insertions(+), 6 deletions(-) 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 d3fc6511..13fda5f6 100644 --- a/src/main/java/camp/woowak/lab/customer/domain/Customer.java +++ b/src/main/java/camp/woowak/lab/customer/domain/Customer.java @@ -1,13 +1,92 @@ package camp.woowak.lab.customer.domain; +import camp.woowak.lab.customer.exception.InvalidCreationException; import camp.woowak.lab.payaccount.domain.PayAccount; -import jakarta.persistence.*; +import camp.woowak.lab.web.authentication.PasswordEncoder; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToOne; +import lombok.Getter; @Entity +@Getter public class Customer { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @OneToOne(fetch = FetchType.LAZY) - private PayAccount payAccount; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + @Column(nullable = false, length = 50) + private String name; + @Column(unique = true, nullable = false, length = 100) + private String email; + @Column(nullable = false, length = 30) + private String password; + @Column(nullable = false, length = 30) + private String phone; + @OneToOne(fetch = FetchType.LAZY) + private PayAccount payAccount; + + public Customer() { + } + + public Customer(String name, String email, String password, String phone, PayAccount payAccount, + PasswordEncoder passwordEncoder) throws + InvalidCreationException { + checkName(name); + checkEmail(email); + checkPassword(password); + checkPhone(phone); + checkPayAccount(payAccount); + this.name = name; + this.email = email; + this.password = passwordEncoder.encode(password); + this.phone = phone; + this.payAccount = payAccount; + } + + private void checkPayAccount(PayAccount payAccount) throws InvalidCreationException { + if (payAccount == null) { + throw new InvalidCreationException("Pay account cannot be null"); + } + } + + private void checkPhone(String phone) throws InvalidCreationException { + if (phone == null || phone.isBlank()) { + throw new InvalidCreationException("Vendor phone cannot be blank"); + } + if (phone.trim().length() > 30) { + throw new InvalidCreationException("Vendor phone cannot be longer than 30 characters"); + } + } + + private void checkPassword(String password) throws InvalidCreationException { + if (password == null || password.isBlank()) { + throw new InvalidCreationException("Vendor password cannot be blank"); + } + if (password.trim().length() > 30) { + throw new InvalidCreationException("Vendor password cannot be longer than 30 characters"); + } + } + + private void checkEmail(String email) throws InvalidCreationException { + if (email == null || email.isBlank()) { + throw new InvalidCreationException("Vendor email cannot be blank"); + } + if (email.trim().length() > 100) { + throw new InvalidCreationException("Vendor email cannot be longer than 100 characters"); + } + } + + private void checkName(String name) throws InvalidCreationException { + if (name == null || name.isBlank()) { + throw new InvalidCreationException("Vendor name cannot be blank"); + } + if (name.length() > 50) { + throw new InvalidCreationException("Vendor name cannot exceed 50 characters"); + } + } + } From d7482dc2f3111c465221523c12dafc9408bdfa27 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sat, 10 Aug 2024 20:15:45 +0900 Subject: [PATCH 016/146] =?UTF-8?q?[feat]=20CustomerRepository=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 구매자 영속화를 위한 Repository 인터페이스 구현 --- .../lab/customer/repository/CustomerRepository.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java diff --git a/src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java b/src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java new file mode 100644 index 00000000..9b8e9bc4 --- /dev/null +++ b/src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java @@ -0,0 +1,10 @@ +package camp.woowak.lab.customer.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import camp.woowak.lab.customer.domain.Customer; + +@Repository +public interface CustomerRepository extends JpaRepository { +} From 8a9470120b260423a72764305119003eefe53d4b Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sat, 10 Aug 2024 20:16:35 +0900 Subject: [PATCH 017/146] =?UTF-8?q?[feat]=20SignUpCustomerCommand=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SignUpCustomerService.signUp 파라미터 구현 --- .../lab/customer/service/command/SignUpCustomerCommand.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/customer/service/command/SignUpCustomerCommand.java diff --git a/src/main/java/camp/woowak/lab/customer/service/command/SignUpCustomerCommand.java b/src/main/java/camp/woowak/lab/customer/service/command/SignUpCustomerCommand.java new file mode 100644 index 00000000..d59b8160 --- /dev/null +++ b/src/main/java/camp/woowak/lab/customer/service/command/SignUpCustomerCommand.java @@ -0,0 +1,4 @@ +package camp.woowak.lab.customer.service.command; + +public record SignUpCustomerCommand(String name, String email, String password, String phone) { +} From 04f61a0fa99a65f32344b0c22a55e93d3413e569 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sat, 10 Aug 2024 20:17:11 +0900 Subject: [PATCH 018/146] =?UTF-8?q?[feat]=20SignUpCustomerService=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 구매자 회원가입 구현 --- .../service/SignUpCustomerService.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java diff --git a/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java b/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java new file mode 100644 index 00000000..be5cd040 --- /dev/null +++ b/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java @@ -0,0 +1,42 @@ +package camp.woowak.lab.customer.service; + +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.stereotype.Service; + +import camp.woowak.lab.customer.domain.Customer; +import camp.woowak.lab.customer.exception.DuplicateEmailException; +import camp.woowak.lab.customer.exception.InvalidCreationException; +import camp.woowak.lab.customer.repository.CustomerRepository; +import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.repository.PayAccountRepository; +import camp.woowak.lab.web.authentication.PasswordEncoder; + +@Service +public class SignUpCustomerService { + private final CustomerRepository customerRepository; + private final PayAccountRepository payAccountRepository; + private final PasswordEncoder passwordEncoder; + + public SignUpCustomerService(CustomerRepository customerRepository, PayAccountRepository payAccountRepository, + PasswordEncoder passwordEncoder) { + this.customerRepository = customerRepository; + this.payAccountRepository = payAccountRepository; + this.passwordEncoder = passwordEncoder; + } + + public Long signUp(SignUpCustomerCommand cmd) throws InvalidCreationException, DuplicateEmailException { + PayAccount payAccount = new PayAccount(); + payAccountRepository.save(payAccount); + + Customer newCustomer = new Customer(cmd.name(), cmd.email(), cmd.password(), cmd.phone(), payAccount, + passwordEncoder); + + try { + customerRepository.save(newCustomer); + } catch (DataIntegrityViolationException e) { + throw new DuplicateEmailException(); + } + return newCustomer.getId(); + } +} From 29006814b4b99f66271beaffa0ee85040d32ef7f Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 16:24:31 +0900 Subject: [PATCH 019/146] =?UTF-8?q?[feat]=20Vendor=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=EC=A0=84=EC=86=A1=20=EA=B3=84=EC=B8=B5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `+` AuthController: "/auth" 컨텍스트 처리 `+` ApiResponse: 공통 응답처리를 위한 모델 `+` ErrorCode: 공통 예외처리를 위한 코드 `+` SignUpVendorRequest: POST /auth/vendor 요청을 받는 dto --- .../woowak/lab/web/api/AuthController.java | 42 +++++++++++++++++++ .../web/dto/request/SignUpVendorRequest.java | 9 ++++ .../lab/web/dto/response/ApiResponse.java | 40 ++++++++++++++++++ .../camp/woowak/lab/web/error/ErrorCode.java | 22 ++++++++++ 4 files changed, 113 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/api/AuthController.java create mode 100644 src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java create mode 100644 src/main/java/camp/woowak/lab/web/dto/response/ApiResponse.java create mode 100644 src/main/java/camp/woowak/lab/web/error/ErrorCode.java diff --git a/src/main/java/camp/woowak/lab/web/api/AuthController.java b/src/main/java/camp/woowak/lab/web/api/AuthController.java new file mode 100644 index 00000000..933f1125 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/AuthController.java @@ -0,0 +1,42 @@ +package camp.woowak.lab.web.api; + +import java.net.URI; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import camp.woowak.lab.vendor.exception.DuplicateEmailException; +import camp.woowak.lab.vendor.exception.InvalidCreationException; +import camp.woowak.lab.vendor.service.SignUpVendorService; +import camp.woowak.lab.vendor.service.command.SignUpVendorCommand; +import camp.woowak.lab.web.dto.request.SignUpVendorRequest; +import camp.woowak.lab.web.dto.response.ApiResponse; +import camp.woowak.lab.web.error.ErrorCode; + +@RestController +@RequestMapping("/auth") +public class AuthController { + private final SignUpVendorService signUpVendorService; + + public AuthController(SignUpVendorService signUpVendorService) { + this.signUpVendorService = signUpVendorService; + } + + @PostMapping("/vendors") + public ResponseEntity signUpVendor(@RequestBody SignUpVendorRequest request) { + SignUpVendorCommand command = + new SignUpVendorCommand(request.name(), request.email(), request.password(), request.phone()); + Long registeredId; + try { + registeredId = signUpVendorService.signUp(command); + } catch (InvalidCreationException e) { + return ResponseEntity.badRequest().body(ApiResponse.error(ErrorCode.SIGNUP_INVALID_REQUEST)); + } catch (DuplicateEmailException e) { + return ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_DUPLICATE_EMAIL)); + } + return ResponseEntity.created(URI.create("/vendors/" + registeredId)).build(); + } +} diff --git a/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java new file mode 100644 index 00000000..60044894 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java @@ -0,0 +1,9 @@ +package camp.woowak.lab.web.dto.request; + +public record SignUpVendorRequest( + String name, + String email, + String password, + String phone +) { +} diff --git a/src/main/java/camp/woowak/lab/web/dto/response/ApiResponse.java b/src/main/java/camp/woowak/lab/web/dto/response/ApiResponse.java new file mode 100644 index 00000000..7f0be70f --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/dto/response/ApiResponse.java @@ -0,0 +1,40 @@ +package camp.woowak.lab.web.dto.response; + +import camp.woowak.lab.web.error.ErrorCode; + +public class ApiResponse { + private String code; + private String message; + private T data; + + private ApiResponse(String code, String message) { + this.code = code; + this.message = message; + } + + private ApiResponse(String code, String message, T data) { + this.code = code; + this.message = message; + this.data = data; + } + + public static ApiResponse ok(T data) { + return new ApiResponse<>("OK", "success", data); + } + + public static ApiResponse error(ErrorCode errorCode) { + return new ApiResponse<>(errorCode.getCode(), errorCode.getMessage()); + } + + public String getCode() { + return code; + } + + public String getMessage() { + return message; + } + + public T getData() { + return data; + } +} diff --git a/src/main/java/camp/woowak/lab/web/error/ErrorCode.java b/src/main/java/camp/woowak/lab/web/error/ErrorCode.java new file mode 100644 index 00000000..53b0e82e --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/error/ErrorCode.java @@ -0,0 +1,22 @@ +package camp.woowak.lab.web.error; + +public enum ErrorCode { + AUTH_DUPLICATE_EMAIL("a1", "이미 가입된 이메일 입니다."), + SIGNUP_INVALID_REQUEST("s1", "잘못된 요청입니다."); + + private final String code; + private final String message; + + ErrorCode(String code, String message) { + this.code = code; + this.message = message; + } + + public String getCode() { + return code; + } + + public String getMessage() { + return message; + } +} From 4d6a20cdf5a1dc366daa18f926121c436ca5cbdf Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sat, 10 Aug 2024 20:57:21 +0900 Subject: [PATCH 020/146] =?UTF-8?q?[feat]=20SignUpCustomerRequest=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 구매자 회원가입 요청 DTO 생성 --- .../lab/web/dto/request/SignUpCustomerRequest.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java diff --git a/src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java new file mode 100644 index 00000000..4f1e877c --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java @@ -0,0 +1,9 @@ +package camp.woowak.lab.web.dto.request; + +public record SignUpCustomerRequest( + String name, + String email, + String password, + String phone +) { +} From f93f83d940e5ea536ffcc7aefef9bea204cab80c Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sat, 10 Aug 2024 20:58:00 +0900 Subject: [PATCH 021/146] =?UTF-8?q?[feat]=20AuthController.signUpCustomer?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 구매자 회원가입 API 구현 --- .../woowak/lab/web/api/AuthController.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/camp/woowak/lab/web/api/AuthController.java b/src/main/java/camp/woowak/lab/web/api/AuthController.java index 933f1125..59b67e7d 100644 --- a/src/main/java/camp/woowak/lab/web/api/AuthController.java +++ b/src/main/java/camp/woowak/lab/web/api/AuthController.java @@ -8,10 +8,13 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import camp.woowak.lab.customer.service.SignUpCustomerService; +import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; import camp.woowak.lab.vendor.exception.DuplicateEmailException; import camp.woowak.lab.vendor.exception.InvalidCreationException; import camp.woowak.lab.vendor.service.SignUpVendorService; import camp.woowak.lab.vendor.service.command.SignUpVendorCommand; +import camp.woowak.lab.web.dto.request.SignUpCustomerRequest; import camp.woowak.lab.web.dto.request.SignUpVendorRequest; import camp.woowak.lab.web.dto.response.ApiResponse; import camp.woowak.lab.web.error.ErrorCode; @@ -20,9 +23,11 @@ @RequestMapping("/auth") public class AuthController { private final SignUpVendorService signUpVendorService; + private final SignUpCustomerService signUpCustomerService; - public AuthController(SignUpVendorService signUpVendorService) { + public AuthController(SignUpVendorService signUpVendorService, SignUpCustomerService signUpCustomerService) { this.signUpVendorService = signUpVendorService; + this.signUpCustomerService = signUpCustomerService; } @PostMapping("/vendors") @@ -39,4 +44,19 @@ public ResponseEntity signUpVendor(@RequestBody SignUpVendorRequest request) } return ResponseEntity.created(URI.create("/vendors/" + registeredId)).build(); } + + @PostMapping("/customers") + public ResponseEntity signUpCustomer(@RequestBody SignUpCustomerRequest request) { + SignUpCustomerCommand command = + new SignUpCustomerCommand(request.name(), request.email(), request.password(), request.phone()); + Long registeredId; + try { + registeredId = signUpCustomerService.signUp(command); + } catch (camp.woowak.lab.customer.exception.InvalidCreationException e) { + return ResponseEntity.badRequest().body(ApiResponse.error(ErrorCode.SIGNUP_INVALID_REQUEST)); + } catch (camp.woowak.lab.customer.exception.DuplicateEmailException e) { + return ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_DUPLICATE_EMAIL)); + } + return ResponseEntity.created(URI.create("/customers/" + registeredId)).build(); + } } From a0a49f37dcdc55be4de65d75fac6a6715f3fbf20 Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 22:09:34 +0900 Subject: [PATCH 022/146] =?UTF-8?q?[test]=20Vendor=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `+` 성공시 vendorReposity/payAccountRepository의 save 호출 `+` 실패시 DuplicateEmailException 발생 --- .../service/SignUpVendorServiceTest.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/vendor/service/SignUpVendorServiceTest.java diff --git a/src/test/java/camp/woowak/lab/vendor/service/SignUpVendorServiceTest.java b/src/test/java/camp/woowak/lab/vendor/service/SignUpVendorServiceTest.java new file mode 100644 index 00000000..711ae8c2 --- /dev/null +++ b/src/test/java/camp/woowak/lab/vendor/service/SignUpVendorServiceTest.java @@ -0,0 +1,75 @@ +package camp.woowak.lab.vendor.service; + +import static org.mockito.BDDMockito.*; + +import org.junit.jupiter.api.Assertions; +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.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.dao.DataIntegrityViolationException; + +import camp.woowak.lab.fixture.VendorFixture; +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.repository.PayAccountRepository; +import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.vendor.exception.DuplicateEmailException; +import camp.woowak.lab.vendor.exception.DuplicateException; +import camp.woowak.lab.vendor.exception.InvalidCreationException; +import camp.woowak.lab.vendor.repository.VendorRepository; +import camp.woowak.lab.vendor.service.command.SignUpVendorCommand; +import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; +import camp.woowak.lab.web.authentication.PasswordEncoder; + +@ExtendWith(MockitoExtension.class) +class SignUpVendorServiceTest implements VendorFixture { + @InjectMocks + private SignUpVendorService service; + @Mock + private VendorRepository vendorRepository; + @Mock + private PayAccountRepository payAccountRepository; + @Mock + private PasswordEncoder passwordEncoder; + + @Test + @DisplayName("[성공] Vendor가 저장된다.") + void success() throws InvalidCreationException, DuplicateEmailException { + // given + given(passwordEncoder.encode(Mockito.anyString())).willReturn("password"); + PayAccount payAccount = createPayAccount(); + Vendor vendor = createVendor(payAccount, new NoOpPasswordEncoder()); + given(payAccountRepository.save(Mockito.any(PayAccount.class))).willReturn(payAccount); + given(vendorRepository.save(Mockito.any(Vendor.class))).willReturn(vendor); + + // when + SignUpVendorCommand command = + new SignUpVendorCommand("vendorName", "vendorEmail@example.com", "password", "010-0000-0000"); + service.signUp(command); + + // then + then(payAccountRepository).should().save(Mockito.any(PayAccount.class)); + then(vendorRepository).should().save(Mockito.any(Vendor.class)); + } + + @Test + @DisplayName("[예외] 가입된 이메일인 경우 예외 발생") + void failWithDuplicateEmail() throws InvalidCreationException, DuplicateEmailException { + // given + given(passwordEncoder.encode(Mockito.anyString())).willReturn("password"); + given(payAccountRepository.save(Mockito.any(PayAccount.class))).willReturn(createPayAccount()); + + // when + when(vendorRepository.save(Mockito.any(Vendor.class))).thenThrow(DataIntegrityViolationException.class); + SignUpVendorCommand command = + new SignUpVendorCommand("vendorName", "vendorEmail@example.com", "password", "010-0000-0000"); + + // then + Assertions.assertThrows(DuplicateException.class, () -> service.signUp(command)); + then(payAccountRepository).should().save(Mockito.any(PayAccount.class)); + then(vendorRepository).should().save(Mockito.any(Vendor.class)); + } +} From db202b2baabb39571dc44a3c51a799b3742f9f6f Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 22:53:29 +0900 Subject: [PATCH 023/146] =?UTF-8?q?[fix]=20Vendor=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `~` /auth/vendors -> /vendors `~` 예외처리 rfc7807에 부합하게 변경 --- .../lab/web/api/GlobalExceptionHandler.java | 9 +++++++++ ...{AuthController.java => VendorController.java} | 15 +++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 src/main/java/camp/woowak/lab/web/api/GlobalExceptionHandler.java rename src/main/java/camp/woowak/lab/web/api/{AuthController.java => VendorController.java} (73%) diff --git a/src/main/java/camp/woowak/lab/web/api/GlobalExceptionHandler.java b/src/main/java/camp/woowak/lab/web/api/GlobalExceptionHandler.java new file mode 100644 index 00000000..fe0ac45b --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/GlobalExceptionHandler.java @@ -0,0 +1,9 @@ +package camp.woowak.lab.web.api; + +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +@RestControllerAdvice +public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { + +} diff --git a/src/main/java/camp/woowak/lab/web/api/AuthController.java b/src/main/java/camp/woowak/lab/web/api/VendorController.java similarity index 73% rename from src/main/java/camp/woowak/lab/web/api/AuthController.java rename to src/main/java/camp/woowak/lab/web/api/VendorController.java index 933f1125..a2e8fe03 100644 --- a/src/main/java/camp/woowak/lab/web/api/AuthController.java +++ b/src/main/java/camp/woowak/lab/web/api/VendorController.java @@ -2,10 +2,11 @@ import java.net.URI; +import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import camp.woowak.lab.vendor.exception.DuplicateEmailException; @@ -15,25 +16,27 @@ import camp.woowak.lab.web.dto.request.SignUpVendorRequest; import camp.woowak.lab.web.dto.response.ApiResponse; import camp.woowak.lab.web.error.ErrorCode; +import jakarta.validation.Valid; @RestController -@RequestMapping("/auth") -public class AuthController { +public class VendorController { private final SignUpVendorService signUpVendorService; - public AuthController(SignUpVendorService signUpVendorService) { + public VendorController(SignUpVendorService signUpVendorService) { this.signUpVendorService = signUpVendorService; } @PostMapping("/vendors") - public ResponseEntity signUpVendor(@RequestBody SignUpVendorRequest request) { + public ResponseEntity signUpVendor(@Valid @RequestBody SignUpVendorRequest request) { SignUpVendorCommand command = new SignUpVendorCommand(request.name(), request.email(), request.password(), request.phone()); Long registeredId; try { registeredId = signUpVendorService.signUp(command); } catch (InvalidCreationException e) { - return ResponseEntity.badRequest().body(ApiResponse.error(ErrorCode.SIGNUP_INVALID_REQUEST)); + return ResponseEntity.badRequest() + .body(ProblemDetail.forStatusAndDetail( + HttpStatus.BAD_REQUEST, ErrorCode.SIGNUP_INVALID_REQUEST.getMessage())); } catch (DuplicateEmailException e) { return ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_DUPLICATE_EMAIL)); } From dc518296c03eb55940a6d8c6018a9e3e2c838a43 Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 23:05:10 +0900 Subject: [PATCH 024/146] =?UTF-8?q?[feat]=20Phone=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 전화번호를 검증하기 위한 어노테이션 및 커스텀 Validator 구현 --- .../web/dto/request/SignUpVendorRequest.java | 9 ++++++++ .../lab/web/validation/annotation/Phone.java | 21 +++++++++++++++++++ .../validator/PhoneNumberValidator.java | 17 +++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/validation/annotation/Phone.java create mode 100644 src/main/java/camp/woowak/lab/web/validation/validator/PhoneNumberValidator.java diff --git a/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java index 60044894..00cbe2ab 100644 --- a/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java +++ b/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java @@ -1,9 +1,18 @@ package camp.woowak.lab.web.dto.request; +import org.hibernate.validator.constraints.Length; + +import camp.woowak.lab.web.validation.annotation.Phone; +import jakarta.validation.constraints.Email; + public record SignUpVendorRequest( + @Length(min = 1, max = 50) String name, + @Email String email, + @Length(min = 1, max = 30) String password, + @Phone String phone ) { } diff --git a/src/main/java/camp/woowak/lab/web/validation/annotation/Phone.java b/src/main/java/camp/woowak/lab/web/validation/annotation/Phone.java new file mode 100644 index 00000000..60deb9ec --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/validation/annotation/Phone.java @@ -0,0 +1,21 @@ +package camp.woowak.lab.web.validation.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import camp.woowak.lab.web.validation.validator.PhoneNumberValidator; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = PhoneNumberValidator.class) +public @interface Phone { + String message() default "Invalid phone number"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/src/main/java/camp/woowak/lab/web/validation/validator/PhoneNumberValidator.java b/src/main/java/camp/woowak/lab/web/validation/validator/PhoneNumberValidator.java new file mode 100644 index 00000000..788ec848 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/validation/validator/PhoneNumberValidator.java @@ -0,0 +1,17 @@ +package camp.woowak.lab.web.validation.validator; + +import camp.woowak.lab.web.validation.annotation.Phone; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +public class PhoneNumberValidator implements ConstraintValidator { + private static final String PHONE_NUMBER_PATTERN = "^(01[0167]|02|0[3-6][1-4])-\\d{3,4}-\\d{4}$"; + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if (value == null) { + return false; + } + return value.matches(PHONE_NUMBER_PATTERN); + } +} From 0900ed4ba2122350e44fa2ab253cadfbed0f756d Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 23:06:10 +0900 Subject: [PATCH 025/146] =?UTF-8?q?[test]=20Vendor=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `+` 판매자 회원가입 테스트 --- .../lab/web/api/VendorControllerTest.java | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/web/api/VendorControllerTest.java diff --git a/src/test/java/camp/woowak/lab/web/api/VendorControllerTest.java b/src/test/java/camp/woowak/lab/web/api/VendorControllerTest.java new file mode 100644 index 00000000..1f5e0ec9 --- /dev/null +++ b/src/test/java/camp/woowak/lab/web/api/VendorControllerTest.java @@ -0,0 +1,139 @@ +package camp.woowak.lab.web.api; + +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.Random; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +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.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import camp.woowak.lab.vendor.exception.DuplicateEmailException; +import camp.woowak.lab.vendor.service.SignUpVendorService; +import camp.woowak.lab.vendor.service.command.SignUpVendorCommand; +import camp.woowak.lab.web.dto.request.SignUpVendorRequest; + +@WebMvcTest(controllers = VendorController.class) +@MockBean(JpaMetamodelMappingContext.class) +class VendorControllerTest { + @Autowired + private MockMvc mockMvc; + @MockBean + private SignUpVendorService signUpVendorService; + + @Nested + @DisplayName("판매자 회원가입: POST /vendors") + class SignUpVendor { + @Test + @DisplayName("[성공] 201") + void success() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); + + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("validName", "validEmail@validEmail.com", "validPassword", + "010-0000-0000"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isCreated()) + .andExpect(MockMvcResultMatchers.header().string("location", "/vendors/" + fakeVendorId)) + .andDo(print()); + } + + @Test + @DisplayName("[실패] 400 : 이름이 비어있는 경우") + void failWithInvalidName() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); + + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("", "validEmail@validEmail.com", "validPassword", + "010-0000-0000"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) + .andDo(print()); + } + + @Test + @DisplayName("[실패] 400 : 불가능한 전화번호") + void failWithInvalidPhone() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); + + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("", "validEmail@validEmail.com", "validPassword", + "111-1111-0000"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) + .andDo(print()); + } + + @Test + @DisplayName("[실패] 200 a1: 이미 가입된 이메일인 경우") + void failWithDuplicateEmail() throws Exception { + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willThrow(DuplicateEmailException.class); + + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("validName", "validEmail@validEmail.com", "validPassword", + "010-0000-0000"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value("a1")) + .andExpect(jsonPath("$.message").value("이미 가입된 이메일 입니다.")) + .andExpect(jsonPath("$.data").isEmpty()) + .andDo(print()); + } + } +} From c1bd5dc5eb48e2b1b21c9831c48fd615d0a96cfe Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 11:37:26 +0900 Subject: [PATCH 026/146] [refactor] AuthController -> CustomerController MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 구매자 회원가입 API 클래스명 변경 --- ...ontroller.java => CustomerController.java} | 28 ++----------------- 1 file changed, 2 insertions(+), 26 deletions(-) rename src/main/java/camp/woowak/lab/web/api/{AuthController.java => CustomerController.java} (52%) diff --git a/src/main/java/camp/woowak/lab/web/api/AuthController.java b/src/main/java/camp/woowak/lab/web/api/CustomerController.java similarity index 52% rename from src/main/java/camp/woowak/lab/web/api/AuthController.java rename to src/main/java/camp/woowak/lab/web/api/CustomerController.java index 59b67e7d..490da989 100644 --- a/src/main/java/camp/woowak/lab/web/api/AuthController.java +++ b/src/main/java/camp/woowak/lab/web/api/CustomerController.java @@ -5,46 +5,22 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import camp.woowak.lab.customer.service.SignUpCustomerService; import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; -import camp.woowak.lab.vendor.exception.DuplicateEmailException; -import camp.woowak.lab.vendor.exception.InvalidCreationException; -import camp.woowak.lab.vendor.service.SignUpVendorService; -import camp.woowak.lab.vendor.service.command.SignUpVendorCommand; import camp.woowak.lab.web.dto.request.SignUpCustomerRequest; -import camp.woowak.lab.web.dto.request.SignUpVendorRequest; import camp.woowak.lab.web.dto.response.ApiResponse; import camp.woowak.lab.web.error.ErrorCode; @RestController -@RequestMapping("/auth") -public class AuthController { - private final SignUpVendorService signUpVendorService; +public class CustomerController { private final SignUpCustomerService signUpCustomerService; - public AuthController(SignUpVendorService signUpVendorService, SignUpCustomerService signUpCustomerService) { - this.signUpVendorService = signUpVendorService; + public CustomerController(SignUpCustomerService signUpCustomerService) { this.signUpCustomerService = signUpCustomerService; } - @PostMapping("/vendors") - public ResponseEntity signUpVendor(@RequestBody SignUpVendorRequest request) { - SignUpVendorCommand command = - new SignUpVendorCommand(request.name(), request.email(), request.password(), request.phone()); - Long registeredId; - try { - registeredId = signUpVendorService.signUp(command); - } catch (InvalidCreationException e) { - return ResponseEntity.badRequest().body(ApiResponse.error(ErrorCode.SIGNUP_INVALID_REQUEST)); - } catch (DuplicateEmailException e) { - return ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_DUPLICATE_EMAIL)); - } - return ResponseEntity.created(URI.create("/vendors/" + registeredId)).build(); - } - @PostMapping("/customers") public ResponseEntity signUpCustomer(@RequestBody SignUpCustomerRequest request) { SignUpCustomerCommand command = From 07cd0511d3418902e6938d029a35321d09898080 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 11:41:54 +0900 Subject: [PATCH 027/146] =?UTF-8?q?[test]=20Customer=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 구매자 제약조건 테스트(점주 제약조건 참조함) --- .../lab/customer/domain/CustomerTest.java | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/customer/domain/CustomerTest.java diff --git a/src/test/java/camp/woowak/lab/customer/domain/CustomerTest.java b/src/test/java/camp/woowak/lab/customer/domain/CustomerTest.java new file mode 100644 index 00000000..28adbfd2 --- /dev/null +++ b/src/test/java/camp/woowak/lab/customer/domain/CustomerTest.java @@ -0,0 +1,200 @@ +package camp.woowak.lab.customer.domain; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import camp.woowak.lab.customer.exception.InvalidCreationException; +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.domain.TestPayAccount; +import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; +import camp.woowak.lab.web.authentication.PasswordEncoder; + +class CustomerTest { + + private PayAccount payAccount; + private PasswordEncoder passwordEncoder; + + @BeforeEach + void setUp() { + payAccount = new TestPayAccount(1L); + passwordEncoder = new NoOpPasswordEncoder(); + } + + @Nested + @DisplayName("Customer 생성은") + class IsConstructed { + @Nested + @DisplayName("이름이") + class NameMust { + @Test + @DisplayName("[성공] 50자까지 허용한다.") + void successWith50() { + Assertions.assertDoesNotThrow( + () -> new Customer("aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeee", + "validEmail@validEmail.com", + "validPassword", "010-0000-0000", payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] null이면 예외가 발생한다.") + void failWithNull() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Customer(null, "validEmail@validEmail.com", "validPassword", "010-0000-0000", payAccount, + passwordEncoder)); + } + + @Test + @DisplayName("[예외] 공란이면 예외가 발생한다.") + void failWithBlank() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Customer(" ", "validEmail@validEmail.com", "validPassword", "010-0000-0000", payAccount, + passwordEncoder)); + } + + @Test + @DisplayName("[예외] 50자를 초과하면 예외가 발생한다.") + void failWith51() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Customer("aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeef", + "validEmail@validEmail.com", + "validPassword", "010-0000-0000", payAccount, passwordEncoder)); + } + } + + @Nested + @DisplayName("이메일이") + class EmailMust { + @Test + @DisplayName("[성공] 100자까지 허용한다.") + void successWith100() { + Assertions.assertDoesNotThrow( + () -> new Customer("aaaaaaaaaa", + "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeee", + "validPassword", "010-0000-0000", payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] null이면 예외가 발생한다.") + void failWithNull() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Customer("aaaaaaaaaa", null, "validPassword", "010-0000-0000", payAccount, + passwordEncoder)); + } + + @Test + @DisplayName("[예외] 공란이면 예외가 발생한다.") + void failWithBlank() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Customer("aaaaaaaaaa", " ", "validPassword", "010-0000-0000", payAccount, + passwordEncoder)); + } + + @Test + @DisplayName("[예외] 100자를 초과하면 예외가 발생한다.") + void failWith101() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Customer("aaaaaaaaaa", + "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeea", + "validPassword", "010-0000-0000", payAccount, passwordEncoder)); + } + } + + @Nested + @DisplayName("비밀번호가") + class PasswordMust { + @Test + @DisplayName("[성공] 30자까지 허용한다.") + void successWith30() { + Assertions.assertDoesNotThrow( + () -> new Customer("aaaaaaaaaa", "validEmail@validEmail.com", "thisstringsizeisthirtyalsnvien", + "010-0000-0000", payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] null이면 예외가 발생한다.") + void failWithNull() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Customer("aaaaaaaaaa", "validEmail@validEmail.com", null, "010-0000-0000", payAccount, + passwordEncoder)); + } + + @Test + @DisplayName("[예외] 공란이면 예외가 발생한다.") + void failWithBlank() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Customer("aaaaaaaaaa", "validEmail@validEmail.com", " ", "010-0000-0000", payAccount, + passwordEncoder)); + } + + @Test + @DisplayName("[예외] 30자를 초과하면 예외가 발생한다.") + void failWith31() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Customer("aaaaaaaaaa", "validEmail@validEmail.com", "thisstringsizeisthirtyonesnvien", + "010-0000-0000", payAccount, passwordEncoder)); + } + } + + @Nested + @DisplayName("전화번호가") + class PhoneMust { + @Test + @DisplayName("[성공] 30자까지 허용한다.") + void successWith30() { + Assertions.assertDoesNotThrow( + () -> new Customer("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", + "0000000000-0000000000-00000000", + payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] null이면 예외가 발생한다.") + void failWithNull() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Customer("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", null, + payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] 공란이면 예외가 발생한다.") + void failWithBlank() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Customer("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", " ", + payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] 30자를 초과하면 예외가 발생한다.") + void failWith31() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Customer("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", + "0000000000-0000000000-000000000", + payAccount, passwordEncoder)); + } + } + + @Nested + @DisplayName("페이계좌가") + class PayAccountMust { + @Test + @DisplayName("[성공] 있으면 성공한다.") + void successWithExist() { + Assertions.assertDoesNotThrow( + () -> new Customer("validName", "validEmail@validEmail.com", "validPassword", "010-0000-0000", + payAccount, passwordEncoder)); + } + + @Test + @DisplayName("[예외] null이면 예외가 발생한다.") + void failWithNull() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Customer("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", "010-0000-0000", + null, + passwordEncoder)); + } + } + } +} From 17fb832af0f5145cd55797ec33a6f1556f891f39 Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 23:05:10 +0900 Subject: [PATCH 028/146] =?UTF-8?q?[feat]=20Phone=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 전화번호를 검증하기 위한 어노테이션 및 커스텀 Validator 구현 --- .../web/dto/request/SignUpVendorRequest.java | 9 ++++++++ .../lab/web/validation/annotation/Phone.java | 21 +++++++++++++++++++ .../validator/PhoneNumberValidator.java | 17 +++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/validation/annotation/Phone.java create mode 100644 src/main/java/camp/woowak/lab/web/validation/validator/PhoneNumberValidator.java diff --git a/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java index 60044894..00cbe2ab 100644 --- a/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java +++ b/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java @@ -1,9 +1,18 @@ package camp.woowak.lab.web.dto.request; +import org.hibernate.validator.constraints.Length; + +import camp.woowak.lab.web.validation.annotation.Phone; +import jakarta.validation.constraints.Email; + public record SignUpVendorRequest( + @Length(min = 1, max = 50) String name, + @Email String email, + @Length(min = 1, max = 30) String password, + @Phone String phone ) { } diff --git a/src/main/java/camp/woowak/lab/web/validation/annotation/Phone.java b/src/main/java/camp/woowak/lab/web/validation/annotation/Phone.java new file mode 100644 index 00000000..60deb9ec --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/validation/annotation/Phone.java @@ -0,0 +1,21 @@ +package camp.woowak.lab.web.validation.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import camp.woowak.lab.web.validation.validator.PhoneNumberValidator; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = PhoneNumberValidator.class) +public @interface Phone { + String message() default "Invalid phone number"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/src/main/java/camp/woowak/lab/web/validation/validator/PhoneNumberValidator.java b/src/main/java/camp/woowak/lab/web/validation/validator/PhoneNumberValidator.java new file mode 100644 index 00000000..788ec848 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/validation/validator/PhoneNumberValidator.java @@ -0,0 +1,17 @@ +package camp.woowak.lab.web.validation.validator; + +import camp.woowak.lab.web.validation.annotation.Phone; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +public class PhoneNumberValidator implements ConstraintValidator { + private static final String PHONE_NUMBER_PATTERN = "^(01[0167]|02|0[3-6][1-4])-\\d{3,4}-\\d{4}$"; + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if (value == null) { + return false; + } + return value.matches(PHONE_NUMBER_PATTERN); + } +} From bbafb207888faab72aec8849c93a1f5f14206807 Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 16:18:01 +0900 Subject: [PATCH 029/146] =?UTF-8?q?[feat]=20jpa=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `~` show-sql: 실행되는 sql 조회 `~` generate-ddl: 테스트시 테이블 자동 생성 `~` ddl-auto: 어플리케이션 생성시 생성, 종료시 삭제 `~` open-in-view: 의도하지 않은 조회 쿼리 발생 방지 --- src/main/resources/application.properties | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index cc1ad9a6..66b1c0c5 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,5 @@ spring.application.name=lab +spring.jpa.show-sql=true +spring.jpa.generate-ddl=true +spring.jpa.open-in-view=false +spring.jpa.hibernate.ddl-auto=create-drop From a9201d787b30a3e2936955116d7687b5d434b6e0 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 12:13:33 +0900 Subject: [PATCH 030/146] =?UTF-8?q?[test]=20CustomerController=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 구매자 API RequestBody 제약조건 테스트 --- .../lab/web/api/CustomerControllerTest.java | 191 ++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java diff --git a/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java b/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java new file mode 100644 index 00000000..b2fcd5c4 --- /dev/null +++ b/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java @@ -0,0 +1,191 @@ +package camp.woowak.lab.web.api; + +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.MockMvcResultMatchers.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import camp.woowak.lab.customer.exception.DuplicateEmailException; +import camp.woowak.lab.customer.service.SignUpCustomerService; +import camp.woowak.lab.web.dto.request.SignUpCustomerRequest; +import camp.woowak.lab.web.error.ErrorCode; + +@WebMvcTest(CustomerController.class) +@MockBean(JpaMetamodelMappingContext.class) +class CustomerControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private SignUpCustomerService signUpCustomerService; + + @Autowired + private ObjectMapper objectMapper; + + @Test + @DisplayName("구매자 회원가입 테스트 - 성공") + void testSignUpCustomer() throws Exception { + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "password123", + "010-1234-5678"); + given(signUpCustomerService.signUp(any())).willReturn(1L); + + mockMvc.perform(post("/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isCreated()); + } + + @Test + @DisplayName("구매자 회원가입 테스트 - 이름이 없는 경우") + void testSignUpCustomerWithoutName() throws Exception { + SignUpCustomerRequest request = new SignUpCustomerRequest("", "email@test.com", "password123", "01012345678"); + + mockMvc.perform(post("/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("구매자 회원가입 테스트 - 이메일이 없는 경우") + void testSignUpCustomerWithoutEmail() throws Exception { + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "", "password123", "01012345678"); + + mockMvc.perform(post("/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("구매자 회원가입 테스트 - 비밀번호가 없는 경우") + void testSignUpCustomerWithoutPassword() throws Exception { + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "", "01012345678"); + + mockMvc.perform(post("/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("구매자 회원가입 테스트 - 전화번호가 없는 경우") + void testSignUpCustomerWithoutPhone() throws Exception { + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "password123", ""); + + mockMvc.perform(post("/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("구매자 회원가입 테스트 - 이름이 50자 초과인 경우") + void testSignUpCustomerWithLongName() throws Exception { + SignUpCustomerRequest request = new SignUpCustomerRequest("n".repeat(51), "email@test.com", "password123", + "01012345678"); + + mockMvc.perform(post("/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("구매자 회원가입 테스트 - 이메일이 100자 초과인 경우") + void testSignUpCustomerWithLongEmail() throws Exception { + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "e".repeat(90) + "@test.com", "password123", + "01012345678"); + + mockMvc.perform(post("/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("구매자 회원가입 테스트 - 비밀번호가 20자 초과인 경우") + void testSignUpCustomerWithLongPassword() throws Exception { + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "p".repeat(21), + "01012345678"); + + mockMvc.perform(post("/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("구매자 회원가입 테스트 - 비밀번호가 8자 미만인 경우") + void testSignUpCustomerWithShortPassword() throws Exception { + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "pass", "01012345678"); + + mockMvc.perform(post("/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("구매자 회원가입 테스트 - 전화번호가 30자 초과인 경우") + void testSignUpCustomerWithLongPhone() throws Exception { + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "password123", + "0".repeat(31)); + + mockMvc.perform(post("/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("구매자 회원가입 테스트 - 이메일 형식이 아닌 경우") + void testSignUpCustomerWithInvalidEmail() throws Exception { + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "invalid-email", "password123", + "01012345678"); + + mockMvc.perform(post("/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("구매자 회원가입 테스트 - 전화번호 형식이 아닌 경우") + void testSignUpCustomerWithInvalidPhone() throws Exception { + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "password123", + "invalid-phone"); + + mockMvc.perform(post("/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isBadRequest()); + } + + @Test + @DisplayName("구매자 회원가입 테스트 - 중복된 이메일인 경우") + void testSignUpCustomerWithDuplicateEmail() throws Exception { + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "duplicate@test.com", "password123", + "010-1234-5678"); + given(signUpCustomerService.signUp(any())).willThrow(new DuplicateEmailException()); + + mockMvc.perform(post("/customers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(ErrorCode.AUTH_DUPLICATE_EMAIL.getCode())) + .andExpect(jsonPath("$.message").value(ErrorCode.AUTH_DUPLICATE_EMAIL.getMessage())); + } +} \ No newline at end of file From 2d54d492668b76d6db8ab4bff99c01b8353ca652 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 12:14:19 +0900 Subject: [PATCH 031/146] =?UTF-8?q?[feat]=20SignUpCustomerRequest=20?= =?UTF-8?q?=EC=A0=9C=EC=95=BD=20=EC=A1=B0=EA=B1=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 이름 길이 1~50 - 이메일 - 비밀번호 8~20 - 전화번호 --- .../lab/web/dto/request/SignUpCustomerRequest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java index 4f1e877c..753cb1a1 100644 --- a/src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java +++ b/src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java @@ -1,9 +1,18 @@ package camp.woowak.lab.web.dto.request; +import org.hibernate.validator.constraints.Length; + +import camp.woowak.lab.web.validation.annotation.Phone; +import jakarta.validation.constraints.Email; + public record SignUpCustomerRequest( + @Length(min = 1, max = 50) String name, + @Email String email, + @Length(min = 8, max = 20) String password, + @Phone String phone ) { } From 98f450b88cf235066120c06f421002d0a170224a Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 12:15:11 +0900 Subject: [PATCH 032/146] =?UTF-8?q?[feat]=20CustomerController.signUp=20?= =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20Valid=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 --- src/main/java/camp/woowak/lab/web/api/CustomerController.java | 3 ++- 1 file changed, 2 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 490da989..498070b0 100644 --- a/src/main/java/camp/woowak/lab/web/api/CustomerController.java +++ b/src/main/java/camp/woowak/lab/web/api/CustomerController.java @@ -12,6 +12,7 @@ import camp.woowak.lab.web.dto.request.SignUpCustomerRequest; import camp.woowak.lab.web.dto.response.ApiResponse; import camp.woowak.lab.web.error.ErrorCode; +import jakarta.validation.Valid; @RestController public class CustomerController { @@ -22,7 +23,7 @@ public CustomerController(SignUpCustomerService signUpCustomerService) { } @PostMapping("/customers") - public ResponseEntity signUpCustomer(@RequestBody SignUpCustomerRequest request) { + public ResponseEntity signUp(@Valid @RequestBody SignUpCustomerRequest request) { SignUpCustomerCommand command = new SignUpCustomerCommand(request.name(), request.email(), request.password(), request.phone()); Long registeredId; From 6d718e5ae9ea94043466b8e6e3a9ff98be04f5b4 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 12:48:44 +0900 Subject: [PATCH 033/146] =?UTF-8?q?[refactor]=20SignUpCustomerServiceTest?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Repository 의존성 제거 --- .../service/SignUpCustomerServiceTest.java | 77 ++++++++++++------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java index 9727de50..0f8f93af 100644 --- a/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java +++ b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java @@ -1,56 +1,79 @@ package camp.woowak.lab.customer.service; -import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.BDDMockito.*; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.dao.DataIntegrityViolationException; import camp.woowak.lab.customer.domain.Customer; import camp.woowak.lab.customer.exception.DuplicateEmailException; +import camp.woowak.lab.customer.exception.DuplicateException; import camp.woowak.lab.customer.exception.InvalidCreationException; import camp.woowak.lab.customer.repository.CustomerRepository; import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; +import camp.woowak.lab.fixture.CustomerFixture; +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.repository.PayAccountRepository; +import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; +import camp.woowak.lab.web.authentication.PasswordEncoder; -@SpringBootTest -class SignUpCustomerServiceTest { +@ExtendWith(MockitoExtension.class) +class SignUpCustomerServiceTest implements CustomerFixture { - @Autowired - SignUpCustomerService signUpCustomerService; + @InjectMocks + private SignUpCustomerService service; - @Autowired - CustomerRepository customerRepository; + @Mock + private CustomerRepository customerRepository; - @BeforeEach - void setUp() { - customerRepository.deleteAll(); - } + @Mock + private PayAccountRepository payAccountRepository; + + @Mock + private PasswordEncoder passwordEncoder; @Test @DisplayName("구매자 회원가입 테스트") void testSignUp() throws InvalidCreationException, DuplicateEmailException { - SignUpCustomerCommand cmd = new SignUpCustomerCommand("name", "email", "password", "phone"); + // given + given(passwordEncoder.encode(Mockito.anyString())).willReturn("password"); + PayAccount payAccount = createPayAccount(); + Customer customer = createCustomer(payAccount, new NoOpPasswordEncoder()); + given(payAccountRepository.save(Mockito.any(PayAccount.class))).willReturn(payAccount); + given(customerRepository.save(Mockito.any(Customer.class))).willReturn(customer); - Long id = signUpCustomerService.signUp(cmd); + // when + SignUpCustomerCommand command = + new SignUpCustomerCommand("name", "email@example.com", "password", "01012345678"); + Long id = service.signUp(command); - Customer customer = customerRepository.findById(id).orElseThrow(); - - assertEquals("name", customer.getName()); - assertEquals("email", customer.getEmail()); - assertEquals("password", customer.getPassword()); - assertEquals("phone", customer.getPhone()); + // then + then(payAccountRepository).should().save(Mockito.any(PayAccount.class)); + then(customerRepository).should().save(Mockito.any(Customer.class)); } @Test @DisplayName("구매자 이메일 중복 회원가입 테스트") void testSignUpWithExistingEmail() { - SignUpCustomerCommand cmd = new SignUpCustomerCommand("name", "email", "password", "phone"); + // given + given(passwordEncoder.encode(Mockito.anyString())).willReturn("password"); + given(payAccountRepository.save(Mockito.any(PayAccount.class))).willReturn(createPayAccount()); + when(customerRepository.save(Mockito.any(Customer.class))).thenThrow(DataIntegrityViolationException.class); + + // when + SignUpCustomerCommand command = + new SignUpCustomerCommand("name", "email@example.com", "password", "01012345678"); - assertThrows(DuplicateEmailException.class, () -> { - signUpCustomerService.signUp(cmd); - signUpCustomerService.signUp(cmd); - }); + // then + Assertions.assertThrows(DuplicateException.class, () -> service.signUp(command)); + then(payAccountRepository).should().save(Mockito.any(PayAccount.class)); + then(customerRepository).should().save(Mockito.any(Customer.class)); } } \ No newline at end of file From 5197be330fb59df763095a284296b9452e41d6a5 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 12:49:16 +0900 Subject: [PATCH 034/146] =?UTF-8?q?[feat]=20CustomerFixture=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 - 반복되는 생성 추상화 --- .../woowak/lab/fixture/CustomerFixture.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/fixture/CustomerFixture.java diff --git a/src/test/java/camp/woowak/lab/fixture/CustomerFixture.java b/src/test/java/camp/woowak/lab/fixture/CustomerFixture.java new file mode 100644 index 00000000..75c1ac1b --- /dev/null +++ b/src/test/java/camp/woowak/lab/fixture/CustomerFixture.java @@ -0,0 +1,22 @@ +package camp.woowak.lab.fixture; + +import camp.woowak.lab.customer.domain.Customer; +import camp.woowak.lab.customer.exception.InvalidCreationException; +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.web.authentication.PasswordEncoder; + +public interface CustomerFixture { + default PayAccount createPayAccount() { + return new PayAccount(); + } + + default Customer createCustomer(PayAccount payAccount, PasswordEncoder passwordEncoder) { + try { + return new Customer("vendorName", "vendorEmail@example.com", "vendorPassword", "010-0000-0000", payAccount, + passwordEncoder); + } catch (InvalidCreationException e) { + throw new RuntimeException(e); + } + } + +} From 476489cdc842fa9fce21819f3dc60403d89a0fb2 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 12:51:14 +0900 Subject: [PATCH 035/146] =?UTF-8?q?[chore]=20CustomerControllerTest=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80=20-=20given,=20when,=20?= =?UTF-8?q?then=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/web/api/CustomerControllerTest.java | 24 +++++++++++++++++++ 1 file changed, 24 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 b2fcd5c4..04c31f3e 100644 --- a/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java @@ -37,10 +37,12 @@ class CustomerControllerTest { @Test @DisplayName("구매자 회원가입 테스트 - 성공") void testSignUpCustomer() throws Exception { + // given SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "password123", "010-1234-5678"); given(signUpCustomerService.signUp(any())).willReturn(1L); + // when & then mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) @@ -51,7 +53,9 @@ void testSignUpCustomer() throws Exception { @DisplayName("구매자 회원가입 테스트 - 이름이 없는 경우") void testSignUpCustomerWithoutName() throws Exception { SignUpCustomerRequest request = new SignUpCustomerRequest("", "email@test.com", "password123", "01012345678"); + // given + // when & then mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) @@ -62,7 +66,9 @@ void testSignUpCustomerWithoutName() throws Exception { @DisplayName("구매자 회원가입 테스트 - 이메일이 없는 경우") void testSignUpCustomerWithoutEmail() throws Exception { SignUpCustomerRequest request = new SignUpCustomerRequest("name", "", "password123", "01012345678"); + // given + // when & then mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) @@ -73,7 +79,9 @@ void testSignUpCustomerWithoutEmail() throws Exception { @DisplayName("구매자 회원가입 테스트 - 비밀번호가 없는 경우") void testSignUpCustomerWithoutPassword() throws Exception { SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "", "01012345678"); + // given + // when & then mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) @@ -83,8 +91,10 @@ void testSignUpCustomerWithoutPassword() throws Exception { @Test @DisplayName("구매자 회원가입 테스트 - 전화번호가 없는 경우") void testSignUpCustomerWithoutPhone() throws Exception { + // given SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "password123", ""); + // when & then mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) @@ -94,9 +104,11 @@ void testSignUpCustomerWithoutPhone() throws Exception { @Test @DisplayName("구매자 회원가입 테스트 - 이름이 50자 초과인 경우") void testSignUpCustomerWithLongName() throws Exception { + // given SignUpCustomerRequest request = new SignUpCustomerRequest("n".repeat(51), "email@test.com", "password123", "01012345678"); + // when & then mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) @@ -106,9 +118,11 @@ void testSignUpCustomerWithLongName() throws Exception { @Test @DisplayName("구매자 회원가입 테스트 - 이메일이 100자 초과인 경우") void testSignUpCustomerWithLongEmail() throws Exception { + // given SignUpCustomerRequest request = new SignUpCustomerRequest("name", "e".repeat(90) + "@test.com", "password123", "01012345678"); + // when & then mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) @@ -131,7 +145,9 @@ void testSignUpCustomerWithLongPassword() throws Exception { @DisplayName("구매자 회원가입 테스트 - 비밀번호가 8자 미만인 경우") void testSignUpCustomerWithShortPassword() throws Exception { SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "pass", "01012345678"); + // given + // when & then mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) @@ -141,9 +157,11 @@ void testSignUpCustomerWithShortPassword() throws Exception { @Test @DisplayName("구매자 회원가입 테스트 - 전화번호가 30자 초과인 경우") void testSignUpCustomerWithLongPhone() throws Exception { + // given SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "password123", "0".repeat(31)); + // when & then mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) @@ -153,9 +171,11 @@ void testSignUpCustomerWithLongPhone() throws Exception { @Test @DisplayName("구매자 회원가입 테스트 - 이메일 형식이 아닌 경우") void testSignUpCustomerWithInvalidEmail() throws Exception { + // given SignUpCustomerRequest request = new SignUpCustomerRequest("name", "invalid-email", "password123", "01012345678"); + // when & then mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) @@ -165,9 +185,11 @@ void testSignUpCustomerWithInvalidEmail() throws Exception { @Test @DisplayName("구매자 회원가입 테스트 - 전화번호 형식이 아닌 경우") void testSignUpCustomerWithInvalidPhone() throws Exception { + // given SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "password123", "invalid-phone"); + // when & then mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) @@ -177,10 +199,12 @@ void testSignUpCustomerWithInvalidPhone() throws Exception { @Test @DisplayName("구매자 회원가입 테스트 - 중복된 이메일인 경우") void testSignUpCustomerWithDuplicateEmail() throws Exception { + // given SignUpCustomerRequest request = new SignUpCustomerRequest("name", "duplicate@test.com", "password123", "010-1234-5678"); given(signUpCustomerService.signUp(any())).willThrow(new DuplicateEmailException()); + // when & then mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) From 4adf5de577e407b67943a9fbc934224457028ece Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 12:53:29 +0900 Subject: [PATCH 036/146] =?UTF-8?q?[fix]=20CustomerControllerTest=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?-=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EA=B2=80=EC=A6=9D?= =?UTF-8?q?=20=EC=8B=9C=20=ED=95=AD=EC=83=81=20=EC=9E=98=EB=AA=BB=EB=90=9C?= =?UTF-8?q?=20=EC=A0=84=ED=99=94=EB=B2=88=ED=98=B8=20=ED=98=95=EC=8B=9D?= =?UTF-8?q?=EC=9D=B4=20=EB=93=A4=EC=96=B4=EA=B0=80=EB=8A=94=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/web/api/CustomerControllerTest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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 04c31f3e..0799d428 100644 --- a/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java @@ -52,8 +52,8 @@ void testSignUpCustomer() throws Exception { @Test @DisplayName("구매자 회원가입 테스트 - 이름이 없는 경우") void testSignUpCustomerWithoutName() throws Exception { - SignUpCustomerRequest request = new SignUpCustomerRequest("", "email@test.com", "password123", "01012345678"); // given + SignUpCustomerRequest request = new SignUpCustomerRequest("", "email@test.com", "password123", "010-1234-5678"); // when & then mockMvc.perform(post("/customers") @@ -65,8 +65,8 @@ void testSignUpCustomerWithoutName() throws Exception { @Test @DisplayName("구매자 회원가입 테스트 - 이메일이 없는 경우") void testSignUpCustomerWithoutEmail() throws Exception { - SignUpCustomerRequest request = new SignUpCustomerRequest("name", "", "password123", "01012345678"); // given + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "", "password123", "010-1234-5678"); // when & then mockMvc.perform(post("/customers") @@ -78,8 +78,8 @@ void testSignUpCustomerWithoutEmail() throws Exception { @Test @DisplayName("구매자 회원가입 테스트 - 비밀번호가 없는 경우") void testSignUpCustomerWithoutPassword() throws Exception { - SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "", "01012345678"); // given + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "", "010-1234-5678"); // when & then mockMvc.perform(post("/customers") @@ -106,7 +106,7 @@ void testSignUpCustomerWithoutPhone() throws Exception { void testSignUpCustomerWithLongName() throws Exception { // given SignUpCustomerRequest request = new SignUpCustomerRequest("n".repeat(51), "email@test.com", "password123", - "01012345678"); + "010-1234-5678"); // when & then mockMvc.perform(post("/customers") @@ -120,7 +120,7 @@ void testSignUpCustomerWithLongName() throws Exception { void testSignUpCustomerWithLongEmail() throws Exception { // given SignUpCustomerRequest request = new SignUpCustomerRequest("name", "e".repeat(90) + "@test.com", "password123", - "01012345678"); + "010-1234-5678"); // when & then mockMvc.perform(post("/customers") @@ -133,7 +133,7 @@ void testSignUpCustomerWithLongEmail() throws Exception { @DisplayName("구매자 회원가입 테스트 - 비밀번호가 20자 초과인 경우") void testSignUpCustomerWithLongPassword() throws Exception { SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "p".repeat(21), - "01012345678"); + "010-1234-5678"); mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) @@ -144,8 +144,8 @@ void testSignUpCustomerWithLongPassword() throws Exception { @Test @DisplayName("구매자 회원가입 테스트 - 비밀번호가 8자 미만인 경우") void testSignUpCustomerWithShortPassword() throws Exception { - SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "pass", "01012345678"); // given + SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "pass", "010-1234-5678"); // when & then mockMvc.perform(post("/customers") @@ -173,7 +173,7 @@ void testSignUpCustomerWithLongPhone() throws Exception { void testSignUpCustomerWithInvalidEmail() throws Exception { // given SignUpCustomerRequest request = new SignUpCustomerRequest("name", "invalid-email", "password123", - "01012345678"); + "010-1234-5678"); // when & then mockMvc.perform(post("/customers") From 3abdeb97c236ff95e2a0293b27a7c34576cfdb60 Mon Sep 17 00:00:00 2001 From: donghar Date: Sun, 11 Aug 2024 13:16:41 +0900 Subject: [PATCH 037/146] =?UTF-8?q?[feat]=20Vendor=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9D=80=20=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=EB=A5=BC=208?= =?UTF-8?q?=EC=9E=90=EB=B6=80=ED=84=B0=20=ED=97=88=EC=9A=A9=ED=95=9C?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 검증 로직 수정 --- src/main/java/camp/woowak/lab/vendor/domain/Vendor.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java b/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java index 59fc91cf..8c1866c0 100644 --- a/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java +++ b/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java @@ -67,8 +67,9 @@ private void checkPassword(String password) throws InvalidCreationException { if (password == null || password.isBlank()) { throw new InvalidCreationException("Vendor password cannot be blank"); } - if (password.trim().length() > 30) { - throw new InvalidCreationException("Vendor password cannot be longer than 30 characters"); + if (password.trim().length() < 8 || password.trim().length() > 30) { + throw new InvalidCreationException( + "Vendor password must be at least 8 characters and at most 30 characters"); } } From c92a6347a9debd56de0d21ff091b75011aac147e Mon Sep 17 00:00:00 2001 From: donghar Date: Sun, 11 Aug 2024 13:16:49 +0900 Subject: [PATCH 038/146] =?UTF-8?q?[test]=20Vendor=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9D=80=20=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=EB=A5=BC=208?= =?UTF-8?q?=EC=9E=90=EB=B6=80=ED=84=B0=20=ED=97=88=EC=9A=A9=ED=95=9C?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `+` 패스워트 7/8글자 테스트 추가 --- .../woowak/lab/vendor/domain/VendorTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/java/camp/woowak/lab/vendor/domain/VendorTest.java b/src/test/java/camp/woowak/lab/vendor/domain/VendorTest.java index 39b77f25..ec8d949f 100644 --- a/src/test/java/camp/woowak/lab/vendor/domain/VendorTest.java +++ b/src/test/java/camp/woowak/lab/vendor/domain/VendorTest.java @@ -102,6 +102,14 @@ void failWith101() { @Nested @DisplayName("비밀번호가") class PasswordMust { + @Test + @DisplayName("[성공] 8자 이상부터 허용한다.") + void successWith8() { + Assertions.assertDoesNotThrow( + () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "thisis8c", + "010-0000-0000", payAccount, passwordEncoder)); + } + @Test @DisplayName("[성공] 30자까지 허용한다.") void successWith30() { @@ -126,6 +134,14 @@ void failWithBlank() { passwordEncoder)); } + @Test + @DisplayName("[예외] 8자 미만이면 예외가 발생한다.") + void failWith7() { + Assertions.assertThrows(InvalidCreationException.class, + () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "thisis7", + "010-0000-0000", payAccount, passwordEncoder)); + } + @Test @DisplayName("[예외] 30자를 초과하면 예외가 발생한다.") void failWith31() { From 4e8fa20a8fdfb370f1fd2ec10535b3402930f6e5 Mon Sep 17 00:00:00 2001 From: donghar Date: Sun, 11 Aug 2024 13:17:26 +0900 Subject: [PATCH 039/146] =?UTF-8?q?[feat]=20Vendor=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20RequestDto=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 패스워드는 8자 이상부터 허용한다. --- .../camp/woowak/lab/web/dto/request/SignUpVendorRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java index 00cbe2ab..2e6e598d 100644 --- a/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java +++ b/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java @@ -10,7 +10,7 @@ public record SignUpVendorRequest( String name, @Email String email, - @Length(min = 1, max = 30) + @Length(min = 8, max = 30) String password, @Phone String phone From 5f51c1e24f0b8968d1cc76fa9ecae7617f5bd01b Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 13:45:25 +0900 Subject: [PATCH 040/146] =?UTF-8?q?[test]=20SignUpCustomerServiceIntegrati?= =?UTF-8?q?onTest=20=EC=B6=94=EA=B0=80=20-=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=9D=B4=EB=A9=94=EC=9D=BC=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EC=8B=9C=20=EB=A1=A4=EB=B0=B1=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SignUpCustomerServiceIntegrationTest.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceIntegrationTest.java diff --git a/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceIntegrationTest.java b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceIntegrationTest.java new file mode 100644 index 00000000..afb237b4 --- /dev/null +++ b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceIntegrationTest.java @@ -0,0 +1,52 @@ +package camp.woowak.lab.customer.service; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import camp.woowak.lab.customer.exception.DuplicateEmailException; +import camp.woowak.lab.customer.exception.InvalidCreationException; +import camp.woowak.lab.customer.repository.CustomerRepository; +import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; +import camp.woowak.lab.payaccount.repository.PayAccountRepository; + +@SpringBootTest +class SignUpCustomerServiceIntegrationTest { + + @Autowired + private SignUpCustomerService service; + + @Autowired + private CustomerRepository customerRepository; + + @Autowired + private PayAccountRepository payAccountRepository; + + @Test + @DisplayName("이메일 중복 시 롤백 테스트") + void testRollbackOnDuplicateEmail() throws InvalidCreationException, DuplicateEmailException { + // given + SignUpCustomerCommand command1 = new SignUpCustomerCommand("name1", "email@example.com", "password", + "010-1234-5678"); + SignUpCustomerCommand command2 = new SignUpCustomerCommand("name2", "email@example.com", "password", + "010-8765-4321"); + + // when + service.signUp(command1); + + assertEquals(1, customerRepository.count()); + assertEquals(1, payAccountRepository.count()); + + // then + try { + service.signUp(command2); + fail("중복 이메일 예외가 발생해야 합니다."); + } catch (DuplicateEmailException e) { + assertEquals(1, customerRepository.count()); + assertEquals(1, payAccountRepository.count()); + } + } +} \ No newline at end of file From 1ceeb0d21141b75dfb92dc2898b27326c305f4ca Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 13:45:59 +0900 Subject: [PATCH 041/146] =?UTF-8?q?[feat]=20SignUpCustomerService.signUp?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20-=20@Transactional=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/customer/service/SignUpCustomerService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java b/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java index be5cd040..0a4f70cb 100644 --- a/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java +++ b/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java @@ -11,6 +11,7 @@ import camp.woowak.lab.payaccount.domain.PayAccount; import camp.woowak.lab.payaccount.repository.PayAccountRepository; import camp.woowak.lab.web.authentication.PasswordEncoder; +import jakarta.transaction.Transactional; @Service public class SignUpCustomerService { @@ -25,6 +26,7 @@ public SignUpCustomerService(CustomerRepository customerRepository, PayAccountRe this.passwordEncoder = passwordEncoder; } + @Transactional public Long signUp(SignUpCustomerCommand cmd) throws InvalidCreationException, DuplicateEmailException { PayAccount payAccount = new PayAccount(); payAccountRepository.save(payAccount); From 8dcc908c56356e28b03359b7318dc04b6687d2d4 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 13:48:56 +0900 Subject: [PATCH 042/146] =?UTF-8?q?[feat]=20DuplicateException,=20InvalidC?= =?UTF-8?q?reationException=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RuntimeException 을 사용해 @Transactional 내의 예상하지 못한 RuntimeException이 발생해도 트랜잭션이 롤백되도록 수정 --- .../camp/woowak/lab/customer/exception/DuplicateException.java | 2 +- .../woowak/lab/customer/exception/InvalidCreationException.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/camp/woowak/lab/customer/exception/DuplicateException.java b/src/main/java/camp/woowak/lab/customer/exception/DuplicateException.java index a6364e76..8b3e6d10 100644 --- a/src/main/java/camp/woowak/lab/customer/exception/DuplicateException.java +++ b/src/main/java/camp/woowak/lab/customer/exception/DuplicateException.java @@ -1,4 +1,4 @@ package camp.woowak.lab.customer.exception; -public abstract class DuplicateException extends Exception { +public abstract class DuplicateException extends RuntimeException { } diff --git a/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java b/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java index bdfc625a..dc469af6 100644 --- a/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java +++ b/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java @@ -1,6 +1,6 @@ package camp.woowak.lab.customer.exception; -public class InvalidCreationException extends Exception { +public class InvalidCreationException extends RuntimeException { public InvalidCreationException(String message) { super(message); } From f0aa992eef613e2afc46da14104b8e773a2461e9 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 13:51:55 +0900 Subject: [PATCH 043/146] =?UTF-8?q?[fix]=20SignUpCustomerRequest=20-=20ema?= =?UTF-8?q?il=20=ED=95=84=EB=93=9C=EC=97=90=20@NotBlank=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20-=20=EC=9D=B4=EB=A9=94=EC=9D=BC=EC=9D=B4=20""=20?= =?UTF-8?q?=EC=9D=B4=EC=96=B4=EB=8F=84=20=ED=86=B5=EA=B3=BC=EB=90=98?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java index 753cb1a1..50b7ec2d 100644 --- a/src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java +++ b/src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java @@ -4,10 +4,12 @@ import camp.woowak.lab.web.validation.annotation.Phone; import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; public record SignUpCustomerRequest( @Length(min = 1, max = 50) String name, + @NotBlank @Email String email, @Length(min = 8, max = 20) From a06d1c68ce4c94474805a8bcfa099b5dba0a5e8a Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 14:20:17 +0900 Subject: [PATCH 044/146] =?UTF-8?q?[feat]=20TestPayAccount=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20-=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20TestPayAccount=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/payaccount/domain/TestPayAccount.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/payaccount/domain/TestPayAccount.java diff --git a/src/test/java/camp/woowak/lab/payaccount/domain/TestPayAccount.java b/src/test/java/camp/woowak/lab/payaccount/domain/TestPayAccount.java new file mode 100644 index 00000000..0e0dc6c1 --- /dev/null +++ b/src/test/java/camp/woowak/lab/payaccount/domain/TestPayAccount.java @@ -0,0 +1,14 @@ +package camp.woowak.lab.payaccount.domain; + +public class TestPayAccount extends PayAccount { + private Long id; + private PayAccount payAccount; + + public TestPayAccount(Long id) { + this.payAccount = payAccount; + } + + public Long getId() { + return id; + } +} \ No newline at end of file From 7bab41519c5f304ecf9a9d3f08e68ee5345be823 Mon Sep 17 00:00:00 2001 From: donghar Date: Sun, 11 Aug 2024 14:56:37 +0900 Subject: [PATCH 045/146] =?UTF-8?q?[fix]=20Vendor=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20RequestDto=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 파라미터가 오지 않은 경우 또는 비어있는 경우에 대한 검증 추가 --- .../woowak/lab/web/dto/request/SignUpVendorRequest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java index 2e6e598d..b8d886cb 100644 --- a/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java +++ b/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java @@ -4,13 +4,14 @@ import camp.woowak.lab.web.validation.annotation.Phone; import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; public record SignUpVendorRequest( - @Length(min = 1, max = 50) + @NotBlank @Length(min = 1, max = 50) String name, - @Email + @NotBlank @Email String email, - @Length(min = 8, max = 30) + @NotBlank @Length(min = 8, max = 30) String password, @Phone String phone From 8d52b59da009ae9d04d58c2c270aaf0a37da5d16 Mon Sep 17 00:00:00 2001 From: donghar Date: Sun, 11 Aug 2024 14:57:05 +0900 Subject: [PATCH 046/146] =?UTF-8?q?[test]=20=ED=8C=8C=EB=A6=AC=EB=AF=B8?= =?UTF-8?q?=ED=84=B0=EA=B0=80=20=EB=B9=84=EC=96=B4=EC=9E=88=EB=8A=94=20Ven?= =?UTF-8?q?dor=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=EC=9A=94=EC=B2=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 파라미터가 오지 않은 경우 또는 비어있는 경우에 대한 테스트 추가 --- .../lab/web/api/VendorControllerTest.java | 342 +++++++++++++++--- 1 file changed, 297 insertions(+), 45 deletions(-) diff --git a/src/test/java/camp/woowak/lab/web/api/VendorControllerTest.java b/src/test/java/camp/woowak/lab/web/api/VendorControllerTest.java index 1f5e0ec9..5d38fb01 100644 --- a/src/test/java/camp/woowak/lab/web/api/VendorControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/VendorControllerTest.java @@ -60,56 +60,308 @@ void success() throws Exception { .andDo(print()); } - @Test - @DisplayName("[실패] 400 : 이름이 비어있는 경우") - void failWithInvalidName() throws Exception { - long fakeVendorId = new Random().nextLong(1000L); - BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) - .willReturn(fakeVendorId); + @Nested + @DisplayName("[실패] 400") + class FailWith400 { + @Nested + @DisplayName("이름이") + class NameMust { + @Test + @DisplayName("비어있는 경우") + void failWithEmptyName() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); - // when - ResultActions actions = mockMvc.perform( - post("/vendors") - .content(new ObjectMapper().writeValueAsString( - new SignUpVendorRequest("", "validEmail@validEmail.com", "validPassword", - "010-0000-0000"))) - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - ); + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest(null, "validEmail@validEmail.com", "validPassword", + "010-0000-0000"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); - // then - actions.andExpect(status().isBadRequest()) - .andExpect(jsonPath("$.type").value("about:blank")) - .andExpect(jsonPath("$.title").value("Bad Request")) - .andExpect(jsonPath("$.status").value(400)) - .andExpect(jsonPath("$.instance").value("/vendors")) - .andDo(print()); - } + // then + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) + .andDo(print()); + } - @Test - @DisplayName("[실패] 400 : 불가능한 전화번호") - void failWithInvalidPhone() throws Exception { - long fakeVendorId = new Random().nextLong(1000L); - BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) - .willReturn(fakeVendorId); + @Test + @DisplayName("공란인 경우") + void failWithBlankName() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); - // when - ResultActions actions = mockMvc.perform( - post("/vendors") - .content(new ObjectMapper().writeValueAsString( - new SignUpVendorRequest("", "validEmail@validEmail.com", "validPassword", - "111-1111-0000"))) - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - ); + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("", "validEmail@validEmail.com", "validPassword", + "010-0000-0000"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); - // then - actions.andExpect(status().isBadRequest()) - .andExpect(jsonPath("$.type").value("about:blank")) - .andExpect(jsonPath("$.title").value("Bad Request")) - .andExpect(jsonPath("$.status").value(400)) - .andExpect(jsonPath("$.instance").value("/vendors")) - .andDo(print()); + // then + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) + .andDo(print()); + } + } + + @Nested + @DisplayName("이메일이") + class EmailMust { + @Test + @DisplayName("비어있는 경우") + void failWithEmptyEmail() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); + + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("validName", null, "validPassword", "010-0000-0000"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) + .andDo(print()); + } + + @Test + @DisplayName("공란인 경우") + void failWithBlankEmail() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); + + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("validName", "", "validPassword", "010-0000-0000"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) + .andDo(print()); + } + } + + @Nested + @DisplayName("비밀번호가") + class PasswordMust { + @Test + @DisplayName("비어있는 경우") + void failWithEmptyPassword() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); + + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("validName", "validEmail@validEmail.com", null, + "010-0000-0000"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) + .andDo(print()); + } + + @Test + @DisplayName("공란인 경우") + void failWithBlankPassword() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); + + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("validName", "validEmail@validEmail.com", "", + "010-0000-0000"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) + .andDo(print()); + } + + @Test + @DisplayName("8자 미만인 경우") + void failWith7Password() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); + + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("validName", "validEmail@validEmail.com", "abcdefg", + "010-0000-0000"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) + .andDo(print()); + } + + @Test + @DisplayName("30자 초과인 경우") + void failWith31Password() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); + + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("validName", "validEmail@validEmail.com", + "aaaaaaaaaabbbbbbbbbbccccccccccd", + "010-0000-0000"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) + .andDo(print()); + } + } + + @Nested + @DisplayName("전화번호가") + class PhoneMust { + @Test + @DisplayName("비어있는 경우") + void failWithEmptyPhone() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); + + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("validName", "validEmail@validEmail.com", "validPassword", + null))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) + .andDo(print()); + } + + @Test + @DisplayName("공란인 경우") + void failWithBlankPhone() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); + + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("validName", "validEmail@validEmail.com", "validPassword", ""))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) + .andDo(print()); + } + + @Test + @DisplayName("잘못된 형식인 경우") + void failWithInvalidPhone() throws Exception { + long fakeVendorId = new Random().nextLong(1000L); + BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) + .willReturn(fakeVendorId); + + // when + ResultActions actions = mockMvc.perform( + post("/vendors") + .content(new ObjectMapper().writeValueAsString( + new SignUpVendorRequest("", "validEmail@validEmail.com", "validPassword", + "111-1111-0000"))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ); + + // then + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) + .andDo(print()); + } + } } @Test From c5755f24bcd9678cbc4792b13ad6de2053488ea8 Mon Sep 17 00:00:00 2001 From: donghar Date: Sun, 11 Aug 2024 15:12:00 +0900 Subject: [PATCH 047/146] =?UTF-8?q?[fix]=20open-in-view=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20=EC=84=A4=EC=A0=95=EC=9C=BC=EB=A1=9C=20=EB=B3=B5?= =?UTF-8?q?=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 66b1c0c5..b4956434 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,4 @@ spring.application.name=lab spring.jpa.show-sql=true spring.jpa.generate-ddl=true -spring.jpa.open-in-view=false spring.jpa.hibernate.ddl-auto=create-drop From 2750dbcf5c3392440af1566a03a86fa950b7a22a Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Sun, 11 Aug 2024 20:20:58 +0900 Subject: [PATCH 048/146] =?UTF-8?q?[chore]=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EB=A9=94=EC=84=B8=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/customer/domain/Customer.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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 13fda5f6..db1fefb5 100644 --- a/src/main/java/camp/woowak/lab/customer/domain/Customer.java +++ b/src/main/java/camp/woowak/lab/customer/domain/Customer.java @@ -55,37 +55,37 @@ private void checkPayAccount(PayAccount payAccount) throws InvalidCreationExcept private void checkPhone(String phone) throws InvalidCreationException { if (phone == null || phone.isBlank()) { - throw new InvalidCreationException("Vendor phone cannot be blank"); + throw new InvalidCreationException("Customer phone cannot be blank"); } if (phone.trim().length() > 30) { - throw new InvalidCreationException("Vendor phone cannot be longer than 30 characters"); + throw new InvalidCreationException("Customer phone cannot be longer than 30 characters"); } } private void checkPassword(String password) throws InvalidCreationException { if (password == null || password.isBlank()) { - throw new InvalidCreationException("Vendor password cannot be blank"); + throw new InvalidCreationException("Customer password cannot be blank"); } if (password.trim().length() > 30) { - throw new InvalidCreationException("Vendor password cannot be longer than 30 characters"); + throw new InvalidCreationException("Customer password cannot be longer than 30 characters"); } } private void checkEmail(String email) throws InvalidCreationException { if (email == null || email.isBlank()) { - throw new InvalidCreationException("Vendor email cannot be blank"); + throw new InvalidCreationException("Customer email cannot be blank"); } if (email.trim().length() > 100) { - throw new InvalidCreationException("Vendor email cannot be longer than 100 characters"); + throw new InvalidCreationException("Customer email cannot be longer than 100 characters"); } } private void checkName(String name) throws InvalidCreationException { if (name == null || name.isBlank()) { - throw new InvalidCreationException("Vendor name cannot be blank"); + throw new InvalidCreationException("Customer name cannot be blank"); } if (name.length() > 50) { - throw new InvalidCreationException("Vendor name cannot exceed 50 characters"); + throw new InvalidCreationException("Customer name cannot exceed 50 characters"); } } From ea783db2ddcc195d593ca9d6f4680e126532894e Mon Sep 17 00:00:00 2001 From: donghar Date: Mon, 12 Aug 2024 20:15:50 +0900 Subject: [PATCH 049/146] =?UTF-8?q?[feat]=20AuthenticationPrincipal=20?= =?UTF-8?q?=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 컨트롤러에서 사용할 인증을 요구하는 어노테이션 --- .../annotation/AuthenticationPrincipal.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/authentication/annotation/AuthenticationPrincipal.java diff --git a/src/main/java/camp/woowak/lab/web/authentication/annotation/AuthenticationPrincipal.java b/src/main/java/camp/woowak/lab/web/authentication/annotation/AuthenticationPrincipal.java new file mode 100644 index 00000000..4b6ae416 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/authentication/annotation/AuthenticationPrincipal.java @@ -0,0 +1,12 @@ +package camp.woowak.lab.web.authentication.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface AuthenticationPrincipal { + boolean required() default true; +} From 30b47ecf9faafed7a48f11bc5aa5e88c5c89acc4 Mon Sep 17 00:00:00 2001 From: donghar Date: Mon, 12 Aug 2024 20:16:16 +0900 Subject: [PATCH 050/146] =?UTF-8?q?[feat]=20=EC=9D=B8=EC=A6=9D=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 컨트롤러에서 사용할 인증된 사용자 객체 --- .../lab/web/authentication/LoginCustomer.java | 14 ++++++++++++++ .../woowak/lab/web/authentication/LoginMember.java | 5 +++++ .../woowak/lab/web/authentication/LoginVendor.java | 14 ++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/authentication/LoginCustomer.java create mode 100644 src/main/java/camp/woowak/lab/web/authentication/LoginMember.java create mode 100644 src/main/java/camp/woowak/lab/web/authentication/LoginVendor.java diff --git a/src/main/java/camp/woowak/lab/web/authentication/LoginCustomer.java b/src/main/java/camp/woowak/lab/web/authentication/LoginCustomer.java new file mode 100644 index 00000000..0a55c31d --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/authentication/LoginCustomer.java @@ -0,0 +1,14 @@ +package camp.woowak.lab.web.authentication; + +public class LoginCustomer implements LoginMember { + private final Long id; + + public LoginCustomer(Long id) { + this.id = id; + } + + @Override + public Long getId() { + return id; + } +} diff --git a/src/main/java/camp/woowak/lab/web/authentication/LoginMember.java b/src/main/java/camp/woowak/lab/web/authentication/LoginMember.java new file mode 100644 index 00000000..5079e9b8 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/authentication/LoginMember.java @@ -0,0 +1,5 @@ +package camp.woowak.lab.web.authentication; + +public interface LoginMember { + Long getId(); +} diff --git a/src/main/java/camp/woowak/lab/web/authentication/LoginVendor.java b/src/main/java/camp/woowak/lab/web/authentication/LoginVendor.java new file mode 100644 index 00000000..4ac97539 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/authentication/LoginVendor.java @@ -0,0 +1,14 @@ +package camp.woowak.lab.web.authentication; + +public class LoginVendor implements LoginMember { + private final Long id; + + public LoginVendor(Long id) { + this.id = id; + } + + @Override + public Long getId() { + return id; + } +} From 22aeada29c086263f07a0a067b77fbfb16357d0e Mon Sep 17 00:00:00 2001 From: donghar Date: Mon, 12 Aug 2024 20:16:45 +0900 Subject: [PATCH 051/146] [feat] UnauthorizedRequestException MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 인증 실패시 발생할 예외 --- .../lab/common/exception/UnauthorizedRequestException.java | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/common/exception/UnauthorizedRequestException.java diff --git a/src/main/java/camp/woowak/lab/common/exception/UnauthorizedRequestException.java b/src/main/java/camp/woowak/lab/common/exception/UnauthorizedRequestException.java new file mode 100644 index 00000000..2b6e2919 --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/UnauthorizedRequestException.java @@ -0,0 +1,6 @@ +package camp.woowak.lab.common.exception; + +public class UnauthorizedRequestException extends RuntimeException { + public UnauthorizedRequestException(String message) { + } +} From b86ed02ed9da2359bca7cb16f25e0ab71c3178db Mon Sep 17 00:00:00 2001 From: donghar Date: Mon, 12 Aug 2024 20:17:07 +0900 Subject: [PATCH 052/146] =?UTF-8?q?[feat]=20=EC=84=B8=EC=85=98=20=ED=82=A4?= =?UTF-8?q?=EB=A5=BC=20=EC=A0=80=EC=9E=A5=ED=95=A0=20=EC=83=81=EC=88=98=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/web/resolver/session/SessionConst.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/resolver/session/SessionConst.java diff --git a/src/main/java/camp/woowak/lab/web/resolver/session/SessionConst.java b/src/main/java/camp/woowak/lab/web/resolver/session/SessionConst.java new file mode 100644 index 00000000..a705bdb2 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/resolver/session/SessionConst.java @@ -0,0 +1,9 @@ +package camp.woowak.lab.web.resolver.session; + +public final class SessionConst { + public static final String SESSION_VENDOR_KEY = "authentication_vendor"; + public static final String SESSION_CUSTOMER_KEY = "authentication_customer"; + + private SessionConst() { + } +} From 59e78bf32f3afda7f6efa0b56d79bd79a205a788 Mon Sep 17 00:00:00 2001 From: donghar Date: Mon, 12 Aug 2024 20:17:56 +0900 Subject: [PATCH 053/146] [feat] LoginMemberArgumentResolver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 세션에 저장된 Customer 및 Vendor의 정보를 바인딩해주는 ArgumentResolver --- .../session/LoginMemberArgumentResolver.java | 15 ++++++++ .../SessionCustomerArgumentResolver.java | 36 +++++++++++++++++++ .../SessionVendorArgumentResolver.java | 36 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/resolver/session/LoginMemberArgumentResolver.java create mode 100644 src/main/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolver.java create mode 100644 src/main/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolver.java diff --git a/src/main/java/camp/woowak/lab/web/resolver/session/LoginMemberArgumentResolver.java b/src/main/java/camp/woowak/lab/web/resolver/session/LoginMemberArgumentResolver.java new file mode 100644 index 00000000..435a0d54 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/resolver/session/LoginMemberArgumentResolver.java @@ -0,0 +1,15 @@ +package camp.woowak.lab.web.resolver.session; + +import org.springframework.core.MethodParameter; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; + +import camp.woowak.lab.web.authentication.LoginMember; +import camp.woowak.lab.web.authentication.annotation.AuthenticationPrincipal; + +public abstract class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(AuthenticationPrincipal.class) + && LoginMember.class.isAssignableFrom(parameter.getParameterType()); + } +} diff --git a/src/main/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolver.java b/src/main/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolver.java new file mode 100644 index 00000000..2d2ffe12 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolver.java @@ -0,0 +1,36 @@ +package camp.woowak.lab.web.resolver.session; + +import org.springframework.core.MethodParameter; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.ModelAndViewContainer; + +import camp.woowak.lab.common.exception.UnauthorizedRequestException; +import camp.woowak.lab.web.authentication.LoginCustomer; +import camp.woowak.lab.web.authentication.annotation.AuthenticationPrincipal; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpSession; + +public class SessionCustomerArgumentResolver extends LoginMemberArgumentResolver { + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(AuthenticationPrincipal.class) + && LoginCustomer.class.isAssignableFrom(parameter.getParameterType()); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + AuthenticationPrincipal parameterAnnotation = parameter.getParameterAnnotation(AuthenticationPrincipal.class); + if (parameterAnnotation == null) { + return null; + } + HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest(); + HttpSession session = request.getSession(false); + if (parameterAnnotation.required() && + (session == null || session.getAttribute(SessionConst.SESSION_CUSTOMER_KEY) == null)) { + throw new UnauthorizedRequestException("Required session is null"); + } + return session == null ? null : session.getAttribute(SessionConst.SESSION_CUSTOMER_KEY); + } +} diff --git a/src/main/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolver.java b/src/main/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolver.java new file mode 100644 index 00000000..a0cafcaf --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolver.java @@ -0,0 +1,36 @@ +package camp.woowak.lab.web.resolver.session; + +import org.springframework.core.MethodParameter; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.ModelAndViewContainer; + +import camp.woowak.lab.common.exception.UnauthorizedRequestException; +import camp.woowak.lab.web.authentication.LoginVendor; +import camp.woowak.lab.web.authentication.annotation.AuthenticationPrincipal; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpSession; + +public class SessionVendorArgumentResolver extends LoginMemberArgumentResolver { + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(AuthenticationPrincipal.class) + && LoginVendor.class.isAssignableFrom(parameter.getParameterType()); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + AuthenticationPrincipal parameterAnnotation = parameter.getParameterAnnotation(AuthenticationPrincipal.class); + if (parameterAnnotation == null) { + return null; + } + HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest(); + HttpSession session = request.getSession(false); + if (parameterAnnotation.required() && + (session == null || session.getAttribute(SessionConst.SESSION_VENDOR_KEY) == null)) { + throw new UnauthorizedRequestException("Required session is null"); + } + return session == null ? null : session.getAttribute(SessionConst.SESSION_VENDOR_KEY); + } +} From fc96d42947af06252cfd30a7c6f8d3c04c6acc5f Mon Sep 17 00:00:00 2001 From: Hyeon-Uk Date: Mon, 12 Aug 2024 21:02:34 +0900 Subject: [PATCH 054/146] =?UTF-8?q?[feat]=20APIResponse=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 회의 결과로 결정된 API Response 형식에 맞게 status 와 Generic type의 data를 포함하는 클래스 생성 - 이 Response의 생성자는 해당 패키지의 Utils의 메서드를 이용해서만 생성할 수 있도록 private-default 접근 제어자로 설정 --- .../woowak/lab/web/api/utils/APIResponse.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java diff --git a/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java b/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java new file mode 100644 index 00000000..bf74a9d8 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java @@ -0,0 +1,21 @@ +package camp.woowak.lab.web.api.utils; + +import org.springframework.http.HttpStatus; + +public class APIResponse { + private final T data; + private final int status; + + APIResponse(final HttpStatus status, final T data) { + this.data = data; + this.status = status.value(); + } + + public T getData() { + return data; + } + + public int getStatus() { + return status; + } +} From 57db17bda0782a343ed9c675f6ad34982333ce01 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Mon, 12 Aug 2024 21:03:13 +0900 Subject: [PATCH 055/146] =?UTF-8?q?[feat]=20HttpStatusException=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20HttpStatus=20=EC=97=90=20=EA=B8=B0?= =?UTF-8?q?=EB=B0=98=ED=95=9C=20exception=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/common/exception/HttpStatusException.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/common/exception/HttpStatusException.java diff --git a/src/main/java/camp/woowak/lab/common/exception/HttpStatusException.java b/src/main/java/camp/woowak/lab/common/exception/HttpStatusException.java new file mode 100644 index 00000000..b9c07ac1 --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/HttpStatusException.java @@ -0,0 +1,14 @@ +package camp.woowak.lab.common.exception; + +public class HttpStatusException extends RuntimeException { + private final ErrorCode errorCode; + + public HttpStatusException(ErrorCode errorCode) { + super(errorCode.getMessage()); + this.errorCode = errorCode; + } + + public ErrorCode errorCode() { + return errorCode; + } +} From 0d894889f09f0e3e4be4b6cdfdefef5c9d672ae3 Mon Sep 17 00:00:00 2001 From: Hyeon-Uk Date: Mon, 12 Aug 2024 21:04:05 +0900 Subject: [PATCH 056/146] =?UTF-8?q?[feat]=20APIUtils=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - of 메서드를 이용해 APIResponse를 body에 포함한 ResponseEntity를 만들어 낼 수 있습니다. --- .../woowak/lab/web/api/utils/APIUtils.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/api/utils/APIUtils.java diff --git a/src/main/java/camp/woowak/lab/web/api/utils/APIUtils.java b/src/main/java/camp/woowak/lab/web/api/utils/APIUtils.java new file mode 100644 index 00000000..9bdb3c68 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/utils/APIUtils.java @@ -0,0 +1,19 @@ +package camp.woowak.lab.web.api.utils; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +/** + * + * API Utils + * of Method는 status와 data를 이용해 APIResponse객체를 만들 수 있습니다. + * + */ +public final class APIUtils { + private APIUtils() { + } + + public static ResponseEntity> of(HttpStatus status, T data) { + return new ResponseEntity<>(new APIResponse<>(status, data), status); + } +} From 6ae13e72c0a6cd56dfbce21ce19d0021af23c0c1 Mon Sep 17 00:00:00 2001 From: Hyeon-Uk Date: Mon, 12 Aug 2024 21:04:49 +0900 Subject: [PATCH 057/146] =?UTF-8?q?[test]=20APIUtils=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - APIUtils에 대한 테스트코드입니다. - 원시타입의 변수를 Generic으로 설정 가능합니다. - 객체 타입의 변수를 설정할 수 있습니다. --- .../lab/web/api/utils/APIUtilsTest.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/web/api/utils/APIUtilsTest.java diff --git a/src/test/java/camp/woowak/lab/web/api/utils/APIUtilsTest.java b/src/test/java/camp/woowak/lab/web/api/utils/APIUtilsTest.java new file mode 100644 index 00000000..a421a8fa --- /dev/null +++ b/src/test/java/camp/woowak/lab/web/api/utils/APIUtilsTest.java @@ -0,0 +1,73 @@ +package camp.woowak.lab.web.api.utils; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import com.fasterxml.jackson.core.JsonProcessingException; + +@DisplayName("APIUtils 클래스") +class APIUtilsTest { + @Nested + @DisplayName("of메서드의") + class OfTest { + @Nested + @DisplayName("HttpStatus 값과 Data를 파라미터로 받는 메서드는") + class ParamWithHttpStatusAndData { + @Test + @DisplayName("data와 status를 가지는 APIResponse를 생성할 수 있다.") + void APIResponseWithHttpStatusAndData() throws JsonProcessingException { + //given + HttpStatus status = HttpStatus.OK; + String message = "hello world"; + + //when + ResponseEntity> apiResponse = APIUtils.of(status, message); + + //then + assertThat(apiResponse.getStatusCode()).isEqualTo(status); + assertThat(apiResponse.getBody().getData()).isEqualTo(message); + assertThat(apiResponse.getBody().getStatus()).isEqualTo(status.value()); + } + + @Test + @DisplayName("data가 객체인 경우도 APIResponse를 생성할 수 있다.") + void APIResponseWithObjectData() throws JsonProcessingException { + //given + HttpStatus status = HttpStatus.OK; + Example example = new Example(27, "Hyeon-Uk"); + + //when + ResponseEntity> apiResponse = APIUtils.of(status, example); + + //then + assertThat(apiResponse.getStatusCode()).isEqualTo(status); + assertThat(apiResponse.getBody().getData()).isEqualTo(example); + assertThat(apiResponse.getBody().getStatus()).isEqualTo(status.value()); + } + + private class Example { + int age; + String name; + + public Example(int age, String name) { + this.age = age; + this.name = name; + } + + public int getAge() { + return age; + } + + public String getName() { + return name; + } + } + } + + } +} \ No newline at end of file From 5f0a4f7e4aacef635f823bc6890cb6ae8521b4ab Mon Sep 17 00:00:00 2001 From: Hyeon-Uk Date: Mon, 12 Aug 2024 21:06:17 +0900 Subject: [PATCH 058/146] =?UTF-8?q?[docs]=20APIResponse=EC=97=90=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=8B=9C=20=EC=A3=BC=EC=9D=98=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Jackson의 ObjectMapper와 함께 사용하기 위해서는 data로 들어오는 변수에 Getter가 필수적으로 있어야한다는 내용을 주석으로 추가 --- src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java b/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java index bf74a9d8..e41f44a8 100644 --- a/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java +++ b/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java @@ -2,6 +2,10 @@ import org.springframework.http.HttpStatus; +/** + * APIResponse를 Jackson의 ObjectMapper와 함께 사용하려면, + * Generic Type의 {@code data}에는 Getter 메서드가 필요합니다. + */ public class APIResponse { private final T data; private final int status; From 3c20162511ab6dcedbdf23b20a14e2356a00db81 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Mon, 12 Aug 2024 21:09:10 +0900 Subject: [PATCH 059/146] =?UTF-8?q?[feat]=20HttpStatusException=20?= =?UTF-8?q?=EB=A5=BC=20=EA=B5=AC=ED=98=84=ED=95=98=EB=8A=94=20Exception=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20BadRequestException:=20400=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=EC=97=90=20=EB=8C=80=ED=95=9C=20Exception=20-=20Unaut?= =?UTF-8?q?horizedException:=20401=20=EC=97=90=EB=9F=AC=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20Exception=20-=20ForbiddenException:=20403?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=EC=97=90=20=EB=8C=80=ED=95=9C=20Exception?= =?UTF-8?q?=20-=20NotFoundException:=20404=20=EC=97=90=EB=9F=AC=EC=97=90?= =?UTF-8?q?=20=EB=8C=80=ED=95=9C=20Exception=20-=20MethodNotAllowedExcepti?= =?UTF-8?q?on:=20405=20=EC=97=90=EB=9F=AC=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?Exception=20-=20ConflictException:=20409=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20Exception?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/advice/GlobalExceptionHandler.java | 27 +++++++++++++++++++ .../common/exception/BadRequestException.java | 7 +++++ .../common/exception/ConflictException.java | 7 +++++ .../common/exception/ForbiddenException.java | 7 +++++ .../exception/MethodNotAllowedException.java | 7 +++++ .../common/exception/NotFoundException.java | 7 +++++ .../exception/UnauthorizedException.java | 7 +++++ 7 files changed, 69 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java create mode 100644 src/main/java/camp/woowak/lab/common/exception/BadRequestException.java create mode 100644 src/main/java/camp/woowak/lab/common/exception/ConflictException.java create mode 100644 src/main/java/camp/woowak/lab/common/exception/ForbiddenException.java create mode 100644 src/main/java/camp/woowak/lab/common/exception/MethodNotAllowedException.java create mode 100644 src/main/java/camp/woowak/lab/common/exception/NotFoundException.java create mode 100644 src/main/java/camp/woowak/lab/common/exception/UnauthorizedException.java diff --git a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java new file mode 100644 index 00000000..6f9bc5fc --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java @@ -0,0 +1,27 @@ +package camp.woowak.lab.common.advice; + +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(Exception.class) + public ResponseEntity handleAllUncaughtException(Exception e) { + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.INTERNAL_SERVER_ERROR, + e.getMessage()); + problemDetail.setProperty("errorCode", "9999"); + + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(problemDetail); + } +} diff --git a/src/main/java/camp/woowak/lab/common/exception/BadRequestException.java b/src/main/java/camp/woowak/lab/common/exception/BadRequestException.java new file mode 100644 index 00000000..3b4d4090 --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/BadRequestException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public class BadRequestException extends HttpStatusException { + public BadRequestException(ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/camp/woowak/lab/common/exception/ConflictException.java b/src/main/java/camp/woowak/lab/common/exception/ConflictException.java new file mode 100644 index 00000000..e7b16219 --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/ConflictException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public class ConflictException extends HttpStatusException { + public ConflictException(ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/camp/woowak/lab/common/exception/ForbiddenException.java b/src/main/java/camp/woowak/lab/common/exception/ForbiddenException.java new file mode 100644 index 00000000..05ab0863 --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/ForbiddenException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public class ForbiddenException extends HttpStatusException { + public ForbiddenException(ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/camp/woowak/lab/common/exception/MethodNotAllowedException.java b/src/main/java/camp/woowak/lab/common/exception/MethodNotAllowedException.java new file mode 100644 index 00000000..6704a8cd --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/MethodNotAllowedException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public class MethodNotAllowedException extends HttpStatusException { + public MethodNotAllowedException(ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/camp/woowak/lab/common/exception/NotFoundException.java b/src/main/java/camp/woowak/lab/common/exception/NotFoundException.java new file mode 100644 index 00000000..6928975e --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/NotFoundException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public class NotFoundException extends HttpStatusException { + public NotFoundException(ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/camp/woowak/lab/common/exception/UnauthorizedException.java b/src/main/java/camp/woowak/lab/common/exception/UnauthorizedException.java new file mode 100644 index 00000000..ba2e1237 --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/UnauthorizedException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public class UnauthorizedException extends HttpStatusException { + public UnauthorizedException(ErrorCode errorCode) { + super(errorCode); + } +} From bb1fa119c244dcef0253859b54edd5ce85d2e275 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Mon, 12 Aug 2024 21:09:31 +0900 Subject: [PATCH 060/146] =?UTF-8?q?[feat]=20ErrorCode=20interface=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/camp/woowak/lab/common/exception/ErrorCode.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/common/exception/ErrorCode.java diff --git a/src/main/java/camp/woowak/lab/common/exception/ErrorCode.java b/src/main/java/camp/woowak/lab/common/exception/ErrorCode.java new file mode 100644 index 00000000..54a2beda --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/ErrorCode.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public interface ErrorCode { + int getStatus(); + String getErrorCode(); + String getMessage(); +} From ee1c8beb3dc80dae4074e46d10f69550fedac476 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Mon, 12 Aug 2024 21:15:55 +0900 Subject: [PATCH 061/146] =?UTF-8?q?[feat]=20CustomRestControllerAdvice=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20ControllerAdvice=20=EA=B8=B0=EB=B3=B8?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EC=9A=B0=EC=84=A0=20=EC=88=9C=EC=9C=84?= =?UTF-8?q?=20=EB=AC=B8=EC=A0=9C=20=EB=95=8C=EB=AC=B8=EC=97=90=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=ED=95=9C=20CustomRestControllerAdvice=20-=20=EA=B8=B0?= =?UTF-8?q?=EC=A1=B4=20RestControllerAdvice=20=EB=B3=B4=EB=8B=A4=20?= =?UTF-8?q?=EC=9A=B0=EC=84=A0=20=EC=88=9C=EC=9C=84=EA=B0=80=20=ED=95=9C=20?= =?UTF-8?q?=EB=8B=A8=EA=B3=84=20=EB=86=92=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../advice/CustomRestControllerAdvice.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java diff --git a/src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java b/src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java new file mode 100644 index 00000000..4fd5b48a --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java @@ -0,0 +1,27 @@ +package camp.woowak.lab.common.advice; + +import org.springframework.core.Ordered; +import org.springframework.core.annotation.AliasFor; +import org.springframework.core.annotation.Order; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@RestControllerAdvice +@Order(Ordered.LOWEST_PRECEDENCE - 1) +public @interface CustomRestControllerAdvice { + @AliasFor(annotation = RestControllerAdvice.class, attribute = "basePackages") + String[] basePackages() default {}; + + @AliasFor(annotation = RestControllerAdvice.class, attribute = "basePackageClasses") + Class[] basePackageClasses() default {}; + + @AliasFor(annotation = RestControllerAdvice.class, attribute = "assignableTypes") + Class[] assignableTypes() default {}; + + @AliasFor(annotation = RestControllerAdvice.class, attribute = "annotations") + Class[] annotations() default {}; +} From 4910979a5ed5bceda0c406c6dbfdebb1d0aaccd9 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Mon, 12 Aug 2024 21:23:02 +0900 Subject: [PATCH 062/146] =?UTF-8?q?[chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/common/advice/GlobalExceptionHandler.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java index 6f9bc5fc..69c86318 100644 --- a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java +++ b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java @@ -1,12 +1,9 @@ package camp.woowak.lab.common.advice; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; import org.springframework.http.HttpStatus; import org.springframework.http.ProblemDetail; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import lombok.extern.slf4j.Slf4j; From d66b8e60cbf427cdb601dd7cbf0f5a2ad2a42ece Mon Sep 17 00:00:00 2001 From: donghar Date: Mon, 12 Aug 2024 21:26:33 +0900 Subject: [PATCH 063/146] [test] SessionCustomerArgumentResolver `+` supportsParameter `+` resolveArgument --- .../SessionCustomerArgumentResolverTest.java | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolverTest.java diff --git a/src/test/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolverTest.java b/src/test/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolverTest.java new file mode 100644 index 00000000..4b327d49 --- /dev/null +++ b/src/test/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolverTest.java @@ -0,0 +1,135 @@ +package camp.woowak.lab.web.resolver.session; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.lang.annotation.Annotation; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +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 org.springframework.core.MethodParameter; +import org.springframework.web.context.request.NativeWebRequest; + +import camp.woowak.lab.common.exception.UnauthorizedRequestException; +import camp.woowak.lab.web.authentication.LoginCustomer; +import camp.woowak.lab.web.authentication.LoginVendor; +import camp.woowak.lab.web.authentication.annotation.AuthenticationPrincipal; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpSession; + +@ExtendWith(MockitoExtension.class) +public class SessionCustomerArgumentResolverTest { + @InjectMocks + private SessionCustomerArgumentResolver resolver; + @Mock + private MethodParameter methodParameter; + @Mock + private NativeWebRequest webRequest; + @Mock + private HttpServletRequest request; + @Mock + private HttpSession session; + @Mock + private LoginCustomer mockCustomer; + + @Nested + @DisplayName("supportsParameter") + class SupportsParameter { + @Test + @DisplayName("[True] 파라미터에 @AuthenticationPrincipal이 붙은 경우") + public void supportsParameter_ReturnsTrue_WhenCorrectAnnotationAndType() { + when(methodParameter.hasParameterAnnotation(AuthenticationPrincipal.class)).thenReturn(true); + when(methodParameter.getParameterType()).thenReturn((Class)LoginCustomer.class); + + boolean supports = resolver.supportsParameter(methodParameter); + + assertThat(supports).isTrue(); + } + + @Test + @DisplayName("[False] 파라미터가 LoginCustomer가 아닌 경우") + public void supportsParameter_ReturnsTrue_WhenIncorrectType() { + when(methodParameter.hasParameterAnnotation(AuthenticationPrincipal.class)).thenReturn(true); + when(methodParameter.getParameterType()).thenReturn((Class)LoginVendor.class); + + boolean supports = resolver.supportsParameter(methodParameter); + + assertThat(supports).isFalse(); + } + + @Test + @DisplayName("[False] 파라미터에 @AuthenticationPrincipal이 붙지 않은 경우") + public void supportsParameter_ReturnsFalse_WhenIncorrectAnnotationOrType() { + when(methodParameter.hasParameterAnnotation(AuthenticationPrincipal.class)).thenReturn(false); + + boolean supports = resolver.supportsParameter(methodParameter); + + assertThat(supports).isFalse(); + } + } + + @Nested + @DisplayName("resolveArgument") + class ResolveArgument { + @Test + @DisplayName("[LoginCustomer] 세션에 LoginCustomer가 있는 경우") + public void resolveArgument_ReturnsCustomer_WhenSessionExists() throws Exception { + when(webRequest.getNativeRequest()).thenReturn(request); + when(request.getSession(false)).thenReturn(session); + when(session.getAttribute(SessionConst.SESSION_CUSTOMER_KEY)).thenReturn(mockCustomer); + when(methodParameter.getParameterAnnotation(AuthenticationPrincipal.class)).thenReturn( + new AuthenticationPrincipal() { + @Override + public Class annotationType() { + return null; + } + + @Override + public boolean required() { + return true; + } + } + ); + + Object result = resolver.resolveArgument(methodParameter, null, webRequest, null); + + assertThat(result).isEqualTo(mockCustomer); + } + + @Test + @DisplayName("[Null] 파라미터에 @AuthenticationPrincipal이 붙지 않은 경우") + public void resolveArgument_ReturnsNull_WhenSessionDoesNotExist() throws Exception { + Object result = resolver.resolveArgument(methodParameter, null, webRequest, null); + + assertThat(result).isNull(); + } + + @Test + @DisplayName("[UnauthorizedRequestException] @AuthenticationPrincipal(required=true)인데 세션이 LoginCustomer가 없는 경우") + public void resolveArgument_ThrowsException_WhenSessionRequiredButMissing() { + when(webRequest.getNativeRequest()).thenReturn(request); + when(methodParameter.getParameterAnnotation(AuthenticationPrincipal.class)).thenReturn( + new AuthenticationPrincipal() { + @Override + public boolean required() { + return true; + } + + @Override + public Class annotationType() { + return AuthenticationPrincipal.class; + } + }); + + assertThrows( + UnauthorizedRequestException.class, + () -> resolver.resolveArgument(methodParameter, null, webRequest, null)); + } + } +} From 1288adb30c5ccb28faf6252e2c57d366dfa5e6e9 Mon Sep 17 00:00:00 2001 From: donghar Date: Mon, 12 Aug 2024 21:26:42 +0900 Subject: [PATCH 064/146] [test] SessionVendorArgumentResolver `+` supportsParameter `+` resolveArgument --- .../SessionVendorArgumentResolverTest.java | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolverTest.java diff --git a/src/test/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolverTest.java b/src/test/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolverTest.java new file mode 100644 index 00000000..36e7db30 --- /dev/null +++ b/src/test/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolverTest.java @@ -0,0 +1,135 @@ +package camp.woowak.lab.web.resolver.session; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.lang.annotation.Annotation; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +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 org.springframework.core.MethodParameter; +import org.springframework.web.context.request.NativeWebRequest; + +import camp.woowak.lab.common.exception.UnauthorizedRequestException; +import camp.woowak.lab.web.authentication.LoginCustomer; +import camp.woowak.lab.web.authentication.LoginVendor; +import camp.woowak.lab.web.authentication.annotation.AuthenticationPrincipal; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpSession; + +@ExtendWith(MockitoExtension.class) +class SessionVendorArgumentResolverTest { + @InjectMocks + private SessionVendorArgumentResolver resolver; + @Mock + private MethodParameter methodParameter; + @Mock + private NativeWebRequest webRequest; + @Mock + private HttpServletRequest request; + @Mock + private HttpSession session; + @Mock + private LoginVendor mockVendor; + + @Nested + @DisplayName("supportsParameter") + class SupportsParameter { + @Test + @DisplayName("[True] 파라미터에 @AuthenticationPrincipal이 붙은 경우") + public void supportsParameter_ReturnsTrue_WhenCorrectAnnotationAndType() { + when(methodParameter.hasParameterAnnotation(AuthenticationPrincipal.class)).thenReturn(true); + when(methodParameter.getParameterType()).thenReturn((Class)LoginVendor.class); + + boolean supports = resolver.supportsParameter(methodParameter); + + assertThat(supports).isTrue(); + } + + @Test + @DisplayName("[False] 파라미터가 LoginVendor가 아닌 경우") + public void supportsParameter_ReturnsTrue_WhenIncorrectType() { + when(methodParameter.hasParameterAnnotation(AuthenticationPrincipal.class)).thenReturn(true); + when(methodParameter.getParameterType()).thenReturn((Class)LoginCustomer.class); + + boolean supports = resolver.supportsParameter(methodParameter); + + assertThat(supports).isFalse(); + } + + @Test + @DisplayName("[False] 파라미터에 @AuthenticationPrincipal이 붙지 않은 경우") + public void supportsParameter_ReturnsFalse_WhenIncorrectAnnotationOrType() { + when(methodParameter.hasParameterAnnotation(AuthenticationPrincipal.class)).thenReturn(false); + + boolean supports = resolver.supportsParameter(methodParameter); + + assertThat(supports).isFalse(); + } + } + + @Nested + @DisplayName("resolveArgument") + class ResolveArgument { + @Test + @DisplayName("[LoginVendor] 세션에 LoginVendor 있는 경우") + public void resolveArgument_ReturnsVendor_WhenSessionExists() throws Exception { + when(webRequest.getNativeRequest()).thenReturn(request); + when(request.getSession(false)).thenReturn(session); + when(session.getAttribute(SessionConst.SESSION_VENDOR_KEY)).thenReturn(mockVendor); + when(methodParameter.getParameterAnnotation(AuthenticationPrincipal.class)).thenReturn( + new AuthenticationPrincipal() { + @Override + public Class annotationType() { + return null; + } + + @Override + public boolean required() { + return true; + } + } + ); + + Object result = resolver.resolveArgument(methodParameter, null, webRequest, null); + + assertThat(result).isEqualTo(mockVendor); + } + + @Test + @DisplayName("[Null] 파라미터에 @AuthenticationPrincipal이 붙지 않은 경우") + public void resolveArgument_ReturnsNull_WhenSessionDoesNotExist() throws Exception { + Object result = resolver.resolveArgument(methodParameter, null, webRequest, null); + + assertThat(result).isNull(); + } + + @Test + @DisplayName("[UnauthorizedRequestException] @AuthenticationPrincipal(required=true)인데 세션이 LoginVendor가 없는 경우") + public void resolveArgument_ThrowsException_WhenSessionRequiredButMissing() { + when(webRequest.getNativeRequest()).thenReturn(request); + when(methodParameter.getParameterAnnotation(AuthenticationPrincipal.class)).thenReturn( + new AuthenticationPrincipal() { + @Override + public boolean required() { + return true; + } + + @Override + public Class annotationType() { + return AuthenticationPrincipal.class; + } + }); + + assertThrows( + UnauthorizedRequestException.class, + () -> resolver.resolveArgument(methodParameter, null, webRequest, null)); + } + } +} From 6d08742adb007b339805d28cb50be5fb5c3cb395 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Mon, 12 Aug 2024 22:01:48 +0900 Subject: [PATCH 065/146] =?UTF-8?q?[refactor]=20CustomRestControllerAdvice?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD=20-=20DomainExceptio?= =?UTF-8?q?nHandler=20=EB=A1=9C=20=EB=B3=80=EA=B2=BD=ED=96=88=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...trollerAdvice.java => DomainExceptionHandler.java} | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) rename src/main/java/camp/woowak/lab/common/advice/{CustomRestControllerAdvice.java => DomainExceptionHandler.java} (76%) diff --git a/src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java b/src/main/java/camp/woowak/lab/common/advice/DomainExceptionHandler.java similarity index 76% rename from src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java rename to src/main/java/camp/woowak/lab/common/advice/DomainExceptionHandler.java index 4fd5b48a..56a9c564 100644 --- a/src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java +++ b/src/main/java/camp/woowak/lab/common/advice/DomainExceptionHandler.java @@ -1,18 +1,23 @@ package camp.woowak.lab.common.advice; +import java.lang.annotation.Annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + import org.springframework.core.Ordered; import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.Order; import org.springframework.web.bind.annotation.RestControllerAdvice; -import java.lang.annotation.*; - @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @RestControllerAdvice @Order(Ordered.LOWEST_PRECEDENCE - 1) -public @interface CustomRestControllerAdvice { +public @interface DomainExceptionHandler { @AliasFor(annotation = RestControllerAdvice.class, attribute = "basePackages") String[] basePackages() default {}; From a7d1ead51c1a1dfcf93902b78aa160634e12aa41 Mon Sep 17 00:00:00 2001 From: donghar Date: Mon, 12 Aug 2024 23:43:24 +0900 Subject: [PATCH 066/146] =?UTF-8?q?[feat]=20=EC=9D=B8=EC=A6=9D=20=EB=8B=B4?= =?UTF-8?q?=EB=8B=B9=20ErrorCode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuthenticationErrorCode.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/authentication/AuthenticationErrorCode.java diff --git a/src/main/java/camp/woowak/lab/web/authentication/AuthenticationErrorCode.java b/src/main/java/camp/woowak/lab/web/authentication/AuthenticationErrorCode.java new file mode 100644 index 00000000..9e635a74 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/authentication/AuthenticationErrorCode.java @@ -0,0 +1,34 @@ +package camp.woowak.lab.web.authentication; + +import org.springframework.http.HttpStatus; + +import camp.woowak.lab.common.exception.ErrorCode; + +public enum AuthenticationErrorCode implements ErrorCode { + UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "a1", "로그인이 필요합니다."); + + private final int status; + private final String errorCode; + private final String message; + + AuthenticationErrorCode(HttpStatus httpStatus, String errorCode, String message) { + this.status = httpStatus.value(); + this.errorCode = errorCode; + this.message = message; + } + + @Override + public int getStatus() { + return status; + } + + @Override + public String getErrorCode() { + return errorCode; + } + + @Override + public String getMessage() { + return message; + } +} From 2a005de998b6fa29c0435956571363e48a30c710 Mon Sep 17 00:00:00 2001 From: donghar Date: Mon, 12 Aug 2024 23:43:43 +0900 Subject: [PATCH 067/146] =?UTF-8?q?[refactor]=20ErrorCode=EC=9D=98=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=82=AC=EC=9D=B4=20=EA=B0=9C?= =?UTF-8?q?=ED=96=89=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/common/exception/ErrorCode.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/camp/woowak/lab/common/exception/ErrorCode.java b/src/main/java/camp/woowak/lab/common/exception/ErrorCode.java index 54a2beda..93bd938f 100644 --- a/src/main/java/camp/woowak/lab/common/exception/ErrorCode.java +++ b/src/main/java/camp/woowak/lab/common/exception/ErrorCode.java @@ -2,6 +2,8 @@ public interface ErrorCode { int getStatus(); + String getErrorCode(); + String getMessage(); } From 2b80d0d21cfcb0d7e3948d5ff3382655bc0f397e Mon Sep 17 00:00:00 2001 From: donghar Date: Mon, 12 Aug 2024 23:44:48 +0900 Subject: [PATCH 068/146] =?UTF-8?q?[fix]=20common=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=ED=95=98=EB=8B=A8=EC=9D=98=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UnauthorizedRequestException -> UnauthorizedException --- .../lab/common/exception/UnauthorizedRequestException.java | 6 ------ .../resolver/session/SessionCustomerArgumentResolver.java | 5 +++-- .../web/resolver/session/SessionVendorArgumentResolver.java | 5 +++-- .../session/SessionCustomerArgumentResolverTest.java | 4 ++-- .../resolver/session/SessionVendorArgumentResolverTest.java | 4 ++-- 5 files changed, 10 insertions(+), 14 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/common/exception/UnauthorizedRequestException.java diff --git a/src/main/java/camp/woowak/lab/common/exception/UnauthorizedRequestException.java b/src/main/java/camp/woowak/lab/common/exception/UnauthorizedRequestException.java deleted file mode 100644 index 2b6e2919..00000000 --- a/src/main/java/camp/woowak/lab/common/exception/UnauthorizedRequestException.java +++ /dev/null @@ -1,6 +0,0 @@ -package camp.woowak.lab.common.exception; - -public class UnauthorizedRequestException extends RuntimeException { - public UnauthorizedRequestException(String message) { - } -} diff --git a/src/main/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolver.java b/src/main/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolver.java index 2d2ffe12..a172b231 100644 --- a/src/main/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolver.java +++ b/src/main/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolver.java @@ -5,7 +5,8 @@ import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.ModelAndViewContainer; -import camp.woowak.lab.common.exception.UnauthorizedRequestException; +import camp.woowak.lab.common.exception.UnauthorizedException; +import camp.woowak.lab.web.authentication.AuthenticationErrorCode; import camp.woowak.lab.web.authentication.LoginCustomer; import camp.woowak.lab.web.authentication.annotation.AuthenticationPrincipal; import jakarta.servlet.http.HttpServletRequest; @@ -29,7 +30,7 @@ public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer m HttpSession session = request.getSession(false); if (parameterAnnotation.required() && (session == null || session.getAttribute(SessionConst.SESSION_CUSTOMER_KEY) == null)) { - throw new UnauthorizedRequestException("Required session is null"); + throw new UnauthorizedException(AuthenticationErrorCode.UNAUTHORIZED); } return session == null ? null : session.getAttribute(SessionConst.SESSION_CUSTOMER_KEY); } diff --git a/src/main/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolver.java b/src/main/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolver.java index a0cafcaf..c6cafbfd 100644 --- a/src/main/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolver.java +++ b/src/main/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolver.java @@ -5,7 +5,8 @@ import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.ModelAndViewContainer; -import camp.woowak.lab.common.exception.UnauthorizedRequestException; +import camp.woowak.lab.common.exception.UnauthorizedException; +import camp.woowak.lab.web.authentication.AuthenticationErrorCode; import camp.woowak.lab.web.authentication.LoginVendor; import camp.woowak.lab.web.authentication.annotation.AuthenticationPrincipal; import jakarta.servlet.http.HttpServletRequest; @@ -29,7 +30,7 @@ public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer m HttpSession session = request.getSession(false); if (parameterAnnotation.required() && (session == null || session.getAttribute(SessionConst.SESSION_VENDOR_KEY) == null)) { - throw new UnauthorizedRequestException("Required session is null"); + throw new UnauthorizedException(AuthenticationErrorCode.UNAUTHORIZED); } return session == null ? null : session.getAttribute(SessionConst.SESSION_VENDOR_KEY); } diff --git a/src/test/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolverTest.java b/src/test/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolverTest.java index 4b327d49..2d9e1590 100644 --- a/src/test/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolverTest.java +++ b/src/test/java/camp/woowak/lab/web/resolver/session/SessionCustomerArgumentResolverTest.java @@ -16,7 +16,7 @@ import org.springframework.core.MethodParameter; import org.springframework.web.context.request.NativeWebRequest; -import camp.woowak.lab.common.exception.UnauthorizedRequestException; +import camp.woowak.lab.common.exception.UnauthorizedException; import camp.woowak.lab.web.authentication.LoginCustomer; import camp.woowak.lab.web.authentication.LoginVendor; import camp.woowak.lab.web.authentication.annotation.AuthenticationPrincipal; @@ -128,7 +128,7 @@ public Class annotationType() { }); assertThrows( - UnauthorizedRequestException.class, + UnauthorizedException.class, () -> resolver.resolveArgument(methodParameter, null, webRequest, null)); } } diff --git a/src/test/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolverTest.java b/src/test/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolverTest.java index 36e7db30..07ff28c0 100644 --- a/src/test/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolverTest.java +++ b/src/test/java/camp/woowak/lab/web/resolver/session/SessionVendorArgumentResolverTest.java @@ -16,7 +16,7 @@ import org.springframework.core.MethodParameter; import org.springframework.web.context.request.NativeWebRequest; -import camp.woowak.lab.common.exception.UnauthorizedRequestException; +import camp.woowak.lab.common.exception.UnauthorizedException; import camp.woowak.lab.web.authentication.LoginCustomer; import camp.woowak.lab.web.authentication.LoginVendor; import camp.woowak.lab.web.authentication.annotation.AuthenticationPrincipal; @@ -128,7 +128,7 @@ public Class annotationType() { }); assertThrows( - UnauthorizedRequestException.class, + UnauthorizedException.class, () -> resolver.resolveArgument(methodParameter, null, webRequest, null)); } } From f9073b5c75b872fb7c73a2b919fba60416de3812 Mon Sep 17 00:00:00 2001 From: donghar Date: Tue, 13 Aug 2024 00:41:08 +0900 Subject: [PATCH 069/146] =?UTF-8?q?[fix]=20=EC=A0=84=EC=97=AD=20ExceptionH?= =?UTF-8?q?andler=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `-` 기존에 등록된 ExceptionHandler `~` 새로운 ExceptionHandler에 ResponseEntityExceptionHandler 상속 --- .../woowak/lab/common/advice/GlobalExceptionHandler.java | 3 ++- .../camp/woowak/lab/web/api/GlobalExceptionHandler.java | 9 --------- 2 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/web/api/GlobalExceptionHandler.java diff --git a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java index 69c86318..78dede28 100644 --- a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java +++ b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java @@ -5,12 +5,13 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import lombok.extern.slf4j.Slf4j; @Slf4j @RestControllerAdvice -public class GlobalExceptionHandler { +public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity handleAllUncaughtException(Exception e) { diff --git a/src/main/java/camp/woowak/lab/web/api/GlobalExceptionHandler.java b/src/main/java/camp/woowak/lab/web/api/GlobalExceptionHandler.java deleted file mode 100644 index fe0ac45b..00000000 --- a/src/main/java/camp/woowak/lab/web/api/GlobalExceptionHandler.java +++ /dev/null @@ -1,9 +0,0 @@ -package camp.woowak.lab.web.api; - -import org.springframework.web.bind.annotation.RestControllerAdvice; -import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; - -@RestControllerAdvice -public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { - -} From 49d8714547a319f00e1a184d606940e64b86798d Mon Sep 17 00:00:00 2001 From: donghar Date: Tue, 13 Aug 2024 00:42:11 +0900 Subject: [PATCH 070/146] [fix] DuplicateEmailException MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HttpStatusException을 상속하는 구조로 변경 --- .../lab/vendor/exception/DuplicateEmailException.java | 7 ++++++- .../woowak/lab/vendor/exception/DuplicateException.java | 4 ---- 2 files changed, 6 insertions(+), 5 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/vendor/exception/DuplicateException.java diff --git a/src/main/java/camp/woowak/lab/vendor/exception/DuplicateEmailException.java b/src/main/java/camp/woowak/lab/vendor/exception/DuplicateEmailException.java index e4b34724..d0867c72 100644 --- a/src/main/java/camp/woowak/lab/vendor/exception/DuplicateEmailException.java +++ b/src/main/java/camp/woowak/lab/vendor/exception/DuplicateEmailException.java @@ -1,4 +1,9 @@ package camp.woowak.lab.vendor.exception; -public class DuplicateEmailException extends DuplicateException { +import camp.woowak.lab.common.exception.BadRequestException; + +public class DuplicateEmailException extends BadRequestException { + public DuplicateEmailException() { + super(VendorErrorCode.DUPLICATE_EMAIL); + } } diff --git a/src/main/java/camp/woowak/lab/vendor/exception/DuplicateException.java b/src/main/java/camp/woowak/lab/vendor/exception/DuplicateException.java deleted file mode 100644 index 11599090..00000000 --- a/src/main/java/camp/woowak/lab/vendor/exception/DuplicateException.java +++ /dev/null @@ -1,4 +0,0 @@ -package camp.woowak.lab.vendor.exception; - -public abstract class DuplicateException extends Exception { -} From a967a2c1da8111217678ce827ceffdda47f8f8da Mon Sep 17 00:00:00 2001 From: donghar Date: Tue, 13 Aug 2024 00:44:09 +0900 Subject: [PATCH 071/146] =?UTF-8?q?[feat]=20Vendor=20=EC=A0=84=EC=9A=A9=20?= =?UTF-8?q?ErrorCode=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/vendor/exception/VendorErrorCode.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/vendor/exception/VendorErrorCode.java diff --git a/src/main/java/camp/woowak/lab/vendor/exception/VendorErrorCode.java b/src/main/java/camp/woowak/lab/vendor/exception/VendorErrorCode.java new file mode 100644 index 00000000..8ff33311 --- /dev/null +++ b/src/main/java/camp/woowak/lab/vendor/exception/VendorErrorCode.java @@ -0,0 +1,43 @@ +package camp.woowak.lab.vendor.exception; + +import org.springframework.http.HttpStatus; + +import camp.woowak.lab.common.exception.ErrorCode; + +public enum VendorErrorCode implements ErrorCode { + INVALID_PHONE_EMPTY(HttpStatus.BAD_REQUEST, "v_1_1", "전화번호가 입력되지 않았습니다."), + INVALID_PHONE_RANGE(HttpStatus.BAD_REQUEST, "v_1_2", "전화번호는 30자를 넘을 수 없습니다."), + INVALID_PASSWORD_EMPTY(HttpStatus.BAD_REQUEST, "v1_3", "비밀번호가 입력되지 않았습니다."), + INVALID_PASSWORD_RANGE(HttpStatus.BAD_REQUEST, "v1_4", "비밀번호는 8-30자 입력되어야 합니다."), + INVALID_EMAIL_EMPTY(HttpStatus.BAD_REQUEST, "v1_5", "이메일이 입력되지 않았습니다."), + INVALID_EMAIL_RANGE(HttpStatus.BAD_REQUEST, "v1_6", "이메일은 100자를 넘을 수 없습니다."), + INVALID_NAME_EMPTY(HttpStatus.BAD_REQUEST, "v1_7", "이름이 입력되지 않았습니다."), + INVALID_NAME_RANGE(HttpStatus.BAD_REQUEST, "v1_8", "이름은 50자를 넘을 수 없습니다."), + INVALID_PAY_ACCOUNT_EMPTY(HttpStatus.BAD_REQUEST, "v_1_9", "포인트 계좌가 입력되지 않았습니다."), + DUPLICATE_EMAIL(HttpStatus.BAD_REQUEST, "v_2", "이미 가입된 이메일입니다."); + + private final int status; + private final String errorCode; + private final String message; + + VendorErrorCode(HttpStatus httpStatus, String errorCode, String message) { + this.status = httpStatus.value(); + this.errorCode = errorCode; + this.message = message; + } + + @Override + public int getStatus() { + return status; + } + + @Override + public String getErrorCode() { + return errorCode; + } + + @Override + public String getMessage() { + return message; + } +} From 819b08d7d61da0333a2c66b21f3d467ef27058e7 Mon Sep 17 00:00:00 2001 From: donghar Date: Tue, 13 Aug 2024 00:44:56 +0900 Subject: [PATCH 072/146] =?UTF-8?q?[fix]=20Vandor=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=EC=97=90=EC=84=9C=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 검증 로직은 VendorValidator에서 수행 --- .../camp/woowak/lab/vendor/domain/Vendor.java | 57 ++--------------- .../lab/vendor/domain/VendorValidator.java | 64 +++++++++++++++++++ .../InvalidVendorCreationException.java | 10 +++ 3 files changed, 81 insertions(+), 50 deletions(-) create mode 100644 src/main/java/camp/woowak/lab/vendor/domain/VendorValidator.java create mode 100644 src/main/java/camp/woowak/lab/vendor/exception/InvalidVendorCreationException.java diff --git a/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java b/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java index 8c1866c0..910eb8e4 100644 --- a/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java +++ b/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java @@ -1,7 +1,7 @@ package camp.woowak.lab.vendor.domain; import camp.woowak.lab.payaccount.domain.PayAccount; -import camp.woowak.lab.vendor.exception.InvalidCreationException; +import camp.woowak.lab.vendor.exception.InvalidVendorCreationException; import camp.woowak.lab.web.authentication.PasswordEncoder; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -30,13 +30,13 @@ public class Vendor { protected Vendor() { } + /** + * + * @throws InvalidVendorCreationException 검증에 실패하면 + */ public Vendor(String name, String email, String password, String phone, PayAccount payAccount, - PasswordEncoder passwordEncoder) throws InvalidCreationException { - checkName(name); - checkEmail(email); - checkPassword(password); - checkPhone(phone); - checkPayAccount(payAccount); + PasswordEncoder passwordEncoder) { + VendorValidator.validate(name, email, password, phone, payAccount); this.name = name; this.email = email; this.password = passwordEncoder.encode(password); @@ -47,47 +47,4 @@ public Vendor(String name, String email, String password, String phone, PayAccou public Long getId() { return id; } - - private void checkPayAccount(PayAccount payAccount) throws InvalidCreationException { - if (payAccount == null) { - throw new InvalidCreationException("Pay account cannot be null"); - } - } - - private void checkPhone(String phone) throws InvalidCreationException { - if (phone == null || phone.isBlank()) { - throw new InvalidCreationException("Vendor phone cannot be blank"); - } - if (phone.trim().length() > 30) { - throw new InvalidCreationException("Vendor phone cannot be longer than 30 characters"); - } - } - - private void checkPassword(String password) throws InvalidCreationException { - if (password == null || password.isBlank()) { - throw new InvalidCreationException("Vendor password cannot be blank"); - } - if (password.trim().length() < 8 || password.trim().length() > 30) { - throw new InvalidCreationException( - "Vendor password must be at least 8 characters and at most 30 characters"); - } - } - - private void checkEmail(String email) throws InvalidCreationException { - if (email == null || email.isBlank()) { - throw new InvalidCreationException("Vendor email cannot be blank"); - } - if (email.trim().length() > 100) { - throw new InvalidCreationException("Vendor email cannot be longer than 100 characters"); - } - } - - private void checkName(String name) throws InvalidCreationException { - if (name == null || name.isBlank()) { - throw new InvalidCreationException("Vendor name cannot be blank"); - } - if (name.length() > 50) { - throw new InvalidCreationException("Vendor name cannot exceed 50 characters"); - } - } } diff --git a/src/main/java/camp/woowak/lab/vendor/domain/VendorValidator.java b/src/main/java/camp/woowak/lab/vendor/domain/VendorValidator.java new file mode 100644 index 00000000..6f8dcf0d --- /dev/null +++ b/src/main/java/camp/woowak/lab/vendor/domain/VendorValidator.java @@ -0,0 +1,64 @@ +package camp.woowak.lab.vendor.domain; + +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.vendor.exception.InvalidVendorCreationException; +import camp.woowak.lab.vendor.exception.VendorErrorCode; + +public final class VendorValidator { + private static final int MAX_NAME_LENGTH = 50; + private static final int MAX_EMAIL_LENGTH = 100; + private static final int MIN_PASSWORD_LENGTH = 8; + private static final int MAX_PASSWORD_LENGTH = 30; + private static final int MAX_PHONE_LENGTH = 30; + + public static void validate(final String name, final String email, final String password, final String phone, + final PayAccount payAccount) throws InvalidVendorCreationException { + checkName(name); + checkEmail(email); + checkPassword(password); + checkPhone(phone); + checkPayAccount(payAccount); + } + + private static void checkName(String name) throws InvalidVendorCreationException { + if (name == null || name.isBlank()) { + throw new InvalidVendorCreationException(VendorErrorCode.INVALID_NAME_EMPTY); + } + if (name.length() > MAX_NAME_LENGTH) { + throw new InvalidVendorCreationException(VendorErrorCode.INVALID_NAME_RANGE); + } + } + + private static void checkEmail(String email) throws InvalidVendorCreationException { + if (email == null || email.isBlank()) { + throw new InvalidVendorCreationException(VendorErrorCode.INVALID_EMAIL_EMPTY); + } + if (email.trim().length() > MAX_EMAIL_LENGTH) { + throw new InvalidVendorCreationException(VendorErrorCode.INVALID_EMAIL_RANGE); + } + } + + private static void checkPassword(String password) throws InvalidVendorCreationException { + if (password == null || password.isBlank()) { + throw new InvalidVendorCreationException(VendorErrorCode.INVALID_PASSWORD_EMPTY); + } + if (password.trim().length() < MIN_PASSWORD_LENGTH || password.trim().length() > MAX_PASSWORD_LENGTH) { + throw new InvalidVendorCreationException(VendorErrorCode.INVALID_PASSWORD_RANGE); + } + } + + private static void checkPhone(String phone) throws InvalidVendorCreationException { + if (phone == null || phone.isBlank()) { + throw new InvalidVendorCreationException(VendorErrorCode.INVALID_PHONE_EMPTY); + } + if (phone.trim().length() > MAX_PHONE_LENGTH) { + throw new InvalidVendorCreationException(VendorErrorCode.INVALID_PHONE_RANGE); + } + } + + private static void checkPayAccount(PayAccount payAccount) throws InvalidVendorCreationException { + if (payAccount == null) { + throw new InvalidVendorCreationException(VendorErrorCode.INVALID_PAY_ACCOUNT_EMPTY); + } + } +} diff --git a/src/main/java/camp/woowak/lab/vendor/exception/InvalidVendorCreationException.java b/src/main/java/camp/woowak/lab/vendor/exception/InvalidVendorCreationException.java new file mode 100644 index 00000000..ded3d009 --- /dev/null +++ b/src/main/java/camp/woowak/lab/vendor/exception/InvalidVendorCreationException.java @@ -0,0 +1,10 @@ +package camp.woowak.lab.vendor.exception; + +import camp.woowak.lab.common.exception.BadRequestException; +import camp.woowak.lab.common.exception.ErrorCode; + +public class InvalidVendorCreationException extends BadRequestException { + public InvalidVendorCreationException(ErrorCode errorCode) { + super(errorCode); + } +} From 033b7592db08f04a7b69b513acdc64090fd83344 Mon Sep 17 00:00:00 2001 From: donghar Date: Tue, 13 Aug 2024 00:45:45 +0900 Subject: [PATCH 073/146] =?UTF-8?q?[test]=20Vandor=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Exception 계층 수정으로 인한 테스트 코드 수정 --- .../woowak/lab/fixture/VendorFixture.java | 10 ++----- .../woowak/lab/vendor/domain/VendorTest.java | 30 +++++++++---------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/test/java/camp/woowak/lab/fixture/VendorFixture.java b/src/test/java/camp/woowak/lab/fixture/VendorFixture.java index ce05a9fb..ccf7063d 100644 --- a/src/test/java/camp/woowak/lab/fixture/VendorFixture.java +++ b/src/test/java/camp/woowak/lab/fixture/VendorFixture.java @@ -2,7 +2,6 @@ import camp.woowak.lab.payaccount.domain.PayAccount; import camp.woowak.lab.vendor.domain.Vendor; -import camp.woowak.lab.vendor.exception.InvalidCreationException; import camp.woowak.lab.web.authentication.PasswordEncoder; public interface VendorFixture { @@ -11,12 +10,7 @@ default PayAccount createPayAccount() { } default Vendor createVendor(PayAccount payAccount, PasswordEncoder passwordEncoder) { - try { - return new Vendor("vendorName", "vendorEmail@example.com", "vendorPassword", "010-0000-0000", payAccount, - passwordEncoder); - } catch (InvalidCreationException e) { - throw new RuntimeException(e); - } + return new Vendor("vendorName", "vendorEmail@example.com", "vendorPassword", "010-0000-0000", payAccount, + passwordEncoder); } - } diff --git a/src/test/java/camp/woowak/lab/vendor/domain/VendorTest.java b/src/test/java/camp/woowak/lab/vendor/domain/VendorTest.java index ec8d949f..ad89b05e 100644 --- a/src/test/java/camp/woowak/lab/vendor/domain/VendorTest.java +++ b/src/test/java/camp/woowak/lab/vendor/domain/VendorTest.java @@ -8,7 +8,7 @@ import camp.woowak.lab.payaccount.domain.PayAccount; import camp.woowak.lab.payaccount.domain.TestPayAccount; -import camp.woowak.lab.vendor.exception.InvalidCreationException; +import camp.woowak.lab.vendor.exception.InvalidVendorCreationException; import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; import camp.woowak.lab.web.authentication.PasswordEncoder; @@ -40,7 +40,7 @@ void successWith50() { @Test @DisplayName("[예외] null이면 예외가 발생한다.") void failWithNull() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor(null, "validEmail@validEmail.com", "validPassword", "010-0000-0000", payAccount, passwordEncoder)); } @@ -48,7 +48,7 @@ void failWithNull() { @Test @DisplayName("[예외] 공란이면 예외가 발생한다.") void failWithBlank() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor(" ", "validEmail@validEmail.com", "validPassword", "010-0000-0000", payAccount, passwordEncoder)); } @@ -56,7 +56,7 @@ void failWithBlank() { @Test @DisplayName("[예외] 50자를 초과하면 예외가 발생한다.") void failWith51() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor("aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeef", "validEmail@validEmail.com", "validPassword", "010-0000-0000", payAccount, passwordEncoder)); } @@ -77,7 +77,7 @@ void successWith100() { @Test @DisplayName("[예외] null이면 예외가 발생한다.") void failWithNull() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor("aaaaaaaaaa", null, "validPassword", "010-0000-0000", payAccount, passwordEncoder)); } @@ -85,14 +85,14 @@ void failWithNull() { @Test @DisplayName("[예외] 공란이면 예외가 발생한다.") void failWithBlank() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor("aaaaaaaaaa", " ", "validPassword", "010-0000-0000", payAccount, passwordEncoder)); } @Test @DisplayName("[예외] 100자를 초과하면 예외가 발생한다.") void failWith101() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor("aaaaaaaaaa", "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeea", "validPassword", "010-0000-0000", payAccount, passwordEncoder)); @@ -121,7 +121,7 @@ void successWith30() { @Test @DisplayName("[예외] null이면 예외가 발생한다.") void failWithNull() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", null, "010-0000-0000", payAccount, passwordEncoder)); } @@ -129,7 +129,7 @@ void failWithNull() { @Test @DisplayName("[예외] 공란이면 예외가 발생한다.") void failWithBlank() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", " ", "010-0000-0000", payAccount, passwordEncoder)); } @@ -137,7 +137,7 @@ void failWithBlank() { @Test @DisplayName("[예외] 8자 미만이면 예외가 발생한다.") void failWith7() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "thisis7", "010-0000-0000", payAccount, passwordEncoder)); } @@ -145,7 +145,7 @@ void failWith7() { @Test @DisplayName("[예외] 30자를 초과하면 예외가 발생한다.") void failWith31() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "thisstringsizeisthirtyonesnvien", "010-0000-0000", payAccount, passwordEncoder)); } @@ -166,7 +166,7 @@ void successWith30() { @Test @DisplayName("[예외] null이면 예외가 발생한다.") void failWithNull() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", null, payAccount, passwordEncoder)); } @@ -174,7 +174,7 @@ void failWithNull() { @Test @DisplayName("[예외] 공란이면 예외가 발생한다.") void failWithBlank() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", " ", payAccount, passwordEncoder)); } @@ -182,7 +182,7 @@ void failWithBlank() { @Test @DisplayName("[예외] 30자를 초과하면 예외가 발생한다.") void failWith31() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", "0000000000-0000000000-000000000", payAccount, passwordEncoder)); @@ -203,7 +203,7 @@ void successWithExist() { @Test @DisplayName("[예외] null이면 예외가 발생한다.") void failWithNull() { - Assertions.assertThrows(InvalidCreationException.class, + Assertions.assertThrows(InvalidVendorCreationException.class, () -> new Vendor("aaaaaaaaaa", "validEmail@validEmail.com", "validPassword", "010-0000-0000", null, passwordEncoder)); } From 196b911715d07e5bc2bcb37a11bb60297cef82c8 Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 23:26:18 +0900 Subject: [PATCH 074/146] =?UTF-8?q?[build]=20=EA=B9=83=ED=97=99=20?= =?UTF-8?q?=ED=85=9C=ED=94=8C=EB=A6=BF=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `~` PR 템플릿 파일 이름 변경 `~` ISSUE 템플릿 내용 일부 수정 --- .github/ISSUE_TEMPLATE/bug-report.md | 4 ++-- .github/ISSUE_TEMPLATE/feature-request.md | 4 ++-- .github/{pr-template.md => pull_request_template.md} | 0 3 files changed, 4 insertions(+), 4 deletions(-) rename .github/{pr-template.md => pull_request_template.md} (100%) diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 2675453c..51088305 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -1,8 +1,8 @@ --- name: Report bug about: 오류가 발생한 영역에 대해 보고합니다 [Dev] -title: "[BUG] " -labels: bug +title: "[오류] " +labels: 🐞 BugFix assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md index c5f818a0..74c97725 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.md +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -1,8 +1,8 @@ --- name: Feature request about: Github Discussion, 회의에서 화제가 된 주제에 대해 제안합니다 [Moderator, Chef] -title: '[REQ]' -labels: enhancement +title: "[기능] " +labels: ✨ Feature assignees: '' --- diff --git a/.github/pr-template.md b/.github/pull_request_template.md similarity index 100% rename from .github/pr-template.md rename to .github/pull_request_template.md From 9ae90e9959ff4a7e5fed1aea056e71ec9c75e9a7 Mon Sep 17 00:00:00 2001 From: donghar Date: Sat, 10 Aug 2024 23:38:35 +0900 Subject: [PATCH 075/146] =?UTF-8?q?[build]=20=EA=B9=83=ED=97=99=20?= =?UTF-8?q?=ED=85=9C=ED=94=8C=EB=A6=BF=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `~` PR 템플릿의 Issue Link 위치 변경 --- .github/pull_request_template.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 2d54b96a..c920935a 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,11 +1,12 @@ ## 💡 다음 이슈를 해결했어요. +### Issue Link - #1 + - (가능한 한 자세히 작성해 주시면 도움이 됩니다.)
## 💡 이슈를 처리하면서 추가된 코드가 있어요. -### Issue Link - #1 - (없다면 이 문항을 지워주세요.) From 56ec6f2a50661c6c2a3292bccfc08518c6f5f464 Mon Sep 17 00:00:00 2001 From: donghar Date: Sun, 11 Aug 2024 00:13:38 +0900 Subject: [PATCH 076/146] =?UTF-8?q?[build]=20=EA=B9=83=ED=97=99=20?= =?UTF-8?q?=EC=95=A1=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 빌드 테스트 액션 추가 --- .github/workflows/build.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..cc8cb265 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,21 @@ +name: Build-Test + +on: + pull_request: + branches: [ main ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 17 + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + - name: Build with Gradle + run: ./gradlew build From 8e8691037e32c3ee47ae33f7d66df8ff1b28a3e6 Mon Sep 17 00:00:00 2001 From: Hyeon-Uk Date: Mon, 12 Aug 2024 21:02:34 +0900 Subject: [PATCH 077/146] =?UTF-8?q?[feat]=20APIResponse=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 회의 결과로 결정된 API Response 형식에 맞게 status 와 Generic type의 data를 포함하는 클래스 생성 - 이 Response의 생성자는 해당 패키지의 Utils의 메서드를 이용해서만 생성할 수 있도록 private-default 접근 제어자로 설정 --- .../woowak/lab/web/api/utils/APIResponse.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java diff --git a/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java b/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java new file mode 100644 index 00000000..bf74a9d8 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java @@ -0,0 +1,21 @@ +package camp.woowak.lab.web.api.utils; + +import org.springframework.http.HttpStatus; + +public class APIResponse { + private final T data; + private final int status; + + APIResponse(final HttpStatus status, final T data) { + this.data = data; + this.status = status.value(); + } + + public T getData() { + return data; + } + + public int getStatus() { + return status; + } +} From 079708478dcc7dd7c0ab1ab01109433759683273 Mon Sep 17 00:00:00 2001 From: Hyeon-Uk Date: Mon, 12 Aug 2024 21:04:05 +0900 Subject: [PATCH 078/146] =?UTF-8?q?[feat]=20APIUtils=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - of 메서드를 이용해 APIResponse를 body에 포함한 ResponseEntity를 만들어 낼 수 있습니다. --- .../woowak/lab/web/api/utils/APIUtils.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/api/utils/APIUtils.java diff --git a/src/main/java/camp/woowak/lab/web/api/utils/APIUtils.java b/src/main/java/camp/woowak/lab/web/api/utils/APIUtils.java new file mode 100644 index 00000000..9bdb3c68 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/utils/APIUtils.java @@ -0,0 +1,19 @@ +package camp.woowak.lab.web.api.utils; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +/** + * + * API Utils + * of Method는 status와 data를 이용해 APIResponse객체를 만들 수 있습니다. + * + */ +public final class APIUtils { + private APIUtils() { + } + + public static ResponseEntity> of(HttpStatus status, T data) { + return new ResponseEntity<>(new APIResponse<>(status, data), status); + } +} From b9a7e0b986a36b2b2ede8901fbf589af9d732323 Mon Sep 17 00:00:00 2001 From: Hyeon-Uk Date: Mon, 12 Aug 2024 21:04:49 +0900 Subject: [PATCH 079/146] =?UTF-8?q?[test]=20APIUtils=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - APIUtils에 대한 테스트코드입니다. - 원시타입의 변수를 Generic으로 설정 가능합니다. - 객체 타입의 변수를 설정할 수 있습니다. --- .../lab/web/api/utils/APIUtilsTest.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/test/java/camp/woowak/lab/web/api/utils/APIUtilsTest.java diff --git a/src/test/java/camp/woowak/lab/web/api/utils/APIUtilsTest.java b/src/test/java/camp/woowak/lab/web/api/utils/APIUtilsTest.java new file mode 100644 index 00000000..a421a8fa --- /dev/null +++ b/src/test/java/camp/woowak/lab/web/api/utils/APIUtilsTest.java @@ -0,0 +1,73 @@ +package camp.woowak.lab.web.api.utils; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import com.fasterxml.jackson.core.JsonProcessingException; + +@DisplayName("APIUtils 클래스") +class APIUtilsTest { + @Nested + @DisplayName("of메서드의") + class OfTest { + @Nested + @DisplayName("HttpStatus 값과 Data를 파라미터로 받는 메서드는") + class ParamWithHttpStatusAndData { + @Test + @DisplayName("data와 status를 가지는 APIResponse를 생성할 수 있다.") + void APIResponseWithHttpStatusAndData() throws JsonProcessingException { + //given + HttpStatus status = HttpStatus.OK; + String message = "hello world"; + + //when + ResponseEntity> apiResponse = APIUtils.of(status, message); + + //then + assertThat(apiResponse.getStatusCode()).isEqualTo(status); + assertThat(apiResponse.getBody().getData()).isEqualTo(message); + assertThat(apiResponse.getBody().getStatus()).isEqualTo(status.value()); + } + + @Test + @DisplayName("data가 객체인 경우도 APIResponse를 생성할 수 있다.") + void APIResponseWithObjectData() throws JsonProcessingException { + //given + HttpStatus status = HttpStatus.OK; + Example example = new Example(27, "Hyeon-Uk"); + + //when + ResponseEntity> apiResponse = APIUtils.of(status, example); + + //then + assertThat(apiResponse.getStatusCode()).isEqualTo(status); + assertThat(apiResponse.getBody().getData()).isEqualTo(example); + assertThat(apiResponse.getBody().getStatus()).isEqualTo(status.value()); + } + + private class Example { + int age; + String name; + + public Example(int age, String name) { + this.age = age; + this.name = name; + } + + public int getAge() { + return age; + } + + public String getName() { + return name; + } + } + } + + } +} \ No newline at end of file From 8c9a2229a0a45857433cd459500991f639992d75 Mon Sep 17 00:00:00 2001 From: Hyeon-Uk Date: Mon, 12 Aug 2024 21:06:17 +0900 Subject: [PATCH 080/146] =?UTF-8?q?[docs]=20APIResponse=EC=97=90=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=8B=9C=20=EC=A3=BC=EC=9D=98=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Jackson의 ObjectMapper와 함께 사용하기 위해서는 data로 들어오는 변수에 Getter가 필수적으로 있어야한다는 내용을 주석으로 추가 --- src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java b/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java index bf74a9d8..e41f44a8 100644 --- a/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java +++ b/src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java @@ -2,6 +2,10 @@ import org.springframework.http.HttpStatus; +/** + * APIResponse를 Jackson의 ObjectMapper와 함께 사용하려면, + * Generic Type의 {@code data}에는 Getter 메서드가 필요합니다. + */ public class APIResponse { private final T data; private final int status; From e43860cb58bcbd7093770ced545722cd5609b37e Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Mon, 12 Aug 2024 21:03:13 +0900 Subject: [PATCH 081/146] =?UTF-8?q?[feat]=20HttpStatusException=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20HttpStatus=20=EC=97=90=20=EA=B8=B0?= =?UTF-8?q?=EB=B0=98=ED=95=9C=20exception=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/common/exception/HttpStatusException.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/common/exception/HttpStatusException.java diff --git a/src/main/java/camp/woowak/lab/common/exception/HttpStatusException.java b/src/main/java/camp/woowak/lab/common/exception/HttpStatusException.java new file mode 100644 index 00000000..b9c07ac1 --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/HttpStatusException.java @@ -0,0 +1,14 @@ +package camp.woowak.lab.common.exception; + +public class HttpStatusException extends RuntimeException { + private final ErrorCode errorCode; + + public HttpStatusException(ErrorCode errorCode) { + super(errorCode.getMessage()); + this.errorCode = errorCode; + } + + public ErrorCode errorCode() { + return errorCode; + } +} From 587c0d5efdaa9c32c3614cd4a766b04bad340a92 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Mon, 12 Aug 2024 21:09:10 +0900 Subject: [PATCH 082/146] =?UTF-8?q?[feat]=20HttpStatusException=20?= =?UTF-8?q?=EB=A5=BC=20=EA=B5=AC=ED=98=84=ED=95=98=EB=8A=94=20Exception=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20BadRequestException:=20400=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=EC=97=90=20=EB=8C=80=ED=95=9C=20Exception=20-=20Unaut?= =?UTF-8?q?horizedException:=20401=20=EC=97=90=EB=9F=AC=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20Exception=20-=20ForbiddenException:=20403?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=EC=97=90=20=EB=8C=80=ED=95=9C=20Exception?= =?UTF-8?q?=20-=20NotFoundException:=20404=20=EC=97=90=EB=9F=AC=EC=97=90?= =?UTF-8?q?=20=EB=8C=80=ED=95=9C=20Exception=20-=20MethodNotAllowedExcepti?= =?UTF-8?q?on:=20405=20=EC=97=90=EB=9F=AC=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?Exception=20-=20ConflictException:=20409=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20Exception?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/advice/GlobalExceptionHandler.java | 27 +++++++++++++++++++ .../common/exception/BadRequestException.java | 7 +++++ .../common/exception/ConflictException.java | 7 +++++ .../common/exception/ForbiddenException.java | 7 +++++ .../exception/MethodNotAllowedException.java | 7 +++++ .../common/exception/NotFoundException.java | 7 +++++ .../exception/UnauthorizedException.java | 7 +++++ 7 files changed, 69 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java create mode 100644 src/main/java/camp/woowak/lab/common/exception/BadRequestException.java create mode 100644 src/main/java/camp/woowak/lab/common/exception/ConflictException.java create mode 100644 src/main/java/camp/woowak/lab/common/exception/ForbiddenException.java create mode 100644 src/main/java/camp/woowak/lab/common/exception/MethodNotAllowedException.java create mode 100644 src/main/java/camp/woowak/lab/common/exception/NotFoundException.java create mode 100644 src/main/java/camp/woowak/lab/common/exception/UnauthorizedException.java diff --git a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java new file mode 100644 index 00000000..6f9bc5fc --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java @@ -0,0 +1,27 @@ +package camp.woowak.lab.common.advice; + +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(Exception.class) + public ResponseEntity handleAllUncaughtException(Exception e) { + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.INTERNAL_SERVER_ERROR, + e.getMessage()); + problemDetail.setProperty("errorCode", "9999"); + + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(problemDetail); + } +} diff --git a/src/main/java/camp/woowak/lab/common/exception/BadRequestException.java b/src/main/java/camp/woowak/lab/common/exception/BadRequestException.java new file mode 100644 index 00000000..3b4d4090 --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/BadRequestException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public class BadRequestException extends HttpStatusException { + public BadRequestException(ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/camp/woowak/lab/common/exception/ConflictException.java b/src/main/java/camp/woowak/lab/common/exception/ConflictException.java new file mode 100644 index 00000000..e7b16219 --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/ConflictException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public class ConflictException extends HttpStatusException { + public ConflictException(ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/camp/woowak/lab/common/exception/ForbiddenException.java b/src/main/java/camp/woowak/lab/common/exception/ForbiddenException.java new file mode 100644 index 00000000..05ab0863 --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/ForbiddenException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public class ForbiddenException extends HttpStatusException { + public ForbiddenException(ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/camp/woowak/lab/common/exception/MethodNotAllowedException.java b/src/main/java/camp/woowak/lab/common/exception/MethodNotAllowedException.java new file mode 100644 index 00000000..6704a8cd --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/MethodNotAllowedException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public class MethodNotAllowedException extends HttpStatusException { + public MethodNotAllowedException(ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/camp/woowak/lab/common/exception/NotFoundException.java b/src/main/java/camp/woowak/lab/common/exception/NotFoundException.java new file mode 100644 index 00000000..6928975e --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/NotFoundException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public class NotFoundException extends HttpStatusException { + public NotFoundException(ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/camp/woowak/lab/common/exception/UnauthorizedException.java b/src/main/java/camp/woowak/lab/common/exception/UnauthorizedException.java new file mode 100644 index 00000000..ba2e1237 --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/UnauthorizedException.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public class UnauthorizedException extends HttpStatusException { + public UnauthorizedException(ErrorCode errorCode) { + super(errorCode); + } +} From 3d2bc74d54469b38b6f45ae82dbf34da403b2583 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Mon, 12 Aug 2024 21:09:31 +0900 Subject: [PATCH 083/146] =?UTF-8?q?[feat]=20ErrorCode=20interface=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/camp/woowak/lab/common/exception/ErrorCode.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/common/exception/ErrorCode.java diff --git a/src/main/java/camp/woowak/lab/common/exception/ErrorCode.java b/src/main/java/camp/woowak/lab/common/exception/ErrorCode.java new file mode 100644 index 00000000..54a2beda --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/exception/ErrorCode.java @@ -0,0 +1,7 @@ +package camp.woowak.lab.common.exception; + +public interface ErrorCode { + int getStatus(); + String getErrorCode(); + String getMessage(); +} From 11994fbbe81863f737636cf75dfe6416c1329880 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Mon, 12 Aug 2024 21:15:55 +0900 Subject: [PATCH 084/146] =?UTF-8?q?[feat]=20CustomRestControllerAdvice=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20ControllerAdvice=20=EA=B8=B0=EB=B3=B8?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EC=9A=B0=EC=84=A0=20=EC=88=9C=EC=9C=84?= =?UTF-8?q?=20=EB=AC=B8=EC=A0=9C=20=EB=95=8C=EB=AC=B8=EC=97=90=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=ED=95=9C=20CustomRestControllerAdvice=20-=20=EA=B8=B0?= =?UTF-8?q?=EC=A1=B4=20RestControllerAdvice=20=EB=B3=B4=EB=8B=A4=20?= =?UTF-8?q?=EC=9A=B0=EC=84=A0=20=EC=88=9C=EC=9C=84=EA=B0=80=20=ED=95=9C=20?= =?UTF-8?q?=EB=8B=A8=EA=B3=84=20=EB=86=92=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../advice/CustomRestControllerAdvice.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java diff --git a/src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java b/src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java new file mode 100644 index 00000000..4fd5b48a --- /dev/null +++ b/src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java @@ -0,0 +1,27 @@ +package camp.woowak.lab.common.advice; + +import org.springframework.core.Ordered; +import org.springframework.core.annotation.AliasFor; +import org.springframework.core.annotation.Order; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@RestControllerAdvice +@Order(Ordered.LOWEST_PRECEDENCE - 1) +public @interface CustomRestControllerAdvice { + @AliasFor(annotation = RestControllerAdvice.class, attribute = "basePackages") + String[] basePackages() default {}; + + @AliasFor(annotation = RestControllerAdvice.class, attribute = "basePackageClasses") + Class[] basePackageClasses() default {}; + + @AliasFor(annotation = RestControllerAdvice.class, attribute = "assignableTypes") + Class[] assignableTypes() default {}; + + @AliasFor(annotation = RestControllerAdvice.class, attribute = "annotations") + Class[] annotations() default {}; +} From 99df6fda5ac0e3e088213712d3a6c29b7fd4a971 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Mon, 12 Aug 2024 21:23:02 +0900 Subject: [PATCH 085/146] =?UTF-8?q?[chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/common/advice/GlobalExceptionHandler.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java index 6f9bc5fc..69c86318 100644 --- a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java +++ b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java @@ -1,12 +1,9 @@ package camp.woowak.lab.common.advice; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; import org.springframework.http.HttpStatus; import org.springframework.http.ProblemDetail; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import lombok.extern.slf4j.Slf4j; From 7d5773747e85c11d6cb88570e6b0d574ccbb6dea Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Mon, 12 Aug 2024 22:01:48 +0900 Subject: [PATCH 086/146] =?UTF-8?q?[refactor]=20CustomRestControllerAdvice?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD=20-=20DomainExceptio?= =?UTF-8?q?nHandler=20=EB=A1=9C=20=EB=B3=80=EA=B2=BD=ED=96=88=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...trollerAdvice.java => DomainExceptionHandler.java} | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) rename src/main/java/camp/woowak/lab/common/advice/{CustomRestControllerAdvice.java => DomainExceptionHandler.java} (76%) diff --git a/src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java b/src/main/java/camp/woowak/lab/common/advice/DomainExceptionHandler.java similarity index 76% rename from src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java rename to src/main/java/camp/woowak/lab/common/advice/DomainExceptionHandler.java index 4fd5b48a..56a9c564 100644 --- a/src/main/java/camp/woowak/lab/common/advice/CustomRestControllerAdvice.java +++ b/src/main/java/camp/woowak/lab/common/advice/DomainExceptionHandler.java @@ -1,18 +1,23 @@ package camp.woowak.lab.common.advice; +import java.lang.annotation.Annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + import org.springframework.core.Ordered; import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.Order; import org.springframework.web.bind.annotation.RestControllerAdvice; -import java.lang.annotation.*; - @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @RestControllerAdvice @Order(Ordered.LOWEST_PRECEDENCE - 1) -public @interface CustomRestControllerAdvice { +public @interface DomainExceptionHandler { @AliasFor(annotation = RestControllerAdvice.class, attribute = "basePackages") String[] basePackages() default {}; From 0677fb48732a736a03396c716f46aab6e2facfb3 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 00:00:00 +0900 Subject: [PATCH 087/146] =?UTF-8?q?[fix]=20open-in-view=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20=EC=84=A4=EC=A0=95=EC=9C=BC=EB=A1=9C=20=EB=B3=B5?= =?UTF-8?q?=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 66b1c0c5..b4956434 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,4 @@ spring.application.name=lab spring.jpa.show-sql=true spring.jpa.generate-ddl=true -spring.jpa.open-in-view=false spring.jpa.hibernate.ddl-auto=create-drop From eb702f8aef5956cab3e32772f8719f62cdff9af2 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 00:24:03 +0900 Subject: [PATCH 088/146] =?UTF-8?q?[chore]=20.gitkeep=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/camp/woowak/lab/web/dto/request/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/web/dto/request/.gitkeep diff --git a/src/main/java/camp/woowak/lab/web/dto/request/.gitkeep b/src/main/java/camp/woowak/lab/web/dto/request/.gitkeep deleted file mode 100644 index e69de29b..00000000 From b76a98f3315f78f2f01f2fc0f068623cde097f50 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 00:24:25 +0900 Subject: [PATCH 089/146] =?UTF-8?q?[chore]=20.gitkeep=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/camp/woowak/lab/web/api/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/web/api/.gitkeep diff --git a/src/main/java/camp/woowak/lab/web/api/.gitkeep b/src/main/java/camp/woowak/lab/web/api/.gitkeep deleted file mode 100644 index e69de29b..00000000 From 6ec34a9134a361f600881b1b71effdafc921412a Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 00:27:42 +0900 Subject: [PATCH 090/146] =?UTF-8?q?[feat]=20CustomerErrorCode=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20-=20INVALID=5FPAY=5FACCOUNT=5FIS=5FNOT=5FNULL:=20?= =?UTF-8?q?=EA=B5=AC=EB=A7=A4=EC=9E=90=EC=9D=98=20=EA=B3=84=EC=A2=8C?= =?UTF-8?q?=EB=8A=94=20Null=EC=9D=B4=20=EB=90=A0=20=EC=88=98=20=EC=97=86?= =?UTF-8?q?=EB=8B=A4.=20-=20INVALID=5FPHONE=5FIS=5FNOT=5FBLANK:=20?= =?UTF-8?q?=EA=B5=AC=EB=A7=A4=EC=9E=90=EC=9D=98=20=EC=A0=84=ED=99=94?= =?UTF-8?q?=EB=B2=88=ED=98=B8=EB=8A=94=20=EB=B9=84=EC=96=B4=EC=9E=88?= =?UTF-8?q?=EC=9D=84=20=EC=88=98=20=EC=97=86=EB=8B=A4.=20-=20INVALID=5FPHO?= =?UTF-8?q?NE=5FIS=5FTOO=5FLONG:=20=EA=B5=AC=EB=A7=A4=EC=9E=90=EC=9D=98=20?= =?UTF-8?q?=EC=A0=84=ED=99=94=EB=B2=88=ED=98=B8=EB=8A=94=2030=EC=9E=90?= =?UTF-8?q?=EB=A5=BC=20=EC=B4=88=EA=B3=BC=ED=95=A0=20=EC=88=98=20=EC=97=86?= =?UTF-8?q?=EB=8B=A4.=20-=20INVALID=5FPASSWORD=5FIS=5FNOT=5FBLANK:=20?= =?UTF-8?q?=EA=B5=AC=EB=A7=A4=EC=9E=90=EC=9D=98=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=EB=8A=94=20=EB=B9=84=EC=96=B4=EC=9E=88?= =?UTF-8?q?=EC=9D=84=20=EC=88=98=20=EC=97=86=EB=8B=A4.=20-=20INVALID=5FPAS?= =?UTF-8?q?SWORD=5FIS=5FTOO=5FLONG:=20=EA=B5=AC=EB=A7=A4=EC=9E=90=EC=9D=98?= =?UTF-8?q?=20=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=EB=8A=94=2030=EC=9E=90?= =?UTF-8?q?=EB=A5=BC=20=EC=B4=88=EA=B3=BC=ED=95=A0=20=EC=88=98=20=EC=97=86?= =?UTF-8?q?=EB=8B=A4.=20-=20INVALID=5FEMAIL=5FIS=5FNOT=5FBLANK:=20?= =?UTF-8?q?=EA=B5=AC=EB=A7=A4=EC=9E=90=EC=9D=98=20=EC=9D=B4=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=EC=9D=80=20=EB=B9=84=EC=96=B4=EC=9E=88=EC=9D=84=20?= =?UTF-8?q?=EC=88=98=20=EC=97=86=EB=8B=A4.=20-=20INVALID=5FEMAIL=5FIS=5FTO?= =?UTF-8?q?O=5FLONG:=20=EA=B5=AC=EB=A7=A4=EC=9E=90=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=A9=94=EC=9D=BC=EC=9D=80=20100=EC=9E=90=EB=A5=BC=20=EC=B4=88?= =?UTF-8?q?=EA=B3=BC=ED=95=A0=20=EC=88=98=20=EC=97=86=EB=8B=A4.=20-=20INVA?= =?UTF-8?q?LID=5FNAME=5FIS=5FNOT=5FBLANK:=20=EA=B5=AC=EB=A7=A4=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=9D=B4=EB=A6=84=EC=9D=80=20=EB=B9=84=EC=96=B4?= =?UTF-8?q?=EC=9E=88=EC=9D=84=20=EC=88=98=20=EC=97=86=EB=8B=A4.=20-=20INVA?= =?UTF-8?q?LID=5FNAME=5FIS=5FTOO=5FLONG:=20=EA=B5=AC=EB=A7=A4=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=9D=B4=EB=A6=84=EC=9D=80=20100=EC=9E=90=EB=A5=BC?= =?UTF-8?q?=20=EC=B4=88=EA=B3=BC=ED=95=A0=20=EC=88=98=20=EC=97=86=EB=8B=A4?= =?UTF-8?q?.=20-=20DUPLICATE=5FEMAIL:=20=EA=B5=AC=EB=A7=A4=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=9D=B4=EB=A9=94=EC=9D=BC=EC=9D=B4=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=20=EC=82=AC=EC=9A=A9=20=EC=A4=91=EC=9D=B4=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../customer/exception/CustomerErrorCode.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java diff --git a/src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java b/src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java new file mode 100644 index 00000000..fae69360 --- /dev/null +++ b/src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java @@ -0,0 +1,41 @@ +package camp.woowak.lab.customer.exception; + +import camp.woowak.lab.common.exception.ErrorCode; + +public enum CustomerErrorCode implements ErrorCode { + INVALID_PAY_ACCOUNT_IS_NOT_NULL(400, "C1", "Customer payAccount cannot be null"), + INVALID_PHONE_IS_NOT_BLANK(400, "C2", "Customer phone cannot be blank"), + INVALID_PHONE_IS_TOO_LONG(400, "C3", "Customer phone cannot be longer than 30 characters"), + INVALID_PASSWORD_IS_NOT_BLANK(400, "C4", "Customer password cannot be blank"), + INVALID_PASSWORD_IS_TOO_LONG(400, "C5", "Customer password cannot be longer than 30 characters"), + INVALID_EMAIL_IS_NOT_BLANK(400, "C6", "Customer email cannot be blank"), + INVALID_EMAIL_IS_TOO_LONG(400, "C7", "Customer email cannot be longer than 100 characters"), + INVALID_NAME_IS_NOT_BLANK(400, "C8", "Customer name cannot be blank"), + INVALID_NAME_IS_TOO_LONG(400, "C9", "Customer name cannot be longer than 100 characters"), + DUPLICATE_EMAIL(400, "C10", "Customer email is already in use"); + + private final int status; + private final String errorCode; + private final String message; + + CustomerErrorCode(int status, String errorCode, String message) { + this.status = status; + this.errorCode = errorCode; + this.message = message; + } + + @Override + public int getStatus() { + return status; + } + + @Override + public String getErrorCode() { + return errorCode; + } + + @Override + public String getMessage() { + return message; + } +} From ed6a9b82526d3f87640d45eddf6e50946f4e23a6 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 00:28:35 +0900 Subject: [PATCH 091/146] =?UTF-8?q?[refactor]=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20Validation=20=EC=A3=BC=EC=B2=B4=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=20-=20CustomerValidator=20=EB=A5=BC=20=ED=86=B5?= =?UTF-8?q?=ED=95=B4=20Customer=20=EC=9D=98=20validation=20=EC=9D=84=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=ED=95=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/customer/domain/Customer.java | 49 +-------------- .../customer/domain/CustomerValidator.java | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+), 48 deletions(-) create mode 100644 src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java 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 db1fefb5..be53fb4f 100644 --- a/src/main/java/camp/woowak/lab/customer/domain/Customer.java +++ b/src/main/java/camp/woowak/lab/customer/domain/Customer.java @@ -35,58 +35,11 @@ public Customer() { public Customer(String name, String email, String password, String phone, PayAccount payAccount, PasswordEncoder passwordEncoder) throws InvalidCreationException { - checkName(name); - checkEmail(email); - checkPassword(password); - checkPhone(phone); - checkPayAccount(payAccount); + CustomerValidator.validateCreation(name, email, password, phone, payAccount); this.name = name; this.email = email; this.password = passwordEncoder.encode(password); this.phone = phone; this.payAccount = payAccount; } - - private void checkPayAccount(PayAccount payAccount) throws InvalidCreationException { - if (payAccount == null) { - throw new InvalidCreationException("Pay account cannot be null"); - } - } - - private void checkPhone(String phone) throws InvalidCreationException { - if (phone == null || phone.isBlank()) { - throw new InvalidCreationException("Customer phone cannot be blank"); - } - if (phone.trim().length() > 30) { - throw new InvalidCreationException("Customer phone cannot be longer than 30 characters"); - } - } - - private void checkPassword(String password) throws InvalidCreationException { - if (password == null || password.isBlank()) { - throw new InvalidCreationException("Customer password cannot be blank"); - } - if (password.trim().length() > 30) { - throw new InvalidCreationException("Customer password cannot be longer than 30 characters"); - } - } - - private void checkEmail(String email) throws InvalidCreationException { - if (email == null || email.isBlank()) { - throw new InvalidCreationException("Customer email cannot be blank"); - } - if (email.trim().length() > 100) { - throw new InvalidCreationException("Customer email cannot be longer than 100 characters"); - } - } - - private void checkName(String name) throws InvalidCreationException { - if (name == null || name.isBlank()) { - throw new InvalidCreationException("Customer name cannot be blank"); - } - if (name.length() > 50) { - throw new InvalidCreationException("Customer name cannot exceed 50 characters"); - } - } - } diff --git a/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java b/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java new file mode 100644 index 00000000..5e8d5ece --- /dev/null +++ b/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java @@ -0,0 +1,59 @@ +package camp.woowak.lab.customer.domain; + +import camp.woowak.lab.customer.exception.CustomerErrorCode; +import camp.woowak.lab.customer.exception.InvalidCreationException; +import camp.woowak.lab.payaccount.domain.PayAccount; + +public class CustomerValidator { + + public static void validateCreation(String name, String email, String password, String phone, + PayAccount payAccount) throws InvalidCreationException { + validateName(name); + validateEmail(email); + validatePassword(password); + validatePhone(phone); + validatePayAccount(payAccount); + } + + public static void validateName(String name) throws InvalidCreationException { + if (name == null || name.isBlank()) { + throw new InvalidCreationException(CustomerErrorCode.INVALID_NAME_IS_NOT_BLANK); + } + if (name.length() > 50) { + throw new InvalidCreationException(CustomerErrorCode.INVALID_NAME_IS_TOO_LONG); + } + } + + public static void validateEmail(String email) throws InvalidCreationException { + if (email == null || email.isBlank()) { + throw new InvalidCreationException(CustomerErrorCode.INVALID_EMAIL_IS_NOT_BLANK); + } + if (email.trim().length() > 100) { + throw new InvalidCreationException(CustomerErrorCode.INVALID_EMAIL_IS_TOO_LONG); + } + } + + public static void validatePassword(String password) throws InvalidCreationException { + if (password == null || password.isBlank()) { + throw new InvalidCreationException(CustomerErrorCode.INVALID_PASSWORD_IS_NOT_BLANK); + } + if (password.trim().length() > 30) { + throw new InvalidCreationException(CustomerErrorCode.INVALID_PASSWORD_IS_TOO_LONG); + } + } + + public static void validatePhone(String phone) throws InvalidCreationException { + if (phone == null || phone.isBlank()) { + throw new InvalidCreationException(CustomerErrorCode.INVALID_PHONE_IS_NOT_BLANK); + } + if (phone.trim().length() > 30) { + throw new InvalidCreationException(CustomerErrorCode.INVALID_PHONE_IS_TOO_LONG); + } + } + + public static void validatePayAccount(PayAccount payAccount) throws InvalidCreationException { + if (payAccount == null) { + throw new InvalidCreationException(CustomerErrorCode.INVALID_PAY_ACCOUNT_IS_NOT_NULL); + } + } +} From 70f0f1454780b3790052cd87e709e03855032c22 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 00:30:48 +0900 Subject: [PATCH 092/146] =?UTF-8?q?[refactor]=20CustomerException=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20-=20=EA=B3=B5=ED=86=B5=20Exception=20?= =?UTF-8?q?=EC=9D=84=20=EC=83=81=EC=86=8D=EB=B0=9B=EC=95=84=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/customer/exception/DuplicateEmailException.java | 7 ++++++- .../lab/customer/exception/DuplicateException.java | 4 ---- .../lab/customer/exception/InvalidCreationException.java | 9 ++++++--- 3 files changed, 12 insertions(+), 8 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/customer/exception/DuplicateException.java diff --git a/src/main/java/camp/woowak/lab/customer/exception/DuplicateEmailException.java b/src/main/java/camp/woowak/lab/customer/exception/DuplicateEmailException.java index 4614a21b..643729b0 100644 --- a/src/main/java/camp/woowak/lab/customer/exception/DuplicateEmailException.java +++ b/src/main/java/camp/woowak/lab/customer/exception/DuplicateEmailException.java @@ -1,4 +1,9 @@ package camp.woowak.lab.customer.exception; -public class DuplicateEmailException extends DuplicateException { +import camp.woowak.lab.common.exception.BadRequestException; + +public class DuplicateEmailException extends BadRequestException { + public DuplicateEmailException() { + super(CustomerErrorCode.DUPLICATE_EMAIL); + } } diff --git a/src/main/java/camp/woowak/lab/customer/exception/DuplicateException.java b/src/main/java/camp/woowak/lab/customer/exception/DuplicateException.java deleted file mode 100644 index 8b3e6d10..00000000 --- a/src/main/java/camp/woowak/lab/customer/exception/DuplicateException.java +++ /dev/null @@ -1,4 +0,0 @@ -package camp.woowak.lab.customer.exception; - -public abstract class DuplicateException extends RuntimeException { -} diff --git a/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java b/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java index dc469af6..72e05311 100644 --- a/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java +++ b/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java @@ -1,7 +1,10 @@ package camp.woowak.lab.customer.exception; -public class InvalidCreationException extends RuntimeException { - public InvalidCreationException(String message) { - super(message); +import camp.woowak.lab.common.exception.BadRequestException; +import camp.woowak.lab.common.exception.ErrorCode; + +public class InvalidCreationException extends BadRequestException { + public InvalidCreationException(ErrorCode errorCode) { + super(errorCode); } } From a542d7c60e1b2a9dad3f08e6cece2ce81191ee51 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 00:31:43 +0900 Subject: [PATCH 093/146] =?UTF-8?q?[fix]=20=EC=98=AC=EB=B0=94=EB=A5=B8=20E?= =?UTF-8?q?xception=20=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20-=20Except?= =?UTF-8?q?ion=20=EC=A0=95=EC=B1=85=20=EB=B3=80=EA=B2=BD=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EC=97=90=20=EC=82=AC=EC=9A=A9=EB=90=9C=20Exception=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 --- .../woowak/lab/customer/service/SignUpCustomerServiceTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java index 0f8f93af..c9f0432a 100644 --- a/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java +++ b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java @@ -14,7 +14,6 @@ import camp.woowak.lab.customer.domain.Customer; import camp.woowak.lab.customer.exception.DuplicateEmailException; -import camp.woowak.lab.customer.exception.DuplicateException; import camp.woowak.lab.customer.exception.InvalidCreationException; import camp.woowak.lab.customer.repository.CustomerRepository; import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; @@ -72,7 +71,7 @@ void testSignUpWithExistingEmail() { new SignUpCustomerCommand("name", "email@example.com", "password", "01012345678"); // then - Assertions.assertThrows(DuplicateException.class, () -> service.signUp(command)); + Assertions.assertThrows(DuplicateEmailException.class, () -> service.signUp(command)); then(payAccountRepository).should().save(Mockito.any(PayAccount.class)); then(customerRepository).should().save(Mockito.any(Customer.class)); } From 956fb2b650431acee370283a7246d8c24b51c032 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 00:32:23 +0900 Subject: [PATCH 094/146] =?UTF-8?q?[chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/customer/service/SignUpCustomerServiceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java index c9f0432a..f3bbb0d9 100644 --- a/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java +++ b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java @@ -51,7 +51,7 @@ void testSignUp() throws InvalidCreationException, DuplicateEmailException { // when SignUpCustomerCommand command = new SignUpCustomerCommand("name", "email@example.com", "password", "01012345678"); - Long id = service.signUp(command); + service.signUp(command); // then then(payAccountRepository).should().save(Mockito.any(PayAccount.class)); From f3b814241f2345093db9a89dfe0095b5f4827d4e Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 00:34:03 +0900 Subject: [PATCH 095/146] =?UTF-8?q?[chore]=20Exception=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20Service=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20-=20SignUpCustomerService.signUp=20=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94=20Exception=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=EC=9C=BC=EB=A1=9C=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/SignUpCustomerService.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java b/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java index 0a4f70cb..64b69f50 100644 --- a/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java +++ b/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java @@ -26,6 +26,11 @@ public SignUpCustomerService(CustomerRepository customerRepository, PayAccountRe this.passwordEncoder = passwordEncoder; } + /** + * + * @throws InvalidCreationException 구매자 생성에 오류가 나는 경우 + * @throws DuplicateEmailException 이메일이 중복되는 경우 + */ @Transactional public Long signUp(SignUpCustomerCommand cmd) throws InvalidCreationException, DuplicateEmailException { PayAccount payAccount = new PayAccount(); From ca680490525d458eb70df00cd177ded52fe22e39 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 00:34:57 +0900 Subject: [PATCH 096/146] =?UTF-8?q?[feat]=20CustomerController=20=EB=A5=BC?= =?UTF-8?q?=20=EC=A0=84=EB=8B=B4=ED=95=98=EB=8A=94=20DomainExceptionHandle?= =?UTF-8?q?r=20=EA=B5=AC=ED=98=84=20-=20BadRequestException=20=EB=A5=BC=20?= =?UTF-8?q?=EC=83=81=EC=86=8D=ED=95=98=EB=8A=94=20Exception=20=EA=B3=BC=20?= =?UTF-8?q?Validation=20=EC=8B=9C=20=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94?= =?UTF-8?q?=20MethodArgumentNotValidException=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/web/api/CustomerExceptionHandler.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/api/CustomerExceptionHandler.java diff --git a/src/main/java/camp/woowak/lab/web/api/CustomerExceptionHandler.java b/src/main/java/camp/woowak/lab/web/api/CustomerExceptionHandler.java new file mode 100644 index 00000000..272fea86 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/CustomerExceptionHandler.java @@ -0,0 +1,24 @@ +package camp.woowak.lab.web.api; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; + +import camp.woowak.lab.common.advice.DomainExceptionHandler; +import camp.woowak.lab.common.exception.BadRequestException; + +@DomainExceptionHandler +public class CustomerExceptionHandler { + + /** + * + * BadRequestException.class 와 MethodArgumentNotValidException.class 를 처리한다. + */ + @ExceptionHandler({BadRequestException.class, MethodArgumentNotValidException.class}) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ProblemDetail handleBadRequestException(BadRequestException e) { + return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, e.getMessage()); + } +} From e81511de029dba5b83815282f75c75ccc3741b62 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 09:19:34 +0900 Subject: [PATCH 097/146] =?UTF-8?q?[refactor]=20CustomerController=20?= =?UTF-8?q?=EC=9D=98=20=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC=20=EC=A3=BC?= =?UTF-8?q?=EC=B2=B4=20=EB=B3=80=EA=B2=BD=20-=20CustomerController=20?= =?UTF-8?q?=EC=9D=98=20=EC=97=90=EB=9F=AC=EC=B2=98=EB=A6=AC=EB=A5=BC=20Cus?= =?UTF-8?q?tomerExceptionHandler=20=EC=97=90=20=EC=9C=84=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/web/api/CustomerController.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) 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..cd013915 100644 --- a/src/main/java/camp/woowak/lab/web/api/CustomerController.java +++ b/src/main/java/camp/woowak/lab/web/api/CustomerController.java @@ -10,8 +10,6 @@ import camp.woowak.lab.customer.service.SignUpCustomerService; import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; import camp.woowak.lab.web.dto.request.SignUpCustomerRequest; -import camp.woowak.lab.web.dto.response.ApiResponse; -import camp.woowak.lab.web.error.ErrorCode; import jakarta.validation.Valid; @RestController @@ -27,13 +25,9 @@ public ResponseEntity signUp(@Valid @RequestBody SignUpCustomerRequest reques SignUpCustomerCommand command = new SignUpCustomerCommand(request.name(), request.email(), request.password(), request.phone()); Long registeredId; - try { - registeredId = signUpCustomerService.signUp(command); - } catch (camp.woowak.lab.customer.exception.InvalidCreationException e) { - return ResponseEntity.badRequest().body(ApiResponse.error(ErrorCode.SIGNUP_INVALID_REQUEST)); - } catch (camp.woowak.lab.customer.exception.DuplicateEmailException e) { - return ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_DUPLICATE_EMAIL)); - } + + registeredId = signUpCustomerService.signUp(command); + return ResponseEntity.created(URI.create("/customers/" + registeredId)).build(); } } From 140dbcc464ee2b653461303692b92255666519bb Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 09:20:34 +0900 Subject: [PATCH 098/146] =?UTF-8?q?[test]=20CustomerControllerTest=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20-=20=EC=A4=91=EB=B3=B5=20=EC=9D=B4?= =?UTF-8?q?=EB=A9=94=EC=9D=BC=20=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EC=A0=95=EC=B1=85=20=EB=B3=80=EA=B2=BD=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B8=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/web/api/CustomerControllerTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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..4f85d3cd 100644 --- a/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java @@ -208,8 +208,8 @@ void testSignUpCustomerWithDuplicateEmail() throws Exception { mockMvc.perform(post("/customers") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.code").value(ErrorCode.AUTH_DUPLICATE_EMAIL.getCode())) - .andExpect(jsonPath("$.message").value(ErrorCode.AUTH_DUPLICATE_EMAIL.getMessage())); + .andExpect(status().isConflict()) + .andExpect(jsonPath("$.errorCode").value(ErrorCode.AUTH_DUPLICATE_EMAIL.getCode())) + .andExpect(jsonPath("$.detail").value(ErrorCode.AUTH_DUPLICATE_EMAIL.getMessage())); } -} \ No newline at end of file +} From 5c5a49e59bddcdbc9b0f0c97e8f185aa08fb716a Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 10:48:38 +0900 Subject: [PATCH 099/146] =?UTF-8?q?[feat]=20HttpStatusException=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=B6=94=EA=B0=80=20-=20?= =?UTF-8?q?=EB=8F=99=EC=A0=81=EC=9C=BC=EB=A1=9C=20message=20=EB=A5=BC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8A=94=20?= =?UTF-8?q?HttpStatusException=20=EC=83=9D=EC=84=B1=EC=9E=90=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 --- .../woowak/lab/common/exception/HttpStatusException.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/camp/woowak/lab/common/exception/HttpStatusException.java b/src/main/java/camp/woowak/lab/common/exception/HttpStatusException.java index b9c07ac1..98deaf25 100644 --- a/src/main/java/camp/woowak/lab/common/exception/HttpStatusException.java +++ b/src/main/java/camp/woowak/lab/common/exception/HttpStatusException.java @@ -3,11 +3,17 @@ public class HttpStatusException extends RuntimeException { private final ErrorCode errorCode; + @Deprecated public HttpStatusException(ErrorCode errorCode) { super(errorCode.getMessage()); this.errorCode = errorCode; } + public HttpStatusException(ErrorCode errorCode, String message) { + super(message); + this.errorCode = errorCode; + } + public ErrorCode errorCode() { return errorCode; } From 93161c85ddd3c91aa26cee30fd612fc3ae5eb27d Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 12:37:45 +0900 Subject: [PATCH 100/146] =?UTF-8?q?[refactor]=20GlobalExceptionHandler=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=EB=B0=A9=EC=8B=9D=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?-=20=EB=85=BC=EC=9D=98=20-=20#31=20=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=9D=BC=20ResponseEntity=20=EA=B0=80=20=EC=95=84=EB=8B=8C=20P?= =?UTF-8?q?roblemDetail=20=EB=A5=BC=20=EB=84=98=EA=B8=B0=EB=8F=84=EB=A1=9D?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/common/advice/GlobalExceptionHandler.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java index 69c86318..26b81789 100644 --- a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java +++ b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java @@ -2,7 +2,6 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ProblemDetail; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -13,12 +12,11 @@ public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) - public ResponseEntity handleAllUncaughtException(Exception e) { + public ProblemDetail handleAllUncaughtException(Exception e) { ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage()); problemDetail.setProperty("errorCode", "9999"); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) - .body(problemDetail); + return problemDetail; } } From e15460df6af9c81483de046b17fcd1902f2b1de8 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 12:43:13 +0900 Subject: [PATCH 101/146] =?UTF-8?q?[feat]=20GlobalExceptionHandler=20?= =?UTF-8?q?=EB=A1=9C=EA=B9=85=20=EC=B6=94=EA=B0=80=20-=20=EC=98=88?= =?UTF-8?q?=EA=B8=B0=EC=B9=98=20=EB=AA=BB=ED=95=9C=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=EB=A1=9C=EA=B9=85=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 --- .../camp/woowak/lab/common/advice/GlobalExceptionHandler.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java index 26b81789..3fd08514 100644 --- a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java +++ b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java @@ -17,6 +17,8 @@ public ProblemDetail handleAllUncaughtException(Exception e) { e.getMessage()); problemDetail.setProperty("errorCode", "9999"); + log.error("[Unexpected Exception]", e); + return problemDetail; } } From 3df7fb35456372130f1c955e26aa21e999eba514 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 12:44:16 +0900 Subject: [PATCH 102/146] =?UTF-8?q?[chore]=20TODO=20=EB=93=B1=EB=A1=9D=20-?= =?UTF-8?q?=20=EC=B6=94=ED=9B=84=20Notion=20Hook=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EA=B8=B0=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/common/advice/GlobalExceptionHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java index 3fd08514..1b463618 100644 --- a/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java +++ b/src/main/java/camp/woowak/lab/common/advice/GlobalExceptionHandler.java @@ -18,6 +18,7 @@ public ProblemDetail handleAllUncaughtException(Exception e) { problemDetail.setProperty("errorCode", "9999"); log.error("[Unexpected Exception]", e); + // TODO: Notion Hook 등록 return problemDetail; } From 9f90cf1485ec8a2a0ec84d530fd4a7d23405eb1a Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 13:48:40 +0900 Subject: [PATCH 103/146] =?UTF-8?q?[chore]=20.gitkeep=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/camp/woowak/lab/web/dto/response/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/web/dto/response/.gitkeep diff --git a/src/main/java/camp/woowak/lab/web/dto/response/.gitkeep b/src/main/java/camp/woowak/lab/web/dto/response/.gitkeep deleted file mode 100644 index e69de29b..00000000 From ca72425c6e954266aff80a31d2b690eac8ad6259 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 13:48:53 +0900 Subject: [PATCH 104/146] =?UTF-8?q?[chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/web/dto/response/ApiResponse.java | 40 ------------------- 1 file changed, 40 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/web/dto/response/ApiResponse.java diff --git a/src/main/java/camp/woowak/lab/web/dto/response/ApiResponse.java b/src/main/java/camp/woowak/lab/web/dto/response/ApiResponse.java deleted file mode 100644 index 7f0be70f..00000000 --- a/src/main/java/camp/woowak/lab/web/dto/response/ApiResponse.java +++ /dev/null @@ -1,40 +0,0 @@ -package camp.woowak.lab.web.dto.response; - -import camp.woowak.lab.web.error.ErrorCode; - -public class ApiResponse { - private String code; - private String message; - private T data; - - private ApiResponse(String code, String message) { - this.code = code; - this.message = message; - } - - private ApiResponse(String code, String message, T data) { - this.code = code; - this.message = message; - this.data = data; - } - - public static ApiResponse ok(T data) { - return new ApiResponse<>("OK", "success", data); - } - - public static ApiResponse error(ErrorCode errorCode) { - return new ApiResponse<>(errorCode.getCode(), errorCode.getMessage()); - } - - public String getCode() { - return code; - } - - public String getMessage() { - return message; - } - - public T getData() { - return data; - } -} From c38cbdb3ed1c029abe449643888543b70dad4acb Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 13:49:31 +0900 Subject: [PATCH 105/146] =?UTF-8?q?[chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/web/error/ErrorCode.java | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/web/error/ErrorCode.java diff --git a/src/main/java/camp/woowak/lab/web/error/ErrorCode.java b/src/main/java/camp/woowak/lab/web/error/ErrorCode.java deleted file mode 100644 index 53b0e82e..00000000 --- a/src/main/java/camp/woowak/lab/web/error/ErrorCode.java +++ /dev/null @@ -1,22 +0,0 @@ -package camp.woowak.lab.web.error; - -public enum ErrorCode { - AUTH_DUPLICATE_EMAIL("a1", "이미 가입된 이메일 입니다."), - SIGNUP_INVALID_REQUEST("s1", "잘못된 요청입니다."); - - private final String code; - private final String message; - - ErrorCode(String code, String message) { - this.code = code; - this.message = message; - } - - public String getCode() { - return code; - } - - public String getMessage() { - return message; - } -} From d917fa0a305cf5db68ea6a8d4877f517e7d8e184 Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:51:20 +0900 Subject: [PATCH 106/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DISCUSSION_TEMPLATE/General.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 DISCUSSION_TEMPLATE/General.yml diff --git a/DISCUSSION_TEMPLATE/General.yml b/DISCUSSION_TEMPLATE/General.yml new file mode 100644 index 00000000..6aa137b3 --- /dev/null +++ b/DISCUSSION_TEMPLATE/General.yml @@ -0,0 +1,20 @@ +name: [논의] +description: 논의를 시작할 때 참고할 정보를 입력하세요. +title: [논의] 제목 +body: + - type: markdown + attributes: + value: | + ## 논의 배경 + 이 논의의 배경이나 맥락을 설명해주세요. 문제점, 아이디어의 출처, 관련된 자료나 정보를 포함하세요. + - type: textarea + id: background + attributes: + label: 논의 배경 + description: 이 논의를 시작하게 된 이유와 관련된 배경 정보를 입력하세요. + placeholder: 예: 문제의 원인, 관련된 이슈, 제안된 솔루션 등 + value: | + # 예시 + - 최근 발생한 문제 또는 기회 + - 관련된 기존 논의 + - 이 논의의 중요성 From 7192e418f546385aba5ae36528cebfb15aa743cf Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:53:21 +0900 Subject: [PATCH 107/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/DISCUSSION_TEMPLATE/general.yml diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml new file mode 100644 index 00000000..6aa137b3 --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -0,0 +1,20 @@ +name: [논의] +description: 논의를 시작할 때 참고할 정보를 입력하세요. +title: [논의] 제목 +body: + - type: markdown + attributes: + value: | + ## 논의 배경 + 이 논의의 배경이나 맥락을 설명해주세요. 문제점, 아이디어의 출처, 관련된 자료나 정보를 포함하세요. + - type: textarea + id: background + attributes: + label: 논의 배경 + description: 이 논의를 시작하게 된 이유와 관련된 배경 정보를 입력하세요. + placeholder: 예: 문제의 원인, 관련된 이슈, 제안된 솔루션 등 + value: | + # 예시 + - 최근 발생한 문제 또는 기회 + - 관련된 기존 논의 + - 이 논의의 중요성 From f96eb51199bc1ea4a3152c48f14d4585cfa560ea Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:55:12 +0900 Subject: [PATCH 108/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index 6aa137b3..c76f25c3 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -1,6 +1,6 @@ -name: [논의] -description: 논의를 시작할 때 참고할 정보를 입력하세요. -title: [논의] 제목 +name: "[논의] " +description: "논의를 시작할 때 참고할 정보를 입력하세요." +title: "[논의] 제목" body: - type: markdown attributes: From ba7ef9591ae94ebb920c6bc8dd46b4658dfbe94b Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 14:10:23 +0900 Subject: [PATCH 109/146] =?UTF-8?q?[refactor]=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/web/api/CustomerExceptionHandler.java | 24 ----------- .../{ => customer}/CustomerController.java | 2 +- .../customer/CustomerExceptionHandler.java | 43 +++++++++++++++++++ .../CustomerControllerTest.java | 6 +-- 4 files changed, 47 insertions(+), 28 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/web/api/CustomerExceptionHandler.java rename src/main/java/camp/woowak/lab/web/api/{ => customer}/CustomerController.java (96%) create mode 100644 src/main/java/camp/woowak/lab/web/api/customer/CustomerExceptionHandler.java rename src/test/java/camp/woowak/lab/web/api/{ => customer}/CustomerControllerTest.java (97%) diff --git a/src/main/java/camp/woowak/lab/web/api/CustomerExceptionHandler.java b/src/main/java/camp/woowak/lab/web/api/CustomerExceptionHandler.java deleted file mode 100644 index 272fea86..00000000 --- a/src/main/java/camp/woowak/lab/web/api/CustomerExceptionHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -package camp.woowak.lab.web.api; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ProblemDetail; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; - -import camp.woowak.lab.common.advice.DomainExceptionHandler; -import camp.woowak.lab.common.exception.BadRequestException; - -@DomainExceptionHandler -public class CustomerExceptionHandler { - - /** - * - * BadRequestException.class 와 MethodArgumentNotValidException.class 를 처리한다. - */ - @ExceptionHandler({BadRequestException.class, MethodArgumentNotValidException.class}) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public ProblemDetail handleBadRequestException(BadRequestException e) { - return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, e.getMessage()); - } -} diff --git a/src/main/java/camp/woowak/lab/web/api/CustomerController.java b/src/main/java/camp/woowak/lab/web/api/customer/CustomerController.java similarity index 96% rename from src/main/java/camp/woowak/lab/web/api/CustomerController.java rename to src/main/java/camp/woowak/lab/web/api/customer/CustomerController.java index cd013915..5207aa87 100644 --- a/src/main/java/camp/woowak/lab/web/api/CustomerController.java +++ b/src/main/java/camp/woowak/lab/web/api/customer/CustomerController.java @@ -1,4 +1,4 @@ -package camp.woowak.lab.web.api; +package camp.woowak.lab.web.api.customer; import java.net.URI; 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 new file mode 100644 index 00000000..e7fb2482 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/customer/CustomerExceptionHandler.java @@ -0,0 +1,43 @@ +package camp.woowak.lab.web.api.customer; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +import camp.woowak.lab.common.advice.DomainExceptionHandler; +import camp.woowak.lab.common.exception.BadRequestException; +import camp.woowak.lab.customer.exception.DuplicateEmailException; +import camp.woowak.lab.customer.exception.InvalidCreationException; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@DomainExceptionHandler +public class CustomerExceptionHandler extends ResponseEntityExceptionHandler { + /** + * + * BadRequestException.class 와 MethodArgumentNotValidException.class 를 처리한다. + */ + @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; + } + + /** + * + * DuplicateEmailException.class 를 처리한다. + */ + @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; + } +} diff --git a/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java b/src/test/java/camp/woowak/lab/web/api/customer/CustomerControllerTest.java similarity index 97% rename from src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java rename to src/test/java/camp/woowak/lab/web/api/customer/CustomerControllerTest.java index 4f85d3cd..499a8303 100644 --- a/src/test/java/camp/woowak/lab/web/api/CustomerControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/customer/CustomerControllerTest.java @@ -1,4 +1,4 @@ -package camp.woowak.lab.web.api; +package camp.woowak.lab.web.api.customer; import static org.mockito.ArgumentMatchers.*; import static org.mockito.BDDMockito.*; @@ -16,10 +16,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; +import camp.woowak.lab.customer.exception.CustomerErrorCode; import camp.woowak.lab.customer.exception.DuplicateEmailException; import camp.woowak.lab.customer.service.SignUpCustomerService; -import camp.woowak.lab.web.dto.request.SignUpCustomerRequest; -import camp.woowak.lab.web.error.ErrorCode; +import camp.woowak.lab.web.dto.request.customer.SignUpCustomerRequest; @WebMvcTest(CustomerController.class) @MockBean(JpaMetamodelMappingContext.class) From d2b4f552c869b94d58c5930dd719d87856e8e3c5 Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:13:00 +0900 Subject: [PATCH 110/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index c76f25c3..0d74b9fd 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -4,17 +4,10 @@ title: "[논의] 제목" body: - type: markdown attributes: - value: | - ## 논의 배경 - 이 논의의 배경이나 맥락을 설명해주세요. 문제점, 아이디어의 출처, 관련된 자료나 정보를 포함하세요. + value: "## 논의 배경\n이 논의의 배경이나 맥락을 설명해주세요. 문제점, 아이디어의 출처, 관련된 자료나 정보를 포함하세요." - type: textarea id: background attributes: label: 논의 배경 description: 이 논의를 시작하게 된 이유와 관련된 배경 정보를 입력하세요. placeholder: 예: 문제의 원인, 관련된 이슈, 제안된 솔루션 등 - value: | - # 예시 - - 최근 발생한 문제 또는 기회 - - 관련된 기존 논의 - - 이 논의의 중요성 From 3b07854a6552893a79584375c0387a686973abdd Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 14:13:04 +0900 Subject: [PATCH 111/146] =?UTF-8?q?[test]=20=EC=97=90=EB=9F=AC=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=A0=95=EC=B1=85=20=EB=B3=80=EA=B2=BD=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20=EC=88=98=EC=A0=95=20-=20Error?= =?UTF-8?q?Code=20=EC=82=AD=EC=A0=9C=20=ED=9B=84=20CustomerErrorCode=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../woowak/lab/web/api/customer/CustomerControllerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/camp/woowak/lab/web/api/customer/CustomerControllerTest.java b/src/test/java/camp/woowak/lab/web/api/customer/CustomerControllerTest.java index 499a8303..6d372caa 100644 --- a/src/test/java/camp/woowak/lab/web/api/customer/CustomerControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/customer/CustomerControllerTest.java @@ -209,7 +209,7 @@ void testSignUpCustomerWithDuplicateEmail() throws Exception { .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) .andExpect(status().isConflict()) - .andExpect(jsonPath("$.errorCode").value(ErrorCode.AUTH_DUPLICATE_EMAIL.getCode())) - .andExpect(jsonPath("$.detail").value(ErrorCode.AUTH_DUPLICATE_EMAIL.getMessage())); + .andExpect(jsonPath("$.errorCode").value(CustomerErrorCode.DUPLICATE_EMAIL.getErrorCode())) + .andExpect(jsonPath("$.detail").value(CustomerErrorCode.DUPLICATE_EMAIL.getMessage())); } } From d3d1cfc59428669a2af3be947fb7b6a497e562aa Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 14:13:24 +0900 Subject: [PATCH 112/146] =?UTF-8?q?[chore]=20@Repository=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/customer/repository/CustomerRepository.java | 2 -- 1 file changed, 2 deletions(-) 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..32b96ef2 100644 --- a/src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java +++ b/src/main/java/camp/woowak/lab/customer/repository/CustomerRepository.java @@ -1,10 +1,8 @@ package camp.woowak.lab.customer.repository; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; import camp.woowak.lab.customer.domain.Customer; -@Repository public interface CustomerRepository extends JpaRepository { } From 20dcbab49388e5a37a12805ba87de3330b9d9d43 Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:13:28 +0900 Subject: [PATCH 113/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index 0d74b9fd..0394c953 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -10,4 +10,4 @@ body: attributes: label: 논의 배경 description: 이 논의를 시작하게 된 이유와 관련된 배경 정보를 입력하세요. - placeholder: 예: 문제의 원인, 관련된 이슈, 제안된 솔루션 등 + placeholder: "예: 문제의 원인, 관련된 이슈, 제안된 솔루션 등" From 6be87cdd9bd71efbc72d77e2b55e41f251dd2b09 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 14:16:20 +0900 Subject: [PATCH 114/146] =?UTF-8?q?[chore]=20CustomerController=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD=20-=20CustomerControlle?= =?UTF-8?q?r=20->=20CustomerApiController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/customer/CustomerApiController.java | 38 +++++++++++++++++++ .../web/api/customer/CustomerController.java | 33 ---------------- ...st.java => CustomerApiControllerTest.java} | 4 +- 3 files changed, 40 insertions(+), 35 deletions(-) create mode 100644 src/main/java/camp/woowak/lab/web/api/customer/CustomerApiController.java delete mode 100644 src/main/java/camp/woowak/lab/web/api/customer/CustomerController.java rename src/test/java/camp/woowak/lab/web/api/customer/{CustomerControllerTest.java => CustomerApiControllerTest.java} (99%) 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 new file mode 100644 index 00000000..17397fcd --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/customer/CustomerApiController.java @@ -0,0 +1,38 @@ +package camp.woowak.lab.web.api.customer; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import camp.woowak.lab.customer.service.SignUpCustomerService; +import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; +import camp.woowak.lab.web.api.utils.APIResponse; +import camp.woowak.lab.web.api.utils.APIUtils; +import camp.woowak.lab.web.dto.request.customer.SignUpCustomerRequest; +import camp.woowak.lab.web.dto.response.customer.SignUpCustomerResponse; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; + +@RestController +public class CustomerApiController { + private final SignUpCustomerService signUpCustomerService; + + public CustomerApiController(SignUpCustomerService signUpCustomerService) { + this.signUpCustomerService = signUpCustomerService; + } + + @PostMapping("/customers") + public ResponseEntity> signUp(@Valid @RequestBody SignUpCustomerRequest request, + HttpServletResponse response) { + SignUpCustomerCommand command = + new SignUpCustomerCommand(request.name(), request.email(), request.password(), request.phone()); + + Long registeredId = signUpCustomerService.signUp(command); + + response.setHeader("Location", "/customers/" + registeredId); + + return APIUtils.of(HttpStatus.CREATED, new SignUpCustomerResponse(registeredId)); + } +} diff --git a/src/main/java/camp/woowak/lab/web/api/customer/CustomerController.java b/src/main/java/camp/woowak/lab/web/api/customer/CustomerController.java deleted file mode 100644 index 5207aa87..00000000 --- a/src/main/java/camp/woowak/lab/web/api/customer/CustomerController.java +++ /dev/null @@ -1,33 +0,0 @@ -package camp.woowak.lab.web.api.customer; - -import java.net.URI; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import camp.woowak.lab.customer.service.SignUpCustomerService; -import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; -import camp.woowak.lab.web.dto.request.SignUpCustomerRequest; -import jakarta.validation.Valid; - -@RestController -public class CustomerController { - private final SignUpCustomerService signUpCustomerService; - - public CustomerController(SignUpCustomerService signUpCustomerService) { - this.signUpCustomerService = signUpCustomerService; - } - - @PostMapping("/customers") - public ResponseEntity signUp(@Valid @RequestBody SignUpCustomerRequest request) { - SignUpCustomerCommand command = - new SignUpCustomerCommand(request.name(), request.email(), request.password(), request.phone()); - Long registeredId; - - registeredId = signUpCustomerService.signUp(command); - - return ResponseEntity.created(URI.create("/customers/" + registeredId)).build(); - } -} diff --git a/src/test/java/camp/woowak/lab/web/api/customer/CustomerControllerTest.java b/src/test/java/camp/woowak/lab/web/api/customer/CustomerApiControllerTest.java similarity index 99% rename from src/test/java/camp/woowak/lab/web/api/customer/CustomerControllerTest.java rename to src/test/java/camp/woowak/lab/web/api/customer/CustomerApiControllerTest.java index 6d372caa..4d55fbe2 100644 --- a/src/test/java/camp/woowak/lab/web/api/customer/CustomerControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/customer/CustomerApiControllerTest.java @@ -21,9 +21,9 @@ import camp.woowak.lab.customer.service.SignUpCustomerService; import camp.woowak.lab.web.dto.request.customer.SignUpCustomerRequest; -@WebMvcTest(CustomerController.class) +@WebMvcTest(CustomerApiController.class) @MockBean(JpaMetamodelMappingContext.class) -class CustomerControllerTest { +class CustomerApiControllerTest { @Autowired private MockMvc mockMvc; From e6b0b0c2ff99614dbc0ec09539588e6ba7cf6429 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 14:17:37 +0900 Subject: [PATCH 115/146] =?UTF-8?q?[refactor]=20SignUpCustomerRequest=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20-=20camp.woowak.lab.web.dto.request.customer=20?= =?UTF-8?q?=EB=B0=91=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/dto/request/{ => customer}/SignUpCustomerRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/camp/woowak/lab/web/dto/request/{ => customer}/SignUpCustomerRequest.java (88%) diff --git a/src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/customer/SignUpCustomerRequest.java similarity index 88% rename from src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java rename to src/main/java/camp/woowak/lab/web/dto/request/customer/SignUpCustomerRequest.java index 50b7ec2d..06d257d5 100644 --- a/src/main/java/camp/woowak/lab/web/dto/request/SignUpCustomerRequest.java +++ b/src/main/java/camp/woowak/lab/web/dto/request/customer/SignUpCustomerRequest.java @@ -1,4 +1,4 @@ -package camp.woowak.lab.web.dto.request; +package camp.woowak.lab.web.dto.request.customer; import org.hibernate.validator.constraints.Length; From f6d3346983ab0cd741a58099456c663dd1dde8c9 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 14:18:57 +0900 Subject: [PATCH 116/146] =?UTF-8?q?[feat]=20BadRequestException=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=B6=94=EA=B0=80=20-=20BadReque?= =?UTF-8?q?stException(ErrorCode,=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 --- .../camp/woowak/lab/common/exception/BadRequestException.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/camp/woowak/lab/common/exception/BadRequestException.java b/src/main/java/camp/woowak/lab/common/exception/BadRequestException.java index 3b4d4090..4fb65cd5 100644 --- a/src/main/java/camp/woowak/lab/common/exception/BadRequestException.java +++ b/src/main/java/camp/woowak/lab/common/exception/BadRequestException.java @@ -4,4 +4,8 @@ public class BadRequestException extends HttpStatusException { public BadRequestException(ErrorCode errorCode) { super(errorCode); } + + public BadRequestException(ErrorCode errorCode, String message) { + super(errorCode, message); + } } From 16ff26ce1acb24a343d4998ef950a46fbea919b7 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 14:20:19 +0900 Subject: [PATCH 117/146] =?UTF-8?q?[feat]=20=EC=97=90=EB=9F=AC=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=A0=95=EC=B1=85=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=EC=84=9C?= =?UTF-8?q?=EB=B2=84=EC=97=90=20=EB=82=A8=EA=B8=B0=EA=B3=A0=20=EC=8B=B6?= =?UTF-8?q?=EC=9D=80=20=EB=A1=9C=EA=B7=B8=EB=8A=94=20=EC=A7=81=EC=A0=91=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20-=20=EC=97=90=EB=9F=AC=EC=BD=94=EB=93=9C=EC=97=90?= =?UTF-8?q?=20=EC=9E=88=EB=8A=94=20=EB=A9=94=EC=8B=9C=EC=A7=80=EB=8A=94=20?= =?UTF-8?q?=ED=81=B4=EB=9D=BC=EC=9D=B4=EC=96=B8=ED=8A=B8=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EA=B2=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/customer/exception/CustomerErrorCode.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 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 fae69360..7ad34f6c 100644 --- a/src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java +++ b/src/main/java/camp/woowak/lab/customer/exception/CustomerErrorCode.java @@ -3,16 +3,8 @@ import camp.woowak.lab.common.exception.ErrorCode; public enum CustomerErrorCode implements ErrorCode { - INVALID_PAY_ACCOUNT_IS_NOT_NULL(400, "C1", "Customer payAccount cannot be null"), - INVALID_PHONE_IS_NOT_BLANK(400, "C2", "Customer phone cannot be blank"), - INVALID_PHONE_IS_TOO_LONG(400, "C3", "Customer phone cannot be longer than 30 characters"), - INVALID_PASSWORD_IS_NOT_BLANK(400, "C4", "Customer password cannot be blank"), - INVALID_PASSWORD_IS_TOO_LONG(400, "C5", "Customer password cannot be longer than 30 characters"), - INVALID_EMAIL_IS_NOT_BLANK(400, "C6", "Customer email cannot be blank"), - INVALID_EMAIL_IS_TOO_LONG(400, "C7", "Customer email cannot be longer than 100 characters"), - INVALID_NAME_IS_NOT_BLANK(400, "C8", "Customer name cannot be blank"), - INVALID_NAME_IS_TOO_LONG(400, "C9", "Customer name cannot be longer than 100 characters"), - DUPLICATE_EMAIL(400, "C10", "Customer email is already in use"); + INVALID_CREATION(400, "C1", "잘못된 요청입니다."), + DUPLICATE_EMAIL(400, "C2", "이미 존재하는 이메일입니다."); private final int status; private final String errorCode; From 0cf6e1b1cfc648e60b6a1e0a10210ae518c53e4c Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:20:23 +0900 Subject: [PATCH 118/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index 0394c953..618efe4f 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -1,13 +1,7 @@ -name: "[논의] " -description: "논의를 시작할 때 참고할 정보를 입력하세요." -title: "[논의] 제목" +title: "[논의] " +labels: ["🙋‍♂️ Question"] body: - type: markdown attributes: - value: "## 논의 배경\n이 논의의 배경이나 맥락을 설명해주세요. 문제점, 아이디어의 출처, 관련된 자료나 정보를 포함하세요." - - type: textarea - id: background - attributes: - label: 논의 배경 - description: 이 논의를 시작하게 된 이유와 관련된 배경 정보를 입력하세요. - placeholder: "예: 문제의 원인, 관련된 이슈, 제안된 솔루션 등" + value: | + ### 논의 배경 From f932caeb697222a2f75f2293538c981ef6d0603a Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 14:20:38 +0900 Subject: [PATCH 119/146] =?UTF-8?q?[feat]=20=EC=97=90=EB=9F=AC=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=A0=95=EC=B1=85=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?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../customer/domain/CustomerValidator.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java b/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java index 5e8d5ece..d890eff8 100644 --- a/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java +++ b/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java @@ -7,7 +7,7 @@ public class CustomerValidator { public static void validateCreation(String name, String email, String password, String phone, - PayAccount payAccount) throws InvalidCreationException { + PayAccount payAccount) throws InvalidCreationException { validateName(name); validateEmail(email); validatePassword(password); @@ -17,43 +17,48 @@ public static void validateCreation(String name, String email, String password, public static void validateName(String name) throws InvalidCreationException { if (name == null || name.isBlank()) { - throw new InvalidCreationException(CustomerErrorCode.INVALID_NAME_IS_NOT_BLANK); + throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, "Customer name cannot be blank"); } if (name.length() > 50) { - throw new InvalidCreationException(CustomerErrorCode.INVALID_NAME_IS_TOO_LONG); + throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, + "Customer name cannot be longer than 50 characters"); } } public static void validateEmail(String email) throws InvalidCreationException { if (email == null || email.isBlank()) { - throw new InvalidCreationException(CustomerErrorCode.INVALID_EMAIL_IS_NOT_BLANK); + throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, "Customer email cannot be blank"); } if (email.trim().length() > 100) { - throw new InvalidCreationException(CustomerErrorCode.INVALID_EMAIL_IS_TOO_LONG); + throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, + "Customer email cannot be longer than 100 characters"); } } public static void validatePassword(String password) throws InvalidCreationException { if (password == null || password.isBlank()) { - throw new InvalidCreationException(CustomerErrorCode.INVALID_PASSWORD_IS_NOT_BLANK); + throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, "Customer password cannot be blank"); } if (password.trim().length() > 30) { - throw new InvalidCreationException(CustomerErrorCode.INVALID_PASSWORD_IS_TOO_LONG); + throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, + "Customer password cannot be longer than 30 characters"); } } public static void validatePhone(String phone) throws InvalidCreationException { if (phone == null || phone.isBlank()) { - throw new InvalidCreationException(CustomerErrorCode.INVALID_PHONE_IS_NOT_BLANK); + throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, "Customer phone cannot be blank"); } if (phone.trim().length() > 30) { - throw new InvalidCreationException(CustomerErrorCode.INVALID_PHONE_IS_TOO_LONG); + throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, + "Customer phone cannot be longer than 30 characters"); } } public static void validatePayAccount(PayAccount payAccount) throws InvalidCreationException { if (payAccount == null) { - throw new InvalidCreationException(CustomerErrorCode.INVALID_PAY_ACCOUNT_IS_NOT_NULL); + throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, + "Customer payAccount cannot be null"); } } } From 24d844b92314a4c245214b7308afe73c71e215e2 Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:20:56 +0900 Subject: [PATCH 120/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 54 +++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index 618efe4f..537f49a2 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -1,7 +1,55 @@ -title: "[논의] " -labels: ["🙋‍♂️ Question"] +title: "[General] " +labels: ["General Introduction"] body: - type: markdown attributes: value: | - ### 논의 배경 + This is text that will show up in the template! + - type: textarea + id: improvements + attributes: + label: Top 3 improvements + description: "What are the top 3 improvements we could make to this project?" + value: | + 1. + 2. + 3. + ... + render: bash + validations: + required: true + - type: markdown + attributes: + value: | + ## Markdown header + And some more markdown + - type: input + id: has-id + attributes: + label: Suggestions + description: A description about suggestions to help you + validations: + required: true + - type: dropdown + id: download + attributes: + label: Which area of this project could be most improved? + options: + - Documentation + - Pull request review time + - Bug fix time + - Release cadence + validations: + required: true + - type: checkboxes + attributes: + label: Check that box! + options: + - label: This one! + required: true + - label: I won't stop you if you check this one, too + - type: markdown + attributes: + value: | + ### The thrilling conclusion + _to our template_ From 54840c1d85bed69a4511179512171f92045fe596 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 14:21:34 +0900 Subject: [PATCH 121/146] =?UTF-8?q?[feat]=20InvalidCreationException=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20-=20InvalidCreationException(ErrorCode,=20?= =?UTF-8?q?String)=20=EC=83=9D=EC=84=B1=EC=9E=90=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/InvalidCreationException.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java b/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java index 72e05311..26ae7d49 100644 --- a/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java +++ b/src/main/java/camp/woowak/lab/customer/exception/InvalidCreationException.java @@ -4,7 +4,7 @@ import camp.woowak.lab.common.exception.ErrorCode; public class InvalidCreationException extends BadRequestException { - public InvalidCreationException(ErrorCode errorCode) { - super(errorCode); + public InvalidCreationException(ErrorCode errorCode, String message) { + super(errorCode, message); } } From e4115f2d97c58566fcf76c47fca3178c784add0b Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:22:07 +0900 Subject: [PATCH 122/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DISCUSSION_TEMPLATE/General.yml | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 DISCUSSION_TEMPLATE/General.yml diff --git a/DISCUSSION_TEMPLATE/General.yml b/DISCUSSION_TEMPLATE/General.yml deleted file mode 100644 index 6aa137b3..00000000 --- a/DISCUSSION_TEMPLATE/General.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: [논의] -description: 논의를 시작할 때 참고할 정보를 입력하세요. -title: [논의] 제목 -body: - - type: markdown - attributes: - value: | - ## 논의 배경 - 이 논의의 배경이나 맥락을 설명해주세요. 문제점, 아이디어의 출처, 관련된 자료나 정보를 포함하세요. - - type: textarea - id: background - attributes: - label: 논의 배경 - description: 이 논의를 시작하게 된 이유와 관련된 배경 정보를 입력하세요. - placeholder: 예: 문제의 원인, 관련된 이슈, 제안된 솔루션 등 - value: | - # 예시 - - 최근 발생한 문제 또는 기회 - - 관련된 기존 논의 - - 이 논의의 중요성 From c8784cda9ec1e8f8c4053edbba8a39e1e8b8fdbd Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 14:22:31 +0900 Subject: [PATCH 123/146] =?UTF-8?q?[feat]=20SignUpCustomerResponse=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20SignUp=20API=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=EC=9D=98=20Response=20DTO=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/SignUpCustomerResponse.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/camp/woowak/lab/web/dto/response/customer/SignUpCustomerResponse.java diff --git a/src/main/java/camp/woowak/lab/web/dto/response/customer/SignUpCustomerResponse.java b/src/main/java/camp/woowak/lab/web/dto/response/customer/SignUpCustomerResponse.java new file mode 100644 index 00000000..87b9a605 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/dto/response/customer/SignUpCustomerResponse.java @@ -0,0 +1,4 @@ +package camp.woowak.lab.web.dto.response.customer; + +public record SignUpCustomerResponse(Long id) { +} From 6f125c943c62a25ba5ce9fe27016e2431c39a3de Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 14:25:30 +0900 Subject: [PATCH 124/146] =?UTF-8?q?[feat]=20CustomerValidator=20private=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=B6=94=EA=B0=80=20-=20?= =?UTF-8?q?=EC=9C=A0=ED=8B=B8=EB=A6=AC=ED=8B=B0=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=EC=97=90=20private=20=EC=83=9D=EC=84=B1=EC=9E=90=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/customer/domain/CustomerValidator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java b/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java index d890eff8..4db3c2d0 100644 --- a/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java +++ b/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java @@ -6,6 +6,9 @@ public class CustomerValidator { + private CustomerValidator() { + } + public static void validateCreation(String name, String email, String password, String phone, PayAccount payAccount) throws InvalidCreationException { validateName(name); From c058602e9feec3c38e310b34cdd085dc97670710 Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:29:08 +0900 Subject: [PATCH 125/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 45 +++---------------------- 1 file changed, 5 insertions(+), 40 deletions(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index 537f49a2..730c7f07 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -1,15 +1,15 @@ -title: "[General] " -labels: ["General Introduction"] +title: "[논의] " +labels: ["🙋‍♂️ Question"] body: - type: markdown attributes: value: | - This is text that will show up in the template! + 논의하고 싶은 세부 주제에 대해 작성해주세요. - type: textarea id: improvements attributes: - label: Top 3 improvements - description: "What are the top 3 improvements we could make to this project?" + label: 세부 주제 + description: "논의하고 싶은 세부 주제에 대해 작성해주세요." value: | 1. 2. @@ -18,38 +18,3 @@ body: render: bash validations: required: true - - type: markdown - attributes: - value: | - ## Markdown header - And some more markdown - - type: input - id: has-id - attributes: - label: Suggestions - description: A description about suggestions to help you - validations: - required: true - - type: dropdown - id: download - attributes: - label: Which area of this project could be most improved? - options: - - Documentation - - Pull request review time - - Bug fix time - - Release cadence - validations: - required: true - - type: checkboxes - attributes: - label: Check that box! - options: - - label: This one! - required: true - - label: I won't stop you if you check this one, too - - type: markdown - attributes: - value: | - ### The thrilling conclusion - _to our template_ From 8ad84f93221a1c4ac569fa6608ee5382d7b8b853 Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:30:24 +0900 Subject: [PATCH 126/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 36 ++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index 730c7f07..36f9d5e7 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -1,15 +1,15 @@ -title: "[논의] " +title: "[논의] " labels: ["🙋‍♂️ Question"] body: - type: markdown attributes: value: | - 논의하고 싶은 세부 주제에 대해 작성해주세요. + This is text that will show up in the template! - type: textarea id: improvements attributes: - label: 세부 주제 - description: "논의하고 싶은 세부 주제에 대해 작성해주세요." + label: Top 3 improvements + description: "논의하고 싶은 세부 주제를 입력해주세요." value: | 1. 2. @@ -18,3 +18,31 @@ body: render: bash validations: required: true + - type: markdown + attributes: + value: | + ## Markdown header + And some more markdown + - type: input + id: has-id + attributes: + label: Suggestions + description: A description about suggestions to help you + validations: + required: true + - type: dropdown + id: download + attributes: + label: Which area of this project could be most improved? + options: + - Documentation + - Pull request review time + - Bug fix time + - Release cadence + validations: + required: true + - type: markdown + attributes: + value: | + ### The thrilling conclusion + _to our template_ From e5543bfd2d57e6375ceabc5c7b94dbec578dc1e2 Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:31:14 +0900 Subject: [PATCH 127/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index 36f9d5e7..10da55c1 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -1,4 +1,4 @@ -title: "[논의] " +title: "[논의]" labels: ["🙋‍♂️ Question"] body: - type: markdown From f4d8c1dfe2e32334f40c0e2f6f7e8bb432a6360b Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:32:25 +0900 Subject: [PATCH 128/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index 10da55c1..f85e81d6 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -1,5 +1,5 @@ -title: "[논의]" -labels: ["🙋‍♂️ Question"] +title: "[Discussion] " +labels: ["General Introduction"] body: - type: markdown attributes: @@ -9,7 +9,7 @@ body: id: improvements attributes: label: Top 3 improvements - description: "논의하고 싶은 세부 주제를 입력해주세요." + description: "What are the top 3 improvements we could make to this project?" value: | 1. 2. @@ -41,6 +41,13 @@ body: - Release cadence validations: required: true + - type: checkboxes + attributes: + label: Check that box! + options: + - label: This one! + required: true + - label: I won't stop you if you check this one, too - type: markdown attributes: value: | From 9e1c97780186b97f6e13d2b5a773c34b31d6bc14 Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:33:11 +0900 Subject: [PATCH 129/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index f85e81d6..f54030be 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -1,4 +1,4 @@ -title: "[Discussion] " +title: "[논의] " labels: ["General Introduction"] body: - type: markdown From 1de348efceb186a0aeb9fb21b193872d10602a72 Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:33:54 +0900 Subject: [PATCH 130/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index f54030be..3fcd34e9 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -41,13 +41,6 @@ body: - Release cadence validations: required: true - - type: checkboxes - attributes: - label: Check that box! - options: - - label: This one! - required: true - - label: I won't stop you if you check this one, too - type: markdown attributes: value: | From cba5b74db337ea4701f73a1a1694315c39c35199 Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:35:55 +0900 Subject: [PATCH 131/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 28 ------------------------- 1 file changed, 28 deletions(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index 3fcd34e9..b3a4c05e 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -18,31 +18,3 @@ body: render: bash validations: required: true - - type: markdown - attributes: - value: | - ## Markdown header - And some more markdown - - type: input - id: has-id - attributes: - label: Suggestions - description: A description about suggestions to help you - validations: - required: true - - type: dropdown - id: download - attributes: - label: Which area of this project could be most improved? - options: - - Documentation - - Pull request review time - - Bug fix time - - Release cadence - validations: - required: true - - type: markdown - attributes: - value: | - ### The thrilling conclusion - _to our template_ From 8d1c4b8977d81518d18af7b9cbdc2210d2ec466d Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:38:57 +0900 Subject: [PATCH 132/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index b3a4c05e..7dae2838 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -6,10 +6,21 @@ body: value: | This is text that will show up in the template! - type: textarea - id: improvements + id: background attributes: - label: Top 3 improvements - description: "What are the top 3 improvements we could make to this project?" + label: 배경 + description: "발의한 배경에 대해 간략히 서술해주세요" + value: | + + ... + render: bash + validations: + required: true + - type: textarea + id: subject + attributes: + label: 세부 주제 + description: "논의하고 싶은 세부 주제를 작성해주세요." value: | 1. 2. From 5b040ae5090a2e7e9426f4ae7995e0bab39622db Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:39:49 +0900 Subject: [PATCH 133/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index 7dae2838..afdd06e4 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -11,8 +11,6 @@ body: label: 배경 description: "발의한 배경에 대해 간략히 서술해주세요" value: | - - ... render: bash validations: required: true @@ -25,7 +23,6 @@ body: 1. 2. 3. - ... render: bash validations: required: true From 035111020a71261a79dd216b1cb309468210b30e Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:40:40 +0900 Subject: [PATCH 134/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index afdd06e4..ae8e8441 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -11,6 +11,7 @@ body: label: 배경 description: "발의한 배경에 대해 간략히 서술해주세요" value: | + ... render: bash validations: required: true From 10c1b8cbee973c2e9131013070137aecec4d83f6 Mon Sep 17 00:00:00 2001 From: Dr-KoKo <97681286+Dr-KoKo@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:41:23 +0900 Subject: [PATCH 135/146] =?UTF-8?q?[docs]=20Discussion=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/DISCUSSION_TEMPLATE/general.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/DISCUSSION_TEMPLATE/general.yml b/.github/DISCUSSION_TEMPLATE/general.yml index ae8e8441..01e86dad 100644 --- a/.github/DISCUSSION_TEMPLATE/general.yml +++ b/.github/DISCUSSION_TEMPLATE/general.yml @@ -1,5 +1,5 @@ title: "[논의] " -labels: ["General Introduction"] +labels: ["🙋‍♂️ Question"] body: - type: markdown attributes: From ffdb3a47f4b1ea0aff634d83c129a63e1f94d506 Mon Sep 17 00:00:00 2001 From: donghar Date: Tue, 13 Aug 2024 14:46:13 +0900 Subject: [PATCH 136/146] =?UTF-8?q?[fix]=20SignUpVendorService=EB=8A=94=20?= =?UTF-8?q?UncheckedException=EC=9D=84=20=EB=8D=98=EC=A7=84=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 서비스에서 UncheckedException을 던지게 수정 --- .../camp/woowak/lab/vendor/service/SignUpVendorService.java | 5 ++--- .../woowak/lab/vendor/service/SignUpVendorServiceTest.java | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/camp/woowak/lab/vendor/service/SignUpVendorService.java b/src/main/java/camp/woowak/lab/vendor/service/SignUpVendorService.java index 8db42e1d..13b9e30a 100644 --- a/src/main/java/camp/woowak/lab/vendor/service/SignUpVendorService.java +++ b/src/main/java/camp/woowak/lab/vendor/service/SignUpVendorService.java @@ -8,13 +8,12 @@ import camp.woowak.lab.payaccount.repository.PayAccountRepository; import camp.woowak.lab.vendor.domain.Vendor; import camp.woowak.lab.vendor.exception.DuplicateEmailException; -import camp.woowak.lab.vendor.exception.InvalidCreationException; import camp.woowak.lab.vendor.repository.VendorRepository; import camp.woowak.lab.vendor.service.command.SignUpVendorCommand; import camp.woowak.lab.web.authentication.PasswordEncoder; @Service -@Transactional(rollbackFor = {InvalidCreationException.class, DuplicateEmailException.class}) +@Transactional public class SignUpVendorService { private final VendorRepository vendorRepository; private final PayAccountRepository payAccountRepository; @@ -27,7 +26,7 @@ public SignUpVendorService( this.passwordEncoder = passwordEncoder; } - public Long signUp(SignUpVendorCommand cmd) throws InvalidCreationException, DuplicateEmailException { + public Long signUp(SignUpVendorCommand cmd) { PayAccount newPayAccount = new PayAccount(); payAccountRepository.save(newPayAccount); Vendor newVendor = diff --git a/src/test/java/camp/woowak/lab/vendor/service/SignUpVendorServiceTest.java b/src/test/java/camp/woowak/lab/vendor/service/SignUpVendorServiceTest.java index 711ae8c2..cf7498d5 100644 --- a/src/test/java/camp/woowak/lab/vendor/service/SignUpVendorServiceTest.java +++ b/src/test/java/camp/woowak/lab/vendor/service/SignUpVendorServiceTest.java @@ -17,7 +17,6 @@ import camp.woowak.lab.payaccount.repository.PayAccountRepository; import camp.woowak.lab.vendor.domain.Vendor; import camp.woowak.lab.vendor.exception.DuplicateEmailException; -import camp.woowak.lab.vendor.exception.DuplicateException; import camp.woowak.lab.vendor.exception.InvalidCreationException; import camp.woowak.lab.vendor.repository.VendorRepository; import camp.woowak.lab.vendor.service.command.SignUpVendorCommand; @@ -68,7 +67,7 @@ void failWithDuplicateEmail() throws InvalidCreationException, DuplicateEmailExc new SignUpVendorCommand("vendorName", "vendorEmail@example.com", "password", "010-0000-0000"); // then - Assertions.assertThrows(DuplicateException.class, () -> service.signUp(command)); + Assertions.assertThrows(DuplicateEmailException.class, () -> service.signUp(command)); then(payAccountRepository).should().save(Mockito.any(PayAccount.class)); then(vendorRepository).should().save(Mockito.any(Vendor.class)); } From 2f94a72afd49097aa0c1178c77fb73cc02c0a6de Mon Sep 17 00:00:00 2001 From: donghar Date: Tue, 13 Aug 2024 14:53:00 +0900 Subject: [PATCH 137/146] =?UTF-8?q?[refactor]=20=EC=BD=94=EB=94=A9=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=A4=EC=85=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/camp/woowak/lab/vendor/domain/Vendor.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java b/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java index 910eb8e4..d6f35a9b 100644 --- a/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java +++ b/src/main/java/camp/woowak/lab/vendor/domain/Vendor.java @@ -31,11 +31,10 @@ protected Vendor() { } /** - * * @throws InvalidVendorCreationException 검증에 실패하면 */ public Vendor(String name, String email, String password, String phone, PayAccount payAccount, - PasswordEncoder passwordEncoder) { + PasswordEncoder passwordEncoder) { VendorValidator.validate(name, email, password, phone, payAccount); this.name = name; this.email = email; From d6895c32894c69f9ee4de7cf0fc801b4b703ad17 Mon Sep 17 00:00:00 2001 From: donghar Date: Tue, 13 Aug 2024 14:54:32 +0900 Subject: [PATCH 138/146] =?UTF-8?q?[fix]=20VendorApiController=EB=8A=94=20?= =?UTF-8?q?APIResponse=EB=A5=BC=20=EC=9D=91=EB=8B=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 예외는 VendorApiControllerAdvice에서 처리 --- .../woowak/lab/web/api/VendorController.java | 45 ------------------- .../web/api/vendor/VendorApiController.java | 35 +++++++++++++++ .../api/vendor/VendorApiControllerAdvice.java | 25 +++++++++++ .../{ => vendor}/SignUpVendorRequest.java | 2 +- .../response/vendor/SignUpVendorResponse.java | 6 +++ 5 files changed, 67 insertions(+), 46 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/web/api/VendorController.java create mode 100644 src/main/java/camp/woowak/lab/web/api/vendor/VendorApiController.java create mode 100644 src/main/java/camp/woowak/lab/web/api/vendor/VendorApiControllerAdvice.java rename src/main/java/camp/woowak/lab/web/dto/request/{ => vendor}/SignUpVendorRequest.java (89%) create mode 100644 src/main/java/camp/woowak/lab/web/dto/response/vendor/SignUpVendorResponse.java diff --git a/src/main/java/camp/woowak/lab/web/api/VendorController.java b/src/main/java/camp/woowak/lab/web/api/VendorController.java deleted file mode 100644 index a2e8fe03..00000000 --- a/src/main/java/camp/woowak/lab/web/api/VendorController.java +++ /dev/null @@ -1,45 +0,0 @@ -package camp.woowak.lab.web.api; - -import java.net.URI; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ProblemDetail; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import camp.woowak.lab.vendor.exception.DuplicateEmailException; -import camp.woowak.lab.vendor.exception.InvalidCreationException; -import camp.woowak.lab.vendor.service.SignUpVendorService; -import camp.woowak.lab.vendor.service.command.SignUpVendorCommand; -import camp.woowak.lab.web.dto.request.SignUpVendorRequest; -import camp.woowak.lab.web.dto.response.ApiResponse; -import camp.woowak.lab.web.error.ErrorCode; -import jakarta.validation.Valid; - -@RestController -public class VendorController { - private final SignUpVendorService signUpVendorService; - - public VendorController(SignUpVendorService signUpVendorService) { - this.signUpVendorService = signUpVendorService; - } - - @PostMapping("/vendors") - public ResponseEntity signUpVendor(@Valid @RequestBody SignUpVendorRequest request) { - SignUpVendorCommand command = - new SignUpVendorCommand(request.name(), request.email(), request.password(), request.phone()); - Long registeredId; - try { - registeredId = signUpVendorService.signUp(command); - } catch (InvalidCreationException e) { - return ResponseEntity.badRequest() - .body(ProblemDetail.forStatusAndDetail( - HttpStatus.BAD_REQUEST, ErrorCode.SIGNUP_INVALID_REQUEST.getMessage())); - } catch (DuplicateEmailException e) { - return ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_DUPLICATE_EMAIL)); - } - return ResponseEntity.created(URI.create("/vendors/" + registeredId)).build(); - } -} diff --git a/src/main/java/camp/woowak/lab/web/api/vendor/VendorApiController.java b/src/main/java/camp/woowak/lab/web/api/vendor/VendorApiController.java new file mode 100644 index 00000000..3d54139a --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/vendor/VendorApiController.java @@ -0,0 +1,35 @@ +package camp.woowak.lab.web.api.vendor; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +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.vendor.service.SignUpVendorService; +import camp.woowak.lab.vendor.service.command.SignUpVendorCommand; +import camp.woowak.lab.web.api.utils.APIResponse; +import camp.woowak.lab.web.api.utils.APIUtils; +import camp.woowak.lab.web.dto.request.vendor.SignUpVendorRequest; +import camp.woowak.lab.web.dto.response.vendor.SignUpVendorResponse; +import jakarta.validation.Valid; + +@RestController +public class VendorApiController { + private final SignUpVendorService signUpVendorService; + + public VendorApiController(SignUpVendorService signUpVendorService) { + this.signUpVendorService = signUpVendorService; + } + + @PostMapping("/vendors") + @ResponseStatus(HttpStatus.CREATED) + public ResponseEntity> signUpVendor( + @Valid @RequestBody SignUpVendorRequest request) { + SignUpVendorCommand command = + new SignUpVendorCommand(request.name(), request.email(), request.password(), request.phone()); + Long registeredId = signUpVendorService.signUp(command); + return APIUtils.of(HttpStatus.CREATED, new SignUpVendorResponse(registeredId)); + } +} diff --git a/src/main/java/camp/woowak/lab/web/api/vendor/VendorApiControllerAdvice.java b/src/main/java/camp/woowak/lab/web/api/vendor/VendorApiControllerAdvice.java new file mode 100644 index 00000000..1e328a3f --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/api/vendor/VendorApiControllerAdvice.java @@ -0,0 +1,25 @@ +package camp.woowak.lab.web.api.vendor; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import camp.woowak.lab.common.advice.DomainExceptionHandler; +import camp.woowak.lab.vendor.exception.DuplicateEmailException; +import camp.woowak.lab.vendor.exception.InvalidVendorCreationException; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@DomainExceptionHandler(basePackageClasses = VendorApiController.class) +public class VendorApiControllerAdvice { + @ExceptionHandler(InvalidVendorCreationException.class) + public ResponseEntity handleInvalidVendorCreationException(InvalidVendorCreationException ex) { + return ResponseEntity.of(ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, ex.getMessage())).build(); + } + + @ExceptionHandler(DuplicateEmailException.class) + public ResponseEntity handleDuplicateEmailException(DuplicateEmailException ex) { + return ResponseEntity.of(ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, ex.getMessage())).build(); + } +} diff --git a/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/vendor/SignUpVendorRequest.java similarity index 89% rename from src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java rename to src/main/java/camp/woowak/lab/web/dto/request/vendor/SignUpVendorRequest.java index b8d886cb..63cf946d 100644 --- a/src/main/java/camp/woowak/lab/web/dto/request/SignUpVendorRequest.java +++ b/src/main/java/camp/woowak/lab/web/dto/request/vendor/SignUpVendorRequest.java @@ -1,4 +1,4 @@ -package camp.woowak.lab.web.dto.request; +package camp.woowak.lab.web.dto.request.vendor; import org.hibernate.validator.constraints.Length; diff --git a/src/main/java/camp/woowak/lab/web/dto/response/vendor/SignUpVendorResponse.java b/src/main/java/camp/woowak/lab/web/dto/response/vendor/SignUpVendorResponse.java new file mode 100644 index 00000000..48216659 --- /dev/null +++ b/src/main/java/camp/woowak/lab/web/dto/response/vendor/SignUpVendorResponse.java @@ -0,0 +1,6 @@ +package camp.woowak.lab.web.dto.response.vendor; + +public record SignUpVendorResponse( + Long id +) { +} From 5fbc11a6fd6006aae26b62742722edc8c218fcc4 Mon Sep 17 00:00:00 2001 From: donghar Date: Tue, 13 Aug 2024 14:54:56 +0900 Subject: [PATCH 139/146] =?UTF-8?q?[refactor]=20=EC=BD=94=EB=94=A9=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=A4=EC=85=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/camp/woowak/lab/vendor/domain/VendorValidator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/camp/woowak/lab/vendor/domain/VendorValidator.java b/src/main/java/camp/woowak/lab/vendor/domain/VendorValidator.java index 6f8dcf0d..6d8580cc 100644 --- a/src/main/java/camp/woowak/lab/vendor/domain/VendorValidator.java +++ b/src/main/java/camp/woowak/lab/vendor/domain/VendorValidator.java @@ -12,7 +12,7 @@ public final class VendorValidator { private static final int MAX_PHONE_LENGTH = 30; public static void validate(final String name, final String email, final String password, final String phone, - final PayAccount payAccount) throws InvalidVendorCreationException { + final PayAccount payAccount) throws InvalidVendorCreationException { checkName(name); checkEmail(email); checkPassword(password); From 5235f93a0a0b0bddd06d66dc32b05b163f82f7c7 Mon Sep 17 00:00:00 2001 From: donghar Date: Tue, 13 Aug 2024 14:55:42 +0900 Subject: [PATCH 140/146] =?UTF-8?q?[test]=20=EC=A4=91=EB=B3=B5=20=EC=9D=B4?= =?UTF-8?q?=EB=A9=94=EC=9D=BC=EC=9D=80=20ProblemDetail=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...Test.java => VendorApiControllerTest.java} | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) rename src/test/java/camp/woowak/lab/web/api/{VendorControllerTest.java => VendorApiControllerTest.java} (94%) diff --git a/src/test/java/camp/woowak/lab/web/api/VendorControllerTest.java b/src/test/java/camp/woowak/lab/web/api/VendorApiControllerTest.java similarity index 94% rename from src/test/java/camp/woowak/lab/web/api/VendorControllerTest.java rename to src/test/java/camp/woowak/lab/web/api/VendorApiControllerTest.java index 5d38fb01..b6083049 100644 --- a/src/test/java/camp/woowak/lab/web/api/VendorControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/VendorApiControllerTest.java @@ -14,21 +14,22 @@ 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 org.springframework.test.web.servlet.result.MockMvcResultMatchers; import com.fasterxml.jackson.databind.ObjectMapper; import camp.woowak.lab.vendor.exception.DuplicateEmailException; import camp.woowak.lab.vendor.service.SignUpVendorService; import camp.woowak.lab.vendor.service.command.SignUpVendorCommand; -import camp.woowak.lab.web.dto.request.SignUpVendorRequest; +import camp.woowak.lab.web.api.vendor.VendorApiController; +import camp.woowak.lab.web.dto.request.vendor.SignUpVendorRequest; -@WebMvcTest(controllers = VendorController.class) +@WebMvcTest(controllers = VendorApiController.class) @MockBean(JpaMetamodelMappingContext.class) -class VendorControllerTest { +class VendorApiControllerTest { @Autowired private MockMvc mockMvc; @MockBean @@ -56,7 +57,8 @@ void success() throws Exception { // then actions.andExpect(status().isCreated()) - .andExpect(MockMvcResultMatchers.header().string("location", "/vendors/" + fakeVendorId)) + .andExpect(jsonPath("$.status").value(HttpStatus.CREATED.value())) + .andExpect(jsonPath("$.data.id").value(fakeVendorId)) .andDo(print()); } @@ -365,7 +367,7 @@ void failWithInvalidPhone() throws Exception { } @Test - @DisplayName("[실패] 200 a1: 이미 가입된 이메일인 경우") + @DisplayName("[실패] 400 : 이미 가입된 이메일인 경우") void failWithDuplicateEmail() throws Exception { BDDMockito.given(signUpVendorService.signUp(BDDMockito.any(SignUpVendorCommand.class))) .willThrow(DuplicateEmailException.class); @@ -381,10 +383,11 @@ void failWithDuplicateEmail() throws Exception { ); // then - actions.andExpect(status().isOk()) - .andExpect(jsonPath("$.code").value("a1")) - .andExpect(jsonPath("$.message").value("이미 가입된 이메일 입니다.")) - .andExpect(jsonPath("$.data").isEmpty()) + actions.andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.type").value("about:blank")) + .andExpect(jsonPath("$.title").value("Bad Request")) + .andExpect(jsonPath("$.status").value(400)) + .andExpect(jsonPath("$.instance").value("/vendors")) .andDo(print()); } } From 1c0386fd158a55be862a2d8236924731b3f5f397 Mon Sep 17 00:00:00 2001 From: donghar Date: Tue, 13 Aug 2024 15:02:19 +0900 Subject: [PATCH 141/146] =?UTF-8?q?[fix]=20=EA=B8=B0=EC=A1=B4=EC=9D=98=20C?= =?UTF-8?q?heckedException=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HttpStatusException을 상속받은 RuntimeException으로 변경 --- .../lab/vendor/exception/InvalidCreationException.java | 7 ------- .../woowak/lab/vendor/service/SignUpVendorServiceTest.java | 5 ++--- 2 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 src/main/java/camp/woowak/lab/vendor/exception/InvalidCreationException.java diff --git a/src/main/java/camp/woowak/lab/vendor/exception/InvalidCreationException.java b/src/main/java/camp/woowak/lab/vendor/exception/InvalidCreationException.java deleted file mode 100644 index 019da917..00000000 --- a/src/main/java/camp/woowak/lab/vendor/exception/InvalidCreationException.java +++ /dev/null @@ -1,7 +0,0 @@ -package camp.woowak.lab.vendor.exception; - -public class InvalidCreationException extends Exception { - public InvalidCreationException(String message) { - super(message); - } -} diff --git a/src/test/java/camp/woowak/lab/vendor/service/SignUpVendorServiceTest.java b/src/test/java/camp/woowak/lab/vendor/service/SignUpVendorServiceTest.java index cf7498d5..daeb2398 100644 --- a/src/test/java/camp/woowak/lab/vendor/service/SignUpVendorServiceTest.java +++ b/src/test/java/camp/woowak/lab/vendor/service/SignUpVendorServiceTest.java @@ -17,7 +17,6 @@ import camp.woowak.lab.payaccount.repository.PayAccountRepository; import camp.woowak.lab.vendor.domain.Vendor; import camp.woowak.lab.vendor.exception.DuplicateEmailException; -import camp.woowak.lab.vendor.exception.InvalidCreationException; import camp.woowak.lab.vendor.repository.VendorRepository; import camp.woowak.lab.vendor.service.command.SignUpVendorCommand; import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; @@ -36,7 +35,7 @@ class SignUpVendorServiceTest implements VendorFixture { @Test @DisplayName("[성공] Vendor가 저장된다.") - void success() throws InvalidCreationException, DuplicateEmailException { + void success() throws DuplicateEmailException { // given given(passwordEncoder.encode(Mockito.anyString())).willReturn("password"); PayAccount payAccount = createPayAccount(); @@ -56,7 +55,7 @@ void success() throws InvalidCreationException, DuplicateEmailException { @Test @DisplayName("[예외] 가입된 이메일인 경우 예외 발생") - void failWithDuplicateEmail() throws InvalidCreationException, DuplicateEmailException { + void failWithDuplicateEmail() throws DuplicateEmailException { // given given(passwordEncoder.encode(Mockito.anyString())).willReturn("password"); given(payAccountRepository.save(Mockito.any(PayAccount.class))).willReturn(createPayAccount()); From ae0385d5755edf984bedebb27ff4ad23e881d53b Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 15:16:04 +0900 Subject: [PATCH 142/146] =?UTF-8?q?[style]=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= 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 | 2 +- .../camp/woowak/lab/customer/service/SignUpCustomerService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 be53fb4f..c18a476a 100644 --- a/src/main/java/camp/woowak/lab/customer/domain/Customer.java +++ b/src/main/java/camp/woowak/lab/customer/domain/Customer.java @@ -33,7 +33,7 @@ public Customer() { } public Customer(String name, String email, String password, String phone, PayAccount payAccount, - PasswordEncoder passwordEncoder) throws + PasswordEncoder passwordEncoder) throws InvalidCreationException { CustomerValidator.validateCreation(name, email, password, phone, payAccount); this.name = name; diff --git a/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java b/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java index 64b69f50..c8b1cbdb 100644 --- a/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java +++ b/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java @@ -20,7 +20,7 @@ public class SignUpCustomerService { private final PasswordEncoder passwordEncoder; public SignUpCustomerService(CustomerRepository customerRepository, PayAccountRepository payAccountRepository, - PasswordEncoder passwordEncoder) { + PasswordEncoder passwordEncoder) { this.customerRepository = customerRepository; this.payAccountRepository = payAccountRepository; this.passwordEncoder = passwordEncoder; From 7a44fac3c69ffbe4a92acf27c55e9dca4d5b95aa Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 16:21:11 +0900 Subject: [PATCH 143/146] =?UTF-8?q?[feat]=20SignUpCustomerRequest=20annota?= =?UTF-8?q?tion=20param=20=EC=88=98=EC=A0=95=20-=20Validation=20=EC=8B=A4?= =?UTF-8?q?=ED=8C=A8=20=EC=8B=9C=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EB=AA=85?= =?UTF-8?q?=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/dto/request/customer/SignUpCustomerRequest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/camp/woowak/lab/web/dto/request/customer/SignUpCustomerRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/customer/SignUpCustomerRequest.java index 06d257d5..48cc5397 100644 --- a/src/main/java/camp/woowak/lab/web/dto/request/customer/SignUpCustomerRequest.java +++ b/src/main/java/camp/woowak/lab/web/dto/request/customer/SignUpCustomerRequest.java @@ -7,14 +7,14 @@ import jakarta.validation.constraints.NotBlank; public record SignUpCustomerRequest( - @Length(min = 1, max = 50) + @Length(min = 1, max = 50, message = "이름은 1자 이상 50자 이하여야 합니다.") String name, @NotBlank - @Email + @Email(message = "이메일 형식이 올바르지 않습니다.") String email, - @Length(min = 8, max = 20) + @Length(min = 8, max = 20, message = "비밀번호는 8자 이상 20자 이하여야 합니다.") String password, - @Phone + @Phone(message = "전화번호 형식이 올바르지 않습니다.") String phone ) { } From b28cc5dfb00bd811bd43281c3ee9560d9d0edcf8 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 16:22:14 +0900 Subject: [PATCH 144/146] =?UTF-8?q?[refactor]=20Validation=20=EC=83=81?= =?UTF-8?q?=EC=88=98=20=EA=B0=92=20=EC=B6=94=EC=B6=9C=20-=20Validate=20?= =?UTF-8?q?=EC=8B=9C=20=EC=97=90=EC=84=9C=20=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=EA=B0=92=EC=9D=84=20Validator=20=EC=9D=98=20field=20=EB=A1=9C?= =?UTF-8?q?=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/customer/domain/CustomerValidator.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java b/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java index 4db3c2d0..118692fb 100644 --- a/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java +++ b/src/main/java/camp/woowak/lab/customer/domain/CustomerValidator.java @@ -5,6 +5,11 @@ import camp.woowak.lab.payaccount.domain.PayAccount; public class CustomerValidator { + private static final int MAX_NAME_LENGTH = 50; + private static final int MAX_EMAIL_LENGTH = 100; + private static final int MIN_PASSWORD_LENGTH = 8; + private static final int MAX_PASSWORD_LENGTH = 30; + private static final int MAX_PHONE_LENGTH = 30; private CustomerValidator() { } @@ -22,7 +27,7 @@ public static void validateName(String name) throws InvalidCreationException { if (name == null || name.isBlank()) { throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, "Customer name cannot be blank"); } - if (name.length() > 50) { + if (name.length() > MAX_NAME_LENGTH) { throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, "Customer name cannot be longer than 50 characters"); } @@ -32,7 +37,7 @@ public static void validateEmail(String email) throws InvalidCreationException { if (email == null || email.isBlank()) { throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, "Customer email cannot be blank"); } - if (email.trim().length() > 100) { + if (email.trim().length() > MAX_EMAIL_LENGTH) { throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, "Customer email cannot be longer than 100 characters"); } @@ -42,7 +47,11 @@ public static void validatePassword(String password) throws InvalidCreationExcep if (password == null || password.isBlank()) { throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, "Customer password cannot be blank"); } - if (password.trim().length() > 30) { + if (password.trim().length() < MIN_PASSWORD_LENGTH) { + throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, + "Customer password cannot be shorter than 8 characters"); + } + if (password.trim().length() > MAX_PASSWORD_LENGTH) { throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, "Customer password cannot be longer than 30 characters"); } @@ -52,7 +61,7 @@ public static void validatePhone(String phone) throws InvalidCreationException { if (phone == null || phone.isBlank()) { throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, "Customer phone cannot be blank"); } - if (phone.trim().length() > 30) { + if (phone.trim().length() > MAX_PHONE_LENGTH) { throw new InvalidCreationException(CustomerErrorCode.INVALID_CREATION, "Customer phone cannot be longer than 30 characters"); } From 7a1e3fbef03d60da9e2bf8a62138fce9e39649b4 Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 16:31:49 +0900 Subject: [PATCH 145/146] =?UTF-8?q?[feat]=20SignUpCustomerRequest=20annota?= =?UTF-8?q?tion=20param=20=EC=88=98=EC=A0=95=20-=20Validation=20=EC=8B=A4?= =?UTF-8?q?=ED=8C=A8=20=EC=8B=9C=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EB=AA=85?= =?UTF-8?q?=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lab/web/dto/request/customer/SignUpCustomerRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/camp/woowak/lab/web/dto/request/customer/SignUpCustomerRequest.java b/src/main/java/camp/woowak/lab/web/dto/request/customer/SignUpCustomerRequest.java index 48cc5397..80dc9cbe 100644 --- a/src/main/java/camp/woowak/lab/web/dto/request/customer/SignUpCustomerRequest.java +++ b/src/main/java/camp/woowak/lab/web/dto/request/customer/SignUpCustomerRequest.java @@ -9,7 +9,7 @@ public record SignUpCustomerRequest( @Length(min = 1, max = 50, message = "이름은 1자 이상 50자 이하여야 합니다.") String name, - @NotBlank + @NotBlank(message = "이메일은 필수 입력값입니다.") @Email(message = "이메일 형식이 올바르지 않습니다.") String email, @Length(min = 8, max = 20, message = "비밀번호는 8자 이상 20자 이하여야 합니다.") From b68368ac761255ca5369e126f8b6b2329a3a186b Mon Sep 17 00:00:00 2001 From: kimhyun5u <22kimhyun5u@gmail.com> Date: Tue, 13 Aug 2024 16:33:38 +0900 Subject: [PATCH 146/146] =?UTF-8?q?[chore]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20throws=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/woowak/lab/customer/service/SignUpCustomerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java b/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java index c8b1cbdb..3aa0c421 100644 --- a/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java +++ b/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java @@ -32,7 +32,7 @@ public SignUpCustomerService(CustomerRepository customerRepository, PayAccountRe * @throws DuplicateEmailException 이메일이 중복되는 경우 */ @Transactional - public Long signUp(SignUpCustomerCommand cmd) throws InvalidCreationException, DuplicateEmailException { + public Long signUp(SignUpCustomerCommand cmd) { PayAccount payAccount = new PayAccount(); payAccountRepository.save(payAccount);