From 8bcfa932e8e09286f402c0d385b66bf1d25c6cc5 Mon Sep 17 00:00:00 2001 From: Romangduck <129341526+Romangduck@users.noreply.github.com> Date: Thu, 21 Sep 2023 18:12:10 +0900 Subject: [PATCH] =?UTF-8?q?[FEATURE]=20=EA=B4=80=EB=A6=AC=EC=9E=90?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=B4=88=EC=95=88=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20(#41)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * admin_list * admin_list , detail in Controller -ing * figuring Request * feat : temp commit * figuring JPA Entity Admin * figuring list.html with thymeleaf * figuring list controller & list service * feat : temp commit * figuring detail controller , service & html with thymeleaf * figuring Approve * modify for exception and error * finished approve , detail and list figuring * dev * feat : 테이블 명 수정에 따른 쿼리 변경 * feat : AdminBackEnd완료 * Add Modified admin's BackEnd file approvePicture 메서드에 isSessionUserAdmin 주석처리 --------- Co-authored-by: donsonioc2010 --- .../api/admin/controller/AdminController.java | 71 +++++++++++++++++++ .../AlreadyChangePictureException.java | 15 ++++ .../exception/NotAdminUserException.java | 13 ++++ .../api/admin/service/AdminService.java | 64 +++++++++++++++++ .../auction/controller/PictureController.java | 2 +- .../GlobalControllerExceptionHandler.java | 9 +-- .../resources/templates/admin/detail.html | 56 +++++++++++++++ .../main/resources/templates/admin/list.html | 39 ++++++++++ .../common/exception/GlobalException.java | 6 +- .../common/exception/NotFoundException.java | 11 +++ .../server/domain/domains/dto/PictureDTO.java | 8 ++- .../server/domain/domains/items/Picture.java | 2 +- .../domains/repository/PictureRepository.java | 2 + Domain/src/main/resources/data.sql | 14 ++-- 14 files changed, 300 insertions(+), 12 deletions(-) create mode 100644 Api/src/main/java/picasso/server/api/admin/controller/AdminController.java create mode 100644 Api/src/main/java/picasso/server/api/admin/exception/AlreadyChangePictureException.java create mode 100644 Api/src/main/java/picasso/server/api/admin/exception/NotAdminUserException.java create mode 100644 Api/src/main/java/picasso/server/api/admin/service/AdminService.java create mode 100644 Api/src/main/resources/templates/admin/detail.html create mode 100644 Api/src/main/resources/templates/admin/list.html create mode 100644 Common/src/main/java/picasso/server/common/exception/NotFoundException.java diff --git a/Api/src/main/java/picasso/server/api/admin/controller/AdminController.java b/Api/src/main/java/picasso/server/api/admin/controller/AdminController.java new file mode 100644 index 00000000..ae0a7a66 --- /dev/null +++ b/Api/src/main/java/picasso/server/api/admin/controller/AdminController.java @@ -0,0 +1,71 @@ +package picasso.server.api.admin.controller; + +import jakarta.servlet.http.HttpSession; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import picasso.server.api.admin.exception.NotAdminUserException; +import picasso.server.api.admin.service.AdminService; +import picasso.server.domain.domains.member.entity.User; +import picasso.server.domain.domains.member.type.UserRole; + +@Controller +@Slf4j +@RequiredArgsConstructor +@RequestMapping("/admin") +public class AdminController { + + private final AdminService adminService; + + @PostMapping("/approve/{pictureId}") + public String approvePicture(@PathVariable Long pictureId, HttpSession session) { +// isSessionUserAdmin(session); + adminService.approvePicture(pictureId); + return "redirect:/admin/list"; + } + + /** + * 관리자 페이지 미승인된 게시물 조회 Page + * + * @param model + * @param session + * @return + */ + @GetMapping("/list") + public String list(Model model, HttpSession session) { +// isSessionUserAdmin(session); + model.addAttribute("pictures", adminService.findAll()); + return "admin/list"; + } + + /** + * 세부 게시물 조회 페이지 + * + * @param pictureId + * @param model + * @param session + * @return + */ + @GetMapping("/detail/{pictureId}") + public String detail(@PathVariable Long pictureId, Model model, HttpSession session) { +// isSessionUserAdmin(session); + model.addAttribute( + "picture", + adminService.getBeforeApproveStatusPictureDetailById(pictureId) + ); + return "admin/detail"; + } + + private void isSessionUserAdmin(HttpSession session) { + User user = (User) session.getAttribute("loginUser"); + if (user == null || !user.getUserRole().equals(UserRole.ADMIN)) { + log.error("ADMIN Auth Not Enough"); + throw NotAdminUserException.EXCEPTION; + } + } +} diff --git a/Api/src/main/java/picasso/server/api/admin/exception/AlreadyChangePictureException.java b/Api/src/main/java/picasso/server/api/admin/exception/AlreadyChangePictureException.java new file mode 100644 index 00000000..d9a8f68d --- /dev/null +++ b/Api/src/main/java/picasso/server/api/admin/exception/AlreadyChangePictureException.java @@ -0,0 +1,15 @@ +package picasso.server.api.admin.exception; + +import picasso.server.common.exception.BaseException; + +import static picasso.server.common.exception.GlobalException.PICTURE_STATUS_AFTER_APPROVE; + +/** + * 이미 관리자가 승인한 게시물인 경우 발생되는 Exception + */ +public class AlreadyChangePictureException extends BaseException { + public static final BaseException EXCEPTION = new AlreadyChangePictureException(); + private AlreadyChangePictureException() { + super(PICTURE_STATUS_AFTER_APPROVE); + } +} diff --git a/Api/src/main/java/picasso/server/api/admin/exception/NotAdminUserException.java b/Api/src/main/java/picasso/server/api/admin/exception/NotAdminUserException.java new file mode 100644 index 00000000..cdf0564b --- /dev/null +++ b/Api/src/main/java/picasso/server/api/admin/exception/NotAdminUserException.java @@ -0,0 +1,13 @@ +package picasso.server.api.admin.exception; + +import picasso.server.common.exception.BaseException; + +import static picasso.server.common.exception.GlobalException.NOT_ADMIN; + +public class NotAdminUserException extends BaseException { + public static final BaseException EXCEPTION = new NotAdminUserException(); + + public NotAdminUserException() { + super(NOT_ADMIN); + } +} diff --git a/Api/src/main/java/picasso/server/api/admin/service/AdminService.java b/Api/src/main/java/picasso/server/api/admin/service/AdminService.java new file mode 100644 index 00000000..56a496d0 --- /dev/null +++ b/Api/src/main/java/picasso/server/api/admin/service/AdminService.java @@ -0,0 +1,64 @@ +package picasso.server.api.admin.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import picasso.server.api.admin.exception.AlreadyChangePictureException; +import picasso.server.common.exception.NotFoundException; +import picasso.server.domain.domains.items.Picture; +import picasso.server.domain.domains.repository.PictureRepository; + +import java.util.List; +import java.util.Optional; + +import static picasso.server.domain.domains.items.PictureStatus.AFTER_APPROVE; +import static picasso.server.domain.domains.items.PictureStatus.BEFORE_APPROVE; + +@Slf4j +@Service +@Transactional +@RequiredArgsConstructor +public class AdminService { + private final PictureRepository pictureRepository; + + // TODO : 추후 Pagenation으로의 수정 필요함. + @Transactional(readOnly = true) + public List findAll() { + return pictureRepository.findAll(); + } + + + public Picture getBeforeApproveStatusPictureDetailById(Long id) { + Optional picture = pictureRepository + .findByPictureIdAndPictureStatus(id, BEFORE_APPROVE); + if (picture.isPresent()) { + return picture.get(); + } + throw NotFoundException.EXCEPTION; + } + + + /** + * 관리자 승인전의 게시물을 관리자 승인 상태로 변경하는 기능 + * @param pictureId + */ + public void approvePicture(Long pictureId) { + Optional optionalPicture = pictureRepository.findById(pictureId); + if (optionalPicture.isPresent()) { + Picture picture = optionalPicture.get(); + if (picture.getPictureStatus().equals(BEFORE_APPROVE)) { + picture.setPictureStatus(AFTER_APPROVE); + pictureRepository.save(picture); + log.info("ApprovePicture Success >>> Picture Id : {}, Title : {}", + picture.getPictureId(), picture.getPictureName()); + return; + } + log.warn("ApprovePicture Failure >>> Picture Id : {}, Title : {}", + picture.getPictureId(), picture.getPictureName()); + throw AlreadyChangePictureException.EXCEPTION; + } + log.error("ApprovePicture Failure : Fail Reason Is {} Id is Empty", pictureId); + throw NotFoundException.EXCEPTION; + } +} diff --git a/Api/src/main/java/picasso/server/api/auction/controller/PictureController.java b/Api/src/main/java/picasso/server/api/auction/controller/PictureController.java index 6dc6940e..49726a29 100644 --- a/Api/src/main/java/picasso/server/api/auction/controller/PictureController.java +++ b/Api/src/main/java/picasso/server/api/auction/controller/PictureController.java @@ -35,7 +35,7 @@ public String createForm(Model model) { @PostMapping public String add(PictureDTO dto, MultipartFile imageFile, Model model) { Picture picture = new Picture(); - picture.setPicture_id(dto.getPicture_id()); + picture.setPictureId(dto.getPictureId()); picture.setPictureName(dto.getPictureName()); picture.setPainterName(dto.getPainterName()); picture.setSize(dto.getSize()); diff --git a/Api/src/main/java/picasso/server/api/config/advice/GlobalControllerExceptionHandler.java b/Api/src/main/java/picasso/server/api/config/advice/GlobalControllerExceptionHandler.java index c388d6ac..6e4377e1 100644 --- a/Api/src/main/java/picasso/server/api/config/advice/GlobalControllerExceptionHandler.java +++ b/Api/src/main/java/picasso/server/api/config/advice/GlobalControllerExceptionHandler.java @@ -5,8 +5,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; import picasso.server.common.dto.ErrorDetail; import picasso.server.common.exception.BaseException; import picasso.server.common.exception.GlobalException; @@ -14,15 +14,16 @@ //TODO : 현재 `GlobalRestControllerExceptionHandler`와 동일한 코드, 추후 수정 필요 @Slf4j @RequiredArgsConstructor -@RestControllerAdvice +@ControllerAdvice public class GlobalControllerExceptionHandler { @ExceptionHandler(BaseException.class) - protected ResponseEntity baseExceptionHandle(BaseException e, HttpServletRequest request) { + protected String baseExceptionHandle(BaseException e, HttpServletRequest request) { ErrorDetail errorDetail = e.getErrorCode().getErrorDetail(); log.warn("ExceptionName >>> {}, ErrorCode >>> {}, ExceptionReason >>> {}", e.getClass(), errorDetail.getStatusCode(), errorDetail.getReason()); - return ResponseEntity.status(errorDetail.getStatusCode()).body(errorDetail); + //return ResponseEntity.status(errorDetail.getStatusCode()).body(errorDetail); + return "redirect:/error"; } @ExceptionHandler(MethodArgumentNotValidException.class) diff --git a/Api/src/main/resources/templates/admin/detail.html b/Api/src/main/resources/templates/admin/detail.html new file mode 100644 index 00000000..83458d5d --- /dev/null +++ b/Api/src/main/resources/templates/admin/detail.html @@ -0,0 +1,56 @@ + + + + Picasso - Picture Detail + + +

Picture Detail

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID:
그림 URL:
그림 이름:
화가 이름:
그림 설명:
시작 가격:
최소 입찰 단위:
그림 사이즈:
생성일:
+
+ +
+
+ + + diff --git a/Api/src/main/resources/templates/admin/list.html b/Api/src/main/resources/templates/admin/list.html new file mode 100644 index 00000000..d784a077 --- /dev/null +++ b/Api/src/main/resources/templates/admin/list.html @@ -0,0 +1,39 @@ + + + + Picasso - Approve List + + +

Admin Approve List

+ + + + + + + + + + + + + + + + + + + + + +
ID그림명시작가생성일승인 상태승인 버튼
+ + + + +
+ +
+
+ + diff --git a/Common/src/main/java/picasso/server/common/exception/GlobalException.java b/Common/src/main/java/picasso/server/common/exception/GlobalException.java index 5527fe15..c3246122 100644 --- a/Common/src/main/java/picasso/server/common/exception/GlobalException.java +++ b/Common/src/main/java/picasso/server/common/exception/GlobalException.java @@ -2,11 +2,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; -import org.springframework.http.HttpStatus; import picasso.server.common.dto.ErrorDetail; import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; +import static org.springframework.http.HttpStatus.NOT_FOUND; +import static org.springframework.http.HttpStatus.UNAUTHORIZED; @Getter @AllArgsConstructor @@ -22,6 +23,9 @@ public enum GlobalException implements BaseErrorCode { MAIL_SEND_ERROR(INTERNAL_SERVER_ERROR.value(), "메일 발송중 오류가 발생하였습니다"), ALREADY_EXISTS_PAYMENT_HISTORY_ERROR(INTERNAL_SERVER_ERROR.value(), "이미 존재하는 결제 내역입니다"), PAYMENT_FAILED_ERROR(INTERNAL_SERVER_ERROR.value(), "결제 실패 오류입니다."), + NOT_ADMIN(UNAUTHORIZED.value(), "관리자만 사용가능한 페이지입니다."), + NOT_FOUND_ERROR(NOT_FOUND.value(), "검색 결과가 존재하지 않습니다"), + PICTURE_STATUS_AFTER_APPROVE(INTERNAL_SERVER_ERROR.value(), "이미 관리자가 승인한 게시물 입니다.") ; private final Integer statusCode; diff --git a/Common/src/main/java/picasso/server/common/exception/NotFoundException.java b/Common/src/main/java/picasso/server/common/exception/NotFoundException.java new file mode 100644 index 00000000..32c17aa6 --- /dev/null +++ b/Common/src/main/java/picasso/server/common/exception/NotFoundException.java @@ -0,0 +1,11 @@ +package picasso.server.common.exception; + +import static picasso.server.common.exception.GlobalException.NOT_FOUND_ERROR; + +public class NotFoundException extends BaseException{ + public static final BaseException EXCEPTION = new NotFoundException(); + + private NotFoundException() { + super(NOT_FOUND_ERROR); + } +} diff --git a/Domain/src/main/java/picasso/server/domain/domains/dto/PictureDTO.java b/Domain/src/main/java/picasso/server/domain/domains/dto/PictureDTO.java index 32c39267..ae2f2981 100644 --- a/Domain/src/main/java/picasso/server/domain/domains/dto/PictureDTO.java +++ b/Domain/src/main/java/picasso/server/domain/domains/dto/PictureDTO.java @@ -7,7 +7,7 @@ @Getter @Setter public class PictureDTO { - private Long picture_id; //그림 ID + private Long pictureId; //그림 ID private String pictureName; //그림 이름 private String painterName; //화가 이름 private String details; //그림 설명 @@ -17,3 +17,9 @@ public class PictureDTO { private LocalDate dateTime; private String imgUrl; //그림 url } + + + + + + diff --git a/Domain/src/main/java/picasso/server/domain/domains/items/Picture.java b/Domain/src/main/java/picasso/server/domain/domains/items/Picture.java index 5e82f559..3f628c56 100644 --- a/Domain/src/main/java/picasso/server/domain/domains/items/Picture.java +++ b/Domain/src/main/java/picasso/server/domain/domains/items/Picture.java @@ -24,7 +24,7 @@ public class Picture { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long picture_id; + private Long pictureId; @NotNull private String imgUrl; //그림 url diff --git a/Domain/src/main/java/picasso/server/domain/domains/repository/PictureRepository.java b/Domain/src/main/java/picasso/server/domain/domains/repository/PictureRepository.java index 9b006b78..4705110a 100644 --- a/Domain/src/main/java/picasso/server/domain/domains/repository/PictureRepository.java +++ b/Domain/src/main/java/picasso/server/domain/domains/repository/PictureRepository.java @@ -6,6 +6,7 @@ import picasso.server.domain.domains.items.PictureStatus; import java.util.List; +import java.util.Optional; @Repository public interface PictureRepository extends JpaRepository{ @@ -14,4 +15,5 @@ public interface PictureRepository extends JpaRepository{ List findAllByPictureStatusOrderByBidStartDateAsc(PictureStatus status); + Optional findByPictureIdAndPictureStatus(Long id, PictureStatus status); } diff --git a/Domain/src/main/resources/data.sql b/Domain/src/main/resources/data.sql index 8ddfbb12..8060d272 100644 --- a/Domain/src/main/resources/data.sql +++ b/Domain/src/main/resources/data.sql @@ -8,12 +8,18 @@ insert into t_test(name, param1,param2,param3,param4) values ('dddd', 'a','b','c','d'); insert into t_test(name, param1,param2,param3,param4) values ('ffff', 'a','b','c','d'); + -- 테스트용 데이터 -insert into picture(picture_id, increment_amount, starting_price, bid_start_date, bid_end_date, details, img_url, painter_name, picture_name, picture_status, size) +insert into tbl_picture(picture_id, increment_amount, starting_price, bid_start_date, bid_end_date, details, img_url, painter_name, picture_name, picture_status, size) values (1, 10, 1000, '2023-09-22', '2023-09-29', 'test1', 'local/paint/d5fdd501-8251-4082-9cc6-f1a65e5ad0a9.jpg', '안유진', '안유진', 'BIDDING' ,'800x600'); -insert into picture(picture_id, increment_amount, starting_price, bid_start_date, bid_end_date, details, img_url, painter_name, picture_name, picture_status, size) +insert into tbl_picture(picture_id, increment_amount, starting_price, bid_start_date, bid_end_date, details, img_url, painter_name, picture_name, picture_status, size) values (2, 20, 2000, '2023-09-21', '2023-09-28', 'test2', 'local/paint/6b075c7b-7149-4ecd-8b0a-ac71bb316e4d.jpeg', '은채', '은채', 'SUCCESS_BID','800x600'); -insert into picture(picture_id, increment_amount, starting_price, bid_start_date, bid_end_date, details, img_url, painter_name, picture_name, picture_status, size) +insert into tbl_picture(picture_id, increment_amount, starting_price, bid_start_date, bid_end_date, details, img_url, painter_name, picture_name, picture_status, size) values (3, 30, 3000, '2023-09-20', '2023-09-27', 'test3', 'local/paint/b6025492-6291-4ae2-916d-00981db26ed2.jpeg', '카리나', '카리나','BIDDING' ,'800x600'); -insert into picture(picture_id, increment_amount, starting_price, bid_start_date, bid_end_date, details, img_url, painter_name, picture_name, picture_status, size) +insert into tbl_picture(picture_id, increment_amount, starting_price, bid_start_date, bid_end_date, details, img_url, painter_name, picture_name, picture_status, size) values (4, 40, 4000, '2023-09-19', '2023-09-26', 'test4', 'local/paint/bf50117d-e28a-4393-8bc4-2fefa7220718.jpeg', '한소희', '한소희','SUCCESS_BID' ,'800x600'); +insert into tbl_picture(picture_id, increment_amount, starting_price, bid_start_date, bid_end_date, details, img_url, painter_name, picture_name, picture_status, size) +values (5, 50, 5000, '2023-09-28', '2023-10-03', 'test5', 'local/paint/bf50117d-e28a-4393-8bc4-2fefa7220718.jpeg', '한소희', '한소희','BEFORE_APPROVE' ,'800x600'); + + +