From db67577ff732b98ade1496df2ccc161082d1abfe Mon Sep 17 00:00:00 2001 From: yeonsu Date: Fri, 26 Jan 2024 21:20:23 +0900 Subject: [PATCH 1/2] generate unique account --- build.gradle | 2 + .../common/dto/request/AccountRequestDTO.java | 13 ++++ .../dto/response/AccountResponseDTO.java | 16 +++++ .../bank/controller/AccountController.java | 28 ++++++++ .../exception/GlobalExceptionHandler.java | 1 - .../bank/repository/AccountRepository.java | 2 + .../com/eum/bank/service/AccountService.java | 71 +++++++++++++++++++ 7 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/eum/bank/common/dto/request/AccountRequestDTO.java create mode 100644 src/main/java/com/eum/bank/common/dto/response/AccountResponseDTO.java create mode 100644 src/main/java/com/eum/bank/controller/AccountController.java create mode 100644 src/main/java/com/eum/bank/service/AccountService.java diff --git a/build.gradle b/build.gradle index 70b6c2a..61359f0 100644 --- a/build.gradle +++ b/build.gradle @@ -24,12 +24,14 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'io.springfox:springfox-boot-starter:3.0.0' implementation 'io.springfox:springfox-swagger-ui:3.0.0' + } tasks.named('test') { diff --git a/src/main/java/com/eum/bank/common/dto/request/AccountRequestDTO.java b/src/main/java/com/eum/bank/common/dto/request/AccountRequestDTO.java new file mode 100644 index 0000000..2654aef --- /dev/null +++ b/src/main/java/com/eum/bank/common/dto/request/AccountRequestDTO.java @@ -0,0 +1,13 @@ +package com.eum.bank.common.dto.request; + +import jakarta.validation.constraints.NotEmpty; +import lombok.Getter; + +public class AccountRequestDTO { + // 계좌 생성 요청 + @Getter + public static class CreateAccount { + @NotEmpty(message = "비밀번호를 입력해주세요.") + private Long password; + } +} diff --git a/src/main/java/com/eum/bank/common/dto/response/AccountResponseDTO.java b/src/main/java/com/eum/bank/common/dto/response/AccountResponseDTO.java new file mode 100644 index 0000000..6bd1b95 --- /dev/null +++ b/src/main/java/com/eum/bank/common/dto/response/AccountResponseDTO.java @@ -0,0 +1,16 @@ +package com.eum.bank.common.dto.response; + +import jakarta.validation.constraints.NotEmpty; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +public class AccountResponseDTO { + // 계좌 생성 응답 + @Builder + @Getter + public static class Create { + @NotEmpty(message = "계좌 번호가 생성되어야 합니다.") + private String accountNumber; + } +} diff --git a/src/main/java/com/eum/bank/controller/AccountController.java b/src/main/java/com/eum/bank/controller/AccountController.java new file mode 100644 index 0000000..70dea47 --- /dev/null +++ b/src/main/java/com/eum/bank/controller/AccountController.java @@ -0,0 +1,28 @@ +package com.eum.bank.controller; + +import com.eum.bank.common.APIResponse; +import com.eum.bank.common.dto.request.AccountRequestDTO; +import com.eum.bank.common.dto.response.AccountResponseDTO; +import com.eum.bank.common.enums.SuccessCode; +import com.eum.bank.service.AccountService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/account") +@Slf4j +public class AccountController { + private final AccountService accountService; + @PostMapping("/create") + public ResponseEntity create(@RequestBody AccountRequestDTO.CreateAccount createAccount) { + + Long password = createAccount.getPassword(); + APIResponse response = accountService.createAccount(password); + + return ResponseEntity.ok(response); + } +} diff --git a/src/main/java/com/eum/bank/exception/GlobalExceptionHandler.java b/src/main/java/com/eum/bank/exception/GlobalExceptionHandler.java index dd0f637..cb201eb 100644 --- a/src/main/java/com/eum/bank/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/eum/bank/exception/GlobalExceptionHandler.java @@ -28,7 +28,6 @@ public class GlobalExceptionHandler { private final HttpStatus HTTP_STATUS_OK = HttpStatus.OK; - /** * [Exception] API 호출 시 '객체' 혹은 '파라미터' 데이터 값이 유효하지 않은 경우 * diff --git a/src/main/java/com/eum/bank/repository/AccountRepository.java b/src/main/java/com/eum/bank/repository/AccountRepository.java index a93c973..4aae0e5 100644 --- a/src/main/java/com/eum/bank/repository/AccountRepository.java +++ b/src/main/java/com/eum/bank/repository/AccountRepository.java @@ -4,4 +4,6 @@ import org.springframework.data.jpa.repository.JpaRepository; public interface AccountRepository extends JpaRepository { + Account save(Account account); + Boolean findByAccountNumber(String accountNumber); } \ No newline at end of file diff --git a/src/main/java/com/eum/bank/service/AccountService.java b/src/main/java/com/eum/bank/service/AccountService.java new file mode 100644 index 0000000..865d3aa --- /dev/null +++ b/src/main/java/com/eum/bank/service/AccountService.java @@ -0,0 +1,71 @@ +package com.eum.bank.service; + +import com.eum.bank.common.APIResponse; +import com.eum.bank.common.dto.response.AccountResponseDTO; +import com.eum.bank.common.enums.SuccessCode; +import com.eum.bank.domain.account.entity.Account; +import com.eum.bank.repository.AccountRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Random; + +@Service +@RequiredArgsConstructor +public class AccountService { + + private final AccountRepository accountRepository; + + public APIResponse createAccount(Long password) { + + String accountNumber; + do { + accountNumber = generateAccountNumber(); + }while ( + validateAccountNumber(accountNumber) + ); + + Account account = Account.builder() + .accountNumber(accountNumber) + .password(password.toString()) + .totalBudget(0L) + .availableBudget(0L) + .build(); + + accountRepository.save(account); + + return APIResponse.of(SuccessCode.SELECT_SUCCESS, AccountResponseDTO.Create.builder() + .accountNumber(account.getAccountNumber()) + .build()); + } + + public String generateAccountNumber() { + Random random = new Random(); + StringBuilder uniqueNumber = new StringBuilder(); + + for (int i = 0; i < 12; i++) { + int digit = random.nextInt(10); + uniqueNumber.append(digit); + } + + if( validateAccountNumber(uniqueNumber.toString()) ) + generateAccountNumber(); + + return uniqueNumber.toString(); + } + public Boolean validateAccountNumber(String accountNumber) { + if (accountNumber.length() != 12) { + return false; + } + + try { + Long.parseLong(accountNumber); + accountRepository.findByAccountNumber(accountNumber); + } catch (NumberFormatException e) { + return false; + } + return true; + } + + +} From 34319438447f84330c7aaed84180936265e8aa91 Mon Sep 17 00:00:00 2001 From: jykim-rust Date: Sun, 28 Jan 2024 17:27:51 +0900 Subject: [PATCH 2/2] =?UTF-8?q?:adhesive=5Fbandage:=20issue#11=20=EB=B9=84?= =?UTF-8?q?=EB=B0=80=EB=B2=88=ED=98=B8=EB=A5=BC=20passwordEncoder=EB=A1=9C?= =?UTF-8?q?=20=EC=9D=B8=EC=BD=94=EB=94=A9=ED=95=B4=EC=84=9C=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 ++ .../com/eum/bank/config/PasswordEncoderConfig.java | 14 ++++++++++++++ .../java/com/eum/bank/service/AccountService.java | 6 +++++- 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/eum/bank/config/PasswordEncoderConfig.java diff --git a/build.gradle b/build.gradle index 61359f0..179eccc 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,8 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'io.springfox:springfox-boot-starter:3.0.0' implementation 'io.springfox:springfox-swagger-ui:3.0.0' + implementation 'org.springframework.security:spring-security-crypto:5.7.1' + } diff --git a/src/main/java/com/eum/bank/config/PasswordEncoderConfig.java b/src/main/java/com/eum/bank/config/PasswordEncoderConfig.java new file mode 100644 index 0000000..26171d0 --- /dev/null +++ b/src/main/java/com/eum/bank/config/PasswordEncoderConfig.java @@ -0,0 +1,14 @@ +package com.eum.bank.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.factory.PasswordEncoderFactories; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class PasswordEncoderConfig { + @Bean + public PasswordEncoder passwordEncoder() { + return PasswordEncoderFactories.createDelegatingPasswordEncoder(); + } +} diff --git a/src/main/java/com/eum/bank/service/AccountService.java b/src/main/java/com/eum/bank/service/AccountService.java index 865d3aa..ced31a7 100644 --- a/src/main/java/com/eum/bank/service/AccountService.java +++ b/src/main/java/com/eum/bank/service/AccountService.java @@ -8,6 +8,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.security.crypto.password.PasswordEncoder; import java.util.Random; @Service @@ -15,6 +16,8 @@ public class AccountService { private final AccountRepository accountRepository; + private final PasswordEncoder passwordEncoder; + public APIResponse createAccount(Long password) { @@ -27,7 +30,7 @@ public APIResponse createAccount(Long password) { Account account = Account.builder() .accountNumber(accountNumber) - .password(password.toString()) + .password(passwordEncoder.encode(password.toString())) .totalBudget(0L) .availableBudget(0L) .build(); @@ -68,4 +71,5 @@ public Boolean validateAccountNumber(String accountNumber) { } + }