diff --git a/majorLink/src/main/java/com/example/majorLink/controller/NotificationController.java b/majorLink/src/main/java/com/example/majorLink/controller/NotificationController.java index 313e077..563777d 100644 --- a/majorLink/src/main/java/com/example/majorLink/controller/NotificationController.java +++ b/majorLink/src/main/java/com/example/majorLink/controller/NotificationController.java @@ -3,37 +3,64 @@ import com.example.majorLink.domain.User; import com.example.majorLink.dto.response.NotificationResponse; import com.example.majorLink.global.auth.AuthUser; +import com.example.majorLink.global.jwt.JwtService; import com.example.majorLink.service.NotificationService; +import io.jsonwebtoken.Claims; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.util.List; +import java.util.UUID; @RestController @RequestMapping("/notification") @RequiredArgsConstructor public class NotificationController { private final NotificationService notificationService; + private final JwtService jwtService; /** * 알림을 위한 구독 API - * [GET] /notification/subscribe + * [GET] /notification/subscribe/{X-AUTH-TOKEN} * @param lastEventId - * @param userId + * @param token * @return */ // Last-Event-ID는 SSE 연결이 끊어졌을 경우, 클라이언트가 수신한 마지막 데이터 ID 값을 의미, 항상 존재 X -> false @GetMapping(value = "/subscribe/{X-AUTH-TOKEN}", produces = "text/event-stream") public SseEmitter subscribe( @RequestHeader(value = "Last-Event-ID", required = false, defaultValue = "") String lastEventId, - @PathVariable("X-AUTH-TOKEN") String userId) { - return notificationService.subscribe(userId, lastEventId); + @PathVariable("X-AUTH-TOKEN") String token // 경로 변수로 토큰을 받음 + ) { + + // 토큰 유효성 검사 + if (!jwtService.checkValidationToken(token)) { + throw new RuntimeException("유효하지 않은 토큰입니다."); + } + + // 토큰에서 사용자 UUID 추출 + Claims claims = jwtService.getClaims(token); + String userId = claims.get("uuid", String.class); + + // UUID 변환 및 검증 + UUID userUuid; + try { + userUuid = UUID.fromString(userId); + } catch (IllegalArgumentException e) { + throw new RuntimeException("유효하지 않은 UUID입니다.", e); + } + + // notificationService를 통해 사용자 구독 처리 + return notificationService.subscribe(userUuid, lastEventId); } + // 수강 신청 시 튜터에게 알림 전달 /** diff --git a/majorLink/src/main/java/com/example/majorLink/service/NotificationService.java b/majorLink/src/main/java/com/example/majorLink/service/NotificationService.java index ebd5601..2f563d5 100644 --- a/majorLink/src/main/java/com/example/majorLink/service/NotificationService.java +++ b/majorLink/src/main/java/com/example/majorLink/service/NotificationService.java @@ -5,9 +5,10 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.util.List; +import java.util.UUID; public interface NotificationService { - SseEmitter subscribe(String userId, String lastEventId); + SseEmitter subscribe(UUID userId, String lastEventId); void send(User sender, Long lectureId, String content); // 전체 알림 조회 diff --git a/majorLink/src/main/java/com/example/majorLink/service/NotificationServiceImpl.java b/majorLink/src/main/java/com/example/majorLink/service/NotificationServiceImpl.java index 1691510..fdc2cbc 100644 --- a/majorLink/src/main/java/com/example/majorLink/service/NotificationServiceImpl.java +++ b/majorLink/src/main/java/com/example/majorLink/service/NotificationServiceImpl.java @@ -30,7 +30,7 @@ public class NotificationServiceImpl implements NotificationService { private final LectureRepository lectureRepository; @Override - public SseEmitter subscribe(String userId, String lastEventId) { + public SseEmitter subscribe(UUID userId, String lastEventId) { // 토큰을 고유 식별자로 사용하여 emitterId를 생성합니다. String emitterId = userId + "_" + System.currentTimeMillis(); SseEmitter emitter = emitterRepository.save(emitterId, new SseEmitter(DEFAULT_TIMEOUT)); @@ -47,7 +47,7 @@ public SseEmitter subscribe(String userId, String lastEventId) { sendToClient(emitter, emitterId, "EventStream Create. [userId = " + userId + "]"); if (!lastEventId.isEmpty()) { - Map events = emitterRepository.findAllEventCacheStartWithByUserId(UUID.fromString(userId)); + Map events = emitterRepository.findAllEventCacheStartWithByUserId(userId); events.entrySet().stream() .filter(entry -> lastEventId.compareTo(entry.getKey()) < 0) .forEach(entry -> sendToClient(emitter, entry.getKey(), entry.getValue()));