Skip to content

Commit

Permalink
feat: 가입된 유저라면 201 OK 반환, 가입되지 않은 유저라면 302 FOUND 반환
Browse files Browse the repository at this point in the history
  • Loading branch information
70825 committed Jul 28, 2023
1 parent 3a1fe6b commit 1e81060
Show file tree
Hide file tree
Showing 12 changed files with 245 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.funeat.auth.application;

import com.funeat.auth.dto.SignUserDto;
import com.funeat.auth.dto.UserInfoDto;
import com.funeat.auth.util.PlatformUserProvider;
import com.funeat.member.application.MemberService;
import com.funeat.member.domain.Member;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -19,9 +19,13 @@ public AuthService(final MemberService memberService, final PlatformUserProvider
this.platformUserProvider = platformUserProvider;
}

public Long loginWithKakao(final String code) {
public SignUserDto loginWithKakao(final String code) {
final UserInfoDto userInfoDto = platformUserProvider.getPlatformUser(code);
final Member member = memberService.findOrCreateMember(userInfoDto);
return member.getId();
final SignUserDto signUserDto = memberService.findOrCreateMember(userInfoDto);
return signUserDto;
}

public String getLoginRedirectUri() {
return platformUserProvider.getRedirectURI();
}
}
26 changes: 26 additions & 0 deletions backend/src/main/java/com/funeat/auth/dto/SignUserDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.funeat.auth.dto;

import com.funeat.member.domain.Member;

public class SignUserDto {

private final boolean isSignIn;
private final Member member;

public SignUserDto(final boolean isSignIn, final Member member) {
this.isSignIn = isSignIn;
this.member = member;
}

public static SignUserDto of(final boolean isSignIn, final Member member) {
return new SignUserDto(isSignIn, member);
}

public boolean isSignIn() {
return isSignIn;
}

public Member getMember() {
return member;
}
}
6 changes: 6 additions & 0 deletions backend/src/main/java/com/funeat/auth/dto/UserInfoDto.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.funeat.auth.dto;

import com.funeat.member.domain.Member;

public class UserInfoDto {

private final Long id;
Expand All @@ -20,6 +22,10 @@ public static UserInfoDto from(final KakaoUserInfoDto kakaoUserInfoDto) {
);
}

public Member toMember() {
return new Member(this.nickname, this.profileImageUrl, this.id.toString());
}

