diff --git a/api/src/main/java/com/org/gunbbang/auth/jwt/service/JwtService.java b/api/src/main/java/com/org/gunbbang/auth/jwt/service/JwtService.java index cfebc81..d7bc2ef 100644 --- a/api/src/main/java/com/org/gunbbang/auth/jwt/service/JwtService.java +++ b/api/src/main/java/com/org/gunbbang/auth/jwt/service/JwtService.java @@ -28,22 +28,22 @@ @Slf4j public class JwtService { @Value("${jwt.secretKey}") - private String secretKey; + private String SECRET_KEY; @Value("${jwt.access.expiration}") - private Long accessTokenExpirationPeriod; + private Long ACCESS_TOKEN_EXPIRE_PERIOD; @Value("${jwt.refresh.expiration}") - private Long refreshTokenExpirationPeriod; + private Long REFRESH_TOKEN_EXPIRE_PERIOD; @Value("${jwt.access.header}") - private String accessHeader; + private String ACCESS_HEADER; @Value("${jwt.refresh.header}") - private String refreshHeader; + private String REFRESH_HEADER; @Value("${apple.refresh.header}") - private String appleRefreshHeader; + private String APLLE_REFRESH_HEADER; private static final String ACCESS_TOKEN_SUBJECT = "AccessToken"; private static final String REFRESH_TOKEN_SUBJECT = "RefreshToken"; @@ -59,10 +59,10 @@ public String createAccessToken(String email, Long memberId) { Date now = new Date(); return JWT.create() .withSubject(ACCESS_TOKEN_SUBJECT) // jwt의 subject 지정 (AccessToken으로 지정) - .withExpiresAt(new Date(now.getTime() + accessTokenExpirationPeriod)) // 토큰 만료시간 지정 + .withExpiresAt(new Date(now.getTime() + ACCESS_TOKEN_EXPIRE_PERIOD)) // 토큰 만료시간 지정 .withClaim(EMAIL_CLAIM, email) .withClaim(MEMBER_ID_CLAIM, memberId) - .sign(Algorithm.HMAC512(secretKey)); + .sign(Algorithm.HMAC512(SECRET_KEY)); } // refreshToken 생성 @@ -70,22 +70,22 @@ public String createRefreshToken() { Date now = new Date(); return JWT.create() .withSubject(REFRESH_TOKEN_SUBJECT) - .withExpiresAt(new Date(now.getTime() + refreshTokenExpirationPeriod)) - .sign(Algorithm.HMAC512(secretKey)); + .withExpiresAt(new Date(now.getTime() + REFRESH_TOKEN_EXPIRE_PERIOD)) + .sign(Algorithm.HMAC512(SECRET_KEY)); } public void setSignedUpMemberToken(SignedUpMemberVO vo, HttpServletResponse response) { String accessToken = createAccessToken(vo.getEmail(), vo.getMemberId()); - response.setHeader(accessHeader, accessToken); + response.setHeader(ACCESS_HEADER, accessToken); if (vo.getRole().equals(Role.ROLE_MEMBER)) { String refreshToken = createRefreshToken(); updateRefreshTokenByMemberId(vo.getMemberId(), refreshToken); - response.setHeader(refreshHeader, refreshToken); + response.setHeader(REFRESH_HEADER, refreshToken); } if (vo.getPlatformType().equals(PlatformType.APPLE)) { - response.setHeader(appleRefreshHeader, vo.getAppleRefreshToken()); + response.setHeader(APLLE_REFRESH_HEADER, vo.getAppleRefreshToken()); } } @@ -134,30 +134,30 @@ public void sendAccessToken(HttpServletResponse response, String accessToken) { /** accessToken 헤더 설정 */ public void setAccessTokenHeader(HttpServletResponse response, String accessToken) { - response.setHeader(accessHeader, accessToken); + response.setHeader(ACCESS_HEADER, accessToken); } /** refreshToken 헤더 설정 */ public void setRefreshTokenHeader(HttpServletResponse response, String refreshToken) { - response.setHeader(refreshHeader, refreshToken); + response.setHeader(REFRESH_HEADER, refreshToken); } /** header에서 refreshToken 추출 토큰 앞에 붙은 Bearer 문자열 삭제 후 리턴 */ public Optional extractRefreshToken(HttpServletRequest request) { - return Optional.ofNullable(request.getHeader(refreshHeader)) + return Optional.ofNullable(request.getHeader(REFRESH_HEADER)) .filter(refreshToken -> refreshToken.startsWith(BEARER_PREFIX)) .map(refreshToken -> refreshToken.replace(BEARER_PREFIX, "")); } /** header에서 accessToken 추출 토큰 앞에 붙은 Bearer 문자열 삭제 후 리턴 */ public Optional extractAccessToken(HttpServletRequest request) { - return Optional.ofNullable(request.getHeader(accessHeader)) + return Optional.ofNullable(request.getHeader(ACCESS_HEADER)) .filter(accessToken -> accessToken.startsWith(BEARER_PREFIX)) .map(accessToken -> accessToken.replace(BEARER_PREFIX, "")); } public String extractAccessTokenAsString(HttpServletRequest request) { - String header = request.getHeader(accessHeader); + String header = request.getHeader(ACCESS_HEADER); if (header.startsWith(BEARER_PREFIX)) { return header.replace(BEARER_PREFIX, ""); } @@ -165,7 +165,7 @@ public String extractAccessTokenAsString(HttpServletRequest request) { } public String extractRefreshTokenAsString(HttpServletRequest request) { - String header = request.getHeader(refreshHeader); + String header = request.getHeader(REFRESH_HEADER); if (header.startsWith(BEARER_PREFIX)) { return header.replace(BEARER_PREFIX, ""); } @@ -173,13 +173,11 @@ public String extractRefreshTokenAsString(HttpServletRequest request) { } public boolean isAccessTokenExist(HttpServletRequest request) { - log.info("request url: " + request.getRequestURI()); - log.info("accessHeader: " + request.getHeader(accessHeader)); - return request.getHeader(accessHeader) != null; + return request.getHeader(ACCESS_HEADER) != null; } public boolean isRefreshTokenExist(HttpServletRequest request) { - return request.getHeader(refreshHeader) != null; + return request.getHeader(REFRESH_HEADER) != null; } public Optional extractEmailClaim(String accessToken) { @@ -215,7 +213,7 @@ public Long extractMemberIdClaimFromExpiredToken(String accessToken) } public DecodedJWT getVerifiedJWT(String jwtToken) { - return JWT.require(Algorithm.HMAC512(secretKey)).build().verify(jwtToken); + return JWT.require(Algorithm.HMAC512(SECRET_KEY)).build().verify(jwtToken); } public boolean isTokenValid(String token) { diff --git a/api/src/main/java/com/org/gunbbang/auth/security/config/SecurityConfig.java b/api/src/main/java/com/org/gunbbang/auth/security/config/SecurityConfig.java index 4d7a286..d4d901d 100644 --- a/api/src/main/java/com/org/gunbbang/auth/security/config/SecurityConfig.java +++ b/api/src/main/java/com/org/gunbbang/auth/security/config/SecurityConfig.java @@ -76,10 +76,10 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { "/bookMarks/{bakeryId}", // 북마크 "/report/review/{reviewId}", // 리뷰신고 "/member/withdraw", // 회원탈퇴 - "/auth/logout", // 로그아웃 "/member", // 유저 정보 상세보기(마이페이지) "/member/bookMarks", // 북마크 목록 조회 - "/member/types" // 유져 필터 조회 및 필터 변경 + "/member/types", // 유져 필터 조회 및 필터 변경 + "/auth/withdraw" // 회원 탈퇴 ) .hasRole("MEMBER") .and() diff --git a/api/src/main/java/com/org/gunbbang/auth/security/handler/CustomLogoutHandler.java b/api/src/main/java/com/org/gunbbang/auth/security/handler/CustomLogoutHandler.java index 70edc48..1c3876e 100644 --- a/api/src/main/java/com/org/gunbbang/auth/security/handler/CustomLogoutHandler.java +++ b/api/src/main/java/com/org/gunbbang/auth/security/handler/CustomLogoutHandler.java @@ -1,5 +1,6 @@ package com.org.gunbbang.auth.security.handler; +import com.org.gunbbang.BadRequestException; import com.org.gunbbang.NotFoundException; import com.org.gunbbang.auth.security.util.SecurityUtil; import com.org.gunbbang.entity.Member; @@ -8,6 +9,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.logout.LogoutHandler; @@ -16,6 +18,9 @@ public class CustomLogoutHandler implements LogoutHandler { private final MemberRepository memberRepository; + @Value("${jwt.access.header}") + private String accessHeader; + public CustomLogoutHandler(MemberRepository memberRepository) { this.memberRepository = memberRepository; } @@ -25,6 +30,10 @@ public void logout( HttpServletRequest request, HttpServletResponse response, Authentication authentication) { log.info("########## CustomLogoutHandler 진입 ##########"); + if (request.getHeader(accessHeader) == null) { + throw new BadRequestException(ErrorType.NO_REQUEST_HEADER_EXCEPTION); + } + Long memberId = SecurityUtil.getLoginMemberId(); Member foundMember = memberRepository diff --git a/api/src/main/java/com/org/gunbbang/service/AmplitudeService.java b/api/src/main/java/com/org/gunbbang/service/AmplitudeService.java index 4ac3749..9295d63 100644 --- a/api/src/main/java/com/org/gunbbang/service/AmplitudeService.java +++ b/api/src/main/java/com/org/gunbbang/service/AmplitudeService.java @@ -23,7 +23,7 @@ @Slf4j public class AmplitudeService { @Value("${amplitude.api.key}") - private String apiKey; + private String API_KEY; private final AmplitudeFeignClient amplitudeFeignClient; private final ObjectMapper objectMapper; @@ -71,7 +71,7 @@ public void sendUserProperty(Long memberId) { ObjectNode identification = getIdentification(propertyMap, memberId); - String requestBody = "api_key=" + apiKey + "&identification=" + identification; + String requestBody = "api_key=" + API_KEY + "&identification=" + identification; amplitudeFeignClient.identifyUserProperty(requestBody); } catch (Exception e) { log.error("%%%%%%%%%% user property 전송 과정에서 에러 발생 %%%%%%%%%%"); diff --git a/api/src/main/java/com/org/gunbbang/service/BakeryService.java b/api/src/main/java/com/org/gunbbang/service/BakeryService.java index 78a5d88..96730a1 100644 --- a/api/src/main/java/com/org/gunbbang/service/BakeryService.java +++ b/api/src/main/java/com/org/gunbbang/service/BakeryService.java @@ -41,7 +41,7 @@ public class BakeryService { private final NutrientTypeRepository nutrientTypeRepository; private final String BLANK_SPACE = " "; - private final int maxBestBakeryCount = 10; + private final int MAX_BEST_BAKERY_COUNT = 10; public Page getBakeryList( String sortingOption, @@ -210,7 +210,7 @@ public List getBestBakeries() { .collect(Collectors.toList()); List bestBakeries = getBestBakeries(foundMember, breadTypes); - if (bestBakeries.size() == maxBestBakeryCount) { + if (bestBakeries.size() == MAX_BEST_BAKERY_COUNT) { log.info("########## 베스트 베이커리 10개 조회 완료. 추가 조회 쿼리 없이 바로 반환 ##########"); return BakeryMapper.INSTANCE.toBestBakeryListResponseDTO(bestBakeries); } @@ -219,7 +219,7 @@ public List getBestBakeries() { alreadyFoundBakeryIds.add(-1L); getRestBakeries(alreadyFoundBakeryIds, breadTypes, bestBakeries); - if (bestBakeries.size() == maxBestBakeryCount) { + if (bestBakeries.size() == MAX_BEST_BAKERY_COUNT) { log.info("##########빵유형 10개 조회 완료. 추가 조회 쿼리 없이 바로 반환 ##########"); return BakeryMapper.INSTANCE.toBestBakeryListResponseDTO(bestBakeries); } @@ -229,7 +229,7 @@ public List getBestBakeries() { } private List getOnlyRandomBakeries() { - PageRequest bestPageRequest = PageRequest.of(0, maxBestBakeryCount); + PageRequest bestPageRequest = PageRequest.of(0, MAX_BEST_BAKERY_COUNT); return bakeryRepository.findBakeriesRandomly(bestPageRequest); } @@ -250,7 +250,7 @@ private void setAlreadyFoundBakeryIds( private void getRestRandomBakeries(List alreadyFoundBakeryIds, List bestBakeries) { log.info("########## 나머지만 랜덤으로 고르는 베이커리. 현재까지 조회된 베이커리 수: {} ##########", bestBakeries.size()); setAlreadyFoundBakeryIds(alreadyFoundBakeryIds, bestBakeries); - PageRequest bestPageRequest = PageRequest.of(0, maxBestBakeryCount - bestBakeries.size()); + PageRequest bestPageRequest = PageRequest.of(0, MAX_BEST_BAKERY_COUNT - bestBakeries.size()); bestBakeries.addAll( bakeryRepository.findRestBakeriesRandomly(alreadyFoundBakeryIds, bestPageRequest)); } @@ -259,7 +259,7 @@ private void getRestBakeries( List alreadyFoundBakeryIds, List breadTypes, List bestBakeries) { log.info("########## 빵유형 일치 베이커리 조회 시작. 현재까지 조회된 베이커리 수: {} ##########", bestBakeries.size()); setAlreadyFoundBakeryIds(alreadyFoundBakeryIds, bestBakeries); - PageRequest bestPageRequest = PageRequest.of(0, maxBestBakeryCount - bestBakeries.size()); + PageRequest bestPageRequest = PageRequest.of(0, MAX_BEST_BAKERY_COUNT - bestBakeries.size()); bestBakeries.addAll( bakeryRepository.findRestBakeriesByBreadTypes( breadTypes, alreadyFoundBakeryIds, bestPageRequest)); @@ -267,7 +267,7 @@ private void getRestBakeries( private List getBestBakeries(Member foundMember, List breadTypes) { log.info("########## 베스트 건빵집 조회 시작 ##########"); - PageRequest bestPageRequest = PageRequest.of(0, maxBestBakeryCount); + PageRequest bestPageRequest = PageRequest.of(0, MAX_BEST_BAKERY_COUNT); // 1. MemberBreadType 뒤져서 나랑 동일한 BreadType 선택한 멤버 가져옴 // 2. 북마크 테이블+베이커리 테이블 뒤져서 해당 멤버들이 북마크한 빵집 가져옴 diff --git a/api/src/main/java/com/org/gunbbang/service/ReviewService.java b/api/src/main/java/com/org/gunbbang/service/ReviewService.java index 7337721..d013d1d 100644 --- a/api/src/main/java/com/org/gunbbang/service/ReviewService.java +++ b/api/src/main/java/com/org/gunbbang/service/ReviewService.java @@ -34,7 +34,7 @@ public class ReviewService { private final MemberBreadTypeRepository memberBreadTypeRepository; private final MemberBreadTypeRepository memberNutrientTypeRepository; private final BakeryBreadTypeRepository bakeryBreadTypeRepository; - private final int maxBestBakeryCount = 10; + private final int MAX_BEST_BAKERY_COUNT = 10; public Long createReview(Long currentMemberId, Long bakeryId, ReviewRequestDTO reviewRequestDto) { String reviewText = reviewRequestDto.getReviewText().trim(); @@ -233,7 +233,7 @@ public List getBestReviews() { .collect(Collectors.toList()); List bestReviews = getBestReviews(foundMember, breadTypes); - if (bestReviews.size() == maxBestBakeryCount) { + if (bestReviews.size() == MAX_BEST_BAKERY_COUNT) { log.info("########## 베스트 리뷰 10개 조회 완료. 추가 조회 쿼리 없이 바로 반환 ##########"); return getBestReviewListResponseDTOs(bestReviews); } @@ -247,7 +247,7 @@ public List getBestReviews() { } private List getRandomReviews() { - PageRequest randomPageRequest = PageRequest.of(0, maxBestBakeryCount); + PageRequest randomPageRequest = PageRequest.of(0, MAX_BEST_BAKERY_COUNT); List randomReviews = reviewRepository.findRandomReviews(randomPageRequest); // 랜덤 리뷰 10개 조회 return randomReviews; @@ -263,7 +263,7 @@ private boolean isFilterSelected(Member foundMember) { private void getRestReviewsRandomly( List alreadyFoundReviewIds, List bestReviews) { - PageRequest restPageRequest = PageRequest.of(0, maxBestBakeryCount - bestReviews.size()); + PageRequest restPageRequest = PageRequest.of(0, MAX_BEST_BAKERY_COUNT - bestReviews.size()); setAlreadyFoundReviewIds(alreadyFoundReviewIds, bestReviews); bestReviews.addAll( reviewRepository.findRestBestReviewDTOListByBreadType( @@ -277,7 +277,7 @@ private void setAlreadyFoundReviewIds( } private List getBestReviews(Member foundMember, List breadTypes) { - PageRequest bestPageRequest = PageRequest.of(0, maxBestBakeryCount); + PageRequest bestPageRequest = PageRequest.of(0, MAX_BEST_BAKERY_COUNT); List bestReviews = reviewRepository.findBestReviewDTOList( breadTypes, foundMember.getMainPurpose(), bestPageRequest); diff --git a/storage/db-core/src/main/java/com/org/gunbbang/repository/BakeryRepository.java b/storage/db-core/src/main/java/com/org/gunbbang/repository/BakeryRepository.java index 827b462..fc4571c 100644 --- a/storage/db-core/src/main/java/com/org/gunbbang/repository/BakeryRepository.java +++ b/storage/db-core/src/main/java/com/org/gunbbang/repository/BakeryRepository.java @@ -66,11 +66,11 @@ List findRestBakeriesRandomly( @Query( value = "SELECT distinct b FROM Bakery b " - + "LEFT JOIN BakeryBreadType bbt ON b.bakeryId = bbt.bakery.bakeryId AND bbt.breadType IN :breadTypeList " - + "LEFT JOIN BakeryCategory bc ON b.bakeryId = bc.bakery.bakeryId AND bc.category IN :categoryList " - + "LEFT JOIN BakeryNutrientType bnt ON b.bakeryId = bnt.bakery.bakeryId AND bnt.nutrientType = :bakeryNutrientType " + + "INNER JOIN BakeryBreadType bbt ON b.bakeryId = bbt.bakery.bakeryId AND bbt.breadType IN :breadTypeList " + + "INNER JOIN BakeryCategory bc ON b.bakeryId = bc.bakery.bakeryId AND bc.category IN :categoryList " + + "INNER JOIN BakeryNutrientType bnt ON b.bakeryId = bnt.bakery.bakeryId AND bnt.nutrientType = :bakeryNutrientType " + "GROUP BY b.bakeryId " - + "ORDER BY COUNT(bc.bakery.bakeryId) DESC, COUNT(bbt.bakery.bakeryId) DESC") + + "ORDER BY COUNT(bbt.bakery.bakeryId) DESC, COUNT(bc.bakery.bakeryId) DESC") Page findFilteredBakeries( @Param("categoryList") List categoryList, @Param("breadTypeList") List breadTypeList, @@ -80,11 +80,11 @@ Page findFilteredBakeries( @Query( value = "SELECT distinct b FROM Bakery b " - + "LEFT JOIN BakeryBreadType bbt ON b.bakeryId = bbt.bakery.bakeryId AND bbt.breadType IN :breadTypeList " - + "LEFT JOIN BakeryCategory bc ON b.bakeryId = bc.bakery.bakeryId AND bc.category IN :categoryList " - + "LEFT JOIN BakeryNutrientType bnt ON b.bakeryId = bnt.bakery.bakeryId AND bnt.nutrientType = :bakeryNutrientType " + + "INNER JOIN BakeryBreadType bbt ON b.bakeryId = bbt.bakery.bakeryId AND bbt.breadType IN :breadTypeList " + + "INNER JOIN BakeryCategory bc ON b.bakeryId = bc.bakery.bakeryId AND bc.category IN :categoryList " + + "INNER JOIN BakeryNutrientType bnt ON b.bakeryId = bnt.bakery.bakeryId AND bnt.nutrientType = :bakeryNutrientType " + "GROUP BY b.bakeryId " - + "ORDER BY b.reviewCount DESC, COUNT(bc.bakery.bakeryId) DESC, COUNT(bbt.bakery.bakeryId) DESC") + + "ORDER BY b.reviewCount DESC, COUNT(bbt.bakery.bakeryId) DESC, COUNT(bc.bakery.bakeryId) DESC") Page findFilteredBakeriesSortByReview( @Param("categoryList") List categoryList, @Param("breadTypeList") List breadTypeList,