Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/main/java/com/cleanengine/coin/user/domain/OAuth.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.cleanengine.coin.user.domain;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
Expand All @@ -13,7 +12,6 @@
@Entity
@Table(name = "oauth")
@NoArgsConstructor
@AllArgsConstructor
public class OAuth {

@Id
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/com/cleanengine/coin/user/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class User {

@Id
Expand All @@ -26,4 +25,13 @@ public class User {
@Column(name = "created_at", nullable = false, updatable = false)
private LocalDateTime createdAt;

private User(Integer id, LocalDateTime createdAt) {
this.id = id;
this.createdAt = createdAt;
}

public static User of(Integer id, LocalDateTime createdAt) {
return new User(id, createdAt);
}

}
34 changes: 30 additions & 4 deletions src/main/java/com/cleanengine/coin/user/domain/Wallet.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package com.cleanengine.coin.user.domain;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.*;

@Setter
@Getter
Expand Down Expand Up @@ -34,6 +31,35 @@ public class Wallet {
@Column(name = "roi")
private Double roi; // Return on Investment (수익률)

@Builder
private Wallet(String ticker, Integer accountId, Double size, Double buyPrice, Double roi) {
this.ticker = ticker;
this.accountId = accountId;
this.size = size;
this.buyPrice = buyPrice;
this.roi = roi;
}

public static Wallet of(String ticker, Integer accountId) {
return Wallet.builder()
.ticker(ticker)
.accountId(accountId)
.size(0.0)
.buyPrice(0.0)
.roi(0.0)
.build();
}

public static Wallet of(String ticker, Integer accountId, Double size) {
return Wallet.builder()
.ticker(ticker)
.accountId(accountId)
.size(size)
.buyPrice(0.0)
.roi(0.0)
.build();
}

public static Wallet generateEmptyWallet(String ticker, Integer accountId){
Wallet wallet = new Wallet();
wallet.setTicker(ticker);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.cleanengine.coin.user.info.application;

import com.cleanengine.coin.user.domain.Account;
import com.cleanengine.coin.user.domain.Wallet;
import com.cleanengine.coin.user.info.infra.AccountRepository;
import com.cleanengine.coin.user.info.infra.WalletRepository;
import org.springframework.stereotype.Service;

Expand All @@ -11,14 +11,14 @@
public class WalletService {

private final WalletRepository walletRepository;
private final AccountService accountService;
private final AccountRepository accountRepository;

public WalletService(WalletRepository walletRepository, AccountService accountService) {
public WalletService(WalletRepository walletRepository, AccountRepository accountRepository) {
this.walletRepository = walletRepository;
this.accountService = accountService;
this.accountRepository = accountRepository;
}

public List<Wallet> retrieveWalletsByAccountId(Integer accountId) {
public List<Wallet> findByAccountId(Integer accountId) {
return walletRepository.findByAccountId(accountId);
}

Expand All @@ -27,19 +27,9 @@ public Wallet save(Wallet wallet) {
}

public Wallet findWalletByUserIdAndTicker(Integer userId, String ticker) {
Account account = accountService.findAccountByUserId(userId).orElseThrow();
return walletRepository.findByAccountIdAndTicker(account.getId(), ticker)
.orElseGet(() -> createNewWallet(account.getId(), ticker));
}

public Wallet createNewWallet(Integer accountId, String ticker) {
Wallet newWallet = new Wallet();
newWallet.setAccountId(accountId);
newWallet.setTicker(ticker);
newWallet.setSize(0.0);
newWallet.setBuyPrice(0.0);
newWallet.setRoi(0.0);
return newWallet;
int accountId = accountRepository.findByUserId(userId).orElseThrow().getId();
return walletRepository.findByAccountIdAndTicker(accountId, ticker)
.orElseGet(() -> Wallet.of(ticker, accountId));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public ApiResponse<UserInfoDTO> retrieveUserInfo() {
return ApiResponse.fail(ErrorResponse.of(ErrorStatus.UNAUTHORIZED_RESOURCE));
}
Account account = accountService.retrieveAccountByUserId(userId);
List<Wallet> wallets = walletService.retrieveWalletsByAccountId(account.getId());
List<Wallet> wallets = walletService.findByAccountId(account.getId());
userInfoDTO.setWallets(wallets);

return ApiResponse.success(userInfoDTO, HttpStatus.OK);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public CustomOAuth2UserService(UserRepository userRepository, OAuthRepository oA

@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = super.loadUser(userRequest);
OAuth2User oAuth2User = doSuperLoadMethod(userRequest);

OAuth2Response oAuth2Response = new KakaoResponse(oAuth2User.getAttributes());
/* 추후 OAuth 플랫폼 추가 시 이런 식으로 Response 분기처리
Expand Down Expand Up @@ -64,18 +64,24 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic
oAuthRepository.save(newOAuth);
accountService.createNewAccount(newUser.getId(), CommonValues.INITIAL_USER_CASH);

return new CustomOAuth2User(UserOAuthDetails.of(newUser, newOAuth));
UserOAuthDetails newUserOAuthDetails = UserOAuthDetails.of(newUser, newOAuth);
return CustomOAuth2User.of(newUserOAuthDetails);
}
else {
OAuth existOAuth = oAuthRepository.findByProviderAndProviderUserId(provider, providerUserId);

existOAuth.setEmail(email);
existOAuth.setNickname(oAuth2Response.getName());
// TODO : KAKAO Token 관련 정보 추가
existOAuth.setNickname(name);
oAuthRepository.save(existOAuth);

return new CustomOAuth2User(existData);
existData.update(existOAuth);

return CustomOAuth2User.of(existData);
}
}

protected OAuth2User doSuperLoadMethod(OAuth2UserRequest userRequest) {
return super.loadUser(userRequest);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ public class CustomSuccessHandler extends SimpleUrlAuthenticationSuccessHandler

private final JWTUtil jwtUtil;

@Value("${spring.security.cookie.secure}")
private boolean isCookieSecure;
private final boolean isCookieSecure;

@Value("${frontend.url}")
private String frontendUrl;
private final String frontendUrl;

public CustomSuccessHandler(JWTUtil jwtUtil) {
public CustomSuccessHandler(JWTUtil jwtUtil,
@Value("${spring.security.cookie.secure}") boolean isCookieSecure,
@Value("${frontend.url}") String frontendUrl) {
this.jwtUtil = jwtUtil;
this.isCookieSecure = isCookieSecure;
this.frontendUrl = frontendUrl;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServlet

private static Authentication getAuthentication(Integer userId) {
UserOAuthDetails userOAuthDetails = UserOAuthDetails.of(userId);
CustomOAuth2User customOAuth2User = new CustomOAuth2User(userOAuthDetails);
CustomOAuth2User customOAuth2User = CustomOAuth2User.of(userOAuthDetails);

// 스프링 시큐리티 인증 토큰 생성
return new UsernamePasswordAuthenticationToken(customOAuth2User,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ public class CustomOAuth2User implements OAuth2User {

private final UserOAuthDetails userOAuthDetails;

public CustomOAuth2User(UserOAuthDetails userOAuthDetails) {
private CustomOAuth2User(UserOAuthDetails userOAuthDetails) {
this.userOAuthDetails = userOAuthDetails;
}

public static CustomOAuth2User of(UserOAuthDetails userOAuthDetails) {
return new CustomOAuth2User(userOAuthDetails);
}

@Override
public Map<String, Object> getAttributes() {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,9 @@ public static UserOAuthDetails of(int userId) {
.build();
}

public void update(OAuth oauth) {
this.email = oauth.getEmail();
this.name = oauth.getNickname();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public SecurityContext createSecurityContext(WithCustomMockUser annotation) {
SecurityContext context = SecurityContextHolder.createEmptyContext();

UserOAuthDetails userOAuthDetails = UserOAuthDetails.of(annotation.id());
CustomOAuth2User customOAuth2User = new CustomOAuth2User(userOAuthDetails);
CustomOAuth2User customOAuth2User = CustomOAuth2User.of(userOAuthDetails);

Authentication authentication = new UsernamePasswordAuthenticationToken(customOAuth2User,
null, customOAuth2User.getAuthorities());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

import static org.assertj.core.api.Assertions.assertThat;

@ActiveProfiles({"dev", "it", "h2-mem"})
@ActiveProfiles({"dev", "h2-mem"})
@DisplayName("계좌 서비스 - h2 통합테스트")
@SpringBootTest
class AccountServiceTest {
Expand All @@ -22,7 +22,7 @@ class AccountServiceTest {
@Test
void createNewAccount() {
// given
int userId = 3;
int userId = Integer.MAX_VALUE;
double cash = CommonValues.INITIAL_USER_CASH;

// when
Expand All @@ -41,7 +41,7 @@ void createNewAccount() {
@Test
void retrieveAccountByInvalidUserId() {
// given, when
Account account = accountService.retrieveAccountByUserId(1000);
Account account = accountService.retrieveAccountByUserId(Integer.MAX_VALUE - 1);

// then
assertThat(account).isNull();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.cleanengine.coin.user.info.application;

import com.cleanengine.coin.user.domain.Account;
import com.cleanengine.coin.user.domain.Wallet;
import com.cleanengine.coin.user.info.infra.AccountRepository;
import com.cleanengine.coin.user.info.infra.WalletRepository;
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 org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

@DisplayName("지갑 서비스-Repository 통합테스트")
@ActiveProfiles({"dev", "h2-mem"})
@Transactional
@SpringBootTest
class WalletServiceTest {

@Autowired
private WalletService walletService;

@Autowired
private WalletRepository walletRepository;

@Autowired
private AccountRepository accountRepository;

private Account testAccount;

@BeforeEach
void setUp() {
// given
testAccount = Account.of(3, 0.0);
accountRepository.save(testAccount);

Wallet testWallet = Wallet.of("BTC", testAccount.getId(), 1000.0);
walletRepository.save(testWallet);
}

@DisplayName("계좌 ID로 조회 시 지갑이 정상 반환된다.")
@Test
void findByAccountId_thenReturnWallet() {
// when
List<Wallet> wallets = walletService.findByAccountId(testAccount.getId());

// then
assertThat(wallets).isNotEmpty();
assertThat(wallets.getFirst().getTicker()).isEqualTo("BTC");
}

@DisplayName("지갑이 성공적으로 저장된다.")
@Test
void save_thenCreateNewWallet() {
// when
Wallet newWallet = Wallet.of("TRUMP", testAccount.getId(), 5000.0);
Wallet savedWallet = walletService.save(newWallet);

// then
assertThat(savedWallet.getId()).isNotNull();
assertThat(savedWallet.getTicker()).isEqualTo("TRUMP");
assertThat(savedWallet.getSize()).isEqualTo(5000.0);
}

@DisplayName("유저 ID, 티커로 존재하는 지갑 조회 시 정상적으로 반환된다.")
@Test
void findWalletByUserIdAndTicker_ExistingWallet_thenReturnWallet() {
// when
Wallet wallet = walletService.findWalletByUserIdAndTicker(testAccount.getUserId(), "BTC");

// then
assertThat(wallet).isNotNull();
assertThat(wallet.getId()).isNotNull();
assertThat(wallet.getTicker()).isEqualTo("BTC");
assertThat(wallet.getSize()).isEqualTo(1000.0);
}

@DisplayName("유저 ID, 티커로 존재하지 않는 지갑 조회 시 빈 지갑이 새로 반환된다.")
@Test
void findWalletByUserIdAndTicker_NonExistingWallet_thenReturnEmptyWallet() {
// when
Wallet wallet = walletService.findWalletByUserIdAndTicker(testAccount.getUserId(), "TRUMP");

// then
assertThat(wallet).isNotNull();
assertThat(wallet.getTicker()).isEqualTo("TRUMP");
assertThat(wallet.getSize()).isEqualTo(0.0);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public void testRetrieveUserInfoSuccess() throws Exception {

verify(userService, times(1)).retrieveUserInfoByUserId(userId);
verify(accountService, times(1)).retrieveAccountByUserId(userId);
verify(walletService, times(1)).retrieveWalletsByAccountId(account.getId());
verify(walletService, times(1)).findByAccountId(account.getId());
}

@Test
Expand Down
Loading
Loading