Skip to content

Commit

Permalink
Merge pull request #56 from dnd-side-project/feat/#55
Browse files Browse the repository at this point in the history
#55 회원 탈퇴 변경
  • Loading branch information
min-0 authored Oct 17, 2024
2 parents 0f793b6 + 9101b01 commit ad12856
Show file tree
Hide file tree
Showing 13 changed files with 43 additions and 57 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ jobs:
- name: Upload to AWS S3
run: |
aws deploy push \
--application-name ${{ env.AWS_CODE_DEPLOY_APPLICATION }} \
--ignore-hidden-files \
--s3-location s3://$AWS_S3_BUCKET/cicdtest/$GITHUB_SHA.zip \
--source .
--application-name ${{ env.AWS_CODE_DEPLOY_APPLICATION }} \
--ignore-hidden-files \
--s3-location s3://$AWS_S3_BUCKET/cicdtest/$GITHUB_SHA.zip \
--source .
#업로드된 ZIP 파일을 CodeDeploy로 배포
- name: AWS Code Deploy
run: |
Expand Down
4 changes: 2 additions & 2 deletions appspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ os: linux
files:
- source: / # 인스턴스에 복사할 디렉터리 경로
destination: /home/ec2-user/mapddang-back # 인스턴스에서 파일이 복사되는 위치
overwrite: yes # 복사할 위치에 파일이 있는 경우 대체
overwrite: true # 복사할 위치에 파일이 있는 경우 대체

permissions:
- object: / # 권한이 지정되는 파일 or 디렉터리
Expand All @@ -18,4 +18,4 @@ hooks:

ApplicationStart: # CodeDeploy의 ApplicationStart 단계에서 실행
- location: scripts/start.sh
timeout: 60
timeout: 60
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@
import com.dnd.dndtravel.auth.controller.request.AppleWithdrawRequest;
import com.dnd.dndtravel.auth.controller.request.ReIssueTokenRequest;
import com.dnd.dndtravel.auth.controller.swagger.AuthControllerSwagger;
import com.dnd.dndtravel.auth.service.TokenDecoder;
import com.dnd.dndtravel.auth.service.dto.response.AppleIdTokenPayload;
import com.dnd.dndtravel.auth.service.AppleOAuthService;
import com.dnd.dndtravel.auth.service.JwtTokenService;
import com.dnd.dndtravel.auth.controller.request.AppleLoginRequest;
import com.dnd.dndtravel.auth.service.dto.response.AppleSocialTokenInfoResponse;
import com.dnd.dndtravel.auth.service.dto.response.TokenResponse;
import com.dnd.dndtravel.auth.service.dto.response.ReissueTokenResponse;
import com.dnd.dndtravel.config.AuthenticationMember;
import com.dnd.dndtravel.member.domain.Member;
import com.dnd.dndtravel.member.service.MemberService;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