public Long getId() {
return id;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.funeat.auth.presentation;

import com.funeat.auth.application.AuthService;
import com.funeat.auth.dto.SignUserDto;
import java.net.URI;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
Expand All @@ -16,11 +19,27 @@ public AuthController(final AuthService authService) {
this.authService = authService;
}

@GetMapping("/api/auth/kakao")
public ResponseEntity<Void> kakaoLogin() {
return ResponseEntity.status(HttpStatus.FOUND)
.location(URI.create(authService.getLoginRedirectUri()))
.build();
}

@GetMapping("/login/oauth2/code/kakao")
public ResponseEntity<Void> kakaoLogin(@RequestParam("code") final String code,
final HttpServletRequest request) {
final Long memberId = authService.loginWithKakao(code);
public ResponseEntity<Void> loginAuthorizeUser(@RequestParam("code") final String code,
final HttpServletRequest request) {
final SignUserDto signUserDto = authService.loginWithKakao(code);
final Long memberId = signUserDto.getMember().getId();
request.getSession().setAttribute("member", memberId);
return ResponseEntity.ok().build();

if (signUserDto.isSignIn()) {
return ResponseEntity.status(HttpStatus.FOUND)
.location(URI.create("/"))
.build();
}
return ResponseEntity.status(HttpStatus.FOUND)
.location(URI.create("/profile"))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.funeat.auth.dto.KakaoTokenDto;
import com.funeat.auth.dto.KakaoUserInfoDto;
import com.funeat.auth.dto.UserInfoDto;
import java.util.StringJoiner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Profile;
Expand Down Expand Up @@ -98,9 +99,7 @@ private ResponseEntity<String> requestKakaoUserInfo(final String accessToken) {
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

final HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(null, headers);
ResponseEntity<String> response = restTemplate.postForEntity(RESOURCE_BASE_URL + USER_INFO_URI, request,
String.class);
return response;
return restTemplate.postForEntity(RESOURCE_BASE_URL + USER_INFO_URI, request, String.class);
}

private KakaoUserInfoDto convertJsonToKakaoUserDto(final String responseBody) {
Expand All @@ -110,4 +109,14 @@ private KakaoUserInfoDto convertJsonToKakaoUserDto(final String responseBody) {
throw new IllegalArgumentException();
}
}

@Override
public String getRedirectURI() {
final StringJoiner joiner = new StringJoiner("&");
joiner.add("response_type=code");
joiner.add("client_id=" + kakaoRestApiKey);
joiner.add("redirect_uri=" + redirectUri);

return AUTHORIZATION_BASE_URL + "?" + joiner;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@
public interface PlatformUserProvider {

UserInfoDto getPlatformUser(final String code);

String getRedirectURI();
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.funeat.member.application;

import com.funeat.auth.dto.SignUserDto;
import com.funeat.auth.dto.UserInfoDto;
import com.funeat.member.domain.Member;
import com.funeat.member.persistence.MemberRepository;
Expand All @@ -16,21 +17,19 @@ public MemberService(final MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}

public Member findOrCreateMember(final UserInfoDto userInfoDto) {
public SignUserDto findOrCreateMember(final UserInfoDto userInfoDto) {
final String platformId = userInfoDto.getId().toString();

return memberRepository.findByPlatformId(platformId)
.map(value -> SignUserDto.of(false, value))
.orElseGet(() -> save(userInfoDto));
}

@Transactional
public Member save(final UserInfoDto userInfoDto) {
final String nickname = userInfoDto.getNickname();
final String profileImage = userInfoDto.getProfileImageUrl();
final String platformId = userInfoDto.getId().toString();

final Member member = new Member(nickname, profileImage, platformId);
public SignUserDto save(final UserInfoDto userInfoDto) {
final Member member = userInfoDto.toMember();
memberRepository.save(member);

return memberRepository.save(member);
return SignUserDto.of(true, member);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.funeat.acceptance.auth;

import static io.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.assertThat;

import com.funeat.acceptance.common.AcceptanceTest;
import com.funeat.auth.application.AuthService;
import io.restassured.response.ExtractableResponse;
import io.restassured.response.Response;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

@SuppressWarnings("NonAsciiCharacters")
public class AuthAcceptanceTest extends AcceptanceTest {

@Autowired
private AuthService authService;

@Test
void 유저가_카카오_로그인_버튼을_누르면_카카오_로그인_페이지로_리다이렉트할__있다() {
// given
final var response = 카카오_로그인_버튼_클릭();
final var expected = authService.getLoginRedirectUri();

// when
final String actual = response.header("Location");

// then
assertThat(actual).isEqualTo(expected);
}

private ExtractableResponse<Response> 카카오_로그인_버튼_클릭() {
return given()
.redirects().follow(false)
.when()
.get("/api/auth/kakao")
.then()
.extract();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,9 @@ public class TestPlatformUserProvider implements PlatformUserProvider {
public UserInfoDto getPlatformUser(final String code) {
return new UserInfoDto(1L, "test", "https://www.test.com");
}

@Override
public String getRedirectURI() {
return "https://www.test.com";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.funeat.auth.application;

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

import com.funeat.auth.dto.SignUserDto;
import com.funeat.common.DataClearExtension;
import com.funeat.member.domain.Member;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@SpringBootTest
@ExtendWith(DataClearExtension.class)
@SuppressWarnings("NonAsciiCharacters")
@DisplayNameGeneration(ReplaceUnderscores.class)
public class AuthServiceTest {

@Autowired
private AuthService authService;

@Test
void 카카오_로그인을_하여_유저_정보를_가져온다() {
// given
final var code = "test";
final var member = new Member("test", "https://www.test.com", "1");
final var expected = SignUserDto.of(true, member);

// when
final var actual = authService.loginWithKakao(code);

// then
assertThat(actual).usingRecursiveComparison()
.ignoringFields("member.id")
.isEqualTo(expected);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.funeat.auth.presentation;

import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.funeat.auth.application.AuthService;
import com.funeat.auth.dto.SignUserDto;
import com.funeat.member.domain.Member;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;

@WebMvcTest(AuthController.class)
@SuppressWarnings("NonAsciiCharacters")
public class AuthControllerTest {

@Autowired
private MockMvc mockMvc;

@MockBean
private AuthService authService;

@Nested
class loginAuthorizeUser_테스트 {

@Test
void 이미_가입된_유저라면__경로로_리다이렉트한다() throws Exception {
// given
final var code = "test";
final var member = new Member("test", "www.test.com", "1");
final var signUserDto = SignUserDto.of(true, member);

// when
when(authService.loginWithKakao(code)).thenReturn(signUserDto);

// then
mockMvc.perform(get("/login/oauth2/code/kakao")
.param("code", code))
.andExpect(status().isFound())
.andExpect(redirectedUrl("/"));
}

@Test
void 입되지_않은_유저라면_프로필_경로로_리다이렉트한다() throws Exception {
// given
final var code = "test";
final var member = new Member("test", "www.test.com", "1");
final var signUserDto = SignUserDto.of(false, member);

// when
when(authService.loginWithKakao(code)).thenReturn(signUserDto);

// then
mockMvc.perform(get("/login/oauth2/code/kakao")
.param("code", code))
.andExpect(status().isFound())
.andExpect(redirectedUrl("/profile"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import com.funeat.common.DataClearExtension;
import com.funeat.member.domain.Member;
import com.funeat.member.persistence.MemberRepository;
import org.assertj.core.api.SoftAssertions;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores;
import org.junit.jupiter.api.Nested;
Expand Down Expand Up @@ -44,7 +46,10 @@ class findOrCreateMember_테스트 {
final var actual = memberService.findOrCreateMember(userInfoDto);

// then
assertThat(expected).containsExactly(actual);
SoftAssertions.assertSoftly(softAssertions -> {
Assertions.assertFalse(actual.isSignIn());
assertThat(expected).containsExactly(actual.getMember());
});
}

@Test
Expand All @@ -60,7 +65,10 @@ class findOrCreateMember_테스트 {
final var actual = memberService.findOrCreateMember(userInfoDto);

// then
assertThat(expected).doesNotContain(actual);
SoftAssertions.assertSoftly(softAssertions -> {
Assertions.assertTrue(actual.isSignIn());
assertThat(expected).doesNotContain(actual.getMember());
});
}
}
}

0 comments on commit 1e81060

Please sign in to comment.