diff --git a/src/main/java/com/somemore/auth/annotation/CurrentUser.java b/src/main/java/com/somemore/auth/annotation/CurrentUser.java new file mode 100644 index 000000000..d6773bef5 --- /dev/null +++ b/src/main/java/com/somemore/auth/annotation/CurrentUser.java @@ -0,0 +1,14 @@ +package com.somemore.auth.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.springframework.security.core.annotation.AuthenticationPrincipal; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null :T(java.util.UUID).fromString(#this)") +public @interface CurrentUser { + +} diff --git a/src/main/java/com/somemore/center/controller/CenterSignController.java b/src/main/java/com/somemore/center/controller/CenterSignController.java index f4a3c781d..a79b3418b 100644 --- a/src/main/java/com/somemore/center/controller/CenterSignController.java +++ b/src/main/java/com/somemore/center/controller/CenterSignController.java @@ -1,6 +1,7 @@ package com.somemore.center.controller; import com.somemore.auth.signout.usecase.SignOutUseCase; +import com.somemore.center.dto.request.CenterSignRequestDto; import com.somemore.global.common.response.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; @@ -9,17 +10,30 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j @RequiredArgsConstructor @RequestMapping("/api/center") -@Tag(name = "center Sign API", description = "기관 로그아웃") +@Tag(name = "center Sign API", description = "기관 로그인, 로그아웃") public class CenterSignController { private final SignOutUseCase signOutUseCase; + /* + * 기관 로그인 엔드포인트 + * 실제 로그인 절차는 필터에서 처리됩니다. + * 이 엔드포인트는 로그인 요청을 받아 필터에 의한 인증 절차를 수행합니다. + */ + @PostMapping("/sign-in") + public ApiResponse signIn( + @RequestParam CenterSignRequestDto requestDto + ) { + return ApiResponse.ok("로그인되었습니다."); + } + @PostMapping("/sign-out") public ApiResponse signOut( HttpServletResponse response, diff --git a/src/main/java/com/somemore/center/controller/PreferItemCommandApiController.java b/src/main/java/com/somemore/center/controller/PreferItemCommandApiController.java index cde5cfc10..776f03389 100644 --- a/src/main/java/com/somemore/center/controller/PreferItemCommandApiController.java +++ b/src/main/java/com/somemore/center/controller/PreferItemCommandApiController.java @@ -1,5 +1,6 @@ package com.somemore.center.controller; +import com.somemore.auth.annotation.CurrentUser; import com.somemore.center.dto.request.PreferItemCreateRequestDto; import com.somemore.center.dto.response.PreferItemCreateResponseDto; import com.somemore.center.usecase.command.CreatePreferItemUseCase; @@ -7,16 +8,14 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.security.access.annotation.Secured; -import org.springframework.security.core.annotation.AuthenticationPrincipal; 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.RestController; -import java.util.UUID; - @RequiredArgsConstructor @RestController @RequestMapping("/api/preferItem") @@ -28,10 +27,12 @@ public class PreferItemCommandApiController { @Secured("ROLE_CENTER") @Operation(summary = "기관 선호물품 등록 API") @PostMapping() - public ApiResponse registerPreferItem(@Valid @RequestBody PreferItemCreateRequestDto requestDto, - @AuthenticationPrincipal String userId) { + public ApiResponse registerPreferItem( + @Valid @RequestBody PreferItemCreateRequestDto requestDto, + @CurrentUser UUID userId) { - PreferItemCreateResponseDto responseDto = createPreferItemUseCase.createPreferItem(UUID.fromString(userId), requestDto); + PreferItemCreateResponseDto responseDto = createPreferItemUseCase.createPreferItem(userId, + requestDto); return ApiResponse.ok(200, responseDto, "관심 기관 등록 성공"); } diff --git a/src/main/java/com/somemore/center/dto/request/CenterSignRequestDto.java b/src/main/java/com/somemore/center/dto/request/CenterSignRequestDto.java new file mode 100644 index 000000000..df982e41d --- /dev/null +++ b/src/main/java/com/somemore/center/dto/request/CenterSignRequestDto.java @@ -0,0 +1,17 @@ +package com.somemore.center.dto.request; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; + +@JsonNaming(SnakeCaseStrategy.class) +@Builder +public record CenterSignRequestDto( + @Schema(description = "기관 아이디", example = "somemore") + String accountId, + @Schema(description = "기관 패스워드", example = "password1234") + String accountPassword +) { + +} diff --git a/src/main/java/com/somemore/global/common/response/ApiResponse.java b/src/main/java/com/somemore/global/common/response/ApiResponse.java index 6b00a6c07..1d2f84813 100644 --- a/src/main/java/com/somemore/global/common/response/ApiResponse.java +++ b/src/main/java/com/somemore/global/common/response/ApiResponse.java @@ -1,5 +1,6 @@ package com.somemore.global.common.response; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.NoArgsConstructor; @@ -7,8 +8,11 @@ @Getter public class ApiResponse { + @Schema(description = "응답 상태 코드. 성공 시 200, 실패 시 오류 코드", example = "200") private int code; + @Schema(description = "응답에 대한 메시지. 요청 성공/실패에 대한 설명", example = "요청 성공") private String message; + @Schema(description = "API 요청 처리 결과로 반환되는 데이터", example = "{ name : 손모아 }") private T data; public static ApiResponse ok(int status, T data, String message) { diff --git a/src/main/java/com/somemore/interestcenter/controller/InterestCenterQueryApiController.java b/src/main/java/com/somemore/interestcenter/controller/InterestCenterQueryApiController.java index 1b8cd43d2..f039057e7 100644 --- a/src/main/java/com/somemore/interestcenter/controller/InterestCenterQueryApiController.java +++ b/src/main/java/com/somemore/interestcenter/controller/InterestCenterQueryApiController.java @@ -1,18 +1,17 @@ package com.somemore.interestcenter.controller; +import com.somemore.auth.annotation.CurrentUser; import com.somemore.global.common.response.ApiResponse; import com.somemore.interestcenter.dto.response.InterestCentersResponseDto; import com.somemore.interestcenter.usecase.InterestCenterQueryUseCase; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; +import java.util.UUID; import lombok.RequiredArgsConstructor; -import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.List; -import java.util.UUID; - @RequiredArgsConstructor @RestController @Tag(name = "Interest Center Query API", description = "관심 기관의 조회 API를 제공합니다") @@ -22,9 +21,11 @@ public class InterestCenterQueryApiController { @Operation(summary = "관심기관 목록 조회 API") @GetMapping("/api/interest-centers") - public ApiResponse> getInterestCenters(@AuthenticationPrincipal String volunteerId) { + public ApiResponse> getInterestCenters( + @CurrentUser UUID volunteerId) { - List responseDtos = interestCenterQueryUseCase.getInterestCenters(UUID.fromString(volunteerId)); + List responseDtos = interestCenterQueryUseCase.getInterestCenters( + volunteerId); return ApiResponse.ok(200, responseDtos, "관심기관 조회 성공"); } diff --git a/src/main/java/com/somemore/recruitboard/controller/RecruitBoardCommandApiController.java b/src/main/java/com/somemore/recruitboard/controller/RecruitBoardCommandApiController.java index d8274b6a0..2f1804c1c 100644 --- a/src/main/java/com/somemore/recruitboard/controller/RecruitBoardCommandApiController.java +++ b/src/main/java/com/somemore/recruitboard/controller/RecruitBoardCommandApiController.java @@ -3,6 +3,7 @@ import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE; +import com.somemore.auth.annotation.CurrentUser; import com.somemore.global.common.response.ApiResponse; import com.somemore.imageupload.dto.ImageUploadRequestDto; import com.somemore.imageupload.usecase.ImageUploadUseCase; @@ -20,7 +21,6 @@ import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.security.access.annotation.Secured; -import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -47,7 +47,7 @@ public class RecruitBoardCommandApiController { @Operation(summary = "봉사 활동 모집글 등록", description = "봉사 활동 모집글을 등록합니다.") @PostMapping(value = "/recruit-board", consumes = MULTIPART_FORM_DATA_VALUE) public ApiResponse createRecruitBoard( - @AuthenticationPrincipal String userId, + @CurrentUser UUID userId, @Valid @RequestPart("data") RecruitBoardCreateRequestDto requestDto, @RequestPart(value = "img_file", required = false) MultipartFile image ) { @@ -55,8 +55,7 @@ public ApiResponse createRecruitBoard( String imgUrl = imageUploadUseCase.uploadImage(new ImageUploadRequestDto(image)); return ApiResponse.ok( 201, - createRecruitBoardUseCase.createRecruitBoard(requestDto, getCenterId(userId), - imgUrl), + createRecruitBoardUseCase.createRecruitBoard(requestDto, userId, imgUrl), "봉사 활동 모집글 등록 성공" ); } @@ -65,13 +64,13 @@ public ApiResponse createRecruitBoard( @Operation(summary = "봉사 활동 모집글 수정", description = "봉사 활동 모집글을 수정합니다.") @PutMapping(value = "/recruit-board/{id}", consumes = MULTIPART_FORM_DATA_VALUE) public ApiResponse updateRecruitBoard( - @AuthenticationPrincipal String userId, + @CurrentUser UUID userId, @PathVariable Long id, @Valid @RequestPart("data") RecruitBoardUpdateRequestDto requestDto, @RequestPart(value = "img_file", required = false) MultipartFile image ) { String imgUrl = imageUploadUseCase.uploadImage(new ImageUploadRequestDto(image)); - updateRecruitBoardUseCase.updateRecruitBoard(requestDto, id, getCenterId(userId), imgUrl); + updateRecruitBoardUseCase.updateRecruitBoard(requestDto, id, userId, imgUrl); return ApiResponse.ok("봉사 활동 모집글 수정 성공"); } @@ -80,12 +79,12 @@ public ApiResponse updateRecruitBoard( @Operation(summary = "봉사 활동 모집글 위치 수정", description = "봉사 활동 모집글의 위치를 수정합니다.") @PutMapping(value = "/recruit-board/{id}/location") public ApiResponse updateRecruitBoardLocation( - @AuthenticationPrincipal String userId, + @CurrentUser UUID userId, @PathVariable Long id, @Valid @RequestBody RecruitBoardLocationUpdateRequestDto requestDto ) { - updateRecruitBoardUseCase.updateRecruitBoardLocation(requestDto, id, getCenterId(userId)); + updateRecruitBoardUseCase.updateRecruitBoardLocation(requestDto, id, userId); return ApiResponse.ok("봉사 활동 모집글 위치 수정 성공"); } @@ -93,14 +92,12 @@ public ApiResponse updateRecruitBoardLocation( @Operation(summary = "봉사 활동 모집글 상태 수정", description = "봉사 활동 모집글의 상태를 수정합니다.") @PatchMapping(value = "/recruit-board/{id}") public ApiResponse updateRecruitBoardStatus( - @AuthenticationPrincipal String userId, + @CurrentUser UUID userId, @PathVariable Long id, @RequestBody RecruitBoardStatusUpdateRequestDto requestDto ) { LocalDateTime now = LocalDateTime.now(); - updateRecruitBoardUseCase.updateRecruitBoardStatus(requestDto.status(), id, - getCenterId(userId), - now); + updateRecruitBoardUseCase.updateRecruitBoardStatus(requestDto.status(), id, userId, now); return ApiResponse.ok("봉사 활동 모집글 상태 수정 성공"); } @@ -109,15 +106,11 @@ public ApiResponse updateRecruitBoardStatus( @Operation(summary = "봉사 활동 모집글 삭제", description = "봉사 활동 모집글을 삭제합니다.") @DeleteMapping(value = "/recruit-board/{id}") public ApiResponse deleteRecruitBoard( - @AuthenticationPrincipal String userId, + @CurrentUser UUID userId, @PathVariable Long id ) { - deleteRecruitBoardUseCase.deleteRecruitBoard(getCenterId(userId), id); + deleteRecruitBoardUseCase.deleteRecruitBoard(userId, id); return ApiResponse.ok("봉사 활동 모집글 삭제 성공"); } - private static UUID getCenterId(String userId) { - return UUID.fromString(userId); - } - } diff --git a/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardCreateRequestDto.java b/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardCreateRequestDto.java index aeb2a38f6..a90bf03ea 100644 --- a/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardCreateRequestDto.java +++ b/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardCreateRequestDto.java @@ -16,51 +16,51 @@ @JsonNaming(SnakeCaseStrategy.class) @Builder public record RecruitBoardCreateRequestDto( - @Schema(description = "봉사 모집글 제목", example = "서울 청계천 환경 미화 봉사 모집") - @NotBlank(message = "모집글 제목은 필수 값입니다.") - String title, - @Schema(description = "봉사 모집글 내용", example = "서울 청계천 주변 환경 미화 봉사 모집합니다.
") - @NotBlank(message = "모집글 내용은 필수 값입니다.") - String content, - @Schema(description = "봉사 지역", example = "서울") - @NotBlank(message = "봉사 지역은 필수 값입니다.") - String region, - @Schema(description = "예상 모집 인원", example = "4") - @NotNull(message = "예상 모집 인원은 필수 값입니다.") - Integer recruitmentCount, - @Schema(description = "봉사 시작 일시", example = "2024-11-20T10:00:00") - @NotNull(message = "봉사 시작 일시는 필수 값입니다.") - LocalDateTime volunteerStartDateTime, - @Schema(description = "봉사 종료 일시", example = "2024-11-20T12:00:00") - @NotNull(message = "봉사 종료 일시는 필수 값입니다.") - LocalDateTime volunteerEndDateTime, - @Schema(description = "봉사 활동 유형", example = "ENVIRONMENTAL_PROTECTION") - @NotNull(message = "봉사 활동 유형은 필수 값입니다.") - VolunteerCategory volunteerCategory, - @Schema(description = "봉사 시간 인정 여부", example = "true") - @NotNull(message = "시간 인정 여부는 필수 값입니다.") - Boolean admitted, - @NotNull(message = "위치 정보는 필수 값입니다.") - LocationCreateRequestDto location + @Schema(description = "봉사 모집글 제목", example = "서울 청계천 환경 미화 봉사 모집") + @NotBlank(message = "모집글 제목은 필수 값입니다.") + String title, + @Schema(description = "봉사 모집글 내용", example = "서울 청계천 주변 환경 미화 봉사 모집합니다.
") + @NotBlank(message = "모집글 내용은 필수 값입니다.") + String content, + @Schema(description = "봉사 지역", example = "서울") + @NotBlank(message = "봉사 지역은 필수 값입니다.") + String region, + @Schema(description = "예상 모집 인원", example = "4") + @NotNull(message = "예상 모집 인원은 필수 값입니다.") + Integer recruitmentCount, + @Schema(description = "봉사 시작 일시", example = "2024-11-20T10:00:00", type = "string") + @NotNull(message = "봉사 시작 일시는 필수 값입니다.") + LocalDateTime volunteerStartDateTime, + @Schema(description = "봉사 종료 일시", example = "2024-11-20T12:00:00", type = "string") + @NotNull(message = "봉사 종료 일시는 필수 값입니다.") + LocalDateTime volunteerEndDateTime, + @Schema(description = "봉사 활동 유형", example = "ENVIRONMENTAL_PROTECTION") + @NotNull(message = "봉사 활동 유형은 필수 값입니다.") + VolunteerCategory volunteerCategory, + @Schema(description = "봉사 시간 인정 여부", example = "true") + @NotNull(message = "시간 인정 여부는 필수 값입니다.") + Boolean admitted, + @NotNull(message = "위치 정보는 필수 값입니다.") + LocationCreateRequestDto location ) { public RecruitBoard toEntity(UUID centerId, Long locationId, String imgUrl) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() - .region(region) - .recruitmentCount(recruitmentCount) - .volunteerStartDateTime(volunteerStartDateTime) - .volunteerEndDateTime(volunteerEndDateTime) - .volunteerCategory(volunteerCategory) - .admitted(admitted) - .build(); + .region(region) + .recruitmentCount(recruitmentCount) + .volunteerStartDateTime(volunteerStartDateTime) + .volunteerEndDateTime(volunteerEndDateTime) + .volunteerCategory(volunteerCategory) + .admitted(admitted) + .build(); return RecruitBoard.builder() - .centerId(centerId) - .locationId(locationId) - .title(title) - .content(content) - .imgUrl(imgUrl) - .recruitmentInfo(recruitmentInfo) - .build(); + .centerId(centerId) + .locationId(locationId) + .title(title) + .content(content) + .imgUrl(imgUrl) + .recruitmentInfo(recruitmentInfo) + .build(); } } diff --git a/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardUpdateRequestDto.java b/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardUpdateRequestDto.java index 431056365..544c74df5 100644 --- a/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardUpdateRequestDto.java +++ b/src/main/java/com/somemore/recruitboard/dto/request/RecruitBoardUpdateRequestDto.java @@ -12,27 +12,27 @@ @JsonNaming(SnakeCaseStrategy.class) @Builder public record RecruitBoardUpdateRequestDto( - @Schema(description = "봉사 모집글 제목", example = "서울 청계천 환경 미화 봉사 모집") - @NotBlank(message = "모집글 제목은 필수 값입니다.") - String title, - @Schema(description = "봉사 모집글 내용", example = "서울 청계천 주변 환경 미화 봉사 모집합니다.
") - @NotBlank(message = "모집글 내용은 필수 값입니다.") - String content, - @Schema(description = "예상 모집 인원", example = "4") - @NotNull(message = "예상 모집 인원은 필수 값입니다.") - Integer recruitmentCount, - @Schema(description = "봉사 시작 일시", example = "2024-11-20T10:00:00") - @NotNull(message = "봉사 시작 일시는 필수 값입니다.") - LocalDateTime volunteerStartDateTime, - @Schema(description = "봉사 종료 일시", example = "2024-11-20T12:00:00") - @NotNull(message = "봉사 종료 일시는 필수 값입니다.") - LocalDateTime volunteerEndDateTime, - @Schema(description = "봉사 활동 유형", example = "ENVIRONMENTAL_PROTECTION") - @NotNull(message = "봉사 활동 유형은 필수 값입니다.") - VolunteerCategory volunteerCategory, - @Schema(description = "봉사 시간 인정 여부", example = "true") - @NotNull(message = "시간 인정 여부는 필수 값입니다.") - Boolean admitted + @Schema(description = "봉사 모집글 제목", example = "서울 청계천 환경 미화 봉사 모집") + @NotBlank(message = "모집글 제목은 필수 값입니다.") + String title, + @Schema(description = "봉사 모집글 내용", example = "서울 청계천 주변 환경 미화 봉사 모집합니다.
") + @NotBlank(message = "모집글 내용은 필수 값입니다.") + String content, + @Schema(description = "예상 모집 인원", example = "4") + @NotNull(message = "예상 모집 인원은 필수 값입니다.") + Integer recruitmentCount, + @Schema(description = "봉사 시작 일시", example = "2024-11-20T10:00:00", type = "string") + @NotNull(message = "봉사 시작 일시는 필수 값입니다.") + LocalDateTime volunteerStartDateTime, + @Schema(description = "봉사 종료 일시", example = "2024-11-20T12:00:00", type = "string") + @NotNull(message = "봉사 종료 일시는 필수 값입니다.") + LocalDateTime volunteerEndDateTime, + @Schema(description = "봉사 활동 유형", example = "ENVIRONMENTAL_PROTECTION") + @NotNull(message = "봉사 활동 유형은 필수 값입니다.") + VolunteerCategory volunteerCategory, + @Schema(description = "봉사 시간 인정 여부", example = "true") + @NotNull(message = "시간 인정 여부는 필수 값입니다.") + Boolean admitted ) { } diff --git a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardDetailResponseDto.java b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardDetailResponseDto.java index 50f89a751..89489bd95 100644 --- a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardDetailResponseDto.java +++ b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardDetailResponseDto.java @@ -19,67 +19,67 @@ @JsonNaming(SnakeCaseStrategy.class) @Schema(description = "봉사 모집글 기관 및 위치 포함 응답 DTO") public record RecruitBoardDetailResponseDto( - @Schema(description = "봉사 모집글 ID", example = "123") - Long id, - @Schema(description = "모집글 생성 일시", example = "2024-12-01T09:00:00") - LocalDateTime createdAt, - @Schema(description = "모집글 수정 일시", example = "2024-12-01T09:00:00") - LocalDateTime updatedAt, - @Schema(description = "모집글 제목", example = "환경 정화 봉사") - String title, - @Schema(description = "모집글 내용", example = "도시 공원에서 환경 정화 활동") - String content, - @Schema(description = "지역 정보", example = "서울특별시") - String region, - @Schema(description = "모집 상태", example = "RECRUITING") - RecruitStatus recruitStatus, - @Schema(description = "모집 인원 수", example = "15") - Integer recruitmentCount, - @Schema(description = "봉사 시작 일시", example = "2024-12-01T09:00:00") - LocalDateTime volunteerStartDateTime, - @Schema(description = "봉사 종료 일시", example = "2024-12-01T13:00:00") - LocalDateTime volunteerEndDateTime, - @Schema(description = "봉사 유형", example = "LIVING_SUPPORT") - VolunteerCategory volunteerCategory, - @Schema(description = "봉사 시간", example = "04:00:00") - LocalTime volunteerTime, - @Schema(description = "시간 인정 여부", example = "true") - Boolean admitted, - @Schema(description = "이미지 URL", example = "https://image.domain.com/links") - String imgUrl, - @Schema(description = "센터 간단 정보") - CenterSimpleInfoResponseDto center, - @Schema(description = "위치 정보 DTO") - LocationResponseDto location + @Schema(description = "봉사 모집글 ID", example = "123") + Long id, + @Schema(description = "모집글 생성 일시", example = "2024-12-01T09:00:00", type = "string") + LocalDateTime createdAt, + @Schema(description = "모집글 수정 일시", example = "2024-12-01T09:00:00", type = "string") + LocalDateTime updatedAt, + @Schema(description = "모집글 제목", example = "환경 정화 봉사") + String title, + @Schema(description = "모집글 내용", example = "도시 공원에서 환경 정화 활동") + String content, + @Schema(description = "지역 정보", example = "서울특별시") + String region, + @Schema(description = "모집 상태", example = "RECRUITING") + RecruitStatus recruitStatus, + @Schema(description = "모집 인원 수", example = "15") + Integer recruitmentCount, + @Schema(description = "봉사 시작 일시", example = "2024-12-01T09:00:00", type = "string") + LocalDateTime volunteerStartDateTime, + @Schema(description = "봉사 종료 일시", example = "2024-12-01T13:00:00", type = "string") + LocalDateTime volunteerEndDateTime, + @Schema(description = "봉사 유형", example = "LIVING_SUPPORT") + VolunteerCategory volunteerCategory, + @Schema(description = "봉사 시간", example = "04:00:00") + LocalTime volunteerTime, + @Schema(description = "시간 인정 여부", example = "true") + Boolean admitted, + @Schema(description = "이미지 URL", example = "https://image.domain.com/links") + String imgUrl, + @Schema(description = "센터 간단 정보") + CenterSimpleInfoResponseDto center, + @Schema(description = "위치 정보 DTO") + LocationResponseDto location ) { public static RecruitBoardDetailResponseDto from(RecruitBoardDetail recruitBoardDetail) { RecruitBoard board = recruitBoardDetail.recruitBoard(); RecruitmentInfo info = board.getRecruitmentInfo(); CenterSimpleInfoResponseDto center = CenterSimpleInfoResponseDto.of(board.getCenterId(), - recruitBoardDetail.centerName()); + recruitBoardDetail.centerName()); LocationResponseDto location = LocationResponseDto.of( - recruitBoardDetail.address(), recruitBoardDetail.latitude(), - recruitBoardDetail.longitude()); + recruitBoardDetail.address(), recruitBoardDetail.latitude(), + recruitBoardDetail.longitude()); return RecruitBoardDetailResponseDto.builder() - .id(board.getId()) - .createdAt(board.getCreatedAt()) - .updatedAt(board.getUpdatedAt()) - .title(board.getTitle()) - .content(board.getContent()) - .region(info.getRegion()) - .recruitStatus(board.getRecruitStatus()) - .recruitmentCount(info.getRecruitmentCount()) - .volunteerStartDateTime(info.getVolunteerStartDateTime()) - .volunteerEndDateTime(info.getVolunteerEndDateTime()) - .volunteerCategory(info.getVolunteerCategory()) - .volunteerTime(info.calculateVolunteerTime()) - .admitted(info.getAdmitted()) - .imgUrl(board.getImgUrl()) - .location(location) - .center(center) - .build(); + .id(board.getId()) + .createdAt(board.getCreatedAt()) + .updatedAt(board.getUpdatedAt()) + .title(board.getTitle()) + .content(board.getContent()) + .region(info.getRegion()) + .recruitStatus(board.getRecruitStatus()) + .recruitmentCount(info.getRecruitmentCount()) + .volunteerStartDateTime(info.getVolunteerStartDateTime()) + .volunteerEndDateTime(info.getVolunteerEndDateTime()) + .volunteerCategory(info.getVolunteerCategory()) + .volunteerTime(info.calculateVolunteerTime()) + .admitted(info.getAdmitted()) + .imgUrl(board.getImgUrl()) + .location(location) + .center(center) + .build(); } } diff --git a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardResponseDto.java b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardResponseDto.java index 323dd6d50..e209f4c71 100644 --- a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardResponseDto.java +++ b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardResponseDto.java @@ -16,59 +16,59 @@ @JsonNaming(SnakeCaseStrategy.class) @Schema(description = "봉사 모집글 응답 DTO") public record RecruitBoardResponseDto( - @Schema(description = "봉사 모집글 ID", example = "123") - Long id, - @Schema(description = "센터 ID", example = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d") - UUID centerId, - @Schema(description = "위치 ID", example = "1") - Long locationId, - @Schema(description = "모집글 생성 일시", example = "2024-12-01T09:00:00") - LocalDateTime createdAt, - @Schema(description = "모집글 수정 일시", example = "2024-12-01T09:00:00") - LocalDateTime updatedAt, - @Schema(description = "모집글 제목", example = "환경 정화 봉사") - String title, - @Schema(description = "모집글 내용", example = "도시 공원에서 환경 정화 활동") - String content, - @Schema(description = "지역 정보", example = "서울특별시") - String region, - @Schema(description = "모집 상태", example = "RECRUITING") - RecruitStatus recruitStatus, - @Schema(description = "모집 인원 수", example = "15") - Integer recruitmentCount, - @Schema(description = "봉사 시작 일시", example = "2024-12-01T09:00:00") - LocalDateTime volunteerStartDateTime, - @Schema(description = "봉사 종료 일시", example = "2024-12-01T13:00:00") - LocalDateTime volunteerEndDateTime, - @Schema(description = "봉사 유형", example = "LIVING_SUPPORT") - VolunteerCategory volunteerCategory, - @Schema(description = "봉사 시간", example = "04:00:00") - LocalTime volunteerTime, - @Schema(description = "시간 인정 여부", example = "true") - Boolean admitted, - @Schema(description = "이미지 URL", example = "https://image.domain.com/links") - String imgUrl + @Schema(description = "봉사 모집글 ID", example = "123") + Long id, + @Schema(description = "센터 ID", example = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d") + UUID centerId, + @Schema(description = "위치 ID", example = "1") + Long locationId, + @Schema(description = "모집글 생성 일시", example = "2024-12-01T09:00:00", type = "string") + LocalDateTime createdAt, + @Schema(description = "모집글 수정 일시", example = "2024-12-01T09:00:00", type = "string") + LocalDateTime updatedAt, + @Schema(description = "모집글 제목", example = "환경 정화 봉사") + String title, + @Schema(description = "모집글 내용", example = "도시 공원에서 환경 정화 활동") + String content, + @Schema(description = "지역 정보", example = "서울특별시") + String region, + @Schema(description = "모집 상태", example = "RECRUITING") + RecruitStatus recruitStatus, + @Schema(description = "모집 인원 수", example = "15") + Integer recruitmentCount, + @Schema(description = "봉사 시작 일시", example = "2024-12-01T09:00:00", type = "string") + LocalDateTime volunteerStartDateTime, + @Schema(description = "봉사 종료 일시", example = "2024-12-01T13:00:00", type = "string") + LocalDateTime volunteerEndDateTime, + @Schema(description = "봉사 유형", example = "LIVING_SUPPORT") + VolunteerCategory volunteerCategory, + @Schema(description = "봉사 시간", example = "04:00:00") + LocalTime volunteerTime, + @Schema(description = "시간 인정 여부", example = "true") + Boolean admitted, + @Schema(description = "이미지 URL", example = "https://image.domain.com/links") + String imgUrl ) { public static RecruitBoardResponseDto from(RecruitBoard board) { RecruitmentInfo info = board.getRecruitmentInfo(); return RecruitBoardResponseDto.builder() - .id(board.getId()) - .centerId(board.getCenterId()) - .createdAt(board.getCreatedAt()) - .updatedAt(board.getUpdatedAt()) - .title(board.getTitle()) - .content(board.getContent()) - .region(info.getRegion()) - .recruitStatus(board.getRecruitStatus()) - .recruitmentCount(info.getRecruitmentCount()) - .volunteerStartDateTime(info.getVolunteerStartDateTime()) - .volunteerEndDateTime(info.getVolunteerEndDateTime()) - .volunteerCategory(info.getVolunteerCategory()) - .volunteerTime(info.calculateVolunteerTime()) - .admitted(info.getAdmitted()) - .imgUrl(board.getImgUrl()) - .build(); + .id(board.getId()) + .centerId(board.getCenterId()) + .createdAt(board.getCreatedAt()) + .updatedAt(board.getUpdatedAt()) + .title(board.getTitle()) + .content(board.getContent()) + .region(info.getRegion()) + .recruitStatus(board.getRecruitStatus()) + .recruitmentCount(info.getRecruitmentCount()) + .volunteerStartDateTime(info.getVolunteerStartDateTime()) + .volunteerEndDateTime(info.getVolunteerEndDateTime()) + .volunteerCategory(info.getVolunteerCategory()) + .volunteerTime(info.calculateVolunteerTime()) + .admitted(info.getAdmitted()) + .imgUrl(board.getImgUrl()) + .build(); } } diff --git a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithCenterResponseDto.java b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithCenterResponseDto.java index da6013e34..ce0926751 100644 --- a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithCenterResponseDto.java +++ b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithCenterResponseDto.java @@ -17,63 +17,64 @@ @JsonNaming(SnakeCaseStrategy.class) @Schema(description = "봉사 모집글 기관 포함 응답 DTO") public record RecruitBoardWithCenterResponseDto( - @Schema(description = "봉사 모집글 ID", example = "123") - Long id, - @Schema(description = "위치 ID", example = "1") - Long locationId, - @Schema(description = "모집글 생성 일시", example = "2024-12-01T09:00:00") - LocalDateTime createdAt, - @Schema(description = "모집글 수정 일시", example = "2024-12-01T09:00:00") - LocalDateTime updatedAt, - @Schema(description = "모집글 제목", example = "환경 정화 봉사") - String title, - @Schema(description = "모집글 내용", example = "도시 공원에서 환경 정화 활동") - String content, - @Schema(description = "지역 정보", example = "서울특별시") - String region, - @Schema(description = "모집 상태", example = "RECRUITING") - RecruitStatus recruitStatus, - @Schema(description = "모집 인원 수", example = "15") - Integer recruitmentCount, - @Schema(description = "봉사 시작 일시", example = "2024-12-01T09:00:00") - LocalDateTime volunteerStartDateTime, - @Schema(description = "봉사 종료 일시", example = "2024-12-01T13:00:00") - LocalDateTime volunteerEndDateTime, - @Schema(description = "봉사 유형", example = "LIVING_SUPPORT") - VolunteerCategory volunteerCategory, - @Schema(description = "봉사 시간", example = "04:00:00") - LocalTime volunteerTime, - @Schema(description = "시간 인정 여부", example = "true") - Boolean admitted, - @Schema(description = "이미지 URL", example = "https://image.domain.com/links") - String imgUrl, - @Schema(description = "센터 간단 정보") - CenterSimpleInfoResponseDto center + @Schema(description = "봉사 모집글 ID", example = "123") + Long id, + @Schema(description = "위치 ID", example = "1") + Long locationId, + @Schema(description = "모집글 생성 일시", example = "2024-12-01T09:00:00", type = "string") + LocalDateTime createdAt, + @Schema(description = "모집글 수정 일시", example = "2024-12-01T09:00:00", type = "string") + LocalDateTime updatedAt, + @Schema(description = "모집글 제목", example = "환경 정화 봉사") + String title, + @Schema(description = "모집글 내용", example = "도시 공원에서 환경 정화 활동") + String content, + @Schema(description = "지역 정보", example = "서울특별시") + String region, + @Schema(description = "모집 상태", example = "RECRUITING") + RecruitStatus recruitStatus, + @Schema(description = "모집 인원 수", example = "15") + Integer recruitmentCount, + @Schema(description = "봉사 시작 일시", example = "2024-12-01T09:00:00", type = "string") + LocalDateTime volunteerStartDateTime, + @Schema(description = "봉사 종료 일시", example = "2024-12-01T13:00:00", type = "string") + LocalDateTime volunteerEndDateTime, + @Schema(description = "봉사 유형", example = "LIVING_SUPPORT") + VolunteerCategory volunteerCategory, + @Schema(description = "봉사 시간", example = "04:00:00") + LocalTime volunteerTime, + @Schema(description = "시간 인정 여부", example = "true") + Boolean admitted, + @Schema(description = "이미지 URL", example = "https://image.domain.com/links") + String imgUrl, + @Schema(description = "센터 간단 정보") + CenterSimpleInfoResponseDto center ) { public static RecruitBoardWithCenterResponseDto from( - RecruitBoardWithCenter recruitBoardWithCenter) { + RecruitBoardWithCenter recruitBoardWithCenter) { RecruitBoard board = recruitBoardWithCenter.recruitBoard(); RecruitmentInfo info = board.getRecruitmentInfo(); return RecruitBoardWithCenterResponseDto.builder() - .id(board.getId()) - .locationId(board.getLocationId()) - .createdAt(board.getCreatedAt()) - .updatedAt(board.getUpdatedAt()) - .title(board.getTitle()) - .content(board.getContent()) - .region(info.getRegion()) - .recruitStatus(board.getRecruitStatus()) - .recruitmentCount(info.getRecruitmentCount()) - .volunteerStartDateTime(info.getVolunteerStartDateTime()) - .volunteerEndDateTime(info.getVolunteerEndDateTime()) - .volunteerCategory(info.getVolunteerCategory()) - .volunteerTime(info.calculateVolunteerTime()) - .admitted(info.getAdmitted()) - .imgUrl(board.getImgUrl()) - .center(CenterSimpleInfoResponseDto.of(board.getCenterId(), recruitBoardWithCenter.centerName())) - .build(); + .id(board.getId()) + .locationId(board.getLocationId()) + .createdAt(board.getCreatedAt()) + .updatedAt(board.getUpdatedAt()) + .title(board.getTitle()) + .content(board.getContent()) + .region(info.getRegion()) + .recruitStatus(board.getRecruitStatus()) + .recruitmentCount(info.getRecruitmentCount()) + .volunteerStartDateTime(info.getVolunteerStartDateTime()) + .volunteerEndDateTime(info.getVolunteerEndDateTime()) + .volunteerCategory(info.getVolunteerCategory()) + .volunteerTime(info.calculateVolunteerTime()) + .admitted(info.getAdmitted()) + .imgUrl(board.getImgUrl()) + .center(CenterSimpleInfoResponseDto.of(board.getCenterId(), + recruitBoardWithCenter.centerName())) + .build(); } } diff --git a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithLocationResponseDto.java b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithLocationResponseDto.java index 1c3d2e436..61462bc71 100644 --- a/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithLocationResponseDto.java +++ b/src/main/java/com/somemore/recruitboard/dto/response/RecruitBoardWithLocationResponseDto.java @@ -18,66 +18,66 @@ @JsonNaming(SnakeCaseStrategy.class) @Schema(description = "봉사 모집글 위치 포함 응답 DTO") public record RecruitBoardWithLocationResponseDto( - @Schema(description = "봉사 모집글 ID", example = "123") - Long id, - @Schema(description = "기관 ID", example = "123e4567-e89b-12d3-a456-426614174000") - UUID centerId, - @Schema(description = "모집글 생성 일시", example = "2024-12-01T09:00:00") - LocalDateTime createdAt, - @Schema(description = "모집글 수정 일시", example = "2024-12-01T09:00:00") - LocalDateTime updatedAt, - @Schema(description = "모집글 제목", example = "환경 정화 봉사") - String title, - @Schema(description = "모집글 내용", example = "도시 공원에서 환경 정화 활동") - String content, - @Schema(description = "지역 정보", example = "서울특별시") - String region, - @Schema(description = "모집 상태", example = "RECRUITING") - RecruitStatus recruitStatus, - @Schema(description = "모집 인원 수", example = "15") - Integer recruitmentCount, - @Schema(description = "봉사 시작 일시", example = "2024-12-01T09:00:00") - LocalDateTime volunteerStartDateTime, - @Schema(description = "봉사 종료 일시", example = "2024-12-01T13:00:00") - LocalDateTime volunteerEndDateTime, - @Schema(description = "봉사 유형", example = "LIVING_SUPPORT") - VolunteerCategory volunteerCategory, - @Schema(description = "봉사 시간", example = "04:00:00") - LocalTime volunteerTime, - @Schema(description = "시간 인정 여부", example = "true") - Boolean admitted, - @Schema(description = "이미지 URL", example = "https://image.domain.com/links") - String imgUrl, - @Schema(description = "위치 정보 DTO") - LocationResponseDto location + @Schema(description = "봉사 모집글 ID", example = "123") + Long id, + @Schema(description = "기관 ID", example = "123e4567-e89b-12d3-a456-426614174000") + UUID centerId, + @Schema(description = "모집글 생성 일시", example = "2024-12-01T09:00:00", type = "string") + LocalDateTime createdAt, + @Schema(description = "모집글 수정 일시", example = "2024-12-01T09:00:00", type = "string") + LocalDateTime updatedAt, + @Schema(description = "모집글 제목", example = "환경 정화 봉사") + String title, + @Schema(description = "모집글 내용", example = "도시 공원에서 환경 정화 활동") + String content, + @Schema(description = "지역 정보", example = "서울특별시") + String region, + @Schema(description = "모집 상태", example = "RECRUITING") + RecruitStatus recruitStatus, + @Schema(description = "모집 인원 수", example = "15") + Integer recruitmentCount, + @Schema(description = "봉사 시작 일시", example = "2024-12-01T09:00:00", type = "string") + LocalDateTime volunteerStartDateTime, + @Schema(description = "봉사 종료 일시", example = "2024-12-01T13:00:00", type = "string") + LocalDateTime volunteerEndDateTime, + @Schema(description = "봉사 유형", example = "LIVING_SUPPORT") + VolunteerCategory volunteerCategory, + @Schema(description = "봉사 시간", example = "04:00:00") + LocalTime volunteerTime, + @Schema(description = "시간 인정 여부", example = "true") + Boolean admitted, + @Schema(description = "이미지 URL", example = "https://image.domain.com/links") + String imgUrl, + @Schema(description = "위치 정보 DTO") + LocationResponseDto location ) { public static RecruitBoardWithLocationResponseDto from( - RecruitBoardWithLocation recruitBoardWithLocation) { + RecruitBoardWithLocation recruitBoardWithLocation) { RecruitBoard board = recruitBoardWithLocation.recruitBoard(); RecruitmentInfo info = board.getRecruitmentInfo(); return RecruitBoardWithLocationResponseDto.builder() - .id(board.getId()) - .centerId(board.getCenterId()) - .createdAt(board.getCreatedAt()) - .updatedAt(board.getUpdatedAt()) - .title(board.getTitle()) - .content(board.getContent()) - .region(info.getRegion()) - .recruitStatus(board.getRecruitStatus()) - .recruitmentCount(info.getRecruitmentCount()) - .volunteerStartDateTime(info.getVolunteerStartDateTime()) - .volunteerEndDateTime(info.getVolunteerEndDateTime()) - .volunteerCategory(info.getVolunteerCategory()) - .volunteerTime(info.calculateVolunteerTime()) - .admitted(info.getAdmitted()) - .imgUrl(board.getImgUrl()) - .location( - LocationResponseDto.of(recruitBoardWithLocation.address(), - recruitBoardWithLocation.latitude(), - recruitBoardWithLocation.longitude())) - .build(); + .id(board.getId()) + .centerId(board.getCenterId()) + .createdAt(board.getCreatedAt()) + .updatedAt(board.getUpdatedAt()) + .title(board.getTitle()) + .content(board.getContent()) + .region(info.getRegion()) + .recruitStatus(board.getRecruitStatus()) + .recruitmentCount(info.getRecruitmentCount()) + .volunteerStartDateTime(info.getVolunteerStartDateTime()) + .volunteerEndDateTime(info.getVolunteerEndDateTime()) + .volunteerCategory(info.getVolunteerCategory()) + .volunteerTime(info.calculateVolunteerTime()) + .admitted(info.getAdmitted()) + .imgUrl(board.getImgUrl()) + .location( + LocationResponseDto.of(recruitBoardWithLocation.address(), + recruitBoardWithLocation.latitude(), + recruitBoardWithLocation.longitude())) + .build(); } } diff --git a/src/main/java/com/somemore/review/controller/ReviewCommandApiController.java b/src/main/java/com/somemore/review/controller/ReviewCommandApiController.java index f316b73d2..4735c1093 100644 --- a/src/main/java/com/somemore/review/controller/ReviewCommandApiController.java +++ b/src/main/java/com/somemore/review/controller/ReviewCommandApiController.java @@ -2,6 +2,7 @@ import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE; +import com.somemore.auth.annotation.CurrentUser; import com.somemore.global.common.response.ApiResponse; import com.somemore.imageupload.dto.ImageUploadRequestDto; import com.somemore.imageupload.usecase.ImageUploadUseCase; @@ -13,7 +14,6 @@ import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.security.access.annotation.Secured; -import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestPart; @@ -33,20 +33,16 @@ public class ReviewCommandApiController { @Operation(summary = "리뷰 등록", description = "리뷰를 등록합니다.") @PostMapping(value = "/review", consumes = MULTIPART_FORM_DATA_VALUE) public ApiResponse createReview( - @AuthenticationPrincipal String userId, + @CurrentUser UUID userId, @Valid @RequestPart("data") ReviewCreateRequestDto requestDto, @RequestPart(value = "img_file", required = false) MultipartFile image) { String imgUrl = imageUploadUseCase.uploadImage(new ImageUploadRequestDto(image)); return ApiResponse.ok( 201, - createReviewUseCase.createReview(requestDto, getId(userId), imgUrl), + createReviewUseCase.createReview(requestDto, userId, imgUrl), "리뷰 등록 성공" ); } - private static UUID getId(String id) { - return UUID.fromString(id); - } - } diff --git a/src/main/java/com/somemore/review/dto/response/ReviewResponseDto.java b/src/main/java/com/somemore/review/dto/response/ReviewResponseDto.java index 06d65a135..6af72e6dc 100644 --- a/src/main/java/com/somemore/review/dto/response/ReviewResponseDto.java +++ b/src/main/java/com/somemore/review/dto/response/ReviewResponseDto.java @@ -22,9 +22,9 @@ public record ReviewResponseDto( String content, @Schema(description = "이미지 링크", example = "https://image.domain.com/links") String imgUrl, - @Schema(description = "작성 일자", example = "2024-12-01T09:00:00") + @Schema(description = "작성 일자", example = "2024-12-01T09:00:00", type = "string") LocalDateTime createdAt, - @Schema(description = "수정 일자", example = "2024-12-01T09:00:00") + @Schema(description = "수정 일자", example = "2024-12-01T09:00:00", type = "string") LocalDateTime updateAt ) { diff --git a/src/main/java/com/somemore/review/dto/response/ReviewWithNicknameResponseDto.java b/src/main/java/com/somemore/review/dto/response/ReviewWithNicknameResponseDto.java index b7a274767..8607bb2d0 100644 --- a/src/main/java/com/somemore/review/dto/response/ReviewWithNicknameResponseDto.java +++ b/src/main/java/com/somemore/review/dto/response/ReviewWithNicknameResponseDto.java @@ -24,9 +24,9 @@ public record ReviewWithNicknameResponseDto( String content, @Schema(description = "이미지 링크", example = "https://image.domain.com/links") String imgUrl, - @Schema(description = "작성 일자", example = "2024-12-01T09:00:00") + @Schema(description = "작성 일자", example = "2024-12-01T09:00:00", type = "string") LocalDateTime createdAt, - @Schema(description = "수정 일자", example = "2024-12-01T09:00:00") + @Schema(description = "수정 일자", example = "2024-12-01T09:00:00", type = "string") LocalDateTime updateAt ) { diff --git a/src/main/java/com/somemore/volunteer/controller/VolunteerProfileCommandController.java b/src/main/java/com/somemore/volunteer/controller/VolunteerProfileCommandController.java index dfa9fae6b..b6ae1f497 100644 --- a/src/main/java/com/somemore/volunteer/controller/VolunteerProfileCommandController.java +++ b/src/main/java/com/somemore/volunteer/controller/VolunteerProfileCommandController.java @@ -1,5 +1,8 @@ package com.somemore.volunteer.controller; +import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE; + +import com.somemore.auth.annotation.CurrentUser; import com.somemore.global.common.response.ApiResponse; import com.somemore.imageupload.dto.ImageUploadRequestDto; import com.somemore.imageupload.usecase.ImageUploadUseCase; @@ -8,20 +11,16 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import java.util.UUID; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.annotation.Secured; -import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import java.util.UUID; - -import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE; - @RestController @Slf4j @RequiredArgsConstructor @@ -36,14 +35,14 @@ public class VolunteerProfileCommandController { @Operation(summary = "프로필 수정", description = "현재 로그인된 사용자의 프로필을 수정합니다.") @PutMapping(consumes = MULTIPART_FORM_DATA_VALUE) public ApiResponse updateProfile( - @AuthenticationPrincipal String volunteerId, + @CurrentUser UUID volunteerId, @Valid @RequestPart("data") VolunteerProfileUpdateRequestDto requestDto, @RequestPart(value = "img_file", required = false) MultipartFile image) { String imgUrl = imageUploadUseCase.uploadImage(new ImageUploadRequestDto(image)); updateVolunteerProfileUseCase.update( - UUID.fromString(volunteerId), + volunteerId, requestDto, imgUrl ); diff --git a/src/main/java/com/somemore/volunteer/controller/VolunteerProfileQueryController.java b/src/main/java/com/somemore/volunteer/controller/VolunteerProfileQueryController.java index a1ddeaf0e..54f1f7c60 100644 --- a/src/main/java/com/somemore/volunteer/controller/VolunteerProfileQueryController.java +++ b/src/main/java/com/somemore/volunteer/controller/VolunteerProfileQueryController.java @@ -1,21 +1,20 @@ package com.somemore.volunteer.controller; +import com.somemore.auth.annotation.CurrentUser; import com.somemore.global.common.response.ApiResponse; import com.somemore.volunteer.dto.response.VolunteerProfileResponseDto; import com.somemore.volunteer.usecase.VolunteerQueryUseCase; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.UUID; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.annotation.Secured; -import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.UUID; - @RestController @Slf4j @RequiredArgsConstructor @@ -29,11 +28,11 @@ public class VolunteerProfileQueryController { @Secured("ROLE_VOLUNTEER") @GetMapping("/me") public ApiResponse getMyProfile( - @AuthenticationPrincipal String volunteerId) { + @CurrentUser UUID volunteerId) { return ApiResponse.ok( 200, - volunteerQueryUseCase.getMyProfile(UUID.fromString(volunteerId)), + volunteerQueryUseCase.getMyProfile(volunteerId), "본인 상세 프로필 조회 성공"); } @@ -54,11 +53,11 @@ public ApiResponse getVolunteerProfile( @Operation(summary = "지원자 상세 프로필 조회", description = "기관이 작성한 모집 글에 지원한 봉사자의 상세 프로필을 조회합니다.") public ApiResponse getVolunteerDetailedProfile( @PathVariable UUID volunteerId, - @AuthenticationPrincipal String centerId) { + @CurrentUser UUID centerId) { return ApiResponse.ok( 200, - volunteerQueryUseCase.getVolunteerDetailedProfile(volunteerId, UUID.fromString(centerId)), + volunteerQueryUseCase.getVolunteerDetailedProfile(volunteerId, centerId), "지원자 상세 프로필 조회 성공" ); } diff --git a/src/test/java/com/somemore/CustomSecurityContextFactory.java b/src/test/java/com/somemore/CustomSecurityContextFactory.java index 15c9c3457..3884f81af 100644 --- a/src/test/java/com/somemore/CustomSecurityContextFactory.java +++ b/src/test/java/com/somemore/CustomSecurityContextFactory.java @@ -1,5 +1,7 @@ package com.somemore; +import java.util.Collections; +import java.util.UUID; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -7,15 +9,15 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.test.context.support.WithSecurityContextFactory; -import java.util.Collections; +public class CustomSecurityContextFactory implements + WithSecurityContextFactory { -public class CustomSecurityContextFactory implements WithSecurityContextFactory { @Override public SecurityContext createSecurityContext(WithMockCustomUser annotation) { SecurityContext context = SecurityContextHolder.createEmptyContext(); Authentication auth = new UsernamePasswordAuthenticationToken( - annotation.username(), + UUID.fromString(annotation.username()), "password", Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + annotation.role())) );