From 611b33a7e09fd7865c9695926ed9b9c5fb0081da Mon Sep 17 00:00:00 2001 From: CYY1007 Date: Tue, 3 Oct 2023 20:55:25 +0900 Subject: [PATCH] =?UTF-8?q?:recycle:=20Refactor=20:=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=20=EB=B0=9C=EA=B8=89=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/briefing/BriefingApplication.java | 2 + .../java/briefing/member/api/MemberApi.java | 29 +++++-- .../briefing/member/api/MemberConverter.java | 7 ++ .../application/MemberCommandService.java | 6 ++ .../application/MemberQueryService.java | 10 +++ .../member/application/dto/MemberRequest.java | 2 + .../application/dto/MemberResponse.java | 8 ++ .../domain/repository/MemberRepository.java | 2 + .../briefing/redis/service/RedisService.java | 5 +- .../redis/service/RedisServiceImpl.java | 8 +- src/main/resources/application.yml | 2 + src/main/resources/logback-spring.xml | 79 ------------------- 12 files changed, 67 insertions(+), 93 deletions(-) delete mode 100644 src/main/resources/logback-spring.xml diff --git a/src/main/java/briefing/BriefingApplication.java b/src/main/java/briefing/BriefingApplication.java index 567be3e..c78eec0 100644 --- a/src/main/java/briefing/BriefingApplication.java +++ b/src/main/java/briefing/BriefingApplication.java @@ -5,9 +5,11 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.FeignAutoConfiguration; +import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; @SpringBootApplication @EnableFeignClients +@EnableRedisRepositories @ImportAutoConfiguration({FeignAutoConfiguration.class}) public class BriefingApplication { diff --git a/src/main/java/briefing/member/api/MemberApi.java b/src/main/java/briefing/member/api/MemberApi.java index fff243c..e61315a 100644 --- a/src/main/java/briefing/member/api/MemberApi.java +++ b/src/main/java/briefing/member/api/MemberApi.java @@ -7,20 +7,25 @@ import briefing.member.application.dto.MemberResponse; import briefing.member.domain.Member; import briefing.member.domain.SocialType; +import briefing.redis.domain.RefreshToken; import briefing.redis.service.RedisService; import briefing.security.provider.TokenProvider; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.Arrays; +import java.util.List; import java.util.UUID; @Tag(name = "02-Member \uD83D\uDC64",description = "사용자 관련 API") @RestController +@Validated @RequestMapping("/members") @RequiredArgsConstructor public class MemberApi { @@ -31,6 +36,15 @@ public class MemberApi { private final RedisService redisService; + @Operation(summary = "Member\uD83D\uDC64 토큰 잘 발급되나 테스트용API", description = "테스트 용") + @GetMapping("/auth/test") + public CommonResponse testGenerateToken(){ + Member member = memberQueryService.testForTokenApi(); + String accessToken = tokenProvider.createAccessToken(member.getId(), member.getSocialType().toString() ,member.getSocialId(), Arrays.asList(new SimpleGrantedAuthority(member.getRole().name()))); + RefreshToken refreshToken = redisService.generateRefreshToken(member.getSocialId(), member.getSocialType()); + return CommonResponse.onSuccess(MemberConverter.toLoginDTO(member,accessToken, refreshToken.getToken())); + } + @Operation(summary = "02-01 Member\uD83D\uDC64 소셜 로그인 #FRAME", description = "구글, 애플 소셜로그인 API입니다.") @PostMapping("/auth/{socialType}") public CommonResponse login( @@ -40,16 +54,15 @@ public CommonResponse login( Member member = memberCommandService.login(socialType, request); // TODO - TokenProvider에서 발급해주도록 변경 String accessToken = tokenProvider.createAccessToken(member.getId(),member.getSocialType().toString() ,member.getSocialId(), Arrays.asList(new SimpleGrantedAuthority("USER"))); - String refreshToken = redisService.generateRefreshToken(member.getSocialId(),member.getSocialType()); + String refreshToken = redisService.generateRefreshToken(member.getSocialId(),member.getSocialType()).getToken(); return CommonResponse.onSuccess(MemberConverter.toLoginDTO(member, accessToken, refreshToken)); } - @Operation(summary = "토큰 잘 발급되나 테스트용API", description = "테스트 후 삭제합니다") - @GetMapping("/auth/test") - public CommonResponse testGenerateToken(){ - Member member = memberQueryService.findMember(1L); - String accessToken = tokenProvider.createAccessToken(member.getId(), member.getSocialType().toString() ,member.getSocialId(), Arrays.asList(new SimpleGrantedAuthority(member.getRole().name()))); - String refreshToken = redisService.generateRefreshToken(member.getSocialId(), member.getSocialType()); - return CommonResponse.onSuccess(MemberConverter.toLoginDTO(member,accessToken, refreshToken)); + @PostMapping("/auth/token") + public CommonResponse reissueToken(@Valid @RequestBody MemberRequest.ReissueDTO request){ + RefreshToken refreshToken = redisService.reGenerateRefreshToken(request); + Member parsedMember = memberCommandService.parseRefreshToken(refreshToken); + String accessToken = tokenProvider.createAccessToken(parsedMember.getId(),parsedMember.getSocialType().toString(), parsedMember.getSocialId(), List.of(new SimpleGrantedAuthority(parsedMember.getRole().toString()))); + return CommonResponse.onSuccess(MemberConverter.toReIssueTokenDTO(accessToken,refreshToken.getToken())); } } diff --git a/src/main/java/briefing/member/api/MemberConverter.java b/src/main/java/briefing/member/api/MemberConverter.java index 67a0479..c3b5158 100644 --- a/src/main/java/briefing/member/api/MemberConverter.java +++ b/src/main/java/briefing/member/api/MemberConverter.java @@ -39,4 +39,11 @@ public static Member toMember(String appleSocialId) { .status(MemberStatus.ACTIVE) .build(); } + + public static MemberResponse.ReIssueTokenDTO toReIssueTokenDTO(String accessToken, String refreshToken){ + return MemberResponse.ReIssueTokenDTO.builder() + .accessToken(accessToken) + .refreshToken(refreshToken) + .build(); + } } diff --git a/src/main/java/briefing/member/application/MemberCommandService.java b/src/main/java/briefing/member/application/MemberCommandService.java index c9223ba..ab3b76f 100644 --- a/src/main/java/briefing/member/application/MemberCommandService.java +++ b/src/main/java/briefing/member/application/MemberCommandService.java @@ -2,6 +2,7 @@ import briefing.exception.ErrorCode; import briefing.exception.handler.AppleOAuthException; +import briefing.exception.handler.MemberException; import briefing.feign.oauth.apple.client.AppleOauth2Client; import briefing.feign.oauth.apple.dto.ApplePublicKey; import briefing.feign.oauth.apple.dto.ApplePublicKeyList; @@ -14,6 +15,7 @@ import briefing.member.domain.MemberStatus; import briefing.member.domain.SocialType; import briefing.member.domain.repository.MemberRepository; +import briefing.redis.domain.RefreshToken; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import lombok.RequiredArgsConstructor; @@ -127,4 +129,8 @@ private PublicKey getPublicKey(ApplePublicKey applePublicKeyDTO) { throw new AppleOAuthException(ErrorCode.FAIL_TO_MAKE_APPLE_PUBLIC_KEY); } } + + public Member parseRefreshToken(RefreshToken refreshToken){ + return memberRepository.findById(refreshToken.getMemberId()).orElseThrow(() -> new MemberException(ErrorCode.MEMBER_NOT_FOUND)); + } } diff --git a/src/main/java/briefing/member/application/MemberQueryService.java b/src/main/java/briefing/member/application/MemberQueryService.java index 8cc791b..e34467c 100644 --- a/src/main/java/briefing/member/application/MemberQueryService.java +++ b/src/main/java/briefing/member/application/MemberQueryService.java @@ -1,6 +1,8 @@ package briefing.member.application; import briefing.member.domain.Member; +import briefing.member.domain.MemberRole; +import briefing.member.domain.SocialType; import briefing.member.domain.repository.MemberRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -15,4 +17,12 @@ public class MemberQueryService { public Member findMember(Long memberId){ return memberRepository.findById(memberId).get(); } + + @Transactional + public Member testForTokenApi(){ + return memberRepository.findFirstByOrderByCreatedAt().orElseGet(()-> + memberRepository.save(Member.builder().nickName(",,,!,1").socialId("1234567").socialType(SocialType.GOOGLE).role(MemberRole.ROLE_USER) + .build()) + ); + } } diff --git a/src/main/java/briefing/member/application/dto/MemberRequest.java b/src/main/java/briefing/member/application/dto/MemberRequest.java index 08996a4..d31fc0a 100644 --- a/src/main/java/briefing/member/application/dto/MemberRequest.java +++ b/src/main/java/briefing/member/application/dto/MemberRequest.java @@ -1,5 +1,6 @@ package briefing.member.application.dto; +import jakarta.validation.constraints.NotBlank; import lombok.Getter; public class MemberRequest { @@ -11,6 +12,7 @@ public static class LoginDTO { @Getter public static class ReissueDTO{ + @NotBlank private String refreshToken; } } diff --git a/src/main/java/briefing/member/application/dto/MemberResponse.java b/src/main/java/briefing/member/application/dto/MemberResponse.java index 37c1d8e..7f9539b 100644 --- a/src/main/java/briefing/member/application/dto/MemberResponse.java +++ b/src/main/java/briefing/member/application/dto/MemberResponse.java @@ -15,4 +15,12 @@ public static class LoginDTO { private String accessToken; private String refreshToken; } + + @Builder @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class ReIssueTokenDTO{ + private String accessToken; + private String refreshToken; + } } diff --git a/src/main/java/briefing/member/domain/repository/MemberRepository.java b/src/main/java/briefing/member/domain/repository/MemberRepository.java index e864d7d..dbf6935 100644 --- a/src/main/java/briefing/member/domain/repository/MemberRepository.java +++ b/src/main/java/briefing/member/domain/repository/MemberRepository.java @@ -8,4 +8,6 @@ public interface MemberRepository extends JpaRepository { Optional findBySocialIdAndSocialType(String socialId, SocialType socialType); + + Optional findFirstByOrderByCreatedAt(); } diff --git a/src/main/java/briefing/redis/service/RedisService.java b/src/main/java/briefing/redis/service/RedisService.java index e4543ce..1472a5f 100644 --- a/src/main/java/briefing/redis/service/RedisService.java +++ b/src/main/java/briefing/redis/service/RedisService.java @@ -1,15 +1,16 @@ package briefing.redis.service; import briefing.member.application.dto.MemberRequest; +import briefing.member.domain.Member; import briefing.member.domain.SocialType; import briefing.redis.domain.RefreshToken; public interface RedisService { - String generateRefreshToken(String socialId, SocialType socialType); + RefreshToken generateRefreshToken(String socialId, SocialType socialType); // accessToken 만료 시 발급 혹은 그대로 반환 - String reGenerateRefreshToken(MemberRequest.ReissueDTO request); + RefreshToken reGenerateRefreshToken(MemberRequest.ReissueDTO request); void deleteRefreshToken(String refreshToken); } diff --git a/src/main/java/briefing/redis/service/RedisServiceImpl.java b/src/main/java/briefing/redis/service/RedisServiceImpl.java index 3e84132..04aa7dd 100644 --- a/src/main/java/briefing/redis/service/RedisServiceImpl.java +++ b/src/main/java/briefing/redis/service/RedisServiceImpl.java @@ -33,7 +33,7 @@ public class RedisServiceImpl implements RedisService{ @Override @Transactional - public String generateRefreshToken(String socialId, SocialType socialType) { + public RefreshToken generateRefreshToken(String socialId, SocialType socialType) { Member member = memberRepository.findBySocialIdAndSocialType(socialId, socialType).orElseThrow(() -> new RefreshTokenException(ErrorCode.MEMBER_NOT_FOUND)); // 이 부분 괜찮은지 리뷰 @@ -50,11 +50,11 @@ public String generateRefreshToken(String socialId, SocialType socialType) { .memberId(memberId) .token(token) .expireTime(expireTime).build() - ).getToken(); + ); } @Override - public String reGenerateRefreshToken(MemberRequest.ReissueDTO request) { + public RefreshToken reGenerateRefreshToken(MemberRequest.ReissueDTO request) { if(request.getRefreshToken() == null) throw new MemberException(ErrorCode.INVALID_TOKEN_EXCEPTION); RefreshToken findRefreshToken = refreshTokenRepository.findByToken(request.getRefreshToken()).orElseThrow(() -> new RefreshTokenException(ErrorCode.INVALID_TOKEN_EXCEPTION)); @@ -73,7 +73,7 @@ public String reGenerateRefreshToken(MemberRequest.ReissueDTO request) { // 새로 발급할 accessToken보다 refreshToken이 먼저 만료 될 경우인가? if(expireTime.isAfter(expireDeadLine)) { logger.info("기존 리프레시 토큰 발급"); - return findRefreshToken.getToken(); + return findRefreshToken; } else { logger.info("accessToken보다 먼저 만료될 예정인 리프레시 토큰 발견"); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 87addba..67edbf5 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -10,6 +10,8 @@ spring: sql: init: mode: never + redis: + briefing-redis-ro.0ot2cs.ng.0001.apn2.cache.amazonaws.com jpa: properties: hibernate: diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml deleted file mode 100644 index 879b29f..0000000 --- a/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -