Skip to content

Commit

Permalink
Merge pull request #689 from woowacourse-teams/feature/#685
Browse files Browse the repository at this point in the history
회원 탈퇴 시 논리 삭제 및 재가입 로직 구현
  • Loading branch information
Mingyum-Kim authored Oct 19, 2024
2 parents c914df2 + 4b1f507 commit 051eaf6
Show file tree
Hide file tree
Showing 17 changed files with 140 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
Expand Down Expand Up @@ -58,22 +57,23 @@ public String getRefreshToken(String code) {
return response.refresh_token();
}

public void revoke(String refreshToken) {
String revokeUrl = APPLE_API_URL + "/oauth2/v2/revoke";
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("client_id", CLIENT_ID);
formData.add("client_secret", clientSecretProvider.provide());
formData.add("token", refreshToken);
formData.add("token_hint_type", "refresh_token");

ResponseEntity<String> result = restClient.method(HttpMethod.POST)
.uri(revokeUrl)
.headers(httpHeaders -> httpHeaders.addAll(getHttpHeaders()))
.body(formData)
.retrieve()
.toEntity(String.class);
log.info("revoke status code : {}", result.getStatusCode());
}
// TODO: 애플 심사 시 필요할 수 있으므로 제거하지 않습니다.
// public void revoke(String refreshToken) {
// String revokeUrl = APPLE_API_URL + "/oauth2/v2/revoke";
// MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
// formData.add("client_id", CLIENT_ID);
// formData.add("client_secret", clientSecretProvider.provide());
// formData.add("token", refreshToken);
// formData.add("token_hint_type", "refresh_token");
//
// ResponseEntity<String> result = restClient.method(HttpMethod.POST)
// .uri(revokeUrl)
// .headers(httpHeaders -> httpHeaders.addAll(getHttpHeaders()))
// .body(formData)
// .retrieve()
// .toEntity(String.class);
// log.info("revoke status code : {}", result.getStatusCode());
// }

