From e988355ff34a6b1f841db2d707f413b4c886539d Mon Sep 17 00:00:00 2001 From: jeonghyemin Date: Mon, 7 Jul 2025 15:40:10 +0900 Subject: [PATCH] =?UTF-8?q?feat(Store):=20=EA=B4=80=EB=A6=AC=EC=9E=90=20?= =?UTF-8?q?=EC=A0=91=EA=B7=BC=20=EC=A0=9C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - store RUD 시 접근 제한 로직 추가 - 비즈니스 로직 고려하여 user 생성 후 storeId 수동 추가 로직으로 변경 --- .../exception/GlobalExceptionHandler.java | 23 +++++++++++++ .../store/controller/StoreController.java | 15 +++++---- .../store/service/StoreService.java | 7 ++-- .../store/service/StoreServiceImpl.java | 32 +++++++++++++++---- .../user/dto/ManagerSignupRequestDto.java | 4 --- .../nowait/common/exception/ErrorMessage.java | 3 ++ .../StoreDeleteUnauthorizedException.java | 9 ++++++ .../StoreUpdateUnauthorizedException.java | 9 ++++++ .../StoreViewUnauthorizedException.java | 9 ++++++ .../domaincorerdb/user/entity/User.java | 1 - 10 files changed, 91 insertions(+), 21 deletions(-) create mode 100644 nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreDeleteUnauthorizedException.java create mode 100644 nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreUpdateUnauthorizedException.java create mode 100644 nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreViewUnauthorizedException.java diff --git a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/exception/GlobalExceptionHandler.java b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/exception/GlobalExceptionHandler.java index 3361fcd9..b2cbf47f 100644 --- a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/exception/GlobalExceptionHandler.java +++ b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/exception/GlobalExceptionHandler.java @@ -34,6 +34,9 @@ import com.nowait.domaincorerdb.reservation.exception.ReservationNotFoundException; import com.nowait.domaincorerdb.reservation.exception.ReservationUpdateUnauthorizedException; import com.nowait.domaincorerdb.reservation.exception.ReservationViewUnauthorizedException; +import com.nowait.domaincorerdb.store.exception.StoreDeleteUnauthorizedException; +import com.nowait.domaincorerdb.store.exception.StoreUpdateUnauthorizedException; +import com.nowait.domaincorerdb.store.exception.StoreViewUnauthorizedException; import com.nowait.domaincorerdb.token.exception.BusinessException; import com.nowait.domaincorerdb.user.exception.UserNotFoundException; @@ -200,6 +203,26 @@ public ErrorResponse menuDeleteUnauthorizedException(MenuDeleteUnauthorizedExcep return new ErrorResponse(e.getMessage(), MENU_DELETE_UNAUTHORIZED.getCode()); } + @ResponseStatus(value = FORBIDDEN) + @ExceptionHandler(StoreViewUnauthorizedException.class) + public ErrorResponse storeViewUnauthorizedException(StoreViewUnauthorizedException e) { + log.error("storeViewUnauthorizedException", e); + return new ErrorResponse(e.getMessage(), STORE_VIEW_UNAUTHORIZED.getCode()); + } + + @ResponseStatus(value = FORBIDDEN) + @ExceptionHandler(StoreUpdateUnauthorizedException.class) + public ErrorResponse storeUpdateUnauthorizedException(StoreUpdateUnauthorizedException e) { + log.error("storeUpdateUnauthorizedException", e); + return new ErrorResponse(e.getMessage(), STORE_UPDATE_UNAUTHORIZED.getCode()); + } + + @ResponseStatus(value = FORBIDDEN) + @ExceptionHandler(StoreDeleteUnauthorizedException.class) + public ErrorResponse storeDeleteUnauthorizedException(StoreDeleteUnauthorizedException e) { + log.error("storeDeleteUnauthorizedException", e); + return new ErrorResponse(e.getMessage(), STORE_DELETE_UNAUTHORIZED.getCode()); + } private static Map getErrors(MethodArgumentNotValidException e) { return e.getBindingResult() diff --git a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/store/controller/StoreController.java b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/store/controller/StoreController.java index 07a5e63f..2d3a6aae 100644 --- a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/store/controller/StoreController.java +++ b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/store/controller/StoreController.java @@ -2,6 +2,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; @@ -16,6 +17,7 @@ import com.nowait.applicationadmin.store.dto.StoreUpdateRequest; import com.nowait.applicationadmin.store.service.StoreService; import com.nowait.common.api.ApiUtils; +import com.nowait.domaincorerdb.user.entity.MemberDetails; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -52,12 +54,12 @@ public ResponseEntity createStore(@Valid @RequestBody StoreCreateRequest requ @GetMapping("/{storeId}") @Operation(summary = "주점 조회", description = "주점 ID로 주점을 조회합니다.") @ApiResponse(responseCode = "200", description = "주점 조회 성공") - public ResponseEntity getStoreById(@PathVariable Long storeId) { + public ResponseEntity getStoreById(@PathVariable Long storeId,@AuthenticationPrincipal MemberDetails memberDetails) { return ResponseEntity .status(HttpStatus.OK) .body( ApiUtils.success( - storeService.getStoreByStoreId(storeId) + storeService.getStoreByStoreId(storeId,memberDetails) ) ); } @@ -67,13 +69,14 @@ public ResponseEntity getStoreById(@PathVariable Long storeId) { @ApiResponse(responseCode = "200", description = "주점 정보 수정 성공") public ResponseEntity updateStore( @PathVariable Long storeId, - @Valid @RequestBody StoreUpdateRequest request + @Valid @RequestBody StoreUpdateRequest request, + @AuthenticationPrincipal MemberDetails memberDetails ) { return ResponseEntity .status(HttpStatus.OK) .body( ApiUtils.success( - storeService.updateStore(storeId, request) + storeService.updateStore(storeId, request, memberDetails) ) ); } @@ -81,12 +84,12 @@ public ResponseEntity updateStore( @DeleteMapping("/{storeId}") @Operation(summary = "주점 삭제", description = "주점 ID로 주점을 삭제합니다.") @ApiResponse(responseCode = "200", description = "주점 삭제 성공") - public ResponseEntity deleteStore(@PathVariable Long storeId) { + public ResponseEntity deleteStore(@PathVariable Long storeId,@AuthenticationPrincipal MemberDetails memberDetails) { return ResponseEntity .ok() .body( ApiUtils.success( - storeService.deleteStore(storeId) + storeService.deleteStore(storeId,memberDetails) ) ); } diff --git a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/store/service/StoreService.java b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/store/service/StoreService.java index 02c39915..5ae0dcdf 100644 --- a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/store/service/StoreService.java +++ b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/store/service/StoreService.java @@ -4,16 +4,17 @@ import com.nowait.applicationadmin.store.dto.StoreCreateResponse; import com.nowait.applicationadmin.store.dto.StoreReadDto; import com.nowait.applicationadmin.store.dto.StoreUpdateRequest; +import com.nowait.domaincorerdb.user.entity.MemberDetails; public interface StoreService { StoreCreateResponse createStore(StoreCreateRequest request); - StoreReadDto getStoreByStoreId(Long storeId); + StoreReadDto getStoreByStoreId(Long storeId, MemberDetails memberDetails); - StoreReadDto updateStore(Long storeId, StoreUpdateRequest request); + StoreReadDto updateStore(Long storeId, StoreUpdateRequest request, MemberDetails memberDetails); - String deleteStore(Long storeId); + String deleteStore(Long storeId, MemberDetails memberDetails); Boolean toggleActive(Long storeId); } diff --git a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/store/service/StoreServiceImpl.java b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/store/service/StoreServiceImpl.java index ce4f65da..0dec4fd8 100644 --- a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/store/service/StoreServiceImpl.java +++ b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/store/service/StoreServiceImpl.java @@ -10,15 +10,22 @@ import com.nowait.applicationadmin.store.dto.StoreImageUploadResponse; import com.nowait.applicationadmin.store.dto.StoreReadDto; import com.nowait.applicationadmin.store.dto.StoreUpdateRequest; +import com.nowait.common.enums.Role; +import com.nowait.domaincorerdb.reservation.exception.ReservationUpdateUnauthorizedException; import com.nowait.domaincorerdb.store.entity.Store; import com.nowait.domaincorerdb.store.entity.StoreImage; +import com.nowait.domaincorerdb.store.exception.StoreDeleteUnauthorizedException; import com.nowait.domaincorerdb.store.exception.StoreNotFoundException; import com.nowait.domaincorerdb.store.exception.StoreParamEmptyException; +import com.nowait.domaincorerdb.store.exception.StoreUpdateUnauthorizedException; +import com.nowait.domaincorerdb.store.exception.StoreViewUnauthorizedException; import com.nowait.domaincorerdb.store.repository.StoreImageRepository; import com.nowait.domaincorerdb.store.repository.StoreRepository; +import com.nowait.domaincorerdb.user.entity.MemberDetails; +import com.nowait.domaincorerdb.user.entity.User; +import com.nowait.domaincorerdb.user.exception.UserNotFoundException; +import com.nowait.domaincorerdb.user.repository.UserRepository; - -import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; @Service @@ -27,6 +34,7 @@ public class StoreServiceImpl implements StoreService { private final StoreRepository storeRepository; private final StoreImageRepository storeImageRepository; + private final UserRepository userRepository; @Override @Transactional @@ -42,9 +50,12 @@ public StoreCreateResponse createStore(StoreCreateRequest request) { @Override @Transactional(readOnly = true) - public StoreReadDto getStoreByStoreId(Long storeId) { + public StoreReadDto getStoreByStoreId(Long storeId, MemberDetails memberDetails) { if (storeId == null) throw new StoreParamEmptyException(); - + User user = userRepository.findById(memberDetails.getId()).orElseThrow(UserNotFoundException::new); + if (!Role.SUPER_ADMIN.equals(user.getRole()) && !user.getStoreId().equals(storeId)) { + throw new StoreViewUnauthorizedException(); + } Store store = storeRepository.findByStoreIdAndDeletedFalse(storeId) .orElseThrow(StoreNotFoundException::new); @@ -58,9 +69,12 @@ public StoreReadDto getStoreByStoreId(Long storeId) { @Override @Transactional - public StoreReadDto updateStore(Long storeId, StoreUpdateRequest request) { + public StoreReadDto updateStore(Long storeId, StoreUpdateRequest request, MemberDetails memberDetails) { + User user = userRepository.findById(memberDetails.getId()).orElseThrow(UserNotFoundException::new); if (storeId == null || request == null) throw new StoreParamEmptyException(); - + if (!Role.SUPER_ADMIN.equals(user.getRole()) && !user.getStoreId().equals(storeId)) { + throw new StoreUpdateUnauthorizedException(); + } Store store = storeRepository.findByStoreIdAndDeletedFalse(storeId) .orElseThrow(StoreNotFoundException::new); @@ -82,10 +96,14 @@ public StoreReadDto updateStore(Long storeId, StoreUpdateRequest request) { @Override @Transactional - public String deleteStore(Long storeId) { + public String deleteStore(Long storeId, MemberDetails memberDetails) { + User user = userRepository.findById(memberDetails.getId()).orElseThrow(UserNotFoundException::new); if (storeId == null) { throw new StoreParamEmptyException(); } + if (!Role.SUPER_ADMIN.equals(user.getRole()) && !user.getStoreId().equals(storeId)) { + throw new StoreDeleteUnauthorizedException(); + } Store store = storeRepository.findByStoreIdAndDeletedFalse(storeId) .orElseThrow(StoreNotFoundException::new); diff --git a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/user/dto/ManagerSignupRequestDto.java b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/user/dto/ManagerSignupRequestDto.java index 1e8368fe..8b327e01 100644 --- a/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/user/dto/ManagerSignupRequestDto.java +++ b/nowait-app-admin-api/src/main/java/com/nowait/applicationadmin/user/dto/ManagerSignupRequestDto.java @@ -35,9 +35,6 @@ public class ManagerSignupRequestDto { @Schema(description = "로그인타입", example = "LOCAL") private String socialType; - @NotNull - @Schema(description = "관리자가 속한 storeId", example = "1") - private Long storeId; public User toEntity() { return User.builder() @@ -46,7 +43,6 @@ public User toEntity() { .nickname(nickname) .socialType(SocialType.LOCAL) .role(Role.MANAGER) - .storeId(storeId) .build(); } diff --git a/nowait-common/src/main/java/com/nowait/common/exception/ErrorMessage.java b/nowait-common/src/main/java/com/nowait/common/exception/ErrorMessage.java index 422010e8..5a651f45 100644 --- a/nowait-common/src/main/java/com/nowait/common/exception/ErrorMessage.java +++ b/nowait-common/src/main/java/com/nowait/common/exception/ErrorMessage.java @@ -43,6 +43,9 @@ public enum ErrorMessage { // store STORE_PARAMETER_EMPTY("주점 생성 시 파라미터 정보가 없습니다.", "store001"), STORE_NOT_FOUND("해당 주점을 찾을 수 없습니다.", "store002"), + STORE_VIEW_UNAUTHORIZED("주점 보기 권한이 없습니다.(슈퍼계정 or 주점 관리자만 가능)", "store003"), + STORE_UPDATE_UNAUTHORIZED("주점 수정 권한이 없습니다.(슈퍼계정 or 주점 관리자만 가능)", "store004"), + STORE_DELETE_UNAUTHORIZED("주점 삭제 권한이 없습니다.(슈퍼계정 or 주점 관리자만 가능)", "store005"), // image IMAGE_FILE_EMPTY("이미지 파일을 업로드 해주세요", "image001"), diff --git a/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreDeleteUnauthorizedException.java b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreDeleteUnauthorizedException.java new file mode 100644 index 00000000..9b92d807 --- /dev/null +++ b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreDeleteUnauthorizedException.java @@ -0,0 +1,9 @@ +package com.nowait.domaincorerdb.store.exception; + +import com.nowait.common.exception.ErrorMessage; + +public class StoreDeleteUnauthorizedException extends RuntimeException { + public StoreDeleteUnauthorizedException() { + super(ErrorMessage.STORE_DELETE_UNAUTHORIZED.getMessage()); + } +} diff --git a/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreUpdateUnauthorizedException.java b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreUpdateUnauthorizedException.java new file mode 100644 index 00000000..a77d8379 --- /dev/null +++ b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreUpdateUnauthorizedException.java @@ -0,0 +1,9 @@ +package com.nowait.domaincorerdb.store.exception; + +import com.nowait.common.exception.ErrorMessage; + +public class StoreUpdateUnauthorizedException extends RuntimeException { + public StoreUpdateUnauthorizedException() { + super(ErrorMessage.STORE_UPDATE_UNAUTHORIZED.getMessage()); + } +} diff --git a/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreViewUnauthorizedException.java b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreViewUnauthorizedException.java new file mode 100644 index 00000000..ee996974 --- /dev/null +++ b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/store/exception/StoreViewUnauthorizedException.java @@ -0,0 +1,9 @@ +package com.nowait.domaincorerdb.store.exception; + +import com.nowait.common.exception.ErrorMessage; + +public class StoreViewUnauthorizedException extends RuntimeException { + public StoreViewUnauthorizedException() { + super(ErrorMessage.STORE_VIEW_UNAUTHORIZED.getMessage()); + } +} diff --git a/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/user/entity/User.java b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/user/entity/User.java index c1502486..86d45d9b 100644 --- a/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/user/entity/User.java +++ b/nowait-domain/domain-core-rdb/src/main/java/com/nowait/domaincorerdb/user/entity/User.java @@ -44,7 +44,6 @@ public class User { @Enumerated(EnumType.STRING) private Role role; - @Column(nullable = false) private Long storeId; @Builder