diff --git a/NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/oauth/dao/RefreshTokenBlackListRepository.java b/NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/oauth/dao/RefreshTokenBlackListRepository.java index b042e300..bd30dfb2 100644 --- a/NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/oauth/dao/RefreshTokenBlackListRepository.java +++ b/NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/oauth/dao/RefreshTokenBlackListRepository.java @@ -5,7 +5,11 @@ import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface RefreshTokenBlackListRepository extends JpaRepository { void deleteByRefreshToken(RefreshToken refreshToken); + + Optional findByRefreshTokenId(Long refreshTokenId); } diff --git a/NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/oauth/dto/request/LogoutRequest.java b/NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/oauth/dto/request/LogoutRequest.java index 84834514..b815678f 100644 --- a/NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/oauth/dto/request/LogoutRequest.java +++ b/NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/oauth/dto/request/LogoutRequest.java @@ -1,10 +1,12 @@ package io.twogether.nbe_5_7_2_02team.oauth.dto.request; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @NoArgsConstructor +@AllArgsConstructor public class LogoutRequest { private String refreshToken; } diff --git a/NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/oauth/dto/request/RefreshRequest.java b/NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/oauth/dto/request/RefreshRequest.java index 656e83e1..1b9b6a5e 100644 --- a/NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/oauth/dto/request/RefreshRequest.java +++ b/NBE_5_7_2_02TEAM/src/main/java/io/twogether/nbe_5_7_2_02team/oauth/dto/request/RefreshRequest.java @@ -1,10 +1,12 @@ package io.twogether.nbe_5_7_2_02team.oauth.dto.request; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @NoArgsConstructor +@AllArgsConstructor public class RefreshRequest { private String refreshToken; } diff --git a/NBE_5_7_2_02TEAM/src/test/java/io/twogether/nbe_5_7_2_02team/oauth/api/TokenBrowserSuccessTest.java b/NBE_5_7_2_02TEAM/src/test/java/io/twogether/nbe_5_7_2_02team/oauth/api/TokenBrowserSuccessTest.java new file mode 100644 index 00000000..c0b87ce2 --- /dev/null +++ b/NBE_5_7_2_02TEAM/src/test/java/io/twogether/nbe_5_7_2_02team/oauth/api/TokenBrowserSuccessTest.java @@ -0,0 +1,95 @@ +package io.twogether.nbe_5_7_2_02team.oauth.api; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.database.rider.core.api.dataset.DataSet; + +import io.twogether.nbe_5_7_2_02team.browser.template.BrowserTestTemplate; +import io.twogether.nbe_5_7_2_02team.global.annotation.FlywayReset; +import io.twogether.nbe_5_7_2_02team.member.dao.MemberRepository; +import io.twogether.nbe_5_7_2_02team.member.domain.Member; +import io.twogether.nbe_5_7_2_02team.member.dto.request.SignUpRequest; +import io.twogether.nbe_5_7_2_02team.oauth.dao.RefreshTokenBlackListRepository; +import io.twogether.nbe_5_7_2_02team.oauth.dto.common.TokenPair; +import io.twogether.nbe_5_7_2_02team.oauth.dto.request.LogoutRequest; +import io.twogether.nbe_5_7_2_02team.oauth.dto.request.RefreshRequest; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; + +@FlywayReset +public class TokenBrowserSuccessTest extends BrowserTestTemplate { + + @Autowired MemberRepository memberRepository; + @Autowired ObjectMapper objectMapper; + @Autowired RefreshTokenBlackListRepository refreshTokenBlackListRepository; + + @Test + @DataSet(value = "datasets/v2/member.yml", cleanBefore = true, cleanAfter = true) + @DisplayName("POST: /api/token/refresh 리프레시 토큰을 이용해 토큰 재발급") + void refreshToken() throws Exception { + // given + TokenPair tokenPair = genTokenPair(1L); + RefreshRequest request = new RefreshRequest(tokenPair.getRefreshToken()); + + // when & then + mockMvc.perform( + post("/api/token/refresh") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.access_token").value(tokenPair.getAccessToken())) + .andExpect(jsonPath("$.refresh_token").value(tokenPair.getRefreshToken())); + } + + @Test + @DataSet(value = "datasets/v2/member.yml", cleanBefore = true, cleanAfter = true) + @DisplayName("POST: /api/logout 로그아웃 요청 성공") + void logout() throws Exception { + // given + TokenPair tokenPair = genTokenPair(1L); + LogoutRequest request = new LogoutRequest(tokenPair.getRefreshToken()); + + // when & then + mockMvc.perform( + post("/api/logout") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + .header("Authorization", "Bearer " + tokenPair.getAccessToken())) + .andExpect(status().isOk()); + } + + @Test + @DataSet(value = "datasets/v2/member.yml", cleanBefore = true, cleanAfter = true) + @DisplayName("POST: /api/signup 회원가입 성공") + void signup() throws Exception { + // given + long memberId = 1L; + TokenPair tokenPair = genTokenPair(memberId); + + SignUpRequest request = + SignUpRequest.builder().name("신규가입자").job("DEVELOPER").course("SPRING").build(); + + // when & then + mockMvc.perform( + post("/api/signup") + .header("Authorization", "Bearer " + tokenPair.getAccessToken()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").value(memberId)) + .andExpect(jsonPath("$.name").value(request.getName())) + .andExpect(jsonPath("$.job").value(request.getJob())) + .andExpect(jsonPath("$.course").value(request.getCourse())); + } + + private TokenPair genTokenPair(Long memberId) { + Member member = memberRepository.findById(memberId).orElseThrow(); + return jwtTokenProvider.generateTokenPair(member); + } +} diff --git a/NBE_5_7_2_02TEAM/src/test/java/io/twogether/nbe_5_7_2_02team/oauth/service/OAuthServiceTest.java b/NBE_5_7_2_02TEAM/src/test/java/io/twogether/nbe_5_7_2_02team/oauth/service/OAuthServiceTest.java new file mode 100644 index 00000000..159d6d71 --- /dev/null +++ b/NBE_5_7_2_02TEAM/src/test/java/io/twogether/nbe_5_7_2_02team/oauth/service/OAuthServiceTest.java @@ -0,0 +1,78 @@ +// package io.twogether.nbe_5_7_2_02team.oauth.service; +// +// import static org.assertj.core.api.Assertions.assertThat; +// import static org.junit.jupiter.api.Assertions.*; +// import static org.mockito.ArgumentMatchers.eq; +// import static org.mockito.Mockito.doReturn; +// import static org.mockito.Mockito.when; +// +// import io.twogether.nbe_5_7_2_02team.browser.template.BrowserTestTemplate; +// import io.twogether.nbe_5_7_2_02team.global.annotation.FlywayReset; +// import io.twogether.nbe_5_7_2_02team.member.dao.MemberRepository; +// import io.twogether.nbe_5_7_2_02team.member.domain.Member; +// import io.twogether.nbe_5_7_2_02team.member.domain.Role; +// import io.twogether.nbe_5_7_2_02team.member.dto.response.LoginResponse; +// import io.twogether.nbe_5_7_2_02team.oauth.dto.response.GitHubUserInfoResponse; +// import io.twogether.nbe_5_7_2_02team.oauth.jwt.JwtTokenProvider; +// import java.util.List; +// import java.util.Optional; +// 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.bean.override.mockito.MockitoBean; +// import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; +// import org.springframework.transaction.annotation.Transactional; +// import org.springframework.web.client.RestTemplate; +// import org.testcontainers.shaded.org.checkerframework.checker.units.qual.A; +// +// +// @FlywayReset +// @SpringBootTest +// @Transactional +// class OAuthServiceTest extends BrowserTestTemplate { +// +// @Autowired +// JwtTokenProvider jwtTokenProvider; +// @Autowired +// MemberRepository memberRepository; +// @Autowired +// OAuthService oAuthService; +// +// private String dummyAccessToken = "dummyAccessToken"; +// +// private GitHubUserInfoResponse dummyUserInfo; +// +// private final RestTemplate restTemplate = new RestTemplate(); +// +// @BeforeEach +// void setUp() { +// dummyUserInfo = GitHubUserInfoResponse.builder() +// .githubId("testGithubId") +// .githubId("testGithubId") +// .avatarUrl("http://avatar.url") +// .email("test@example.com") +// .organizations(List.of("prgrms-web-devcourse")) +// .build(); +// } +// +// @Test +// @DisplayName("") +// void first_login_success() throws Exception { +// +// when(oAuthService.getUserInfo(dummyAccessToken)).thenReturn(dummyUserInfo); +// +// LoginResponse loginResponse = oAuthService.login(dummyAccessToken); +// +// assertNotNull(loginResponse); +// assertNotNull(loginResponse.getTokenPair()); +// assertEquals(Role.MEMBER, loginResponse.getRole()); +// +// Optional savedMember = memberRepository.findByEmail(dummyUserInfo.getEmail()); +// assertThat(savedMember).isPresent(); +// assertThat(savedMember.get().getGithubId()).isEqualTo("testGithubId"); +// +// } +// +// } diff --git a/NBE_5_7_2_02TEAM/src/test/java/io/twogether/nbe_5_7_2_02team/oauth/service/TokenServiceTest.java b/NBE_5_7_2_02TEAM/src/test/java/io/twogether/nbe_5_7_2_02team/oauth/service/TokenServiceTest.java new file mode 100644 index 00000000..8706f0c2 --- /dev/null +++ b/NBE_5_7_2_02TEAM/src/test/java/io/twogether/nbe_5_7_2_02team/oauth/service/TokenServiceTest.java @@ -0,0 +1,59 @@ +package io.twogether.nbe_5_7_2_02team.oauth.service; + +import static org.junit.jupiter.api.Assertions.*; + +import com.github.database.rider.core.api.dataset.DataSet; + +import io.twogether.nbe_5_7_2_02team.browser.template.BrowserTestTemplate; +import io.twogether.nbe_5_7_2_02team.global.annotation.FlywayReset; +import io.twogether.nbe_5_7_2_02team.member.dao.MemberRepository; +import io.twogether.nbe_5_7_2_02team.member.domain.Member; +import io.twogether.nbe_5_7_2_02team.oauth.dao.RefreshTokenBlackListRepository; +import io.twogether.nbe_5_7_2_02team.oauth.dao.RefreshTokenRepository; +import io.twogether.nbe_5_7_2_02team.oauth.domain.RefreshToken; +import io.twogether.nbe_5_7_2_02team.oauth.dto.common.TokenPair; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +@SpringBootTest +@FlywayReset +@Transactional +class TokenServiceTest extends BrowserTestTemplate { + + @Autowired MemberRepository memberRepository; + @Autowired TokenService tokenService; + @Autowired RefreshTokenBlackListRepository refreshTokenBlackListRepository; + @Autowired RefreshTokenRepository refreshTokenRepository; + + @Test + @DataSet(value = "datasets/v2/member.yml", cleanBefore = true, cleanAfter = true) + void refresh_success() throws Exception { + + TokenPair originTokenPair = genTokenPair(1L); + + TokenPair refreshTokenPair = tokenService.refreshToken(originTokenPair.getRefreshToken()); + + assertEquals(originTokenPair.getRefreshToken(), refreshTokenPair.getRefreshToken()); + } + + @Test + @DataSet(value = "datasets/v2/member.yml", cleanBefore = true, cleanAfter = true) + void logout_success() throws Exception { + + TokenPair tokenPair = genTokenPair(1L); + + tokenService.invalidateRefreshToken(tokenPair.getRefreshToken()); + + RefreshToken refreshToken = refreshTokenRepository.findByMemberId(1L).orElseThrow(); + + assertNotNull(refreshTokenBlackListRepository.findByRefreshTokenId(refreshToken.getId())); + } + + private TokenPair genTokenPair(Long memberId) { + Member member = memberRepository.findById(memberId).orElseThrow(); + return jwtTokenProvider.generateTokenPair(member); + } +}