From f101d136710b5df4fdb377c6c8177091a0649f9a Mon Sep 17 00:00:00 2001 From: SHEOM Date: Sun, 8 Sep 2024 22:53:31 +0900 Subject: [PATCH] =?UTF-8?q?Feat/authentication=20-=20=EC=9E=90=EC=9B=90=20?= =?UTF-8?q?=EC=9D=B8=EA=B0=80=20=EA=B2=80=EC=A6=9D=20(#72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../active/ActiveSessionController.java | 12 +++++- .../active/service/ActiveSessionService.java | 2 +- .../service/ActiveSessionServiceImpl.java | 6 +-- .../controller/AttendanceController.java | 10 +++-- .../repository/AttendanceRepository.java | 13 ++++++ .../attendance/service/AttendanceService.java | 2 +- .../service/AttendanceServiceImpl.java | 13 +++++- .../service/rdb/AttendanceRDBService.java | 4 +- .../service/rdb/AttendanceRDBServiceImpl.java | 11 +++-- .../controller/AttendeeController.java | 30 +++++++++---- .../command/AttendeeCommandService.java | 6 +-- .../command/AttendeeCommandServiceImpl.java | 19 +++++++-- .../service/query/AttendeeQueryService.java | 2 +- .../query/AttendeeQueryServiceImpl.java | 14 ++++++- .../common/error/GlobalExceptionHandler.java | 7 ++++ .../course/advice/CourseExceptionAdvice.java | 7 ---- .../course/controller/CourseController.java | 6 ++- .../domain/repository/CourseRepository.java | 2 + .../course/service/CourseService.java | 2 +- .../course/service/CourseServiceImpl.java | 25 +++++++---- .../controller/DashBoardController.java | 14 +++++-- .../session/controller/SessionController.java | 38 +++++++++++------ .../domain/repository/SessionRepository.java | 6 +++ .../command/SessionCommandService.java | 8 ++-- .../command/SessionCommandServiceImpl.java | 29 ++++++++++--- .../service/query/SessionQueryService.java | 12 +++--- .../query/SessionQueryServiceImpl.java | 42 ++++++++++++++++--- 27 files changed, 253 insertions(+), 89 deletions(-) diff --git a/src/main/java/com/waruru/areyouhere/active/ActiveSessionController.java b/src/main/java/com/waruru/areyouhere/active/ActiveSessionController.java index f585a4d..0255274 100644 --- a/src/main/java/com/waruru/areyouhere/active/ActiveSessionController.java +++ b/src/main/java/com/waruru/areyouhere/active/ActiveSessionController.java @@ -4,6 +4,9 @@ import com.waruru.areyouhere.attendance.dto.request.AuthCodeDeactivationRequestDto; import com.waruru.areyouhere.attendance.dto.request.AuthCodeRequestDto; import com.waruru.areyouhere.active.service.ActiveSessionService; +import com.waruru.areyouhere.common.annotation.Login; +import com.waruru.areyouhere.common.annotation.LoginRequired; +import com.waruru.areyouhere.manager.domain.entity.Manager; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -23,14 +26,19 @@ public class ActiveSessionController { @PostMapping - public ResponseEntity activate(@RequestBody AuthCodeRequestDto authCodeRequestDto) { + @LoginRequired + public ResponseEntity activate( + @Login Manager manager, + @RequestBody AuthCodeRequestDto authCodeRequestDto) { Long sessionId = authCodeRequestDto.getSessionId(); Long courseId = authCodeRequestDto.getCourseId(); - return ResponseEntity.ok(activeSessionService.activate(sessionId, courseId)); + return ResponseEntity.ok(activeSessionService.activate(manager.getId(), sessionId, courseId)); } @PostMapping("/deactivate") + @LoginRequired public ResponseEntity deactivate( + @Login Manager manager, @RequestBody AuthCodeDeactivationRequestDto authCodeDeactivationRequestDto) { Long sessionId = authCodeDeactivationRequestDto.getSessionId(); Long courseId = authCodeDeactivationRequestDto.getCourseId(); diff --git a/src/main/java/com/waruru/areyouhere/active/service/ActiveSessionService.java b/src/main/java/com/waruru/areyouhere/active/service/ActiveSessionService.java index f15f847..e3c9336 100644 --- a/src/main/java/com/waruru/areyouhere/active/service/ActiveSessionService.java +++ b/src/main/java/com/waruru/areyouhere/active/service/ActiveSessionService.java @@ -4,6 +4,6 @@ public interface ActiveSessionService { public void deactivate(String authCode, Long sessionId, Long courseId); - public String activate(Long sessionId, Long courseId); + public String activate(Long managerId, Long sessionId, Long courseId); } diff --git a/src/main/java/com/waruru/areyouhere/active/service/ActiveSessionServiceImpl.java b/src/main/java/com/waruru/areyouhere/active/service/ActiveSessionServiceImpl.java index a3a7ae3..407024f 100644 --- a/src/main/java/com/waruru/areyouhere/active/service/ActiveSessionServiceImpl.java +++ b/src/main/java/com/waruru/areyouhere/active/service/ActiveSessionServiceImpl.java @@ -27,9 +27,9 @@ public class ActiveSessionServiceImpl implements ActiveSessionService { @Override @Transactional - public String activate(Long sessionId, Long courseId) { - Course course = courseService.get(courseId); - Session session = sessionQueryService.get(sessionId); + public String activate(Long managerId, Long sessionId, Long courseId) { + Course course = courseService.get(managerId, courseId); + Session session = sessionQueryService.get(managerId, sessionId); LocalDateTime currentTime = LocalDateTime.now(ZoneId.of("Asia/Seoul")); sessionCommandService.setAuthCodeDate(session, currentTime); return activeAttendanceService.activate(course, session, currentTime); diff --git a/src/main/java/com/waruru/areyouhere/attendance/controller/AttendanceController.java b/src/main/java/com/waruru/areyouhere/attendance/controller/AttendanceController.java index 995a32f..6e72da6 100644 --- a/src/main/java/com/waruru/areyouhere/attendance/controller/AttendanceController.java +++ b/src/main/java/com/waruru/areyouhere/attendance/controller/AttendanceController.java @@ -9,7 +9,9 @@ import com.waruru.areyouhere.attendance.service.AttendanceService; import com.waruru.areyouhere.attendance.service.dto.CurrentSessionAttendCount; import com.waruru.areyouhere.attendance.service.dto.CurrentSessionAttendeeAttendance; +import com.waruru.areyouhere.common.annotation.Login; import com.waruru.areyouhere.common.annotation.LoginRequired; +import com.waruru.areyouhere.manager.domain.entity.Manager; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import java.util.Arrays; @@ -67,11 +69,11 @@ public ResponseEntity attend(HttpServletRequest request, @LoginRequired @PutMapping - ResponseEntity update(@RequestBody UpdateAttendanceRequestDto updateAttendanceRequestDto) { - Long sessionId = updateAttendanceRequestDto.getSessionId(); + ResponseEntity update( + @Login Manager manager, + @RequestBody UpdateAttendanceRequestDto updateAttendanceRequestDto) { List updateAttendance = updateAttendanceRequestDto.getUpdateAttendances(); - - attendanceService.updateAllStatuses(sessionId, updateAttendance); + attendanceService.updateAllStatuses(manager.getId(), updateAttendance); return ResponseEntity.ok().build(); } diff --git a/src/main/java/com/waruru/areyouhere/attendance/domain/repository/AttendanceRepository.java b/src/main/java/com/waruru/areyouhere/attendance/domain/repository/AttendanceRepository.java index 0077c27..8a3a391 100644 --- a/src/main/java/com/waruru/areyouhere/attendance/domain/repository/AttendanceRepository.java +++ b/src/main/java/com/waruru/areyouhere/attendance/domain/repository/AttendanceRepository.java @@ -2,6 +2,7 @@ import com.waruru.areyouhere.attendance.domain.entity.Attendance; import java.util.List; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -22,4 +23,16 @@ public interface AttendanceRepository extends JpaRepository{ @Modifying(clearAutomatically = true) @Query("delete from attendance a where a.session.id in :ids") public void deleteAllBySessionIds(@Param("ids") List ids); + + + // TODO: 이런 쿼리를 사용하는게 맞는지에 대한 의문. -> 일단 사용하지 맙시다. + @Query(nativeQuery = true, value = "SELECT case when EXISTS" + + "(SELECT 1 FROM course WHERE course.id = " + + "(SELECT course_id FROM session WHERE id = " + + "(SELECT session_id FROM attendance WHERE id = :attendanceId)) and manager_id = :managerId)" + + "then 'true' else 'false' end") + public boolean isAttendanceOwnByManagerId(@Param("managerId") Long managerId, @Param("attendanceId") Long attendanceId); + + @Query(nativeQuery = true, value = "SELECT session_id FROM attendance WHERE id = :attendanceId") + public Optional getSessionIdByAttendanceId(@Param("attendanceId") Long attendanceId); } diff --git a/src/main/java/com/waruru/areyouhere/attendance/service/AttendanceService.java b/src/main/java/com/waruru/areyouhere/attendance/service/AttendanceService.java index bf85290..cfc6780 100644 --- a/src/main/java/com/waruru/areyouhere/attendance/service/AttendanceService.java +++ b/src/main/java/com/waruru/areyouhere/attendance/service/AttendanceService.java @@ -10,7 +10,7 @@ public interface AttendanceService { public AttendResponseDto attend(String attendeeName, String authCode, Long attendeeId); - public void updateAllStatuses(Long sessionId, List updateAttendances); + public void updateAllStatuses(Long managerId, List updateAttendances); public CurrentSessionAttendCount getCurrentSessionAttendCount(Long sessionId); diff --git a/src/main/java/com/waruru/areyouhere/attendance/service/AttendanceServiceImpl.java b/src/main/java/com/waruru/areyouhere/attendance/service/AttendanceServiceImpl.java index add6e0d..2b08add 100644 --- a/src/main/java/com/waruru/areyouhere/attendance/service/AttendanceServiceImpl.java +++ b/src/main/java/com/waruru/areyouhere/attendance/service/AttendanceServiceImpl.java @@ -8,7 +8,9 @@ import com.waruru.areyouhere.attendance.service.rdb.AttendanceRDBService; import com.waruru.areyouhere.active.service.ActiveAttendanceService; import com.waruru.areyouhere.attendee.service.dto.AttendeeInfo; +import com.waruru.areyouhere.session.domain.repository.SessionRepository; import com.waruru.areyouhere.session.service.dto.AuthCodeInfo; +import com.waruru.areyouhere.session.service.query.SessionQueryService; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.List; @@ -23,6 +25,7 @@ public class AttendanceServiceImpl implements AttendanceService { private final AttendanceRDBService attendanceRDBService; private final ActiveAttendanceService activeAttendanceService; + private final SessionQueryService sessionQueryService; @Override @Transactional @@ -53,8 +56,9 @@ public AttendResponseDto attend(String attendeeName, String authCode, Long atten @Override @Transactional - public void updateAllStatuses(Long sessionId, List updateAttendances) { - attendanceRDBService.setAttendanceStatuses(sessionId, updateAttendances); + public void updateAllStatuses(Long managerId, List updateAttendances) { + updateAttendances.forEach(updateAttendance -> throwIfAttendanceNotOwnByManager(managerId, updateAttendance.getAttendanceId())); + attendanceRDBService.setAttendanceStatuses(updateAttendances); } @Override @@ -72,6 +76,11 @@ public CurrentSessionAttendeeAttendance getCurrentSessionAttendeesAndAbsentees(S return activeAttendanceService.getCurrentSessionAttendees(authCode); } + private void throwIfAttendanceNotOwnByManager(Long managerId, Long attendanceId){ + long sessionId = attendanceRDBService.getSessionId(attendanceId); + sessionQueryService.throwIfSessionAuthorizationFail(managerId, sessionId); + } + } diff --git a/src/main/java/com/waruru/areyouhere/attendance/service/rdb/AttendanceRDBService.java b/src/main/java/com/waruru/areyouhere/attendance/service/rdb/AttendanceRDBService.java index a6bf7cb..f3f9f88 100644 --- a/src/main/java/com/waruru/areyouhere/attendance/service/rdb/AttendanceRDBService.java +++ b/src/main/java/com/waruru/areyouhere/attendance/service/rdb/AttendanceRDBService.java @@ -8,5 +8,7 @@ public interface AttendanceRDBService { public void setAttendancesAfterDeactivate(long courseId, long sessionId, CurrentSessionAttendanceInfo currentSessionAttendanceInfo); - public void setAttendanceStatuses(Long sessionId, List updateAttendances); + public void setAttendanceStatuses(List updateAttendances); + + public long getSessionId(Long attendanceId); } diff --git a/src/main/java/com/waruru/areyouhere/attendance/service/rdb/AttendanceRDBServiceImpl.java b/src/main/java/com/waruru/areyouhere/attendance/service/rdb/AttendanceRDBServiceImpl.java index b90b7c0..7634f13 100644 --- a/src/main/java/com/waruru/areyouhere/attendance/service/rdb/AttendanceRDBServiceImpl.java +++ b/src/main/java/com/waruru/areyouhere/attendance/service/rdb/AttendanceRDBServiceImpl.java @@ -10,6 +10,7 @@ import com.waruru.areyouhere.attendance.service.dto.CurrentSessionAttendeeAttendance; import com.waruru.areyouhere.attendee.domain.entity.Attendee; import com.waruru.areyouhere.attendee.domain.repository.AttendeeRepository; +import com.waruru.areyouhere.manager.exception.UnAuthenticatedException; import com.waruru.areyouhere.session.domain.entity.Session; import com.waruru.areyouhere.session.domain.repository.SessionRepository; import com.waruru.areyouhere.session.exception.SessionIdNotFoundException; @@ -34,11 +35,9 @@ public class AttendanceRDBServiceImpl implements AttendanceRDBService { private final AttendanceRepository attendanceRepository; private final AttendanceBatchRepository attendanceBatchRepository; - @Override public void setAttendancesAfterDeactivate(long courseId, long sessionId, CurrentSessionAttendanceInfo currentSessionAttendanceInfo) { - LocalDateTime absentTime = LocalDateTime.now(); List attendees = new LinkedList<>(); List absentees = new LinkedList<>(); @@ -58,7 +57,8 @@ public void setAttendancesAfterDeactivate(long courseId, long sessionId, } - public void setAttendanceStatuses(Long sessionId, List updateAttendances) { + public void setAttendanceStatuses(List updateAttendances) { + List attendancesToUpdate = updateAttendances.stream() .map(updateAttendance -> { Attendance attendance = attendanceRepository.findById(updateAttendance.getAttendanceId()) @@ -72,5 +72,10 @@ public void setAttendanceStatuses(Long sessionId, List updateA attendanceRepository.saveAll(attendancesToUpdate); } + @Override + public long getSessionId(Long attendanceId){ + return attendanceRepository.getSessionIdByAttendanceId(attendanceId).orElseThrow(); + } + } diff --git a/src/main/java/com/waruru/areyouhere/attendee/controller/AttendeeController.java b/src/main/java/com/waruru/areyouhere/attendee/controller/AttendeeController.java index 628f5b6..f023067 100644 --- a/src/main/java/com/waruru/areyouhere/attendee/controller/AttendeeController.java +++ b/src/main/java/com/waruru/areyouhere/attendee/controller/AttendeeController.java @@ -10,7 +10,9 @@ import com.waruru.areyouhere.attendee.service.dto.ClassAttendees; import com.waruru.areyouhere.attendee.service.dto.DuplicateAttendees; import com.waruru.areyouhere.attendee.service.query.AttendeeQueryService; +import com.waruru.areyouhere.common.annotation.Login; import com.waruru.areyouhere.common.annotation.LoginRequired; +import com.waruru.areyouhere.manager.domain.entity.Manager; import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -36,8 +38,10 @@ public class AttendeeController { @LoginRequired @GetMapping - public ResponseEntity getClassAttendees(@RequestParam("courseId") Long courseId) { - List classAttendees = attendeeQueryService.getClassAttendeesIfExistsOrEmpty(courseId); + public ResponseEntity getClassAttendees( + @Login Manager manager, + @RequestParam("courseId") Long courseId) { + List classAttendees = attendeeQueryService.getClassAttendeesIfExistsOrEmpty(manager.getId(), courseId); return ResponseEntity.ok(ClassAttendeesResponseDto.builder() .classAttendees(classAttendees) @@ -46,16 +50,22 @@ public ResponseEntity getClassAttendees(@RequestParam @LoginRequired @PostMapping - public ResponseEntity create(@RequestBody NewAttendeesRequestDto newAttendeesRequestDto) { - attendeeCommandService.createAll(newAttendeesRequestDto.getCourseId(), + public ResponseEntity create( + @Login Manager manager, + @RequestBody NewAttendeesRequestDto newAttendeesRequestDto) { + attendeeCommandService.createAll( + manager.getId(), + newAttendeesRequestDto.getCourseId(), newAttendeesRequestDto.getNewAttendees()); return ResponseEntity.ok().build(); } @LoginRequired @PostMapping("/delete") - public ResponseEntity delete(@RequestBody DeleteAttendeesRequestDto deleteAttendeesRequestDto) { - attendeeCommandService.deleteAll(deleteAttendeesRequestDto.getAttendeeIds()); + public ResponseEntity delete( + @Login Manager manager, + @RequestBody DeleteAttendeesRequestDto deleteAttendeesRequestDto) { + attendeeCommandService.deleteAll(manager.getId(), deleteAttendeesRequestDto.getAttendeeIds()); return ResponseEntity.ok().build(); } @@ -75,8 +85,12 @@ public ResponseEntity getAttendeeDetail(@RequestParam("attend @LoginRequired @PutMapping - public ResponseEntity update(@RequestBody UpdateAttendeesRequestDto UpdateAttendeesRequestDto) { - attendeeCommandService.updateAll(UpdateAttendeesRequestDto.getCourseId(), + public ResponseEntity update( + @Login Manager manager, + @RequestBody UpdateAttendeesRequestDto UpdateAttendeesRequestDto) { + attendeeCommandService.updateAll( + manager.getId(), + UpdateAttendeesRequestDto.getCourseId(), UpdateAttendeesRequestDto.getUpdatedAttendees()); return ResponseEntity.ok().build(); } diff --git a/src/main/java/com/waruru/areyouhere/attendee/service/command/AttendeeCommandService.java b/src/main/java/com/waruru/areyouhere/attendee/service/command/AttendeeCommandService.java index f53c5e4..a122018 100644 --- a/src/main/java/com/waruru/areyouhere/attendee/service/command/AttendeeCommandService.java +++ b/src/main/java/com/waruru/areyouhere/attendee/service/command/AttendeeCommandService.java @@ -4,8 +4,8 @@ import java.util.List; public interface AttendeeCommandService { - public void createAll(Long courseId, List newAttendees); - public void deleteAll(List deleteAttendees); + public void createAll(Long managerId, Long courseId, List newAttendees); + public void deleteAll(Long managerId, List deleteAttendees); - public void updateAll(Long courseId, List updatedAttendees); + public void updateAll(Long managerId, Long courseId, List updatedAttendees); } diff --git a/src/main/java/com/waruru/areyouhere/attendee/service/command/AttendeeCommandServiceImpl.java b/src/main/java/com/waruru/areyouhere/attendee/service/command/AttendeeCommandServiceImpl.java index 80dbe6f..d8e32e0 100644 --- a/src/main/java/com/waruru/areyouhere/attendee/service/command/AttendeeCommandServiceImpl.java +++ b/src/main/java/com/waruru/areyouhere/attendee/service/command/AttendeeCommandServiceImpl.java @@ -11,6 +11,7 @@ import com.waruru.areyouhere.course.domain.entity.Course; import com.waruru.areyouhere.course.domain.repository.CourseRepository; import com.waruru.areyouhere.course.exception.CourseNotFoundException; +import com.waruru.areyouhere.manager.exception.UnAuthenticatedException; import com.waruru.areyouhere.session.exception.ActivatedSessionExistsException; import java.util.HashMap; import java.util.HashSet; @@ -37,7 +38,8 @@ public class AttendeeCommandServiceImpl implements AttendeeCommandService{ private final ActiveAttendanceService activeAttendanceService; @Override - public void createAll(Long courseId, List newAttendees){ + public void createAll(Long managerId, Long courseId, List newAttendees){ + throwIfCourseAuthorizationFail(managerId, courseId); Course course = courseRepository.findById(courseId) .orElseThrow(CourseNotFoundException::new); @@ -69,8 +71,8 @@ public void createAll(Long courseId, List newAttendees){ } @Override - public void updateAll(Long courseId, List updatedAttendees){ - + public void updateAll(Long managerId, Long courseId, List updatedAttendees){ + throwIfCourseAuthorizationFail(managerId, courseId); throwIfAttendeesNameAndNoteNotUnique(updatedAttendees, courseId); updatedAttendees.stream() .map(attendee -> @@ -85,10 +87,11 @@ public void updateAll(Long courseId, List updatedAttendees){ syncToRedis(courseId); } - public void deleteAll(List deleteAttendees){ + public void deleteAll(Long managerId, List deleteAttendees){ Long courseId = attendeeRepository.findById(deleteAttendees.get(0)) .orElseThrow(() -> new AttendeeNotFoundException("Attendee not found")) .getCourse().getId(); + throwIfCourseAuthorizationFail(managerId, courseId); if(activeAttendanceService.isSessionActivatedByCourseId(courseId)){ throw new ActivatedSessionExistsException(); } @@ -174,4 +177,12 @@ private boolean addUniqueNameAndNote(Attendee attendee, Map> .get(attendee.getName()) .add(Optional.ofNullable(attendee.getNote()).orElse("")); } + + private void throwIfCourseAuthorizationFail(Long managerId, Long courseId){ + if(!courseRepository.isCourseMadeByManagerId(managerId, courseId)){ + throw new UnAuthenticatedException(); + } + } + + } diff --git a/src/main/java/com/waruru/areyouhere/attendee/service/query/AttendeeQueryService.java b/src/main/java/com/waruru/areyouhere/attendee/service/query/AttendeeQueryService.java index b7bc52b..f241c9c 100644 --- a/src/main/java/com/waruru/areyouhere/attendee/service/query/AttendeeQueryService.java +++ b/src/main/java/com/waruru/areyouhere/attendee/service/query/AttendeeQueryService.java @@ -14,7 +14,7 @@ public interface AttendeeQueryService { public List getSessionAbsenteesIfExistsOrEmpty(Long sessionId); - public List getClassAttendeesIfExistsOrEmpty(Long courseId); + public List getClassAttendeesIfExistsOrEmpty(Long managerId, Long courseId); public int getAllByCourseId(Long courseId); diff --git a/src/main/java/com/waruru/areyouhere/attendee/service/query/AttendeeQueryServiceImpl.java b/src/main/java/com/waruru/areyouhere/attendee/service/query/AttendeeQueryServiceImpl.java index a5bec63..5a507ba 100644 --- a/src/main/java/com/waruru/areyouhere/attendee/service/query/AttendeeQueryServiceImpl.java +++ b/src/main/java/com/waruru/areyouhere/attendee/service/query/AttendeeQueryServiceImpl.java @@ -11,6 +11,8 @@ import com.waruru.areyouhere.attendee.service.dto.ClassAttendees; import com.waruru.areyouhere.attendee.service.dto.DuplicateAttendees; import com.waruru.areyouhere.attendee.service.dto.SessionAttendees; +import com.waruru.areyouhere.course.domain.repository.CourseRepository; +import com.waruru.areyouhere.manager.exception.UnAuthenticatedException; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -25,6 +27,8 @@ public class AttendeeQueryServiceImpl implements AttendeeQueryService{ private final AttendeeRepository attendeeRepository; + private final CourseRepository courseRepository; + @Override public AttendeeDetailDto getAttendanceCount(Long attendeeId) { Attendee attendee = attendeeRepository.findById(attendeeId) @@ -114,12 +118,14 @@ public List getSessionAbsenteesIfExistsOrEmpty(Long sessionId) } @Override - public List getClassAttendeesIfExistsOrEmpty(Long courseId) { + public List getClassAttendeesIfExistsOrEmpty(Long managerId, Long courseId) { List classAttendancesInfos = attendeeRepository.getClassAttendancesInfo(courseId); if(classAttendancesInfos == null || classAttendancesInfos.isEmpty()) throw new ClassAttendeesEmptyException(); + throwIfCourseAuthorizationFail(managerId, courseId); + return classAttendancesInfos.stream().map( classAttendancesInfo -> ClassAttendees.builder() .id(classAttendancesInfo.getAttendeeId()) .name(classAttendancesInfo.getName()) @@ -134,4 +140,10 @@ public List getClassAttendeesIfExistsOrEmpty(Long courseId) { public int getAllByCourseId(Long courseId) { return attendeeRepository.findAttendeesByCourse_Id(courseId).size(); } + + private void throwIfCourseAuthorizationFail(Long managerId, Long courseId){ + if(!courseRepository.isCourseMadeByManagerId(managerId, courseId)){ + throw new UnAuthenticatedException(); + } + } } diff --git a/src/main/java/com/waruru/areyouhere/common/error/GlobalExceptionHandler.java b/src/main/java/com/waruru/areyouhere/common/error/GlobalExceptionHandler.java index f8d9897..d73a502 100644 --- a/src/main/java/com/waruru/areyouhere/common/error/GlobalExceptionHandler.java +++ b/src/main/java/com/waruru/areyouhere/common/error/GlobalExceptionHandler.java @@ -1,8 +1,10 @@ package com.waruru.areyouhere.common.error; import static com.waruru.areyouhere.common.utils.HttpStatusResponseEntity.RESPONSE_NOT_FOUND; +import static com.waruru.areyouhere.common.utils.HttpStatusResponseEntity.RESPONSE_UNAUTHORIZED; import com.waruru.areyouhere.common.annotation.SlackNotification; +import com.waruru.areyouhere.manager.exception.UnAuthenticatedException; import jakarta.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; @@ -59,5 +61,10 @@ public Map handleValidationExceptions( return errors; } + @ExceptionHandler(UnAuthenticatedException.class) + public ResponseEntity unAuthenticatedHandler(){ + return RESPONSE_UNAUTHORIZED; + } + } diff --git a/src/main/java/com/waruru/areyouhere/course/advice/CourseExceptionAdvice.java b/src/main/java/com/waruru/areyouhere/course/advice/CourseExceptionAdvice.java index a3af266..78c7321 100644 --- a/src/main/java/com/waruru/areyouhere/course/advice/CourseExceptionAdvice.java +++ b/src/main/java/com/waruru/areyouhere/course/advice/CourseExceptionAdvice.java @@ -46,11 +46,4 @@ public ResponseEntity handleActivatedSessionExistsException(ActivatedSessionE return ResponseEntity.status(HttpStatus.CONFLICT).body(ex.getMessage()); } - - @ExceptionHandler(Exception.class) - public ResponseEntity handleGlobalException(Exception ex, WebRequest request) { - // 모든 나머지 예외들을 처리 - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An unexpected error occurred"); - } - } diff --git a/src/main/java/com/waruru/areyouhere/course/controller/CourseController.java b/src/main/java/com/waruru/areyouhere/course/controller/CourseController.java index 83e2c3b..5953634 100644 --- a/src/main/java/com/waruru/areyouhere/course/controller/CourseController.java +++ b/src/main/java/com/waruru/areyouhere/course/controller/CourseController.java @@ -25,8 +25,10 @@ public class CourseController { @LoginRequired @GetMapping("/{courseId}") - ResponseEntity get(@PathVariable Long courseId) { - Course course = courseService.get(courseId); + ResponseEntity get( + @Login Manager manager, + @PathVariable Long courseId) { + Course course = courseService.get(manager.getId(), courseId); return ResponseEntity.ok(CourseGetResponse.from(course)); } diff --git a/src/main/java/com/waruru/areyouhere/course/domain/repository/CourseRepository.java b/src/main/java/com/waruru/areyouhere/course/domain/repository/CourseRepository.java index 3896c36..4367239 100644 --- a/src/main/java/com/waruru/areyouhere/course/domain/repository/CourseRepository.java +++ b/src/main/java/com/waruru/areyouhere/course/domain/repository/CourseRepository.java @@ -12,4 +12,6 @@ public interface CourseRepository extends JpaRepository { @Query("SELECT c FROM course c WHERE c.manager.id = :managerId") List findAllByManagerId(@Param("managerId")Long managerId); + @Query(nativeQuery = true, value = "SELECT case when EXISTS(SELECT 1 from course WHERE course.id = :courseId and manager_id = :managerId) then 'true' else 'false' end") + boolean isCourseMadeByManagerId(@Param("managerId") Long managerId, @Param("courseId") Long courseId); } diff --git a/src/main/java/com/waruru/areyouhere/course/service/CourseService.java b/src/main/java/com/waruru/areyouhere/course/service/CourseService.java index ff70635..bff78eb 100644 --- a/src/main/java/com/waruru/areyouhere/course/service/CourseService.java +++ b/src/main/java/com/waruru/areyouhere/course/service/CourseService.java @@ -18,5 +18,5 @@ void create(Long managerId, String name, String description, List void delete(Long managerId, Long courseId); - public Course get(Long courseId); + public Course get(Long managerId, Long courseId); } diff --git a/src/main/java/com/waruru/areyouhere/course/service/CourseServiceImpl.java b/src/main/java/com/waruru/areyouhere/course/service/CourseServiceImpl.java index 8ade8c1..dd500aa 100644 --- a/src/main/java/com/waruru/areyouhere/course/service/CourseServiceImpl.java +++ b/src/main/java/com/waruru/areyouhere/course/service/CourseServiceImpl.java @@ -15,6 +15,7 @@ import com.waruru.areyouhere.course.exception.UnauthorizedManagerException; import com.waruru.areyouhere.manager.domain.entity.Manager; import com.waruru.areyouhere.manager.domain.repository.ManagerRepository; +import com.waruru.areyouhere.manager.exception.UnAuthenticatedException; import com.waruru.areyouhere.session.domain.entity.Session; import com.waruru.areyouhere.session.domain.repository.SessionRepository; import com.waruru.areyouhere.session.exception.ActivatedSessionExistsException; @@ -101,15 +102,15 @@ public void update(Long managerId, Long courseId, String name, String descriptio Course course = courseRepository.findById(courseId). orElseThrow(() -> new CourseNotFoundException("Course not found")); - if (!course.getManager().getId().equals(managerId)) { - throw new UnauthorizedManagerException("Manager not authorized"); - } + throwIfCourseAuthorizationFail(managerId, courseId); course.update(name, description, onlyListNameAllowed); courseRepository.save(course); activeAttendanceService.updateCourseName(courseId, name); } + + @Override public void delete(Long managerId, Long courseId) { if(activeAttendanceService.isSessionActivatedByCourseId(courseId)){ @@ -119,9 +120,7 @@ public void delete(Long managerId, Long courseId) { Course course = courseRepository.findById(courseId). orElseThrow(() -> new CourseNotFoundException("Course not found")); - if (!course.getManager().getId().equals(managerId)) { - throw new UnauthorizedManagerException("Manager not authorized"); - } + throwIfCourseAuthorizationFail(managerId, courseId); List sessions = sessionRepository.findAllByCourseId(courseId); attendanceRepository.deleteAllBySessionIds(sessions.stream().map(Session::getId).toList()); sessionRepository.deleteAllByCourseId(courseId); @@ -130,12 +129,13 @@ public void delete(Long managerId, Long courseId) { } - @Override @Transactional(readOnly = true) - public Course get(Long courseId) { - return courseRepository.findById(courseId). + public Course get(Long managerId, Long courseId) { + Course course = courseRepository.findById(courseId). orElseThrow(() -> new CourseNotFoundException("Course not found")); + throwIfCourseAuthorizationFail(managerId, courseId); + return course; } private boolean isAttendeesUnique(List attendees) { @@ -144,4 +144,11 @@ private boolean isAttendeesUnique(List attendees) { return uniqueAttendees.size() == attendees.size(); } + + private void throwIfCourseAuthorizationFail(Long managerId, Long courseId){ + if(!courseRepository.isCourseMadeByManagerId(managerId, courseId)){ + throw new UnAuthenticatedException(); + } + } + } diff --git a/src/main/java/com/waruru/areyouhere/session/controller/DashBoardController.java b/src/main/java/com/waruru/areyouhere/session/controller/DashBoardController.java index 3639e06..3413547 100644 --- a/src/main/java/com/waruru/areyouhere/session/controller/DashBoardController.java +++ b/src/main/java/com/waruru/areyouhere/session/controller/DashBoardController.java @@ -1,7 +1,9 @@ package com.waruru.areyouhere.session.controller; +import com.waruru.areyouhere.common.annotation.Login; import com.waruru.areyouhere.common.annotation.LoginRequired; +import com.waruru.areyouhere.manager.domain.entity.Manager; import com.waruru.areyouhere.session.dto.response.CurrentSessionResponseDto; import com.waruru.areyouhere.session.dto.response.PreviousFiveSessionResponseDto; import com.waruru.areyouhere.session.exception.CurrentSessionNotFoundException; @@ -29,8 +31,10 @@ public class DashBoardController { @LoginRequired @GetMapping - public ResponseEntity getCurrentSessionInfo(@PathVariable Long courseId) { - CurrentSessionDto currentSessionInfo = sessionQueryService.getCurrentSessionInfo(courseId); + public ResponseEntity getCurrentSessionInfo( + @Login Manager manager, + @PathVariable Long courseId) { + CurrentSessionDto currentSessionInfo = sessionQueryService.getCurrentSessionInfo(manager.getId(), courseId); CurrentSessionResponseDto currentSessionResponseDto = CurrentSessionResponseDto.builder() .authCode(currentSessionInfo.getAuthCode()) .sessionName(currentSessionInfo.getSessionName()) @@ -43,9 +47,11 @@ public ResponseEntity getCurrentSessionInfo(@PathVari @LoginRequired @GetMapping("/session") - public ResponseEntity getRecentFiveSessionInfo(@PathVariable Long courseId){ + public ResponseEntity getRecentFiveSessionInfo( + @Login Manager manager, + @PathVariable Long courseId){ - List recentFiveSessions = sessionQueryService.getRecentFive(courseId); + List recentFiveSessions = sessionQueryService.getRecentFive(manager.getId(), courseId); if(recentFiveSessions.isEmpty()){ throw new CurrentSessionNotFoundException(); } diff --git a/src/main/java/com/waruru/areyouhere/session/controller/SessionController.java b/src/main/java/com/waruru/areyouhere/session/controller/SessionController.java index 3a9a40b..9e378ab 100644 --- a/src/main/java/com/waruru/areyouhere/session/controller/SessionController.java +++ b/src/main/java/com/waruru/areyouhere/session/controller/SessionController.java @@ -3,7 +3,9 @@ import com.waruru.areyouhere.attendee.service.dto.SessionAttendees; import com.waruru.areyouhere.attendee.service.query.AttendeeQueryService; +import com.waruru.areyouhere.common.annotation.Login; import com.waruru.areyouhere.common.annotation.LoginRequired; +import com.waruru.areyouhere.manager.domain.entity.Manager; import com.waruru.areyouhere.session.dto.request.CreateSessionRequestDto; import com.waruru.areyouhere.session.dto.request.DeleteSessionRequestDto; import com.waruru.areyouhere.session.dto.request.UpdateSessionsRequestDto; @@ -40,9 +42,11 @@ public class SessionController { // TODO : refactor => service Dto 그대로 사용. @LoginRequired @GetMapping - public ResponseEntity getAll(@RequestParam("courseId") Long courseId){ + public ResponseEntity getAll( + @Login Manager manager, + @RequestParam("courseId") Long courseId){ - List allSessions = sessionQueryService.getAll(courseId); + List allSessions = sessionQueryService.getAll(manager.getId(), courseId); if(allSessions.isEmpty()){ return ResponseEntity.noContent().build(); } @@ -53,27 +57,35 @@ public ResponseEntity getAll(@RequestParam("courseId") } @LoginRequired @PostMapping - public ResponseEntity create(@RequestBody CreateSessionRequestDto createSessionRequestDto){ - sessionCommandService.create(createSessionRequestDto.getCourseId(), createSessionRequestDto.getSessionName()); + public ResponseEntity create( + @Login Manager manager, + @RequestBody CreateSessionRequestDto createSessionRequestDto){ + sessionCommandService.create(manager.getId(), createSessionRequestDto.getCourseId(), createSessionRequestDto.getSessionName()); return ResponseEntity.ok().build(); } @LoginRequired @PostMapping("/delete") - public ResponseEntity delete(@RequestBody DeleteSessionRequestDto sessionIds){ - sessionCommandService.deleteAll(sessionIds.getSessionIds()); + public ResponseEntity delete( + @Login Manager manager, + @RequestBody DeleteSessionRequestDto sessionIds){ + sessionCommandService.deleteAll(manager.getId(), sessionIds.getSessionIds()); return ResponseEntity.ok().build(); } @LoginRequired @DeleteMapping - public ResponseEntity deleteNotActivated(@RequestParam("courseId") Long courseId){ - sessionCommandService.deleteNotActivated(courseId); + public ResponseEntity deleteNotActivated( + @Login Manager manager, + @RequestParam("courseId") Long courseId){ + sessionCommandService.deleteNotActivated(manager.getId(), courseId); return ResponseEntity.ok().build(); } @LoginRequired @GetMapping("/{sessionId}") - public ResponseEntity getSessionBasicInfo(@PathVariable("sessionId") Long sessionId){ - return ResponseEntity.ok(sessionQueryService.getSessionAttendanceInfo(sessionId)); + public ResponseEntity getSessionBasicInfo( + @Login Manager manager, + @PathVariable("sessionId") Long sessionId){ + return ResponseEntity.ok(sessionQueryService.getSessionAttendanceInfo(manager.getId(), sessionId)); } // TODO: refactor => attendeeService로 이동 @LoginRequired @@ -98,8 +110,10 @@ public ResponseEntity getSessionAbsenteeOnly(@PathV } @LoginRequired @PutMapping - public ResponseEntity updateAll(@RequestBody UpdateSessionsRequestDto updateSessionsRequestDto){ - sessionCommandService.updateAll(updateSessionsRequestDto.getSessions()); + public ResponseEntity updateAll( + @Login Manager manager, + @RequestBody UpdateSessionsRequestDto updateSessionsRequestDto){ + sessionCommandService.updateAll(manager.getId(), updateSessionsRequestDto.getSessions()); return ResponseEntity.ok().build(); } diff --git a/src/main/java/com/waruru/areyouhere/session/domain/repository/SessionRepository.java b/src/main/java/com/waruru/areyouhere/session/domain/repository/SessionRepository.java index 18ef14f..e7d8066 100644 --- a/src/main/java/com/waruru/areyouhere/session/domain/repository/SessionRepository.java +++ b/src/main/java/com/waruru/areyouhere/session/domain/repository/SessionRepository.java @@ -64,4 +64,10 @@ public interface SessionRepository extends JpaRepository{ @Query("UPDATE session s SET s.name= :name WHERE s.id = :sessionId") void setSessionNameById(@Param("name") String name, @Param("sessionId") Long sessionId); + @Query(nativeQuery = true, value = "SELECT case when EXISTS " + + "(SELECT 1 FROM course WHERE course.id = " + + "(SELECT s.course_id FROM session AS s WHERE s.id = :sessionId)" + + " and course.manager_id = :managerId) then 'true' else 'false' end") + boolean isSessionMadeByManagerId(@Param("managerId") Long managerId, @Param("sessionId") Long sessionId); + } diff --git a/src/main/java/com/waruru/areyouhere/session/service/command/SessionCommandService.java b/src/main/java/com/waruru/areyouhere/session/service/command/SessionCommandService.java index cdc1386..7f828b5 100644 --- a/src/main/java/com/waruru/areyouhere/session/service/command/SessionCommandService.java +++ b/src/main/java/com/waruru/areyouhere/session/service/command/SessionCommandService.java @@ -6,15 +6,15 @@ import java.util.List; public interface SessionCommandService { - public void create(Long courseId, String sessionName); + public void create(Long managerId, Long courseId, String sessionName); - public void deleteNotActivated(Long courseId); + public void deleteNotActivated(Long managerId, Long courseId); - public void deleteAll(List sessionIds); + public void deleteAll(Long managerId, List sessionIds); public void deactivate(Long sessionId); public void setAuthCodeDate(Session session, LocalDateTime date); - public void updateAll(List sessions); + public void updateAll(Long managerId, List sessions); } diff --git a/src/main/java/com/waruru/areyouhere/session/service/command/SessionCommandServiceImpl.java b/src/main/java/com/waruru/areyouhere/session/service/command/SessionCommandServiceImpl.java index 16448e0..26b5ea2 100644 --- a/src/main/java/com/waruru/areyouhere/session/service/command/SessionCommandServiceImpl.java +++ b/src/main/java/com/waruru/areyouhere/session/service/command/SessionCommandServiceImpl.java @@ -7,6 +7,7 @@ import com.waruru.areyouhere.course.domain.entity.Course; import com.waruru.areyouhere.course.domain.repository.CourseRepository; import com.waruru.areyouhere.course.exception.CourseNotFoundException; +import com.waruru.areyouhere.manager.exception.UnAuthenticatedException; import com.waruru.areyouhere.session.domain.entity.Session; import com.waruru.areyouhere.session.domain.repository.SessionRepository; import com.waruru.areyouhere.session.exception.ActivatedSessionExistsException; @@ -32,11 +33,11 @@ public class SessionCommandServiceImpl implements SessionCommandService { private final ActiveAttendanceService activeAttendanceService; @Override - public void create(Long courseId, String sessionName) { + public void create(Long managerId, Long courseId, String sessionName) { // TODO : exception 수정 Course course = courseRepository.findById(courseId) .orElseThrow(CourseNotFoundException::new); - + throwIfCourseAuthorizationFail(managerId, courseId); sessionRepository.findMostRecentByCourseId(courseId) .ifPresent(session -> { if (!session.isDeactivated()) { @@ -57,7 +58,9 @@ public void create(Long courseId, String sessionName) { } @Override - public void deleteNotActivated(Long courseId) { + public void deleteNotActivated(Long managerId, Long courseId) { + throwIfCourseAuthorizationFail(managerId, courseId); + sessionRepository.findMostRecentByCourseId(courseId) .ifPresent(session -> { if (!activeAttendanceService.isSessionActivatedByCourseId(courseId) && !session.isDeactivated()) { @@ -66,7 +69,10 @@ public void deleteNotActivated(Long courseId) { }); } @Override - public void deleteAll(List sessionIds) { + public void deleteAll(Long managerId, List sessionIds) { + + sessionIds.forEach(sessionId -> throwIfSessionAuthorizationFail(managerId, sessionId)); + sessionIds.forEach(sessionId -> { attendanceRepository.deleteAllBySessionId(sessionId); sessionRepository.findById(sessionId).orElseThrow(CurrentSessionNotFoundException::new); @@ -89,11 +95,24 @@ public void setAuthCodeDate(Session session, LocalDateTime date){ } @Override - public void updateAll(List sessions) { + public void updateAll(Long managerId, List sessions) { + sessions.forEach(session -> throwIfSessionAuthorizationFail(managerId, session.getId())); + sessions.forEach(session -> { sessionRepository.setSessionNameById(session.getName(), session.getId()); }); } + private void throwIfCourseAuthorizationFail(Long managerId, Long courseId){ + if(!courseRepository.isCourseMadeByManagerId(managerId, courseId)){ + throw new UnAuthenticatedException(); + } + } + + private void throwIfSessionAuthorizationFail(Long managerId, Long sessionId){ + if(!sessionRepository.isSessionMadeByManagerId(managerId, sessionId)){ + throw new UnAuthenticatedException(); + } + } } diff --git a/src/main/java/com/waruru/areyouhere/session/service/query/SessionQueryService.java b/src/main/java/com/waruru/areyouhere/session/service/query/SessionQueryService.java index 07a7c60..6020408 100644 --- a/src/main/java/com/waruru/areyouhere/session/service/query/SessionQueryService.java +++ b/src/main/java/com/waruru/areyouhere/session/service/query/SessionQueryService.java @@ -6,15 +6,17 @@ import java.util.List; public interface SessionQueryService { - public CurrentSessionDto getCurrentSessionInfo(Long courseId); + public CurrentSessionDto getCurrentSessionInfo(Long managerId, Long courseId); - public List getRecentFive(Long courseId); + public List getRecentFive(Long managerId, Long courseId); - public List getAll(Long courseId); + public List getAll(Long managerId, Long courseId); - public SessionAttendanceInfo getSessionAttendanceInfo(Long sessionId); + public SessionAttendanceInfo getSessionAttendanceInfo(Long managerId, Long sessionId); public void checkNotDeactivated(Long sessionId); - public Session get(Long sessionId); + public Session get(Long managerId, Long sessionId); + + public void throwIfSessionAuthorizationFail(Long managerId, Long sessionId); } diff --git a/src/main/java/com/waruru/areyouhere/session/service/query/SessionQueryServiceImpl.java b/src/main/java/com/waruru/areyouhere/session/service/query/SessionQueryServiceImpl.java index 7924793..508dfda 100644 --- a/src/main/java/com/waruru/areyouhere/session/service/query/SessionQueryServiceImpl.java +++ b/src/main/java/com/waruru/areyouhere/session/service/query/SessionQueryServiceImpl.java @@ -1,6 +1,8 @@ package com.waruru.areyouhere.session.service.query; import com.waruru.areyouhere.active.domain.entity.CurrentSessionAttendanceInfo; +import com.waruru.areyouhere.course.domain.repository.CourseRepository; +import com.waruru.areyouhere.manager.exception.UnAuthenticatedException; import com.waruru.areyouhere.session.domain.entity.Session; import com.waruru.areyouhere.active.domain.repository.ActiveSessionRepository; import com.waruru.areyouhere.session.domain.repository.SessionRepository; @@ -24,10 +26,14 @@ public class SessionQueryServiceImpl implements SessionQueryService { private final SessionRepository sessionRepository; + private final CourseRepository courseRepository; private final ActiveSessionRepository activeSessionRepository; @Override - public CurrentSessionDto getCurrentSessionInfo(Long courseId) { + public CurrentSessionDto getCurrentSessionInfo(Long managerId, Long courseId) { + + throwIfCourseAuthorizationFail(managerId, courseId); + Session mostRecentSession = sessionRepository .findMostRecentByCourseId(courseId) .orElseThrow(CurrentSessionNotFoundException::new); @@ -49,7 +55,8 @@ public CurrentSessionDto getCurrentSessionInfo(Long courseId) { @Override - public List getRecentFive(Long courseId) { + public List getRecentFive(Long managerId, Long courseId) { + throwIfCourseAuthorizationFail(managerId, courseId); List recentSessions = getRecentSessions(courseId); removeExtraSession(recentSessions); return getSessionAttendanceInfoList(recentSessions); @@ -57,7 +64,9 @@ public List getRecentFive(Long courseId) { @Override - public List getAll(Long courseId) { + public List getAll(Long managerId, Long courseId) { + throwIfCourseAuthorizationFail(managerId, courseId); + List allSessions = sessionRepository.findSessionsWithAttendance(courseId); return allSessions == null || allSessions.isEmpty() @@ -73,11 +82,13 @@ public List getAll(Long courseId) { } @Override - public SessionAttendanceInfo getSessionAttendanceInfo(Long sessionId) { + public SessionAttendanceInfo getSessionAttendanceInfo(Long managerId, Long sessionId) { SessionInfo sessionWithAttendance = sessionRepository .findSessionWithAttendance(sessionId) .orElseThrow(SessionIdNotFoundException::new); + throwIfSessionAuthorizationFail(managerId, sessionId); + return SessionAttendanceInfo.builder() .id(sessionWithAttendance.getid()) .name(sessionWithAttendance.getname()) @@ -96,9 +107,20 @@ public void checkNotDeactivated(Long sessionId) { } @Override - public Session get(Long sessionId) { - return sessionRepository.findById(sessionId) + public Session get(Long managerId, Long sessionId) { + Session session = sessionRepository.findById(sessionId) .orElseThrow(SessionIdNotFoundException::new); + throwIfSessionAuthorizationFail(managerId, sessionId); + + return session; + } + + + @Override + public void throwIfSessionAuthorizationFail(Long managerId, Long sessionId){ + if(!sessionRepository.isSessionMadeByManagerId(managerId, sessionId)){ + throw new UnAuthenticatedException(); + } } private void throwIfSessionDeactivated(Session mostRecentSession) { @@ -132,6 +154,14 @@ private void removeExtraSession(List recentFiveSessions) { } } + private void throwIfCourseAuthorizationFail(Long managerId, Long courseId){ + if(!courseRepository.isCourseMadeByManagerId(managerId, courseId)){ + throw new UnAuthenticatedException(); + } + } + + + //FIXME : 404 발생 private List getSessionAttendanceInfoList(List recentFiveSessions) { return recentFiveSessions.stream()