diff --git a/application/wypl-core/build.gradle b/application/wypl-core/build.gradle index 1369f9c..b521914 100644 --- a/application/wypl-core/build.gradle +++ b/application/wypl-core/build.gradle @@ -18,6 +18,7 @@ dependencies { implementation project(':domain:jpa-member-domain') implementation project(':domain:auth-domain') implementation project(':domain:redis-embedded-domain') + implementation project(':domain:redis-token-domain') implementation project(':common') implementation 'org.springframework.boot:spring-boot-starter-actuator' diff --git a/application/wypl-core/src/main/java/com/wypl/wyplcore/auth/controller/AuthController.java b/application/wypl-core/src/main/java/com/wypl/wyplcore/auth/controller/AuthController.java index dcd6e8e..555bf30 100644 --- a/application/wypl-core/src/main/java/com/wypl/wyplcore/auth/controller/AuthController.java +++ b/application/wypl-core/src/main/java/com/wypl/wyplcore/auth/controller/AuthController.java @@ -12,7 +12,7 @@ import com.wypl.googleoauthclient.annotation.Authenticated; import com.wypl.googleoauthclient.domain.AuthMember; import com.wypl.wyplcore.auth.data.response.AuthTokensResponse; -import com.wypl.wyplcore.auth.service.AuthServiceImpl; +import com.wypl.wyplcore.facade.AuthMemberFacade; import lombok.RequiredArgsConstructor; @@ -20,14 +20,14 @@ @RequestMapping("/auth") @RestController public class AuthController { - private final AuthServiceImpl authService; + private final AuthMemberFacade authMemberFacade; @PostMapping("/v1/sign-in/{provider}") public WyplResponseEntity signIn( @PathVariable("provider") String provider, @RequestParam("code") String code ) { - AuthTokensResponse response = authService.generateToken(provider, code); + AuthTokensResponse response = authMemberFacade.generateToken(provider, code); return WyplResponseEntity.ok(response, "로그인에 성공하였습니다."); } @@ -36,7 +36,7 @@ public WyplResponseEntity reissue( @RequestParam("access_token") String accessToken, @RequestParam("refresh_token") String refreshToken ) { - AuthTokensResponse response = authService.reissueToken(accessToken, refreshToken); + AuthTokensResponse response = authMemberFacade.reissueToken(accessToken, refreshToken); return WyplResponseEntity.created(response, "토큰 재발급에 성공하였습니다."); } @@ -44,7 +44,7 @@ public WyplResponseEntity reissue( public WyplResponseEntity logout( @Authenticated AuthMember authMember ) { - authService.logout(authMember); + authMemberFacade.logout(authMember); return WyplResponseEntity.ok("로그아웃에 성공하였습니다."); } } diff --git a/application/wypl-core/src/main/java/com/wypl/wyplcore/auth/service/AuthMemberServiceImpl.java b/application/wypl-core/src/main/java/com/wypl/wyplcore/auth/service/AuthMemberServiceImpl.java index c76d9c7..793b603 100644 --- a/application/wypl-core/src/main/java/com/wypl/wyplcore/auth/service/AuthMemberServiceImpl.java +++ b/application/wypl-core/src/main/java/com/wypl/wyplcore/auth/service/AuthMemberServiceImpl.java @@ -2,7 +2,6 @@ import org.springframework.stereotype.Component; -import com.wypl.authdomain.auth.service.AuthDomainServiceImpl; import com.wypl.googleoauthclient.GoogleOAuthClient; import com.wypl.googleoauthclient.data.response.GoogleTokenValidationResponse; import com.wypl.googleoauthclient.domain.AuthMember; @@ -12,6 +11,7 @@ import com.wypl.jpamemberdomain.member.domain.SocialMember; import com.wypl.jpamemberdomain.member.repository.SocialMemberRepository; import com.wypl.jpamemberdomain.member.utils.SocialMemberRepositoryUtils; +import com.wypl.wyplcore.token.service.TokenService; import lombok.RequiredArgsConstructor; @@ -20,7 +20,7 @@ public class AuthMemberServiceImpl implements AuthMemberService { private final GoogleOAuthClient googleOAuthClient; private final SocialMemberRepository socialMemberRepository; - private final AuthDomainServiceImpl authDomainService; + private final TokenService tokenService; @Override public AuthMember getValidatedMemberId(String accessToken) { @@ -37,7 +37,7 @@ private GoogleTokenValidationResponse getGoogleTokenValidationResponse(String ac try { return googleOAuthClient.validateToken(accessToken); } catch (GoogleOAuthException e) { - if (authDomainService.checkExistsToken(accessToken)) { + if (tokenService.checkExistsToken(accessToken)) { throw new GoogleOAuthException(GoogleOAuthErrorCode.REFRESH_TOKEN); } throw new GoogleOAuthException(GoogleOAuthErrorCode.INVALID_TOKEN); diff --git a/application/wypl-core/src/main/java/com/wypl/wyplcore/auth/service/AuthServiceImpl.java b/application/wypl-core/src/main/java/com/wypl/wyplcore/auth/service/AuthServiceImpl.java index f208ebf..2000128 100644 --- a/application/wypl-core/src/main/java/com/wypl/wyplcore/auth/service/AuthServiceImpl.java +++ b/application/wypl-core/src/main/java/com/wypl/wyplcore/auth/service/AuthServiceImpl.java @@ -1,111 +1,14 @@ -package com.wypl.wyplcore.auth.service; - -import java.time.LocalDate; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.wypl.authdomain.auth.service.AuthDomainServiceImpl; -import com.wypl.googleoauthclient.GoogleOAuthClient; -import com.wypl.googleoauthclient.data.response.GoogleTokenResponse; -import com.wypl.googleoauthclient.data.response.GoogleUserInfoResponse; -import com.wypl.googleoauthclient.domain.AuthMember; -import com.wypl.googleoauthclient.exception.GoogleOAuthErrorCode; -import com.wypl.googleoauthclient.exception.GoogleOAuthException; -import com.wypl.jpamemberdomain.member.OauthProvider; -import com.wypl.jpamemberdomain.member.data.MemberSaveDto; -import com.wypl.jpamemberdomain.member.data.SocialMemberSaveDto; -import com.wypl.jpamemberdomain.member.repository.SocialMemberRepository; -import com.wypl.jpamemberdomain.member.utils.SocialMemberRepositoryUtils; -import com.wypl.wyplcore.auth.data.response.AuthTokensResponse; -import com.wypl.wyplcore.member.service.MemberServiceImpl; - -import lombok.RequiredArgsConstructor; - -@Transactional(readOnly = true) -@RequiredArgsConstructor -@Service -public class AuthServiceImpl { - private final GoogleOAuthClient googleOAuthClient; - private final SocialMemberRepository socialMemberRepository; - private final AuthDomainServiceImpl authDomainService; - private final MemberServiceImpl memberService; - - @Transactional - public AuthTokensResponse generateToken(final String provider, final String code) { - GoogleTokenResponse googleTokenResponse = googleOAuthClient.fetchGoogleOAuthToken(code); - - GoogleUserInfoResponse googleUserInfoResponse = googleOAuthClient.fetchUserInfo( - googleTokenResponse.accessToken()); - - long memberId = findMemberIdAfterSaveMember(googleTokenResponse.accessToken(), googleUserInfoResponse); - - authDomainService.saveToken(googleTokenResponse.accessToken(), googleTokenResponse.refreshToken()); - - return AuthTokensResponse.of(memberId, googleTokenResponse); - } - - @Transactional - public AuthTokensResponse reissueToken(final String accessToken, final String refreshToken) { - if (isInvalidRefreshToken(accessToken, refreshToken)) { - throw new GoogleOAuthException(GoogleOAuthErrorCode.NOT_AUTHORIZATION_MEMBER); - } - - GoogleTokenResponse googleTokenResponse = googleOAuthClient.fetchRefreshGoogleOAuthToken(refreshToken); - - authDomainService.deleteToken(accessToken); - authDomainService.saveToken(googleTokenResponse.accessToken(), refreshToken); - - return AuthTokensResponse.of(googleTokenResponse.accessToken(), refreshToken); - } - - @Transactional - public void logout(AuthMember authMember) { - deleteToken(authMember); - } - - @Transactional - public void quitMember(AuthMember authMember) { - // Todo : 회원 탈퇴 로직 논의 - deleteToken(authMember); - memberService.deleteMember(authMember); - } - - private void deleteToken(AuthMember authMember) { - authDomainService.deleteToken(authMember.accessToken()); - } - - private boolean isInvalidRefreshToken(String accessToken, String refreshToken) { - return refreshToken.isEmpty() || !refreshToken.equals(authDomainService.getRefreshToken(accessToken)); - } - - // todo: - private long findMemberIdAfterSaveMember(String accessToken, GoogleUserInfoResponse googleUserInfoResponse) { - if (isNewMember(googleUserInfoResponse)) { - LocalDate birthday = googleOAuthClient.fetchBirthday(accessToken); - - MemberSaveDto memberSaveDto = MemberSaveDto.builder() - .email(googleUserInfoResponse.email()) - .birthday(birthday) - .nickname(googleUserInfoResponse.name()) - .profileImage(googleUserInfoResponse.picture()) - .build(); - - SocialMemberSaveDto socialMemberSaveDto = SocialMemberSaveDto.builder() - .oauthProvider(OauthProvider.GOOGLE) - .oauthId(googleUserInfoResponse.id()) - .build(); - - return authDomainService.saveAuthData(memberSaveDto, socialMemberSaveDto); - } - - return SocialMemberRepositoryUtils.getSocialMember(socialMemberRepository, googleUserInfoResponse.id()).getId(); - } - - // todo: - private boolean isNewMember(GoogleUserInfoResponse googleUserInfoResponse) { - return !socialMemberRepository.existsByOauthProviderAndOauthId(OauthProvider.GOOGLE, - googleUserInfoResponse.id()); - } -} - +// package com.wypl.wyplcore.auth.service; +// +// import org.springframework.stereotype.Service; +// import org.springframework.transaction.annotation.Transactional; +// +// import lombok.RequiredArgsConstructor; +// +// @Transactional(readOnly = true) +// @RequiredArgsConstructor +// @Service +// public class AuthServiceImpl { +// +// } +// diff --git a/application/wypl-core/src/main/java/com/wypl/wyplcore/facade/AuthMemberFacade.java b/application/wypl-core/src/main/java/com/wypl/wyplcore/facade/AuthMemberFacade.java new file mode 100644 index 0000000..92b8152 --- /dev/null +++ b/application/wypl-core/src/main/java/com/wypl/wyplcore/facade/AuthMemberFacade.java @@ -0,0 +1,11 @@ +package com.wypl.wyplcore.facade; + +import com.wypl.googleoauthclient.domain.AuthMember; +import com.wypl.wyplcore.auth.data.response.AuthTokensResponse; + +public interface AuthMemberFacade { + AuthTokensResponse generateToken(final String provider, final String code); + AuthTokensResponse reissueToken(final String accessToken, final String refreshToken); + void logout(final AuthMember authMember); + void quitMember(final AuthMember authMember); +} diff --git a/application/wypl-core/src/main/java/com/wypl/wyplcore/facade/AuthMemberFacadeImpl.java b/application/wypl-core/src/main/java/com/wypl/wyplcore/facade/AuthMemberFacadeImpl.java new file mode 100644 index 0000000..9f3b574 --- /dev/null +++ b/application/wypl-core/src/main/java/com/wypl/wyplcore/facade/AuthMemberFacadeImpl.java @@ -0,0 +1,78 @@ +package com.wypl.wyplcore.facade; + +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import com.wypl.googleoauthclient.GoogleOAuthClient; +import com.wypl.googleoauthclient.data.response.GoogleTokenResponse; +import com.wypl.googleoauthclient.data.response.GoogleUserInfoResponse; +import com.wypl.googleoauthclient.domain.AuthMember; +import com.wypl.googleoauthclient.exception.GoogleOAuthErrorCode; +import com.wypl.googleoauthclient.exception.GoogleOAuthException; +import com.wypl.wyplcore.auth.data.response.AuthTokensResponse; +import com.wypl.wyplcore.member.service.MemberService; +import com.wypl.wyplcore.token.service.TokenService; + +import lombok.RequiredArgsConstructor; + +@Transactional(readOnly = true) +@RequiredArgsConstructor +@Component +public class AuthMemberFacadeImpl implements AuthMemberFacade { + private final GoogleOAuthClient googleOAuthClient; + private final TokenService tokenService; + private final MemberService memberService; + + @Override + @Transactional + public AuthTokensResponse generateToken(final String provider, final String code) { + GoogleTokenResponse googleTokenResponse = googleOAuthClient.fetchGoogleOAuthToken(code); + + GoogleUserInfoResponse googleUserInfoResponse = googleOAuthClient.fetchUserInfo( + googleTokenResponse.accessToken()); + + long memberId = memberService.findMemberIdOrSaveMember(googleTokenResponse.accessToken(), googleUserInfoResponse); + + tokenService.saveToken(googleTokenResponse.accessToken(), googleTokenResponse.refreshToken()); + + return AuthTokensResponse.of(memberId, googleTokenResponse); + } + + @Override + @Transactional + public AuthTokensResponse reissueToken(final String accessToken, final String refreshToken) { + if (isInvalidRefreshToken(accessToken, refreshToken)) { + throw new GoogleOAuthException(GoogleOAuthErrorCode.NOT_AUTHORIZATION_MEMBER); + } + + GoogleTokenResponse googleTokenResponse = googleOAuthClient.fetchRefreshGoogleOAuthToken(refreshToken); + + tokenService.deleteToken(accessToken); + tokenService.saveToken(googleTokenResponse.accessToken(), refreshToken); + + return AuthTokensResponse.of(googleTokenResponse.accessToken(), refreshToken); + } + + @Override + @Transactional + public void logout(final AuthMember authMember) { + deleteToken(authMember); + } + + @Override + @Transactional + public void quitMember(final AuthMember authMember) { + // Todo : 회원 탈퇴 로직 논의 + // Todo : deleteToken은 스프링에서 비동기 처리하고(토큰이 아니라 멤버 탈퇴가 중요한거다), deleteMember는 Member 쪽으로 옮기자 + deleteToken(authMember); + memberService.deleteMember(authMember); + } + + private void deleteToken(AuthMember authMember) { + tokenService.deleteToken(authMember.accessToken()); + } + + private boolean isInvalidRefreshToken(String accessToken, String refreshToken) { + return refreshToken.isEmpty() || !refreshToken.equals(tokenService.getRefreshToken(accessToken)); + } +} diff --git a/application/wypl-core/src/main/java/com/wypl/wyplcore/member/service/MemberService.java b/application/wypl-core/src/main/java/com/wypl/wyplcore/member/service/MemberService.java new file mode 100644 index 0000000..7245340 --- /dev/null +++ b/application/wypl-core/src/main/java/com/wypl/wyplcore/member/service/MemberService.java @@ -0,0 +1,68 @@ +package com.wypl.wyplcore.member.service; + +import java.time.LocalDate; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.wypl.googleoauthclient.GoogleOAuthClient; +import com.wypl.googleoauthclient.data.response.GoogleUserInfoResponse; +import com.wypl.googleoauthclient.domain.AuthMember; +import com.wypl.jpamemberdomain.member.OauthProvider; +import com.wypl.jpamemberdomain.member.data.MemberSaveDto; +import com.wypl.jpamemberdomain.member.data.SocialMemberSaveDto; +import com.wypl.jpamemberdomain.member.domain.Member; +import com.wypl.jpamemberdomain.member.domain.SocialMember; +import com.wypl.jpamemberdomain.member.repository.MemberRepository; +import com.wypl.jpamemberdomain.member.repository.SocialMemberRepository; +import com.wypl.jpamemberdomain.member.utils.SocialMemberRepositoryUtils; + +import lombok.RequiredArgsConstructor; + +@Transactional(readOnly = true) +@RequiredArgsConstructor +@Service +public class MemberService { + private final GoogleOAuthClient googleOAuthClient; + private final MemberRepository memberRepository; + private final SocialMemberRepository socialMemberRepository; + + @Transactional + public void deleteMember(AuthMember authMember) { + memberRepository.deleteById(authMember.id()); + } + + @Transactional + public long findMemberIdOrSaveMember(String accessToken, GoogleUserInfoResponse googleUserInfoResponse) { + if (isNewMember(googleUserInfoResponse)) { + LocalDate birthday = googleOAuthClient.fetchBirthday(accessToken); + + MemberSaveDto memberSaveDto = MemberSaveDto.builder() + .email(googleUserInfoResponse.email()) + .birthday(birthday) + .nickname(googleUserInfoResponse.name()) + .profileImage(googleUserInfoResponse.picture()) + .build(); + + SocialMemberSaveDto socialMemberSaveDto = SocialMemberSaveDto.builder() + .oauthProvider(OauthProvider.GOOGLE) + .oauthId(googleUserInfoResponse.id()) + .build(); + + return saveNewMember(memberSaveDto, socialMemberSaveDto); + } + + return SocialMemberRepositoryUtils.getSocialMember(socialMemberRepository, googleUserInfoResponse.id()).getId(); + } + + private boolean isNewMember(GoogleUserInfoResponse googleUserInfoResponse) { + return !socialMemberRepository.existsByOauthProviderAndOauthId(OauthProvider.GOOGLE, + googleUserInfoResponse.id()); + } + + private long saveNewMember(MemberSaveDto memberSaveDto, SocialMemberSaveDto socialMemberSaveDto) { + Member newMember = memberRepository.save(Member.of(memberSaveDto)); + SocialMember socialMember = socialMemberRepository.save(SocialMember.of(newMember, socialMemberSaveDto)); + return socialMember.getId(); + } +} diff --git a/application/wypl-core/src/main/java/com/wypl/wyplcore/member/service/MemberServiceImpl.java b/application/wypl-core/src/main/java/com/wypl/wyplcore/member/service/MemberServiceImpl.java deleted file mode 100644 index 992d66b..0000000 --- a/application/wypl-core/src/main/java/com/wypl/wyplcore/member/service/MemberServiceImpl.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.wypl.wyplcore.member.service; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.wypl.googleoauthclient.domain.AuthMember; -import com.wypl.jpamemberdomain.member.repository.MemberRepository; - -import lombok.RequiredArgsConstructor; - -@Transactional(readOnly = true) -@RequiredArgsConstructor -@Service -public class MemberServiceImpl { - private final MemberRepository memberRepository; - - @Transactional - public void deleteMember(AuthMember authMember) { - memberRepository.deleteById(authMember.id()); - } -} diff --git a/application/wypl-core/src/main/java/com/wypl/wyplcore/token/service/TokenService.java b/application/wypl-core/src/main/java/com/wypl/wyplcore/token/service/TokenService.java new file mode 100644 index 0000000..7c78246 --- /dev/null +++ b/application/wypl-core/src/main/java/com/wypl/wyplcore/token/service/TokenService.java @@ -0,0 +1,33 @@ +package com.wypl.wyplcore.token.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.wypl.redistokendomain.TokenRepository; + +import lombok.RequiredArgsConstructor; + +@Transactional(readOnly = true) +@RequiredArgsConstructor +@Service +public class TokenService { + private final TokenRepository tokenRepository; + + public boolean checkExistsToken(String accessToken) { + return tokenRepository.checkExistsToken(accessToken); + } + + @Transactional + public void saveToken(String accessToken, String refreshToken) { + tokenRepository.saveToken(accessToken, refreshToken); + } + + public String getRefreshToken(String accessToken) { + return tokenRepository.getRefreshToken(accessToken); + } + + @Transactional + public void deleteToken(String accessToken) { + tokenRepository.deleteToken(accessToken); + } +} diff --git a/application/wypl-core/src/test/java/com/wypl/wyplcore/auth/controller/AuthControllerTest.java b/application/wypl-core/src/test/java/com/wypl/wyplcore/auth/controller/AuthControllerTest.java index 6121227..b7f2813 100644 --- a/application/wypl-core/src/test/java/com/wypl/wyplcore/auth/controller/AuthControllerTest.java +++ b/application/wypl-core/src/test/java/com/wypl/wyplcore/auth/controller/AuthControllerTest.java @@ -30,7 +30,7 @@ import com.wypl.googleoauthclient.service.AuthMemberService; import com.wypl.googleoauthclient.utils.AuthenticatedArgumentResolver; import com.wypl.wyplcore.auth.data.response.AuthTokensResponse; -import com.wypl.wyplcore.auth.service.AuthServiceImpl; +import com.wypl.wyplcore.facade.AuthMemberFacade; @AutoConfigureRestDocs @AutoConfigureMockMvc @@ -43,7 +43,7 @@ class AuthControllerTest { @MockBean private AuthenticatedArgumentResolver authenticatedArgumentResolver; @MockBean - private AuthServiceImpl authService; + private AuthMemberFacade authMemberFacade; @MockBean private AuthMemberService authMemberService; @@ -52,7 +52,7 @@ class AuthControllerTest { void signInTest() throws Exception { /* Given */ AuthTokensResponse response = new AuthTokensResponse(0, "at", "rt"); - given(authService.generateToken(any(String.class), any(String.class))) + given(authMemberFacade.generateToken(any(String.class), any(String.class))) .willReturn(response); /* When */ @@ -95,7 +95,7 @@ void signInTest() throws Exception { void reissueTest() throws Exception { /* Given */ AuthTokensResponse response = new AuthTokensResponse(0, "at", "rt"); - given(authService.reissueToken(any(String.class), any(String.class))) + given(authMemberFacade.reissueToken(any(String.class), any(String.class))) .willReturn(response); /* When */ diff --git a/application/wypl-core/src/test/java/com/wypl/wyplcore/auth/service/AuthMemberFacadeImplTest.java b/application/wypl-core/src/test/java/com/wypl/wyplcore/auth/service/AuthMemberFacadeImplTest.java new file mode 100644 index 0000000..928b723 --- /dev/null +++ b/application/wypl-core/src/test/java/com/wypl/wyplcore/auth/service/AuthMemberFacadeImplTest.java @@ -0,0 +1,161 @@ +package com.wypl.wyplcore.auth.service; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +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.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.wypl.googleoauthclient.GoogleOAuthClient; +import com.wypl.googleoauthclient.data.response.GoogleTokenResponse; +import com.wypl.googleoauthclient.data.response.GoogleUserInfoResponse; +import com.wypl.googleoauthclient.domain.AuthMember; +import com.wypl.googleoauthclient.exception.GoogleOAuthErrorCode; +import com.wypl.googleoauthclient.exception.GoogleOAuthException; +import com.wypl.wyplcore.auth.data.response.AuthTokensResponse; +import com.wypl.wyplcore.facade.AuthMemberFacadeImpl; +import com.wypl.wyplcore.member.service.MemberService; +import com.wypl.wyplcore.token.service.TokenService; + +@ExtendWith(MockitoExtension.class) +class AuthMemberFacadeImplTest { + @InjectMocks + private AuthMemberFacadeImpl authMemberFacade; + @Mock + private GoogleOAuthClient googleOAuthClient; + @Mock + private TokenService tokenService; + @Mock + private MemberService memberService; + + @DisplayName("토큰을 성공적으로 발행한다.") + @Test + void generateTokenTest() { + // Given + GoogleTokenResponse mockGoogleTokenResponse = new GoogleTokenResponse( + "accessToken", + 3600, + "refreshToken", + "scope", + "idToken", + "tokenType" + ); + + GoogleUserInfoResponse mockGoogleUserInfoResponse = new GoogleUserInfoResponse( + "id", + "email", + "verifiedEmail", + "name", + "givenName", + "familyName" + ); + + given(googleOAuthClient.fetchGoogleOAuthToken(anyString())) + .willReturn(mockGoogleTokenResponse); + + given(googleOAuthClient.fetchUserInfo(anyString())) + .willReturn(mockGoogleUserInfoResponse); + + given(memberService.findMemberIdOrSaveMember(anyString(), any(GoogleUserInfoResponse.class))) + .willReturn(1L); + + // When + AuthTokensResponse result = authMemberFacade.generateToken("provider", "Authroization code"); + + // Then + verify(tokenService).saveToken(anyString(), anyString()); + assertThat(result.memberId()).isEqualTo(1L); + assertThat(result.accessToken()).isEqualTo(mockGoogleTokenResponse.accessToken()); + assertThat(result.refreshToken()).isEqualTo(mockGoogleTokenResponse.refreshToken()); + } + + @DisplayName("토큰 재발행 로직을 테스트한다.") + @Nested + class reissueTokenTest { + @DisplayName("유효하지 않은 리프레시 토큰으로 인해 인증되지 않은 회원 오류를 던진다.") + @ParameterizedTest + @ValueSource(strings = {"", "invalid Refresh Token"}) + @NullSource + void invalidRefreshTokenTest(String refreshToken) { + // Given + given(tokenService.getRefreshToken(anyString())) + .willReturn(refreshToken); + + // When & Then + assertThatThrownBy(() -> authMemberFacade.reissueToken("accessToken", "refreshToken")) + .isInstanceOf(GoogleOAuthException.class) + .hasMessageContaining(GoogleOAuthErrorCode.NOT_AUTHORIZATION_MEMBER.getMessage()); + } + + @DisplayName("토큰을 정상적으로 재발행한다.") + @Test + void reissueSuccessTest() { + // Given + GoogleTokenResponse mockGoogleTokenResponse = new GoogleTokenResponse( + "accessToken", + 3600, + "refreshToken", + "scope", + "idToken", + "tokenType" + ); + + given(tokenService.getRefreshToken(anyString())) + .willReturn("refreshToken"); + + given(googleOAuthClient.fetchRefreshGoogleOAuthToken(anyString())) + .willReturn(mockGoogleTokenResponse); + + // When + AuthTokensResponse result = authMemberFacade.reissueToken("accessToken", "refreshToken"); + + // Then + verify(tokenService).deleteToken(anyString()); + verify(tokenService).saveToken(anyString(), anyString()); + assertThat(result.accessToken()).isEqualTo(mockGoogleTokenResponse.accessToken()); + assertThat(result.refreshToken()).isEqualTo("refreshToken"); + } + } + + @DisplayName("로그아웃 로직이 정상적으로 동작한다.") + @Test + void logoutTest() { + // Given + AuthMember mockAuthMember = AuthMember.of( + 1L, + "accessToken" + ); + + // When + authMemberFacade.logout(mockAuthMember); + + // Then + verify(tokenService).deleteToken(anyString()); + } + + @DisplayName("회원탈퇴 로직이 정상적으로 동작한다.") + @Test + void quitMemberTest() { + // Given + AuthMember mockAuthMember = AuthMember.of( + 1L, + "accessToken" + ); + + // When + authMemberFacade.quitMember(mockAuthMember); + + // Then + verify(tokenService).deleteToken(anyString()); + verify(memberService).deleteMember(any(AuthMember.class)); + } +} \ No newline at end of file diff --git a/application/wypl-core/src/test/java/com/wypl/wyplcore/auth/service/AuthServiceImplTest.java b/application/wypl-core/src/test/java/com/wypl/wyplcore/auth/service/AuthServiceImplTest.java deleted file mode 100644 index 00dcb23..0000000 --- a/application/wypl-core/src/test/java/com/wypl/wyplcore/auth/service/AuthServiceImplTest.java +++ /dev/null @@ -1,215 +0,0 @@ -package com.wypl.wyplcore.auth.service; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.BDDMockito.*; - -import java.time.LocalDate; -import java.util.Optional; - -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 org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.NullSource; -import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import com.wypl.authdomain.auth.service.AuthDomainServiceImpl; -import com.wypl.googleoauthclient.GoogleOAuthClient; -import com.wypl.googleoauthclient.data.response.GoogleTokenResponse; -import com.wypl.googleoauthclient.data.response.GoogleUserInfoResponse; -import com.wypl.googleoauthclient.domain.AuthMember; -import com.wypl.googleoauthclient.exception.GoogleOAuthErrorCode; -import com.wypl.googleoauthclient.exception.GoogleOAuthException; -import com.wypl.jpamemberdomain.member.OauthProvider; -import com.wypl.jpamemberdomain.member.data.MemberSaveDto; -import com.wypl.jpamemberdomain.member.data.SocialMemberSaveDto; -import com.wypl.jpamemberdomain.member.domain.SocialMember; -import com.wypl.jpamemberdomain.member.repository.SocialMemberRepository; -import com.wypl.wyplcore.auth.data.response.AuthTokensResponse; -import com.wypl.wyplcore.member.service.MemberServiceImpl; - -@ExtendWith(MockitoExtension.class) -class AuthServiceImplTest { - @InjectMocks - private AuthServiceImpl authService; - @Mock - private GoogleOAuthClient googleOAuthClient; - @Mock - private SocialMemberRepository socialMemberRepository; - @Mock - private AuthDomainServiceImpl authDomainService; - @Mock - private MemberServiceImpl memberService; - - @DisplayName("로그인 및 회원가입 로직을 테스트한다.") - @Nested - class generateTokenTest { - private GoogleTokenResponse mockGoogleTokenResponse; - private GoogleUserInfoResponse mockGoogleUserInfoResponse; - - @BeforeEach - void setUp() { - mockGoogleTokenResponse = new GoogleTokenResponse( - "accessToken", - 3600, - "refreshToken", - "scope", - "idToken", - "tokenType" - ); - - mockGoogleUserInfoResponse = new GoogleUserInfoResponse( - "id", - "email", - "verifiedEmail", - "name", - "givenName", - "familyName" - ); - - given(googleOAuthClient.fetchGoogleOAuthToken(anyString())) - .willReturn(mockGoogleTokenResponse); - - given(googleOAuthClient.fetchUserInfo(anyString())) - .willReturn(mockGoogleUserInfoResponse); - } - - @DisplayName("이미 가입한 회원인 경우, 로그인에 성공한다.") - @Test - void signInTest() { - //Given - SocialMember mockSocialMember = SocialMember.builder() - .id(1L) - .oauthProvider(OauthProvider.GOOGLE) - .oauthId("mockOauthId") - .build(); - - given(socialMemberRepository.existsByOauthProviderAndOauthId(any(OauthProvider.class), anyString())) - .willReturn(true); - - given(socialMemberRepository.findByOauthProviderAndOauthId(any(OauthProvider.class), anyString())) - .willReturn(Optional.of(mockSocialMember)); - - // When - AuthTokensResponse result = authService.generateToken("provider", "Authroization code"); - - // Then - verify(authDomainService).saveToken(mockGoogleTokenResponse.accessToken(), - mockGoogleTokenResponse.refreshToken()); - assertThat(result.memberId()).isEqualTo(mockSocialMember.getId()); - assertThat(result.accessToken()).isEqualTo(mockGoogleTokenResponse.accessToken()); - assertThat(result.refreshToken()).isEqualTo(mockGoogleTokenResponse.refreshToken()); - } - - @DisplayName("신규 회원인 경우, 회원가입에 성공한다.") - @Test - void signUpTest() { - // Given - given(socialMemberRepository.existsByOauthProviderAndOauthId(any(OauthProvider.class), anyString())) - .willReturn(false); - - given(googleOAuthClient.fetchBirthday(anyString())) - .willReturn(LocalDate.now()); - - given(authDomainService.saveAuthData(any(MemberSaveDto.class), any(SocialMemberSaveDto.class))) - .willReturn(2L); - - // When - AuthTokensResponse result = authService.generateToken("provider", "Authroization code"); - - // Then - verify(authDomainService).saveToken(mockGoogleTokenResponse.accessToken(), - mockGoogleTokenResponse.refreshToken()); - assertThat(result.memberId()).isEqualTo(2L); - assertThat(result.accessToken()).isEqualTo(mockGoogleTokenResponse.accessToken()); - assertThat(result.refreshToken()).isEqualTo(mockGoogleTokenResponse.refreshToken()); - } - } - - @DisplayName("토큰 재발행 로직을 테스트한다.") - @Nested - class reissueTokenTest { - @DisplayName("유효하지 않은 리프레시 토큰으로 인해 인증되지 않은 회원 오류를 던진다.") - @ParameterizedTest - @ValueSource(strings = {"", "invalid Refresh Token"}) - @NullSource - void invalidRefreshTokenTest(String refreshToken) { - // Given - given(authDomainService.getRefreshToken(anyString())) - .willReturn(refreshToken); - - // When & Then - assertThatThrownBy(() -> authService.reissueToken("accessToken", "refreshToken")) - .isInstanceOf(GoogleOAuthException.class) - .hasMessageContaining(GoogleOAuthErrorCode.NOT_AUTHORIZATION_MEMBER.getMessage()); - } - - @DisplayName("토큰을 정상적으로 재발행한다.") - @Test - void reissueSuccessTest() { - // Given - GoogleTokenResponse mockGoogleTokenResponse = new GoogleTokenResponse( - "accessToken", - 3600, - "refreshToken", - "scope", - "idToken", - "tokenType" - ); - - given(authDomainService.getRefreshToken(anyString())) - .willReturn("refreshToken"); - - given(googleOAuthClient.fetchRefreshGoogleOAuthToken(anyString())) - .willReturn(mockGoogleTokenResponse); - - // When - AuthTokensResponse result = authService.reissueToken("accessToken", "refreshToken"); - - // Then - verify(authDomainService).deleteToken(anyString()); - verify(authDomainService).saveToken(anyString(), anyString()); - assertThat(result.accessToken()).isEqualTo(mockGoogleTokenResponse.accessToken()); - assertThat(result.refreshToken()).isEqualTo("refreshToken"); - } - } - - @DisplayName("로그아웃 로직이 정상적으로 동작한다.") - @Test - void logoutTest() { - // Given - AuthMember mockAuthMember = AuthMember.of( - 1L, - "accessToken" - ); - - // When - authService.logout(mockAuthMember); - - // Then - verify(authDomainService).deleteToken(anyString()); - } - - @DisplayName("회원탈퇴 로직이 정상적으로 동작한다.") - @Test - void quitMemberTest() { - // Given - AuthMember mockAuthMember = AuthMember.of( - 1L, - "accessToken" - ); - - // When - authService.quitMember(mockAuthMember); - - // Then - verify(authDomainService).deleteToken(anyString()); - verify(memberService).deleteMember(any(AuthMember.class)); - } -} \ No newline at end of file diff --git a/application/wypl-core/src/test/java/com/wypl/wyplcore/member/fixture/MemberFixture.java b/application/wypl-core/src/test/java/com/wypl/wyplcore/member/fixture/MemberFixture.java new file mode 100644 index 0000000..c0006b8 --- /dev/null +++ b/application/wypl-core/src/test/java/com/wypl/wyplcore/member/fixture/MemberFixture.java @@ -0,0 +1,55 @@ +package com.wypl.wyplcore.member.fixture; + +import java.time.LocalDate; +import java.util.UUID; + +import com.wypl.common.Color; +import com.wypl.jpamemberdomain.member.OauthProvider; +import com.wypl.jpamemberdomain.member.TimeZone; +import com.wypl.jpamemberdomain.member.domain.Member; +import com.wypl.jpamemberdomain.member.domain.SocialMember; + +// Todo : Access Level 고민해보자 +// @AllArgsConstructor +public enum MemberFixture { + JEONG_HOON(1L, "biosjh@gmail.com", "sjh", LocalDate.of(1999, 1, 15), "JHprofile", OauthProvider.GOOGLE) + ; + + private final Long memberId; + private final String email; + private final String nickname; + private final LocalDate birthday; + private final String profileImage; + private final OauthProvider oauthProvider; + + // @AllArgsConstructor 인식 불가로 인해, 명시적으로 생성자 추가 + MemberFixture(Long memberId, String email, String nickname, LocalDate birthday, String profileImage, OauthProvider oauthProvider) { + this.memberId = memberId; + this.email = email; + this.nickname = nickname; + this.birthday = birthday; + this.profileImage = profileImage; + this.oauthProvider = oauthProvider; + } + + public Member toMember() { + return Member.builder() + .memberId(memberId) + .email(email) + .nickname(nickname) + .birthday(birthday) + .profileImage(profileImage) + .color(Color.labelBrown) + .timeZone(TimeZone.KOREA) + .build(); + } + + public SocialMember toSocialMember() { + return SocialMember.builder() + .id(memberId) + .member(toMember()) + .oauthProvider(oauthProvider) + .oauthId(UUID.randomUUID().toString()) + .build(); + } +} diff --git a/application/wypl-core/src/test/java/com/wypl/wyplcore/member/service/MemberServiceImplTest.java b/application/wypl-core/src/test/java/com/wypl/wyplcore/member/service/MemberServiceImplTest.java deleted file mode 100644 index 69f516f..0000000 --- a/application/wypl-core/src/test/java/com/wypl/wyplcore/member/service/MemberServiceImplTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.wypl.wyplcore.member.service; - -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import com.wypl.googleoauthclient.domain.AuthMember; -import com.wypl.jpamemberdomain.member.repository.MemberRepository; - -@ExtendWith(MockitoExtension.class) -public class MemberServiceImplTest { - @InjectMocks - private MemberServiceImpl memberService; - @Mock - private MemberRepository memberRepository; - - @DisplayName("Member를 정상적으로 삭제한다.") - @Test - void quitMemberTest() { - // Given - AuthMember mockAuthMember = AuthMember.of( - 1L, - "accessToken" - ); - - // When - memberService.deleteMember(mockAuthMember); - - // Then - verify(memberRepository).deleteById(anyLong()); - } -} diff --git a/application/wypl-core/src/test/java/com/wypl/wyplcore/member/service/MemberServiceTest.java b/application/wypl-core/src/test/java/com/wypl/wyplcore/member/service/MemberServiceTest.java new file mode 100644 index 0000000..c11e504 --- /dev/null +++ b/application/wypl-core/src/test/java/com/wypl/wyplcore/member/service/MemberServiceTest.java @@ -0,0 +1,129 @@ +package com.wypl.wyplcore.member.service; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.*; + +import java.time.LocalDate; +import java.util.Optional; + +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 org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.wypl.googleoauthclient.GoogleOAuthClient; +import com.wypl.googleoauthclient.data.response.GoogleUserInfoResponse; +import com.wypl.googleoauthclient.domain.AuthMember; +import com.wypl.jpamemberdomain.member.OauthProvider; +import com.wypl.jpamemberdomain.member.domain.Member; +import com.wypl.jpamemberdomain.member.domain.SocialMember; +import com.wypl.jpamemberdomain.member.repository.MemberRepository; +import com.wypl.jpamemberdomain.member.repository.SocialMemberRepository; +import com.wypl.wyplcore.member.fixture.MemberFixture; + +@ExtendWith(MockitoExtension.class) +public class MemberServiceTest { + @InjectMocks + private MemberService memberService; + @Mock + private MemberRepository memberRepository; + @Mock + private GoogleOAuthClient googleOAuthClient; + @Mock + private SocialMemberRepository socialMemberRepository; + + @DisplayName("Member를 정상적으로 삭제한다.") + @Test + void quitMemberTest() { + // Given + AuthMember mockAuthMember = AuthMember.of( + 1L, + "accessToken" + ); + + // When + memberService.deleteMember(mockAuthMember); + + // Then + verify(memberRepository).deleteById(anyLong()); + } + + @DisplayName("로그인 및 회원가입 로직을 테스트한다.") + @Nested + class generateTokenTest { + private GoogleUserInfoResponse mockGoogleUserInfoResponse; + private String accessToken; + + @BeforeEach + void setUp() { + mockGoogleUserInfoResponse = new GoogleUserInfoResponse( + "id", + "email", + "verifiedEmail", + "name", + "givenName", + "familyName" + ); + + accessToken = "access_token"; + } + + @DisplayName("이미 가입한 회원인 경우, 로그인에 성공한다.") + @Test + void signInTest() { + // Given + SocialMember mockSocialMember = SocialMember.builder() + .id(1L) + .oauthProvider(OauthProvider.GOOGLE) + .oauthId("mockOauthId") + .build(); + + given(socialMemberRepository.existsByOauthProviderAndOauthId(any(OauthProvider.class), anyString())) + .willReturn(true); + + given(socialMemberRepository.findByOauthProviderAndOauthId(any(OauthProvider.class), anyString())) + .willReturn(Optional.of(mockSocialMember)); + + // When + long result = memberService.findMemberIdOrSaveMember(accessToken, mockGoogleUserInfoResponse); + + // Then + assertThat(result).isEqualTo(1L); + } + + @DisplayName("신규 회원인 경우, 회원가입에 성공한다.") + @ParameterizedTest + @EnumSource + void signUpTest(MemberFixture fixture) { + // Given + Member memberMock = fixture.toMember(); + + SocialMember socialMemberMock = fixture.toSocialMember(); + + given(memberRepository.save(any(Member.class))) + .willReturn(memberMock); + + given(socialMemberRepository.save(any(SocialMember.class))) + .willReturn(socialMemberMock); + + given(socialMemberRepository.existsByOauthProviderAndOauthId(any(OauthProvider.class), anyString())) + .willReturn(false); + + given(googleOAuthClient.fetchBirthday(anyString())) + .willReturn(LocalDate.now()); + + // When + long result = memberService.findMemberIdOrSaveMember(accessToken, mockGoogleUserInfoResponse); + + // Then + assertThat(result).isEqualTo(socialMemberMock.getId()); + } + } +} diff --git a/application/wypl-core/src/test/java/com/wypl/wyplcore/token/service/TokenServiceTest.java b/application/wypl-core/src/test/java/com/wypl/wyplcore/token/service/TokenServiceTest.java new file mode 100644 index 0000000..f779b9a --- /dev/null +++ b/application/wypl-core/src/test/java/com/wypl/wyplcore/token/service/TokenServiceTest.java @@ -0,0 +1,61 @@ +package com.wypl.wyplcore.token.service; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.wypl.redistokendomain.TokenRepository; + +@ExtendWith(MockitoExtension.class) +class TokenServiceTest { + @InjectMocks + private TokenService tokenService; + @Mock + private TokenRepository tokenRepository; + + @DisplayName("Redis에 존재하는 토큰인지 확인한다.") + @Test + void checkExistsTokenTest() { + // When + tokenService.checkExistsToken(anyString()); + + // Then + verify(tokenRepository).checkExistsToken(anyString()); + } + + @DisplayName("Redis에 토큰을 저장한다.") + @Test + void saveTokenTest() { + // When + tokenService.saveToken(anyString(), anyString()); + + // Then + verify(tokenRepository).saveToken(anyString(), anyString()); + } + + @DisplayName("Redis에서 Access Token으로 Refresh Token 값을 가져온다.") + @Test + void getRefreshTokenTest() { + // When + tokenService.getRefreshToken(anyString()); + + // Then + verify(tokenRepository).getRefreshToken(anyString()); + } + + @DisplayName("Redis에 저장된 토큰 정보를 삭제한다.") + @Test + void deleteToken() { + // When + tokenService.deleteToken(anyString()); + + // Then + verify(tokenRepository).deleteToken(anyString()); + } +} \ No newline at end of file diff --git a/domain/auth-domain/src/main/java/com/wypl/authdomain/auth/exception/AuthErrorCode.java b/domain/auth-domain/src/main/java/com/wypl/authdomain/auth/exception/AuthErrorCode.java index 12e8170..ab8ffe6 100644 --- a/domain/auth-domain/src/main/java/com/wypl/authdomain/auth/exception/AuthErrorCode.java +++ b/domain/auth-domain/src/main/java/com/wypl/authdomain/auth/exception/AuthErrorCode.java @@ -1,21 +1,22 @@ -package com.wypl.authdomain.auth.exception; - -import com.wypl.common.exception.ServerErrorCode; - -import lombok.Getter; - -@Getter -public enum AuthErrorCode implements ServerErrorCode { - INVALID_TOKEN(400, "AUTH_001", "올바르지 않은 토큰입니다."), - EXPIRED_TOKEN(401, "AUTH_002", "만료된 토큰입니다."); - - private final int statusCode; - private final String errorCode; - private final String message; - - AuthErrorCode(int statusCode, String errorCode, String message) { - this.statusCode = statusCode; - this.errorCode = errorCode; - this.message = message; - } -} +// package com.wypl.authdomain.auth.exception; +// +// import com.wypl.common.exception.ServerErrorCode; +// +// import lombok.Getter; +// +// @Getter +// public enum AuthErrorCode implements ServerErrorCode { +// INVALID_TOKEN(400, "AUTH_001", "올바르지 않은 토큰입니다."), +// EXPIRED_TOKEN(401, "AUTH_002", "만료된 토큰입니다.") +// ; +// +// private final int statusCode; +// private final String errorCode; +// private final String message; +// +// AuthErrorCode(int statusCode, String errorCode, String message) { +// this.statusCode = statusCode; +// this.errorCode = errorCode; +// this.message = message; +// } +// } \ No newline at end of file diff --git a/domain/auth-domain/src/main/java/com/wypl/authdomain/auth/exception/AuthException.java b/domain/auth-domain/src/main/java/com/wypl/authdomain/auth/exception/AuthException.java index 123aa80..21dceba 100644 --- a/domain/auth-domain/src/main/java/com/wypl/authdomain/auth/exception/AuthException.java +++ b/domain/auth-domain/src/main/java/com/wypl/authdomain/auth/exception/AuthException.java @@ -1,9 +1,9 @@ -package com.wypl.authdomain.auth.exception; - -import com.wypl.common.exception.WyplException; - -public class AuthException extends WyplException { - public AuthException(AuthErrorCode serverErrorCode) { - super(serverErrorCode); - } -} +// package com.wypl.authdomain.auth.exception; +// +// import com.wypl.common.exception.WyplException; +// +// public class AuthException extends WyplException { +// public AuthException(AuthErrorCode serverErrorCode) { +// super(serverErrorCode); +// } +// } \ No newline at end of file diff --git a/domain/auth-domain/src/main/java/com/wypl/authdomain/auth/service/AuthDomainServiceImpl.java b/domain/auth-domain/src/main/java/com/wypl/authdomain/auth/service/AuthDomainServiceImpl.java index 8028c93..0cb55ff 100644 --- a/domain/auth-domain/src/main/java/com/wypl/authdomain/auth/service/AuthDomainServiceImpl.java +++ b/domain/auth-domain/src/main/java/com/wypl/authdomain/auth/service/AuthDomainServiceImpl.java @@ -1,48 +1,18 @@ -package com.wypl.authdomain.auth.service; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.wypl.jpamemberdomain.member.data.MemberSaveDto; -import com.wypl.jpamemberdomain.member.data.SocialMemberSaveDto; -import com.wypl.jpamemberdomain.member.domain.Member; -import com.wypl.jpamemberdomain.member.domain.SocialMember; -import com.wypl.jpamemberdomain.member.repository.MemberRepository; -import com.wypl.jpamemberdomain.member.repository.SocialMemberRepository; -import com.wypl.redistokendomain.TokenRepository; - -import lombok.RequiredArgsConstructor; - -@Transactional(readOnly = true) -@RequiredArgsConstructor -@Service -public class AuthDomainServiceImpl { - private final MemberRepository memberRepository; - private final SocialMemberRepository socialMemberRepository; - private final TokenRepository tokenRepository; - - @Transactional - public long saveAuthData(MemberSaveDto memberSaveDto, SocialMemberSaveDto socialMemberSaveDto) { - Member newMember = memberRepository.save(Member.of(memberSaveDto)); - SocialMember socialMember = socialMemberRepository.save(SocialMember.of(newMember, socialMemberSaveDto)); - return socialMember.getId(); - } - - public boolean checkExistsToken(String accessToken) { - return tokenRepository.checkExistsToken(accessToken); - } - - @Transactional - public void saveToken(String accessToken, String refreshToken) { - tokenRepository.saveToken(accessToken, refreshToken); - } - - public String getRefreshToken(String accessToken) { - return tokenRepository.getRefreshToken(accessToken); - } - - @Transactional - public void deleteToken(String accessToken) { - tokenRepository.deleteToken(accessToken); - } -} +// package com.wypl.authdomain.auth.service; +// +// import org.springframework.stereotype.Service; +// import org.springframework.transaction.annotation.Transactional; +// +// import com.wypl.jpamemberdomain.member.repository.MemberRepository; +// import com.wypl.jpamemberdomain.member.repository.SocialMemberRepository; +// +// import lombok.RequiredArgsConstructor; +// +// @Transactional(readOnly = true) +// @RequiredArgsConstructor +// @Service +// public class AuthDomainServiceImpl { +// private final MemberRepository memberRepository; +// private final SocialMemberRepository socialMemberRepository; +// +// } diff --git a/domain/auth-domain/src/test/java/com/wypl/authdomain/auth/service/AuthDomainServiceImplTest.java b/domain/auth-domain/src/test/java/com/wypl/authdomain/auth/service/AuthDomainServiceImplTest.java index a3ca62e..aebabc3 100644 --- a/domain/auth-domain/src/test/java/com/wypl/authdomain/auth/service/AuthDomainServiceImplTest.java +++ b/domain/auth-domain/src/test/java/com/wypl/authdomain/auth/service/AuthDomainServiceImplTest.java @@ -1,111 +1,111 @@ -package com.wypl.authdomain.auth.service; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.BDDMockito.*; - -import java.time.LocalDate; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import com.wypl.authdomain.auth.service.fixture.MemberFixture; -import com.wypl.jpamemberdomain.member.OauthProvider; -import com.wypl.jpamemberdomain.member.data.MemberSaveDto; -import com.wypl.jpamemberdomain.member.data.SocialMemberSaveDto; -import com.wypl.jpamemberdomain.member.domain.Member; -import com.wypl.jpamemberdomain.member.domain.SocialMember; -import com.wypl.jpamemberdomain.member.repository.MemberRepository; -import com.wypl.jpamemberdomain.member.repository.SocialMemberRepository; -import com.wypl.redistokendomain.TokenRepository; - -@ExtendWith(MockitoExtension.class) -class AuthDomainServiceImplTest { - @InjectMocks - private AuthDomainServiceImpl authDomainService; - @Mock - private MemberRepository memberRepository; - @Mock - private SocialMemberRepository socialMemberRepository; - @Mock - private TokenRepository tokenRepository; - - @DisplayName("유저의 Auth 데이터를 저장한다.") - @ParameterizedTest - @EnumSource - void saveAuthDateTest(MemberFixture fixture) { - // Given - MemberSaveDto memberSaveDtoMock = MemberSaveDto.builder() - .email("email") - .nickname("nickname") - .birthday(LocalDate.of(1999, 1, 15)) - .profileImage("profileImage") - .build(); - - SocialMemberSaveDto socialMemberSaveDtoMock = SocialMemberSaveDto.builder() - .oauthProvider(OauthProvider.GOOGLE) - .oauthId("oauthId") - .build(); - - Member memberMock = fixture.toMember(); - - SocialMember socialMemberMock = fixture.toSocialMember(); - - given(memberRepository.save(any(Member.class))) - .willReturn(memberMock); - - given(socialMemberRepository.save(any(SocialMember.class))) - .willReturn(socialMemberMock); - - // When - long result = authDomainService.saveAuthData(memberSaveDtoMock, socialMemberSaveDtoMock); - - // Then - assertThat(result).isEqualTo(socialMemberMock.getId()); - } - - @DisplayName("Redis에 존재하는 토큰인지 확인한다.") - @Test - void checkExistsTokenTest() { - // When - authDomainService.checkExistsToken(anyString()); - - // Then - verify(tokenRepository).checkExistsToken(anyString()); - } - - @DisplayName("Redis에 토큰을 저장한다.") - @Test - void saveTokenTest() { - // When - authDomainService.saveToken(anyString(), anyString()); - - // Then - verify(tokenRepository).saveToken(anyString(), anyString()); - } - - @DisplayName("Redis에서 Access Token으로 Refresh Token 값을 가져온다.") - @Test - void getRefreshTokenTest() { - // When - authDomainService.getRefreshToken(anyString()); - - // Then - verify(tokenRepository).getRefreshToken(anyString()); - } - - @DisplayName("Redis에 저장된 토큰 정보를 삭제한다.") - @Test - void deleteToken() { - // When - authDomainService.deleteToken(anyString()); - - // Then - verify(tokenRepository).deleteToken(anyString()); - } -} \ No newline at end of file +// package com.wypl.authdomain.auth.service; +// +// import static org.assertj.core.api.Assertions.*; +// import static org.mockito.BDDMockito.*; +// +// import java.time.LocalDate; +// +// import org.junit.jupiter.api.DisplayName; +// import org.junit.jupiter.api.Test; +// import org.junit.jupiter.api.extension.ExtendWith; +// import org.junit.jupiter.params.ParameterizedTest; +// import org.junit.jupiter.params.provider.EnumSource; +// import org.mockito.InjectMocks; +// import org.mockito.Mock; +// import org.mockito.junit.jupiter.MockitoExtension; +// +// import com.wypl.authdomain.auth.service.fixture.MemberFixture; +// import com.wypl.jpamemberdomain.member.OauthProvider; +// import com.wypl.jpamemberdomain.member.data.MemberSaveDto; +// import com.wypl.jpamemberdomain.member.data.SocialMemberSaveDto; +// import com.wypl.jpamemberdomain.member.domain.Member; +// import com.wypl.jpamemberdomain.member.domain.SocialMember; +// import com.wypl.jpamemberdomain.member.repository.MemberRepository; +// import com.wypl.jpamemberdomain.member.repository.SocialMemberRepository; +// import com.wypl.redistokendomain.TokenRepository; +// +// @ExtendWith(MockitoExtension.class) +// class AuthDomainServiceImplTest { +// @InjectMocks +// private AuthDomainServiceImpl authDomainService; +// @Mock +// private MemberRepository memberRepository; +// @Mock +// private SocialMemberRepository socialMemberRepository; +// @Mock +// private TokenRepository tokenRepository; +// +// @DisplayName("유저의 Auth 데이터를 저장한다.") +// @ParameterizedTest +// @EnumSource +// void saveAuthDateTest(MemberFixture fixture) { +// // Given +// MemberSaveDto memberSaveDtoMock = MemberSaveDto.builder() +// .email("email") +// .nickname("nickname") +// .birthday(LocalDate.of(1999, 1, 15)) +// .profileImage("profileImage") +// .build(); +// +// SocialMemberSaveDto socialMemberSaveDtoMock = SocialMemberSaveDto.builder() +// .oauthProvider(OauthProvider.GOOGLE) +// .oauthId("oauthId") +// .build(); +// +// Member memberMock = fixture.toMember(); +// +// SocialMember socialMemberMock = fixture.toSocialMember(); +// +// given(memberRepository.save(any(Member.class))) +// .willReturn(memberMock); +// +// given(socialMemberRepository.save(any(SocialMember.class))) +// .willReturn(socialMemberMock); +// +// // When +// long result = authDomainService.saveAuthData(memberSaveDtoMock, socialMemberSaveDtoMock); +// +// // Then +// assertThat(result).isEqualTo(socialMemberMock.getId()); +// } +// +// @DisplayName("Redis에 존재하는 토큰인지 확인한다.") +// @Test +// void checkExistsTokenTest() { +// // When +// authDomainService.checkExistsToken(anyString()); +// +// // Then +// verify(tokenRepository).checkExistsToken(anyString()); +// } +// +// @DisplayName("Redis에 토큰을 저장한다.") +// @Test +// void saveTokenTest() { +// // When +// authDomainService.saveToken(anyString(), anyString()); +// +// // Then +// verify(tokenRepository).saveToken(anyString(), anyString()); +// } +// +// @DisplayName("Redis에서 Access Token으로 Refresh Token 값을 가져온다.") +// @Test +// void getRefreshTokenTest() { +// // When +// authDomainService.getRefreshToken(anyString()); +// +// // Then +// verify(tokenRepository).getRefreshToken(anyString()); +// } +// +// @DisplayName("Redis에 저장된 토큰 정보를 삭제한다.") +// @Test +// void deleteToken() { +// // When +// authDomainService.deleteToken(anyString()); +// +// // Then +// verify(tokenRepository).deleteToken(anyString()); +// } +// } \ No newline at end of file diff --git a/domain/auth-domain/src/test/java/com/wypl/authdomain/auth/service/fixture/MemberFixture.java b/domain/auth-domain/src/test/java/com/wypl/authdomain/auth/service/fixture/MemberFixture.java index 4fa0d7d..75d15a2 100644 --- a/domain/auth-domain/src/test/java/com/wypl/authdomain/auth/service/fixture/MemberFixture.java +++ b/domain/auth-domain/src/test/java/com/wypl/authdomain/auth/service/fixture/MemberFixture.java @@ -1,55 +1,55 @@ -package com.wypl.authdomain.auth.service.fixture; - -import java.time.LocalDate; -import java.util.UUID; - -import com.wypl.common.Color; -import com.wypl.jpamemberdomain.member.OauthProvider; -import com.wypl.jpamemberdomain.member.TimeZone; -import com.wypl.jpamemberdomain.member.domain.Member; -import com.wypl.jpamemberdomain.member.domain.SocialMember; - -// Todo : Access Level 고민해보자 -// @AllArgsConstructor -public enum MemberFixture { - JEONG_HOON(1L, "biosjh@gmail.com", "sjh", LocalDate.of(1999, 1, 15), "JHprofile", OauthProvider.GOOGLE); - - private final Long memberId; - private final String email; - private final String nickname; - private final LocalDate birthday; - private final String profileImage; - private final OauthProvider oauthProvider; - - // @AllArgsConstructor 인식 불가로 인해, 명시적으로 생성자 추가 - MemberFixture(Long memberId, String email, String nickname, LocalDate birthday, String profileImage, - OauthProvider oauthProvider) { - this.memberId = memberId; - this.email = email; - this.nickname = nickname; - this.birthday = birthday; - this.profileImage = profileImage; - this.oauthProvider = oauthProvider; - } - - public Member toMember() { - return Member.builder() - .memberId(memberId) - .email(email) - .nickname(nickname) - .birthday(birthday) - .profileImage(profileImage) - .color(Color.labelBrown) - .timeZone(TimeZone.KOREA) - .build(); - } - - public SocialMember toSocialMember() { - return SocialMember.builder() - .id(memberId) - .member(toMember()) - .oauthProvider(oauthProvider) - .oauthId(UUID.randomUUID().toString()) - .build(); - } -} +// package com.wypl.authdomain.auth.service.fixture; +// +// import java.time.LocalDate; +// import java.util.UUID; +// +// import com.wypl.common.Color; +// import com.wypl.jpamemberdomain.member.OauthProvider; +// import com.wypl.jpamemberdomain.member.TimeZone; +// import com.wypl.jpamemberdomain.member.domain.Member; +// import com.wypl.jpamemberdomain.member.domain.SocialMember; +// +// // Todo : Access Level 고민해보자 +// // @AllArgsConstructor +// public enum MemberFixture { +// JEONG_HOON(1L, "biosjh@gmail.com", "sjh", LocalDate.of(1999, 1, 15), "JHprofile", OauthProvider.GOOGLE) +// ; +// +// private final Long memberId; +// private final String email; +// private final String nickname; +// private final LocalDate birthday; +// private final String profileImage; +// private final OauthProvider oauthProvider; +// +// // @AllArgsConstructor 인식 불가로 인해, 명시적으로 생성자 추가 +// MemberFixture(Long memberId, String email, String nickname, LocalDate birthday, String profileImage, OauthProvider oauthProvider) { +// this.memberId = memberId; +// this.email = email; +// this.nickname = nickname; +// this.birthday = birthday; +// this.profileImage = profileImage; +// this.oauthProvider = oauthProvider; +// } +// +// public Member toMember() { +// return Member.builder() +// .memberId(memberId) +// .email(email) +// .nickname(nickname) +// .birthday(birthday) +// .profileImage(profileImage) +// .color(Color.labelBrown) +// .timeZone(TimeZone.KOREA) +// .build(); +// } +// +// public SocialMember toSocialMember() { +// return SocialMember.builder() +// .id(memberId) +// .member(toMember()) +// .oauthProvider(oauthProvider) +// .oauthId(UUID.randomUUID().toString()) +// .build(); +// } +// }