diff --git a/mashup-domain/src/main/java/kr/mashup/branding/repository/member/MemberGenerationRepositoryCustom.java b/mashup-domain/src/main/java/kr/mashup/branding/repository/member/MemberGenerationRepositoryCustom.java index a359f239..8bc10bc4 100644 --- a/mashup-domain/src/main/java/kr/mashup/branding/repository/member/MemberGenerationRepositoryCustom.java +++ b/mashup-domain/src/main/java/kr/mashup/branding/repository/member/MemberGenerationRepositoryCustom.java @@ -9,4 +9,6 @@ public interface MemberGenerationRepositoryCustom { Optional findByMemberIdAndGenerationNumber(Long memberId, Integer generationNumber); List findByMemberIdsAndGenerationNumber(List memberIds, Integer generationNumber); -} \ No newline at end of file + + Optional findLatestByMemberId(Long memberId); +} diff --git a/mashup-domain/src/main/java/kr/mashup/branding/repository/member/MemberGenerationRepositoryCustomImpl.java b/mashup-domain/src/main/java/kr/mashup/branding/repository/member/MemberGenerationRepositoryCustomImpl.java index 7916d602..c84d4108 100644 --- a/mashup-domain/src/main/java/kr/mashup/branding/repository/member/MemberGenerationRepositoryCustomImpl.java +++ b/mashup-domain/src/main/java/kr/mashup/branding/repository/member/MemberGenerationRepositoryCustomImpl.java @@ -35,4 +35,16 @@ public List findByMemberIdsAndGenerationNumber(List memb .where(member.id.in(memberIds), generation.number.eq(generationNumber)) .fetch(); } + + public Optional findLatestByMemberId(Long memberId) { + return Optional.ofNullable(queryFactory + .selectFrom(memberGeneration) + .join(memberGeneration.member, member) + .join(memberGeneration.generation, generation) + .where(member.id.eq(memberId)) + .orderBy(generation.number.desc()) + .limit(1) + .fetchFirst() + ); + } } diff --git a/mashup-domain/src/main/java/kr/mashup/branding/service/member/MemberService.java b/mashup-domain/src/main/java/kr/mashup/branding/service/member/MemberService.java index 08d569c0..2a6b1a0f 100644 --- a/mashup-domain/src/main/java/kr/mashup/branding/service/member/MemberService.java +++ b/mashup-domain/src/main/java/kr/mashup/branding/service/member/MemberService.java @@ -4,6 +4,7 @@ import kr.mashup.branding.domain.ResultCode; import kr.mashup.branding.domain.exception.BadRequestException; import kr.mashup.branding.domain.exception.GenerationIntegrityFailException; +import kr.mashup.branding.domain.exception.NotFoundException; import kr.mashup.branding.domain.generation.Generation; import kr.mashup.branding.domain.member.Member; import kr.mashup.branding.domain.member.MemberGeneration; @@ -340,7 +341,12 @@ public void dropOut(final Generation generation, final List members) { .forEach(MemberGeneration::dropOut); } - public MemberGeneration getCurrentMemberGeneration(Member member) { + public MemberGeneration getLatestMemberGeneration(long memberId) { + return memberGenerationRepository.findLatestByMemberId(memberId) + .orElseThrow(NotFoundException::new); + } + + public MemberGeneration getLatestMemberGeneration(Member member) { return member.getMemberGenerations() .stream() .max(Comparator.comparingInt(mg -> mg.getGeneration().getNumber())) diff --git a/mashup-member/src/main/java/kr/mashup/branding/config/web/MemberAuthArgumentResolver.java b/mashup-member/src/main/java/kr/mashup/branding/config/web/MemberAuthArgumentResolver.java index 5265ebd3..199865f7 100644 --- a/mashup-member/src/main/java/kr/mashup/branding/config/web/MemberAuthArgumentResolver.java +++ b/mashup-member/src/main/java/kr/mashup/branding/config/web/MemberAuthArgumentResolver.java @@ -3,10 +3,12 @@ import kr.mashup.branding.domain.exception.UnauthorizedException; import kr.mashup.branding.security.JwtService; import kr.mashup.branding.security.MemberAuth; +import kr.mashup.branding.service.member.MemberService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; import org.springframework.core.MethodParameter; +import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; @@ -21,6 +23,7 @@ public class MemberAuthArgumentResolver implements HandlerMethodArgumentResolver { private final JwtService jwtService; + private final MemberService memberService; public static final String MDC_MEMBER_ID = "memberId"; @Override @@ -30,20 +33,33 @@ public boolean supportsParameter(MethodParameter parameter) { @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { - String authorization = webRequest.getHeader("Authorization"); - //Assert.notNull(authorization, "Authorization Header must be not null"); + String token = extractTokenFromHeader(webRequest); + Map decodedToken = jwtService.decode(token); + + Long memberId = getMemberId(decodedToken); + Long memberGenerationId = getMemberGenerationId(memberId); + + MDC.put(MDC_MEMBER_ID, String.valueOf(memberId)); + return MemberAuth.of(memberId, memberGenerationId); + } + + private String extractTokenFromHeader(NativeWebRequest webRequest) { + String authorization = webRequest.getHeader(HttpHeaders.AUTHORIZATION); if (authorization == null || !authorization.startsWith("Bearer ")) { throw new UnauthorizedException(); } - String token = authorization.substring(7); - Map decodedToken = jwtService.decode(token); + return authorization.substring(7); + } + + private Long getMemberId(Map decodedToken) { Long memberId = decodedToken.get(JwtService.CLAIM_NAME_MEMBER_ID); - Long memberGenerationId = decodedToken.get(JwtService.CLAIM_NAME_MEMBER_GENERATION_ID); - if (memberId == null || memberGenerationId == null) { + if (memberId == null) { throw new UnauthorizedException(); } + return memberId; + } - MDC.put(MDC_MEMBER_ID, String.valueOf(memberId)); - return MemberAuth.of(memberId, memberGenerationId); + private Long getMemberGenerationId(long memberId) { + return memberService.getLatestMemberGeneration(memberId).getId(); } } diff --git a/mashup-member/src/main/java/kr/mashup/branding/facade/birthday/BirthdayCardFacadeService.java b/mashup-member/src/main/java/kr/mashup/branding/facade/birthday/BirthdayCardFacadeService.java index 592ebd43..0eefa7ae 100644 --- a/mashup-member/src/main/java/kr/mashup/branding/facade/birthday/BirthdayCardFacadeService.java +++ b/mashup-member/src/main/java/kr/mashup/branding/facade/birthday/BirthdayCardFacadeService.java @@ -53,7 +53,7 @@ public BirthdayCardImageResponse generatePresignedUrl(long memberId) { @Transactional public void send(Long memberId, BirthdayCardRequest request) { Member senderMember = memberService.findMemberById(memberId); - MemberGeneration latestMemberGeneration = memberService.getCurrentMemberGeneration(senderMember); + MemberGeneration latestMemberGeneration = memberService.getLatestMemberGeneration(senderMember); birthdayCardService.checkAlreadySent(request.getRecipientMemberId(), senderMember, latestMemberGeneration); birthdayCardService.send(request.getRecipientMemberId(), senderMember, latestMemberGeneration, request.getMessage(), request.getImageUrl()); @@ -62,7 +62,7 @@ public void send(Long memberId, BirthdayCardRequest request) { @Transactional(readOnly = true) public BirthdayCardsResponse getMy(Long memberId) { Member member = memberService.findMemberById(memberId); - MemberGeneration generation = memberService.getCurrentMemberGeneration(member); + MemberGeneration generation = memberService.getLatestMemberGeneration(member); List birthdayCards = birthdayCardService.getMy(member, generation) .stream() diff --git a/mashup-member/src/main/java/kr/mashup/branding/facade/member/MemberFacadeService.java b/mashup-member/src/main/java/kr/mashup/branding/facade/member/MemberFacadeService.java index 75bd63c5..fe5d3c72 100644 --- a/mashup-member/src/main/java/kr/mashup/branding/facade/member/MemberFacadeService.java +++ b/mashup-member/src/main/java/kr/mashup/branding/facade/member/MemberFacadeService.java @@ -1,12 +1,5 @@ package kr.mashup.branding.facade.member; -import java.time.LocalDateTime; -import java.util.Comparator; -import java.util.List; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - import kr.mashup.branding.domain.exception.GenerationIntegrityFailException; import kr.mashup.branding.domain.generation.Generation; import kr.mashup.branding.domain.invite.Invite; @@ -16,24 +9,19 @@ import kr.mashup.branding.domain.member.exception.MemberInvalidInviteCodeException; import kr.mashup.branding.domain.scorehistory.ScoreHistory; import kr.mashup.branding.domain.scorehistory.ScoreType; -import kr.mashup.branding.service.member.MemberCreateDto; import kr.mashup.branding.security.JwtService; import kr.mashup.branding.service.invite.InviteService; +import kr.mashup.branding.service.member.MemberCreateDto; import kr.mashup.branding.service.member.MemberService; import kr.mashup.branding.service.scorehistory.ScoreHistoryService; -import kr.mashup.branding.ui.member.request.LoginRequest; -import kr.mashup.branding.ui.member.request.MemberGenerationRequest; -import kr.mashup.branding.ui.member.request.MemberPasswordChangeRequest; -import kr.mashup.branding.ui.member.request.PushNotificationRequest; -import kr.mashup.branding.ui.member.request.SignUpRequest; -import kr.mashup.branding.ui.member.request.ValidInviteRequest; -import kr.mashup.branding.ui.member.response.AccessResponse; -import kr.mashup.branding.ui.member.response.ExistsResponse; -import kr.mashup.branding.ui.member.response.MemberGenerationsResponse; -import kr.mashup.branding.ui.member.response.MemberInfoResponse; -import kr.mashup.branding.ui.member.response.TokenResponse; -import kr.mashup.branding.ui.member.response.ValidResponse; +import kr.mashup.branding.ui.member.request.*; +import kr.mashup.branding.ui.member.response.*; import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; @Service @@ -121,8 +109,8 @@ public void withdraw(Long memberId) { memberService.deleteMember(memberId); } - public TokenResponse getAccessToken(Long memberId, Long memberGenerationId) { - final String token = jwtService.encode(memberId, memberGenerationId); + public TokenResponse getAccessToken(Long memberId) { + final String token = jwtService.encode(memberId); return TokenResponse.of(token); } @@ -175,15 +163,8 @@ public void changePassword( memberService.resetPassword(identification, request.getNewPassword()); } - private MemberGeneration getLatestMemberGeneration(Member member) { - return member.getMemberGenerations().stream().max(Comparator.comparing( - memberGeneration -> memberGeneration.getGeneration().getNumber() - )).orElseThrow(GenerationIntegrityFailException::new); - } - private String getToken(Member member) { - final MemberGeneration latestMemberGeneration = getLatestMemberGeneration(member); - return jwtService.encode(member.getId(), latestMemberGeneration.getId()); + return jwtService.encode(member.getId()); } private void checkMemberGenerationIsIn(Long memberGenerationId, List memberGenerations) { diff --git a/mashup-member/src/main/java/kr/mashup/branding/security/JwtService.java b/mashup-member/src/main/java/kr/mashup/branding/security/JwtService.java index 43d32ce5..e9cbbd0a 100644 --- a/mashup-member/src/main/java/kr/mashup/branding/security/JwtService.java +++ b/mashup-member/src/main/java/kr/mashup/branding/security/JwtService.java @@ -22,12 +22,11 @@ public class JwtService { private String secretKey; public static final String CLAIM_NAME_MEMBER_ID = "MemberId"; - public static final String CLAIM_NAME_MEMBER_GENERATION_ID = "MemberGenerationId"; private Algorithm algorithm; private JWTVerifier jwtVerifier; - public String encode(Long memberId, Long memberGenerationId) { + public String encode(Long memberId) { LocalDateTime expiredAt = LocalDateTime.now().plusWeeks(4L); @@ -35,7 +34,6 @@ public String encode(Long memberId, Long memberGenerationId) { return JWT.create() .withClaim(CLAIM_NAME_MEMBER_ID, memberId) - .withClaim(CLAIM_NAME_MEMBER_GENERATION_ID, memberGenerationId) .withExpiresAt(date) .sign(algorithm); } @@ -43,10 +41,7 @@ public String encode(Long memberId, Long memberGenerationId) { public Map decode(String token) { try { DecodedJWT jwt = jwtVerifier.verify(token); - return Map.of( - CLAIM_NAME_MEMBER_ID, jwt.getClaim(CLAIM_NAME_MEMBER_ID).asLong(), - CLAIM_NAME_MEMBER_GENERATION_ID, jwt.getClaim(CLAIM_NAME_MEMBER_GENERATION_ID).asLong() - ); + return Map.of(CLAIM_NAME_MEMBER_ID, jwt.getClaim(CLAIM_NAME_MEMBER_ID).asLong()); } catch (JWTVerificationException e) { log.warn("Failed to decode jwt. token: {}", token, e); throw new UnauthorizedException(); diff --git a/mashup-member/src/main/java/kr/mashup/branding/ui/member/MemberController.java b/mashup-member/src/main/java/kr/mashup/branding/ui/member/MemberController.java index aecce823..a7510b5c 100644 --- a/mashup-member/src/main/java/kr/mashup/branding/ui/member/MemberController.java +++ b/mashup-member/src/main/java/kr/mashup/branding/ui/member/MemberController.java @@ -104,7 +104,7 @@ public ApiResponse issueAccessToken( @ApiIgnore MemberAuth memberAuth ) { final TokenResponse tokenResponse - = memberFacadeService.getAccessToken(memberAuth.getMemberId(), memberAuth.getMemberGenerationId()); + = memberFacadeService.getAccessToken(memberAuth.getMemberId()); return ApiResponse.success(tokenResponse); }