From 6efbe86e3a7fb4f3e7c0cf8b242f9a7e396d76a7 Mon Sep 17 00:00:00 2001 From: 3un0ia Date: Fri, 22 Mar 2024 00:35:33 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=ED=99=95=EC=9D=B8=20?= =?UTF-8?q?=EB=B0=8F=20=EB=A1=9C=EC=A7=81=20=EC=A0=95=EB=B9=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../JWT/post/controller/PostController.java | 70 ++++----- .../java/JWTLogIn/JWT/post/dto/PostDto.java | 18 +-- .../JWTLogIn/JWT/post/entity/BaseEntity.java | 26 ++++ .../JWTLogIn/JWT/post/entity/PostEntity.java | 2 +- .../JWT/post/repository/PostRepository.java | 8 ++ .../JWT/post/service/PostService.java | 133 +++++++++++++----- 6 files changed, 176 insertions(+), 81 deletions(-) create mode 100644 JWT/src/main/java/JWTLogIn/JWT/post/entity/BaseEntity.java diff --git a/JWT/src/main/java/JWTLogIn/JWT/post/controller/PostController.java b/JWT/src/main/java/JWTLogIn/JWT/post/controller/PostController.java index 4a94949..f9b1484 100644 --- a/JWT/src/main/java/JWTLogIn/JWT/post/controller/PostController.java +++ b/JWT/src/main/java/JWTLogIn/JWT/post/controller/PostController.java @@ -43,23 +43,23 @@ public class PostController { @GetMapping("/info/notice") // 공지글 가져오기 - GET, /tgwing.kr/info/notice public ResponseEntity> getAllPosts() { - System.out.println("-- Retrieve All of Posts --"); + System.out.println("-- Retrieve All of Posts (to Front...) --"); - // postEntity.type = NOT, GAL --> NOT이면 공지, GAL이면 갤러리 - // DB에서 가져온 모든 POST 중에서 type = NOT인 게시글을 모두 가져옴 - List result = new ArrayList<>(); - - List allPosts = postRepository.findAll(); - for (PostEntity post : allPosts) { - if (post.getType() == Type.NOT) { - result.add(toDto(post)); - } - } + List result = postService.getAllPosts(); return new ResponseEntity<>(result, HttpStatus.OK); } @GetMapping("/info/notice/{postId}") // 특정 공지글 가져오기 - GET, /tgwing.kr/info/notice/{id} + public ResponseEntity getPostInfo(@PathVariable("postId") Long postId) { + System.out.println("-- Retreive Specific Post by Id --"); + // 특정 게시글 id에 대한 post 정보를 모아 반환 (id, title, description, writtenDate, ?조회수? + + PostEntity post = postService.getPostInfo(postId); + return ResponseEntity.ok(post); + } + + @GetMapping("/notice/{postId}") // 특정 보기 - GET, /tgwing.kr/notice/{id} public ResponseEntity getPost(@PathVariable("postId") Long postId) { System.out.println("-- Retreive Specific Post by Id --"); // 특정 게시글 id에 대한 post 정보를 모아 반환 (id, title, description, writtenDate, ?조회수? @@ -79,26 +79,26 @@ public ResponseEntity> searchPost(@RequestParam String text) return ResponseEntity.ok(postDtos); } -// @PostMapping("/notice/post/{userId}") // 공지 작성 - POST, /tgwing.kr/notice/post -// public ResponseEntity post(@RequestBody PostDto requestDto, -// @PathVariable("userId") Long userId) -// { -// System.out.println("-- Post new post --"); -// System.out.println("Request Dto = " + requestDto); -// // RequestDTO : title, content, thumbnail(선택) -// // userId : 해당 URL을 요청한 유저의 Id -// -// // dto 가져온 값을 엔티티로 바꾸고 DB에 save -// // 다시 꺼내와서 완성된 객체의 구성요소(id, title, description, writtenDate ...) -// -// // 유저의 level 확인 필요 - level = MANAGER인 경우에만 작성가능 -// // 로그인 되어있지 않은 경우 NORMAL, 로그인 된 경우 MEMBER, 관리자인 경우 MANAGER -// -// PostDto responseDto = postService.createPost(requestDto, userId); -// return ResponseEntity.ok(responseDto); -// } + @PostMapping("/notice/post/{userId}") // 공지 작성 - POST, /tgwing.kr/notice/post + public ResponseEntity post(@RequestBody PostDto requestDto, + @PathVariable("userId") Long userId) + { + System.out.println("-- Post new post --"); + System.out.println("Request Dto = " + requestDto); + // RequestDTO : title, content, thumbnail(선택) + // userId : 해당 URL을 요청한 유저의 Id + + // dto 가져온 값을 엔티티로 바꾸고 DB에 save + // 다시 꺼내와서 완성된 객체의 구성요소(id, title, description, writtenDate ...) + + // 유저의 level 확인 필요 - level = MANAGER인 경우에만 작성가능 + // 로그인 되어있지 않은 경우 NORMAL, 로그인 된 경우 MEMBER, 관리자인 경우 MANAGER + + PostDto responseDto = postService.createPost(requestDto, userId); + return ResponseEntity.ok(responseDto); + } // @CrossOrigin - @PatchMapping ("/notice/put/{id}") // 공지 수정 - PUT, /tgwing.kr/notice/put/{id} + @PatchMapping ("/notice/modify/{id}") // 공지 수정 - PUT, /tgwing.kr/notice/modify/{id} public ResponseEntity modify(@RequestBody PostDto requestDto, @RequestParam Long userId, @PathVariable("id") Long id) @@ -115,20 +115,20 @@ public ResponseEntity modify(@RequestBody PostDto requestDto, } @DeleteMapping("/notice/delete/{id}") // 공지 삭제 - DELETE, /tgwing.kr/notice/delete/{id} - public ResponseEntity delete(@PathVariable("id") Long id, + public ResponseEntity delete(@PathVariable("id") Long postId, @RequestParam Long userId) { System.out.println("-- Delete Specific Post --"); // 아이디에 해당하는 글 객체를 그냥 삭제 -> 응답 - postService.deletePost(userId, id); + postService.deletePost(userId, postId); return ResponseEntity.noContent().build(); } - @GetMapping("/notice") + @GetMapping("/notice") // 공지 게시판 보기 - GET, /tgwing.kr/notice?page={pp}&length={ll} @Transactional public ResponseEntity getPostsInPage(@RequestParam int page, - @RequestParam(required = false) int size, - @PageableDefault(size = 15) Pageable pageable) { + @RequestParam(defaultValue = "15") int size, + @PageableDefault Pageable pageable) { System.out.println("-- Get Posts in Page --"); // 첫 번째 페이지 page = 0이므로, page-1로 전달 -> 1부터 요청할 수 있도록 Page postsInPage = postService.findPostsInPage(page-1, size, pageable); diff --git a/JWT/src/main/java/JWTLogIn/JWT/post/dto/PostDto.java b/JWT/src/main/java/JWTLogIn/JWT/post/dto/PostDto.java index cd63733..5af26e7 100644 --- a/JWT/src/main/java/JWTLogIn/JWT/post/dto/PostDto.java +++ b/JWT/src/main/java/JWTLogIn/JWT/post/dto/PostDto.java @@ -1,6 +1,7 @@ package JWTLogIn.JWT.post.dto; import JWTLogIn.JWT.post.entity.PostEntity; +import JWTLogIn.JWT.post.entity.Type; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -19,14 +20,15 @@ public static PostEntity toEntity(PostDto postDto) { .writer(postDto.writer) .title(postDto.title) .content(postDto.content) - .thumbnail(postDto.thumbnail).build(); + .thumbnail(postDto.thumbnail) + .type(Type.NOT).build(); } - public static PostEntity toEntityWithId (PostDto postDto, Long writerId) { - return PostEntity.builder() - .writer(writerId) - .title(postDto.title) - .content(postDto.content) - .thumbnail(postDto.thumbnail).build(); - } +// public static PostEntity toEntityWithId (PostDto postDto, Long writerId) { +// return PostEntity.builder() +// .writer(writerId) +// .title(postDto.title) +// .content(postDto.content) +// .thumbnail(postDto.thumbnail).build(); +// } } diff --git a/JWT/src/main/java/JWTLogIn/JWT/post/entity/BaseEntity.java b/JWT/src/main/java/JWTLogIn/JWT/post/entity/BaseEntity.java new file mode 100644 index 0000000..96512d7 --- /dev/null +++ b/JWT/src/main/java/JWTLogIn/JWT/post/entity/BaseEntity.java @@ -0,0 +1,26 @@ +package JWTLogIn.JWT.post.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.time.LocalDateTime; + +@MappedSuperclass +@EntityListeners(value = { AuditingEntityListener.class }) +@Getter +abstract class BaseEntity { + + @CreatedDate + @Column(name = "regdate", updatable = false) + private LocalDateTime regDate; + + @LastModifiedDate + @Column(name ="moddate" ) + private LocalDateTime modDate; + +} \ No newline at end of file diff --git a/JWT/src/main/java/JWTLogIn/JWT/post/entity/PostEntity.java b/JWT/src/main/java/JWTLogIn/JWT/post/entity/PostEntity.java index 238a600..48f376f 100644 --- a/JWT/src/main/java/JWTLogIn/JWT/post/entity/PostEntity.java +++ b/JWT/src/main/java/JWTLogIn/JWT/post/entity/PostEntity.java @@ -13,7 +13,7 @@ @NoArgsConstructor @AllArgsConstructor @Table(name="post") -public class PostEntity { +public class PostEntity extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; diff --git a/JWT/src/main/java/JWTLogIn/JWT/post/repository/PostRepository.java b/JWT/src/main/java/JWTLogIn/JWT/post/repository/PostRepository.java index 11f8f15..f004241 100644 --- a/JWT/src/main/java/JWTLogIn/JWT/post/repository/PostRepository.java +++ b/JWT/src/main/java/JWTLogIn/JWT/post/repository/PostRepository.java @@ -2,9 +2,11 @@ import JWTLogIn.JWT.post.dto.PostDto; import JWTLogIn.JWT.post.entity.PostEntity; +import JWTLogIn.JWT.post.entity.Type; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; @@ -18,4 +20,10 @@ public interface PostRepository extends JpaRepository { // List findByTitleContains(String search); List findByContentContains(String search); Page findAllByOrderByIdDesc(Pageable pageable); + + @Query(value = "select * from post p where p.type = 0", nativeQuery = true) + List findAllNotice(); + + @Query(value = "select count(*) from post p where p.type = 0", nativeQuery = true) + int getCount(); } diff --git a/JWT/src/main/java/JWTLogIn/JWT/post/service/PostService.java b/JWT/src/main/java/JWTLogIn/JWT/post/service/PostService.java index cfe253f..596f56f 100644 --- a/JWT/src/main/java/JWTLogIn/JWT/post/service/PostService.java +++ b/JWT/src/main/java/JWTLogIn/JWT/post/service/PostService.java @@ -14,15 +14,17 @@ import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; -import static JWTLogIn.JWT.post.dto.PostDto.toEntityWithId; +import static JWTLogIn.JWT.post.dto.PostDto.toEntity; import static JWTLogIn.JWT.post.entity.PostEntity.toDto; @Service @@ -35,6 +37,35 @@ public class PostService { @Autowired private final UserRepository userRepository; + public List getAllPosts() { + +// List dtos = new ArrayList<>(); + +// List entities = postRepository.findAll(); + List allPosts = postRepository.findAllNotice(); + // DB에서 가져온 모든 POST 중에서 type = NOT인 게시글을 모두 가져옴 + + + if (allPosts.isEmpty()) {throw new ResponseStatusException(HttpStatus.NOT_FOUND);} + + List dtos = allPosts.stream().map(postEntity -> toDto(postEntity)).collect(Collectors.toList()); + + for (PostDto dto : dtos) { + System.out.println("dto = " + dto); + } + + return dtos; + } + + public PostEntity getPostInfo(Long id) // 특정 게시글 가져오기 + { + // 입력된 id에 해당하는 글 찾기 + Optional postEntityInOp = postRepository.findById(id); + PostEntity postEntity = postEntityInOp.orElseThrow(); + // 관리자 여부 확인 + if (postEntity.getType() == Type.NOT) { return postEntity; } + else return null; + } public PostDto getPost(Long id) // 특정 게시글 가져오기 { // 입력된 id에 해당하는 글 찾기 @@ -77,50 +108,53 @@ public List searchPosts(String search) List SearchedEntity = postRepository.findByContentContains(search); for (PostEntity postEntity : SearchedEntity) { - System.out.println("postEntity = " + postEntity); +// System.out.println("postEntity = " + postEntity); postDtos.add(toDto(postEntity)); } return postDtos; } -// public PostDto createPost(PostDto requestDto, Long userId) // 게시글 생성하기 -// { -// // 글을 작성한 user 조회 -// Optional userById = userRepository.findById(userId); -// -//// else { // user 조회되면, user name을 author로 설정 -//// UserEntity userEntity = byId.get(); -//// dto.setAuthor(userEntity.getName()); -//// } -// if(userById.isPresent()) { -// UserEntity userEntity = userById.orElseThrow(); -// if (userEntity.getLevel() == Level.MANAGER) { -// -// PostEntity postEntity = toEntityWithId(requestDto, userId); // DTO 기반으로 엔티티 생성 - writer는 요청된 user의 ID -// System.out.println("postEntity = " + postEntity); // 생성된 엔티티 확인 -// -// PostEntity savedEntity = postRepository.save(postEntity); -// PostDto responseDto = toDto(savedEntity); -// return responseDto; -// -// } else { -// // 공지 생성 불가능 (level이 NORMAL, MEMBER인 경우) -// return null; -// } -// } -// else { -// // 공지 생성 불가능 (등록되지 않은 회원인 경우) -// return null; + public PostDto createPost(PostDto requestDto, Long userId) // 게시글 생성하기 + { + // 글을 작성할 user 조회 + Optional userById = userRepository.findById(userId); + +// else { // user 조회되면, user name을 author로 설정 +// UserEntity userEntity = byId.get(); +// dto.setAuthor(userEntity.getName()); // } -// } - public PostDto updatePost(PostDto postDto, Long userId, Long id) // 게시글 수정하기 + if(userById.isPresent()) { + UserEntity userEntity = userById.orElseThrow(); +// if (userEntity.getLevel() == Level.MANAGER) { + + if(true) { + PostEntity postEntity = toEntity(requestDto); // DTO 기반으로 엔티티 생성 - writer는 요청된 user의 ID + System.out.println("postEntity = " + postEntity); // 생성된 엔티티 확인 + + PostEntity savedEntity = postRepository.save(postEntity); + PostDto responseDto = toDto(savedEntity); + return responseDto; + + } else { + // 공지 생성 불가능 (level이 NORMAL, MEMBER인 경우) + throw new ResponseStatusException(HttpStatus.FORBIDDEN); + } + } + else { + // 공지 생성 불가능 (등록되지 않은 회원인 경우) + throw new ResponseStatusException(HttpStatus.UNAUTHORIZED); + } + } + public PostDto updatePost(PostDto postDto, Long userId, Long postId) // 게시글 수정하기 { - Optional postById = postRepository.findById(id); + Optional postById = postRepository.findById(postId); PostEntity postEntity = postById.orElseThrow(); // 해당 URL을 요청한 사람이 공지 작성자인 경우에만 수정 가능 - if(postEntity.getWriter() == userId) { + // 수정 목록 : title, content, thumbnail + if(postEntity.getWriter() == userId && postEntity.getWriter() == postDto.getWriter()) { + System.out.println("유저 정보가 일치"); postEntity.updateContent(postDto); PostEntity savedEntity = postRepository.save(postEntity); @@ -129,7 +163,8 @@ public PostDto updatePost(PostDto postDto, Long userId, Long id) // 게시글 return responseDto; } else { // 공지 작성자가 아닌 경우 -- 수정 불가능 - return null; + System.out.println("유저 정보 불일치 - 작성자가 아니므로 수정 불가능"); + throw new ResponseStatusException(HttpStatus.FORBIDDEN); } } public void deletePost(Long userId, Long postId) // 게시글 삭제하기 @@ -140,17 +175,41 @@ public void deletePost(Long userId, Long postId) // 게시글 삭제하기 // 해당 URL을 요청한 사람이 공지 작성자인 경우에만 삭제 가능 if(postEntity.getWriter() == userId) { postRepository.deleteById(postId); - } + } else { + System.out.println("삭제 불가 - 작성자가 아님"); + throw new ResponseStatusException(HttpStatus.UNAUTHORIZED); } } public Page findPostsInPage(int page, int size, Pageable pageable) { // Post DB에서 Page 단위로 가져오기 PageRequest pageRequest = PageRequest.of(page, size); Page postPage = postRepository.findAllByOrderByIdDesc(pageRequest); + int total = postRepository.getCount(); + if(!(total > page * size)) {throw new ResponseStatusException(HttpStatus.BAD_REQUEST); } + // 이후 ExceptionHandler 정의 필요 + + if (postPage.isEmpty()) { + System.out.println("조회 불가능"); + } + + // stream이 비어있는 경우 + postPage.stream().findFirst().orElseThrow(()-> new ResponseStatusException(HttpStatus.NO_CONTENT)); + // page를 잘못 입력한 경우 +// int total = (int) postPage.getTotalElements(); +// int limitPage; +// if ( total % size > 0) { limitPage = (int)total/size + 1; } +// else { limitPage = (int)total/size; } +// if(page > limitPage) {throw new ResponseStatusException(HttpStatus.BAD_REQUEST);} + + // page가 총 데이터 건수를 초과하는 경우 + long totalCount = postPage.getTotalElements(); + System.out.println("totalCount = " + totalCount); + long requestCount = (postPage.getTotalPages() - 1) * postPage.getSize(); + System.out.println("requestCount = " + requestCount); + if(!(totalCount > requestCount)) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST); } // Entity -> Dto 변환 - Dto 담은 page 반환 List posts = postPage.getContent(); - List dtos = posts.stream().map(postEntity -> toDto(postEntity)).collect(Collectors.toList()); return new PageImpl<>(dtos, pageable, postPage.getTotalElements());