private MultiValueMap<String, String> getFormData(String code) {
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import mouda.backend.auth.Infrastructure.AppleOauthClient;
import mouda.backend.auth.exception.AuthErrorMessage;
import mouda.backend.auth.exception.AuthException;
import mouda.backend.auth.implement.AppleOauthManager;
import mouda.backend.auth.implement.LoginManager;
import mouda.backend.auth.implement.jwt.AccessTokenProvider;
import mouda.backend.auth.presentation.controller.AppleUserInfoRequest;
import mouda.backend.member.domain.LoginDetail;
Expand All @@ -26,13 +24,11 @@
@RequiredArgsConstructor
public class AppleAuthService {

private final LoginManager loginManager;
private final MemberFinder memberFinder;
private final MemberWriter memberWriter;
private final AppleOauthManager appleOauthManager;
private final AccessTokenProvider accessTokenProvider;
private final ObjectMapper objectMapper;
private final AppleOauthClient appleOauthClient;

// TODO: 더 이상 사용하지 않는 로직. 로그인 프로세스 정착 후 제거할 것
// public LoginResponse oauthLogin(AppleOauthRequest oauthRequest) {
Expand All @@ -43,31 +39,36 @@ public class AppleAuthService {
// return new LoginResponse(accessToken);
// }
// LoginProcessResult result = loginManager.processAppleLogin(member);
// return new LoginResponse(result.accessToken());ap
// return new LoginResponse(result.accessToken());
// }

public String getAccessToken(String idToken) {
public String login(String idToken) {
String socialLoginId = appleOauthManager.getSocialLoginId(idToken);
Member member = memberFinder.findBySocialId(socialLoginId);
reSignup(member);
return accessTokenProvider.provide(member);
}

public void save(String code, String idToken, String user) {
String refreshToken = appleOauthClient.getRefreshToken(code);
private void reSignup(Member member) {
if (member.isDeleted()) {
member.reSignup();
}
}

public void save(String idToken, String user) {
try {
AppleUserInfoRequest request = objectMapper.readValue(user, AppleUserInfoRequest.class);
String firstName = request.name().firstName();
String lastName = request.name().lastName();
saveMember(refreshToken, idToken, firstName, lastName);
saveMember(idToken, firstName, lastName);
} catch (JsonProcessingException exception) {
throw new AuthException(HttpStatus.BAD_REQUEST, AuthErrorMessage.APPLE_USER_BAD_REQUEST);
}
}

private void saveMember(String refreshToken, String idToken, String firstName, String lastName) {
private void saveMember(String idToken, String firstName, String lastName) {
String socialLoginId = appleOauthManager.getSocialLoginId(idToken);
log.info("socialLoginId = " + socialLoginId);
Member member = new Member(lastName + firstName, new LoginDetail(OauthType.APPLE, socialLoginId, refreshToken));
Member member = new Member(lastName + firstName, new LoginDetail(OauthType.APPLE, socialLoginId));
memberWriter.append(member);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import mouda.backend.auth.implement.LoginManager;
import mouda.backend.auth.implement.jwt.AccessTokenProvider;
import mouda.backend.auth.presentation.request.OauthRequest;
import mouda.backend.auth.presentation.response.KakaoLoginResponse;
import mouda.backend.auth.presentation.response.LoginResponse;
import mouda.backend.member.domain.LoginDetail;
import mouda.backend.member.domain.Member;
Expand All @@ -28,11 +27,11 @@ public class KakaoAuthService {
private final MemberWriter memberWriter;
private final MemberFinder memberFinder;

public KakaoLoginResponse oauthLogin(OauthRequest oauthRequest) {
public LoginResponse oauthLogin(OauthRequest oauthRequest) {
String kakaoId = oauthManager.getSocialLoginId(oauthRequest.code());
LoginProcessResult loginProcessResult = loginManager.processSocialLogin(OauthType.KAKAO, kakaoId, "name");

return new KakaoLoginResponse(loginProcessResult.memberId(), loginProcessResult.accessToken());
return new LoginResponse(loginProcessResult.accessToken());
}

public LoginResponse basicLoginAnna() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package mouda.backend.auth.business.result;

public record LoginProcessResult(
Long memberId,
String accessToken
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,23 @@ public class LoginManager {

public LoginProcessResult processSocialLogin(OauthType oauthType, String socialLoginId, String name) {
Optional<Member> member = memberRepository.findByLoginDetail_SocialLoginId(socialLoginId);

return member.map(value -> {
memberWriter.updateName(value.getId(), name);
return new LoginProcessResult(value.getId(), accessTokenProvider.provide(value));
})
.orElseGet(() -> processKakaoLogin(oauthType, socialLoginId, name));

if (member.isEmpty()) {
return signup(oauthType, socialLoginId, name);
}
if (member.get().isDeleted()) {
member.get().reSignup();
memberRepository.save(member.get());
}
memberWriter.updateName(member.get().getId(), name);
return new LoginProcessResult(accessTokenProvider.provide(member.get()));
}

private LoginProcessResult processKakaoLogin(OauthType oauthType, String socialLoginId, String name) {
if (oauthType == OauthType.KAKAO) {
private LoginProcessResult signup(OauthType oauthType, String socialLoginId, String name) {
if (OauthType.KAKAO.equals(oauthType)) {
throw new AuthException(HttpStatus.BAD_REQUEST, AuthErrorMessage.KAKAO_CANNOT_SIGNUP);
}
Member newMember = Member.builder()
.name(name)
.loginDetail(new LoginDetail(oauthType, socialLoginId))
.build();
memberWriter.append(newMember);

return new LoginProcessResult(newMember.getId(), accessTokenProvider.provide(newMember));
}

public LoginProcessResult processAppleLogin(Member member) {
return new LoginProcessResult(member.getId(), accessTokenProvider.provide(member));
Member member = memberWriter.append(new Member(name, new LoginDetail(oauthType, socialLoginId)));
return new LoginProcessResult(accessTokenProvider.provide(member));
}

public String updateOauth(long memberId, OauthType oauthType, String socialLoginId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import mouda.backend.auth.Infrastructure.AppleOauthClient;
import mouda.backend.member.domain.Member;
import mouda.backend.member.domain.OauthType;
import mouda.backend.member.implement.MemberWriter;

@Slf4j
Expand All @@ -16,14 +14,9 @@
@RequiredArgsConstructor
public class CommonAuthService {

private final AppleOauthClient oauthClient;
private final MemberWriter memberWriter;

public void withdraw(Member member) {
if (OauthType.APPLE.equals(member.getOauthType())) {
log.info("revoke apple user");
oauthClient.revoke(member.getRefreshToken());
}
memberWriter.remove(member);
memberWriter.withdraw(member);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,14 @@ public class AppleAuthController {

@PostMapping("/v1/oauth/apple")
public ResponseEntity<Void> test(
@RequestParam("code") String code,
@RequestParam("id_token") String id_token,
@RequestParam(name = "user", required = false) String user
) throws IOException {
// TODO: 이전에 가입한 적 있지만 DB를 갈아엎어서 user가 들어오지 않는 경우 save에 실패한다.
if (user != null) {
appleAuthService.save(code, id_token, user);
appleAuthService.save(id_token, user);
}
String accessToken = appleAuthService.getAccessToken(id_token);
String accessToken = appleAuthService.login(id_token);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Location", "https://dev.mouda.site/oauth/apple?token=" + accessToken);
return new ResponseEntity<>(httpHeaders, HttpStatus.FOUND);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import mouda.backend.auth.presentation.controller.swagger.AuthSwagger;
import mouda.backend.auth.presentation.request.GoogleOauthRequest;
import mouda.backend.auth.presentation.request.OauthRequest;
import mouda.backend.auth.presentation.response.KakaoLoginResponse;
import mouda.backend.auth.presentation.response.LoginResponse;
import mouda.backend.common.config.argumentresolver.LoginMember;
import mouda.backend.common.response.RestResponse;
Expand All @@ -35,8 +34,8 @@ public class AuthController implements AuthSwagger {

@Override
@PostMapping("/kakao/oauth")
public ResponseEntity<RestResponse<KakaoLoginResponse>> loginKakaoOauth(@RequestBody OauthRequest oauthRequest) {
KakaoLoginResponse response = kakaoAuthService.oauthLogin(oauthRequest);
public ResponseEntity<RestResponse<LoginResponse>> loginKakaoOauth(@RequestBody OauthRequest oauthRequest) {
LoginResponse response = kakaoAuthService.oauthLogin(oauthRequest);

return ResponseEntity.ok().body(new RestResponse<>(response));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import mouda.backend.auth.presentation.request.GoogleOauthRequest;
import mouda.backend.auth.presentation.request.OauthRequest;
import mouda.backend.auth.presentation.response.KakaoLoginResponse;
import mouda.backend.auth.presentation.response.LoginResponse;
import mouda.backend.common.config.argumentresolver.LoginMember;
import mouda.backend.common.response.RestResponse;
Expand All @@ -20,7 +19,7 @@ public interface AuthSwagger {
@ApiResponses({
@ApiResponse(responseCode = "200", description = "로그인 성공!"),
})
ResponseEntity<RestResponse<KakaoLoginResponse>> loginKakaoOauth(@RequestBody OauthRequest oauthRequest);
ResponseEntity<RestResponse<LoginResponse>> loginKakaoOauth(@RequestBody OauthRequest oauthRequest);

@Operation(summary = "테스트 용 로그인(안나)", description = "테스트 용 가짜 사용자로 로그인한다(accessToken 발급).")
@ApiResponses({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package mouda.backend.auth.presentation.response;

public record KakaoLoginResponse(
Long memberId,
String accessToken
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ public class LoginDetail {

private String socialLoginId;

private String refreshToken;

protected LoginDetail() {
}

Expand All @@ -26,12 +24,6 @@ public LoginDetail(OauthType oauthType, String socialLoginId) {
this.socialLoginId = socialLoginId;
}

public LoginDetail(OauthType oauthType, String socialLoginId, String refreshToken) {
this.oauthType = oauthType;
this.socialLoginId = socialLoginId;
this.refreshToken = refreshToken;
}

@Override
public boolean equals(Object o) {
if (this == o)
Expand Down
18 changes: 16 additions & 2 deletions backend/src/main/java/mouda/backend/member/domain/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
Expand All @@ -29,11 +31,15 @@ public class Member {
@Embedded
private LoginDetail loginDetail;

@Enumerated(EnumType.STRING)
private MemberStatus memberStatus;

@Builder
public Member(String name, LoginDetail loginDetail) {
this.loginDetail = loginDetail;
validateName(name);
this.name = name;
this.memberStatus = MemberStatus.ACTIVE;
}

private void validateName(String name) {
Expand All @@ -50,8 +56,16 @@ public OauthType getOauthType() {
return loginDetail.getOauthType();
}

public String getRefreshToken() {
return loginDetail.getRefreshToken();
public void withdraw() {
this.memberStatus = MemberStatus.DELETED;
}

public boolean isDeleted() {
return MemberStatus.DELETED.equals(this.memberStatus);
}

public void reSignup() {
this.memberStatus = MemberStatus.ACTIVE;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package mouda.backend.member.domain;

public enum MemberStatus {

ACTIVE,
DELETED
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public void updateName(long memberId, String name) {
memberRepository.updateName(memberId, name);
}

public void remove(Member member) {
memberRepository.delete(member);
public void withdraw(Member member) {
member.withdraw();
memberRepository.save(member);
}
}
Loading

0 comments on commit 051eaf6

Please sign in to comment.