Skip to content

Commit

Permalink
Refactor : ArgumentResolver -> Interceptor로 변경 (#200)
Browse files Browse the repository at this point in the history
* feat : JwtInterceptor 클래스 추가

* refactor : 순환 참조 방지를 위해 메소드 분리

* feat : JwtInterceptor 적용

* refactor : 순환 참조 방지를 위해 메소드 분리

* refactor : 리뷰 조회 경로 변경

* feat : memberId 수정

* refactor : 테스트 코드 수정

* refactor : review 경로 변경

* feat : 메소드의 파라미터에 Long 타입이 있을 때(memberId가 있을 때) jwt 검증하도록 수정

* refactor : 수정했던 경로 복구

* refactor : 관리자용 메소드의 memberId 파라미터 삭제
  • Loading branch information
2iedo authored Nov 8, 2024
1 parent 9b41fec commit 6472e57
Show file tree
Hide file tree
Showing 18 changed files with 194 additions and 185 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -27,15 +26,15 @@ public CallbackController(CallbackService callbackService) {

@Operation(summary = "콜백 전화 리스트 보기(페이지)", description = "시니어가 요청한 콜백전화를 페이징으로 보여줍니다.")
@GetMapping
public ResponseEntity<Page<CallbackResponse>> getWaitingCallbackList(@MemberId Long memberId,
public ResponseEntity<Page<CallbackResponse>> getWaitingCallbackList(@RequestAttribute("memberId") Long memberId,
@PageableDefault(sort = "postTime", direction = Sort.Direction.DESC) Pageable pageable) {

return ResponseEntity.ok(callbackService.getWaitingCallbacks(memberId, pageable));
}

@Operation(summary = "진행 상태인 콜백을 완료 대기 상태로 전환(시니또가)", description = "시니또가 수락한 콜백 수행을 완료했을때 이 api 호출하면 완료 대기 상태로 변합니다.")
@PutMapping("/pendingComplete/{callbackId}")
public ResponseEntity<Void> pendingCompleteCallback(@MemberId Long memberId,
public ResponseEntity<Void> pendingCompleteCallback(@RequestAttribute("memberId") Long memberId,
@PathVariable Long callbackId) {

callbackService.changeCallbackStatusToPendingCompleteBySinitto(memberId, callbackId);
Expand All @@ -44,7 +43,7 @@ public ResponseEntity<Void> pendingCompleteCallback(@MemberId Long memberId,

@Operation(summary = "완료 대기 상태인 콜백을 완료 상태로 전환(보호자가)", description = "보호자가 완료 대기 상태인 콜백을 완료 확정 시킵니다.")
@PutMapping("/complete/{callbackId}")
public ResponseEntity<Void> completeCallback(@MemberId Long memberId,
public ResponseEntity<Void> completeCallback(@RequestAttribute("memberId") Long memberId,
@PathVariable Long callbackId) {

callbackService.changeCallbackStatusToCompleteByGuard(memberId, callbackId);
Expand All @@ -53,7 +52,7 @@ public ResponseEntity<Void> completeCallback(@MemberId Long memberId,

@Operation(summary = "콜백 서비스 수락 신청", description = "시니또가 콜백 서비스 수락을 신청합니다.")
@PutMapping("/accept/{callbackId}")
public ResponseEntity<Void> acceptCallback(@MemberId Long memberId,
public ResponseEntity<Void> acceptCallback(@RequestAttribute("memberId") Long memberId,
@PathVariable Long callbackId) {

callbackService.acceptCallbackBySinitto(memberId, callbackId);
Expand All @@ -62,7 +61,7 @@ public ResponseEntity<Void> acceptCallback(@MemberId Long memberId,

@Operation(summary = "진행중인 콜백 서비스 취소", description = "시니또가 진행중인 콜백 서비스를 취소합니다. 콜백은 다시 대기 상태로 돌아갑니다.")
@PutMapping("/cancel/{callbackId}")
public ResponseEntity<Void> cancelCallback(@MemberId Long memberId,
public ResponseEntity<Void> cancelCallback(@RequestAttribute("memberId") Long memberId,
@PathVariable Long callbackId) {

callbackService.cancelCallbackAssignmentBySinitto(memberId, callbackId);
Expand All @@ -77,22 +76,22 @@ public ResponseEntity<String> addCallCheck(@RequestParam("From") String fromNumb

@Operation(summary = "시니또에게 현재 할당된 콜백 조회", description = "현재 시니또 본인에게 할당된 콜백을 조회합니다.")
@GetMapping("/sinitto/accepted")
public ResponseEntity<CallbackResponse> getAcceptedCallback(@MemberId Long memberId) {
public ResponseEntity<CallbackResponse> getAcceptedCallback(@RequestAttribute("memberId") Long memberId) {

return ResponseEntity.ok(callbackService.getAcceptedCallback(memberId));
}

@Operation(summary = "보호자의 콜백 이용 내역 조회", description = "보호자에게 연관된 모든 콜백 내역을 조회합니다. 기본적으로 최신 내역 부터 조회됩니다.")
@GetMapping("/guard/requested")
public ResponseEntity<Page<CallbackUsageHistoryResponse>> getAcceptedCallback(@MemberId Long memberId,
public ResponseEntity<Page<CallbackUsageHistoryResponse>> getAcceptedCallback(@RequestAttribute("memberId") Long memberId,
@PageableDefault(sort = "postTime", direction = Sort.Direction.DESC) Pageable pageable) {

return ResponseEntity.ok(callbackService.getCallbackHistoryOfGuard(memberId, pageable));
}

@Operation(summary = "콜백 단건 조회 (시니또용)", description = "콜백 id 로 콜백을 단건 조회합니다.")
@GetMapping("/{callbackId}")
public ResponseEntity<CallbackForSinittoResponse> getCallback(@MemberId Long memberId,
public ResponseEntity<CallbackForSinittoResponse> getCallback(@RequestAttribute("memberId") Long memberId,
@PathVariable("callbackId") Long callbackId) {

return ResponseEntity.ok(callbackService.getCallbackForSinitto(memberId, callbackId));
Expand Down
14 changes: 0 additions & 14 deletions src/main/java/com/example/sinitto/common/annotation/MemberId.java

This file was deleted.

This file was deleted.

12 changes: 12 additions & 0 deletions src/main/java/com/example/sinitto/common/config/WebConfig.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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/**");
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -25,61 +24,61 @@ public GuardController(GuardService guardService) {

@Operation(summary = "연결된 모든 시니어 정보 조회", description = "보호자가 등록한 모든 시니어의 정보를 요청합니다.")
@GetMapping("/senior")
public ResponseEntity<List<SeniorResponse>> getAllSeniors(@MemberId Long memberId) {
public ResponseEntity<List<SeniorResponse>> getAllSeniors(@RequestAttribute("memberId") Long memberId) {
return ResponseEntity.ok(guardService.readSeniors(memberId));
}

@Operation(summary = "연결된 특정 시니어 정보 조회", description = "보호자가 등록한 특정 시니어의 정보를 요청합니다.")
@GetMapping("/senior/{seniorId}")
public ResponseEntity<SeniorResponse> getSenior(@MemberId Long memberId, @PathVariable Long seniorId) {
public ResponseEntity<SeniorResponse> getSenior(@RequestAttribute("memberId") Long memberId, @PathVariable Long seniorId) {
return ResponseEntity.ok(guardService.readOneSenior(memberId, seniorId));
}

@Operation(summary = "시니어 정보 수정", description = "시니어의 정보를 수정합니다.")
@PutMapping("/senior/{seniorId}")
public ResponseEntity<String> updateSenior(@MemberId Long memberId, @PathVariable Long seniorId, @RequestBody SeniorRequest seniorRequest) {
public ResponseEntity<String> 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<String> createSenior(@MemberId Long memberId, @RequestBody SeniorRequest seniorRequest) {
public ResponseEntity<String> createSenior(@RequestAttribute("memberId") Long memberId, @RequestBody SeniorRequest seniorRequest) {
guardService.createSenior(memberId, seniorRequest);
return ResponseEntity.ok("새로운 시니어가 등록되었습니다.");
}

@Operation(summary = "시니어 삭제", description = "보호자가 시니어를 등록 해제합니다.")
@DeleteMapping("/senior/{seniorId}")
public ResponseEntity<String> deleteSenior(@MemberId Long memberId, @PathVariable Long seniorId) {
public ResponseEntity<String> deleteSenior(@RequestAttribute("memberId") Long memberId, @PathVariable Long seniorId) {
guardService.deleteSenior(memberId, seniorId);
return ResponseEntity.ok("시니어가 삭제되었습니다.");
}

@Operation(summary = "보호자 본인 정보 조회", description = "보호자의 본인 정보를 조회합니다.")
@GetMapping
public ResponseEntity<GuardResponse> getGuardInfo(@MemberId Long memberId) {
public ResponseEntity<GuardResponse> getGuardInfo(@RequestAttribute("memberId") Long memberId) {
return ResponseEntity.ok(guardService.readGuard(memberId));
}

@Operation(summary = "보호자 본인 정보 수정", description = "보호자의 본인 정보를 수정합니다.")
@PutMapping
public ResponseEntity<String> updateGuardInfo(@MemberId Long memberId, @RequestBody GuardRequest guardRequest) {
public ResponseEntity<String> updateGuardInfo(@RequestAttribute("memberId") Long memberId, @RequestBody GuardRequest guardRequest) {
guardService.updateGuard(memberId, guardRequest);
return ResponseEntity.ok("보호자 정보가 수정되었습니다.");
}

// 현재는 jwt 안의 id를 삭제하게 구현했는데, 나중에 관리자 계정 만들면 특정 id 지정해서 삭제하게 수정해야할 듯합니다.
@Operation(summary = "보호자 삭제", description = "관리자용 API입니다.")
@DeleteMapping
public ResponseEntity<String> deleteGuard(@MemberId Long memberId) {
public ResponseEntity<String> deleteGuard(@RequestAttribute("memberId") Long memberId) {
guardService.deleteGuard(memberId);
return ResponseEntity.ok("보호자가 삭제되었습니다.");
}

@Operation(summary = "모든 보호자 조회", description = "관리자용 API입니다.")
@GetMapping("/all")
public ResponseEntity<List<GuardResponse>> getAllGuards(@MemberId Long memberId) {
public ResponseEntity<List<GuardResponse>> getAllGuards() {
return ResponseEntity.ok(guardService.readAllGuards());
}

Expand Down
Loading

0 comments on commit 6472e57

Please sign in to comment.