diff --git a/src/main/java/com/example/sinitto/callback/controller/CallbackController.java b/src/main/java/com/example/sinitto/callback/controller/CallbackController.java index 5472dabe..f4c591df 100644 --- a/src/main/java/com/example/sinitto/callback/controller/CallbackController.java +++ b/src/main/java/com/example/sinitto/callback/controller/CallbackController.java @@ -4,7 +4,6 @@ import com.example.sinitto.callback.dto.CallbackResponse; import com.example.sinitto.callback.dto.CallbackUsageHistoryResponse; import com.example.sinitto.callback.service.CallbackService; -import com.example.sinitto.common.annotation.MemberId; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.data.domain.Page; @@ -27,7 +26,7 @@ public CallbackController(CallbackService callbackService) { @Operation(summary = "콜백 전화 리스트 보기(페이지)", description = "시니어가 요청한 콜백전화를 페이징으로 보여줍니다.") @GetMapping - public ResponseEntity> getWaitingCallbackList(@MemberId Long memberId, + public ResponseEntity> getWaitingCallbackList(@RequestAttribute("memberId") Long memberId, @PageableDefault(sort = "postTime", direction = Sort.Direction.DESC) Pageable pageable) { return ResponseEntity.ok(callbackService.getWaitingCallbacks(memberId, pageable)); @@ -35,7 +34,7 @@ public ResponseEntity> getWaitingCallbackList(@MemberId L @Operation(summary = "진행 상태인 콜백을 완료 대기 상태로 전환(시니또가)", description = "시니또가 수락한 콜백 수행을 완료했을때 이 api 호출하면 완료 대기 상태로 변합니다.") @PutMapping("/pendingComplete/{callbackId}") - public ResponseEntity pendingCompleteCallback(@MemberId Long memberId, + public ResponseEntity pendingCompleteCallback(@RequestAttribute("memberId") Long memberId, @PathVariable Long callbackId) { callbackService.changeCallbackStatusToPendingCompleteBySinitto(memberId, callbackId); @@ -44,7 +43,7 @@ public ResponseEntity pendingCompleteCallback(@MemberId Long memberId, @Operation(summary = "완료 대기 상태인 콜백을 완료 상태로 전환(보호자가)", description = "보호자가 완료 대기 상태인 콜백을 완료 확정 시킵니다.") @PutMapping("/complete/{callbackId}") - public ResponseEntity completeCallback(@MemberId Long memberId, + public ResponseEntity completeCallback(@RequestAttribute("memberId") Long memberId, @PathVariable Long callbackId) { callbackService.changeCallbackStatusToCompleteByGuard(memberId, callbackId); @@ -53,7 +52,7 @@ public ResponseEntity completeCallback(@MemberId Long memberId, @Operation(summary = "콜백 서비스 수락 신청", description = "시니또가 콜백 서비스 수락을 신청합니다.") @PutMapping("/accept/{callbackId}") - public ResponseEntity acceptCallback(@MemberId Long memberId, + public ResponseEntity acceptCallback(@RequestAttribute("memberId") Long memberId, @PathVariable Long callbackId) { callbackService.acceptCallbackBySinitto(memberId, callbackId); @@ -62,7 +61,7 @@ public ResponseEntity acceptCallback(@MemberId Long memberId, @Operation(summary = "진행중인 콜백 서비스 취소", description = "시니또가 진행중인 콜백 서비스를 취소합니다. 콜백은 다시 대기 상태로 돌아갑니다.") @PutMapping("/cancel/{callbackId}") - public ResponseEntity cancelCallback(@MemberId Long memberId, + public ResponseEntity cancelCallback(@RequestAttribute("memberId") Long memberId, @PathVariable Long callbackId) { callbackService.cancelCallbackAssignmentBySinitto(memberId, callbackId); @@ -77,14 +76,14 @@ public ResponseEntity addCallCheck(@RequestParam("From") String fromNumb @Operation(summary = "시니또에게 현재 할당된 콜백 조회", description = "현재 시니또 본인에게 할당된 콜백을 조회합니다.") @GetMapping("/sinitto/accepted") - public ResponseEntity getAcceptedCallback(@MemberId Long memberId) { + public ResponseEntity getAcceptedCallback(@RequestAttribute("memberId") Long memberId) { return ResponseEntity.ok(callbackService.getAcceptedCallback(memberId)); } @Operation(summary = "보호자의 콜백 이용 내역 조회", description = "보호자에게 연관된 모든 콜백 내역을 조회합니다. 기본적으로 최신 내역 부터 조회됩니다.") @GetMapping("/guard/requested") - public ResponseEntity> getAcceptedCallback(@MemberId Long memberId, + public ResponseEntity> getAcceptedCallback(@RequestAttribute("memberId") Long memberId, @PageableDefault(sort = "postTime", direction = Sort.Direction.DESC) Pageable pageable) { return ResponseEntity.ok(callbackService.getCallbackHistoryOfGuard(memberId, pageable)); @@ -92,7 +91,7 @@ public ResponseEntity> getAcceptedCallback(@M @Operation(summary = "콜백 단건 조회 (시니또용)", description = "콜백 id 로 콜백을 단건 조회합니다.") @GetMapping("/{callbackId}") - public ResponseEntity getCallback(@MemberId Long memberId, + public ResponseEntity getCallback(@RequestAttribute("memberId") Long memberId, @PathVariable("callbackId") Long callbackId) { return ResponseEntity.ok(callbackService.getCallbackForSinitto(memberId, callbackId)); diff --git a/src/main/java/com/example/sinitto/common/annotation/MemberId.java b/src/main/java/com/example/sinitto/common/annotation/MemberId.java deleted file mode 100644 index eaa1cafb..00000000 --- a/src/main/java/com/example/sinitto/common/annotation/MemberId.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.example.sinitto.common.annotation; - -import io.swagger.v3.oas.annotations.Parameter; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.PARAMETER) -@Parameter(hidden = true) -public @interface MemberId { -} diff --git a/src/main/java/com/example/sinitto/common/config/ArgumentResolverConfig.java b/src/main/java/com/example/sinitto/common/config/ArgumentResolverConfig.java deleted file mode 100644 index bde563d2..00000000 --- a/src/main/java/com/example/sinitto/common/config/ArgumentResolverConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.example.sinitto.common.config; - -import com.example.sinitto.common.resolver.MemberIdArgumentResolver; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -import java.util.List; - -@Configuration -public class ArgumentResolverConfig implements WebMvcConfigurer { - - private final MemberIdArgumentResolver memberIdArgumentResolver; - - public ArgumentResolverConfig(MemberIdArgumentResolver memberIdArgumentResolver) { - this.memberIdArgumentResolver = memberIdArgumentResolver; - } - - @Override - public void addArgumentResolvers(List resolvers) { - resolvers.add(memberIdArgumentResolver); - } -} diff --git a/src/main/java/com/example/sinitto/common/config/WebConfig.java b/src/main/java/com/example/sinitto/common/config/WebConfig.java index 8cc90f76..ae986fd1 100644 --- a/src/main/java/com/example/sinitto/common/config/WebConfig.java +++ b/src/main/java/com/example/sinitto/common/config/WebConfig.java @@ -1,5 +1,6 @@ package com.example.sinitto.common.config; +import com.example.sinitto.common.interceptor.JwtInterceptor; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; @@ -13,6 +14,7 @@ import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.time.Duration; @@ -23,6 +25,11 @@ public class WebConfig implements WebMvcConfigurer { private static final int TIME_OUT_DURATION = 5; private static final int MAX_OPEN_CONNECTIONS = 100; private static final int CONNECTIONS_PER_IP_PORT_PAIR = 5; + private final JwtInterceptor jwtInterceptor; + + public WebConfig(JwtInterceptor jwtInterceptor){ + this.jwtInterceptor = jwtInterceptor; + } @Bean public RestTemplate restTemplate(RestTemplateBuilder builder, RestTemplateResponseErrorHandler errorHandler) { @@ -62,4 +69,9 @@ public CorsFilter corsFilter() { source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(jwtInterceptor).addPathPatterns("/api/**"); + } } diff --git a/src/main/java/com/example/sinitto/common/interceptor/JwtInterceptor.java b/src/main/java/com/example/sinitto/common/interceptor/JwtInterceptor.java new file mode 100644 index 00000000..10b9b13c --- /dev/null +++ b/src/main/java/com/example/sinitto/common/interceptor/JwtInterceptor.java @@ -0,0 +1,45 @@ +package com.example.sinitto.common.interceptor; + +import com.example.sinitto.common.exception.UnauthorizedException; +import com.example.sinitto.member.service.MemberTokenService; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import java.lang.reflect.Method; + +@Component +public class JwtInterceptor implements HandlerInterceptor { + private final MemberTokenService memberTokenService; + + public JwtInterceptor(MemberTokenService memberTokenService){ + this.memberTokenService = memberTokenService; + } + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){ + if (handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + Method method = handlerMethod.getMethod(); + + Class[] parameterTypes = method.getParameterTypes(); + + for (Class paramType : parameterTypes) { + if (paramType.equals(Long.class)) { + String authorizationHeader = request.getHeader("Authorization"); + if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) { + throw new UnauthorizedException("토큰이 없거나, 헤더 형식에 맞지 않습니다."); + } + + String token = authorizationHeader.substring(7); + + request.setAttribute("memberId", memberTokenService.getMemberIdByToken(token)); + return true; + } + } + } + + return true; + } +} diff --git a/src/main/java/com/example/sinitto/common/resolver/MemberIdArgumentResolver.java b/src/main/java/com/example/sinitto/common/resolver/MemberIdArgumentResolver.java deleted file mode 100644 index 141a3c85..00000000 --- a/src/main/java/com/example/sinitto/common/resolver/MemberIdArgumentResolver.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.example.sinitto.common.resolver; - -import com.example.sinitto.common.annotation.MemberId; -import com.example.sinitto.common.exception.UnauthorizedException; -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.core.MethodParameter; -import org.springframework.stereotype.Component; -import org.springframework.web.bind.support.WebDataBinderFactory; -import org.springframework.web.context.request.NativeWebRequest; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.method.support.ModelAndViewContainer; - -@Component -public class MemberIdArgumentResolver implements HandlerMethodArgumentResolver { - - private final MemberIdProvider memberIdProvider; - - public MemberIdArgumentResolver(MemberIdProvider memberIdProvider) { - this.memberIdProvider = memberIdProvider; - } - - @Override - public boolean supportsParameter(MethodParameter parameter) { - return parameter.getParameterAnnotation(MemberId.class) != null; - } - - @Override - public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { - HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); - - String authorizationHeader = request.getHeader("Authorization"); - if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) { - throw new UnauthorizedException("토큰이 없거나, 헤더 형식에 맞지 않습니다."); - } - - String token = authorizationHeader.substring(7); - return memberIdProvider.getMemberIdByToken(token); - } - -} diff --git a/src/main/java/com/example/sinitto/common/resolver/MemberIdProvider.java b/src/main/java/com/example/sinitto/common/resolver/MemberIdProvider.java deleted file mode 100644 index 770bef4d..00000000 --- a/src/main/java/com/example/sinitto/common/resolver/MemberIdProvider.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.example.sinitto.common.resolver; - -public interface MemberIdProvider { - Long getMemberIdByToken(String token); -} diff --git a/src/main/java/com/example/sinitto/guard/controller/GuardController.java b/src/main/java/com/example/sinitto/guard/controller/GuardController.java index 3ee13ad0..e2e244cf 100644 --- a/src/main/java/com/example/sinitto/guard/controller/GuardController.java +++ b/src/main/java/com/example/sinitto/guard/controller/GuardController.java @@ -1,6 +1,5 @@ package com.example.sinitto.guard.controller; -import com.example.sinitto.common.annotation.MemberId; import com.example.sinitto.guard.dto.GuardRequest; import com.example.sinitto.guard.dto.GuardResponse; import com.example.sinitto.guard.dto.SeniorRequest; @@ -25,46 +24,46 @@ public GuardController(GuardService guardService) { @Operation(summary = "연결된 모든 시니어 정보 조회", description = "보호자가 등록한 모든 시니어의 정보를 요청합니다.") @GetMapping("/senior") - public ResponseEntity> getAllSeniors(@MemberId Long memberId) { + public ResponseEntity> getAllSeniors(@RequestAttribute("memberId") Long memberId) { return ResponseEntity.ok(guardService.readSeniors(memberId)); } @Operation(summary = "연결된 특정 시니어 정보 조회", description = "보호자가 등록한 특정 시니어의 정보를 요청합니다.") @GetMapping("/senior/{seniorId}") - public ResponseEntity getSenior(@MemberId Long memberId, @PathVariable Long seniorId) { + public ResponseEntity getSenior(@RequestAttribute("memberId") Long memberId, @PathVariable Long seniorId) { return ResponseEntity.ok(guardService.readOneSenior(memberId, seniorId)); } @Operation(summary = "시니어 정보 수정", description = "시니어의 정보를 수정합니다.") @PutMapping("/senior/{seniorId}") - public ResponseEntity updateSenior(@MemberId Long memberId, @PathVariable Long seniorId, @RequestBody SeniorRequest seniorRequest) { + public ResponseEntity updateSenior(@RequestAttribute("memberId") Long memberId, @PathVariable Long seniorId, @RequestBody SeniorRequest seniorRequest) { guardService.updateSenior(memberId, seniorId, seniorRequest); return ResponseEntity.ok("시니어 정보가 수정되었습니다."); } @Operation(summary = "시니어 추가", description = "보호자가 새로운 시니어를 등록합니다.") @PostMapping("/senior") - public ResponseEntity createSenior(@MemberId Long memberId, @RequestBody SeniorRequest seniorRequest) { + public ResponseEntity createSenior(@RequestAttribute("memberId") Long memberId, @RequestBody SeniorRequest seniorRequest) { guardService.createSenior(memberId, seniorRequest); return ResponseEntity.ok("새로운 시니어가 등록되었습니다."); } @Operation(summary = "시니어 삭제", description = "보호자가 시니어를 등록 해제합니다.") @DeleteMapping("/senior/{seniorId}") - public ResponseEntity deleteSenior(@MemberId Long memberId, @PathVariable Long seniorId) { + public ResponseEntity deleteSenior(@RequestAttribute("memberId") Long memberId, @PathVariable Long seniorId) { guardService.deleteSenior(memberId, seniorId); return ResponseEntity.ok("시니어가 삭제되었습니다."); } @Operation(summary = "보호자 본인 정보 조회", description = "보호자의 본인 정보를 조회합니다.") @GetMapping - public ResponseEntity getGuardInfo(@MemberId Long memberId) { + public ResponseEntity getGuardInfo(@RequestAttribute("memberId") Long memberId) { return ResponseEntity.ok(guardService.readGuard(memberId)); } @Operation(summary = "보호자 본인 정보 수정", description = "보호자의 본인 정보를 수정합니다.") @PutMapping - public ResponseEntity updateGuardInfo(@MemberId Long memberId, @RequestBody GuardRequest guardRequest) { + public ResponseEntity updateGuardInfo(@RequestAttribute("memberId") Long memberId, @RequestBody GuardRequest guardRequest) { guardService.updateGuard(memberId, guardRequest); return ResponseEntity.ok("보호자 정보가 수정되었습니다."); } @@ -72,14 +71,14 @@ public ResponseEntity updateGuardInfo(@MemberId Long memberId, @RequestB // 현재는 jwt 안의 id를 삭제하게 구현했는데, 나중에 관리자 계정 만들면 특정 id 지정해서 삭제하게 수정해야할 듯합니다. @Operation(summary = "보호자 삭제", description = "관리자용 API입니다.") @DeleteMapping - public ResponseEntity deleteGuard(@MemberId Long memberId) { + public ResponseEntity deleteGuard(@RequestAttribute("memberId") Long memberId) { guardService.deleteGuard(memberId); return ResponseEntity.ok("보호자가 삭제되었습니다."); } @Operation(summary = "모든 보호자 조회", description = "관리자용 API입니다.") @GetMapping("/all") - public ResponseEntity> getAllGuards(@MemberId Long memberId) { + public ResponseEntity> getAllGuards() { return ResponseEntity.ok(guardService.readAllGuards()); } diff --git a/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineController.java b/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineController.java index 6976a65b..41333565 100644 --- a/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineController.java +++ b/src/main/java/com/example/sinitto/guardGuideline/controller/GuardGuidelineController.java @@ -1,6 +1,5 @@ package com.example.sinitto.guardGuideline.controller; -import com.example.sinitto.common.annotation.MemberId; import com.example.sinitto.guardGuideline.dto.GuardGuidelineRequest; import com.example.sinitto.guardGuideline.dto.GuardGuidelineResponse; import com.example.sinitto.guardGuideline.entity.GuardGuideline; @@ -25,33 +24,33 @@ public GuardGuidelineController(GuardGuidelineService guardGuidelineService) { @Operation(summary = "가이드라인 추가", description = "보호자가 시니어별 가이드라인을 추가합니다.") @PostMapping - public ResponseEntity addGuardGuideline(@MemberId Long memberId, @RequestBody GuardGuidelineRequest guardGuidelineRequest) { + public ResponseEntity addGuardGuideline(@RequestAttribute("memberId") Long memberId, @RequestBody GuardGuidelineRequest guardGuidelineRequest) { guardGuidelineService.addGuardGuideline(memberId, guardGuidelineRequest); return ResponseEntity.ok("가이드라인이 추가되었습니다."); } @Operation(summary = "카테고리에 해당하는 모든 가이드라인 조회(보호자용)", description = "보호자용 앱에서 카테고리에 해당하는 모든 가이드라인들을 요청할 때 필요합니다.") @GetMapping("/guard/{seniorId}/{type}") - public ResponseEntity> getGuardGuidelinesByCategoryAndSenior(@MemberId Long memberId, @PathVariable Long seniorId, @PathVariable GuardGuideline.Type type) { + public ResponseEntity> getGuardGuidelinesByCategoryAndSenior(@RequestAttribute("memberId") Long memberId, @PathVariable Long seniorId, @PathVariable GuardGuideline.Type type) { return ResponseEntity.ok(guardGuidelineService.readAllGuardGuidelinesByCategoryAndSenior(memberId, seniorId, type)); } @Operation(summary = "카테고리에 해당하는 모든 가이드라인 조회(시니또용)", description = "시니또용 앱에서 카테고리에 해당하는 모든 가이드라인들을 요청할 때 필요합니다.") @GetMapping("/sinitto/{callbackId}/{type}") - public ResponseEntity> getGuardGuidelinesByCategoryAndCallback(@MemberId Long memberId, @PathVariable Long callbackId, @PathVariable GuardGuideline.Type type) { + public ResponseEntity> getGuardGuidelinesByCategoryAndCallback(@RequestAttribute("memberId") Long memberId, @PathVariable Long callbackId, @PathVariable GuardGuideline.Type type) { return ResponseEntity.ok(guardGuidelineService.readAllGuardGuidelinesByCategoryAndCallback(memberId, callbackId, type)); } @Operation(summary = "가이드라인 수정", description = "보호자가 특정 가이드라인을 수정할 때 필요합니다.") @PutMapping("/{guidelineId}") - public ResponseEntity updateGuardGuideline(@MemberId Long memberId, @PathVariable Long guidelineId, @RequestBody GuardGuidelineRequest guardGuidelineRequest) { + public ResponseEntity updateGuardGuideline(@RequestAttribute("memberId") Long memberId, @PathVariable Long guidelineId, @RequestBody GuardGuidelineRequest guardGuidelineRequest) { guardGuidelineService.updateGuardGuideline(memberId, guidelineId, guardGuidelineRequest); return ResponseEntity.ok("가이드라인이 수정되었습니다."); } @Operation(summary = "모든 가이드라인 조회(시니어별로)", description = "보호자가 가이드라인 수정을 위해 시니어별로 모든 가이드라인을 요청할 때 필요합니다.") @GetMapping("/{seniorId}") - public ResponseEntity> getAllGuardGuidelinesBySenior(@MemberId Long memberId, @PathVariable Long seniorId) { + public ResponseEntity> getAllGuardGuidelinesBySenior(@RequestAttribute("memberId") Long memberId, @PathVariable Long seniorId) { return ResponseEntity.ok(guardGuidelineService.readAllGuardGuidelinesBySenior(memberId, seniorId)); } @@ -59,7 +58,7 @@ public ResponseEntity> getAllGuardGuidelinesBySenio @Operation(summary = "특정 가이드라인 삭제", description = "보호자용 API입니다.") @DeleteMapping("/delete") - public ResponseEntity deleteGuardGuideline(@MemberId Long memberId, @RequestParam("guidelineId") Long guidelineId) { + public ResponseEntity deleteGuardGuideline(@RequestAttribute("memberId") Long memberId, @RequestParam("guidelineId") Long guidelineId) { guardGuidelineService.deleteGuardGuideline(memberId, guidelineId); return ResponseEntity.ok("가이드라인이 삭제되었습니다."); } diff --git a/src/main/java/com/example/sinitto/helloCall/controller/HelloCallController.java b/src/main/java/com/example/sinitto/helloCall/controller/HelloCallController.java index 5d04ded6..fef1b941 100644 --- a/src/main/java/com/example/sinitto/helloCall/controller/HelloCallController.java +++ b/src/main/java/com/example/sinitto/helloCall/controller/HelloCallController.java @@ -1,6 +1,5 @@ package com.example.sinitto.helloCall.controller; -import com.example.sinitto.common.annotation.MemberId; import com.example.sinitto.helloCall.dto.*; import com.example.sinitto.helloCall.service.HelloCallPriceService; import com.example.sinitto.helloCall.service.HelloCallService; @@ -31,7 +30,7 @@ public HelloCallController(HelloCallService helloCallService, HelloCallPriceServ @Operation(summary = "[시니또용] 안부 전화 서비스 전체 리스트 보기", description = "안부전화 신청정보를 페이지로 조회합니다.") @GetMapping("/sinittos/list") - public ResponseEntity> getHelloCallListBySinitto(@PageableDefault(size = 10, sort = "helloCallId", direction = Sort.Direction.ASC) Pageable pageable) { + public ResponseEntity> getHelloCallListBySinitto(@RequestAttribute("memberId") Long memberId, @PageableDefault(size = 10, sort = "helloCallId", direction = Sort.Direction.ASC) Pageable pageable) { Page helloCallResponses = helloCallService.readAllWaitingHelloCallsBySinitto(pageable); @@ -40,7 +39,7 @@ public ResponseEntity> getHelloCallListBySinitto(@Pageab @Operation(summary = "[보호자용] 보호자가 신청한 안부전화 리스트 보기", description = "보호자 본인이 신청한 안부전화 리스트를 조회합니다.") @GetMapping("/guards/lists") - public ResponseEntity> getHelloCallListByGuard(@MemberId Long memberId) { + public ResponseEntity> getHelloCallListByGuard(@RequestAttribute("memberId") Long memberId) { List helloCallResponses = helloCallService.readAllHelloCallsByGuard(memberId); @@ -49,7 +48,7 @@ public ResponseEntity> getHelloCallListByGuard(@MemberId @Operation(summary = "[시니또, 보호자용] 선택한 안부 전화 서비스의 상세정보 보기", description = "안부전화 신청정보의 상세정보를 조회합니다.") @GetMapping("/{callId}") - public ResponseEntity getHelloCallDetail(@PathVariable Long callId) { + public ResponseEntity getHelloCallDetail(@RequestAttribute("memberId") Long memberId, @PathVariable Long callId) { HelloCallDetailResponse helloCallDetailResponse = helloCallService.readHelloCallDetail(callId); @@ -58,7 +57,7 @@ public ResponseEntity getHelloCallDetail(@PathVariable @Operation(summary = "[보호자용] 안부 전화 서비스 비용 조회", description = "안부 전화 서비스의 이용 비용을 조회합니다.") @PostMapping("/guards/cost") - public ResponseEntity calculateHelloCallPrice(@RequestBody HelloCallPriceRequest helloCallPriceRequest) { + public ResponseEntity calculateHelloCallPrice(@RequestAttribute("memberId") Long memberId, @RequestBody HelloCallPriceRequest helloCallPriceRequest) { HelloCallPriceResponse helloCallPriceResponse = helloCallPriceService.calculateHelloCallPrice(helloCallPriceRequest); @@ -67,7 +66,7 @@ public ResponseEntity calculateHelloCallPrice(@RequestBo @Operation(summary = "[보호자용] 안부 전화 서비스 신청하기", description = "보호자가 안부 전화 서비스를 신청합니다.") @PostMapping("/guards") - public ResponseEntity createHelloCallByGuard(@MemberId Long memberId, @RequestBody HelloCallRequest helloCallRequest) { + public ResponseEntity createHelloCallByGuard(@RequestAttribute("memberId") Long memberId, @RequestBody HelloCallRequest helloCallRequest) { helloCallService.createHelloCallByGuard(memberId, helloCallRequest); @@ -76,7 +75,7 @@ public ResponseEntity createHelloCallByGuard(@MemberId Lo @Operation(summary = "[보호자용] 안부 전화 서비스 삭제하기", description = "보호자가 안부 전화 서비스 신청을 취소합니다.") @DeleteMapping("/guards/{callId}") - public ResponseEntity deleteHelloCallByGuard(@MemberId Long memberId, @PathVariable Long callId) { + public ResponseEntity deleteHelloCallByGuard(@RequestAttribute("memberId") Long memberId, @PathVariable Long callId) { helloCallService.deleteHellCallByGuard(memberId, callId); @@ -85,7 +84,7 @@ public ResponseEntity deleteHelloCallByGuard(@MemberId Lo @Operation(summary = "[시니또용] 서비스 수락하기", description = "시니또가 안부전화 신청을 수락합니다.") @PutMapping("/accept/{callId}") - public ResponseEntity acceptHelloCall(@MemberId Long memberId, @PathVariable Long callId) { + public ResponseEntity acceptHelloCall(@RequestAttribute("memberId") Long memberId, @PathVariable Long callId) { helloCallService.acceptHelloCallBySinitto(memberId, callId); @@ -94,7 +93,7 @@ public ResponseEntity acceptHelloCall(@MemberId Long memb @Operation(summary = "[시니또용] 시니또가 수락한 안부전화 리스트 조회", description = "시니또가 수락한 안부전화 리스트를 조회합니다.") @GetMapping("/own") - public ResponseEntity> readOwnHelloCallBySinitto(@MemberId Long memberId) { + public ResponseEntity> readOwnHelloCallBySinitto(@RequestAttribute("memberId") Long memberId) { List helloCallResponses = helloCallService.readOwnHelloCallBySinitto(memberId); @@ -103,7 +102,7 @@ public ResponseEntity> readOwnHelloCallBySinitto(@Member @Operation(summary = "[시니또용] 안부전화 서비스 시작시간 기록", description = "시니또가 안부전화 시작시간을 기록합니다.") @PostMapping("/sinittos/start/{callId}") - public ResponseEntity writeHelloCallStartTimeBySinitto(@MemberId Long memberId, @PathVariable Long callId) { + public ResponseEntity writeHelloCallStartTimeBySinitto(@RequestAttribute("memberId") Long memberId, @PathVariable Long callId) { helloCallService.writeHelloCallStartTimeBySinitto(memberId, callId); @@ -112,7 +111,7 @@ public ResponseEntity writeHelloCallStartTimeBySinitto(@M @Operation(summary = "[시니또용] 안부전화 서비스 종료시간 기록", description = "시니또가 안부전화 종료시간을 기록합니다.") @PostMapping("/sinittos/end/{callId}") - public ResponseEntity writeHelloCallEndTimeBySinitto(@MemberId Long memberId, @PathVariable Long callId) { + public ResponseEntity writeHelloCallEndTimeBySinitto(@RequestAttribute("memberId") Long memberId, @PathVariable Long callId) { helloCallService.writeHelloCallEndTimeBySinitto(memberId, callId); @@ -121,7 +120,7 @@ public ResponseEntity writeHelloCallEndTimeBySinitto(@Mem @Operation(summary = "[시니또용] 소통 보고서 작성 및 완료 대기 상태 변경", description = "시니또가 최종 안부전화 후에 보고서를 작성합니다.") @PostMapping("/reports") - public ResponseEntity createHelloCallReport(@MemberId Long memberId, @RequestBody HelloCallReportRequest request) { + public ResponseEntity createHelloCallReport(@RequestAttribute("memberId") Long memberId, @RequestBody HelloCallReportRequest request) { helloCallService.sendReportBySinitto(memberId, request); @@ -130,7 +129,7 @@ public ResponseEntity createHelloCallReport(@MemberId Lon @Operation(summary = "[보호자용] 완료 대기 상태 안부전화 완료 처리", description = "보호자가 완료 대기 상태인 안부전화의 상태를 완료로 변경합니다.") @PutMapping("/complete/{callId}") - public ResponseEntity completeHelloCall(@MemberId Long memberId, @PathVariable Long callId) { + public ResponseEntity completeHelloCall(@RequestAttribute("memberId") Long memberId, @PathVariable Long callId) { helloCallService.makeCompleteHelloCallByGuard(memberId, callId); @@ -139,7 +138,7 @@ public ResponseEntity completeHelloCall(@MemberId Long me @Operation(summary = "[보호자용] 안부전화 타임로그 조회", description = "보호자가 안부전화를 수행한 시니또의 전화 타임로그를 리스트로 조회합니다.") @GetMapping("/guards/log/{callId}") - public ResponseEntity> readHelloCallTimeLogByGuard(@MemberId Long memberId, @PathVariable Long callId) { + public ResponseEntity> readHelloCallTimeLogByGuard(@RequestAttribute("memberId") Long memberId, @PathVariable Long callId) { List helloCallTimeLogResponses = helloCallService.readHelloCallTimeLogByGuard(memberId, callId); @@ -149,7 +148,7 @@ public ResponseEntity> readHelloCallTimeLogByGuar @Operation(summary = "[보호자용] 소통 보고서 조회", description = "보호자가 시니또가 작성한 보고서가 있다면 보고서를 조회합니다.") @GetMapping("/reports/{callId}") - public ResponseEntity getHelloCallReportDetail(@MemberId Long memberId, @PathVariable Long callId) { + public ResponseEntity getHelloCallReportDetail(@RequestAttribute("memberId") Long memberId, @PathVariable Long callId) { HelloCallReportResponse helloCallReportResponse = helloCallService.readHelloCallReportByGuard(memberId, callId); @@ -158,7 +157,7 @@ public ResponseEntity getHelloCallReportDetail(@MemberI @Operation(summary = "[시니또용] 진행중인 안부 서비스 취소 요청", description = "시니또가 진행중인 안부전화 서비스를 취소합니다. 취소시 포인트는 받을 수 없습니다.") @PutMapping("/cancel/{callId}") - public ResponseEntity cancelHelloCall(@MemberId Long memberId, @PathVariable Long callId) { + public ResponseEntity cancelHelloCall(@RequestAttribute("memberId") Long memberId, @PathVariable Long callId) { helloCallService.cancelHelloCallBySinitto(memberId, callId); diff --git a/src/main/java/com/example/sinitto/member/controller/MemberController.java b/src/main/java/com/example/sinitto/member/controller/MemberController.java index e063f39c..04453591 100644 --- a/src/main/java/com/example/sinitto/member/controller/MemberController.java +++ b/src/main/java/com/example/sinitto/member/controller/MemberController.java @@ -1,7 +1,6 @@ package com.example.sinitto.member.controller; import com.example.sinitto.member.dto.RegisterResponse; -import com.example.sinitto.common.annotation.MemberId; import com.example.sinitto.member.dto.SignupRequest; import com.example.sinitto.member.service.MemberService; import io.swagger.v3.oas.annotations.Operation; @@ -40,14 +39,14 @@ public ResponseEntity guardSignup(@RequestBody SignupRequest r @Operation(summary = "멤버 로그아웃", description = "레디스에 저장되어있는 멤버의 refreshToken을 삭제합니다.") @DeleteMapping("/logout") - public ResponseEntity memberLogout(@MemberId Long memberId) { + public ResponseEntity memberLogout(@RequestAttribute("memberId") Long memberId) { memberService.memberLogout(memberId); return ResponseEntity.ok().build(); } @Operation(summary = "멤버 회원탈퇴", description = "회원 정보를 삭제합니다.") @DeleteMapping("/withdrawal") - public ResponseEntity deleteMember(@MemberId Long memberId) { + public ResponseEntity deleteMember(@RequestAttribute("memberId") Long memberId) { memberService.deleteMember(memberId); return ResponseEntity.ok().build(); } diff --git a/src/main/java/com/example/sinitto/member/service/MemberService.java b/src/main/java/com/example/sinitto/member/service/MemberService.java index 22e32d49..36bbd723 100644 --- a/src/main/java/com/example/sinitto/member/service/MemberService.java +++ b/src/main/java/com/example/sinitto/member/service/MemberService.java @@ -9,7 +9,6 @@ import com.example.sinitto.callback.service.CallbackService; import com.example.sinitto.common.exception.ConflictException; import com.example.sinitto.common.exception.NotFoundException; -import com.example.sinitto.common.resolver.MemberIdProvider; import com.example.sinitto.helloCall.service.HelloCallService; import com.example.sinitto.member.dto.RegisterResponse; import com.example.sinitto.member.entity.Member; @@ -23,7 +22,7 @@ import java.util.Optional; @Service -public class MemberService implements MemberIdProvider { +public class MemberService{ private final MemberRepository memberRepository; private final TokenService tokenService; @@ -45,15 +44,6 @@ public MemberService(MemberRepository memberRepository, TokenService tokenServic this.helloCallService = helloCallService; } - @Override - public Long getMemberIdByToken(String token) { - String email = tokenService.extractEmailFromAccessToken(token); - Member member = memberRepository.findByEmail(email).orElseThrow( - () -> new NotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") - ); - return member.getId(); - } - public LoginResponse kakaoLogin(String authorizationCode, HttpServletRequest httpServletRequest) { KakaoTokenResponse kakaoTokenResponse = kakaoApiService.getAccessToken(authorizationCode, httpServletRequest); KakaoUserResponse kakaoUserResponse = kakaoApiService.getUserInfo(kakaoTokenResponse.accessToken()); diff --git a/src/main/java/com/example/sinitto/member/service/MemberTokenService.java b/src/main/java/com/example/sinitto/member/service/MemberTokenService.java new file mode 100644 index 00000000..fd18ef08 --- /dev/null +++ b/src/main/java/com/example/sinitto/member/service/MemberTokenService.java @@ -0,0 +1,26 @@ +package com.example.sinitto.member.service; + +import com.example.sinitto.auth.service.TokenService; +import com.example.sinitto.common.exception.NotFoundException; +import com.example.sinitto.member.entity.Member; +import com.example.sinitto.member.repository.MemberRepository; +import org.springframework.stereotype.Service; + +@Service +public class MemberTokenService { + private final TokenService tokenService; + private final MemberRepository memberRepository; + + public MemberTokenService(TokenService tokenService, MemberRepository memberRepository){ + this.tokenService = tokenService; + this.memberRepository = memberRepository; + } + + public Long getMemberIdByToken(String token) { + String email = tokenService.extractEmailFromAccessToken(token); + Member member = memberRepository.findByEmail(email).orElseThrow( + () -> new NotFoundException("이메일에 해당하는 멤버를 찾을 수 없습니다.") + ); + return member.getId(); + } +} diff --git a/src/main/java/com/example/sinitto/point/controller/PointController.java b/src/main/java/com/example/sinitto/point/controller/PointController.java index 4806f7a4..a65f0fd1 100644 --- a/src/main/java/com/example/sinitto/point/controller/PointController.java +++ b/src/main/java/com/example/sinitto/point/controller/PointController.java @@ -1,6 +1,5 @@ package com.example.sinitto.point.controller; -import com.example.sinitto.common.annotation.MemberId; import com.example.sinitto.point.dto.PointChargeResponse; import com.example.sinitto.point.dto.PointLogResponse; import com.example.sinitto.point.dto.PointRequest; @@ -28,14 +27,14 @@ public PointController(PointService pointService) { @Operation(summary = "포인트 조회", description = "시니또, 보호자가 본인의 포인트를 조회합니다.") @GetMapping() - public ResponseEntity getPoint(@MemberId Long memberId) { + public ResponseEntity getPoint(@RequestAttribute("memberId") Long memberId) { return ResponseEntity.ok(pointService.getPoint(memberId)); } @Operation(summary = "포인트 충전 요청", description = "관리자가 직접 추가 - 바로 충전 되는거 아님. 신청->대기->완료 완료시점에 충전 됨") @PutMapping("/charge") - public ResponseEntity savePointChargeRequest(@MemberId Long memberId, + public ResponseEntity savePointChargeRequest(@RequestAttribute("memberId") Long memberId, @RequestBody PointRequest request) { return ResponseEntity.ok(pointService.savePointChargeRequest(memberId, request.price())); @@ -43,7 +42,7 @@ public ResponseEntity savePointChargeRequest(@MemberId Long @Operation(summary = "포인트 출금 요청", description = "시니또가 포인트 출금을 요청합니다.") @PostMapping("/withdraw") - public ResponseEntity savePointWithdrawRequest(@MemberId Long memberId, + public ResponseEntity savePointWithdrawRequest(@RequestAttribute("memberId") Long memberId, @RequestBody PointRequest request) { pointService.savePointWithdrawRequest(memberId, request.price()); @@ -52,7 +51,7 @@ public ResponseEntity savePointWithdrawRequest(@MemberId Long memberId, @Operation(summary = "포인트 로그 조회", description = "포인트 로그를 조회합니다.") @GetMapping("/logs") - public ResponseEntity> getPointLogs(@MemberId Long memberId, + public ResponseEntity> getPointLogs(@RequestAttribute("memberId") Long memberId, @PageableDefault(sort = "postTime", direction = Sort.Direction.DESC) Pageable pageable) { return ResponseEntity.ok(pointService.getPointLogs(memberId, pageable)); diff --git a/src/main/java/com/example/sinitto/review/controller/ReviewController.java b/src/main/java/com/example/sinitto/review/controller/ReviewController.java index ad35d427..89929498 100644 --- a/src/main/java/com/example/sinitto/review/controller/ReviewController.java +++ b/src/main/java/com/example/sinitto/review/controller/ReviewController.java @@ -1,6 +1,5 @@ package com.example.sinitto.review.controller; -import com.example.sinitto.common.annotation.MemberId; import com.example.sinitto.review.dto.ReviewRequest; import com.example.sinitto.review.dto.ReviewResponse; import com.example.sinitto.review.service.ReviewService; @@ -9,7 +8,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.ArrayList; import java.util.List; @RestController @@ -30,7 +28,7 @@ public ResponseEntity> getReviewList() { @Operation(summary = "서비스 리뷰 및 평가 제출", description = "시니또에 대한 별점과 작성한 평가 내용(선택사항)을 제출합니다.") @PostMapping - public ResponseEntity submitReview(@MemberId Long memberId, @RequestBody ReviewRequest reviewRequest) { + public ResponseEntity submitReview(@RequestAttribute("memberId") Long memberId, @RequestBody ReviewRequest reviewRequest) { reviewService.createReview(memberId, reviewRequest); return ResponseEntity.ok("리뷰가 성공적으로 제출되었습니다."); } diff --git a/src/main/java/com/example/sinitto/sinitto/controller/SinittoController.java b/src/main/java/com/example/sinitto/sinitto/controller/SinittoController.java index 301702e1..8ca98e3f 100644 --- a/src/main/java/com/example/sinitto/sinitto/controller/SinittoController.java +++ b/src/main/java/com/example/sinitto/sinitto/controller/SinittoController.java @@ -1,6 +1,5 @@ package com.example.sinitto.sinitto.controller; -import com.example.sinitto.common.annotation.MemberId; import com.example.sinitto.sinitto.dto.SinittoBankRequest; import com.example.sinitto.sinitto.dto.SinittoBankResponse; import com.example.sinitto.sinitto.dto.SinittoRequest; @@ -24,33 +23,33 @@ public SinittoController(SinittoService sinittoService) { @Operation(summary = "시니또 본인 정보 조회", description = "시니또 본인의 정보를 요청한다.") @GetMapping - public ResponseEntity getSinittoInfo(@MemberId Long memberId) { + public ResponseEntity getSinittoInfo(@RequestAttribute("memberId") Long memberId) { return ResponseEntity.ok(sinittoService.readSinitto(memberId)); } @Operation(summary = "시니또 계좌 정보 조회", description = "시니또의 계좌 정보를 요청한다.") @GetMapping("/bank") - public ResponseEntity getSinittoBankInfo(@MemberId Long memberId) { + public ResponseEntity getSinittoBankInfo(@RequestAttribute("memberId") Long memberId) { return ResponseEntity.ok(sinittoService.readSinittoBankInfo(memberId)); } @Operation(summary = "계좌정보 등록", description = "시니또가 계좌정보 등록합니다.") @PostMapping("/bank") - public ResponseEntity createSeniorBankInfo(@MemberId Long memberId, @RequestBody SinittoBankRequest sinittoBankRequest) { + public ResponseEntity createSeniorBankInfo(@RequestAttribute("memberId") Long memberId, @RequestBody SinittoBankRequest sinittoBankRequest) { sinittoService.createSinittoBankInfo(memberId, sinittoBankRequest); return ResponseEntity.ok("계좌등록되었습니다."); } @Operation(summary = "시니또 본인 정보 수정", description = "시니또 본인의 정보를 수정요청한다.") @PutMapping - public ResponseEntity updateSinitto(@MemberId Long memberId, @RequestBody SinittoRequest sinittoRequest) { + public ResponseEntity updateSinitto(@RequestAttribute("memberId") Long memberId, @RequestBody SinittoRequest sinittoRequest) { sinittoService.updateSinitto(memberId, sinittoRequest); return ResponseEntity.ok("시니또 정보가 수정되었습니다."); } @Operation(summary = "시니또 계좌 정보 수정", description = "시니또 본인의 정보를 수정요청한다.") @PutMapping("/bank") - public ResponseEntity updateSinittoBankInfo(@MemberId Long memberId, @RequestBody SinittoBankRequest sinittoBankRequest) { + public ResponseEntity updateSinittoBankInfo(@RequestAttribute("memberId") Long memberId, @RequestBody SinittoBankRequest sinittoBankRequest) { sinittoService.updateSinittoBankInfo(memberId, sinittoBankRequest); return ResponseEntity.ok("시니또 정보가 수정되었습니다."); } diff --git a/src/test/java/com/example/sinitto/member/service/MemberServiceTest.java b/src/test/java/com/example/sinitto/member/service/MemberServiceTest.java index 50b9f6d1..180fec2d 100644 --- a/src/test/java/com/example/sinitto/member/service/MemberServiceTest.java +++ b/src/test/java/com/example/sinitto/member/service/MemberServiceTest.java @@ -46,39 +46,6 @@ public class MemberServiceTest { @Mock HelloCallService helloCallService; - - @Test - @DisplayName("getMemberIdByToken 메소드 테스트") - void getMemberIdByTokenTest() { - //given - String token = "testtoken"; - String email = "test@email.com"; - Member member = mock(Member.class); - - when(tokenService.extractEmailFromAccessToken(token)).thenReturn(email); - when(memberRepository.findByEmail(email)).thenReturn(Optional.of(member)); - - //when - Long result = memberService.getMemberIdByToken(token); - - //then - assertEquals(result, member.getId()); - } - - @Test - @DisplayName("getMemberIdByToken 메소드 테스트 - memberRepository에 없을 경우") - void getMemberIdByTokenTestWhenNotInMemberRepository() { - //given - String token = "testtoken"; - String email = "test@email.com"; - - when(tokenService.extractEmailFromAccessToken(token)).thenReturn(email); - when(memberRepository.findByEmail(email)).thenReturn(Optional.empty()); - - //when, then - assertThrows(NotFoundException.class, () -> memberService.getMemberIdByToken(token)); - } - @Test @DisplayName("registerNewMember 메소드 테스트") void registerNewMemberTest() { diff --git a/src/test/java/com/example/sinitto/member/service/MemberTokenServiceTest.java b/src/test/java/com/example/sinitto/member/service/MemberTokenServiceTest.java new file mode 100644 index 00000000..ac952330 --- /dev/null +++ b/src/test/java/com/example/sinitto/member/service/MemberTokenServiceTest.java @@ -0,0 +1,60 @@ +package com.example.sinitto.member.service; + +import com.example.sinitto.auth.service.TokenService; +import com.example.sinitto.common.exception.NotFoundException; +import com.example.sinitto.member.entity.Member; +import com.example.sinitto.member.repository.MemberRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoSettings; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@MockitoSettings +public class MemberTokenServiceTest { + @Mock + TokenService tokenService; + @Mock + MemberRepository memberRepository; + @InjectMocks + MemberTokenService memberTokenService; + + @Test + @DisplayName("getMemberIdByToken 메소드 테스트") + void getMemberIdByTokenTest() { + //given + String token = "testtoken"; + String email = "test@email.com"; + Member member = mock(Member.class); + + when(tokenService.extractEmailFromAccessToken(token)).thenReturn(email); + when(memberRepository.findByEmail(email)).thenReturn(Optional.of(member)); + + //when + Long result = memberTokenService.getMemberIdByToken(token); + + //then + assertEquals(result, member.getId()); + } + + @Test + @DisplayName("getMemberIdByToken 메소드 테스트 - memberRepository에 없을 경우") + void getMemberIdByTokenTestWhenNotInMemberRepository() { + //given + String token = "testtoken"; + String email = "test@email.com"; + + when(tokenService.extractEmailFromAccessToken(token)).thenReturn(email); + when(memberRepository.findByEmail(email)).thenReturn(Optional.empty()); + + //when, then + assertThrows(NotFoundException.class, () -> memberTokenService.getMemberIdByToken(token)); + } +}