From 85aee747c09e3ac657bfc8d80267f49549fbec12 Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Sun, 20 Oct 2024 01:46:48 +0900 Subject: [PATCH] =?UTF-8?q?[COT-21]=20Feature:=20=EC=84=B8=EC=85=98=20?= =?UTF-8?q?=EB=8B=A8=EA=B1=B4=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#180)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 세션 단건 조회 서비스 메서드 구현 * style: remove unused import line * feat: add session get api * feat: permit all session get api * chore: add description be deprecated * chore: follow annotation convention * feat: change dto --- .../attendance/dto/AttendanceResponse.java | 1 - .../session/controller/SessionController.java | 12 ++++- .../dto/SessionListImageInfoResponse.java | 1 - .../dto/SessionWithAttendanceResponse.java | 52 +++++++++++++++++++ .../csquiz/common/config/SecurityConfig.java | 1 + .../config/filter/JwtAuthorizationFilter.java | 11 ++-- .../generation/service/SessionService.java | 10 ++++ 7 files changed, 79 insertions(+), 9 deletions(-) create mode 100644 src/main/java/org/cotato/csquiz/api/session/dto/SessionWithAttendanceResponse.java diff --git a/src/main/java/org/cotato/csquiz/api/attendance/dto/AttendanceResponse.java b/src/main/java/org/cotato/csquiz/api/attendance/dto/AttendanceResponse.java index 453e5ec1..a7d0f22d 100644 --- a/src/main/java/org/cotato/csquiz/api/attendance/dto/AttendanceResponse.java +++ b/src/main/java/org/cotato/csquiz/api/attendance/dto/AttendanceResponse.java @@ -1,6 +1,5 @@ package org.cotato.csquiz.api.attendance.dto; -import java.time.LocalDate; import java.time.LocalDateTime; import lombok.Builder; import org.cotato.csquiz.domain.attendance.enums.AttendanceOpenStatus; diff --git a/src/main/java/org/cotato/csquiz/api/session/controller/SessionController.java b/src/main/java/org/cotato/csquiz/api/session/controller/SessionController.java index 0db3819a..a42e0a94 100644 --- a/src/main/java/org/cotato/csquiz/api/session/controller/SessionController.java +++ b/src/main/java/org/cotato/csquiz/api/session/controller/SessionController.java @@ -13,6 +13,7 @@ import org.cotato.csquiz.api.session.dto.CsEducationOnSessionNumberResponse; import org.cotato.csquiz.api.session.dto.DeleteSessionImageRequest; import org.cotato.csquiz.api.session.dto.SessionListResponse; +import org.cotato.csquiz.api.session.dto.SessionWithAttendanceResponse; import org.cotato.csquiz.api.session.dto.UpdateSessionImageOrderRequest; import org.cotato.csquiz.api.session.dto.UpdateSessionRequest; import org.cotato.csquiz.domain.generation.service.SessionImageService; @@ -24,29 +25,36 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +@Slf4j @RestController @Tag(name = "세션 정보", description = "세션 관련 API 입니다.") @RequestMapping("/v1/api/session") @RequiredArgsConstructor -@Slf4j public class SessionController { private final SessionService sessionService; private final SessionImageService sessionImageService; + @Operation(summary = "세션 단건 조회 API") + @GetMapping("/{id}") + public ResponseEntity findSession(@PathVariable("id") Long sessionId) { + return ResponseEntity.ok().body(sessionService.findSession(sessionId)); + } + @Operation(summary = "세션 목록 반환 API") @GetMapping public ResponseEntity> findSessionsByGenerationId(@RequestParam Long generationId) { return ResponseEntity.status(HttpStatus.OK).body(sessionService.findSessionsByGenerationId(generationId)); } - @Operation(summary = "CS ON인 세션 목록 반환 API") + @Operation(summary = "CS ON인 세션 목록 반환 API", description = "세션과 교육 연계 제거 시 삭제 예정") @GetMapping("/cs-on") public ResponseEntity> findAllCsOnSessionsByGenerationId( @RequestParam Long generationId) { diff --git a/src/main/java/org/cotato/csquiz/api/session/dto/SessionListImageInfoResponse.java b/src/main/java/org/cotato/csquiz/api/session/dto/SessionListImageInfoResponse.java index 278d8ad8..496d313d 100644 --- a/src/main/java/org/cotato/csquiz/api/session/dto/SessionListImageInfoResponse.java +++ b/src/main/java/org/cotato/csquiz/api/session/dto/SessionListImageInfoResponse.java @@ -1,6 +1,5 @@ package org.cotato.csquiz.api.session.dto; -import java.util.List; import org.cotato.csquiz.domain.generation.entity.SessionImage; public record SessionListImageInfoResponse( diff --git a/src/main/java/org/cotato/csquiz/api/session/dto/SessionWithAttendanceResponse.java b/src/main/java/org/cotato/csquiz/api/session/dto/SessionWithAttendanceResponse.java new file mode 100644 index 00000000..e9229781 --- /dev/null +++ b/src/main/java/org/cotato/csquiz/api/session/dto/SessionWithAttendanceResponse.java @@ -0,0 +1,52 @@ +package org.cotato.csquiz.api.session.dto; + +import java.time.LocalDateTime; +import java.util.List; +import org.cotato.csquiz.api.attendance.dto.AttendanceTimeResponse; +import org.cotato.csquiz.domain.attendance.entity.Attendance; +import org.cotato.csquiz.domain.generation.embedded.SessionContents; +import org.cotato.csquiz.domain.generation.entity.Session; +import org.cotato.csquiz.domain.generation.entity.SessionImage; + +public record SessionWithAttendanceResponse( + Long sessionId, + Integer sessionNumber, + String title, + List sessionImages, + String description, + Long generationId, + String placeName, + LocalDateTime sessionDateTime, + SessionContents sessionContents, + AttendanceTimeResponse attendance +) { + public static SessionWithAttendanceResponse of(Session session, List sessionImages, Attendance attendance) { + return new SessionWithAttendanceResponse( + session.getId(), + session.getNumber(), + session.getTitle(), + sessionImages.stream().map(SessionListImageInfoResponse::from).toList(), + session.getDescription(), + session.getGeneration().getId(), + session.getPlaceName(), + session.getSessionDateTime(), + session.getSessionContents(), + AttendanceTimeResponse.from(attendance) + ); + } + + public static SessionWithAttendanceResponse of(Session session, List sessionImages) { + return new SessionWithAttendanceResponse( + session.getId(), + session.getNumber(), + session.getTitle(), + sessionImages.stream().map(SessionListImageInfoResponse::from).toList(), + session.getDescription(), + session.getGeneration().getId(), + session.getPlaceName(), + session.getSessionDateTime(), + session.getSessionContents(), + null + ); + } +} diff --git a/src/main/java/org/cotato/csquiz/common/config/SecurityConfig.java b/src/main/java/org/cotato/csquiz/common/config/SecurityConfig.java index 89bf9422..82155fc9 100644 --- a/src/main/java/org/cotato/csquiz/common/config/SecurityConfig.java +++ b/src/main/java/org/cotato/csquiz/common/config/SecurityConfig.java @@ -91,6 +91,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers("/v1/api/record/reply").hasAnyRole("MEMBER", "EDUCATION", "OPERATION", "ADMIN") .requestMatchers("/v1/api/record/**").hasAnyRole("EDUCATION", "ADMIN") .requestMatchers("/v1/api/session/cs-on").hasAnyRole("EDUCATION", "ADMIN") + .requestMatchers(new AntPathRequestMatcher("/v1/api/session/**", HttpMethod.GET.name())).permitAll() .requestMatchers(new AntPathRequestMatcher("/v1/api/session", "GET")).authenticated() .requestMatchers("/v1/api/session/**").hasAnyRole("ADMIN") .requestMatchers("/v2/api/attendances/records").hasAnyRole("OPERATION", "ADMIN") diff --git a/src/main/java/org/cotato/csquiz/common/config/filter/JwtAuthorizationFilter.java b/src/main/java/org/cotato/csquiz/common/config/filter/JwtAuthorizationFilter.java index 1142f1c4..ac0ad111 100644 --- a/src/main/java/org/cotato/csquiz/common/config/filter/JwtAuthorizationFilter.java +++ b/src/main/java/org/cotato/csquiz/common/config/filter/JwtAuthorizationFilter.java @@ -33,11 +33,11 @@ public class JwtAuthorizationFilter extends OncePerRequestFilter { private static final String SESSION_PATH = "/v1/api/session"; private static final String POLICIES_PATH = "/v2/api/policies"; private static final String PROJECTS_LIST = "/v2/api/projects"; - private static final String PROJECT_DETAIL = "/v2/api/projects/{projectId:\\d+}"; + private static final String PROJECT_DETAIL = "/v2/api/projects"; private static final String CURRENT_GENERATION = "/v1/api/generation/current"; + private static final String INTEGER_REGEX = "/{id:\\d+}"; private final JwtTokenProvider jwtTokenProvider; - private static final AntPathMatcher pathMatcher = new AntPathMatcher(); @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) @@ -66,8 +66,7 @@ private void setAuthentication(String accessToken) { @Override protected boolean shouldNotFilter(HttpServletRequest request) { String path = request.getRequestURI(); - log.info("요청 경로: {}", path); - log.info("요청 메서드: {}", request.getMethod()); + log.info("요청 경로 및 메서드: {}, {}", path, request.getMethod()); return path.startsWith(AUTH_PATH) || path.equals(LOGIN_PATH) || path.startsWith(SWAGGER_PATH) || path.equals(SWAGGER_FAVICON) || path.startsWith(SWAGGER_PATH_3) || path.startsWith(WS) @@ -75,6 +74,8 @@ protected boolean shouldNotFilter(HttpServletRequest request) { || path.equals(POLICIES_PATH) || path.equals(CURRENT_GENERATION) || path.equals(PROJECTS_LIST) && HttpMethod.GET.name().equals(request.getMethod()) - || pathMatcher.match(PROJECT_DETAIL, path); + || new AntPathMatcher().match(PROJECT_DETAIL + INTEGER_REGEX, path) + || (new AntPathMatcher().match(SESSION_PATH + INTEGER_REGEX, path) && request.getMethod().equals(HttpMethod.GET.name())) + ; } } diff --git a/src/main/java/org/cotato/csquiz/domain/generation/service/SessionService.java b/src/main/java/org/cotato/csquiz/domain/generation/service/SessionService.java index 7b68d9d8..6d803a33 100644 --- a/src/main/java/org/cotato/csquiz/domain/generation/service/SessionService.java +++ b/src/main/java/org/cotato/csquiz/domain/generation/service/SessionService.java @@ -5,6 +5,7 @@ import java.time.LocalTime; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -12,6 +13,7 @@ import org.cotato.csquiz.api.session.dto.AddSessionResponse; import org.cotato.csquiz.api.session.dto.CsEducationOnSessionNumberResponse; import org.cotato.csquiz.api.session.dto.SessionListResponse; +import org.cotato.csquiz.api.session.dto.SessionWithAttendanceResponse; import org.cotato.csquiz.api.session.dto.UpdateSessionRequest; import org.cotato.csquiz.common.error.exception.ImageException; import org.cotato.csquiz.common.schedule.SchedulerService; @@ -171,4 +173,12 @@ public List findAllNotLinkedCsOnSessionsByGe .map(CsEducationOnSessionNumberResponse::from) .toList(); } + + public SessionWithAttendanceResponse findSession(Long sessionId) { + Session session = findSessionById(sessionId); + List sessionImages = sessionImageRepository.findAllBySession(session); + Optional maybeAttendance = attendanceRepository.findBySessionId(sessionId); + return maybeAttendance.map(attendance -> SessionWithAttendanceResponse.of(session, sessionImages, attendance)) + .orElseGet(() -> SessionWithAttendanceResponse.of(session, sessionImages)); + } }