diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index 205ce15..63a8124 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -23,7 +23,7 @@ include::{snippets}/api/v1/oauth/jwt/google/http-response.adoc[] .response fields include::{snippets}/api/v1/oauth/jwt/google/response-fields.adoc[] -== POST /api/v1/oauth/jwt/kakao +== POST /api/v1/oauth/jwt/kakao - 로그인 .request include::{snippets}/api/v1/oauth/jwt/kakao/http-request.adoc[] @@ -37,6 +37,20 @@ include::{snippets}/api/v1/oauth/jwt/kakao/http-response.adoc[] .response fields include::{snippets}/api/v1/oauth/jwt/kakao/response-fields.adoc[] +== POST /api/v1/oauth/jwt/kakao - 가입필요 + +.request +include::{snippets}/api/v1/oauth/jwt/kakao/notjoin/http-request.adoc[] + +.request fields +include::{snippets}/api/v1/oauth/jwt/kakao/notjoin/request-fields.adoc[] + +.response +include::{snippets}/api/v1/oauth/jwt/kakao/notjoin/http-response.adoc[] + +.response fields +include::{snippets}/api/v1/oauth/jwt/kakao/notjoin/response-fields.adoc[] + == POST /api/v1/oauth/jwt/naver .request @@ -65,6 +79,20 @@ include::{snippets}/api/v1/oauth/jwt/get/naver/http-response.adoc[] .response fields include::{snippets}/api/v1/oauth/jwt/get/naver/response-fields.adoc[] +== POST /api/v1/oauth/join/kakao + +.request +include::{snippets}/api/v1/oauth/join/kakao/http-request.adoc[] + +.request fields +include::{snippets}/api/v1/oauth/join/kakao/request-fields.adoc[] + +.response +include::{snippets}/api/v1/oauth/join/kakao/http-response.adoc[] + +.response fields +include::{snippets}/api/v1/oauth/join/kakao/response-fields.adoc[] + = 사용자 == GET /api/v1/member/me @@ -81,16 +109,16 @@ include::{snippets}/api/v1/member/me/get/response-fields.adoc[] == GET /api/v1/member .request -include::{snippets}/api/v1/member/http-request.adoc[] +include::{snippets}/api/v1/member/get/http-request.adoc[] .request parameters -include::{snippets}/api/v1/member/request-parameters.adoc[] +include::{snippets}/api/v1/member/get/request-parameters.adoc[] .response -include::{snippets}/api/v1/member/http-response.adoc[] +include::{snippets}/api/v1/member/get/http-response.adoc[] .response fields -include::{snippets}/api/v1/member/response-fields.adoc[] +include::{snippets}/api/v1/member/get/response-fields.adoc[] == PATCH /api/v1/member/me diff --git a/src/main/java/com/meme/ala/common/message/ResponseMessage.java b/src/main/java/com/meme/ala/common/message/ResponseMessage.java index 1e1e21c..4fe5d0e 100644 --- a/src/main/java/com/meme/ala/common/message/ResponseMessage.java +++ b/src/main/java/com/meme/ala/common/message/ResponseMessage.java @@ -11,6 +11,7 @@ public class ResponseMessage { public static final String UPDATE = "update"; public static final String DELETED = "deleted"; public static final String SUBMITTED = "submitted"; + public static final String USER_NOT_JOINED = "회원 가입이 필요합니다"; // friend public static final String READ_MEMBER_FRIENDS = "사용자 친구 목록을 조회합니다."; diff --git a/src/main/java/com/meme/ala/core/auth/controller/MemberAuthController.java b/src/main/java/com/meme/ala/core/auth/controller/MemberAuthController.java index c308675..ab3e81c 100644 --- a/src/main/java/com/meme/ala/core/auth/controller/MemberAuthController.java +++ b/src/main/java/com/meme/ala/core/auth/controller/MemberAuthController.java @@ -5,8 +5,6 @@ import com.meme.ala.core.auth.jwt.JwtProvider; import com.meme.ala.core.auth.oauth.model.OAuthUserInfo; import com.meme.ala.core.auth.oauth.service.OAuthService; -import com.meme.ala.domain.member.model.dto.JwtVO; -import com.meme.ala.domain.member.service.MemberAuthService; import com.meme.ala.domain.member.service.MemberService; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; @@ -21,7 +19,6 @@ @RestController public class MemberAuthController { private final MemberService memberService; - private final MemberAuthService memberAuthService; private final OAuthService oAuthService; private final JwtProvider jwtProvider; @@ -34,11 +31,11 @@ public ResponseEntity> jwtCreate(@RequestBody Map> jwtCreate(@RequestBody Map> jwtNaverCreate(@RequestParam(required = false) String access_token) { - JwtVO result = memberAuthService.tokenTojwt(access_token); + @PostMapping("/join/{provider}") + public ResponseEntity> joinJwt(@RequestBody Map data, + @PathVariable("provider") String provider) { + Map oAuthMap = new HashMap<>(); + OAuthUserInfo authUserInfo = oAuthService.getMemberByProvider(data, provider); + oAuthMap.put("message", ResponseMessage.JOIN); + memberService.join(authUserInfo, provider, data.get("nickname").toString()); + oAuthMap.put("jwt", jwtProvider.createToken(authUserInfo.getProviderId())); return ResponseEntity .status(HttpStatus.OK) - .body(ResponseDto.of(HttpStatus.OK, result.getMessage(), result.getJwt())); + .body(ResponseDto.of(HttpStatus.OK, oAuthMap.get("message"), oAuthMap.get("jwt"))); } } \ No newline at end of file diff --git a/src/main/java/com/meme/ala/domain/member/service/MemberAuthService.java b/src/main/java/com/meme/ala/domain/member/service/MemberAuthService.java deleted file mode 100644 index 69ce521..0000000 --- a/src/main/java/com/meme/ala/domain/member/service/MemberAuthService.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.meme.ala.domain.member.service; - -import com.meme.ala.common.message.ResponseMessage; -import com.meme.ala.common.utils.NaverOauthUtil; -import com.meme.ala.core.auth.jwt.JwtProvider; -import com.meme.ala.core.auth.oauth.model.OAuthProvider; -import com.meme.ala.core.auth.oauth.model.OAuthUserInfo; -import com.meme.ala.domain.member.model.dto.JwtVO; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@RequiredArgsConstructor -@Service -public class MemberAuthService { - private final MemberService memberService; - private final JwtProvider jwtProvider; - - public JwtVO tokenTojwt(String accessToken) { - OAuthUserInfo authUserInfo = NaverOauthUtil.naverTokenToNaverUser(accessToken); - String message; - if (!memberService.existsProviderId(authUserInfo.getProviderId())) { - message = ResponseMessage.JOIN; - memberService.join(authUserInfo, OAuthProvider.NAVER); - } else - message = ResponseMessage.LOGIN; - String jwt = jwtProvider.createToken(authUserInfo.getProviderId()); - return new JwtVO(message, jwt); - } -} diff --git a/src/main/java/com/meme/ala/domain/member/service/MemberService.java b/src/main/java/com/meme/ala/domain/member/service/MemberService.java index 29c3963..28283d7 100644 --- a/src/main/java/com/meme/ala/domain/member/service/MemberService.java +++ b/src/main/java/com/meme/ala/domain/member/service/MemberService.java @@ -9,7 +9,7 @@ public interface MemberService { boolean existsProviderId(String providerId); - String join(OAuthUserInfo authUserInfo, String provider); + String join(OAuthUserInfo authUserInfo, String provider, String nickname); void updateMember(Member newMember, MemberPrincipalDto memberPrincipalDto); diff --git a/src/main/java/com/meme/ala/domain/member/service/MemberServiceImpl.java b/src/main/java/com/meme/ala/domain/member/service/MemberServiceImpl.java index 5f40f09..5863368 100644 --- a/src/main/java/com/meme/ala/domain/member/service/MemberServiceImpl.java +++ b/src/main/java/com/meme/ala/domain/member/service/MemberServiceImpl.java @@ -36,7 +36,7 @@ public boolean existsProviderId(String providerId) { @Override @PublishEvent @Transactional - public String join(OAuthUserInfo authUserInfo, String provider) { + public String join(OAuthUserInfo authUserInfo, String provider, String nickname) { int newNumber = 0; if (memberRepository.count() != 0) { try { diff --git a/src/test/java/com/meme/ala/core/auth/controller/MemberAuthControllerTest.java b/src/test/java/com/meme/ala/core/auth/controller/MemberAuthControllerTest.java index 255bef2..7baa5b6 100644 --- a/src/test/java/com/meme/ala/core/auth/controller/MemberAuthControllerTest.java +++ b/src/test/java/com/meme/ala/core/auth/controller/MemberAuthControllerTest.java @@ -2,15 +2,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.meme.ala.common.AbstractControllerTest; -import com.meme.ala.common.utils.NaverOauthUtil; import com.meme.ala.core.auth.jwt.JwtProvider; import com.meme.ala.core.auth.oauth.model.GoogleUser; import com.meme.ala.core.auth.oauth.model.KakaoUser; import com.meme.ala.core.auth.oauth.model.NaverUser; import com.meme.ala.core.auth.oauth.model.OAuthProvider; import com.meme.ala.core.auth.oauth.service.OAuthService; -import com.meme.ala.domain.member.model.dto.JwtVO; -import com.meme.ala.domain.member.service.MemberAuthService; import com.meme.ala.domain.member.service.MemberService; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -27,9 +24,6 @@ import static org.mockito.Mockito.when; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.payload.PayloadDocumentation.*; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -46,13 +40,10 @@ public class MemberAuthControllerTest extends AbstractControllerTest { @MockBean private JwtProvider jwtProvider; - @MockBean - private MemberAuthService memberAuthService; - @Autowired private ObjectMapper objectMapper; - @DisplayName("구글 OAuth 로그인/가입 테스트") + @DisplayName("구글 OAuth 로그인 테스트") @Test public void 구글_OAuth_로그인_유닛테스트() throws Exception { String sampleRequestBody = @@ -101,7 +92,7 @@ public class MemberAuthControllerTest extends AbstractControllerTest { )); } - @DisplayName("카카오 OAuth 로그인/가입 테스트") + @DisplayName("카카오 OAuth 로그인 테스트") @Test public void 카카오_OAuth_로그인_유닛테스트() throws Exception { String sampleRequestBody = @@ -146,6 +137,49 @@ public class MemberAuthControllerTest extends AbstractControllerTest { )); } + @DisplayName("카카오 OAuth 이미 가입 테스트") + @Test + public void 카카오_OAuth_이미가입_유닛테스트() throws Exception { + String sampleRequestBody = + "{\n" + + " \"profileObj\": {\n" + + " \"kakaoId\": \"1155\",\n" + + " \"imageUrl\": \"https://user-images.githubusercontent.com/46064193/125324764-2bc8e200-e37b-11eb-8d07-9ac29d0d1b1a.png\",\n" + + " \"email\": \"test@gmail.com\",\n" + + " \"name\": \"Jongmin Jung\"\n" + + " }\n" + + "}"; + + Map data = objectMapper.readValue(sampleRequestBody, Map.class); + + when(oAuthService.getMemberByProvider(new ObjectMapper().readValue(sampleRequestBody, Map.class), OAuthProvider.KAKAO)).thenReturn(new KakaoUser(data)); + + when(memberService.existsProviderId(any())).thenReturn(Boolean.FALSE); + + mockMvc.perform(post("/api/v1/oauth/jwt/kakao") + .contentType(MediaType.APPLICATION_JSON) + .content(sampleRequestBody)) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.data").value("회원 가입이 필요합니다")) + .andDo(print()) + .andDo(document("api/v1/oauth/jwt/kakao/notjoin", + getDocumentRequest(), + getDocumentResponse(), + requestFields( + fieldWithPath("profileObj.kakaoId").description("Identifier"), + fieldWithPath("profileObj.imageUrl").description("사용자 프로필 링크"), + fieldWithPath("profileObj.email").description("사용자 이메일"), + fieldWithPath("profileObj.name").description("사용자 이름") + ), + responseFields( + fieldWithPath("status").description("응답 상태"), + fieldWithPath("message").description("가입되지 않음"), + fieldWithPath("data").description("가입되지 않음"), + fieldWithPath("timestamp").description("타임스탬프") + ) + )); + } + @Test public void 네이버_OAuth_로그인_유닛테스트() throws Exception { String sampleRequestBody = @@ -187,30 +221,38 @@ public class MemberAuthControllerTest extends AbstractControllerTest { )); } + @DisplayName("카카오 가입 테스트") @Test - public void 네이버_OAuth_GET_유닛테스트() throws Exception { - String sampleAccessToken = "AAAAO9t3lY18fHzDi0xlDmoRPNNndkqUfYN7zSMAP17vAYOwxyKIHpKzeN6VxRSG7cfvA8hytclT2nydGBd8qiLCJKM"; - String sampleRequestBody = - " {\n" + - " \"id\": \"afdasfdadsf\",\n" + - " \"profile_image\": \"https://user-images.githubusercontent.com/46064193/125324764-2bc8e200-e37b-11eb-8d07-9ac29d0d1b1a.png\",\n" + - " \"email\": \"test@gmail.com\",\n" + - " \"name\": \"Jongmin Jung\"}"; - + public void 회원가입() throws Exception { + String sampleRequestBody = "{\n" + + " \"nickname\": \"babojjm\",\n" + + " \"profileObj\": {\n" + + " \"kakaoId\": \"1155\",\n" + + " \"imageUrl\": \"https://user-images.githubusercontent.com/46064193/125324764-2bc8e200-e37b-11eb-8d07-9ac29d0d1b1a.png\",\n" + + " \"email\": \"test@gmail.com\",\n" + + " \"name\": \"Jongmin Jung\"\n" + + " }\n" + + "}"; Map data = objectMapper.readValue(sampleRequestBody, Map.class); - when(memberAuthService.tokenTojwt(any())).thenReturn(new JwtVO(OAuthProvider.NAVER, "dummy token")); + when(oAuthService.getMemberByProvider(new ObjectMapper().readValue(sampleRequestBody, Map.class), OAuthProvider.KAKAO)).thenReturn(new KakaoUser(data)); + when(jwtProvider.createToken(any())).thenReturn("dummy token"); - mockMvc.perform(get("/api/v1/oauth/jwt/naver") - .param("access_token", sampleAccessToken)) + mockMvc.perform(post("/api/v1/oauth/join/kakao") + .contentType(MediaType.APPLICATION_JSON) + .content(sampleRequestBody)) .andExpect(status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath("$.data").value("dummy token")) .andDo(print()) - .andDo(document("api/v1/oauth/jwt/get/naver", + .andDo(document("api/v1/oauth/join/kakao", getDocumentRequest(), getDocumentResponse(), - requestParameters( - parameterWithName("access_token").description("네이버 액세스 토큰") + requestFields( + fieldWithPath("nickname").description("설정할 닉네임"), + fieldWithPath("profileObj.kakaoId").description("Identifier"), + fieldWithPath("profileObj.imageUrl").description("사용자 프로필 링크"), + fieldWithPath("profileObj.email").description("사용자 이메일"), + fieldWithPath("profileObj.name").description("사용자 이름") ), responseFields( fieldWithPath("status").description("응답 상태"), diff --git a/src/test/java/com/meme/ala/domain/member/controller/MemberControllerTest.java b/src/test/java/com/meme/ala/domain/member/controller/MemberControllerTest.java index 4d9fdb9..c2270dc 100644 --- a/src/test/java/com/meme/ala/domain/member/controller/MemberControllerTest.java +++ b/src/test/java/com/meme/ala/domain/member/controller/MemberControllerTest.java @@ -5,8 +5,8 @@ import com.meme.ala.core.config.AlaWithAccount; import com.meme.ala.domain.member.model.entity.Member; import com.meme.ala.domain.member.repository.MemberRepository; -import com.meme.ala.domain.member.service.MemberService; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import org.mockito.AdditionalAnswers; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.mock.mockito.MockBean; @@ -17,11 +17,9 @@ import static com.meme.ala.core.config.ApiDocumentUtils.getDocumentRequest; import static com.meme.ala.core.config.ApiDocumentUtils.getDocumentResponse; - import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.payload.PayloadDocumentation.*; @@ -42,7 +40,7 @@ public class MemberControllerTest extends AbstractControllerTest { @AlaWithAccount("test@gmail.com") @DisplayName("내 세팅 정보를 읽어오는 테스트") @Test - public void 내_세팅_정보를_읽기_유닛테스트() throws Exception{ + public void 내_세팅_정보를_읽기_유닛테스트() throws Exception { mockMvc.perform(get("/api/v1/member/me")) .andExpect(status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath("$.data.nickname").value("testNickname")) @@ -68,14 +66,14 @@ public class MemberControllerTest extends AbstractControllerTest { @AlaWithAccount("test@gmail.com") @DisplayName("사용자 세팅 정보를 읽어오는 테스트") @Test - public void 사용자_세팅_정보를_읽기_유닛테스트() throws Exception{ + public void 사용자_세팅_정보를_읽기_유닛테스트() throws Exception { given(memberRepository.findByMemberSettingNicknameAndMemberSetting_IsDeleted(any(String.class), eq(false))).willReturn(Optional.of(EntityFactory.testMember())); mockMvc.perform(get("/api/v1/member").param("nickname", "testNickname")) .andExpect(status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath("$.data.nickname").value("testNickname")) .andDo(print()) - .andDo(document("api/v1/member", + .andDo(document("api/v1/member/get", getDocumentRequest(), getDocumentResponse(), requestParameters( @@ -99,8 +97,8 @@ public class MemberControllerTest extends AbstractControllerTest { @AlaWithAccount("test@gmail.com") @DisplayName("사용자 세팅 정보 업데이트 테스트") @Test - public void 사용자_세팅_정보_업데이트_테스트() throws Exception{ - String sampleRequestBody= + public void 사용자_세팅_정보_업데이트_테스트() throws Exception { + String sampleRequestBody = " {\n" + " \"nickname\": \"alala\", \n" + " \"statusMessage\": \"update status message\", \n" + @@ -110,9 +108,9 @@ public class MemberControllerTest extends AbstractControllerTest { when(memberRepository.save(any(Member.class))).then(AdditionalAnswers.returnsFirstArg()); mockMvc.perform(patch("/api/v1/member/me") - .content(sampleRequestBody) - .contentType(MediaType.APPLICATION_JSON) - ) + .content(sampleRequestBody) + .contentType(MediaType.APPLICATION_JSON) + ) .andExpect(status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath("$.data.nickname").value("alala")) .andExpect(MockMvcResultMatchers.jsonPath("$.data.statusMessage").value("update status message")) @@ -144,7 +142,7 @@ public class MemberControllerTest extends AbstractControllerTest { @DisplayName("사용자 닉네임 중복 처리 테스트") @Test - public void 사용자_닉네임_중복_처리_테스트() throws Exception{ + public void 사용자_닉네임_중복_처리_테스트() throws Exception { when(memberRepository.existsMemberByMemberSettingNicknameAndMemberSetting_IsDeleted("testNickname", false)).thenReturn(true); mockMvc.perform(get("/api/v1/member/exists?nickname=testNickname")) @@ -165,18 +163,18 @@ public class MemberControllerTest extends AbstractControllerTest { ) )); } - + @AlaWithAccount("test") @DisplayName("사용자 삭제 테스트") @Test - public void 사용자_삭제_테스트() throws Exception{ + public void 사용자_삭제_테스트() throws Exception { given(memberRepository.save(any(Member.class))).willReturn(EntityFactory.testMember()); mockMvc.perform(delete("/api/v1/member")) .andExpect(status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath("$.data").value("deleted")) .andDo(print()) - .andDo(document("api/v1/member", + .andDo(document("api/v1/member/delete", getDocumentRequest(), getDocumentResponse(), responseFields( @@ -190,10 +188,10 @@ public class MemberControllerTest extends AbstractControllerTest { @DisplayName("사용자 닉네임으로 셀렉뷰 공유 링크") @Test - public void 사용자_닉네임으로_셀렉뷰_공유_링크() throws Exception{ + public void 사용자_닉네임으로_셀렉뷰_공유_링크() throws Exception { mockMvc.perform(get("/api/v1/member/sharelink?nickname=testNickname")) .andExpect(status().isOk()) - .andExpect(MockMvcResultMatchers.jsonPath("$.data").value(frontUrl+"select/"+"testNickname")) + .andExpect(MockMvcResultMatchers.jsonPath("$.data").value(frontUrl + "select/" + "testNickname")) .andDo(print()) .andDo(document("api/v1/member/sharelink", getDocumentRequest(), @@ -212,10 +210,10 @@ public class MemberControllerTest extends AbstractControllerTest { @DisplayName("사용자 닉네임으로 마이페이지 공유 링크") @Test - public void 사용자_닉네임으로_마이페이지_공유_링크() throws Exception{ + public void 사용자_닉네임으로_마이페이지_공유_링크() throws Exception { mockMvc.perform(get("/api/v1/member/mypagelink?nickname=testNickname")) .andExpect(status().isOk()) - .andExpect(MockMvcResultMatchers.jsonPath("$.data").value(frontUrl+"mypage/"+"testNickname")) + .andExpect(MockMvcResultMatchers.jsonPath("$.data").value(frontUrl + "mypage/" + "testNickname")) .andDo(print()) .andDo(document("api/v1/member/mypagelink", getDocumentRequest(),