import org.springframework.http.ResponseEntity;
Expand All @@ -29,13 +30,14 @@ public class AuthController implements AuthControllerSwagger {
@PostMapping("/login/oauth2/apple")
public ResponseEntity<TokenResponse> appleOAuthLogin(@RequestBody AppleLoginRequest appleLoginRequest) {
// 클라이언트에서 준 code 값으로 apple의 IdToken Payload를 얻어온다
AppleIdTokenPayload tokenPayload = appleOAuthService.get(appleLoginRequest.appleToken());
AppleSocialTokenInfoResponse tokenInfo = appleOAuthService.getTokenInfo(appleLoginRequest.appleToken());
AppleIdTokenPayload tokenPayload = TokenDecoder.decodePayload(tokenInfo.idToken(), AppleIdTokenPayload.class);

// apple에서 가져온 유저정보를 DB에 저장
Member member = memberService.saveMember(tokenPayload.email(), appleLoginRequest.selectedColor());

// 클라이언트와 주고받을 user token(access , refresh) 생성
TokenResponse tokenResponse = jwtTokenService.generateTokens(member.getId());
TokenResponse tokenResponse = jwtTokenService.generateTokens(member.getId(), tokenInfo.refreshToken());

// refresh token 재발급 필요시
if (tokenResponse == null) {
Expand All @@ -51,14 +53,11 @@ public ReissueTokenResponse reissueToken(@RequestBody ReIssueTokenRequest reissu
}

@DeleteMapping("/withdraw")
public void withdraw(@Valid @RequestBody AppleWithdrawRequest withdrawRequest, AuthenticationMember authenticationMember) {
// 1. Apple 서버에서 Access Token 받아오기
String accessToken = appleOAuthService.getAccessToken(withdrawRequest.authorizationCode());
public void withdraw(@RequestBody AppleWithdrawRequest withdrawRequest, AuthenticationMember authenticationMember) {
// 애플 서버에 탈퇴 요청
appleOAuthService.revoke(withdrawRequest.appleRefreshToken());

// 2. Apple 서버에 탈퇴 요청
appleOAuthService.revoke(accessToken);

// 3. 자체 회원 탈퇴 진행
// 자체 회원 탈퇴
memberService.withdrawMember(authenticationMember.id());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
클라이언트에서 서버로 보내는 요청
*/
public record AppleWithdrawRequest(
@Schema(description = "authorization code", requiredMode = REQUIRED)
@NotBlank(message = "authorization code는 필수 입니다.")
@Size(max = 300, message = "authorization code 형식이 아닙니다.")
String authorizationCode
@Schema(description = "Apple Refresh Token", requiredMode = REQUIRED)
@NotBlank(message = "appleRefreshToken은 필수 입니다.")
@Size(max = 300, message = "token 형식이 아닙니다.")
String appleRefreshToken
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@

import com.dnd.dndtravel.auth.domain.RefreshToken;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface RefreshTokenRepository extends JpaRepository<RefreshToken, Long> {
RefreshToken findByMemberId(Long memberId);

void deleteByMemberId(Long memberId);
Optional<RefreshToken> findByRefreshToken(String refreshToken);
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,6 @@ public class AppleOAuthService {
private final AppleClient appleClient;
private final AppleProperties appleProperties;

public AppleIdTokenPayload get(String authorizationCode) {
String idToken = appleClient.getIdToken(
appleProperties.getClientId(),
generateClientSecret(),
appleProperties.getGrantType(),
authorizationCode
).idToken();

return TokenDecoder.decodePayload(idToken, AppleIdTokenPayload.class);
}

private String generateClientSecret() {
LocalDateTime expiration = LocalDateTime.now().plusMinutes(5);

Expand Down Expand Up @@ -87,23 +76,22 @@ private PrivateKey getPrivateKey() {
}
}

public String getAccessToken(String authorizationCode) {
AppleSocialTokenInfoResponse tokenInfo = appleClient.getIdToken(
public AppleSocialTokenInfoResponse getTokenInfo(String authorizationCode) {
return appleClient.getIdToken(
appleProperties.getClientId(),
generateClientSecret(),
appleProperties.getGrantType(),
authorizationCode
);
return tokenInfo.accessToken();
}

public void revoke(String accessToken) {
public void revoke(String refreshToken) {
try {
appleClient.revoke(
appleProperties.getClientId(),
generateClientSecret(),
accessToken,
"access_token"
refreshToken,
"refresh_token"
);
} catch (Exception e) {
throw new AppleTokenRevokeException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ public class JwtTokenService {
private final RefreshTokenRepository refreshTokenRepository;

@Transactional
public TokenResponse generateTokens(Long memberId) {
public TokenResponse generateTokens(Long memberId, String appleRefreshToken) {
RefreshToken refreshToken = refreshTokenRepository.findByMemberId(memberId);

// 리프레시 토큰이 없는경우
if (refreshToken == null) {
String newRefreshToken = jwtProvider.refreshToken();
refreshTokenRepository.save(RefreshToken.of(memberId, newRefreshToken)); // refreshToken은 DB에 저장
return new TokenResponse(jwtProvider.accessToken(memberId), newRefreshToken);
return new TokenResponse(jwtProvider.accessToken(memberId), newRefreshToken, appleRefreshToken);
}

// 리프레시 토큰이 만료됐으면 재발급 받으라고 멘트줌
Expand All @@ -37,7 +37,7 @@ public TokenResponse generateTokens(Long memberId) {
refreshTokenRepository.delete(refreshToken);
String newRefreshToken = jwtProvider.refreshToken();
refreshTokenRepository.save(RefreshToken.of(refreshToken.getMemberId(), newRefreshToken));
return new TokenResponse(jwtProvider.accessToken(memberId), newRefreshToken);
return new TokenResponse(jwtProvider.accessToken(memberId), newRefreshToken, appleRefreshToken);
}

@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

public record TokenResponse(
String accessToken,
String refreshToken
String refreshToken,
String appleRefreshToken
) {
}
2 changes: 1 addition & 1 deletion src/main/java/com/dnd/dndtravel/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class SwaggerConfig {
public OpenAPI openAPI() {
return new OpenAPI()
.info(new Info()
.title("MAPDDANG API")
.title("MAPDDANG TEST API")
.description("맵땅 앱 관련 API")
.version("1.0.0"))
.addServersItem(new Server().url("/").description("Generated Default Server URL")) //local에서는 http, aws에서는 https로 server url 설정됨
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
import com.dnd.dndtravel.map.repository.custom.MemberAttractionRepositoryCustom;

public interface MemberAttractionRepository extends JpaRepository<MemberAttraction, Long>,
MemberAttractionRepositoryCustom {
MemberAttractionRepositoryCustom {

List<MemberAttraction> findByMemberId(long memberId);

Optional<MemberAttraction> findByIdAndMemberId(long memberAttractionId, long memberId);
List<MemberAttraction> findByMemberId(long memberId);
void deleteByMemberId(Long memberId);
Optional<MemberAttraction> findByIdAndMemberId(long memberAttractionId, long memberId);
}

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@

public interface MemberRegionRepository extends JpaRepository<MemberRegion, Long> {
List<MemberRegion> findByMemberId(Long memberId);

void deleteByMemberId(Long memberId);
MemberRegion findByMemberIdAndRegionId(Long memberId, Long regionId);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.dnd.dndtravel.member.service;

import com.dnd.dndtravel.auth.repository.RefreshTokenRepository;
import com.dnd.dndtravel.map.exception.MemberNotFoundException;
import com.dnd.dndtravel.map.repository.MemberAttractionRepository;
import com.dnd.dndtravel.map.repository.MemberRegionRepository;
import com.dnd.dndtravel.auth.service.MemberNameGenerator;
Expand All @@ -19,8 +20,8 @@ public class MemberService {
private final MemberRepository memberRepository;
private final MemberAttractionRepository memberAttractionRepository;
private final MemberRegionRepository memberRegionRepository;
private final RefreshTokenRepository refreshTokenRepository;
private final MemberNameGenerator memberNameGenerator;
private final RefreshTokenRepository refreshTokenRepository;

@Transactional
public Member saveMember(String email, String selectedColor) {
Expand All @@ -32,12 +33,12 @@ public Member saveMember(String email, String selectedColor) {
@Transactional
public void withdrawMember(long memberId) {
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new RuntimeException("Member not found"));
.orElseThrow(() -> new MemberNotFoundException(memberId));

memberAttractionRepository.deleteByMemberId(memberId);
memberRegionRepository.deleteByMemberId(memberId);
refreshTokenRepository.deleteByMemberId(memberId);
memberRepository.delete(member);
memberAttractionRepository.deleteById(memberId);
memberRegionRepository.deleteById(memberId);
refreshTokenRepository.deleteById(memberId);
}

@Transactional(readOnly = true)
Expand Down
3 changes: 1 addition & 2 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,4 @@ cloud:
stack:
auto: false
s3:
bucketName: ${AWS_BUCKET_NAME}

bucketName: ${AWS_BUCKET_NAME}

0 comments on commit ad12856

Please sign in to comment.