From 44f6de4c8dbfbd7cede1ab6601611f23c3548334 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Mon, 9 Oct 2023 13:31:59 +0900 Subject: [PATCH 001/144] =?UTF-8?q?Feat=20:=20List=EB=A5=BC=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EB=B0=9B=EC=95=84=20=EB=AA=A9=EC=B0=A8?= =?UTF-8?q?=EB=A5=BC=20=EC=83=9D=EC=84=B1=ED=95=98=EB=8A=94=20IndexUtils?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Tree 형식으로 구현된 List를 입력받아 DFS로 목차를 생성하는 IndexUtils 구현하였습니다. --- .../wekiki/_core/utils/IndexUtils.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/IndexUtils.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/IndexUtils.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/IndexUtils.java new file mode 100644 index 00000000..c2d1c601 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/IndexUtils.java @@ -0,0 +1,52 @@ +package com.kakao.techcampus.wekiki._core.utils; + + +import com.kakao.techcampus.wekiki.post.Post; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +@Component +public class IndexUtils { + + public HashMap createIndex(List posts){ + HashMap> tree = new HashMap<>(); + HashMap indexs = new HashMap<>(); + + for(Post p : posts){ + // 만약 부모가 존재하면 + if(p.getParent() != null){ + if(tree.containsKey(p.getParent().getId())){ + tree.get(p.getParent().getId()).add(p.getId()); + }else{ + tree.put(p.getParent().getId(),new ArrayList<>(Arrays.asList(p.getId()))); + } + } + } + + int res = 1; + + for(Post p : posts){ + // 루트일때 + if(p.getParent() == null){ + DFS(res,p.getId(),"", indexs , tree); + res++; + } + } + + return indexs; + } + + public void DFS(int res, Long now, String index , HashMap indexs , HashMap> tree){ + indexs.put(now,index+res); + if(tree.containsKey(now)){ + for(int i = 0 ; i < tree.get(now).size(); i++){ + DFS(i+1,tree.get(now).get(i), index+res+"-",indexs,tree); + } + } + } + +} From 9f20664b04b9fe3c6b54ce2cdda3afe7703ba1d3 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Mon, 9 Oct 2023 13:33:02 +0900 Subject: [PATCH 002/144] =?UTF-8?q?Feat=20:=20=ED=8E=98=EC=9D=B4=EC=A7=80I?= =?UTF-8?q?D=EB=A1=9C=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 페이지 ID를 입력받아 특정 페이지들의 Post들을 조회하는 API 구현하였습니다. --- .../wekiki/page/PageInfoResponse.java | 36 +++++++++++++++++++ .../wekiki/page/PageRestController.java | 9 +++-- .../techcampus/wekiki/page/PageService.java | 34 ++++++++++++++++++ .../wekiki/post/PostJPARepository.java | 3 ++ 4 files changed, 80 insertions(+), 2 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index b78b701f..7d0a13bd 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -1,8 +1,11 @@ package com.kakao.techcampus.wekiki.page; +import com.kakao.techcampus.wekiki.post.Post; import lombok.Getter; import lombok.Setter; +import java.util.List; + public class PageInfoResponse { @Getter @Setter @@ -59,4 +62,37 @@ public searchPageDTO(PageInfo pageInfo){ } + @Getter + @Setter + public static class getPageFromIdDTO{ + String pageName; + List postList; + int goodCount; + int badCount; + + public getPageFromIdDTO(PageInfo pageInfo , List postList){ + this.pageName = pageInfo.getTitle(); + this.postList = postList; + this.goodCount = pageInfo.getGoodCount(); + this.badCount = pageInfo.getBadCount(); + } + + + @Getter + @Setter + public static class postDTO { + Long postId; + String index; + String postTitle; + String content; + + public postDTO(Post post, String index){ + this.postId = post.getId(); + this.index = index; + this.postTitle = post.getTitle(); + this.content = post.getContent(); + } + } + } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index 95e7e296..de84bf8d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -2,6 +2,7 @@ import com.kakao.techcampus.wekiki._core.utils.ApiUtils; +import com.kakao.techcampus.wekiki.post.PostResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -16,14 +17,18 @@ public class PageRestController { private final PageService pageService; /* - 페이지 + 글 조회 기능 + 페이지 ID로 페이지 + 글 조회 기능 */ @GetMapping("/page/{pageid}") - public void getPageFromId(@PathVariable Long pageid) { + public ResponseEntity getPageFromId(@PathVariable Long pageid) { + Long tempUserId = 1L; + + PageInfoResponse.getPageFromIdDTO response = pageService.getPageFromId(tempUserId, pageid); + return ResponseEntity.ok(ApiUtils.success(response)); } /* diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index d0ef18d0..29845b66 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -2,6 +2,9 @@ import com.kakao.techcampus.wekiki._core.errors.ApplicationException; import com.kakao.techcampus.wekiki._core.errors.ErrorCode; +import com.kakao.techcampus.wekiki._core.utils.IndexUtils; +import com.kakao.techcampus.wekiki.post.Post; +import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -9,6 +12,8 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; @@ -17,9 +22,38 @@ public class PageService { private final PageJPARepository pageJPARepository; + private final PostJPARepository postJPARepository; + + private final IndexUtils indexUtils; final int PAGE_COUNT = 10; + @Transactional + public PageInfoResponse.getPageFromIdDTO getPageFromId(Long userId, Long pageId){ + // 1. userId로 User 객체 가져오기 + + // 2. pageId로 PageInfo 객체 들고오기 + PageInfo pageInfo = pageJPARepository.findById(pageId).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); + + // 3. PageInfo로부터 Group 객체 들고오기 + + // 4. GroupMember인지 체크 + + // 5. 해당 groupId를 들고 있는 모든 페이지 Order 순으로 들고오기 + List posts = postJPARepository.findPostsByPageIdOrderByOrderAsc(pageId); + + // 6. 목차 생성하기 + HashMap indexs = indexUtils.createIndex(posts); + + // 7. DTO로 return + List temp = posts.stream() + .map(p -> new PageInfoResponse.getPageFromIdDTO.postDTO(p, indexs.get(p.getId()))) + .collect(Collectors.toList()); + + return new PageInfoResponse.getPageFromIdDTO(pageInfo, temp); + + } + @Transactional public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Long userId){ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java index 2fc6bbf2..c53d3420 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java @@ -16,5 +16,8 @@ List findPostsByPageIdAndOrderGreaterThan( @Param("orders") int orders ); + @Query("SELECT p FROM Post p WHERE p.pageInfo.id = :pageId ORDER BY p.orders ASC") + List findPostsByPageIdOrderByOrderAsc(@Param("pageId") Long pageId); + List findAllByGroupMember(GroupMember groupMember); } From b2f2872b8957e5c9b10bdbfc95264324f6da1f3a Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Mon, 9 Oct 2023 14:24:51 +0900 Subject: [PATCH 003/144] =?UTF-8?q?Feat=20:=20Post=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=8B=9C=20History=20=EC=83=9D=EC=84=B1=EB=90=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 페이지에 Post 생성시 History도 생성되도록 구현하였습니다. - Post 생성시 Page의 updated_at 수정되도록 구현하였습니다. --- .../kakao/techcampus/wekiki/history/History.java | 14 +++++++++----- .../kakao/techcampus/wekiki/page/PageInfo.java | 4 ++++ .../kakao/techcampus/wekiki/post/PostService.java | 15 ++++++++++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java index 0cf39692..2dd4cd5a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java @@ -2,7 +2,6 @@ import com.kakao.techcampus.wekiki.group.member.GroupMember; import com.kakao.techcampus.wekiki.group.member.InactiveGroupMember; -import com.kakao.techcampus.wekiki.page.Page; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.AccessLevel; @@ -25,18 +24,23 @@ public class History { private GroupMember groupMember; @ManyToOne private Post post; + + private String title; private String content; private LocalDateTime created_at; @Builder - public History(Long id, GroupMember groupMember, Post post, String content, LocalDateTime created_at) { + public History(Long id, Post post){ this.id = id; - this.groupMember = groupMember; + this.groupMember = post.getGroupMember(); this.post = post; - this.content = content; - this.created_at = created_at; + this.title = post.getTitle(); + this.content = post.getContent(); + this.created_at = post.getCreated_at(); } + + public void updateGroupMember(GroupMember groupMember) { this.groupMember = groupMember; } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java index e1c1fff3..90ed2cc9 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java @@ -47,6 +47,10 @@ public void plusBadCount(){ this.badCount++; } + public void updatePage(){ + this.updated_at = LocalDateTime.now(); + } + @Override public String toString() { return "PageInfo{" + diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index de95af7d..f747f94e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -3,6 +3,8 @@ import com.kakao.techcampus.wekiki._core.errors.ApplicationException; import com.kakao.techcampus.wekiki._core.errors.ErrorCode; +import com.kakao.techcampus.wekiki.history.History; +import com.kakao.techcampus.wekiki.history.HistoryJPARepository; import com.kakao.techcampus.wekiki.page.PageInfo; import com.kakao.techcampus.wekiki.page.PageJPARepository; import lombok.RequiredArgsConstructor; @@ -19,6 +21,10 @@ public class PostService { private final PageJPARepository pageJPARepository; private final PostJPARepository postJPARepository; + private final HistoryJPARepository historyJPARepository; + + + @Transactional public PostResponse.createPostDTO createPost(Long pageId, Long parentPostId, int order, String title, String content){ @@ -27,6 +33,7 @@ public PostResponse.createPostDTO createPost(Long pageId, Long parentPostId, int // 2. pageId로 해당 PageInfo 객체들고오고 update_at 바꾸기 group 객체 가져오기 PageInfo pageInfo = pageJPARepository.findById(pageId).orElseThrow( () -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); + pageInfo.updatePage(); // 3. userId랑 groupId로 groupmember가 맞는지 확인 @@ -56,7 +63,13 @@ public PostResponse.createPostDTO createPost(Long pageId, Long parentPostId, int Post savedPost = postJPARepository.save(newPost); - // 7. return DTO + // 7. 히스토리 생성 + History newHistory = History.builder() + .post(savedPost) + .build(); + historyJPARepository.save(newHistory); + + // 8. return DTO return new PostResponse.createPostDTO(savedPost); } } From d02307d8cf726e2bee24e2c7ee93daad2fd69ab1 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Mon, 9 Oct 2023 15:10:01 +0900 Subject: [PATCH 004/144] =?UTF-8?q?Feat=20:=20Post=20=EB=82=B4=EC=9A=A9=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존 Post에 있는 내용들과 동일하면 Exception을 던져주도록 구현하였습니다. - Post의 내용이 변경되면 History 테이블에 저장되도록 구현하였습니다. --- .../kakao/techcampus/wekiki/post/Post.java | 7 ++++ .../techcampus/wekiki/post/PostRequest.java | 8 +++++ .../techcampus/wekiki/post/PostResponse.java | 15 ++++++++ .../wekiki/post/PostRestController.java | 15 ++++++-- .../techcampus/wekiki/post/PostService.java | 36 +++++++++++++++++-- 5 files changed, 77 insertions(+), 4 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java index 3febeff5..f125f622 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java @@ -52,6 +52,13 @@ public void plusOrder(){ this.orders++; } + public void modifyPost(GroupMember groupMember, String title, String content){ + this.groupMember = groupMember; + this.title = title; + this.content = content; + this.created_at = LocalDateTime.now(); + } + public void updateGroupMember(GroupMember groupMember) { this.groupMember = groupMember; } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRequest.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRequest.java index 6dea2005..27487803 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRequest.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRequest.java @@ -24,4 +24,12 @@ public String toString() { '}'; } } + + @Getter + @Setter + public static class modifyPostDTO{ + private Long postId; + private String title; + private String content; + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java index acf864dd..48cb2569 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java @@ -21,4 +21,19 @@ public createPostDTO(Post post){ } } + @Getter + @Setter + public static class modifyPostDTO{ + + Long postId; + String title; + String content; + + public modifyPostDTO(Post post){ + this.postId = post.getId(); + this.title = post.getTitle(); + this.content = post.getContent(); + } + } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java index c2ab76f4..7e1ef538 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java @@ -2,27 +2,38 @@ import com.kakao.techcampus.wekiki._core.utils.ApiUtils; +import com.kakao.techcampus.wekiki.history.History; +import com.kakao.techcampus.wekiki.history.HistoryJPARepository; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; + @RestController @RequestMapping("/post") @RequiredArgsConstructor public class PostRestController { private final PostService postService; + private final HistoryJPARepository historyJPARepository; @PostMapping("/create") public ResponseEntity createPost(@RequestBody PostRequest.createPostDTO request) { - System.out.println(request.toString()); - PostResponse.createPostDTO response = postService.createPost(request.getPageId(), request.getParentPostId(), request.getOrder(), request.getTitle(),request.getContent()); return ResponseEntity.ok(ApiUtils.success(response)); } + @PutMapping("/modify") + public ResponseEntity modifyPost(@RequestBody PostRequest.modifyPostDTO request){ + + PostResponse.modifyPostDTO response = postService.modifyPost(request.getPostId(), request.getTitle(), request.getContent()); + + return ResponseEntity.ok(ApiUtils.success(response)); + } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index f747f94e..e1839966 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -23,8 +23,6 @@ public class PostService { private final HistoryJPARepository historyJPARepository; - - @Transactional public PostResponse.createPostDTO createPost(Long pageId, Long parentPostId, int order, String title, String content){ @@ -67,9 +65,43 @@ public PostResponse.createPostDTO createPost(Long pageId, Long parentPostId, int History newHistory = History.builder() .post(savedPost) .build(); + historyJPARepository.save(newHistory); // 8. return DTO return new PostResponse.createPostDTO(savedPost); } + + @Transactional + public PostResponse.modifyPostDTO modifyPost(Long postId , String title, String content){ + + // 1. userId user 객체 들고오기 + + // 2. postId -> pageId -> groupId (여기서 groupId 바로 받기..?) + + // 3. userId랑 groupId로 groupMember 있는지 확인 (즉 그룹 멤버인지 확인) + + // 4. postId로 post 엔티티 가져오기 + Post post = postJPARepository.findById(postId).orElseThrow( + () -> new ApplicationException(ErrorCode.POST_NOT_FOUND)); + + // 5. 현재 Post랑 내용 같은지 확인 + if(post.getTitle().equals(title) && post.getContent().equals(content)){ + throw new ApplicationException(ErrorCode.POST_SAME_DATE); + } + + // 6. 다르면 Post 수정후 히스토리 생성 저장 + // TODO : groupMember 추가 + post.modifyPost(null,title,content); + + History newHistory = History.builder() + .post(post) + .build(); + historyJPARepository.save(newHistory); + + // 7. return DTO + return new PostResponse.modifyPostDTO(post); + + } + } From 7d1f12219cf0d4626199223f74dae6b1ae88c5ae Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Mon, 9 Oct 2023 20:25:07 +0900 Subject: [PATCH 005/144] =?UTF-8?q?Style=20:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=EC=8B=9C=20=EB=AA=A9=EC=B0=A8=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 페이지 조회 시 기존 1-1-1 방식에서 1.1.1로 수정 --- .../com/kakao/techcampus/wekiki/_core/utils/IndexUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/IndexUtils.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/IndexUtils.java index c2d1c601..6a770185 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/IndexUtils.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/IndexUtils.java @@ -44,7 +44,7 @@ public void DFS(int res, Long now, String index , HashMap indexs , indexs.put(now,index+res); if(tree.containsKey(now)){ for(int i = 0 ; i < tree.get(now).size(); i++){ - DFS(i+1,tree.get(now).get(i), index+res+"-",indexs,tree); + DFS(i+1,tree.get(now).get(i), index+res+".",indexs,tree); } } } From 068624bac2bfeb163209c1ce464e346ba40280fb Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Mon, 9 Oct 2023 20:29:10 +0900 Subject: [PATCH 006/144] =?UTF-8?q?Feat=20:=20=EC=B5=9C=EA=B7=BC=20?= =?UTF-8?q?=EB=B0=94=EB=80=90=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 최근 생성/변경이 있는 10개의 페이지만 조회하도록 구현하였습니다. - 현재 group쪽은 연결이 안되어 있어서 where문에 groupId는 추후에 추가할 예정입니다. --- .../wekiki/_core/errors/ErrorCode.java | 5 ++- .../wekiki/page/PageInfoResponse.java | 26 +++++++++++++++ .../wekiki/page/PageJPARepository.java | 8 +++++ .../wekiki/page/PageRestController.java | 9 +++-- .../techcampus/wekiki/page/PageService.java | 33 ++++++++++++++++--- 5 files changed, 74 insertions(+), 7 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java index 7ff007d4..e3574c4e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java @@ -9,7 +9,10 @@ public enum ErrorCode { INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "WEKIKI-000", "Internal server error"), PAGE_NOT_FOUND(HttpStatus.NOT_FOUND,"PAGE-001" , "존재하지 않는 페이지 입니다."), - PARENT_POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST-001","존재하지 않는 PARENT POST 입니다."); + PARENT_POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST-001","존재하지 않는 PARENT POST 입니다."), + POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST-002","존재하지 않는 POST 입니다."), + POST_SAME_DATE(HttpStatus.BAD_REQUEST,"POST-003","동일한 데이터 입니다."); + /* 예시) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index 7d0a13bd..14993449 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -4,6 +4,7 @@ import lombok.Getter; import lombok.Setter; +import java.time.LocalDateTime; import java.util.List; public class PageInfoResponse { @@ -95,4 +96,29 @@ public postDTO(Post post, String index){ } } + + @Getter @Setter + public static class getRecentPageDTO{ + + List recentPage; + + public getRecentPageDTO(List recentPage){ + this.recentPage = recentPage; + } + + @Getter @Setter + public static class RecentPageDTO{ + Long pageId; + String title; + private LocalDateTime updated_at; + + public RecentPageDTO(PageInfo pageInfo){ + this.pageId = pageInfo.getId(); + this.title = pageInfo.getTitle(); + this.updated_at = pageInfo.getUpdated_at(); + } + } + + } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java index dd734cde..5bbea0a6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java @@ -5,9 +5,17 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import java.util.List; + public interface PageJPARepository extends JpaRepository { @Query("SELECT p FROM PageInfo p WHERE p.title LIKE :keyword%") Page findPagesByTitleContainingKeyword(String keyword, Pageable pageable); +// @Query("SELECT p FROM PageInfo p WHERE p.group.id = :groupId ORDER BY p.updated_at DESC") +// List findByGroupIdOrderByUpdatedAtDesc(Long groupId, Pageable pageable); + + @Query("SELECT p FROM PageInfo p ORDER BY p.updated_at DESC") + List findOrderByUpdatedAtDesc(Pageable pageable); + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index de84bf8d..732b2093 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -2,7 +2,6 @@ import com.kakao.techcampus.wekiki._core.utils.ApiUtils; -import com.kakao.techcampus.wekiki.post.PostResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -111,6 +110,7 @@ public void getPageFromTitle(@PathVariable Long groupid,@RequestParam(value = "t } + // ======================================================================== /* 페이지 키워드 검색 기능 @@ -131,8 +131,13 @@ public ResponseEntity searchPage(@PathVariable Long groupid,@RequestParam(val */ @GetMapping("/group/{groupid}/page/recent") - public void getRecentPage(@PathVariable Long groupid){ + public ResponseEntity getRecentPage(@PathVariable Long groupid){ + Long tempUserId = 1L; + + PageInfoResponse.getRecentPageDTO response = pageService.getRecentPage(tempUserId, groupid); + + return ResponseEntity.ok(ApiUtils.success(response)); } /* diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 29845b66..e471ece8 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -8,11 +8,11 @@ import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; @@ -61,7 +61,9 @@ public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Lon // 2. groupMember 존재하는지 확인 (없으면 Exception) - // 3. Page 생성 + // TODO : 3. 그룹 내 동일한 Page가 존재하는지 체크 + + // 4. Page 생성 PageInfo newPageInfo = PageInfo.builder() //.group(group) .title(title) @@ -72,10 +74,10 @@ public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Lon .updated_at(LocalDateTime.now()) .build(); - // 4. Page 저장 + // 5. Page 저장 PageInfo savedPageInfo = pageJPARepository.save(newPageInfo); - // 5. return + // 6. return DTO return new PageInfoResponse.createPageDTO(savedPageInfo); } @@ -134,6 +136,29 @@ public List searchPage(int pageNo, String keywor } + // ============================groupId 필요========================================================== + + @Transactional + public PageInfoResponse.getRecentPageDTO getRecentPage(Long userId , Long groupId){ + + // 1. userId user 객체 들고오기 + + // 2. groupId로부터 Group 객체 들고오기 + + // 3. userId랑 groupId로 groupMember 존재하는지 확인 + + // 4. 특정 groupId를 가진 Page들 order by로 updated_at이 최신인 10개 Page 조회 + // TODO : where 문에 groupId 추가 + Pageable pageable = PageRequest.of(0, 10); + //List recentPage = pageJPARepository.findByGroupIdOrderByUpdatedAtDesc(groupId, pageable); + List recentPage = pageJPARepository.findOrderByUpdatedAtDesc(pageable); + + // 5. return DTO + List collect = recentPage.stream().map(pageInfo -> + new PageInfoResponse.getRecentPageDTO.RecentPageDTO(pageInfo)).collect(Collectors.toList()); + return new PageInfoResponse.getRecentPageDTO(collect); + + } } From 9d134f6ba08433e1a3816982ab31019e5b9861a3 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Mon, 9 Oct 2023 20:42:29 +0900 Subject: [PATCH 007/144] =?UTF-8?q?Feat=20:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=EC=97=90=EC=84=9C=20=EB=8F=99=EC=9D=BC?= =?UTF-8?q?=ED=95=9C=20title=EC=97=90=20=EB=8C=80=ED=95=9C=20Exception=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 이미 존재하는 Title의 페이지 생성시 예외 처리 - 추후에 where 문에 groupId 추가할 예정 --- .../com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java | 1 + .../com/kakao/techcampus/wekiki/page/PageJPARepository.java | 5 +++++ .../java/com/kakao/techcampus/wekiki/page/PageService.java | 5 ++++- .../com/kakao/techcampus/wekiki/post/PostRestController.java | 1 - 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java index e3574c4e..ae0c65f3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java @@ -9,6 +9,7 @@ public enum ErrorCode { INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "WEKIKI-000", "Internal server error"), PAGE_NOT_FOUND(HttpStatus.NOT_FOUND,"PAGE-001" , "존재하지 않는 페이지 입니다."), + PAGE_ALREADY_PRESENT(HttpStatus.BAD_REQUEST,"PAGE-002","이미 존재하는 페이지 입니다."), PARENT_POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST-001","존재하지 않는 PARENT POST 입니다."), POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST-002","존재하지 않는 POST 입니다."), POST_SAME_DATE(HttpStatus.BAD_REQUEST,"POST-003","동일한 데이터 입니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java index 5bbea0a6..69bfebf1 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java @@ -4,8 +4,10 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.util.List; +import java.util.Optional; public interface PageJPARepository extends JpaRepository { @@ -18,4 +20,7 @@ public interface PageJPARepository extends JpaRepository { @Query("SELECT p FROM PageInfo p ORDER BY p.updated_at DESC") List findOrderByUpdatedAtDesc(Pageable pageable); + @Query("SELECT p FROM PageInfo p where p.title=:title") + Optional findByTitle(@Param("title") String title); + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index e471ece8..74def97b 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -61,7 +61,10 @@ public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Lon // 2. groupMember 존재하는지 확인 (없으면 Exception) - // TODO : 3. 그룹 내 동일한 Page가 존재하는지 체크 + // 3. 그룹 내 동일한 title의 Page가 존재하는지 체크 (TODO : where 문에 groupId 추가) + if(pageJPARepository.findByTitle(title).isPresent()){ + throw new ApplicationException(ErrorCode.PAGE_ALREADY_PRESENT); + } // 4. Page 생성 PageInfo newPageInfo = PageInfo.builder() diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java index 7e1ef538..c64084e4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java @@ -16,7 +16,6 @@ public class PostRestController { private final PostService postService; - private final HistoryJPARepository historyJPARepository; @PostMapping("/create") public ResponseEntity createPost(@RequestBody PostRequest.createPostDTO request) { From 556dd9a2027cf4b28e41da2afd4b06bb92e24da8 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Tue, 10 Oct 2023 13:58:28 +0900 Subject: [PATCH 008/144] =?UTF-8?q?Feat=20:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 해당 페이지에 post가 존재하는지 확인하고 존재하면 ApplicationException을 던지도록 구현하였습니다. - post가 존재안하는 페이지만 삭제 가능하도록 구현하였습니다. --- .../wekiki/_core/errors/ErrorCode.java | 1 + .../wekiki/page/PageInfoResponse.java | 12 +++++++++ .../wekiki/page/PageRestController.java | 6 ++++- .../techcampus/wekiki/page/PageService.java | 25 ++++++++++++++++++- .../wekiki/post/PostJPARepository.java | 2 ++ .../techcampus/wekiki/report/Report.java | 1 - 6 files changed, 44 insertions(+), 3 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java index ae0c65f3..51a62ebd 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java @@ -10,6 +10,7 @@ public enum ErrorCode { INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "WEKIKI-000", "Internal server error"), PAGE_NOT_FOUND(HttpStatus.NOT_FOUND,"PAGE-001" , "존재하지 않는 페이지 입니다."), PAGE_ALREADY_PRESENT(HttpStatus.BAD_REQUEST,"PAGE-002","이미 존재하는 페이지 입니다."), + PAGE_HAVE_POST(HttpStatus.BAD_REQUEST,"PAGE-003","글이 적혀있는 페이지는 삭제가 불가능합니다."), PARENT_POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST-001","존재하지 않는 PARENT POST 입니다."), POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST-002","존재하지 않는 POST 입니다."), POST_SAME_DATE(HttpStatus.BAD_REQUEST,"POST-003","동일한 데이터 입니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index 14993449..ea5a64d9 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -9,6 +9,18 @@ public class PageInfoResponse { + @Getter @Setter + public static class deletePageDTO{ + + Long pageId; + String title; + + public deletePageDTO(PageInfo pageInfo){ + this.pageId = pageInfo.getId(); + this.title = pageInfo.getTitle(); + } + } + @Getter @Setter public static class createPageDTO{ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index 732b2093..a345ce43 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -62,9 +62,13 @@ public ResponseEntity createPage(@RequestBody PageInfoRequest.createPageDTO r */ @DeleteMapping("/page/{pageid}") - public void deletePage(@PathVariable Long pageid) { + public ResponseEntity deletePage(@PathVariable Long pageid) { + Long tempUserId = 1L; + + PageInfoResponse.deletePageDTO response = pageService.deletePage(tempUserId, pageid); + return ResponseEntity.ok(ApiUtils.success(response)); } /* diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 74def97b..7b878ed4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -28,6 +28,29 @@ public class PageService { final int PAGE_COUNT = 10; + @Transactional + public PageInfoResponse.deletePageDTO deletePage(Long userId, Long pageId){ + // 1. userId로 User 객체 가져오기 + + // 2. GroupMember 인지 체크하기 + + // 3. 존재하는 페이지 인지 체크 + PageInfo pageInfo = pageJPARepository.findById(pageId).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); + + // 3. pageId로 post 있는지 확인 -> post 존재하면 Exception + if(postJPARepository.existsByPageInfoId(pageId)){ + throw new ApplicationException(ErrorCode.PAGE_HAVE_POST); + } + + // 4. 포스트가 하나도 없으면 삭제시키기 + PageInfoResponse.deletePageDTO response = new PageInfoResponse.deletePageDTO(pageInfo); + pageJPARepository.deleteById(pageId); + + // 5. return DTO + return response; + } + + @Transactional public PageInfoResponse.getPageFromIdDTO getPageFromId(Long userId, Long pageId){ // 1. userId로 User 객체 가져오기 @@ -153,8 +176,8 @@ public PageInfoResponse.getRecentPageDTO getRecentPage(Long userId , Long groupI // 4. 특정 groupId를 가진 Page들 order by로 updated_at이 최신인 10개 Page 조회 // TODO : where 문에 groupId 추가 Pageable pageable = PageRequest.of(0, 10); - //List recentPage = pageJPARepository.findByGroupIdOrderByUpdatedAtDesc(groupId, pageable); List recentPage = pageJPARepository.findOrderByUpdatedAtDesc(pageable); + //List recentPage = pageJPARepository.findByGroupIdOrderByUpdatedAtDesc(groupId, pageable); // 5. return DTO List collect = recentPage.stream().map(pageInfo -> diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java index c53d3420..bd179be6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java @@ -19,5 +19,7 @@ List findPostsByPageIdAndOrderGreaterThan( @Query("SELECT p FROM Post p WHERE p.pageInfo.id = :pageId ORDER BY p.orders ASC") List findPostsByPageIdOrderByOrderAsc(@Param("pageId") Long pageId); + boolean existsByPageInfoId(Long pageInfoId); + List findAllByGroupMember(GroupMember groupMember); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java index 7e16a324..9d5ce8ee 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java @@ -1,7 +1,6 @@ package com.kakao.techcampus.wekiki.report; import com.kakao.techcampus.wekiki.group.member.GroupMember; -import com.kakao.techcampus.wekiki.page.Page; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.AccessLevel; From 2f11d5f12e2138a6d10b6a8f0e4abb472e211130 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Tue, 10 Oct 2023 14:49:33 +0900 Subject: [PATCH 009/144] =?UTF-8?q?Feat=20:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=EC=A0=9C=EB=AA=A9=EC=9C=BC=EB=A1=9C=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - groupId랑 title을 가지고 특정 그룹에 존재하는 title의 페이지를 조회할 수 있는 API 구현하였습니다. --- .../wekiki/page/PageRestController.java | 20 +++++++--------- .../techcampus/wekiki/page/PageService.java | 24 +++++++++++++++++++ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index a345ce43..155187ca 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -30,15 +30,6 @@ public ResponseEntity getPageFromId(@PathVariable Long pageid) { return ResponseEntity.ok(ApiUtils.success(response)); } - /* - 페이지 목차 조회 - */ - - @GetMapping("/page/index/{pageid}") - public void getIndex(@PathVariable Long pageid) { - - - } /* 페이지 생성 기능 @@ -104,17 +95,22 @@ public ResponseEntity hatePage(@PathVariable Long pageid) { } + // ======================================================================== + /* 페이지 제목으로 페이지 조회 */ @GetMapping("/group/{groupid}/page") - public void getPageFromTitle(@PathVariable Long groupid,@RequestParam(value = "title") String title) { + public ResponseEntity getPageFromTitle(@PathVariable Long groupid,@RequestParam(value = "title") String title) { + Long tempUserId = 1L; - } + PageInfoResponse.getPageFromIdDTO response = pageService.getPageFromTitle(tempUserId, groupid,title); - // ======================================================================== + return ResponseEntity.ok(ApiUtils.success(response)); + + } /* 페이지 키워드 검색 기능 diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 7b878ed4..fd38c202 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -186,5 +186,29 @@ public PageInfoResponse.getRecentPageDTO getRecentPage(Long userId , Long groupI } + @Transactional + public PageInfoResponse.getPageFromIdDTO getPageFromTitle(Long userId, Long groupId, String title){ + + // 1. userId로 User 객체 가져오기 + + // 2. groupId로 GroupMember인지 체크하기 + + // 3. groupId랑 title로 Page있는지 확인 (TODO : where 문에 groupId 추가) + PageInfo page = pageJPARepository.findByTitle(title).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); + + // 4. 해당 pageId를 들고있는 모든 페이지 Order 순으로 들고오기 + List posts = postJPARepository.findPostsByPageIdOrderByOrderAsc(page.getId()); + + // 5. 목차 생성하기 + HashMap indexs = indexUtils.createIndex(posts); + + // 6. DTO로 return + List temp = posts.stream() + .map(p -> new PageInfoResponse.getPageFromIdDTO.postDTO(p, indexs.get(p.getId()))) + .collect(Collectors.toList()); + + return new PageInfoResponse.getPageFromIdDTO(page, temp); + } + } From afd510fd2137a01fdf284ca3efd2d9bc0e214fbe Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Tue, 10 Oct 2023 15:15:06 +0900 Subject: [PATCH 010/144] =?UTF-8?q?Feat=20:=20=EB=8B=A8=EC=96=B4=EC=97=90?= =?UTF-8?q?=20=EB=A7=81=ED=81=AC=EB=A5=BC=20=EA=B1=B8=EA=B8=B0=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20PagdId=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 글 작성시 단어에 링크를 걸기 위한 PageId 조회하는 API 구현하였습니다. --- .../techcampus/wekiki/page/PageInfoResponse.java | 9 +++++++++ .../wekiki/page/PageRestController.java | 9 ++++++++- .../kakao/techcampus/wekiki/page/PageService.java | 15 +++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index ea5a64d9..2d1802f0 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -133,4 +133,13 @@ public RecentPageDTO(PageInfo pageInfo){ } + @Getter @Setter + public static class getPageLinkDTO{ + Long pageId; + + public getPageLinkDTO(PageInfo pageInfo){ + this.pageId = pageInfo.getId(); + } + } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index 155187ca..bd277702 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -120,6 +120,8 @@ public ResponseEntity getPageFromTitle(@PathVariable Long groupid,@RequestPar @GetMapping("/group/{groupid}/page/search") public ResponseEntity searchPage(@PathVariable Long groupid,@RequestParam(value = "keyword" , defaultValue = "") String keyword, @RequestParam(value = "page", defaultValue = "1") int page) { + Long tempUserId = 1L; + List response = pageService.searchPage(page-1, keyword); return ResponseEntity.ok(ApiUtils.success(response)); @@ -146,8 +148,13 @@ public ResponseEntity getRecentPage(@PathVariable Long groupid){ */ @GetMapping("/group/{groupid}/page/link") - public void getPageLink(@PathVariable Long groupid, @RequestParam(value = "title") String title){ + public ResponseEntity getPageLink(@PathVariable Long groupid, @RequestParam(value = "title") String title){ + + Long tempUserId = 1L; + + PageInfoResponse.getPageLinkDTO response = pageService.getPageLink(tempUserId, groupid, title); + return ResponseEntity.ok(ApiUtils.success(response)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index fd38c202..a35098cd 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -210,5 +210,20 @@ public PageInfoResponse.getPageFromIdDTO getPageFromTitle(Long userId, Long grou return new PageInfoResponse.getPageFromIdDTO(page, temp); } + @Transactional + public PageInfoResponse.getPageLinkDTO getPageLink(Long userId, Long groupId, String title){ + + // 1. userId로 User 객체 가져오기 + + // 2. groupId로 GroupMember인지 체크하기 + + // 3. groupId랑 title로 Page있는지 확인 (TODO : where 문에 groupId 추가) + // (추후에 redis로 Key Value를 로해서 성능 향상시켜보자) + PageInfo page = pageJPARepository.findByTitle(title).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); + + // 4. return DTO + return new PageInfoResponse.getPageLinkDTO(page); + } + } From 08cd881d6c3db3a3b99370feb16c2b6a25584f87 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Tue, 10 Oct 2023 17:34:06 +0900 Subject: [PATCH 011/144] =?UTF-8?q?Feat=20:=20Post=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Post 삭제 시에 해당 Post의 Id를 가진 history 객체들도 모두 삭제시켜주었습니다 - Post들이 한 페이지내에서 트리 구조로 이루어져있어서 child Post를 가지고 있지 않는 Post들만 삭제가능하도록 예외처리하였습니다. - Post들 사이에 순서가 존재하므로 중간 순서의 Post가 삭제되었을 때, 뒷 순서의 Post들의 orders를 -1 처리해주었습니다. --- .../wekiki/_core/errors/ErrorCode.java | 3 +- .../wekiki/history/HistoryJPARepository.java | 9 +++++ .../kakao/techcampus/wekiki/post/Post.java | 4 ++ .../wekiki/post/PostJPARepository.java | 2 + .../techcampus/wekiki/post/PostResponse.java | 13 +++++++ .../wekiki/post/PostRestController.java | 18 ++++++++- .../techcampus/wekiki/post/PostService.java | 37 +++++++++++++++++-- 7 files changed, 80 insertions(+), 6 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java index 51a62ebd..0107a16a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java @@ -13,7 +13,8 @@ public enum ErrorCode { PAGE_HAVE_POST(HttpStatus.BAD_REQUEST,"PAGE-003","글이 적혀있는 페이지는 삭제가 불가능합니다."), PARENT_POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST-001","존재하지 않는 PARENT POST 입니다."), POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST-002","존재하지 않는 POST 입니다."), - POST_SAME_DATE(HttpStatus.BAD_REQUEST,"POST-003","동일한 데이터 입니다."); + POST_SAME_DATE(HttpStatus.BAD_REQUEST,"POST-003","동일한 데이터 입니다."), + HAVE_CHILD_POST(HttpStatus.BAD_REQUEST,"POST-004","하위 포스트가 존재하는 포스트는 삭제가 불가능합니다."); /* diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java index fe6a63fb..8c13527c 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java @@ -1,12 +1,21 @@ package com.kakao.techcampus.wekiki.history; import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.post.Post; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; @Repository public interface HistoryJPARepository extends JpaRepository { + + @Modifying + @Query("DELETE FROM History h WHERE h.post.id = :postId") + void deleteByPostId(@Param("postId") Long postId); + List findAllByGroupMember(GroupMember groupMember); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java index f125f622..d3257f3c 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java @@ -52,6 +52,10 @@ public void plusOrder(){ this.orders++; } + public void minusOrder(){ + this.orders--; + } + public void modifyPost(GroupMember groupMember, String title, String content){ this.groupMember = groupMember; this.title = title; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java index bd179be6..e50a368a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java @@ -21,5 +21,7 @@ List findPostsByPageIdAndOrderGreaterThan( boolean existsByPageInfoId(Long pageInfoId); + boolean existsByParentId(Long parentId); + List findAllByGroupMember(GroupMember groupMember); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java index 48cb2569..7acba5fc 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java @@ -36,4 +36,17 @@ public modifyPostDTO(Post post){ } } + @Getter + @Setter + public static class deletePostDTO{ + + Long postId; + String title; + + public deletePostDTO(Post post){ + this.postId = post.getId(); + this.title = post.getTitle(); + } + } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java index c64084e4..228004d9 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java @@ -20,7 +20,9 @@ public class PostRestController { @PostMapping("/create") public ResponseEntity createPost(@RequestBody PostRequest.createPostDTO request) { - PostResponse.createPostDTO response = postService.createPost(request.getPageId(), request.getParentPostId(), + Long tempUserId = 1L; + + PostResponse.createPostDTO response = postService.createPost(tempUserId,request.getPageId(), request.getParentPostId(), request.getOrder(), request.getTitle(),request.getContent()); return ResponseEntity.ok(ApiUtils.success(response)); @@ -29,7 +31,19 @@ public ResponseEntity createPost(@RequestBody PostRequest.createPostDTO reque @PutMapping("/modify") public ResponseEntity modifyPost(@RequestBody PostRequest.modifyPostDTO request){ - PostResponse.modifyPostDTO response = postService.modifyPost(request.getPostId(), request.getTitle(), request.getContent()); + Long tempUserId = 1L; + + PostResponse.modifyPostDTO response = postService.modifyPost(tempUserId, request.getPostId(), request.getTitle(), request.getContent()); + + return ResponseEntity.ok(ApiUtils.success(response)); + } + + @DeleteMapping("/{postid}") + public ResponseEntity deletePost(@PathVariable Long postid){ + + Long tempUserId = 1L; + + PostResponse.deletePostDTO response = postService.deletePost(tempUserId, postid); return ResponseEntity.ok(ApiUtils.success(response)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index e1839966..ff4733f0 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -20,11 +20,10 @@ public class PostService { private final PageJPARepository pageJPARepository; private final PostJPARepository postJPARepository; - private final HistoryJPARepository historyJPARepository; @Transactional - public PostResponse.createPostDTO createPost(Long pageId, Long parentPostId, int order, String title, String content){ + public PostResponse.createPostDTO createPost(Long userId,Long pageId, Long parentPostId, int order, String title, String content){ // 1. userId로 user 객체 들고오기 @@ -73,7 +72,7 @@ public PostResponse.createPostDTO createPost(Long pageId, Long parentPostId, int } @Transactional - public PostResponse.modifyPostDTO modifyPost(Long postId , String title, String content){ + public PostResponse.modifyPostDTO modifyPost(Long userId, Long postId , String title, String content){ // 1. userId user 객체 들고오기 @@ -104,4 +103,36 @@ public PostResponse.modifyPostDTO modifyPost(Long postId , String title, String } + @Transactional + public PostResponse.deletePostDTO deletePost(Long userId, Long postId){ + + // 1. userId로 user 객체 가져오기 + + // 2. groupId로 GroupMember 인지 체크하기 + + // 3. 존재하는 포스트 인지 체크 + Post post = postJPARepository.findById(postId).orElseThrow( + () -> new ApplicationException(ErrorCode.POST_NOT_FOUND)); + + // 4. parent로 해당 postId를 가지고 있는 post가 있는지 확인 -> 존재하면 Exception + if(postJPARepository.existsByParentId(postId)){ + throw new ApplicationException(ErrorCode.HAVE_CHILD_POST); + } + + // 5. child post 존재 안하면 history + post 삭제 시키기 + PostResponse.deletePostDTO response = new PostResponse.deletePostDTO(post); + historyJPARepository.deleteByPostId(postId); + postJPARepository.deleteById(postId); + + // 6. order값 앞으로 땡기기 + List posts = postJPARepository.findPostsByPageIdAndOrderGreaterThan(post.getPageInfo().getId(), post.getOrders()); + for(Post p : posts){ + p.minusOrder(); + } + + // 7. return DTO; + return response; + + } + } From 61b8f53df632475ce0901ba8bb31fb7bb6f72e3f Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Wed, 11 Oct 2023 17:09:54 +0900 Subject: [PATCH 012/144] =?UTF-8?q?Fix=20:=20pull=20=EC=9D=B4=ED=9B=84=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20MemberId?= =?UTF-8?q?=20Long=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20-=20pull=20?= =?UTF-8?q?=EC=9D=B4=ED=9B=84=20error=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EC=95=88=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20-=20Membe?= =?UTF-8?q?rId=20Long=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20-=20jwt=20?= =?UTF-8?q?=ED=86=A0=ED=81=B0=20=EC=95=88=EC=9D=98=20getName=EC=9D=84=20em?= =?UTF-8?q?ail=EC=9D=B4=20=EC=95=84=EB=8B=8C=20id=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wekiki/_core/error/exception/Exception400.java | 2 +- .../wekiki/_core/error/exception/Exception401.java | 2 +- .../wekiki/_core/error/exception/Exception403.java | 2 +- .../wekiki/_core/error/exception/Exception404.java | 2 +- .../wekiki/_core/error/exception/Exception500.java | 2 +- .../wekiki/_core/utils/CustomUserDetail.java | 2 +- .../techcampus/wekiki/_core/utils/SecurityUtils.java | 4 ++-- .../com/kakao/techcampus/wekiki/history/History.java | 2 -- .../com/kakao/techcampus/wekiki/member/Member.java | 8 ++------ .../techcampus/wekiki/member/MemberJPARepository.java | 2 +- .../kakao/techcampus/wekiki/member/MemberService.java | 11 +++++------ .../com/kakao/techcampus/wekiki/report/Report.java | 1 - 12 files changed, 16 insertions(+), 24 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception400.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception400.java index 3dbdbbe4..3e4c4e25 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception400.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception400.java @@ -14,7 +14,7 @@ public Exception400(String message) { } public ApiUtils.ApiResult body(){ - return ApiUtils.error(getMessage(), HttpStatus.BAD_REQUEST); + return ApiUtils.error(getMessage()); } public HttpStatus status(){ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception401.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception401.java index 680a9f66..1ef0ffd5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception401.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception401.java @@ -14,7 +14,7 @@ public Exception401(String message) { } public ApiUtils.ApiResult body(){ - return ApiUtils.error(getMessage(), HttpStatus.UNAUTHORIZED); + return ApiUtils.error(getMessage()); } public HttpStatus status(){ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception403.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception403.java index c7338a64..fa92b708 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception403.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception403.java @@ -13,7 +13,7 @@ public Exception403(String message) { } public ApiUtils.ApiResult body(){ - return ApiUtils.error(getMessage(), HttpStatus.FORBIDDEN); + return ApiUtils.error(getMessage()); } public HttpStatus status(){ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception404.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception404.java index 6c0debcb..10417d22 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception404.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception404.java @@ -13,7 +13,7 @@ public Exception404(String message) { } public ApiUtils.ApiResult body(){ - return ApiUtils.error(getMessage(), HttpStatus.NOT_FOUND); + return ApiUtils.error(getMessage()); } public HttpStatus status(){ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception500.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception500.java index 53b37ac2..a7dddc46 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception500.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception500.java @@ -12,7 +12,7 @@ public Exception500(String message) { } public ApiUtils.ApiResult body(){ - return ApiUtils.error(getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + return ApiUtils.error(getMessage()); } public HttpStatus status(){ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/CustomUserDetail.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/CustomUserDetail.java index a1addbb2..d9a66521 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/CustomUserDetail.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/CustomUserDetail.java @@ -28,7 +28,7 @@ public UserDetails loadUserByUsername(String email) throws UsernameNotFoundExcep public UserDetails createUserDetails(Member member) { GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(member.getAuthority().toString()); return User.builder() - .username(member.getEmail()) + .username(member.getId().toString()) .password(member.getPassword()) .authorities(grantedAuthority) .build(); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/SecurityUtils.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/SecurityUtils.java index b88e7434..2d575bc9 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/SecurityUtils.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/SecurityUtils.java @@ -4,8 +4,8 @@ public class SecurityUtils { - public static String currentMember() { - return SecurityContextHolder.getContext().getAuthentication().getName(); + public static Long currentMember() { + return Long.valueOf(SecurityContextHolder.getContext().getAuthentication().getName()); } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java index 0cf39692..a6979f33 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java @@ -1,8 +1,6 @@ package com.kakao.techcampus.wekiki.history; import com.kakao.techcampus.wekiki.group.member.GroupMember; -import com.kakao.techcampus.wekiki.group.member.InactiveGroupMember; -import com.kakao.techcampus.wekiki.page.Page; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.AccessLevel; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java index a5f2f04c..a3821430 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java @@ -5,10 +5,8 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.hibernate.annotations.GenericGenerator; import java.time.LocalDateTime; -import java.util.UUID; @Getter @Entity @@ -17,10 +15,8 @@ public class Member { @Id - @GeneratedValue(generator = "uuid2") - @GenericGenerator(name = "uuid2", strategy = "uuid2") - @Column(columnDefinition = "binary(16)") - private UUID id; + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; private String name; private String email; private String password; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberJPARepository.java index 7c6635ca..af7dfbc3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberJPARepository.java @@ -7,7 +7,7 @@ import java.util.Optional; import java.util.UUID; -public interface MemberJPARepository extends JpaRepository { +public interface MemberJPARepository extends JpaRepository { @Query("select m from Member m where m.email=:email") Optional findByEmail(@Param("email") String email); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index 395f6729..53fd9a03 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -3,7 +3,6 @@ import com.kakao.techcampus.wekiki._core.error.exception.*; import com.kakao.techcampus.wekiki._core.jwt.JWTTokenProvider; import com.kakao.techcampus.wekiki._core.utils.RedisUtility; -import com.kakao.techcampus.wekiki.group.member.GroupMember; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.mail.SimpleMailMessage; @@ -62,7 +61,7 @@ public MemberResponse.authTokenDTO login(MemberRequest.loginRequestDTO loginDTO) } public void getMyInfo() { - Optional member = memberRepository.findByEmail(currentMember()); + Optional member = memberRepository.findById(currentMember()); if(member.isEmpty()) throw new Exception404("없는 회원입니다."); // member 안의 groupMember를 뽑아낸 뒤, 그걸로 Response를 제작 @@ -71,14 +70,14 @@ public void getMyInfo() { } public void cancel() { - Optional member = memberRepository.findByEmail(currentMember()); + Optional member = memberRepository.findById(currentMember()); if(member.isEmpty()) throw new Exception404("없는 회원입니다."); memberRepository.delete(member.get()); } public void changePassword(MemberRequest.changePasswordRequestDTO changePasswordDTO) { - Optional member = memberRepository.findByEmail(currentMember()); + Optional member = memberRepository.findById(currentMember()); if(member.isEmpty()) throw new Exception404("없는 회원입니다."); if(!passwordEncoder.matches(changePasswordDTO.getCurrentPassword(), member.get().getPassword())) @@ -87,7 +86,7 @@ public void changePassword(MemberRequest.changePasswordRequestDTO changePassword } public void sendEmail(String email) { - Optional member = memberRepository.findByEmail(currentMember()); + Optional member = memberRepository.findById(currentMember()); if(member.isEmpty()) throw new Exception404("없는 회원입니다."); Integer authNumber = makeEmailAuthNum(); @@ -103,7 +102,7 @@ public void sendEmail(String email) { } public void checkPNUEmail(MemberRequest.checkPNUEmailRequestDTO pnuEmailRequestDTO) { - Optional member = memberRepository.findByEmail(currentMember()); + Optional member = memberRepository.findById(currentMember()); if(member.isEmpty()) throw new Exception404("없는 회원입니다."); if(redisUtility.getValues(pnuEmailRequestDTO.getEmail()).equals(pnuEmailRequestDTO.getCertificationNumber())){ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java index 7e16a324..9d5ce8ee 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java @@ -1,7 +1,6 @@ package com.kakao.techcampus.wekiki.report; import com.kakao.techcampus.wekiki.group.member.GroupMember; -import com.kakao.techcampus.wekiki.page.Page; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.AccessLevel; From 98bca9ad377383d4eba093f50588d6508dd10283 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Thu, 12 Oct 2023 12:50:17 +0900 Subject: [PATCH 013/144] =?UTF-8?q?Feat=20:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=EB=AA=A9=EC=B0=A8=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 프론트팀원의 요청으로 페이지 목차 조회 API 추가하였습니다. --- .../wekiki/page/PageInfoResponse.java | 27 +++++++++++++++++++ .../wekiki/page/PageRestController.java | 17 ++++++++++++ .../techcampus/wekiki/page/PageService.java | 26 ++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index 2d1802f0..b60649e6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -75,6 +75,33 @@ public searchPageDTO(PageInfo pageInfo){ } + @Getter + @Setter + public static class getPageIndexDTO{ + String pageName; + List postList; + + public getPageIndexDTO(PageInfo pageInfo , List postList){ + this.pageName = pageInfo.getTitle(); + this.postList = postList; + } + + + @Getter + @Setter + public static class postDTO { + Long postId; + String index; + String postTitle; + + public postDTO(Post post, String index){ + this.postId = post.getId(); + this.index = index; + this.postTitle = post.getTitle(); + } + } + } + @Getter @Setter public static class getPageFromIdDTO{ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index bd277702..474495a6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -95,6 +95,23 @@ public ResponseEntity hatePage(@PathVariable Long pageid) { } + /* + 페이지 목차 조회 기능 + + */ + + @GetMapping("/page/{pageid}/index") + public ResponseEntity getPageIndex(@PathVariable Long pageid) { + + Long tempUserId = 1L; + + PageInfoResponse.getPageIndexDTO response = pageService.getPageIndex(tempUserId, pageid); + + return ResponseEntity.ok(ApiUtils.success(response)); + } + + + // ======================================================================== /* diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index a35098cd..d222af71 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -28,6 +28,32 @@ public class PageService { final int PAGE_COUNT = 10; + @Transactional + public PageInfoResponse.getPageIndexDTO getPageIndex(Long userId, Long pageId){ + // 1. userId로 User 객체 가져오기 + + // 2. pageId로 PageInfo 객체 들고오기 + PageInfo pageInfo = pageJPARepository.findById(pageId).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); + + // 3. PageInfo로부터 Group 객체 들고오기 + + // 4. GroupMember인지 체크 + + // 5. 해당 groupId를 들고 있는 모든 페이지 Order 순으로 들고오기 + List posts = postJPARepository.findPostsByPageIdOrderByOrderAsc(pageId); + + // 6. 목차 생성하기 + HashMap indexs = indexUtils.createIndex(posts); + + // 7. DTO로 return + List temp = posts.stream() + .map(p -> new PageInfoResponse.getPageIndexDTO.postDTO(p, indexs.get(p.getId()))) + .collect(Collectors.toList()); + + return new PageInfoResponse.getPageIndexDTO(pageInfo, temp); + + } + @Transactional public PageInfoResponse.deletePageDTO deletePage(Long userId, Long pageId){ // 1. userId로 User 객체 가져오기 From fa41ffc110ddaa71b68f437d3e8a5297385e283d Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Thu, 12 Oct 2023 13:10:02 +0900 Subject: [PATCH 014/144] =?UTF-8?q?Refactor=20:=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=9D=B4=EB=A6=84=20pageName=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - pageName이랑 title을 혼동해서 쓰는 경우가 있어서 모두 pageName으로 통일하였습니다. --- .../techcampus/wekiki/page/PageInfo.java | 20 +++----------- .../wekiki/page/PageInfoRequest.java | 2 +- .../wekiki/page/PageInfoResponse.java | 26 +++++++++---------- .../wekiki/page/PageJPARepository.java | 4 +-- .../wekiki/page/PageRestController.java | 2 +- .../techcampus/wekiki/page/PageService.java | 2 +- 6 files changed, 22 insertions(+), 34 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java index 90ed2cc9..3d24a0cf 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java @@ -20,7 +20,7 @@ public class PageInfo { private Long id; @ManyToOne private Group group; - private String title; + private String pageName; private int goodCount; private int badCount; private int viewCount; @@ -28,10 +28,10 @@ public class PageInfo { private LocalDateTime updated_at; @Builder - public PageInfo(Long id, Group group, String title, int goodCount, int badCount, int viewCount, LocalDateTime created_at, LocalDateTime updated_at) { + public PageInfo(Long id, Group group, String pageName, int goodCount, int badCount, int viewCount, LocalDateTime created_at, LocalDateTime updated_at) { this.id = id; this.group = group; - this.title = title; + this.pageName = pageName; this.goodCount = goodCount; this.badCount = badCount; this.viewCount = viewCount; @@ -51,17 +51,5 @@ public void updatePage(){ this.updated_at = LocalDateTime.now(); } - @Override - public String toString() { - return "PageInfo{" + - "id=" + id + - //", group=" + group + - ", title='" + title + '\'' + - ", goodCount=" + goodCount + - ", badCount=" + badCount + - ", viewCount=" + viewCount + - ", created_at=" + created_at + - ", updated_at=" + updated_at + - '}'; - } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoRequest.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoRequest.java index bb4d6f77..73fecee7 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoRequest.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoRequest.java @@ -8,7 +8,7 @@ public class PageInfoRequest { @Getter @Setter public static class createPageDTO { - private String title; + private String pageName; private Long groupId; } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index b60649e6..577b636d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -17,7 +17,7 @@ public static class deletePageDTO{ public deletePageDTO(PageInfo pageInfo){ this.pageId = pageInfo.getId(); - this.title = pageInfo.getTitle(); + this.title = pageInfo.getPageName(); } } @@ -25,11 +25,11 @@ public deletePageDTO(PageInfo pageInfo){ public static class createPageDTO{ Long pageId; - String title; + String pageName; public createPageDTO(PageInfo pageInfo){ this.pageId = pageInfo.getId(); - this.title = pageInfo.getTitle(); + this.pageName = pageInfo.getPageName(); } } @@ -37,12 +37,12 @@ public createPageDTO(PageInfo pageInfo){ public static class likePageDTO{ Long pageId; - String title; + String pageName; int goodCount; public likePageDTO(PageInfo pageInfo){ this.pageId = pageInfo.getId(); - this.title = pageInfo.getTitle(); + this.pageName = pageInfo.getPageName(); this.goodCount = pageInfo.getGoodCount(); } } @@ -51,12 +51,12 @@ public likePageDTO(PageInfo pageInfo){ public static class hatePageDTO{ Long pageId; - String title; + String pageName; int badCount; public hatePageDTO(PageInfo pageInfo){ this.pageId = pageInfo.getId(); - this.title = pageInfo.getTitle(); + this.pageName = pageInfo.getPageName(); this.badCount = pageInfo.getBadCount(); } } @@ -65,12 +65,12 @@ public hatePageDTO(PageInfo pageInfo){ public static class searchPageDTO{ Long pageId; - String title; + String pageName; //String contents; public searchPageDTO(PageInfo pageInfo){ this.pageId = pageInfo.getId(); - this.title = pageInfo.getTitle(); + this.pageName = pageInfo.getPageName(); } } @@ -82,7 +82,7 @@ public static class getPageIndexDTO{ List postList; public getPageIndexDTO(PageInfo pageInfo , List postList){ - this.pageName = pageInfo.getTitle(); + this.pageName = pageInfo.getPageName(); this.postList = postList; } @@ -111,7 +111,7 @@ public static class getPageFromIdDTO{ int badCount; public getPageFromIdDTO(PageInfo pageInfo , List postList){ - this.pageName = pageInfo.getTitle(); + this.pageName = pageInfo.getPageName(); this.postList = postList; this.goodCount = pageInfo.getGoodCount(); this.badCount = pageInfo.getBadCount(); @@ -148,12 +148,12 @@ public getRecentPageDTO(List recentPage){ @Getter @Setter public static class RecentPageDTO{ Long pageId; - String title; + String pageName; private LocalDateTime updated_at; public RecentPageDTO(PageInfo pageInfo){ this.pageId = pageInfo.getId(); - this.title = pageInfo.getTitle(); + this.pageName = pageInfo.getPageName(); this.updated_at = pageInfo.getUpdated_at(); } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java index 69bfebf1..63bf4159 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java @@ -11,7 +11,7 @@ public interface PageJPARepository extends JpaRepository { - @Query("SELECT p FROM PageInfo p WHERE p.title LIKE :keyword%") + @Query("SELECT p FROM PageInfo p WHERE p.pageName LIKE :keyword%") Page findPagesByTitleContainingKeyword(String keyword, Pageable pageable); // @Query("SELECT p FROM PageInfo p WHERE p.group.id = :groupId ORDER BY p.updated_at DESC") @@ -20,7 +20,7 @@ public interface PageJPARepository extends JpaRepository { @Query("SELECT p FROM PageInfo p ORDER BY p.updated_at DESC") List findOrderByUpdatedAtDesc(Pageable pageable); - @Query("SELECT p FROM PageInfo p where p.title=:title") + @Query("SELECT p FROM PageInfo p where p.pageName=:title") Optional findByTitle(@Param("title") String title); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index 474495a6..01195f5a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -42,7 +42,7 @@ public ResponseEntity createPage(@RequestBody PageInfoRequest.createPageDTO r // TODO : JWT에서 userId 꺼내도록 수정 Long tempUserId = 1L; - PageInfoResponse.createPageDTO response = pageService.createPage(request.getTitle(), request.getGroupId(), tempUserId); + PageInfoResponse.createPageDTO response = pageService.createPage(request.getPageName(), request.getGroupId(), tempUserId); return ResponseEntity.ok(ApiUtils.success(response)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index d222af71..80cc3454 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -118,7 +118,7 @@ public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Lon // 4. Page 생성 PageInfo newPageInfo = PageInfo.builder() //.group(group) - .title(title) + .pageName(title) .goodCount(0) .badCount(0) .viewCount(0) From bcdb3847e24aaff5a5abb5bf4fecfffef428ef28 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Thu, 12 Oct 2023 13:14:52 +0900 Subject: [PATCH 015/144] =?UTF-8?q?Refactor=20:=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=A0=9C=EB=AA=A9=EC=9C=BC=EB=A1=9C=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=A1=B0=ED=9A=8C=20API=EC=97=90=EC=84=9C?= =?UTF-8?q?=20response=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 프론트 팀원의 요청으로 페이지 제목으로 페이지 조회 api에서 response에 pageId도 추가해주었습니다. --- .../com/kakao/techcampus/wekiki/page/PageInfoResponse.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index 577b636d..d46ce7e6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -105,12 +105,15 @@ public postDTO(Post post, String index){ @Getter @Setter public static class getPageFromIdDTO{ + + Long pageId; String pageName; List postList; int goodCount; int badCount; public getPageFromIdDTO(PageInfo pageInfo , List postList){ + this.pageId = pageInfo.getId(); this.pageName = pageInfo.getPageName(); this.postList = postList; this.goodCount = pageInfo.getGoodCount(); From 43defcdb7dea0c2f9f306b6603718932f2653587 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Thu, 12 Oct 2023 14:37:47 +0900 Subject: [PATCH 016/144] =?UTF-8?q?Feat=20:=20=EA=B8=80=20=ED=9E=88?= =?UTF-8?q?=EC=8A=A4=ED=86=A0=EB=A6=AC=20=EC=A1=B0=ED=9A=8C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 특정 post의 히스토리 조회 기능을 구현하였습니다. - 페이지네이션을 적용하여 5개씩 response에 담았습니다. --- .../wekiki/history/HistoryJPARepository.java | 9 +++++ .../techcampus/wekiki/post/PostResponse.java | 38 +++++++++++++++++++ .../wekiki/post/PostRestController.java | 11 ++++++ .../techcampus/wekiki/post/PostService.java | 29 ++++++++++++++ 4 files changed, 87 insertions(+) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java index 8c13527c..2e22198e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java @@ -2,6 +2,8 @@ import com.kakao.techcampus.wekiki.group.member.GroupMember; import com.kakao.techcampus.wekiki.post.Post; +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.Modifying; import org.springframework.data.jpa.repository.Query; @@ -18,4 +20,11 @@ public interface HistoryJPARepository extends JpaRepository { void deleteByPostId(@Param("postId") Long postId); List findAllByGroupMember(GroupMember groupMember); + + @Query("SELECT h FROM History h JOIN FETCH h.groupMember m WHERE h.post.id = :postId ORDER BY h.created_at DESC") + Page findHistoryWithMemberByPostId(@Param("postId") Long postId, Pageable pageable); + + @Query("SELECT h FROM History h WHERE h.post.id = :postId ORDER BY h.created_at DESC") + Page findHistoryByPostId(@Param("postId") Long postId, Pageable pageable); + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java index 7acba5fc..5ce54c79 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java @@ -1,9 +1,13 @@ package com.kakao.techcampus.wekiki.post; +import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.page.PageInfo; import lombok.Getter; import lombok.Setter; +import java.time.LocalDateTime; +import java.util.List; + public class PostResponse { @Getter @@ -49,4 +53,38 @@ public deletePostDTO(Post post){ } } + @Getter + @Setter + public static class getPostHistoryDTO{ + + Long postId; + String currentTitle; + List historyList; + + public getPostHistoryDTO(Post post,List historyList){ + this.postId = post.getId(); + this.currentTitle = post.getTitle(); + this.historyList = historyList; + } + + @Getter @Setter + public static class historyDTO{ + + //Long memberId; + //String nickName; + Long historyId; + String title; + String content; + LocalDateTime created_at; + + public historyDTO(History history){ + this.historyId = history.getId(); + this.title = history.getTitle(); + this.content = history.getContent(); + this.created_at = history.getCreated_at(); + } + + } + } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java index 228004d9..040d36f9 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java @@ -48,5 +48,16 @@ public ResponseEntity deletePost(@PathVariable Long postid){ return ResponseEntity.ok(ApiUtils.success(response)); } + @GetMapping("/{postid}/history") + public ResponseEntity getPostHistory(@PathVariable Long postid + ,@RequestParam(value = "page", defaultValue = "1") int page){ + + Long tempUserId = 1L; + + PostResponse.getPostHistoryDTO response = postService.getPostHistory(tempUserId, postid, page - 1); + + return ResponseEntity.ok(ApiUtils.success(response)); + } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index ff4733f0..c0797e9a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -8,11 +8,14 @@ import com.kakao.techcampus.wekiki.page.PageInfo; import com.kakao.techcampus.wekiki.page.PageJPARepository; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.List; +import java.util.stream.Collectors; @RequiredArgsConstructor @Service @@ -21,6 +24,7 @@ public class PostService { private final PageJPARepository pageJPARepository; private final PostJPARepository postJPARepository; private final HistoryJPARepository historyJPARepository; + final int HISTORY_COUNT = 5; @Transactional public PostResponse.createPostDTO createPost(Long userId,Long pageId, Long parentPostId, int order, String title, String content){ @@ -103,6 +107,31 @@ public PostResponse.modifyPostDTO modifyPost(Long userId, Long postId , String t } + @Transactional + public PostResponse.getPostHistoryDTO getPostHistory(Long userId, Long postId , int pageNo){ + + // 1. userId로 user객체 가져오기 + + // 2. GroupMember인지 체크하기 + + // 3. 존재하는 포스트인지 체크 + Post post = postJPARepository.findById(postId).orElseThrow( + () -> new ApplicationException(ErrorCode.POST_NOT_FOUND)); + + // 4. 해당 PostId로 history 모두 가져오기 시간순 + 페이지네이션 + // memberId, nickName, historyId,title, content, created_at (TODO : 나중에 멤버 추가하기 + fetch join 추가) + PageRequest pageRequest = PageRequest.of(pageNo, HISTORY_COUNT); + //Page historys = historyJPARepository.findHistoryWithMemberByPostId(postId, pageRequest); + Page historys = historyJPARepository.findHistoryByPostId(postId, pageRequest); + + + // 5. DTO로 return + List historyDTOs = historys.getContent().stream(). + map(h -> new PostResponse.getPostHistoryDTO.historyDTO(h)).collect(Collectors.toList()); + return new PostResponse.getPostHistoryDTO(post,historyDTOs); + + } + @Transactional public PostResponse.deletePostDTO deletePost(Long userId, Long postId){ From cff115ca67791c60ef2cb171d986923681ca1d4c Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Thu, 12 Oct 2023 17:45:09 +0900 Subject: [PATCH 017/144] =?UTF-8?q?Feat=20:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=ED=82=A4=EC=9B=8C=EB=93=9C=20=EA=B2=80=EC=83=89=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=EC=97=90=EC=84=9C=20=ED=8E=98=EC=9D=B4=EC=A7=80=20con?= =?UTF-8?q?tent=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 페이지 키워드에 검색에서 페이지의 가장 위에 있는 post의 내용을 responseDTO의 content에 추가하였습니다. - post가 하나도 존재하지 않는 페이지는 빈 문자열을 반환해줍니다. --- .../wekiki/page/PageInfoResponse.java | 23 ++++++++++++++----- .../wekiki/page/PageRestController.java | 6 +++-- .../techcampus/wekiki/page/PageService.java | 22 ++++++++++++++---- .../wekiki/post/PostJPARepository.java | 9 ++++++++ 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index d46ce7e6..c7642a63 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -64,17 +64,28 @@ public hatePageDTO(PageInfo pageInfo){ @Getter @Setter public static class searchPageDTO{ - Long pageId; - String pageName; - //String contents; + List pages; - public searchPageDTO(PageInfo pageInfo){ - this.pageId = pageInfo.getId(); - this.pageName = pageInfo.getPageName(); + public searchPageDTO(List pageDTO){ + this.pages = pageDTO; } + @Getter @Setter + public static class pageDTO{ + + Long pageId; + String pageName; + String content; + + public pageDTO(PageInfo pageInfo ,String content){ + this.pageId = pageInfo.getId(); + this.pageName = pageInfo.getPageName(); + this.content = content; + } + } } + @Getter @Setter public static class getPageIndexDTO{ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index 01195f5a..3f09c1ea 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -135,11 +135,13 @@ public ResponseEntity getPageFromTitle(@PathVariable Long groupid,@RequestPar */ @GetMapping("/group/{groupid}/page/search") - public ResponseEntity searchPage(@PathVariable Long groupid,@RequestParam(value = "keyword" , defaultValue = "") String keyword, @RequestParam(value = "page", defaultValue = "1") int page) { + public ResponseEntity searchPage(@PathVariable Long groupid, + @RequestParam(value = "keyword" , defaultValue = "") String keyword, + @RequestParam(value = "page", defaultValue = "1") int page) { Long tempUserId = 1L; - List response = pageService.searchPage(page-1, keyword); + PageInfoResponse.searchPageDTO response = pageService.searchPage(page - 1, keyword); return ResponseEntity.ok(ApiUtils.success(response)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 80cc3454..9b8da816 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -13,6 +13,7 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; @@ -173,19 +174,32 @@ public PageInfoResponse.hatePageDTO hatePage(Long pageId , Long userId){ } @Transactional - public List searchPage(int pageNo, String keyword){ + public PageInfoResponse.searchPageDTO searchPage(int pageNo, String keyword){ // 1. groupId랑 userId로 Group 객체, User 객체 가져오기 (없으면 Exception) // 2. groupMember 존재하는지 확인 (없으면 Exception) - // 3. keyword로 존재하는 page title에 keyword를 가지고 있는 페이지들 다 가져오기 + // 3. keyword로 존재하는 page title에 keyword를 가지고 있는 페이지들 다 가져오기 (TODO : group 추가) PageRequest pageRequest = PageRequest.of(pageNo, PAGE_COUNT); Page pages = pageJPARepository.findPagesByTitleContainingKeyword(keyword, pageRequest); - // 4. pages로 DTO return - return pages.getContent().stream().map(pageInfo -> new PageInfoResponse.searchPageDTO(pageInfo)).collect(Collectors.toList()); + // 해당 Page들을 FK로 가지고 있는 Post들 중에 Orders가 1인 Post들 가져오기 + + List res = new ArrayList<>(); + for(PageInfo p : pages.getContent()){ + List posts = postJPARepository.findFirstPost(p.getId()); + if(posts.size() == 0){ + res.add(new PageInfoResponse.searchPageDTO.pageDTO(p,"")); + }else{ + res.add(new PageInfoResponse.searchPageDTO.pageDTO(p,posts.get(0).getContent())); + } + // TODO : 성능 개선이 필요하긴 할듯 + // posts.get(0)가 존재하면 DTO 만들어서 던지기 + 고려할 점 : post의 contents만 들고 오는 방식? (흠..) + } + // 4. pages로 DTO return + return new PageInfoResponse.searchPageDTO(res); } // ============================groupId 필요========================================================== diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java index e50a368a..765af4b3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java @@ -1,6 +1,9 @@ package com.kakao.techcampus.wekiki.post; import com.kakao.techcampus.wekiki.page.PageInfo; +import com.kakao.techcampus.wekiki.page.PageInfoResponse; +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.data.repository.query.Param; @@ -24,4 +27,10 @@ List findPostsByPageIdAndOrderGreaterThan( boolean existsByParentId(Long parentId); List findAllByGroupMember(GroupMember groupMember); + + // 해당 pageId를 가지고 있는 post들 중에 orders가 1인거 들고오기 + @Query("SELECT p FROM Post p WHERE p.pageInfo.id = :pageId AND p.orders = 1") + List findFirstPost(@Param("pageId") Long pageId); + + } From 144fc1b368475f2a2da7670012fb2e8a1ccccd37 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Fri, 13 Oct 2023 00:47:25 +0900 Subject: [PATCH 018/144] =?UTF-8?q?Feat=20:=20=ED=8E=98=EC=9D=B4=EC=A7=80/?= =?UTF-8?q?=EA=B8=80=20=EA=B4=80=EB=A0=A8=20url=20=EB=A7=A4=ED=95=91=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PageRestController에서 RequestMapping에 "/group/{groupid}/page"로 수정하였습니다. - PostRestController에서 RequestMapping에 "/group/{groupid}/post"로 수정하였습니다. --- .../wekiki/page/PageRestController.java | 34 +++++++++---------- .../wekiki/post/PostRestController.java | 10 +++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index 3f09c1ea..0e4615bd 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -9,7 +9,7 @@ import java.util.List; @RestController -@RequestMapping +@RequestMapping("/group/{groupid}/page") @RequiredArgsConstructor public class PageRestController { @@ -20,8 +20,8 @@ public class PageRestController { */ - @GetMapping("/page/{pageid}") - public ResponseEntity getPageFromId(@PathVariable Long pageid) { + @GetMapping("/{pageid}") + public ResponseEntity getPageFromId(@PathVariable Long groupid,@PathVariable Long pageid) { Long tempUserId = 1L; @@ -36,8 +36,8 @@ public ResponseEntity getPageFromId(@PathVariable Long pageid) { */ - @PostMapping("/page/create") - public ResponseEntity createPage(@RequestBody PageInfoRequest.createPageDTO request) { + @PostMapping("/create") + public ResponseEntity createPage(@PathVariable Long groupid,@RequestBody PageInfoRequest.createPageDTO request) { // TODO : JWT에서 userId 꺼내도록 수정 Long tempUserId = 1L; @@ -52,8 +52,8 @@ public ResponseEntity createPage(@RequestBody PageInfoRequest.createPageDTO r */ - @DeleteMapping("/page/{pageid}") - public ResponseEntity deletePage(@PathVariable Long pageid) { + @DeleteMapping("/{pageid}") + public ResponseEntity deletePage(@PathVariable Long groupid,@PathVariable Long pageid) { Long tempUserId = 1L; @@ -67,8 +67,8 @@ public ResponseEntity deletePage(@PathVariable Long pageid) { */ - @PostMapping("/page/{pageid}/like") - public ResponseEntity likePage(@PathVariable Long pageid) { + @PostMapping("/{pageid}/like") + public ResponseEntity likePage(@PathVariable Long groupid,@PathVariable Long pageid) { // TODO : JWT에서 userId 꺼내도록 수정 Long tempUserId = 1L; @@ -83,8 +83,8 @@ public ResponseEntity likePage(@PathVariable Long pageid) { */ - @PostMapping("/page/{pageid}/hate") - public ResponseEntity hatePage(@PathVariable Long pageid) { + @PostMapping("/{pageid}/hate") + public ResponseEntity hatePage(@PathVariable Long groupid,@PathVariable Long pageid) { // TODO : JWT에서 userId 꺼내도록 수정 Long tempUserId = 1L; @@ -100,8 +100,8 @@ public ResponseEntity hatePage(@PathVariable Long pageid) { */ - @GetMapping("/page/{pageid}/index") - public ResponseEntity getPageIndex(@PathVariable Long pageid) { + @GetMapping("/{pageid}/index") + public ResponseEntity getPageIndex(@PathVariable Long groupid,@PathVariable Long pageid) { Long tempUserId = 1L; @@ -118,7 +118,7 @@ public ResponseEntity getPageIndex(@PathVariable Long pageid) { 페이지 제목으로 페이지 조회 */ - @GetMapping("/group/{groupid}/page") + @GetMapping public ResponseEntity getPageFromTitle(@PathVariable Long groupid,@RequestParam(value = "title") String title) { Long tempUserId = 1L; @@ -134,7 +134,7 @@ public ResponseEntity getPageFromTitle(@PathVariable Long groupid,@RequestPar */ - @GetMapping("/group/{groupid}/page/search") + @GetMapping("/search") public ResponseEntity searchPage(@PathVariable Long groupid, @RequestParam(value = "keyword" , defaultValue = "") String keyword, @RequestParam(value = "page", defaultValue = "1") int page) { @@ -151,7 +151,7 @@ public ResponseEntity searchPage(@PathVariable Long groupid, */ - @GetMapping("/group/{groupid}/page/recent") + @GetMapping("/recent") public ResponseEntity getRecentPage(@PathVariable Long groupid){ Long tempUserId = 1L; @@ -166,7 +166,7 @@ public ResponseEntity getRecentPage(@PathVariable Long groupid){ */ - @GetMapping("/group/{groupid}/page/link") + @GetMapping("/link") public ResponseEntity getPageLink(@PathVariable Long groupid, @RequestParam(value = "title") String title){ Long tempUserId = 1L; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java index 040d36f9..afb3d44a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java @@ -11,14 +11,14 @@ import java.util.List; @RestController -@RequestMapping("/post") +@RequestMapping("/group/{groupid}/post") @RequiredArgsConstructor public class PostRestController { private final PostService postService; @PostMapping("/create") - public ResponseEntity createPost(@RequestBody PostRequest.createPostDTO request) { + public ResponseEntity createPost(@PathVariable Long groupid, @RequestBody PostRequest.createPostDTO request) { Long tempUserId = 1L; @@ -29,7 +29,7 @@ public ResponseEntity createPost(@RequestBody PostRequest.createPostDTO reque } @PutMapping("/modify") - public ResponseEntity modifyPost(@RequestBody PostRequest.modifyPostDTO request){ + public ResponseEntity modifyPost(@PathVariable Long groupid,@RequestBody PostRequest.modifyPostDTO request){ Long tempUserId = 1L; @@ -39,7 +39,7 @@ public ResponseEntity modifyPost(@RequestBody PostRequest.modifyPostDTO reque } @DeleteMapping("/{postid}") - public ResponseEntity deletePost(@PathVariable Long postid){ + public ResponseEntity deletePost(@PathVariable Long groupid, @PathVariable Long postid){ Long tempUserId = 1L; @@ -49,7 +49,7 @@ public ResponseEntity deletePost(@PathVariable Long postid){ } @GetMapping("/{postid}/history") - public ResponseEntity getPostHistory(@PathVariable Long postid + public ResponseEntity getPostHistory(@PathVariable Long groupid,@PathVariable Long postid ,@RequestParam(value = "page", defaultValue = "1") int page){ Long tempUserId = 1L; From 7a031ca7e0c6c90581879229eaff848eadd73dab Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 13 Oct 2023 19:11:53 +0900 Subject: [PATCH 019/144] =?UTF-8?q?Feat:=20=EC=B4=88=EB=8C=80=20=EB=A7=81?= =?UTF-8?q?=ED=81=AC=20=ED=8C=90=EB=B3=84=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 초대 링크 식별 후 GroupId 반환 - 휘발시킬지 말지 고민 중 --- wekiki/build.gradle | 3 ++ .../wekiki/group/GroupJPARepository.java | 11 ++++- .../wekiki/group/GroupRestController.java | 12 ++++-- .../techcampus/wekiki/group/GroupService.java | 42 +++++++++++++++---- .../ValidateInvitationResponseDTO.java | 14 +++++++ .../wekiki/group/invitation/Invitation.java | 28 +++++++++++++ .../closedGroup/UnOfficialClosedGroup.java | 4 ++ 7 files changed, 100 insertions(+), 14 deletions(-) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/ValidateInvitationResponseDTO.java create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java diff --git a/wekiki/build.gradle b/wekiki/build.gradle index 5932b105..24da5e45 100644 --- a/wekiki/build.gradle +++ b/wekiki/build.gradle @@ -57,6 +57,9 @@ dependencies { // 유효성 검사 implementation 'org.springframework.boot:spring-boot-starter-validation' + // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 + implementation 'org.apache.commons:commons-lang3:3.12.0' + // 개발 편의용 compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java index ba560917..b7e351df 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java @@ -2,6 +2,7 @@ import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.SearchGroupDTO; import com.kakao.techcampus.wekiki.group.officialGroup.OfficialGroup; +import com.kakao.techcampus.wekiki.group.unOfficialGroup.closedGroup.UnOfficialClosedGroup; import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -25,5 +26,13 @@ public interface GroupJPARepository extends JpaRepository { /* 비공식 공개 그룹 상세 조회 */ - UnOfficialOpenedGroup findUnOfficialOpenedGroupById(Long id); + @Query("SELECT g FROM UnOfficialOpenedGroup g WHERE g.id = :id") + UnOfficialOpenedGroup findUnOfficialOpenedGroupById(@Param("id") Long id); + + + /* + 초대 링크 + */ + @Query("SELECT g FROM UnOfficialClosedGroup g WHERE g.id = :id") + UnOfficialClosedGroup findUnOfficialClosedGroupById(@Param("id") Long id); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java index ef3e2ba2..cb4da5bd 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java @@ -4,10 +4,7 @@ import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.CreateUnOfficialGroupRequestDTO; import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.JoinGroupRequestDTO; import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.UpdateMyGroupPageDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.CreateUnOfficialGroupResponseDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.MyGroupInfoResponseDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.SearchGroupDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.SearchGroupInfoDTO; +import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.*; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -90,6 +87,13 @@ public ResponseEntity joinGroup(@PathVariable("groupId") Long groupId, JoinGr /* 그룹 초대 */ + @GetMapping("/{invitationLink}") + public ResponseEntity ValidateInvitation(@PathVariable String invitationLink) { + + ValidateInvitationResponseDTO responseDTO = groupService.ValidateInvitation(invitationLink); + + return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); + } /* 그룹 내 본인 정보 조회 diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java index 779b1eb8..9d33708b 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java @@ -3,10 +3,7 @@ import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.CreateUnOfficialGroupRequestDTO; import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.JoinGroupRequestDTO; import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.UpdateMyGroupPageDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.CreateUnOfficialGroupResponseDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.MyGroupInfoResponseDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.SearchGroupDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.SearchGroupInfoDTO; +import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.*; import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.member.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.group.member.InactiveGroupMember; @@ -37,6 +34,7 @@ public class GroupService { private final MemberJPARepository memberJPARepository; private final PostJPARepository postJPARepository; private final HistoryJPARepository historyJPARepository; + /* 비공식 그룹 생성 */ @@ -54,7 +52,7 @@ public CreateUnOfficialGroupResponseDTO createUnOfficialGroup(CreateUnOfficialGr // MemberId로부터 Member 찾기 // TODO: 예외 처리 구현 - Member member = memberJPARepository.findById(memberId).orElse(null); + Member member = getMemberById(memberId); // GroupMember 생성 ActiveGroupMember groupMember = buildGroupMember(member, group, requestDTO.groupNickName()); @@ -128,6 +126,28 @@ public SearchGroupDTO searchGroupByKeyword(String keyword) { return new SearchGroupDTO(officialGroups, unOfficialOpenedGroups); } + /* + 비공식 비공개 그룹 초대 링크 확인 + - 확인 후 해당하는 그룹 Id 반환 + - 가입 url 생성 후 그룹 가입 API + */ + public ValidateInvitationResponseDTO ValidateInvitation(String invitationLink) { + + String[] invitation = invitationLink.split("/"); + + Long groupId = Long.parseLong(invitation[0]); + String invitationCode = invitation[1]; + + UnOfficialClosedGroup group = groupJPARepository.findUnOfficialClosedGroupById(groupId); + + // 초대 코드가 틀린 경우 + if(!group.getInvitation().getInvitationCode().equals(invitationCode)) { + // 예외 처리 + } + + return new ValidateInvitationResponseDTO(groupId); + } + /* 비공식 공개 그룹 상세 정보 조회 */ @@ -151,7 +171,7 @@ public void groupEntry(Long groupId, String entrancePassword) { */ public void joinGroup(Long groupId, Long memberId, JoinGroupRequestDTO requestDTO) { // 회원 정보 확인 - Member member = memberJPARepository.findById(memberId).orElse(null); + Member member = getMemberById(memberId); // 그룹 정보 확인 // TODO: Redis 활용 @@ -177,7 +197,7 @@ public void joinGroup(Long groupId, Long memberId, JoinGroupRequestDTO requestDT */ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { // 회원 정보 확인 - Member member = memberJPARepository.findById(memberId).orElse(null); + Member member = getMemberById(memberId); // 그룹 정보 확인 // TODO: Redis 활용 @@ -199,7 +219,7 @@ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { */ public void updateMyGroupPage(Long groupId, Long memberId, UpdateMyGroupPageDTO requestDTO) { // 회원 정보 확인 - Member member = memberJPARepository.findById(memberId).orElse(null); + Member member = getMemberById(memberId); // 그룹 정보 확인 // TODO: Redis 활용 @@ -221,7 +241,7 @@ public void updateMyGroupPage(Long groupId, Long memberId, UpdateMyGroupPageDTO */ public void leaveGroup(Long groupId, Long memberId) { // 회원 정보 확인 - Member member = memberJPARepository.findById(memberId).orElse(null); + Member member = getMemberById(memberId); // 그룹 정보 확인 // TODO: Redis 활용 @@ -248,4 +268,8 @@ public void leaveGroup(Long groupId, Long memberId) { groupMemberJPARepository.save(inactiveGroupMember); historyJPARepository.saveAll(historyList); } + + public Member getMemberById(Long memberId) { + return memberJPARepository.findById(memberId).orElse(null); + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/ValidateInvitationResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/ValidateInvitationResponseDTO.java new file mode 100644 index 00000000..bb99b6ea --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/ValidateInvitationResponseDTO.java @@ -0,0 +1,14 @@ +package com.kakao.techcampus.wekiki.group.groupDTO.responseDTO; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ValidateInvitationResponseDTO { + private Long groupId; + + public ValidateInvitationResponseDTO(Long groupId) { + this.groupId = groupId; + } +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java new file mode 100644 index 00000000..f7ff7d99 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java @@ -0,0 +1,28 @@ +package com.kakao.techcampus.wekiki.group.invitation; + +import jakarta.persistence.Column; +import lombok.*; +import org.apache.commons.lang3.RandomStringUtils; + +import java.time.LocalDateTime; + +@Getter +@Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Invitation { + + @Column(unique = true) + private String invitationCode; + private String invitationLink; + // private LocalDateTime expired_at; + + private static final int INVITE_CODE_LENGTH = 32; + // private static final Duration DEFAULT_EXPIRED_DAYS = Duration.ofDays(7); + + @Builder + public Invitation(Long groupId) { + this.invitationCode = RandomStringUtils.randomAlphanumeric(INVITE_CODE_LENGTH); + this.invitationLink = groupId + "/" + invitationCode; + // this.expired_at = LocalDateTime.now().plusMinutes(DEFAULT_EXPIRED_DAYS.toMinutes()); + } +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java index 44fb4ab2..6c786668 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java @@ -1,6 +1,7 @@ package com.kakao.techcampus.wekiki.group.unOfficialGroup.closedGroup; import com.kakao.techcampus.wekiki.group.Group; +import com.kakao.techcampus.wekiki.group.invitation.Invitation; import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; import lombok.AccessLevel; @@ -16,8 +17,11 @@ @DiscriminatorValue("un_official_closed_group") public class UnOfficialClosedGroup extends Group { + private Invitation invitation; + @Builder(builderMethodName = "unOfficialClosedGroupBuilder") public UnOfficialClosedGroup(Long id, String groupName, String groupProfileImage, int memberCount, LocalDateTime created_at) { super(id, groupName, groupProfileImage, memberCount, created_at); + this.invitation = Invitation.builder().groupId(id).build(); } } From 0c00ba518d4b501555be1c1bc2ca2a043c0f977e Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 14 Oct 2023 13:13:25 +0900 Subject: [PATCH 020/144] =?UTF-8?q?Feat=20:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1,=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 특정 post에 댓글을 달 수 있도록 구현하였습니다 - 특정 post에 달려있는 댓글들을 최신 순으로 10개씩 페이지네이션으로 조회가능하도록 구현하였습니다. --- .../wekiki/comment/CommentController.java | 42 +++++++++++ .../wekiki/comment/CommentJPARepository.java | 17 +++++ .../wekiki/comment/CommentRequest.java | 14 ++++ .../wekiki/comment/CommentResponse.java | 58 +++++++++++++++ .../wekiki/comment/CommentService.java | 74 +++++++++++++++++++ .../wekiki/page/PageJPARepository.java | 2 + .../wekiki/post/PostJPARepository.java | 2 + 7 files changed, 209 insertions(+) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentRequest.java create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java new file mode 100644 index 00000000..8ae36582 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java @@ -0,0 +1,42 @@ +package com.kakao.techcampus.wekiki.comment; + + +import com.kakao.techcampus.wekiki._core.utils.ApiUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/group/{groupid}/post/{postid}/comment") +@RequiredArgsConstructor +public class CommentController { + + private final CommentService commentService; + + @GetMapping + public ResponseEntity getComment(@PathVariable Long groupid, + @PathVariable Long postid, + @RequestParam(value = "page", defaultValue = "1") int page){ + + Long tempUserId = 1L; + + CommentResponse.getCommentDTO response = commentService.getComment(tempUserId, groupid, postid, page-1); + + return ResponseEntity.ok(ApiUtils.success(response)); + } + + @PostMapping + public ResponseEntity createComment(@PathVariable Long groupid, + @PathVariable Long postid, + @RequestBody CommentRequest.createComment request){ + + Long tempUserId = 1L; + + CommentResponse.createCommentDTO response = commentService.createComment(tempUserId, groupid, postid, request.getContent()); + + return ResponseEntity.ok(ApiUtils.success(response)); + } + + + +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java new file mode 100644 index 00000000..a40c1be8 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java @@ -0,0 +1,17 @@ +package com.kakao.techcampus.wekiki.comment; + +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.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +@Repository +public interface CommentJPARepository extends JpaRepository { + + @Query("SELECT c FROM Comment c WHERE c.post.id = :postId ORDER BY c.created_at") + Page findCommentsByPostId(@Param("postId") Long postId, Pageable pageable); + + +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentRequest.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentRequest.java new file mode 100644 index 00000000..ae2466ab --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentRequest.java @@ -0,0 +1,14 @@ +package com.kakao.techcampus.wekiki.comment; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +public class CommentRequest { + + @Getter + public static class createComment{ + private String content; + } + +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java new file mode 100644 index 00000000..7c30f242 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java @@ -0,0 +1,58 @@ +package com.kakao.techcampus.wekiki.comment; + +import com.kakao.techcampus.wekiki.post.Post; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; +import java.util.List; + +public class CommentResponse { + + @Getter + @Setter + public static class createCommentDTO{ + + Long commentId; + String content; + LocalDateTime createdAt; + String nickName; + + public createCommentDTO(Comment comment, String nickName){ + this.commentId = comment.getId(); + this.content = comment.getContent(); + this.createdAt = comment.getCreated_at(); + this.nickName = nickName; + } + } + + @Getter + @Setter + public static class getCommentDTO{ + + Long postId; + List comments; + + public getCommentDTO(Post post, List comments){ + this.postId = post.getId(); + this.comments = comments; + } + + @Getter @Setter + public static class commentDTO{ + Long commentId; + //String nickName; + String content; + LocalDateTime createdAt; + + public commentDTO(Comment comment){ + this.commentId = comment.getId(); + //this.nickName = "temp"; + this.content = comment.getContent(); + this.createdAt = comment.getCreated_at(); + } + } + + } + +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java new file mode 100644 index 00000000..127bf161 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java @@ -0,0 +1,74 @@ +package com.kakao.techcampus.wekiki.comment; + +import com.kakao.techcampus.wekiki._core.errors.ApplicationException; +import com.kakao.techcampus.wekiki._core.errors.ErrorCode; +import com.kakao.techcampus.wekiki.post.Post; +import com.kakao.techcampus.wekiki.post.PostJPARepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@Service +public class CommentService { + + private final CommentJPARepository commentJPARepository; + private final PostJPARepository postJPARepository; + + final int COMMENT_COUNT = 10; + + @Transactional + public CommentResponse.getCommentDTO getComment(Long userId, Long groupId, Long postId, int pageNo){ + + // 1. userId로 user 객체 들고오기 + + // 2. groupMember 맞는지 확인하기 + + // 3. post 존재하는지 예외처리 + Post post = postJPARepository.findById(postId).orElseThrow( + () -> new ApplicationException(ErrorCode.POST_NOT_FOUND)); + + // 4. postId로 Comment 다 가져오기 + Pageable pageable = PageRequest.of(pageNo, COMMENT_COUNT); + Page comments = commentJPARepository.findCommentsByPostId(postId, pageable); + + // 5. return DTO + List commentDTOs = comments.getContent().stream().map(c -> new CommentResponse.getCommentDTO.commentDTO(c)) + .collect(Collectors.toList()); + return new CommentResponse.getCommentDTO(post,commentDTOs); + } + + @Transactional + public CommentResponse.createCommentDTO createComment(Long userId, Long groupId, Long postId, String content){ + + // 1. userId로 user 객체 들고오기 + + // 2. groupMember 맞는지 확인하기 + + // 3. post 존재하는지 예외처리 + Post post = postJPARepository.findById(postId).orElseThrow( + () -> new ApplicationException(ErrorCode.POST_NOT_FOUND)); + + // 4. comment 생성 + Comment comment = Comment.builder() + //.member() + .post(post) + .content(content) + .created_at(LocalDateTime.now()) + .build(); + Comment savedComment = commentJPARepository.save(comment); + + // 5. return DTO + return new CommentResponse.createCommentDTO(savedComment,"temp"); + } + + + +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java index 63bf4159..acfd5183 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java @@ -5,10 +5,12 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; import java.util.List; import java.util.Optional; +@Repository public interface PageJPARepository extends JpaRepository { @Query("SELECT p FROM PageInfo p WHERE p.pageName LIKE :keyword%") diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java index 765af4b3..91914a67 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java @@ -8,9 +8,11 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import com.kakao.techcampus.wekiki.group.member.GroupMember; +import org.springframework.stereotype.Repository; import java.util.List; +@Repository public interface PostJPARepository extends JpaRepository { @Query("SELECT p FROM Post p WHERE p.pageInfo.id = :pageId AND p.orders >= :orders") From f488f9b2a429f2bc095e4cb41723a35b4fd01ff7 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 14 Oct 2023 13:45:24 +0900 Subject: [PATCH 021/144] =?UTF-8?q?Feat=20:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 특정 댓글을 댓글의 주인만 수정, 삭제가능하도록 구현하였습니다. - 수정시에 기존 댓글이랑 동일한 데이터가 일때 예외처리 하였습니다. --- .../wekiki/_core/errors/ErrorCode.java | 6 ++- .../techcampus/wekiki/comment/Comment.java | 4 ++ .../wekiki/comment/CommentController.java | 31 +++++++++-- .../wekiki/comment/CommentRequest.java | 4 ++ .../wekiki/comment/CommentResponse.java | 28 ++++++++++ .../wekiki/comment/CommentService.java | 52 +++++++++++++++++++ 6 files changed, 121 insertions(+), 4 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java index 0107a16a..7cc9e8a8 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java @@ -14,7 +14,11 @@ public enum ErrorCode { PARENT_POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST-001","존재하지 않는 PARENT POST 입니다."), POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST-002","존재하지 않는 POST 입니다."), POST_SAME_DATE(HttpStatus.BAD_REQUEST,"POST-003","동일한 데이터 입니다."), - HAVE_CHILD_POST(HttpStatus.BAD_REQUEST,"POST-004","하위 포스트가 존재하는 포스트는 삭제가 불가능합니다."); + HAVE_CHILD_POST(HttpStatus.BAD_REQUEST,"POST-004","하위 포스트가 존재하는 포스트는 삭제가 불가능합니다."), + COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND,"COMMENT-001" , "존재하지 않는 댓글 입니다."), + COMMENT_MEMBER_INCONSISTENCY(HttpStatus.BAD_REQUEST,"COMMENT-002" , "본인이 쓴 댓글만 삭제가 가능합니다."), + COMMENT_SAME_DATE(HttpStatus.BAD_REQUEST,"COMMENT-003","동일한 데이터 입니다."); + /* diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java index e06f18e4..398d5dcb 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java @@ -34,4 +34,8 @@ public Comment(Long id, Member member, Post post, String content, LocalDateTime this.content = content; this.created_at = created_at; } + + public void updateContent(String newContent){ + this.content = newContent; + } } \ No newline at end of file diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java index 8ae36582..d21144f6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java @@ -7,13 +7,13 @@ import org.springframework.web.bind.annotation.*; @RestController -@RequestMapping("/group/{groupid}/post/{postid}/comment") +@RequestMapping("/group/{groupid}") @RequiredArgsConstructor public class CommentController { private final CommentService commentService; - @GetMapping + @GetMapping("/post/{postid}/comment") public ResponseEntity getComment(@PathVariable Long groupid, @PathVariable Long postid, @RequestParam(value = "page", defaultValue = "1") int page){ @@ -25,7 +25,7 @@ public ResponseEntity getComment(@PathVariable Long groupid, return ResponseEntity.ok(ApiUtils.success(response)); } - @PostMapping + @PostMapping("/post/{postid}/comment") public ResponseEntity createComment(@PathVariable Long groupid, @PathVariable Long postid, @RequestBody CommentRequest.createComment request){ @@ -37,6 +37,31 @@ public ResponseEntity createComment(@PathVariable Long groupid, return ResponseEntity.ok(ApiUtils.success(response)); } + @DeleteMapping("/comment/{commentid}") + public ResponseEntity deleteComment(@PathVariable Long groupid, + @PathVariable Long commentid){ + + Long tempUserId = 1L; + + CommentResponse.deleteCommentDTO response = commentService.deleteComment(tempUserId, groupid, commentid); + + return ResponseEntity.ok(ApiUtils.success(response)); + + } + + @PatchMapping("/comment/{commentid}") + public ResponseEntity updateComment(@PathVariable Long groupid, + @PathVariable Long commentid, + @RequestBody CommentRequest.updateComment request){ + + Long tempUserId = 1L; + + CommentResponse.updateCommentDTO response = commentService.updateComment(tempUserId, groupid, commentid, request.getContent()); + + return ResponseEntity.ok(ApiUtils.success(response)); + + } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentRequest.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentRequest.java index ae2466ab..a9f5fb8f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentRequest.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentRequest.java @@ -11,4 +11,8 @@ public static class createComment{ private String content; } + @Getter + public static class updateComment{ + private String content; + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java index 7c30f242..c70d3269 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java @@ -55,4 +55,32 @@ public commentDTO(Comment comment){ } + @Getter + @Setter + public static class deleteCommentDTO{ + + Long commentId; + String content; + + + public deleteCommentDTO(Comment comment){ + this.commentId = comment.getId(); + this.content = comment.getContent(); + } + } + + @Getter + @Setter + public static class updateCommentDTO{ + + Long commentId; + String newContent; + + + public updateCommentDTO(Comment comment){ + this.commentId = comment.getId(); + this.newContent = comment.getContent(); + } + } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java index 127bf161..4868839c 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java @@ -69,6 +69,58 @@ public CommentResponse.createCommentDTO createComment(Long userId, Long groupId, return new CommentResponse.createCommentDTO(savedComment,"temp"); } + @Transactional + public CommentResponse.deleteCommentDTO deleteComment(Long memberId, Long groupId, Long commentId){ + + // 1. userId로 user 객체 들고오기 + + // 2. groupMember 맞는지 확인하기 + + // 3. comment 존재하는지 예외처리 + Comment comment = commentJPARepository.findById(commentId).orElseThrow( + () -> new ApplicationException(ErrorCode.COMMENT_NOT_FOUND)); + + // 4. comment 쓴 사람이 삭제하는 유저랑 일치하는지 확인 +// if(comment.getMember().getId() != memberId){ +// throw new ApplicationException(ErrorCode.COMMENT_MEMBER_INCONSISTENCY); +// } + + // 5. comment 삭제 + CommentResponse.deleteCommentDTO response = new CommentResponse.deleteCommentDTO(comment); + commentJPARepository.delete(comment); + + // 6. return DTO + return response; + } + + @Transactional + public CommentResponse.updateCommentDTO updateComment(Long memberId, Long groupId, Long commentId, String updateContent){ + + // 1. userId로 user 객체 들고오기 + + // 2. groupMember 맞는지 확인하기 + + // 3. comment 존재하는지 예외처리 + Comment comment = commentJPARepository.findById(commentId).orElseThrow( + () -> new ApplicationException(ErrorCode.COMMENT_NOT_FOUND)); + + // 4. comment 쓴 사람이 수정하는 유저랑 일치하는지 확인 +// if(comment.getMember().getId() != memberId){ +// throw new ApplicationException(ErrorCode.COMMENT_MEMBER_INCONSISTENCY); +// } + + // 5. 내용 동일하면 exception + if(comment.getContent().equals(updateContent)){ + throw new ApplicationException(ErrorCode.COMMENT_SAME_DATE); + } + + // 6. 수정 + comment.updateContent(updateContent); + + // 7. return DTO + return new CommentResponse.updateCommentDTO(comment); + } + } From a45ebbfa0cf199c4c34e06d2a7c96ec377de0478 Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Sat, 14 Oct 2023 13:51:27 +0900 Subject: [PATCH 022/144] =?UTF-8?q?Feat=20:=20CORS=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20=ED=8C=8C=EC=9D=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20-=20CORS=20=EB=AC=B8=EC=A0=9C=EB=A5=BC=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20Filter=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80.=20-=20=ED=98=84=EC=9E=AC=EB=8A=94=20?= =?UTF-8?q?=EB=AA=A8=EB=93=A0=20url=EC=97=90=20=EB=8C=80=ED=95=B4=20?= =?UTF-8?q?=EC=97=B4=EC=96=B4=EB=91=90=EC=97=88=EC=8A=B5=EB=8B=88=EB=8B=A4?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wekiki/_core/utils/CORSFilter.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/CORSFilter.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/CORSFilter.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/CORSFilter.java new file mode 100644 index 00000000..7420bd9e --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/CORSFilter.java @@ -0,0 +1,44 @@ +package com.kakao.techcampus.wekiki._core.utils; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class CORSFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + Filter.super.init(filterConfig); + } + + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) req; + HttpServletResponse response = (HttpServletResponse) res; + + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Methods","*"); + response.setHeader("Access-Control-Max-Age", "3600"); + response.setHeader("Access-Control-Allow-Headers", + "Origin, X-Requested-With, Content-Type, Accept, Authorization"); + + if("OPTIONS".equalsIgnoreCase(request.getMethod())) { + response.setStatus(HttpServletResponse.SC_OK); + }else { + chain.doFilter(req, res); + } + } + + @Override + public void destroy() { + Filter.super.destroy(); + } +} From 62e8e22f544b92419c326fc91de50361133632ef Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sat, 14 Oct 2023 16:17:51 +0900 Subject: [PATCH 023/144] =?UTF-8?q?Feat:=20=EA=B7=B8=EB=A3=B9=20=EC=B4=88?= =?UTF-8?q?=EB=8C=80=20=EB=A7=81=ED=81=AC=20=ED=99=95=EC=9D=B8=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 비공식 비공개 그룹 초대 링크 확인 기능 구현 --- .../wekiki/group/GroupJPARepository.java | 4 ++++ .../wekiki/group/GroupRestController.java | 15 ++++++++++++-- .../techcampus/wekiki/group/GroupService.java | 20 +++++++++++++------ .../GetInvitationLinkResponseDTO.java | 15 ++++++++++++++ .../groupDTO/responseDTO/SearchGroupDTO.java | 3 ++- 5 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/GetInvitationLinkResponseDTO.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java index b7e351df..6db0b7e3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java @@ -1,6 +1,7 @@ package com.kakao.techcampus.wekiki.group; import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.SearchGroupDTO; +import com.kakao.techcampus.wekiki.group.invitation.Invitation; import com.kakao.techcampus.wekiki.group.officialGroup.OfficialGroup; import com.kakao.techcampus.wekiki.group.unOfficialGroup.closedGroup.UnOfficialClosedGroup; import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; @@ -35,4 +36,7 @@ public interface GroupJPARepository extends JpaRepository { */ @Query("SELECT g FROM UnOfficialClosedGroup g WHERE g.id = :id") UnOfficialClosedGroup findUnOfficialClosedGroupById(@Param("id") Long id); + + @Query("SELECT g.invitation FROM UnOfficialClosedGroup g WHERE g.id = :id") + Invitation findInvitationLinkByGroupId(@Param("id") Long id); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java index cb4da5bd..7fb40501 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java @@ -83,9 +83,20 @@ public ResponseEntity joinGroup(@PathVariable("groupId") Long groupId, JoinGr return ResponseEntity.ok().body(ApiUtils.success(null)); } - + + /* + 그룹 초대링크 확인 + */ + @GetMapping("/{groupId}/invitationLink") + public ResponseEntity getInvitationLink(@PathVariable("groupId") Long groupId) { + + GetInvitationLinkResponseDTO responseDTO = groupService.getGroupInvitationLink(groupId); + + return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); + } + /* - 그룹 초대 + 그룹 초대링크 유효성 검사(?) */ @GetMapping("/{invitationLink}") public ResponseEntity ValidateInvitation(@PathVariable String invitationLink) { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java index 9d33708b..c6050e5a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java @@ -4,6 +4,7 @@ import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.JoinGroupRequestDTO; import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.UpdateMyGroupPageDTO; import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.*; +import com.kakao.techcampus.wekiki.group.invitation.Invitation; import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.member.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.group.member.InactiveGroupMember; @@ -17,6 +18,7 @@ import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -113,19 +115,25 @@ protected ActiveGroupMember buildGroupMember(Member member, Group group, String public SearchGroupDTO searchGroupByKeyword(String keyword) { // 공식 그룹 리스트 - List officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword); + Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword); // 비공식 공개 그룹 리스트 - List unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword); - - // 정렬 - officialGroups.sort(Comparator.comparing(OfficialGroup::getGroupName, String.CASE_INSENSITIVE_ORDER)); - unOfficialOpenedGroups.sort(Comparator.comparing(UnOfficialOpenedGroup::getGroupName, String.CASE_INSENSITIVE_ORDER)); + Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword); // TODO: 페이지네이션 필요 return new SearchGroupDTO(officialGroups, unOfficialOpenedGroups); } + /* + 초대 링크 확인 + */ + public GetInvitationLinkResponseDTO getGroupInvitationLink(Long groupId) { + + Invitation invitation = groupJPARepository.findInvitationLinkByGroupId(groupId); + + return new GetInvitationLinkResponseDTO(invitation); + } + /* 비공식 비공개 그룹 초대 링크 확인 - 확인 후 해당하는 그룹 Id 반환 diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/GetInvitationLinkResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/GetInvitationLinkResponseDTO.java new file mode 100644 index 00000000..333a7361 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/GetInvitationLinkResponseDTO.java @@ -0,0 +1,15 @@ +package com.kakao.techcampus.wekiki.group.groupDTO.responseDTO; + +import com.kakao.techcampus.wekiki.group.invitation.Invitation; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class GetInvitationLinkResponseDTO { + private String invitationLink; + + public GetInvitationLinkResponseDTO(Invitation invitation) { + this.invitationLink = invitation.getInvitationLink(); + } +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupDTO.java index add8ab55..7ff7ea44 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupDTO.java @@ -5,6 +5,7 @@ import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; import lombok.Getter; import lombok.Setter; +import org.springframework.data.domain.Page; import java.util.List; import java.util.stream.Collectors; @@ -15,7 +16,7 @@ public class SearchGroupDTO { private List officialGroups; private List unofficialOpenedGroups; - public SearchGroupDTO(List officialGroups, List unofficialOpenedGroups) { + public SearchGroupDTO(Page officialGroups, Page unofficialOpenedGroups) { this.officialGroups = officialGroups.stream().map(GroupInfoDTO::new).collect(Collectors.toList()); this.unofficialOpenedGroups = unofficialOpenedGroups.stream().map(GroupInfoDTO::new).collect(Collectors.toList()); } From 80a85858e2c589803316011f1ec013af75234574 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 14 Oct 2023 17:47:29 +0900 Subject: [PATCH 024/144] =?UTF-8?q?Feat=20:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EC=99=80=20=EA=B4=80=EB=A0=A8=EB=90=9C=20API=EC=97=90=20Member?= =?UTF-8?q?=EB=9E=91=20Group=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존 페이지와 관련된 API 구축할 때, Member랑 Group 관련 로직을 제외하고 구현했는데 추가해주었습니다. - 모든 API에서 요청을 보낸 유저가 해당 그룹에 속한 유저가 맞는지 확인합니다. --- .../member/GroupMemberJPARepository.java | 6 + .../wekiki/page/PageRestController.java | 45 +--- .../techcampus/wekiki/page/PageService.java | 211 ++++++++++++------ 3 files changed, 160 insertions(+), 102 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMemberJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMemberJPARepository.java index 6feb8c35..df7cf29f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMemberJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMemberJPARepository.java @@ -1,15 +1,21 @@ package com.kakao.techcampus.wekiki.group.member; +import com.kakao.techcampus.wekiki.group.Group; import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; import com.kakao.techcampus.wekiki.member.Member; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface GroupMemberJPARepository extends JpaRepository { @Query("SELECT agm FROM ActiveGroupMember agm WHERE agm.member = :member AND agm.group = :group") ActiveGroupMember findActiveGroupMemberByMemberAndGroup(Member member, UnOfficialOpenedGroup group); @Query("SELECT iagm FROM InactiveGroupMember iagm WHERE iagm.member = :member AND iagm.group = :group") InactiveGroupMember findInactiveGroupMemberByMemberAndGroup(Member member, UnOfficialOpenedGroup group); + + @Query("SELECT agm FROM ActiveGroupMember agm WHERE agm.member.id = :memberId AND agm.group.id = :groupId") + Optional findGroupMemberByMemberIdAndGroupId(Long memberId, Long groupId); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index 0e4615bd..049d7506 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -8,6 +8,8 @@ import java.util.List; +import static com.kakao.techcampus.wekiki._core.utils.SecurityUtils.currentMember; + @RestController @RequestMapping("/group/{groupid}/page") @RequiredArgsConstructor @@ -23,9 +25,7 @@ public class PageRestController { @GetMapping("/{pageid}") public ResponseEntity getPageFromId(@PathVariable Long groupid,@PathVariable Long pageid) { - Long tempUserId = 1L; - - PageInfoResponse.getPageFromIdDTO response = pageService.getPageFromId(tempUserId, pageid); + PageInfoResponse.getPageFromIdDTO response = pageService.getPageFromId(currentMember(), groupid, pageid); return ResponseEntity.ok(ApiUtils.success(response)); } @@ -39,10 +39,7 @@ public ResponseEntity getPageFromId(@PathVariable Long groupid,@PathVariable @PostMapping("/create") public ResponseEntity createPage(@PathVariable Long groupid,@RequestBody PageInfoRequest.createPageDTO request) { - // TODO : JWT에서 userId 꺼내도록 수정 - Long tempUserId = 1L; - - PageInfoResponse.createPageDTO response = pageService.createPage(request.getPageName(), request.getGroupId(), tempUserId); + PageInfoResponse.createPageDTO response = pageService.createPage(request.getPageName(), request.getGroupId(), currentMember()); return ResponseEntity.ok(ApiUtils.success(response)); } @@ -55,9 +52,7 @@ public ResponseEntity createPage(@PathVariable Long groupid,@RequestBody Page @DeleteMapping("/{pageid}") public ResponseEntity deletePage(@PathVariable Long groupid,@PathVariable Long pageid) { - Long tempUserId = 1L; - - PageInfoResponse.deletePageDTO response = pageService.deletePage(tempUserId, pageid); + PageInfoResponse.deletePageDTO response = pageService.deletePage(currentMember(),groupid, pageid); return ResponseEntity.ok(ApiUtils.success(response)); } @@ -70,10 +65,7 @@ public ResponseEntity deletePage(@PathVariable Long groupid,@PathVariable Lon @PostMapping("/{pageid}/like") public ResponseEntity likePage(@PathVariable Long groupid,@PathVariable Long pageid) { - // TODO : JWT에서 userId 꺼내도록 수정 - Long tempUserId = 1L; - - PageInfoResponse.likePageDTO response = pageService.likePage(pageid, tempUserId); + PageInfoResponse.likePageDTO response = pageService.likePage(pageid, groupid, currentMember()); return ResponseEntity.ok(ApiUtils.success(response)); } @@ -86,10 +78,7 @@ public ResponseEntity likePage(@PathVariable Long groupid,@PathVariable Long @PostMapping("/{pageid}/hate") public ResponseEntity hatePage(@PathVariable Long groupid,@PathVariable Long pageid) { - // TODO : JWT에서 userId 꺼내도록 수정 - Long tempUserId = 1L; - - PageInfoResponse.hatePageDTO response = pageService.hatePage(pageid, tempUserId); + PageInfoResponse.hatePageDTO response = pageService.hatePage(pageid, groupid, currentMember()); return ResponseEntity.ok(ApiUtils.success(response)); @@ -103,9 +92,7 @@ public ResponseEntity hatePage(@PathVariable Long groupid,@PathVariable Long @GetMapping("/{pageid}/index") public ResponseEntity getPageIndex(@PathVariable Long groupid,@PathVariable Long pageid) { - Long tempUserId = 1L; - - PageInfoResponse.getPageIndexDTO response = pageService.getPageIndex(tempUserId, pageid); + PageInfoResponse.getPageIndexDTO response = pageService.getPageIndex(groupid,currentMember(), pageid); return ResponseEntity.ok(ApiUtils.success(response)); } @@ -121,9 +108,7 @@ public ResponseEntity getPageIndex(@PathVariable Long groupid,@PathVariable L @GetMapping public ResponseEntity getPageFromTitle(@PathVariable Long groupid,@RequestParam(value = "title") String title) { - Long tempUserId = 1L; - - PageInfoResponse.getPageFromIdDTO response = pageService.getPageFromTitle(tempUserId, groupid,title); + PageInfoResponse.getPageFromIdDTO response = pageService.getPageFromTitle(currentMember(), groupid,title); return ResponseEntity.ok(ApiUtils.success(response)); @@ -139,9 +124,7 @@ public ResponseEntity searchPage(@PathVariable Long groupid, @RequestParam(value = "keyword" , defaultValue = "") String keyword, @RequestParam(value = "page", defaultValue = "1") int page) { - Long tempUserId = 1L; - - PageInfoResponse.searchPageDTO response = pageService.searchPage(page - 1, keyword); + PageInfoResponse.searchPageDTO response = pageService.searchPage(groupid, currentMember(),page - 1, keyword); return ResponseEntity.ok(ApiUtils.success(response)); } @@ -154,9 +137,7 @@ public ResponseEntity searchPage(@PathVariable Long groupid, @GetMapping("/recent") public ResponseEntity getRecentPage(@PathVariable Long groupid){ - Long tempUserId = 1L; - - PageInfoResponse.getRecentPageDTO response = pageService.getRecentPage(tempUserId, groupid); + PageInfoResponse.getRecentPageDTO response = pageService.getRecentPage(currentMember(), groupid); return ResponseEntity.ok(ApiUtils.success(response)); } @@ -169,9 +150,7 @@ public ResponseEntity getRecentPage(@PathVariable Long groupid){ @GetMapping("/link") public ResponseEntity getPageLink(@PathVariable Long groupid, @RequestParam(value = "title") String title){ - Long tempUserId = 1L; - - PageInfoResponse.getPageLinkDTO response = pageService.getPageLink(tempUserId, groupid, title); + PageInfoResponse.getPageLinkDTO response = pageService.getPageLink(currentMember(), groupid, title); return ResponseEntity.ok(ApiUtils.success(response)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 9b8da816..61d3bba4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -1,8 +1,15 @@ package com.kakao.techcampus.wekiki.page; +import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.errors.ApplicationException; import com.kakao.techcampus.wekiki._core.errors.ErrorCode; import com.kakao.techcampus.wekiki._core.utils.IndexUtils; +import com.kakao.techcampus.wekiki.group.Group; +import com.kakao.techcampus.wekiki.group.GroupJPARepository; +import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.member.GroupMemberJPARepository; +import com.kakao.techcampus.wekiki.member.Member; +import com.kakao.techcampus.wekiki.member.MemberJPARepository; import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; @@ -18,27 +25,35 @@ import java.util.List; import java.util.stream.Collectors; +import static com.kakao.techcampus.wekiki._core.utils.SecurityUtils.currentMember; + @RequiredArgsConstructor @Service public class PageService { private final PageJPARepository pageJPARepository; private final PostJPARepository postJPARepository; - + private final MemberJPARepository memberJPARepository; + private final GroupMemberJPARepository groupMemberJPARepository; + private final GroupJPARepository groupJPARepository; private final IndexUtils indexUtils; final int PAGE_COUNT = 10; @Transactional - public PageInfoResponse.getPageIndexDTO getPageIndex(Long userId, Long pageId){ - // 1. userId로 User 객체 가져오기 + public PageInfoResponse.getPageIndexDTO getPageIndex(Long groupId,Long memberId, Long pageId){ - // 2. pageId로 PageInfo 객체 들고오기 - PageInfo pageInfo = pageJPARepository.findById(pageId).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 3. PageInfo로부터 Group 객체 들고오기 + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); - // 4. GroupMember인지 체크 + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + checkGroupMember(memberId, groupId); + + // 4. pageId로 PageInfo 객체 들고오기 + PageInfo pageInfo = checkPageFromPageId(pageId); // 5. 해당 groupId를 들고 있는 모든 페이지 Order 순으로 들고오기 List posts = postJPARepository.findPostsByPageIdOrderByOrderAsc(pageId); @@ -56,38 +71,48 @@ public PageInfoResponse.getPageIndexDTO getPageIndex(Long userId, Long pageId){ } @Transactional - public PageInfoResponse.deletePageDTO deletePage(Long userId, Long pageId){ - // 1. userId로 User 객체 가져오기 + public PageInfoResponse.deletePageDTO deletePage(Long memberId, Long groupId, Long pageId){ + + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 2. GroupMember 인지 체크하기 + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); - // 3. 존재하는 페이지 인지 체크 - PageInfo pageInfo = pageJPARepository.findById(pageId).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + checkGroupMember(memberId, groupId); - // 3. pageId로 post 있는지 확인 -> post 존재하면 Exception + // 4. 존재하는 페이지 인지 체크 + PageInfo pageInfo = checkPageFromPageId(pageId); + + // 5. pageId로 하위 post들이 존재하는지 확인 -> 존재하면 Exception if(postJPARepository.existsByPageInfoId(pageId)){ throw new ApplicationException(ErrorCode.PAGE_HAVE_POST); } - // 4. 포스트가 하나도 없으면 삭제시키기 + // 6. 포스트가 하나도 없으면 삭제시키기 PageInfoResponse.deletePageDTO response = new PageInfoResponse.deletePageDTO(pageInfo); pageJPARepository.deleteById(pageId); - // 5. return DTO + // 7. return DTO return response; } @Transactional - public PageInfoResponse.getPageFromIdDTO getPageFromId(Long userId, Long pageId){ - // 1. userId로 User 객체 가져오기 + public PageInfoResponse.getPageFromIdDTO getPageFromId(Long memberId,Long groupId, Long pageId){ + + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 2. pageId로 PageInfo 객체 들고오기 - PageInfo pageInfo = pageJPARepository.findById(pageId).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); - // 3. PageInfo로부터 Group 객체 들고오기 + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + checkGroupMember(memberId, groupId); - // 4. GroupMember인지 체크 + // 4. 존재하는 페이지 인지 체크 + PageInfo pageInfo = checkPageFromPageId(pageId); // 5. 해당 groupId를 들고 있는 모든 페이지 Order 순으로 들고오기 List posts = postJPARepository.findPostsByPageIdOrderByOrderAsc(pageId); @@ -105,20 +130,25 @@ public PageInfoResponse.getPageFromIdDTO getPageFromId(Long userId, Long pageId) } @Transactional - public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Long userId){ + public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Long memberId){ - // 1. groupId랑 userId로 Group 객체, User 객체 가져오기 (없으면 Exception) + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 2. groupMember 존재하는지 확인 (없으면 Exception) + // 2. 존재하는 group인지 확인하기 + Group group = checkGroupFromGroupId(groupId); - // 3. 그룹 내 동일한 title의 Page가 존재하는지 체크 (TODO : where 문에 groupId 추가) + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + checkGroupMember(memberId, groupId); + + // 4. 그룹 내 동일한 title의 Page가 존재하는지 체크 (TODO : where 문에 groupId 추가) if(pageJPARepository.findByTitle(title).isPresent()){ throw new ApplicationException(ErrorCode.PAGE_ALREADY_PRESENT); } - // 4. Page 생성 + // 5. Page 생성 PageInfo newPageInfo = PageInfo.builder() - //.group(group) + .group(group) .pageName(title) .goodCount(0) .badCount(0) @@ -135,57 +165,71 @@ public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Lon } @Transactional - public PageInfoResponse.likePageDTO likePage(Long pageId , Long userId){ + public PageInfoResponse.likePageDTO likePage(Long pageId , Long groupId, Long memberId){ + + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 1. groupId랑 userId로 Group 객체, User 객체 가져오기 (없으면 Exception) + // 2. 존재하는 group인지 확인하기 + Group group = checkGroupFromGroupId(groupId); - // 2. groupMember 존재하는지 확인 (없으면 Exception) + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + checkGroupMember(memberId, groupId); - // 3. 해당 페이지 불러오기 (없으면 Exception) - PageInfo pageInfo = pageJPARepository.findById(pageId).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); + // 4. 존재하는 페이지 인지 체크 + PageInfo pageInfo = checkPageFromPageId(pageId); - // 4. 페이지 goodCount 증가 + // 5. 페이지 goodCount 증가 pageInfo.plusGoodCount(); - // 5. 유저 경험치증가 or 유저 당일 페이지 좋아요 횟수 차감 + // TODO : 6. 유저 경험치증가 or 유저 당일 페이지 좋아요 횟수 차감 - // 6. return + // 7. return DTO return new PageInfoResponse.likePageDTO(pageInfo); } @Transactional - public PageInfoResponse.hatePageDTO hatePage(Long pageId , Long userId){ + public PageInfoResponse.hatePageDTO hatePage(Long pageId , Long groupId, Long memberId){ + + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 1. groupId랑 userId로 Group 객체, User 객체 가져오기 (없으면 Exception) + // 2. 존재하는 group인지 확인하기 + Group group = checkGroupFromGroupId(groupId); - // 2. groupMember 존재하는지 확인 (없으면 Exception) + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + checkGroupMember(memberId, groupId); - // 3. 해당 페이지 불러오기 (없으면 Exception) - PageInfo pageInfo = pageJPARepository.findById(pageId).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); + // 4. 존재하는 페이지 인지 체크 + PageInfo pageInfo = checkPageFromPageId(pageId); - // 4. 페이지 goodCount 증가 + // 5. 페이지 goodCount 증가 pageInfo.plusBadCount(); - // 5. 유저 경험치증가 or 유저 당일 페이지 좋아요 횟수 차감 + // TODO : 6. 유저 경험치증가 or 유저 당일 페이지 좋아요 횟수 차감 - // 6. return + // 7. return DTO return new PageInfoResponse.hatePageDTO(pageInfo); } @Transactional - public PageInfoResponse.searchPageDTO searchPage(int pageNo, String keyword){ + public PageInfoResponse.searchPageDTO searchPage(Long groupId, Long memberId, int pageNo, String keyword){ - // 1. groupId랑 userId로 Group 객체, User 객체 가져오기 (없으면 Exception) + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 2. groupMember 존재하는지 확인 (없으면 Exception) + // 2. 존재하는 group인지 확인하기 + Group group = checkGroupFromGroupId(groupId); - // 3. keyword로 존재하는 page title에 keyword를 가지고 있는 페이지들 다 가져오기 (TODO : group 추가) + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + checkGroupMember(memberId, groupId); + + // 4. keyword로 존재하는 page title에 keyword를 가지고 있는 페이지들 다 가져오기 (TODO : group 추가) PageRequest pageRequest = PageRequest.of(pageNo, PAGE_COUNT); Page pages = pageJPARepository.findPagesByTitleContainingKeyword(keyword, pageRequest); // 해당 Page들을 FK로 가지고 있는 Post들 중에 Orders가 1인 Post들 가져오기 - List res = new ArrayList<>(); for(PageInfo p : pages.getContent()){ List posts = postJPARepository.findFirstPost(p.getId()); @@ -202,19 +246,19 @@ public PageInfoResponse.searchPageDTO searchPage(int pageNo, String keyword){ return new PageInfoResponse.searchPageDTO(res); } - // ============================groupId 필요========================================================== - @Transactional - public PageInfoResponse.getRecentPageDTO getRecentPage(Long userId , Long groupId){ + public PageInfoResponse.getRecentPageDTO getRecentPage(Long memberId , Long groupId){ - // 1. userId user 객체 들고오기 + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 2. groupId로부터 Group 객체 들고오기 + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); - // 3. userId랑 groupId로 groupMember 존재하는지 확인 + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + checkGroupMember(memberId, groupId); - // 4. 특정 groupId를 가진 Page들 order by로 updated_at이 최신인 10개 Page 조회 - // TODO : where 문에 groupId 추가 + // 4. 특정 groupId를 가진 Page들 order by로 updated_at이 최신인 10개 Page 조회 (TODO : where 문에 groupId 추가) Pageable pageable = PageRequest.of(0, 10); List recentPage = pageJPARepository.findOrderByUpdatedAtDesc(pageable); //List recentPage = pageJPARepository.findByGroupIdOrderByUpdatedAtDesc(groupId, pageable); @@ -227,22 +271,27 @@ public PageInfoResponse.getRecentPageDTO getRecentPage(Long userId , Long groupI } @Transactional - public PageInfoResponse.getPageFromIdDTO getPageFromTitle(Long userId, Long groupId, String title){ + public PageInfoResponse.getPageFromIdDTO getPageFromTitle(Long memberId, Long groupId, String title){ - // 1. userId로 User 객체 가져오기 + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 2. groupId로 GroupMember인지 체크하기 + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); - // 3. groupId랑 title로 Page있는지 확인 (TODO : where 문에 groupId 추가) + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + checkGroupMember(memberId, groupId); + + // 4. groupId랑 title로 Page있는지 확인 (TODO : where 문에 groupId 추가) PageInfo page = pageJPARepository.findByTitle(title).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); - // 4. 해당 pageId를 들고있는 모든 페이지 Order 순으로 들고오기 + // 5. 해당 pageId를 들고있는 모든 페이지 Order 순으로 들고오기 List posts = postJPARepository.findPostsByPageIdOrderByOrderAsc(page.getId()); - // 5. 목차 생성하기 + // 6. 목차 생성하기 HashMap indexs = indexUtils.createIndex(posts); - // 6. DTO로 return + // 7. DTO로 return List temp = posts.stream() .map(p -> new PageInfoResponse.getPageFromIdDTO.postDTO(p, indexs.get(p.getId()))) .collect(Collectors.toList()); @@ -251,19 +300,43 @@ public PageInfoResponse.getPageFromIdDTO getPageFromTitle(Long userId, Long grou } @Transactional - public PageInfoResponse.getPageLinkDTO getPageLink(Long userId, Long groupId, String title){ + public PageInfoResponse.getPageLinkDTO getPageLink(Long memberId, Long groupId, String title){ - // 1. userId로 User 객체 가져오기 + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 2. groupId로 GroupMember인지 체크하기 + // 2. 존재하는 group인지 확인하기 + Group group = checkGroupFromGroupId(groupId); - // 3. groupId랑 title로 Page있는지 확인 (TODO : where 문에 groupId 추가) - // (추후에 redis로 Key Value를 로해서 성능 향상시켜보자) + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + checkGroupMember(memberId, groupId); + + // 4. groupId랑 title로 Page있는지 확인 (TODO : where 문에 groupId 추가) + // (+ 추후에 redis로 Key Value를 로해서 성능 향상시켜보자) PageInfo page = pageJPARepository.findByTitle(title).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); - // 4. return DTO + // 5. return DTO return new PageInfoResponse.getPageLinkDTO(page); } + public Member checkMemberFromMemberId(Long memberId){ + return memberJPARepository.findById(memberId) + .orElseThrow(()-> new Exception404("존재하지 않는 회원입니다.")); + } + + public Group checkGroupFromGroupId(Long groupId){ + return groupJPARepository.findById(groupId) + .orElseThrow(()-> new Exception404("존재하지 않는 그룹입니다.")); + } + + public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ + return groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId,groupId) + .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); + } + + public PageInfo checkPageFromPageId(Long pageId){ + return pageJPARepository.findById(pageId) + .orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); + } } From 44cdf8dd160993264357eee88cb833d663a1f45e Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 14 Oct 2023 18:54:28 +0900 Subject: [PATCH 025/144] =?UTF-8?q?Feat=20:=20Post(=EA=B8=80)=EC=99=80=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=EB=90=9C=20API=EC=97=90=20Member=EB=9E=91=20?= =?UTF-8?q?Group=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존 글과 관련된 API 구축할 때, Member랑 Group 관련 로직을 제외하고 구현했는데 추가해주었습니다. - 모든 글 관련 API에서 요청을 보낸 유저가 해당 그룹에 속한 유저가 맞는지 확인합니다. --- .../techcampus/wekiki/post/PostResponse.java | 9 +- .../wekiki/post/PostRestController.java | 18 +-- .../techcampus/wekiki/post/PostService.java | 152 +++++++++++------- 3 files changed, 109 insertions(+), 70 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java index 5ce54c79..dc18d97a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.post; +import com.kakao.techcampus.wekiki.group.member.GroupMember; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.page.PageInfo; import lombok.Getter; @@ -70,14 +71,16 @@ public getPostHistoryDTO(Post post,List historyList){ @Getter @Setter public static class historyDTO{ - //Long memberId; - //String nickName; + Long memberId; + String nickName; Long historyId; String title; String content; LocalDateTime created_at; - public historyDTO(History history){ + public historyDTO(GroupMember groupMember,History history){ + this.memberId = groupMember.getId(); + this.nickName = groupMember.getNickName(); this.historyId = history.getId(); this.title = history.getTitle(); this.content = history.getContent(); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java index afb3d44a..0d337018 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java @@ -10,6 +10,8 @@ import java.util.List; +import static com.kakao.techcampus.wekiki._core.utils.SecurityUtils.currentMember; + @RestController @RequestMapping("/group/{groupid}/post") @RequiredArgsConstructor @@ -20,9 +22,7 @@ public class PostRestController { @PostMapping("/create") public ResponseEntity createPost(@PathVariable Long groupid, @RequestBody PostRequest.createPostDTO request) { - Long tempUserId = 1L; - - PostResponse.createPostDTO response = postService.createPost(tempUserId,request.getPageId(), request.getParentPostId(), + PostResponse.createPostDTO response = postService.createPost(currentMember(),groupid,request.getPageId(), request.getParentPostId(), request.getOrder(), request.getTitle(),request.getContent()); return ResponseEntity.ok(ApiUtils.success(response)); @@ -31,9 +31,7 @@ public ResponseEntity createPost(@PathVariable Long groupid, @RequestBody Pos @PutMapping("/modify") public ResponseEntity modifyPost(@PathVariable Long groupid,@RequestBody PostRequest.modifyPostDTO request){ - Long tempUserId = 1L; - - PostResponse.modifyPostDTO response = postService.modifyPost(tempUserId, request.getPostId(), request.getTitle(), request.getContent()); + PostResponse.modifyPostDTO response = postService.modifyPost(currentMember(),groupid, request.getPostId(), request.getTitle(), request.getContent()); return ResponseEntity.ok(ApiUtils.success(response)); } @@ -41,9 +39,7 @@ public ResponseEntity modifyPost(@PathVariable Long groupid,@RequestBody Post @DeleteMapping("/{postid}") public ResponseEntity deletePost(@PathVariable Long groupid, @PathVariable Long postid){ - Long tempUserId = 1L; - - PostResponse.deletePostDTO response = postService.deletePost(tempUserId, postid); + PostResponse.deletePostDTO response = postService.deletePost(currentMember(), groupid, postid); return ResponseEntity.ok(ApiUtils.success(response)); } @@ -52,9 +48,7 @@ public ResponseEntity deletePost(@PathVariable Long groupid, @PathVariable Lo public ResponseEntity getPostHistory(@PathVariable Long groupid,@PathVariable Long postid ,@RequestParam(value = "page", defaultValue = "1") int page){ - Long tempUserId = 1L; - - PostResponse.getPostHistoryDTO response = postService.getPostHistory(tempUserId, postid, page - 1); + PostResponse.getPostHistoryDTO response = postService.getPostHistory(currentMember(), groupid, postid, page - 1); return ResponseEntity.ok(ApiUtils.success(response)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index c0797e9a..36b48759 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -1,10 +1,17 @@ package com.kakao.techcampus.wekiki.post; +import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.errors.ApplicationException; import com.kakao.techcampus.wekiki._core.errors.ErrorCode; +import com.kakao.techcampus.wekiki.group.Group; +import com.kakao.techcampus.wekiki.group.GroupJPARepository; +import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.member.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.history.HistoryJPARepository; +import com.kakao.techcampus.wekiki.member.Member; +import com.kakao.techcampus.wekiki.member.MemberJPARepository; import com.kakao.techcampus.wekiki.page.PageInfo; import com.kakao.techcampus.wekiki.page.PageJPARepository; import lombok.RequiredArgsConstructor; @@ -24,69 +31,74 @@ public class PostService { private final PageJPARepository pageJPARepository; private final PostJPARepository postJPARepository; private final HistoryJPARepository historyJPARepository; + private final MemberJPARepository memberJPARepository; + private final GroupMemberJPARepository groupMemberJPARepository; + private final GroupJPARepository groupJPARepository; + final int HISTORY_COUNT = 5; @Transactional - public PostResponse.createPostDTO createPost(Long userId,Long pageId, Long parentPostId, int order, String title, String content){ + public PostResponse.createPostDTO createPost(Long memberId,Long groupId,Long pageId, Long parentPostId, int order, String title, String content){ - // 1. userId로 user 객체 들고오기 + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 2. pageId로 해당 PageInfo 객체들고오고 update_at 바꾸기 group 객체 가져오기 - PageInfo pageInfo = pageJPARepository.findById(pageId).orElseThrow( - () -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); - pageInfo.updatePage(); + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); + + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + ActiveGroupMember groupMember = checkGroupMember(memberId, groupId); - // 3. userId랑 groupId로 groupmember가 맞는지 확인 + // 4. pageId로 PageInfo 객체 들고오기 + PageInfo pageInfo = checkPageFromPageId(pageId); + pageInfo.updatePage(); - // 4. parentPostId로 parentPost 가져오기 + // 5. parentPostId로 parentPost 가져오기 Post parent = null; if(parentPostId != 0) { parent = postJPARepository.findById(parentPostId).orElseThrow( () -> new ApplicationException(ErrorCode.PARENT_POST_NOT_FOUND)); } - // 5. 같은 pageId를 가진 Post들 중에 입력받은 order보다 높은 모든 Post들의 order를 1씩 증가 - List postsByPageIdAndOrderGreaterThan = postJPARepository.findPostsByPageIdAndOrderGreaterThan(pageId, order); - for(Post p : postsByPageIdAndOrderGreaterThan){ - p.plusOrder(); - } + // 6. 같은 pageId를 가진 Post들 중에 입력받은 order보다 높은 모든 Post들의 order를 1씩 증가 + postJPARepository.findPostsByPageIdAndOrderGreaterThan(pageId, order).stream().forEach(p -> p.plusOrder()); - // 6. Post 엔티티 생성하고 저장하기 + // 7. Post 엔티티 생성하고 저장하기 Post newPost = Post.builder() .parent(parent) .orders(order) - //.groupMember() + .groupMember(groupMember) .pageInfo(pageInfo) .title(title) .content(content) .created_at(LocalDateTime.now()) .build(); - Post savedPost = postJPARepository.save(newPost); - // 7. 히스토리 생성 + // 8. 히스토리 생성 History newHistory = History.builder() .post(savedPost) .build(); - historyJPARepository.save(newHistory); - // 8. return DTO + // 9. return DTO return new PostResponse.createPostDTO(savedPost); } @Transactional - public PostResponse.modifyPostDTO modifyPost(Long userId, Long postId , String title, String content){ + public PostResponse.modifyPostDTO modifyPost(Long memberId , Long groupId, Long postId , String title, String content){ - // 1. userId user 객체 들고오기 + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 2. postId -> pageId -> groupId (여기서 groupId 바로 받기..?) + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); - // 3. userId랑 groupId로 groupMember 있는지 확인 (즉 그룹 멤버인지 확인) + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + ActiveGroupMember groupMember = checkGroupMember(memberId, groupId); // 4. postId로 post 엔티티 가져오기 - Post post = postJPARepository.findById(postId).orElseThrow( - () -> new ApplicationException(ErrorCode.POST_NOT_FOUND)); + Post post = checkPostFromPostId(postId); // 5. 현재 Post랑 내용 같은지 확인 if(post.getTitle().equals(title) && post.getContent().equals(content)){ @@ -94,8 +106,7 @@ public PostResponse.modifyPostDTO modifyPost(Long userId, Long postId , String t } // 6. 다르면 Post 수정후 히스토리 생성 저장 - // TODO : groupMember 추가 - post.modifyPost(null,title,content); + post.modifyPost(groupMember,title,content); History newHistory = History.builder() .post(post) @@ -104,64 +115,95 @@ public PostResponse.modifyPostDTO modifyPost(Long userId, Long postId , String t // 7. return DTO return new PostResponse.modifyPostDTO(post); - } @Transactional - public PostResponse.getPostHistoryDTO getPostHistory(Long userId, Long postId , int pageNo){ + public PostResponse.getPostHistoryDTO getPostHistory(Long memberId, Long groupId, Long postId , int pageNo){ - // 1. userId로 user객체 가져오기 + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 2. GroupMember인지 체크하기 + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); - // 3. 존재하는 포스트인지 체크 - Post post = postJPARepository.findById(postId).orElseThrow( - () -> new ApplicationException(ErrorCode.POST_NOT_FOUND)); + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + checkGroupMember(memberId, groupId); - // 4. 해당 PostId로 history 모두 가져오기 시간순 + 페이지네이션 - // memberId, nickName, historyId,title, content, created_at (TODO : 나중에 멤버 추가하기 + fetch join 추가) - PageRequest pageRequest = PageRequest.of(pageNo, HISTORY_COUNT); - //Page historys = historyJPARepository.findHistoryWithMemberByPostId(postId, pageRequest); - Page historys = historyJPARepository.findHistoryByPostId(postId, pageRequest); + // 4. postId로 post 엔티티 가져오기 + Post post = checkPostFromPostId(postId); + // 5. 해당 PostId로 history 모두 가져오기 시간순 + 페이지네이션 (memberId, nickName, historyId,title, content, created_at) + PageRequest pageRequest = PageRequest.of(pageNo, HISTORY_COUNT); + Page historys = historyJPARepository.findHistoryWithMemberByPostId(postId, pageRequest); + //Page historys = historyJPARepository.findHistoryByPostId(postId, pageRequest); - // 5. DTO로 return + // 6. DTO로 return List historyDTOs = historys.getContent().stream(). - map(h -> new PostResponse.getPostHistoryDTO.historyDTO(h)).collect(Collectors.toList()); + map(h -> new PostResponse.getPostHistoryDTO.historyDTO(h.getGroupMember(),h)).collect(Collectors.toList()); return new PostResponse.getPostHistoryDTO(post,historyDTOs); } @Transactional - public PostResponse.deletePostDTO deletePost(Long userId, Long postId){ + public PostResponse.deletePostDTO deletePost(Long memberId, Long groupId, Long postId){ + + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 1. userId로 user 객체 가져오기 + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); - // 2. groupId로 GroupMember 인지 체크하기 + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + checkGroupMember(memberId, groupId); - // 3. 존재하는 포스트 인지 체크 - Post post = postJPARepository.findById(postId).orElseThrow( - () -> new ApplicationException(ErrorCode.POST_NOT_FOUND)); + // 4. postId로 post 엔티티 가져오기 + Post post = checkPostFromPostId(postId); - // 4. parent로 해당 postId를 가지고 있는 post가 있는지 확인 -> 존재하면 Exception + // 5. parent로 해당 postId를 가지고 있는 post가 있는지 확인 -> 존재하면 Exception if(postJPARepository.existsByParentId(postId)){ throw new ApplicationException(ErrorCode.HAVE_CHILD_POST); } - // 5. child post 존재 안하면 history + post 삭제 시키기 + // 6. child post 존재 안하면 history + post 삭제 시키기 PostResponse.deletePostDTO response = new PostResponse.deletePostDTO(post); historyJPARepository.deleteByPostId(postId); postJPARepository.deleteById(postId); - // 6. order값 앞으로 땡기기 - List posts = postJPARepository.findPostsByPageIdAndOrderGreaterThan(post.getPageInfo().getId(), post.getOrders()); - for(Post p : posts){ - p.minusOrder(); - } + // 7. order값 앞으로 땡기기 + postJPARepository.findPostsByPageIdAndOrderGreaterThan(post.getPageInfo().getId(), post.getOrders()); +// postJPARepository.findPostsByPageIdAndOrderGreaterThan(post.getPageInfo().getId(), post.getOrders()).stream().forEach(p->p.minusOrder()); +// for(Post p : posts){ +// p.minusOrder(); +// } - // 7. return DTO; + // 8. return DTO; return response; } + public Member checkMemberFromMemberId(Long memberId){ + return memberJPARepository.findById(memberId) + .orElseThrow(()-> new Exception404("존재하지 않는 회원입니다.")); + } + + public Group checkGroupFromGroupId(Long groupId){ + return groupJPARepository.findById(groupId) + .orElseThrow(()-> new Exception404("존재하지 않는 그룹입니다.")); + } + + public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ + return groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId,groupId) + .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); + } + + public PageInfo checkPageFromPageId(Long pageId){ + return pageJPARepository.findById(pageId) + .orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); + } + + public Post checkPostFromPostId(Long postId){ + return postJPARepository.findById(postId) + .orElseThrow(() -> new Exception404("존재하지 않는 글 입니다.")); + } + } From 9e36b7850cf1fe2f88e46b435c64bee4d931f5e8 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 14 Oct 2023 19:31:26 +0900 Subject: [PATCH 026/144] =?UTF-8?q?Feat=20:=20Comment(=EB=8C=93=EA=B8=80)?= =?UTF-8?q?=EC=99=80=20=EA=B4=80=EB=A0=A8=EB=90=9C=20API=EC=97=90=20Member?= =?UTF-8?q?=EB=9E=91=20Group=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존 댓글과 관련된 API 구축할 때, Member랑 Group 관련 로직을 제외하고 구현했는데 추가해주었습니다. - 모든 댓글 관련 API에서 요청을 보낸 유저가 해당 그룹에 속한 유저가 맞는지 확인합니다. --- .../techcampus/wekiki/comment/Comment.java | 7 +- .../wekiki/comment/CommentController.java | 18 +-- .../wekiki/comment/CommentResponse.java | 9 +- .../wekiki/comment/CommentService.java | 132 ++++++++++++------ .../techcampus/wekiki/post/PostService.java | 4 - 5 files changed, 108 insertions(+), 62 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java index 398d5dcb..3a2ed18b 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.comment; +import com.kakao.techcampus.wekiki.group.member.GroupMember; import com.kakao.techcampus.wekiki.member.Member; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; @@ -20,16 +21,16 @@ public class Comment { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne - private Member member; + private GroupMember groupMember; @ManyToOne private Post post; private String content; private LocalDateTime created_at; @Builder - public Comment(Long id, Member member, Post post, String content, LocalDateTime created_at) { + public Comment(Long id, GroupMember groupMember, Post post, String content, LocalDateTime created_at) { this.id = id; - this.member = member; + this.groupMember = groupMember; this.post = post; this.content = content; this.created_at = created_at; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java index d21144f6..ddf01674 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java @@ -6,6 +6,8 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import static com.kakao.techcampus.wekiki._core.utils.SecurityUtils.currentMember; + @RestController @RequestMapping("/group/{groupid}") @RequiredArgsConstructor @@ -18,9 +20,7 @@ public ResponseEntity getComment(@PathVariable Long groupid, @PathVariable Long postid, @RequestParam(value = "page", defaultValue = "1") int page){ - Long tempUserId = 1L; - - CommentResponse.getCommentDTO response = commentService.getComment(tempUserId, groupid, postid, page-1); + CommentResponse.getCommentDTO response = commentService.getComment(currentMember(), groupid, postid, page-1); return ResponseEntity.ok(ApiUtils.success(response)); } @@ -30,9 +30,7 @@ public ResponseEntity createComment(@PathVariable Long groupid, @PathVariable Long postid, @RequestBody CommentRequest.createComment request){ - Long tempUserId = 1L; - - CommentResponse.createCommentDTO response = commentService.createComment(tempUserId, groupid, postid, request.getContent()); + CommentResponse.createCommentDTO response = commentService.createComment(currentMember(), groupid, postid, request.getContent()); return ResponseEntity.ok(ApiUtils.success(response)); } @@ -41,9 +39,7 @@ public ResponseEntity createComment(@PathVariable Long groupid, public ResponseEntity deleteComment(@PathVariable Long groupid, @PathVariable Long commentid){ - Long tempUserId = 1L; - - CommentResponse.deleteCommentDTO response = commentService.deleteComment(tempUserId, groupid, commentid); + CommentResponse.deleteCommentDTO response = commentService.deleteComment(currentMember(), groupid, commentid); return ResponseEntity.ok(ApiUtils.success(response)); @@ -54,9 +50,7 @@ public ResponseEntity updateComment(@PathVariable Long groupid, @PathVariable Long commentid, @RequestBody CommentRequest.updateComment request){ - Long tempUserId = 1L; - - CommentResponse.updateCommentDTO response = commentService.updateComment(tempUserId, groupid, commentid, request.getContent()); + CommentResponse.updateCommentDTO response = commentService.updateComment(currentMember(), groupid, commentid, request.getContent()); return ResponseEntity.ok(ApiUtils.success(response)); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java index c70d3269..e555b93c 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.comment; +import com.kakao.techcampus.wekiki.group.member.GroupMember; import com.kakao.techcampus.wekiki.post.Post; import lombok.Getter; import lombok.Setter; @@ -41,13 +42,15 @@ public getCommentDTO(Post post, List comments){ @Getter @Setter public static class commentDTO{ Long commentId; - //String nickName; + String nickName; + int memberLevel; String content; LocalDateTime createdAt; - public commentDTO(Comment comment){ + public commentDTO(Comment comment , GroupMember groupMember){ this.commentId = comment.getId(); - //this.nickName = "temp"; + this.nickName = groupMember.getNickName(); + this.memberLevel = groupMember.getMemberLevel(); this.content = comment.getContent(); this.createdAt = comment.getCreated_at(); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java index 4868839c..2fca4b76 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java @@ -1,7 +1,16 @@ package com.kakao.techcampus.wekiki.comment; +import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.errors.ApplicationException; import com.kakao.techcampus.wekiki._core.errors.ErrorCode; +import com.kakao.techcampus.wekiki.group.Group; +import com.kakao.techcampus.wekiki.group.GroupJPARepository; +import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.member.GroupMemberJPARepository; +import com.kakao.techcampus.wekiki.member.Member; +import com.kakao.techcampus.wekiki.member.MemberJPARepository; +import com.kakao.techcampus.wekiki.page.PageInfo; +import com.kakao.techcampus.wekiki.page.PageJPARepository; import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; @@ -21,44 +30,55 @@ public class CommentService { private final CommentJPARepository commentJPARepository; private final PostJPARepository postJPARepository; - + private final MemberJPARepository memberJPARepository; + private final GroupMemberJPARepository groupMemberJPARepository; + private final GroupJPARepository groupJPARepository; final int COMMENT_COUNT = 10; @Transactional - public CommentResponse.getCommentDTO getComment(Long userId, Long groupId, Long postId, int pageNo){ + public CommentResponse.getCommentDTO getComment(Long memberId, Long groupId, Long postId, int pageNo){ + + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 1. userId로 user 객체 들고오기 + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); - // 2. groupMember 맞는지 확인하기 + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + ActiveGroupMember groupMember = checkGroupMember(memberId, groupId); - // 3. post 존재하는지 예외처리 - Post post = postJPARepository.findById(postId).orElseThrow( - () -> new ApplicationException(ErrorCode.POST_NOT_FOUND)); + // 4. post 존재하는지 예외처리 + Post post = checkPostFromPostId(postId); - // 4. postId로 Comment 다 가져오기 + // 5. postId로 Comment 다 가져오기 Pageable pageable = PageRequest.of(pageNo, COMMENT_COUNT); - Page comments = commentJPARepository.findCommentsByPostId(postId, pageable); + Page comments = commentJPARepository.findCommentsByPostId(postId, pageable); // TODO : fetch join (comment랑 groupmember) - // 5. return DTO - List commentDTOs = comments.getContent().stream().map(c -> new CommentResponse.getCommentDTO.commentDTO(c)) + // 6. return DTO + List commentDTOs = comments.getContent() + .stream().map(c -> new CommentResponse.getCommentDTO.commentDTO(c , c.getGroupMember())) .collect(Collectors.toList()); return new CommentResponse.getCommentDTO(post,commentDTOs); } @Transactional - public CommentResponse.createCommentDTO createComment(Long userId, Long groupId, Long postId, String content){ + public CommentResponse.createCommentDTO createComment(Long memberId, Long groupId, Long postId, String content){ + + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 1. userId로 user 객체 들고오기 + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); - // 2. groupMember 맞는지 확인하기 + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + ActiveGroupMember groupMember = checkGroupMember(memberId, groupId); - // 3. post 존재하는지 예외처리 - Post post = postJPARepository.findById(postId).orElseThrow( - () -> new ApplicationException(ErrorCode.POST_NOT_FOUND)); + // 4. post 존재하는지 예외처리 + Post post = checkPostFromPostId(postId); // 4. comment 생성 Comment comment = Comment.builder() - //.member() + .groupMember(groupMember) .post(post) .content(content) .created_at(LocalDateTime.now()) @@ -66,24 +86,28 @@ public CommentResponse.createCommentDTO createComment(Long userId, Long groupId, Comment savedComment = commentJPARepository.save(comment); // 5. return DTO - return new CommentResponse.createCommentDTO(savedComment,"temp"); + return new CommentResponse.createCommentDTO(savedComment,groupMember.getNickName()); } @Transactional public CommentResponse.deleteCommentDTO deleteComment(Long memberId, Long groupId, Long commentId){ - // 1. userId로 user 객체 들고오기 + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 2. groupMember 맞는지 확인하기 + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); - // 3. comment 존재하는지 예외처리 - Comment comment = commentJPARepository.findById(commentId).orElseThrow( - () -> new ApplicationException(ErrorCode.COMMENT_NOT_FOUND)); + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + ActiveGroupMember groupMember = checkGroupMember(memberId, groupId); - // 4. comment 쓴 사람이 삭제하는 유저랑 일치하는지 확인 -// if(comment.getMember().getId() != memberId){ -// throw new ApplicationException(ErrorCode.COMMENT_MEMBER_INCONSISTENCY); -// } + // 4. comment 존재하는지 예외처리 + Comment comment = checkCommentFromCommentId(commentId); + + // 5. comment 쓴 사람이 삭제하는 유저랑 일치하는지 확인 + if(comment.getGroupMember().getId() != groupMember.getId()){ + throw new ApplicationException(ErrorCode.COMMENT_MEMBER_INCONSISTENCY); + } // 5. comment 삭제 CommentResponse.deleteCommentDTO response = new CommentResponse.deleteCommentDTO(comment); @@ -96,31 +120,59 @@ public CommentResponse.deleteCommentDTO deleteComment(Long memberId, Long groupI @Transactional public CommentResponse.updateCommentDTO updateComment(Long memberId, Long groupId, Long commentId, String updateContent){ - // 1. userId로 user 객체 들고오기 + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); - // 2. groupMember 맞는지 확인하기 + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); - // 3. comment 존재하는지 예외처리 - Comment comment = commentJPARepository.findById(commentId).orElseThrow( - () -> new ApplicationException(ErrorCode.COMMENT_NOT_FOUND)); + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + ActiveGroupMember groupMember = checkGroupMember(memberId, groupId); - // 4. comment 쓴 사람이 수정하는 유저랑 일치하는지 확인 -// if(comment.getMember().getId() != memberId){ -// throw new ApplicationException(ErrorCode.COMMENT_MEMBER_INCONSISTENCY); -// } + // 4. comment 존재하는지 예외처리 + Comment comment = checkCommentFromCommentId(commentId); + + // 5. comment 쓴 사람이 삭제하는 유저랑 일치하는지 확인 + if(comment.getGroupMember().getId() != groupMember.getId()){ + throw new ApplicationException(ErrorCode.COMMENT_MEMBER_INCONSISTENCY); + } - // 5. 내용 동일하면 exception + // 6. 내용 동일하면 exception if(comment.getContent().equals(updateContent)){ throw new ApplicationException(ErrorCode.COMMENT_SAME_DATE); } - // 6. 수정 + // 7. 수정 comment.updateContent(updateContent); - // 7. return DTO + // 8. return DTO return new CommentResponse.updateCommentDTO(comment); } + public Member checkMemberFromMemberId(Long memberId){ + return memberJPARepository.findById(memberId) + .orElseThrow(()-> new Exception404("존재하지 않는 회원입니다.")); + } + + public Group checkGroupFromGroupId(Long groupId){ + return groupJPARepository.findById(groupId) + .orElseThrow(()-> new Exception404("존재하지 않는 그룹입니다.")); + } + + public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ + return groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId,groupId) + .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); + } + + public Post checkPostFromPostId(Long postId){ + return postJPARepository.findById(postId) + .orElseThrow(() -> new Exception404("존재하지 않는 글 입니다.")); + } + + public Comment checkCommentFromCommentId(Long commentId){ + return commentJPARepository.findById(commentId) + .orElseThrow(() -> new Exception404("존재하지 않는 댓글 입니다.")); + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index 36b48759..a0c2cbd5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -171,10 +171,6 @@ public PostResponse.deletePostDTO deletePost(Long memberId, Long groupId, Long p // 7. order값 앞으로 땡기기 postJPARepository.findPostsByPageIdAndOrderGreaterThan(post.getPageInfo().getId(), post.getOrders()); -// postJPARepository.findPostsByPageIdAndOrderGreaterThan(post.getPageInfo().getId(), post.getOrders()).stream().forEach(p->p.minusOrder()); -// for(Post p : posts){ -// p.minusOrder(); -// } // 8. return DTO; return response; From ee5fb8b640ed60f5cddc03b4c2400dd6ba60fd70 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 14 Oct 2023 20:20:21 +0900 Subject: [PATCH 027/144] =?UTF-8?q?Feat=20:=20=EC=A0=84=EC=97=AD=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=ED=98=95=EC=8B=9D=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 팀원간에 전역 예외 처리 방식이 상이하여 수정해서 통일해주었습니다. - 예외 발생시 response body에 status도 추가해주었습니다. --- .../_core/error/exception/Exception400.java | 2 +- .../_core/error/exception/Exception401.java | 2 +- .../_core/error/exception/Exception403.java | 2 +- .../_core/error/exception/Exception404.java | 2 +- .../_core/error/exception/Exception500.java | 2 +- .../_core/errors/ApplicationException.java | 19 -------- .../wekiki/_core/errors/ErrorCode.java | 36 -------------- .../_core/errors/GlobalControllerAdvice.java | 47 ------------------- .../wekiki/_core/utils/ApiUtils.java | 10 +++- .../wekiki/comment/CommentService.java | 9 ++-- .../techcampus/wekiki/page/PageService.java | 14 +++--- .../techcampus/wekiki/post/PostService.java | 9 ++-- 12 files changed, 30 insertions(+), 124 deletions(-) delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ApplicationException.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/GlobalControllerAdvice.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception400.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception400.java index 3e4c4e25..3dbdbbe4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception400.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception400.java @@ -14,7 +14,7 @@ public Exception400(String message) { } public ApiUtils.ApiResult body(){ - return ApiUtils.error(getMessage()); + return ApiUtils.error(getMessage(), HttpStatus.BAD_REQUEST); } public HttpStatus status(){ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception401.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception401.java index 1ef0ffd5..680a9f66 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception401.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception401.java @@ -14,7 +14,7 @@ public Exception401(String message) { } public ApiUtils.ApiResult body(){ - return ApiUtils.error(getMessage()); + return ApiUtils.error(getMessage(), HttpStatus.UNAUTHORIZED); } public HttpStatus status(){ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception403.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception403.java index fa92b708..c7338a64 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception403.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception403.java @@ -13,7 +13,7 @@ public Exception403(String message) { } public ApiUtils.ApiResult body(){ - return ApiUtils.error(getMessage()); + return ApiUtils.error(getMessage(), HttpStatus.FORBIDDEN); } public HttpStatus status(){ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception404.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception404.java index 10417d22..6c0debcb 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception404.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception404.java @@ -13,7 +13,7 @@ public Exception404(String message) { } public ApiUtils.ApiResult body(){ - return ApiUtils.error(getMessage()); + return ApiUtils.error(getMessage(), HttpStatus.NOT_FOUND); } public HttpStatus status(){ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception500.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception500.java index a7dddc46..53b37ac2 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception500.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/error/exception/Exception500.java @@ -12,7 +12,7 @@ public Exception500(String message) { } public ApiUtils.ApiResult body(){ - return ApiUtils.error(getMessage()); + return ApiUtils.error(getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } public HttpStatus status(){ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ApplicationException.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ApplicationException.java deleted file mode 100644 index e4daa7cf..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ApplicationException.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.kakao.techcampus.wekiki._core.errors; - -import lombok.Getter; - -import java.time.LocalDateTime; - -@Getter -public class ApplicationException extends RuntimeException { - - private ErrorCode errorCode; - private LocalDateTime timestamp; - - - public ApplicationException(ErrorCode errorCode){ - this.errorCode = errorCode; - this.timestamp = LocalDateTime.now(); - } -} - diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java deleted file mode 100644 index 7cc9e8a8..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/ErrorCode.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.kakao.techcampus.wekiki._core.errors; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import org.springframework.http.HttpStatus; - -@Getter -@AllArgsConstructor -public enum ErrorCode { - INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "WEKIKI-000", "Internal server error"), - PAGE_NOT_FOUND(HttpStatus.NOT_FOUND,"PAGE-001" , "존재하지 않는 페이지 입니다."), - PAGE_ALREADY_PRESENT(HttpStatus.BAD_REQUEST,"PAGE-002","이미 존재하는 페이지 입니다."), - PAGE_HAVE_POST(HttpStatus.BAD_REQUEST,"PAGE-003","글이 적혀있는 페이지는 삭제가 불가능합니다."), - PARENT_POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST-001","존재하지 않는 PARENT POST 입니다."), - POST_NOT_FOUND(HttpStatus.NOT_FOUND,"POST-002","존재하지 않는 POST 입니다."), - POST_SAME_DATE(HttpStatus.BAD_REQUEST,"POST-003","동일한 데이터 입니다."), - HAVE_CHILD_POST(HttpStatus.BAD_REQUEST,"POST-004","하위 포스트가 존재하는 포스트는 삭제가 불가능합니다."), - COMMENT_NOT_FOUND(HttpStatus.NOT_FOUND,"COMMENT-001" , "존재하지 않는 댓글 입니다."), - COMMENT_MEMBER_INCONSISTENCY(HttpStatus.BAD_REQUEST,"COMMENT-002" , "본인이 쓴 댓글만 삭제가 가능합니다."), - COMMENT_SAME_DATE(HttpStatus.BAD_REQUEST,"COMMENT-003","동일한 데이터 입니다."); - - - - /* - 예시) - SAME_EMAIL(HttpStatus.CONFLICT, "USER-001", "이미 가입한 이메일입니다.") - EMAIL_STRUCTURE(HttpStatus.FORBIDDEN,"USER-002","이메일 형식으로 작성해주세요") - - 이렇게 여기 정의하고 throw new ApplicationException(ErrorCode.SAME_EMAIL); 던지면 됨 - */ - - - private HttpStatus status; - private String errorCode; - private String message; -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/GlobalControllerAdvice.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/GlobalControllerAdvice.java deleted file mode 100644 index 22adb644..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/errors/GlobalControllerAdvice.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.kakao.techcampus.wekiki._core.errors; - -import com.kakao.techcampus.wekiki._core.utils.ApiUtils; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import java.time.LocalDateTime; -import java.util.HashMap; -import java.util.Map; - -@Slf4j -@RestControllerAdvice -public class GlobalControllerAdvice { - - @ExceptionHandler(ApplicationException.class) - public ResponseEntity applicationHandler(ApplicationException e){ - log.error("Error occurs {}", e.toString()); - - Map data = new HashMap<>(); - data.put("status",e.getErrorCode().getStatus().value()); - data.put("errorCode", e.getErrorCode().getErrorCode()); - data.put("message",e.getErrorCode().getMessage()); - data.put("timestamp", e.getTimestamp()); - - return ResponseEntity.status(e.getErrorCode().getStatus()) - .body(ApiUtils.error(data)); - } - - @ExceptionHandler(Exception.class) - public ResponseEntity applicationHandler(Exception e){ - log.error("Error occurs {}", e.getMessage()); - - ErrorCode error = ErrorCode.INTERNAL_SERVER_ERROR; - - Map data = new HashMap<>(); - data.put("status",error.getStatus().value()); - data.put("errorCode", error.getErrorCode()); - data.put("message",e.getMessage()); - data.put("timestamp", LocalDateTime.now()); - - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) - .body(ApiUtils.error(data)); - } -} \ No newline at end of file diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/ApiUtils.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/ApiUtils.java index 0cc69889..655b8461 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/ApiUtils.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/ApiUtils.java @@ -13,7 +13,9 @@ public static ApiResult success(T response) { return new ApiResult<>(true, response, null); } - + public static ApiResult error(String message, HttpStatus status) { + return new ApiResult<>(false, null, new ApiError(message, status.value())); + } public static ApiResult error(T data) { return new ApiResult<>(false, null, data); } @@ -28,4 +30,10 @@ public static class ApiResult { private final T error; } + @Getter @Setter @AllArgsConstructor + public static class ApiError { + private final String message; + private final int status; + } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java index 2fca4b76..e87717eb 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java @@ -1,8 +1,7 @@ package com.kakao.techcampus.wekiki.comment; +import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; -import com.kakao.techcampus.wekiki._core.errors.ApplicationException; -import com.kakao.techcampus.wekiki._core.errors.ErrorCode; import com.kakao.techcampus.wekiki.group.Group; import com.kakao.techcampus.wekiki.group.GroupJPARepository; import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; @@ -106,7 +105,7 @@ public CommentResponse.deleteCommentDTO deleteComment(Long memberId, Long groupI // 5. comment 쓴 사람이 삭제하는 유저랑 일치하는지 확인 if(comment.getGroupMember().getId() != groupMember.getId()){ - throw new ApplicationException(ErrorCode.COMMENT_MEMBER_INCONSISTENCY); + throw new Exception400("본인이 쓴 댓글만 삭제가 가능합니다."); } // 5. comment 삭제 @@ -134,12 +133,12 @@ public CommentResponse.updateCommentDTO updateComment(Long memberId, Long groupI // 5. comment 쓴 사람이 삭제하는 유저랑 일치하는지 확인 if(comment.getGroupMember().getId() != groupMember.getId()){ - throw new ApplicationException(ErrorCode.COMMENT_MEMBER_INCONSISTENCY); + throw new Exception400("본인이 쓴 댓글만 수정이 가능합니다."); } // 6. 내용 동일하면 exception if(comment.getContent().equals(updateContent)){ - throw new ApplicationException(ErrorCode.COMMENT_SAME_DATE); + throw new Exception400("기존 댓글과 동일한 내용입니다."); } // 7. 수정 diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 61d3bba4..c7e072fd 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -1,8 +1,7 @@ package com.kakao.techcampus.wekiki.page; +import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; -import com.kakao.techcampus.wekiki._core.errors.ApplicationException; -import com.kakao.techcampus.wekiki._core.errors.ErrorCode; import com.kakao.techcampus.wekiki._core.utils.IndexUtils; import com.kakao.techcampus.wekiki.group.Group; import com.kakao.techcampus.wekiki.group.GroupJPARepository; @@ -87,7 +86,7 @@ public PageInfoResponse.deletePageDTO deletePage(Long memberId, Long groupId, Lo // 5. pageId로 하위 post들이 존재하는지 확인 -> 존재하면 Exception if(postJPARepository.existsByPageInfoId(pageId)){ - throw new ApplicationException(ErrorCode.PAGE_HAVE_POST); + throw new Exception400("글이 적혀있는 페이지는 삭제가 불가능합니다."); } // 6. 포스트가 하나도 없으면 삭제시키기 @@ -143,7 +142,7 @@ public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Lon // 4. 그룹 내 동일한 title의 Page가 존재하는지 체크 (TODO : where 문에 groupId 추가) if(pageJPARepository.findByTitle(title).isPresent()){ - throw new ApplicationException(ErrorCode.PAGE_ALREADY_PRESENT); + throw new Exception400("이미 존재하는 페이지입니다."); } // 5. Page 생성 @@ -283,7 +282,9 @@ public PageInfoResponse.getPageFromIdDTO getPageFromTitle(Long memberId, Long gr checkGroupMember(memberId, groupId); // 4. groupId랑 title로 Page있는지 확인 (TODO : where 문에 groupId 추가) - PageInfo page = pageJPARepository.findByTitle(title).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); + PageInfo page = pageJPARepository.findByTitle(title). + orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); + // 5. 해당 pageId를 들고있는 모든 페이지 Order 순으로 들고오기 List posts = postJPARepository.findPostsByPageIdOrderByOrderAsc(page.getId()); @@ -313,7 +314,8 @@ public PageInfoResponse.getPageLinkDTO getPageLink(Long memberId, Long groupId, // 4. groupId랑 title로 Page있는지 확인 (TODO : where 문에 groupId 추가) // (+ 추후에 redis로 Key Value를 로해서 성능 향상시켜보자) - PageInfo page = pageJPARepository.findByTitle(title).orElseThrow(() -> new ApplicationException(ErrorCode.PAGE_NOT_FOUND)); + PageInfo page = pageJPARepository.findByTitle(title). + orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); // 5. return DTO return new PageInfoResponse.getPageLinkDTO(page); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index a0c2cbd5..2284ac71 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -1,9 +1,8 @@ package com.kakao.techcampus.wekiki.post; +import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; -import com.kakao.techcampus.wekiki._core.errors.ApplicationException; -import com.kakao.techcampus.wekiki._core.errors.ErrorCode; import com.kakao.techcampus.wekiki.group.Group; import com.kakao.techcampus.wekiki.group.GroupJPARepository; import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; @@ -57,7 +56,7 @@ public PostResponse.createPostDTO createPost(Long memberId,Long groupId,Long pag Post parent = null; if(parentPostId != 0) { parent = postJPARepository.findById(parentPostId).orElseThrow( - () -> new ApplicationException(ErrorCode.PARENT_POST_NOT_FOUND)); + () -> new Exception404("존재하지 않는 상위 글입니다.")); } // 6. 같은 pageId를 가진 Post들 중에 입력받은 order보다 높은 모든 Post들의 order를 1씩 증가 @@ -102,7 +101,7 @@ public PostResponse.modifyPostDTO modifyPost(Long memberId , Long groupId, Long // 5. 현재 Post랑 내용 같은지 확인 if(post.getTitle().equals(title) && post.getContent().equals(content)){ - throw new ApplicationException(ErrorCode.POST_SAME_DATE); + throw new Exception400("기존 글과 동일한 글입니다."); } // 6. 다르면 Post 수정후 히스토리 생성 저장 @@ -161,7 +160,7 @@ public PostResponse.deletePostDTO deletePost(Long memberId, Long groupId, Long p // 5. parent로 해당 postId를 가지고 있는 post가 있는지 확인 -> 존재하면 Exception if(postJPARepository.existsByParentId(postId)){ - throw new ApplicationException(ErrorCode.HAVE_CHILD_POST); + throw new Exception400("하위 글이 존재하는 글은 삭제가 불가능합니다."); } // 6. child post 존재 안하면 history + post 삭제 시키기 From bb08bb41ba0c19897218143b44faddd9f00ae36c Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sat, 14 Oct 2023 20:33:22 +0900 Subject: [PATCH 028/144] =?UTF-8?q?Feat:=20=EB=B9=84=EA=B3=B5=EC=8B=9D=20?= =?UTF-8?q?=EA=B3=B5=EA=B0=9C=20=EA=B7=B8=EB=A3=B9=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EA=B2=80=EC=83=89=20=EA=B2=B0=EA=B3=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 비공식 공개 그룹 추가 검색에 대한 결과 반환 --- .../wekiki/group/GroupJPARepository.java | 7 +++--- .../wekiki/group/GroupRestController.java | 17 ++++++++++++-- .../techcampus/wekiki/group/GroupService.java | 22 ++++++++++++++++--- .../groupDTO/responseDTO/SearchGroupDTO.java | 2 +- .../SearchUnOfficialGroupResponseDTO.java | 19 ++++++++++++++++ 5 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchUnOfficialGroupResponseDTO.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java index 6db0b7e3..36ff6c4c 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java @@ -1,10 +1,11 @@ package com.kakao.techcampus.wekiki.group; -import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.SearchGroupDTO; import com.kakao.techcampus.wekiki.group.invitation.Invitation; import com.kakao.techcampus.wekiki.group.officialGroup.OfficialGroup; import com.kakao.techcampus.wekiki.group.unOfficialGroup.closedGroup.UnOfficialClosedGroup; import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; +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.data.repository.query.Param; @@ -20,9 +21,9 @@ public interface GroupJPARepository extends JpaRepository { 그룹 검색 용 */ @Query("SELECT g FROM OfficialGroup g WHERE g.groupName LIKE CONCAT('%', :keyword, '%')") - List findOfficialGroupsByKeyword(@Param("keyword") String keyword); + Page findOfficialGroupsByKeyword(@Param("keyword") String keyword, Pageable pageable); @Query("SELECT g FROM UnOfficialOpenedGroup g WHERE g.groupName LIKE CONCAT('%', :keyword, '%')") - List findUnOfficialOpenedGroupsByKeyword(@Param("keyword") String keyword); + Page findUnOfficialOpenedGroupsByKeyword(@Param("keyword") String keyword, Pageable pageable); /* 비공식 공개 그룹 상세 조회 diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java index 7fb40501..4080123a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java @@ -43,9 +43,22 @@ public ResponseEntity createUnOfficialGroup( public ResponseEntity searchGroup(@RequestParam(value = "keyword", required = false) String keyword) { // TODO: 페이지네이션 필요 - SearchGroupDTO response = groupService.searchGroupByKeyword(keyword); + SearchGroupDTO responseDTO = groupService.searchGroupByKeyword(keyword); - return ResponseEntity.ok().body(ApiUtils.success(response)); + return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); + } + + /* + 그룹 추가 검색 - 비공식 공개 그룹 + */ + @GetMapping("/search/unOfficialGroup") + public ResponseEntity searchUnOfficialGroup(@RequestParam(value = "keyword", required = false) String keyword, + @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "size", defaultValue = "10") int size) { + + SearchUnOfficialGroupResponseDTO responseDTO = groupService.searchUnOfficialGroupByKeyword(keyword, page, size); + + return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } /* diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java index c6050e5a..eb66a786 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java @@ -19,6 +19,8 @@ import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -110,20 +112,34 @@ protected ActiveGroupMember buildGroupMember(Member member, Group group, String /* 공식 그룹 리스트, 비공식 공개 그룹 리스트 그룹 - keyword가 포함된 모든 그룹 그룹별 리스트 - - 이름 정렬 후 반환 */ public SearchGroupDTO searchGroupByKeyword(String keyword) { + Pageable pageable = PageRequest.of(0, 10); + // 공식 그룹 리스트 - Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword); + Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); // 비공식 공개 그룹 리스트 - Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword); + Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); // TODO: 페이지네이션 필요 return new SearchGroupDTO(officialGroups, unOfficialOpenedGroups); } + /* + 비공식 공개 그룹 추가 리스트 + */ + public SearchUnOfficialGroupResponseDTO searchUnOfficialGroupByKeyword(String keyword, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + + // 비공식 공개 그룹 리스트 + Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); + + return new SearchUnOfficialGroupResponseDTO(unOfficialOpenedGroups); + } + /* 초대 링크 확인 */ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupDTO.java index 7ff7ea44..51012ee8 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupDTO.java @@ -23,7 +23,7 @@ public SearchGroupDTO(Page officialGroups, Page unofficialOpenedGroups; + + public SearchUnOfficialGroupResponseDTO(Page unofficialOpenedGroups) { + this.unofficialOpenedGroups = unofficialOpenedGroups.stream().map(SearchGroupDTO.GroupInfoDTO::new).collect(Collectors.toList()); + } +} From 62bedbac634a6dab49875ad6e9c683b420d46c17 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sat, 14 Oct 2023 20:50:05 +0900 Subject: [PATCH 029/144] =?UTF-8?q?Feat:=20=EA=B3=B5=EC=8B=9D=20=EA=B7=B8?= =?UTF-8?q?=EB=A3=B9=20=EC=B6=94=EA=B0=80=20=EA=B2=80=EC=83=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 공식 그룹 추가 검색 반환 --- .../wekiki/group/GroupRestController.java | 13 +++++++++++++ .../techcampus/wekiki/group/GroupService.java | 15 +++++++++++++-- .../SearchOfficialGroupResponseDTO.java | 19 +++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchOfficialGroupResponseDTO.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java index 4080123a..ff1c4c8b 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java @@ -48,6 +48,19 @@ public ResponseEntity searchGroup(@RequestParam(value = "keyword", required = return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } + /* + 그룹 추가 검색 - 공식 그룹 + */ + @GetMapping("/search/officialGroup") + public ResponseEntity searchOfficialGroup(@RequestParam(value = "keyword", required = false) String keyword, + @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "size", defaultValue = "10") int size) { + + SearchOfficialGroupResponseDTO responseDTO = groupService.searchOfficialGroupByKeyword(keyword, page, size); + + return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); + } + /* 그룹 추가 검색 - 비공식 공개 그룹 */ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java index eb66a786..7f4f4859 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java @@ -121,12 +121,23 @@ public SearchGroupDTO searchGroupByKeyword(String keyword) { Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); // 비공식 공개 그룹 리스트 Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); - - // TODO: 페이지네이션 필요 return new SearchGroupDTO(officialGroups, unOfficialOpenedGroups); } + /* + 공식 그룹 추가 리스트 + */ + public SearchOfficialGroupResponseDTO searchOfficialGroupByKeyword(String keyword, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + + // 비공식 공개 그룹 리스트 + Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); + + return new SearchOfficialGroupResponseDTO(officialGroups); + } + /* 비공식 공개 그룹 추가 리스트 */ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchOfficialGroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchOfficialGroupResponseDTO.java new file mode 100644 index 00000000..36b063e6 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchOfficialGroupResponseDTO.java @@ -0,0 +1,19 @@ +package com.kakao.techcampus.wekiki.group.groupDTO.responseDTO; + +import com.kakao.techcampus.wekiki.group.officialGroup.OfficialGroup; +import lombok.Getter; +import lombok.Setter; +import org.springframework.data.domain.Page; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@Setter +public class SearchOfficialGroupResponseDTO { + private List officialOpenedGroups; + + public SearchOfficialGroupResponseDTO(Page officialOpenedGroups) { + this.officialOpenedGroups = officialOpenedGroups.stream().map(SearchGroupDTO.GroupInfoDTO::new).collect(Collectors.toList()); + } +} From 32dbfcb601af010e819e8a69b0815835ed71e172 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sat, 14 Oct 2023 22:54:19 +0900 Subject: [PATCH 030/144] =?UTF-8?q?Refactor:=20=EB=82=B4=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=20=EA=B8=B0=EC=97=AC=20=EB=AA=A9=EB=A1=9D=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EB=84=A4=EC=9D=B4=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 그룹 내 마이 페이지, 내 문서 기여 목록 10개만 던짐 - 전체 보기를 따로 --- .../java/com/kakao/techcampus/wekiki/group/GroupService.java | 5 ++--- .../group/groupDTO/responseDTO/MyGroupInfoResponseDTO.java | 3 ++- .../techcampus/wekiki/history/HistoryJPARepository.java | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java index 7f4f4859..d845b4ee 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java @@ -25,7 +25,6 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; -import java.util.Comparator; import java.util.List; @Transactional(readOnly = true) @@ -242,8 +241,8 @@ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); // 해당 멤버의 Post 기록 정보 확인(History에서 가져옴) - // TODO: 페이지네이션 필요 - List myHistoryList = historyJPARepository.findAllByGroupMember(groupMember); + Pageable pageable = PageRequest.of(0, 10); + Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember, pageable); // 그룹 이름, 현재 닉네임, Post 기록 정보를 담은 responseDTO 반환 return new MyGroupInfoResponseDTO(group, groupMember, myHistoryList); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupInfoResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupInfoResponseDTO.java index e12b53c2..523c0fea 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupInfoResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupInfoResponseDTO.java @@ -6,6 +6,7 @@ import com.kakao.techcampus.wekiki.history.History; import lombok.Getter; import lombok.Setter; +import org.springframework.data.domain.Page; import java.time.LocalDateTime; import java.util.List; @@ -19,7 +20,7 @@ public class MyGroupInfoResponseDTO { private String groupNickName; private List myHistoryDTOS; - public MyGroupInfoResponseDTO(Group group, GroupMember groupMember, List histories) { + public MyGroupInfoResponseDTO(Group group, GroupMember groupMember, Page histories) { this.groupName = group.getGroupName(); this.groupNickName = groupMember.getNickName(); this.myHistoryDTOS = histories.stream().map(MyHistoryDTO::new).collect(Collectors.toList()); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java index fe6a63fb..d733fb3b 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java @@ -1,6 +1,8 @@ package com.kakao.techcampus.wekiki.history; import com.kakao.techcampus.wekiki.group.member.GroupMember; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -9,4 +11,6 @@ @Repository public interface HistoryJPARepository extends JpaRepository { List findAllByGroupMember(GroupMember groupMember); + + Page findAllByGroupMember(GroupMember groupMember, Pageable pageable); } From 026b3204d44dd753212ae7cfa130bf48bbe72412 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sat, 14 Oct 2023 23:09:59 +0900 Subject: [PATCH 031/144] =?UTF-8?q?Refactor:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기본 검색 이후 추가 검색이라 page 기본값을 1로 수정, 그대로 받음 --- .../kakao/techcampus/wekiki/group/GroupRestController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java index ff1c4c8b..e14cea12 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java @@ -53,7 +53,7 @@ public ResponseEntity searchGroup(@RequestParam(value = "keyword", required = */ @GetMapping("/search/officialGroup") public ResponseEntity searchOfficialGroup(@RequestParam(value = "keyword", required = false) String keyword, - @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "page", defaultValue = "1") int page, @RequestParam(value = "size", defaultValue = "10") int size) { SearchOfficialGroupResponseDTO responseDTO = groupService.searchOfficialGroupByKeyword(keyword, page, size); @@ -66,7 +66,7 @@ public ResponseEntity searchOfficialGroup(@RequestParam(value = "keyword", re */ @GetMapping("/search/unOfficialGroup") public ResponseEntity searchUnOfficialGroup(@RequestParam(value = "keyword", required = false) String keyword, - @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "page", defaultValue = "1") int page, @RequestParam(value = "size", defaultValue = "10") int size) { SearchUnOfficialGroupResponseDTO responseDTO = groupService.searchUnOfficialGroupByKeyword(keyword, page, size); From 270a7b38cd4f792b74f3b313907a9db27e4be96e Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sun, 15 Oct 2023 16:41:37 +0900 Subject: [PATCH 032/144] =?UTF-8?q?Refactor:=20Transactional=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Transactional 빼먹은 부분 보완 --- .../java/com/kakao/techcampus/wekiki/group/GroupService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java index d845b4ee..bf5f7016 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java @@ -203,6 +203,7 @@ public void groupEntry(Long groupId, String entrancePassword) { /* 그룹 참가 (공통 부분) */ + @Transactional public void joinGroup(Long groupId, Long memberId, JoinGroupRequestDTO requestDTO) { // 회원 정보 확인 Member member = getMemberById(memberId); @@ -251,6 +252,7 @@ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { /* 그룹 내 마이 페이지 정보 수정 */ + @Transactional public void updateMyGroupPage(Long groupId, Long memberId, UpdateMyGroupPageDTO requestDTO) { // 회원 정보 확인 Member member = getMemberById(memberId); @@ -273,6 +275,7 @@ public void updateMyGroupPage(Long groupId, Long memberId, UpdateMyGroupPageDTO /* 그룹 탈퇴 */ + @Transactional public void leaveGroup(Long groupId, Long memberId) { // 회원 정보 확인 Member member = getMemberById(memberId); From 28e34a3ef3c7f9a93a9d4a139647d450304a3741 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Mon, 16 Oct 2023 14:38:27 +0900 Subject: [PATCH 033/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 각 API마다 잘못 가져온 Group 수정 --- .../kakao/techcampus/wekiki/group/GroupService.java | 11 +++++++---- .../wekiki/group/member/GroupMemberJPARepository.java | 5 ++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java index bf5f7016..abbd685b 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java @@ -191,6 +191,9 @@ public SearchGroupInfoDTO getGroupInfo(Long groupId) { return new SearchGroupInfoDTO(group); } + /* + 비공식 공개 그룹 입장 + */ public void groupEntry(Long groupId, String entrancePassword) { UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId); @@ -210,7 +213,7 @@ public void joinGroup(Long groupId, Long memberId, JoinGroupRequestDTO requestDT // 그룹 정보 확인 // TODO: Redis 활용 - UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId); + Group group = groupJPARepository.findById(groupId).orElse(null); // 재가입 회원인지 확인 InactiveGroupMember wasGroupMember = groupMemberJPARepository.findInactiveGroupMemberByMemberAndGroup(member, group); @@ -236,7 +239,7 @@ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { // 그룹 정보 확인 // TODO: Redis 활용 - UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId); + Group group = groupJPARepository.findById(groupId).orElse(null); // 그룹 멤버 확인 ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); @@ -259,7 +262,7 @@ public void updateMyGroupPage(Long groupId, Long memberId, UpdateMyGroupPageDTO // 그룹 정보 확인 // TODO: Redis 활용 - UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId); + Group group = groupJPARepository.findById(groupId).orElse(null); // 그룹 멤버 확인 // TODO: Redis 활용 @@ -282,7 +285,7 @@ public void leaveGroup(Long groupId, Long memberId) { // 그룹 정보 확인 // TODO: Redis 활용 - UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId); + Group group = groupJPARepository.findById(groupId).orElse(null); // 그룹 멤버 확인 // TODO: Redis 활용 diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMemberJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMemberJPARepository.java index df7cf29f..6a0b1f24 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMemberJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMemberJPARepository.java @@ -1,7 +1,6 @@ package com.kakao.techcampus.wekiki.group.member; import com.kakao.techcampus.wekiki.group.Group; -import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; import com.kakao.techcampus.wekiki.member.Member; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -12,9 +11,9 @@ @Repository public interface GroupMemberJPARepository extends JpaRepository { @Query("SELECT agm FROM ActiveGroupMember agm WHERE agm.member = :member AND agm.group = :group") - ActiveGroupMember findActiveGroupMemberByMemberAndGroup(Member member, UnOfficialOpenedGroup group); + ActiveGroupMember findActiveGroupMemberByMemberAndGroup(Member member, Group group); @Query("SELECT iagm FROM InactiveGroupMember iagm WHERE iagm.member = :member AND iagm.group = :group") - InactiveGroupMember findInactiveGroupMemberByMemberAndGroup(Member member, UnOfficialOpenedGroup group); + InactiveGroupMember findInactiveGroupMemberByMemberAndGroup(Member member, Group group); @Query("SELECT agm FROM ActiveGroupMember agm WHERE agm.member.id = :memberId AND agm.group.id = :groupId") Optional findGroupMemberByMemberIdAndGroupId(Long memberId, Long groupId); From 06c443676f406684d7931650a24b7e1721c75870 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Mon, 16 Oct 2023 15:48:40 +0900 Subject: [PATCH 034/144] =?UTF-8?q?Feat:=20=EB=AC=B8=EC=84=9C=20=EA=B8=B0?= =?UTF-8?q?=EC=97=AC=20=EB=AA=A9=EB=A1=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 내 문서 기여 목록 전체 보기 기능 임시 구현 --- .../wekiki/group/GroupRestController.java | 16 +++++++++++++++ .../techcampus/wekiki/group/GroupService.java | 20 +++++++++++++++++++ .../MyGroupHistoryResponseDTO.java | 20 +++++++++++++++++++ .../responseDTO/MyGroupInfoResponseDTO.java | 2 +- 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupHistoryResponseDTO.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java index e14cea12..7732f8ff 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java @@ -162,6 +162,22 @@ public ResponseEntity updateMyGroupPage(@PathVariable("groupId") Long groupId return ResponseEntity.ok().body(ApiUtils.success(null)); } + + /* + 내 문서 기여 목록 + */ + @GetMapping("/{groupId}/myInfo/myHistory") + public ResponseEntity myGroupHistoryPage(@PathVariable("groupId") Long groupId, + @RequestParam(value = "page", defaultValue = "0") int page, + @RequestParam(value = "size", defaultValue = "10") int size + ) { + // TODO: JWT Token에서 memberId 획득 + Long tempMemberId = 1L; + + MyGroupHistoryResponseDTO responseDTO = groupService.getMyGroupHistory(groupId, tempMemberId, page, size); + + return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); + } /* 그룹 탈퇴 diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java index abbd685b..a8ff485b 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java @@ -252,6 +252,26 @@ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { return new MyGroupInfoResponseDTO(group, groupMember, myHistoryList); } + /* + 내 문서 기여 목록 전체 보기 + */ + public MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, int page, int size) { + // 회원 정보 확인 + Member member = getMemberById(memberId); + + // 그룹 정보 확인 + // TODO: Redis 활용 + Group group = groupJPARepository.findById(groupId).orElse(null); + + // 그룹 멤버 확인 + ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); + + Pageable pageable = PageRequest.of(page, size); + Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember, pageable); + + return new MyGroupHistoryResponseDTO(myHistoryList); + } + /* 그룹 내 마이 페이지 정보 수정 */ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupHistoryResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupHistoryResponseDTO.java new file mode 100644 index 00000000..190e4ca7 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupHistoryResponseDTO.java @@ -0,0 +1,20 @@ +package com.kakao.techcampus.wekiki.group.groupDTO.responseDTO; + +import com.kakao.techcampus.wekiki.history.History; +import lombok.Getter; +import lombok.Setter; +import org.springframework.data.domain.Page; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@Setter +public class MyGroupHistoryResponseDTO { + private List myHistoryDTOS; + + public MyGroupHistoryResponseDTO(Page histories) { + + this.myHistoryDTOS = histories.stream().map(MyGroupInfoResponseDTO.MyHistoryDTO::new).collect(Collectors.toList()); + } +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupInfoResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupInfoResponseDTO.java index 523c0fea..cb31f8fd 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupInfoResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupInfoResponseDTO.java @@ -28,7 +28,7 @@ public MyGroupInfoResponseDTO(Group group, GroupMember groupMember, Page Date: Thu, 19 Oct 2023 14:08:46 +0900 Subject: [PATCH 035/144] =?UTF-8?q?Refactor:=20Token=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=20ID=20=EA=B0=80=EC=A0=B8=EC=98=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - currentMember()를 통해 회원 ID를 가져옴 --- .../wekiki/group/GroupRestController.java | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java index 7732f8ff..b5b3e2bf 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java @@ -11,6 +11,8 @@ import org.springframework.validation.Errors; import org.springframework.web.bind.annotation.*; +import static com.kakao.techcampus.wekiki._core.utils.SecurityUtils.currentMember; + @RequiredArgsConstructor @RestController @RequestMapping("/group") @@ -102,10 +104,8 @@ public ResponseEntity groupEntry(@PathVariable("groupId") Long groupId, @Requ @PostMapping("/{groupId}/join") public ResponseEntity joinGroup(@PathVariable("groupId") Long groupId, JoinGroupRequestDTO requestDTO) { - // TODO: JWT Token에서 memberId 획득 - Long tempMemberId = 1L; - groupService.joinGroup(groupId, tempMemberId, requestDTO); + groupService.joinGroup(groupId, currentMember(), requestDTO); return ResponseEntity.ok().body(ApiUtils.success(null)); } @@ -141,10 +141,7 @@ public ResponseEntity ValidateInvitation(@PathVariable String invitationLink) @GetMapping("/{groupId}/myInfo") public ResponseEntity myGroupPage(@PathVariable("groupId") Long groupId) { - // TODO: JWT Token에서 memberId 획득 - Long tempMemberId = 1L; - - MyGroupInfoResponseDTO responseDTO = groupService.getMyGroupInfo(groupId, tempMemberId); + MyGroupInfoResponseDTO responseDTO = groupService.getMyGroupInfo(groupId, currentMember()); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } @@ -155,10 +152,7 @@ public ResponseEntity myGroupPage(@PathVariable("groupId") Long groupId) { @PatchMapping("/{groupId}/myInfo") public ResponseEntity updateMyGroupPage(@PathVariable("groupId") Long groupId, UpdateMyGroupPageDTO requestDTO) { - // TODO: JWT Token에서 memberId 획득 - Long tempMemberId = 1L; - - groupService.updateMyGroupPage(groupId, tempMemberId, requestDTO); + groupService.updateMyGroupPage(groupId, currentMember(), requestDTO); return ResponseEntity.ok().body(ApiUtils.success(null)); } @@ -171,10 +165,8 @@ public ResponseEntity myGroupHistoryPage(@PathVariable("groupId") Long groupI @RequestParam(value = "page", defaultValue = "0") int page, @RequestParam(value = "size", defaultValue = "10") int size ) { - // TODO: JWT Token에서 memberId 획득 - Long tempMemberId = 1L; - MyGroupHistoryResponseDTO responseDTO = groupService.getMyGroupHistory(groupId, tempMemberId, page, size); + MyGroupHistoryResponseDTO responseDTO = groupService.getMyGroupHistory(groupId, currentMember(), page, size); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } @@ -185,10 +177,7 @@ public ResponseEntity myGroupHistoryPage(@PathVariable("groupId") Long groupI @DeleteMapping("/{groupId}/myInfo") public ResponseEntity leaveGroup(@PathVariable("groupId") Long groupId) { - // TODO: JWT Token에서 memberId 획득 - Long tempMemberId = 1L; - - groupService.leaveGroup(groupId, tempMemberId); + groupService.leaveGroup(groupId, currentMember()); return ResponseEntity.ok().body(ApiUtils.success(null)); } From 8ed1c6d40d0dc0d3e3968ff3fde5f7e04b5807f4 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Thu, 19 Oct 2023 20:26:40 +0900 Subject: [PATCH 036/144] =?UTF-8?q?Feat:=20=EC=97=90=EB=9F=AC=20=ED=95=B8?= =?UTF-8?q?=EB=93=A4=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 모든 service의 API들을 try-catch문으로 감쌌음 --- .../wekiki/group/GroupRestController.java | 8 +- .../techcampus/wekiki/group/GroupService.java | 331 +++++++++++------- 2 files changed, 202 insertions(+), 137 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java index b5b3e2bf..9ec216e0 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java @@ -30,10 +30,7 @@ public class GroupRestController { public ResponseEntity createUnOfficialGroup( @RequestBody @Valid CreateUnOfficialGroupRequestDTO requestDTO, Errors errors) { - // TODO: JWT Token에서 memberId 획득 - Long tempMemberId = 1L; - - CreateUnOfficialGroupResponseDTO response = groupService.createUnOfficialGroup(requestDTO, tempMemberId); + CreateUnOfficialGroupResponseDTO response = groupService.createUnOfficialGroup(requestDTO, currentMember()); return ResponseEntity.ok().body(ApiUtils.success(response)); } @@ -43,8 +40,7 @@ public ResponseEntity createUnOfficialGroup( */ @GetMapping("/search") public ResponseEntity searchGroup(@RequestParam(value = "keyword", required = false) String keyword) { - - // TODO: 페이지네이션 필요 + SearchGroupDTO responseDTO = groupService.searchGroupByKeyword(keyword); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java index a8ff485b..8e331146 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java @@ -1,5 +1,8 @@ package com.kakao.techcampus.wekiki.group; +import com.kakao.techcampus.wekiki._core.error.exception.Exception400; +import com.kakao.techcampus.wekiki._core.error.exception.Exception404; +import com.kakao.techcampus.wekiki._core.error.exception.Exception500; import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.CreateUnOfficialGroupRequestDTO; import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.JoinGroupRequestDTO; import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.UpdateMyGroupPageDTO; @@ -17,6 +20,7 @@ import com.kakao.techcampus.wekiki.member.MemberJPARepository; import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; +import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -43,30 +47,31 @@ public class GroupService { */ @Transactional public CreateUnOfficialGroupResponseDTO createUnOfficialGroup(CreateUnOfficialGroupRequestDTO requestDTO, Long memberId) { - - // Group 생성 - Group group = switch (requestDTO.groupType()) { - case UNOFFICIAL_CLOSED -> buildUnOfficialClosedGroup(requestDTO); - case UNOFFICIAL_OPENED -> buildUnOfficialOpenedGroup(requestDTO); - default -> - // TODO: 예외 처리 구현 - throw new IllegalArgumentException("Invalid groupType"); - }; - - // MemberId로부터 Member 찾기 - // TODO: 예외 처리 구현 - Member member = getMemberById(memberId); - // GroupMember 생성 - ActiveGroupMember groupMember = buildGroupMember(member, group, requestDTO.groupNickName()); - - // Entity 저장 - groupJPARepository.save(group); - groupMemberJPARepository.save(groupMember); - - // return - return new CreateUnOfficialGroupResponseDTO(group); + try { + // Group 생성 + Group group = switch (requestDTO.groupType()) { + case UNOFFICIAL_CLOSED -> buildUnOfficialClosedGroup(requestDTO); + case UNOFFICIAL_OPENED -> buildUnOfficialOpenedGroup(requestDTO); + default -> throw new Exception400("유효하지 않은 그룹 유형입니다."); + }; + + // MemberId로부터 Member 찾기 + Member member = getMemberById(memberId); + // GroupMember 생성 + ActiveGroupMember groupMember = buildGroupMember(member, group, requestDTO.groupNickName()); + + // Entity 저장 + groupJPARepository.save(group); + groupMemberJPARepository.save(groupMember); + + // return + return new CreateUnOfficialGroupResponseDTO(group); + } catch (Exception400 e) { + throw new Exception500("서버 에러가 발생했습니다."); + } } + /* 비공식 비공개 그룹 생성 후 반환 */ @@ -113,51 +118,66 @@ protected ActiveGroupMember buildGroupMember(Member member, Group group, String - keyword가 포함된 모든 그룹 그룹별 리스트 */ public SearchGroupDTO searchGroupByKeyword(String keyword) { + try { + Pageable pageable = PageRequest.of(0, 10); - Pageable pageable = PageRequest.of(0, 10); + // 공식 그룹 리스트 + Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); + // 비공식 공개 그룹 리스트 + Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); - // 공식 그룹 리스트 - Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); - // 비공식 공개 그룹 리스트 - Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); + return new SearchGroupDTO(officialGroups, unOfficialOpenedGroups); - return new SearchGroupDTO(officialGroups, unOfficialOpenedGroups); + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); + } } /* 공식 그룹 추가 리스트 */ public SearchOfficialGroupResponseDTO searchOfficialGroupByKeyword(String keyword, int page, int size) { + try { + Pageable pageable = PageRequest.of(page, size); - Pageable pageable = PageRequest.of(page, size); + // 비공식 공개 그룹 리스트 + Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); - // 비공식 공개 그룹 리스트 - Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); - - return new SearchOfficialGroupResponseDTO(officialGroups); + return new SearchOfficialGroupResponseDTO(officialGroups); + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); + } } /* 비공식 공개 그룹 추가 리스트 */ public SearchUnOfficialGroupResponseDTO searchUnOfficialGroupByKeyword(String keyword, int page, int size) { + try { + Pageable pageable = PageRequest.of(page, size); - Pageable pageable = PageRequest.of(page, size); + // 비공식 공개 그룹 리스트 + Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); - // 비공식 공개 그룹 리스트 - Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); + return new SearchUnOfficialGroupResponseDTO(unOfficialOpenedGroups); - return new SearchUnOfficialGroupResponseDTO(unOfficialOpenedGroups); + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); + } } /* 초대 링크 확인 */ public GetInvitationLinkResponseDTO getGroupInvitationLink(Long groupId) { + try { + Invitation invitation = groupJPARepository.findInvitationLinkByGroupId(groupId); - Invitation invitation = groupJPARepository.findInvitationLinkByGroupId(groupId); + return new GetInvitationLinkResponseDTO(invitation); - return new GetInvitationLinkResponseDTO(invitation); + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); + } } /* @@ -166,170 +186,219 @@ public GetInvitationLinkResponseDTO getGroupInvitationLink(Long groupId) { - 가입 url 생성 후 그룹 가입 API */ public ValidateInvitationResponseDTO ValidateInvitation(String invitationLink) { + try { + String[] invitation = invitationLink.split("/"); - String[] invitation = invitationLink.split("/"); + Long groupId = Long.parseLong(invitation[0]); + String invitationCode = invitation[1]; - Long groupId = Long.parseLong(invitation[0]); - String invitationCode = invitation[1]; + UnOfficialClosedGroup group = groupJPARepository.findUnOfficialClosedGroupById(groupId); - UnOfficialClosedGroup group = groupJPARepository.findUnOfficialClosedGroupById(groupId); + // 초대 코드가 틀린 경우 + if (!group.getInvitation().getInvitationCode().equals(invitationCode)) { + throw new Exception400("초대 코드가 일치하지 않습니다."); + } - // 초대 코드가 틀린 경우 - if(!group.getInvitation().getInvitationCode().equals(invitationCode)) { - // 예외 처리 + return new ValidateInvitationResponseDTO(groupId); + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); } - - return new ValidateInvitationResponseDTO(groupId); } + /* 비공식 공개 그룹 상세 정보 조회 */ public SearchGroupInfoDTO getGroupInfo(Long groupId) { - UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId); - - return new SearchGroupInfoDTO(group); + try { + UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId); + return new SearchGroupInfoDTO(group); + } catch (EntityNotFoundException e) { + throw new Exception404("그룹을 찾을 수 없습니다."); + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); + } } + /* 비공식 공개 그룹 입장 */ public void groupEntry(Long groupId, String entrancePassword) { - UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId); - - // 틀린 경우, 에러 핸들링 - if(group.getEntrancePassword().equals(entrancePassword)) { - // TODO: 예외 처리 + try { + UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId); + + // 틀린 경우, 에러 핸들링 + if(!group.getEntrancePassword().equals(entrancePassword)) { + throw new Exception400("비밀번호가 틀렸습니다."); + } + } catch (EntityNotFoundException e) { + throw new Exception400("그룹을 찾을 수 없습니다."); + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); } } + /* 그룹 참가 (공통 부분) */ @Transactional public void joinGroup(Long groupId, Long memberId, JoinGroupRequestDTO requestDTO) { - // 회원 정보 확인 - Member member = getMemberById(memberId); - - // 그룹 정보 확인 - // TODO: Redis 활용 - Group group = groupJPARepository.findById(groupId).orElse(null); - - // 재가입 회원인지 확인 - InactiveGroupMember wasGroupMember = groupMemberJPARepository.findInactiveGroupMemberByMemberAndGroup(member, group); - - // 재가입 회원이면 활성화, 신규 회원이면 새로 생성 - ActiveGroupMember groupMember = wasGroupMember != null ? new ActiveGroupMember(wasGroupMember) : buildGroupMember(member, group, requestDTO.nickName()); - - // 그룹 멤버 잔재 삭제 - if(wasGroupMember != null) { - groupMemberJPARepository.delete(wasGroupMember); - } + try { + // 회원 정보 확인 + Member member = getMemberById(memberId); + + // 그룹 정보 확인 + // TODO: Redis 활용 + Group group = getGroupById(groupId); - // GroupMember 저장 - groupMemberJPARepository.save(groupMember); + // 재가입 회원인지 확인 + InactiveGroupMember wasGroupMember = groupMemberJPARepository.findInactiveGroupMemberByMemberAndGroup(member, group); + + // 재가입 회원이면 활성화, 신규 회원이면 새로 생성 + ActiveGroupMember groupMember = wasGroupMember != null ? new ActiveGroupMember(wasGroupMember) : buildGroupMember(member, group, requestDTO.nickName()); + + // 그룹 멤버 잔재 삭제 + if(wasGroupMember != null) { + groupMemberJPARepository.delete(wasGroupMember); + } + + // GroupMember 저장 + groupMemberJPARepository.save(groupMember); + + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); + } } /* 그룹 내 마이 페이지 */ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { - // 회원 정보 확인 - Member member = getMemberById(memberId); + try { + // 회원 정보 확인 + Member member = getMemberById(memberId); - // 그룹 정보 확인 - // TODO: Redis 활용 - Group group = groupJPARepository.findById(groupId).orElse(null); + // 그룹 정보 확인 + // TODO: Redis 활용 + Group group = getGroupById(groupId); - // 그룹 멤버 확인 - ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); + // 그룹 멤버 확인 + ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); - // 해당 멤버의 Post 기록 정보 확인(History에서 가져옴) - Pageable pageable = PageRequest.of(0, 10); - Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember, pageable); + // 해당 멤버의 Post 기록 정보 확인(History에서 가져옴) + Pageable pageable = PageRequest.of(0, 10); + Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember, pageable); - // 그룹 이름, 현재 닉네임, Post 기록 정보를 담은 responseDTO 반환 - return new MyGroupInfoResponseDTO(group, groupMember, myHistoryList); + // 그룹 이름, 현재 닉네임, Post 기록 정보를 담은 responseDTO 반환 + return new MyGroupInfoResponseDTO(group, groupMember, myHistoryList); + + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); + } } /* 내 문서 기여 목록 전체 보기 */ + @Transactional public MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, int page, int size) { - // 회원 정보 확인 - Member member = getMemberById(memberId); + try { + // 회원 정보 확인 + Member member = getMemberById(memberId); + + // 그룹 정보 확인 + // TODO: Redis 활용 + Group group = getGroupById(groupId); - // 그룹 정보 확인 - // TODO: Redis 활용 - Group group = groupJPARepository.findById(groupId).orElse(null); + // 그룹 멤버 확인 + ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); - // 그룹 멤버 확인 - ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); + Pageable pageable = PageRequest.of(page, size); + Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember, pageable); - Pageable pageable = PageRequest.of(page, size); - Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember, pageable); + return new MyGroupHistoryResponseDTO(myHistoryList); - return new MyGroupHistoryResponseDTO(myHistoryList); + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); + } } + /* 그룹 내 마이 페이지 정보 수정 */ @Transactional public void updateMyGroupPage(Long groupId, Long memberId, UpdateMyGroupPageDTO requestDTO) { - // 회원 정보 확인 - Member member = getMemberById(memberId); + try { + // 회원 정보 확인 + Member member = getMemberById(memberId); + + // 그룹 정보 확인 + // TODO: Redis 활용 + Group group = getGroupById(groupId); - // 그룹 정보 확인 - // TODO: Redis 활용 - Group group = groupJPARepository.findById(groupId).orElse(null); + // 그룹 멤버 확인 + // TODO: Redis 활용 + ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); - // 그룹 멤버 확인 - // TODO: Redis 활용 - ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); + // 그룹 닉네임 변경 + groupMember.update(requestDTO.groupNickName()); - // 그룹 닉네임 변경 - groupMember.update(requestDTO.groupNickName()); + // 저장 + groupMemberJPARepository.save(groupMember); - // 저장 - groupMemberJPARepository.save(groupMember); + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); + } } + /* 그룹 탈퇴 */ @Transactional public void leaveGroup(Long groupId, Long memberId) { - // 회원 정보 확인 - Member member = getMemberById(memberId); + try { + // 회원 정보 확인 + Member member = getMemberById(memberId); - // 그룹 정보 확인 - // TODO: Redis 활용 - Group group = groupJPARepository.findById(groupId).orElse(null); + // 그룹 정보 확인 + // TODO: Redis 활용 + Group group = getGroupById(groupId); - // 그룹 멤버 확인 - // TODO: Redis 활용 - ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); + // 그룹 멤버 확인 + // TODO: Redis 활용 + ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); - // 탈퇴 그룹 회원 생성 - InactiveGroupMember inactiveGroupMember = new InactiveGroupMember(activeGroupMember); + // 탈퇴 그룹 회원 생성 + InactiveGroupMember inactiveGroupMember = new InactiveGroupMember(activeGroupMember); - // Post의 그룹 멤버 변경 - List postList = postJPARepository.findAllByGroupMember(activeGroupMember); - postList.forEach(p -> p.updateGroupMember(inactiveGroupMember)); + // Post의 그룹 멤버 변경 + List postList = postJPARepository.findAllByGroupMember(activeGroupMember); + postList.forEach(p -> p.updateGroupMember(inactiveGroupMember)); - // History 그룹 멤버 변경 - List historyList = historyJPARepository.findAllByGroupMember(activeGroupMember); - historyList.forEach(h -> h.updateGroupMember(inactiveGroupMember)); + // History 그룹 멤버 변경 + List historyList = historyJPARepository.findAllByGroupMember(activeGroupMember); + historyList.forEach(h -> h.updateGroupMember(inactiveGroupMember)); + + // DB 작업 + groupMemberJPARepository.delete(activeGroupMember); + groupMemberJPARepository.save(inactiveGroupMember); + historyJPARepository.saveAll(historyList); + + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); + } + } - // DB 작업 - groupMemberJPARepository.delete(activeGroupMember); - groupMemberJPARepository.save(inactiveGroupMember); - historyJPARepository.saveAll(historyList); + protected Member getMemberById(Long memberId) { + return memberJPARepository.findById(memberId).orElseThrow(() -> new Exception404("해당 사용자를 찾을 수 없습니다.")); } - public Member getMemberById(Long memberId) { - return memberJPARepository.findById(memberId).orElse(null); + protected Group getGroupById(Long groupId) { + return groupJPARepository.findById(groupId).orElseThrow(() -> new Exception404("해당 그룹을 찾을 수 없습니다.")); } } From 134c08e21340f69b3054fe1e80334b4013b64f55 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Thu, 19 Oct 2023 20:54:09 +0900 Subject: [PATCH 037/144] =?UTF-8?q?Refactor:=20RedisConfig=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 에서 로 수정 --- wekiki/build.gradle | 2 +- .../techcampus/wekiki/_core/config/RedisConfig.java | 13 +++++++++---- .../kakao/techcampus/wekiki/group/GroupService.java | 7 +++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/wekiki/build.gradle b/wekiki/build.gradle index 24da5e45..f776b998 100644 --- a/wekiki/build.gradle +++ b/wekiki/build.gradle @@ -57,7 +57,7 @@ dependencies { // 유효성 검사 implementation 'org.springframework.boot:spring-boot-starter-validation' - // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 + // Random String implementation 'org.apache.commons:commons-lang3:3.12.0' // 개발 편의용 diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/RedisConfig.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/RedisConfig.java index 03e228b7..2c82e9c3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/RedisConfig.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/RedisConfig.java @@ -1,15 +1,18 @@ package com.kakao.techcampus.wekiki._core.config; import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration +@EnableCaching public class RedisConfig { @Value("${spring.data.redis.host}") @@ -22,17 +25,19 @@ public RedisConnectionFactory redisConnectionFactory() { RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); redisStandaloneConfiguration.setHostName(redisHost); redisStandaloneConfiguration.setPort(redisPort); + return new LettuceConnectionFactory(redisStandaloneConfiguration); } @Bean - public RedisTemplate redisTemplate() { - RedisTemplate redisTemplate = new RedisTemplate<>(); + public RedisTemplate redisTemplate() { + RedisTemplate redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory()); + // StringRedisSerializer -> 문자열 형태로 직렬화 redisTemplate.setKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new StringRedisSerializer()); + // GenericJackson2JsonRedisSerializer -> 객체를 JSON 형식으로 직렬화 + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return redisTemplate; } - } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java index 8e331146..15834b5c 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java @@ -66,6 +66,7 @@ public CreateUnOfficialGroupResponseDTO createUnOfficialGroup(CreateUnOfficialGr // return return new CreateUnOfficialGroupResponseDTO(group); + } catch (Exception400 e) { throw new Exception500("서버 에러가 발생했습니다."); } @@ -144,6 +145,7 @@ public SearchOfficialGroupResponseDTO searchOfficialGroupByKeyword(String keywor Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); return new SearchOfficialGroupResponseDTO(officialGroups); + } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } @@ -200,6 +202,7 @@ public ValidateInvitationResponseDTO ValidateInvitation(String invitationLink) { } return new ValidateInvitationResponseDTO(groupId); + } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } @@ -213,6 +216,7 @@ public SearchGroupInfoDTO getGroupInfo(Long groupId) { try { UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId); return new SearchGroupInfoDTO(group); + } catch (EntityNotFoundException e) { throw new Exception404("그룹을 찾을 수 없습니다."); } catch (Exception e) { @@ -232,6 +236,7 @@ public void groupEntry(Long groupId, String entrancePassword) { if(!group.getEntrancePassword().equals(entrancePassword)) { throw new Exception400("비밀번호가 틀렸습니다."); } + } catch (EntityNotFoundException e) { throw new Exception400("그룹을 찾을 수 없습니다."); } catch (Exception e) { @@ -239,7 +244,6 @@ public void groupEntry(Long groupId, String entrancePassword) { } } - /* 그룹 참가 (공통 부분) */ @@ -393,7 +397,6 @@ public void leaveGroup(Long groupId, Long memberId) { } } - protected Member getMemberById(Long memberId) { return memberJPARepository.findById(memberId).orElseThrow(() -> new Exception404("해당 사용자를 찾을 수 없습니다.")); } From 6fe8487d5d0ac02adf808e3e82e1467b5fa70d73 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Thu, 19 Oct 2023 21:22:39 +0900 Subject: [PATCH 038/144] =?UTF-8?q?Refactor:=20Redis=EB=A5=BC=20=ED=99=9C?= =?UTF-8?q?=EC=9A=A9=ED=95=9C=20getMember,=20getGroup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 이게 성능 개선엔 큰 도움이 될 것 같지는 않아서 우선 주석 처리 --- .../techcampus/wekiki/group/GroupService.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java index 15834b5c..97e02f3e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java @@ -404,4 +404,39 @@ protected Member getMemberById(Long memberId) { protected Group getGroupById(Long groupId) { return groupJPARepository.findById(groupId).orElseThrow(() -> new Exception404("해당 그룹을 찾을 수 없습니다.")); } + + // RedisCache를 통한 getMember, getGroup -> 근데 성능 개선에 도움이 될까? + /* + protected Member getMemberById(Long memberId) { + try { + String memberKey = "member:" + memberId; + ValueOperations operations = redisTemplate.opsForValue(); + if(redisTemplate.hasKey(memberKey)) { + return (Member) operations.get(memberKey); + } else { + Member member = memberJPARepository.findById(memberId).orElseThrow(() -> new Exception404("해당 사용자를 찾을 수 없습니다.")); + operations.set(memberKey, member); + return member; + } + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); + } + } + + protected Group getGroupById(Long groupId) { + try { + String groupKey = "group:" + groupId; + ValueOperations operations = redisTemplate.opsForValue(); + if(redisTemplate.hasKey(groupKey)) { + return (Group) operations.get(groupKey); + } else { + Group group = groupJPARepository.findById(groupId).orElseThrow(() -> new Exception404("해당 그룹을 찾을 수 없습니다.")); + operations.set(groupKey, group); + return group; + } + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); + } + } + */ } From e69697e44d431ff426d5010b9cac8f78f1517d83 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 20 Oct 2023 20:45:11 +0900 Subject: [PATCH 039/144] =?UTF-8?q?Refactor:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - try-catch로 묶어서 Exception 처리한 부분 싹 다 고침 --- .../techcampus/wekiki/group/GroupService.java | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java index 97e02f3e..a6bde8fd 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java @@ -68,6 +68,10 @@ public CreateUnOfficialGroupResponseDTO createUnOfficialGroup(CreateUnOfficialGr return new CreateUnOfficialGroupResponseDTO(group); } catch (Exception400 e) { + throw e; + } catch (Exception404 e) { + throw e; + } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } } @@ -203,6 +207,8 @@ public ValidateInvitationResponseDTO ValidateInvitation(String invitationLink) { return new ValidateInvitationResponseDTO(groupId); + } catch (Exception400 e) { + throw e; } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } @@ -237,8 +243,10 @@ public void groupEntry(Long groupId, String entrancePassword) { throw new Exception400("비밀번호가 틀렸습니다."); } - } catch (EntityNotFoundException e) { - throw new Exception400("그룹을 찾을 수 없습니다."); + } catch (Exception400 e) { + throw e; + } catch (EntityNotFoundException e) { + throw new Exception404("그룹을 찾을 수 없습니다."); } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } @@ -271,7 +279,9 @@ public void joinGroup(Long groupId, Long memberId, JoinGroupRequestDTO requestDT // GroupMember 저장 groupMemberJPARepository.save(groupMember); - } catch (Exception e) { + } catch (Exception404 e) { + throw e; + } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } } @@ -298,7 +308,9 @@ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { // 그룹 이름, 현재 닉네임, Post 기록 정보를 담은 responseDTO 반환 return new MyGroupInfoResponseDTO(group, groupMember, myHistoryList); - } catch (Exception e) { + } catch (Exception404 e) { + throw e; + } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } } @@ -324,7 +336,9 @@ public MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, return new MyGroupHistoryResponseDTO(myHistoryList); - } catch (Exception e) { + } catch (Exception404 e) { + throw e; + } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } } @@ -353,7 +367,9 @@ public void updateMyGroupPage(Long groupId, Long memberId, UpdateMyGroupPageDTO // 저장 groupMemberJPARepository.save(groupMember); - } catch (Exception e) { + } catch (Exception404 e) { + throw e; + } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } } @@ -392,6 +408,8 @@ public void leaveGroup(Long groupId, Long memberId) { groupMemberJPARepository.save(inactiveGroupMember); historyJPARepository.saveAll(historyList); + } catch (Exception404 e) { + throw e; } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } From 5819217532f5505107d86aaea104d4e8a13ce768 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 21 Oct 2023 19:41:01 +0900 Subject: [PATCH 040/144] =?UTF-8?q?Feat=20:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=EB=A7=81=ED=81=AC=20=EA=B1=B0=EB=8A=94=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20redis=EB=A1=9C=20=EC=84=B1=EB=8A=A5=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 페이지 생성시에 groupId_pageName을 Key로 하고 Value 값은 pageId를 넣어주었습니다. - 페이지 링크 거는 기능의 성능을 위해 데이터베이스에 쿼리를 날리지 않고 redis를 통해서 페이지 링크를 가져올 수 있게 처리하였습니다. - 페이지 삭제시에 redis에서도 삭제시켜주었습니다. --- .../wekiki/page/PageInfoResponse.java | 4 +-- .../techcampus/wekiki/page/PageService.java | 30 +++++++++++++++---- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index c7642a63..cd53d017 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -178,8 +178,8 @@ public RecentPageDTO(PageInfo pageInfo){ public static class getPageLinkDTO{ Long pageId; - public getPageLinkDTO(PageInfo pageInfo){ - this.pageId = pageInfo.getId(); + public getPageLinkDTO(Long pageId){ + this.pageId = pageId; } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index c7e072fd..83a9d2ab 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -3,6 +3,7 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.utils.IndexUtils; +import com.kakao.techcampus.wekiki._core.utils.RedisUtility; import com.kakao.techcampus.wekiki.group.Group; import com.kakao.techcampus.wekiki.group.GroupJPARepository; import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; @@ -37,6 +38,8 @@ public class PageService { private final GroupJPARepository groupJPARepository; private final IndexUtils indexUtils; + private final RedisUtility redisUtility; + final int PAGE_COUNT = 10; @Transactional @@ -93,7 +96,10 @@ public PageInfoResponse.deletePageDTO deletePage(Long memberId, Long groupId, Lo PageInfoResponse.deletePageDTO response = new PageInfoResponse.deletePageDTO(pageInfo); pageJPARepository.deleteById(pageId); - // 7. return DTO + // 7. redis에 페이지 목록 삭제 시켜주기 + redisUtility.deleteValues(groupId+"_"+pageInfo.getPageName()); + + // 8. return DTO return response; } @@ -159,6 +165,10 @@ public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Lon // 5. Page 저장 PageInfo savedPageInfo = pageJPARepository.save(newPageInfo); + // TODO : 추후에 redis value 자료구조를 String에서 Hash로 변경 (key overhead 최소화) + // > + redisUtility.setValues(groupId+"_"+title,newPageInfo.getId().toString()); + // 6. return DTO return new PageInfoResponse.createPageDTO(savedPageInfo); } @@ -312,13 +322,21 @@ public PageInfoResponse.getPageLinkDTO getPageLink(Long memberId, Long groupId, // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) checkGroupMember(memberId, groupId); - // 4. groupId랑 title로 Page있는지 확인 (TODO : where 문에 groupId 추가) - // (+ 추후에 redis로 Key Value를 로해서 성능 향상시켜보자) - PageInfo page = pageJPARepository.findByTitle(title). - orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); + // 4. redis로 groupId_title을 key로 value 받아오기 (페이지 테이블에 접근할 필요 x) + String value = redisUtility.getValues(groupId+"_"+title); + if(value == null){ + throw new Exception404("존재하지 않는 페이지 입니다."); + }else{ + // 5. return DTO + return new PageInfoResponse.getPageLinkDTO(Long.valueOf(value)); + } + + // 4. groupId랑 title로 Page있는지 확인 - where 문에 groupId 추가 + // PageInfo page = pageJPARepository.findByTitle(title). + // orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); // 5. return DTO - return new PageInfoResponse.getPageLinkDTO(page); + //return new PageInfoResponse.getPageLinkDTO(page); } From 9849f0e11c841d1c4ba9b5e2b3f4789a53015f47 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sat, 21 Oct 2023 19:43:51 +0900 Subject: [PATCH 041/144] =?UTF-8?q?Fix:=20Invitation=20=EC=97=B0=EA=B4=80?= =?UTF-8?q?=EA=B4=80=EA=B3=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 연관관계 설정 - 초대 링크 구현 방법 바꿀 생각이라 임시로 해놨습니다. --- .../wekiki/group/invitation/Invitation.java | 20 +++++++++++++------ .../closedGroup/UnOfficialClosedGroup.java | 8 ++++---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java index f7ff7d99..747f0c5a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java @@ -1,6 +1,7 @@ package com.kakao.techcampus.wekiki.group.invitation; -import jakarta.persistence.Column; +import com.kakao.techcampus.wekiki.group.unOfficialGroup.closedGroup.UnOfficialClosedGroup; +import jakarta.persistence.*; import lombok.*; import org.apache.commons.lang3.RandomStringUtils; @@ -8,21 +9,28 @@ @Getter @Setter +@Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "invitation_tb") public class Invitation { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "group_id") + private UnOfficialClosedGroup group; @Column(unique = true) private String invitationCode; private String invitationLink; - // private LocalDateTime expired_at; private static final int INVITE_CODE_LENGTH = 32; - // private static final Duration DEFAULT_EXPIRED_DAYS = Duration.ofDays(7); @Builder - public Invitation(Long groupId) { + public Invitation(UnOfficialClosedGroup group) { + this.group = group; this.invitationCode = RandomStringUtils.randomAlphanumeric(INVITE_CODE_LENGTH); - this.invitationLink = groupId + "/" + invitationCode; - // this.expired_at = LocalDateTime.now().plusMinutes(DEFAULT_EXPIRED_DAYS.toMinutes()); + this.invitationLink = group.getId() + "/" + invitationCode; } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java index 6c786668..5902b3bc 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java @@ -1,13 +1,12 @@ package com.kakao.techcampus.wekiki.group.unOfficialGroup.closedGroup; import com.kakao.techcampus.wekiki.group.Group; -import com.kakao.techcampus.wekiki.group.invitation.Invitation; -import jakarta.persistence.DiscriminatorValue; -import jakarta.persistence.Entity; +import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import com.kakao.techcampus.wekiki.group.invitation.Invitation; import java.time.LocalDateTime; @@ -17,11 +16,12 @@ @DiscriminatorValue("un_official_closed_group") public class UnOfficialClosedGroup extends Group { + @OneToOne private Invitation invitation; @Builder(builderMethodName = "unOfficialClosedGroupBuilder") public UnOfficialClosedGroup(Long id, String groupName, String groupProfileImage, int memberCount, LocalDateTime created_at) { super(id, groupName, groupProfileImage, memberCount, created_at); - this.invitation = Invitation.builder().groupId(id).build(); + this.invitation = Invitation.builder().group(this).build(); } } From 82bb444868f84e47f337e79a80ce44e13eb6aab8 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sun, 22 Oct 2023 00:17:10 +0900 Subject: [PATCH 042/144] =?UTF-8?q?Feat=20:=20=EA=B8=80=20=EC=8B=A0?= =?UTF-8?q?=EA=B3=A0=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 특정 글에 대해서 신고 하는 기능 구현완료했습니다. - 기존 Post랑 연관관계 매핑이 되어 있었는데, History로 수정했습니다. --- .../techcampus/wekiki/post/PostRequest.java | 17 ++++----- .../techcampus/wekiki/post/PostResponse.java | 13 +++++++ .../wekiki/post/PostRestController.java | 12 ++++++ .../techcampus/wekiki/post/PostService.java | 38 ++++++++++++++++++- .../techcampus/wekiki/report/Report.java | 19 +++++++--- .../wekiki/report/ReportJPARepository.java | 9 +++++ 6 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRequest.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRequest.java index 27487803..8059cfd7 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRequest.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRequest.java @@ -13,16 +13,6 @@ public static class createPostDTO { private String title; private String content; - @Override - public String toString() { - return "createPostDTO{" + - "pageId=" + pageId + - ", parentPostId=" + parentPostId + - ", order=" + order + - ", title='" + title + '\'' + - ", content='" + content + '\'' + - '}'; - } } @Getter @@ -32,4 +22,11 @@ public static class modifyPostDTO{ private String title; private String content; } + + @Getter + @Setter + public static class createReportDTO{ + private Long postId; + private String content; + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java index dc18d97a..1eef2665 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java @@ -3,6 +3,7 @@ import com.kakao.techcampus.wekiki.group.member.GroupMember; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.page.PageInfo; +import com.kakao.techcampus.wekiki.report.Report; import lombok.Getter; import lombok.Setter; @@ -90,4 +91,16 @@ public historyDTO(GroupMember groupMember,History history){ } } + @Getter + @Setter + public static class createReportDTO{ + + Long reportId; + + public createReportDTO(Report report){ + this.reportId = report.getId(); + } + } + + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java index 0d337018..fcbc51c3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java @@ -4,6 +4,8 @@ import com.kakao.techcampus.wekiki._core.utils.ApiUtils; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.history.HistoryJPARepository; +import com.kakao.techcampus.wekiki.report.Report; +import com.kakao.techcampus.wekiki.report.ReportJPARepository; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -53,5 +55,15 @@ public ResponseEntity getPostHistory(@PathVariable Long groupid,@PathVariable return ResponseEntity.ok(ApiUtils.success(response)); } + @PostMapping("/report") + public ResponseEntity createReport(@PathVariable Long groupid , @RequestBody PostRequest.createReportDTO request){ + + PostResponse.createReportDTO response = postService.createReport(currentMember(), groupid, request.getPostId(), request.getContent()); + + return ResponseEntity.ok(ApiUtils.success(response)); + } + + + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index 2284ac71..5fdf30a9 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -6,6 +6,7 @@ import com.kakao.techcampus.wekiki.group.Group; import com.kakao.techcampus.wekiki.group.GroupJPARepository; import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.member.GroupMember; import com.kakao.techcampus.wekiki.group.member.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.history.HistoryJPARepository; @@ -13,6 +14,8 @@ import com.kakao.techcampus.wekiki.member.MemberJPARepository; import com.kakao.techcampus.wekiki.page.PageInfo; import com.kakao.techcampus.wekiki.page.PageJPARepository; +import com.kakao.techcampus.wekiki.report.Report; +import com.kakao.techcampus.wekiki.report.ReportJPARepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -33,7 +36,7 @@ public class PostService { private final MemberJPARepository memberJPARepository; private final GroupMemberJPARepository groupMemberJPARepository; private final GroupJPARepository groupJPARepository; - + private final ReportJPARepository reportJPARepository; final int HISTORY_COUNT = 5; @Transactional @@ -176,6 +179,39 @@ public PostResponse.deletePostDTO deletePost(Long memberId, Long groupId, Long p } + @Transactional + public PostResponse.createReportDTO createReport(Long memberId, Long groupId, Long postId , String content){ + + // 1. memberId로 Member 객체 가져오기 + checkMemberFromMemberId(memberId); + + // 2. 존재하는 group인지 확인하기 + checkGroupFromGroupId(groupId); + + // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + GroupMember groupMember = checkGroupMember(memberId, groupId); + + // 4. postId로 post 엔티티 가져오기 + checkPostFromPostId(postId); + + // 5. postId의 최근 히스토리 가져오기 + List historyByPostId = historyJPARepository.findHistoryByPostId(postId, PageRequest.of(0, 1)); + + // 6. report 생성 + Report report = Report.builder() + .groupMember(groupMember) + .history(historyByPostId.get(0)) + .content(content) + .created_at(LocalDateTime.now()) + .build(); + Report savedReport = reportJPARepository.save(report); + + // 7. return DTO + return new PostResponse.createReportDTO(savedReport); + + } + + public Member checkMemberFromMemberId(Long memberId){ return memberJPARepository.findById(memberId) .orElseThrow(()-> new Exception404("존재하지 않는 회원입니다.")); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java index 9d5ce8ee..73e6ad88 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java @@ -1,6 +1,7 @@ package com.kakao.techcampus.wekiki.report; import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.AccessLevel; @@ -8,6 +9,8 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import java.time.LocalDateTime; + @Getter @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -18,16 +21,22 @@ public class Report { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne - private GroupMember groupMember; + private GroupMember fromMember; + @ManyToOne - private Post post; + private History history; private String content; + private LocalDateTime created_at; + @Builder - public Report(Long id, GroupMember groupMember, Post post, String content) { + public Report(Long id, GroupMember groupMember, History history, String content, LocalDateTime created_at) { this.id = id; - this.groupMember = groupMember; - this.post = post; + this.fromMember = groupMember; + this.history = history; this.content = content; + this.created_at = created_at; } + + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java new file mode 100644 index 00000000..098ca083 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java @@ -0,0 +1,9 @@ +package com.kakao.techcampus.wekiki.report; + +import com.kakao.techcampus.wekiki.post.Post; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReportJPARepository extends JpaRepository { + + +} From 9c99e21ad58640db4ee541d2fbc41e9188c2a0e2 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Mon, 23 Oct 2023 14:35:18 +0900 Subject: [PATCH 043/144] =?UTF-8?q?Refactor:=20Group=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9E=90=20Builder=EC=97=90=EC=84=9C=20memberCount=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=EA=B0=92=201=EB=A1=9C=20=EA=B3=A0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 생성 시 생성자만 있기에 1로 고정 --- .../main/java/com/kakao/techcampus/wekiki/group/Group.java | 4 ++-- .../java/com/kakao/techcampus/wekiki/group/GroupService.java | 2 -- .../unOfficialGroup/closedGroup/UnOfficialClosedGroup.java | 4 ++-- .../unOfficialGroup/openedGroup/UnOfficialOpenedGroup.java | 4 ++-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/Group.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/Group.java index d6669bd0..2674a852 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/Group.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/Group.java @@ -25,11 +25,11 @@ public class Group { private LocalDateTime created_at; @Builder - public Group(Long id, String groupName, String groupProfileImage, int memberCount, LocalDateTime created_at) { + public Group(Long id, String groupName, String groupProfileImage, LocalDateTime created_at) { this.id = id; this.groupName = groupName; this.groupProfileImage = groupProfileImage; - this.memberCount = memberCount; + this.memberCount = 1; this.created_at = created_at; } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java index a6bde8fd..91c728eb 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java @@ -85,7 +85,6 @@ protected UnOfficialClosedGroup buildUnOfficialClosedGroup(CreateUnOfficialGroup return UnOfficialClosedGroup.unOfficialClosedGroupBuilder() .groupName(requestDTO.groupName()) .groupProfileImage(requestDTO.groupImage()) - .memberCount(1) .created_at(LocalDateTime.now()) .build(); } @@ -98,7 +97,6 @@ protected UnOfficialOpenedGroup buildUnOfficialOpenedGroup(CreateUnOfficialGroup return UnOfficialOpenedGroup.unOfficialOpenedGroupBuilder() .groupName(requestDTO.groupName()) .groupProfileImage(requestDTO.groupImage()) - .memberCount(1) .created_at(LocalDateTime.now()) .introduction(requestDTO.introduction()) .entranceHint(requestDTO.entranceHint()) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java index 5902b3bc..c24f52c5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java @@ -20,8 +20,8 @@ public class UnOfficialClosedGroup extends Group { private Invitation invitation; @Builder(builderMethodName = "unOfficialClosedGroupBuilder") - public UnOfficialClosedGroup(Long id, String groupName, String groupProfileImage, int memberCount, LocalDateTime created_at) { - super(id, groupName, groupProfileImage, memberCount, created_at); + public UnOfficialClosedGroup(Long id, String groupName, String groupProfileImage, LocalDateTime created_at) { + super(id, groupName, groupProfileImage, created_at); this.invitation = Invitation.builder().group(this).build(); } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/openedGroup/UnOfficialOpenedGroup.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/openedGroup/UnOfficialOpenedGroup.java index fa0a0f46..a0e62024 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/openedGroup/UnOfficialOpenedGroup.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/openedGroup/UnOfficialOpenedGroup.java @@ -21,8 +21,8 @@ public class UnOfficialOpenedGroup extends Group { private String entrancePassword; @Builder(builderMethodName = "unOfficialOpenedGroupBuilder") - public UnOfficialOpenedGroup(Long id, String groupName, String groupProfileImage, int memberCount, LocalDateTime created_at, String introduction, String entranceHint, String entrancePassword) { - super(id, groupName, groupProfileImage, memberCount, created_at); + public UnOfficialOpenedGroup(Long id, String groupName, String groupProfileImage, LocalDateTime created_at, String introduction, String entranceHint, String entrancePassword) { + super(id, groupName, groupProfileImage, created_at); this.introduction = introduction; this.entranceHint = entranceHint; this.entrancePassword = entrancePassword; From 380806c1a3681c38c924847099968d69c7931d6b Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Mon, 23 Oct 2023 17:16:05 +0900 Subject: [PATCH 044/144] =?UTF-8?q?Refactor:=20=EC=B4=88=EB=8C=80=20?= =?UTF-8?q?=EB=A7=81=ED=81=AC=20=EA=B5=AC=ED=98=84=20=EB=B0=A9=EC=8B=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Redis를 통한 초대 링크 생성, 저장 및 확인 --- .../wekiki/group/GroupRestController.java | 7 ++- .../GetInvitationLinkResponseDTO.java | 2 +- .../wekiki/group/invitation/Invitation.java | 43 +++++++-------- .../group/officialGroup/OfficialGroup.java | 4 +- .../group/{ => service}/GroupService.java | 54 ++----------------- .../group/service/InvitationService.java | 48 +++++++++++++++++ .../closedGroup/UnOfficialClosedGroup.java | 4 -- 7 files changed, 79 insertions(+), 83 deletions(-) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{ => service}/GroupService.java (90%) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java index 9ec216e0..c9c7e755 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java @@ -5,6 +5,8 @@ import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.JoinGroupRequestDTO; import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.UpdateMyGroupPageDTO; import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.*; +import com.kakao.techcampus.wekiki.group.service.GroupService; +import com.kakao.techcampus.wekiki.group.service.InvitationService; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -19,6 +21,7 @@ public class GroupRestController { private final GroupService groupService; + private final InvitationService invitationService; /* 공개, 비공개 그룹 생성 @@ -112,7 +115,7 @@ public ResponseEntity joinGroup(@PathVariable("groupId") Long groupId, JoinGr @GetMapping("/{groupId}/invitationLink") public ResponseEntity getInvitationLink(@PathVariable("groupId") Long groupId) { - GetInvitationLinkResponseDTO responseDTO = groupService.getGroupInvitationLink(groupId); + GetInvitationLinkResponseDTO responseDTO = invitationService.getGroupInvitationCode(groupId); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } @@ -123,7 +126,7 @@ public ResponseEntity getInvitationLink(@PathVariable("groupId") Long groupId @GetMapping("/{invitationLink}") public ResponseEntity ValidateInvitation(@PathVariable String invitationLink) { - ValidateInvitationResponseDTO responseDTO = groupService.ValidateInvitation(invitationLink); + ValidateInvitationResponseDTO responseDTO = invitationService.ValidateInvitation(invitationLink); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/GetInvitationLinkResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/GetInvitationLinkResponseDTO.java index 333a7361..bfa56d9b 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/GetInvitationLinkResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/GetInvitationLinkResponseDTO.java @@ -10,6 +10,6 @@ public class GetInvitationLinkResponseDTO { private String invitationLink; public GetInvitationLinkResponseDTO(Invitation invitation) { - this.invitationLink = invitation.getInvitationLink(); + this.invitationLink = invitation.code(); } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java index 747f0c5a..650db254 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java @@ -1,36 +1,29 @@ package com.kakao.techcampus.wekiki.group.invitation; -import com.kakao.techcampus.wekiki.group.unOfficialGroup.closedGroup.UnOfficialClosedGroup; -import jakarta.persistence.*; -import lombok.*; import org.apache.commons.lang3.RandomStringUtils; +import java.time.Duration; import java.time.LocalDateTime; -@Getter -@Setter -@Entity -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "invitation_tb") -public class Invitation { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "group_id") - private UnOfficialClosedGroup group; +public record Invitation( + Long groupId, + LocalDateTime expiresAt, + String code +) { + private static final long DEFAULT_EXPIRED_DAYS = 7L; + private static final int INVITE_CODE_LENGTH = 32; - @Column(unique = true) - private String invitationCode; - private String invitationLink; + public static Invitation create(final Long groupId) { + LocalDateTime expiresAt = LocalDateTime.now().plusMinutes(Duration.ofDays(DEFAULT_EXPIRED_DAYS).toMinutes()); + String code = RandomStringUtils.randomAlphanumeric(INVITE_CODE_LENGTH); + return new Invitation(groupId, expiresAt, code); + } - private static final int INVITE_CODE_LENGTH = 32; + public boolean isUsableAt(final LocalDateTime now) { + return now.isBefore(expiresAt); + } - @Builder - public Invitation(UnOfficialClosedGroup group) { - this.group = group; - this.invitationCode = RandomStringUtils.randomAlphanumeric(INVITE_CODE_LENGTH); - this.invitationLink = group.getId() + "/" + invitationCode; + public Duration remainDuration(final LocalDateTime now) { + return Duration.between(now, expiresAt); } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/officialGroup/OfficialGroup.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/officialGroup/OfficialGroup.java index 956dfe50..dc5b0d7a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/officialGroup/OfficialGroup.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/officialGroup/OfficialGroup.java @@ -17,7 +17,7 @@ public class OfficialGroup extends Group { @Builder(builderMethodName = "officialGroupBuilder") - public OfficialGroup(Long id, String groupName, String groupProfileImage, int memberCount, LocalDateTime created_at) { - super(id, groupName, groupProfileImage, memberCount, created_at); + public OfficialGroup(Long id, String groupName, String groupProfileImage, LocalDateTime created_at) { + super(id, groupName, groupProfileImage, created_at); } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java similarity index 90% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 91c728eb..c87d4766 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -1,13 +1,14 @@ -package com.kakao.techcampus.wekiki.group; +package com.kakao.techcampus.wekiki.group.service; import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.error.exception.Exception500; +import com.kakao.techcampus.wekiki.group.Group; +import com.kakao.techcampus.wekiki.group.GroupJPARepository; import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.CreateUnOfficialGroupRequestDTO; import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.JoinGroupRequestDTO; import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.UpdateMyGroupPageDTO; import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.*; -import com.kakao.techcampus.wekiki.group.invitation.Invitation; import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.member.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.group.member.InactiveGroupMember; @@ -67,11 +68,9 @@ public CreateUnOfficialGroupResponseDTO createUnOfficialGroup(CreateUnOfficialGr // return return new CreateUnOfficialGroupResponseDTO(group); - } catch (Exception400 e) { - throw e; - } catch (Exception404 e) { + } catch (Exception400 | Exception404 e) { throw e; - } catch (Exception e) { + } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } } @@ -170,49 +169,6 @@ public SearchUnOfficialGroupResponseDTO searchUnOfficialGroupByKeyword(String ke } } - /* - 초대 링크 확인 - */ - public GetInvitationLinkResponseDTO getGroupInvitationLink(Long groupId) { - try { - Invitation invitation = groupJPARepository.findInvitationLinkByGroupId(groupId); - - return new GetInvitationLinkResponseDTO(invitation); - - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); - } - } - - /* - 비공식 비공개 그룹 초대 링크 확인 - - 확인 후 해당하는 그룹 Id 반환 - - 가입 url 생성 후 그룹 가입 API - */ - public ValidateInvitationResponseDTO ValidateInvitation(String invitationLink) { - try { - String[] invitation = invitationLink.split("/"); - - Long groupId = Long.parseLong(invitation[0]); - String invitationCode = invitation[1]; - - UnOfficialClosedGroup group = groupJPARepository.findUnOfficialClosedGroupById(groupId); - - // 초대 코드가 틀린 경우 - if (!group.getInvitation().getInvitationCode().equals(invitationCode)) { - throw new Exception400("초대 코드가 일치하지 않습니다."); - } - - return new ValidateInvitationResponseDTO(groupId); - - } catch (Exception400 e) { - throw e; - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); - } - } - - /* 비공식 공개 그룹 상세 정보 조회 */ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java new file mode 100644 index 00000000..267553fb --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -0,0 +1,48 @@ +package com.kakao.techcampus.wekiki.group.service; + +import com.kakao.techcampus.wekiki._core.utils.RedisUtility; +import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.GetInvitationLinkResponseDTO; +import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.ValidateInvitationResponseDTO; +import com.kakao.techcampus.wekiki.group.invitation.Invitation; +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; + +@RequiredArgsConstructor +@Service +public class InvitationService { + + private final RedisTemplate redisInvitation; + + private static final String INVITATION_PREFIX = "invitation:"; + + /* + InvitationCode 확인 + - 기존에 있으면 Code 반환 + - 기존에 없으면 새로 생성 + - new GetInvitationLinkResponseDTO(Invitation invitation) + */ + public GetInvitationLinkResponseDTO getGroupInvitationCode(Long groupId) { + + String key = INVITATION_PREFIX + groupId; + + // 기존 초대 링크 여부 확인 + Invitation invitation = redisInvitation.opsForValue().get(key); + + // 없으면 새로 생성 후 Redis 저장 + if(invitation == null) { + invitation = Invitation.create(groupId); + redisInvitation.opsForValue().set(key, invitation, invitation.remainDuration(LocalDateTime.now())); + } + + // 있으면 해당 초대 링크로 requestDTO 생성 + return new GetInvitationLinkResponseDTO(invitation); + } + + // 초대 링크를 통한 접근 시 유효한 초대 링크 확인, 해당 그룹으로 연결 + public ValidateInvitationResponseDTO ValidateInvitation(String invitationLink) { + return null; + } +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java index c24f52c5..33460aef 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java @@ -16,12 +16,8 @@ @DiscriminatorValue("un_official_closed_group") public class UnOfficialClosedGroup extends Group { - @OneToOne - private Invitation invitation; - @Builder(builderMethodName = "unOfficialClosedGroupBuilder") public UnOfficialClosedGroup(Long id, String groupName, String groupProfileImage, LocalDateTime created_at) { super(id, groupName, groupProfileImage, created_at); - this.invitation = Invitation.builder().group(this).build(); } } From 92116969f8b9b2ceb0e32bf98235759890ec0da3 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Mon, 23 Oct 2023 21:54:16 +0900 Subject: [PATCH 045/144] =?UTF-8?q?Feat:=20=EC=A3=BC=EA=B8=B0=EC=A0=81?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=A7=8C=EB=A3=8C=EB=90=9C=20=EC=B4=88?= =?UTF-8?q?=EB=8C=80=20=EB=A7=81=ED=81=AC=20=ED=99=95=EC=9D=B8=20=ED=9B=84?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 2주에 한 번, 새벽 4시에 만료된 초대 링크 관련 데이터들을 삭제 --- .../group/service/InvitationService.java | 42 +++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index 267553fb..a72abcc8 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -1,21 +1,25 @@ package com.kakao.techcampus.wekiki.group.service; -import com.kakao.techcampus.wekiki._core.utils.RedisUtility; +import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.GetInvitationLinkResponseDTO; import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.ValidateInvitationResponseDTO; import com.kakao.techcampus.wekiki.group.invitation.Invitation; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.time.LocalDateTime; +import java.util.Set; @RequiredArgsConstructor @Service public class InvitationService { private final RedisTemplate redisInvitation; + private final RedisTemplate redisGroupId; + private static final String GROUP_ID_PREFIX = "group_id:"; private static final String INVITATION_PREFIX = "invitation:"; /* @@ -26,15 +30,20 @@ public class InvitationService { */ public GetInvitationLinkResponseDTO getGroupInvitationCode(Long groupId) { - String key = INVITATION_PREFIX + groupId; + String groupKey = GROUP_ID_PREFIX + groupId; // 기존 초대 링크 여부 확인 - Invitation invitation = redisInvitation.opsForValue().get(key); + Invitation invitation = redisInvitation.opsForValue().get(groupKey); // 없으면 새로 생성 후 Redis 저장 + /* + redisInvitation : groupId로 Invitation 저장 + redisGroupId : invitation.code로 groupId 저장 + */ if(invitation == null) { invitation = Invitation.create(groupId); - redisInvitation.opsForValue().set(key, invitation, invitation.remainDuration(LocalDateTime.now())); + redisInvitation.opsForValue().set(groupKey, invitation, invitation.remainDuration(LocalDateTime.now())); + redisGroupId.opsForValue().set(INVITATION_PREFIX + invitation.code(), groupId, invitation.remainDuration(LocalDateTime.now())); } // 있으면 해당 초대 링크로 requestDTO 생성 @@ -43,6 +52,31 @@ public GetInvitationLinkResponseDTO getGroupInvitationCode(Long groupId) { // 초대 링크를 통한 접근 시 유효한 초대 링크 확인, 해당 그룹으로 연결 public ValidateInvitationResponseDTO ValidateInvitation(String invitationLink) { + return null; } + + /* + 초대 링크의 만료를 확인하고 삭제 + - redisInvitation, redisGroupId는 같은 수명을 가지기 때문에 하나만 확인해서 둘 다 삭제 + */ + private void removeExpiredInvitations() { + Set keys = redisInvitation.keys(GROUP_ID_PREFIX + "*"); + + for (String key : keys) { + Invitation invitation = redisInvitation.opsForValue().get(key); + + // 초대 링크 수명이 다하면 삭제 + if (invitation != null && !invitation.isUsableAt(LocalDateTime.now())) { + redisInvitation.delete(key); + redisGroupId.delete(INVITATION_PREFIX + invitation.code()); + } + } + } + + // 2주마다 화요일 새벽 4시에 Redis 검사 후 만료된 초대 링크 확인하고 삭제 + @Scheduled(cron = "0 0 4 */14 * 2") + public void removeExpiredInvitationsJob() { + removeExpiredInvitations(); + } } From 00430e2c9aa51ced58328120c5aac973281b54bd Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Mon, 23 Oct 2023 22:40:42 +0900 Subject: [PATCH 046/144] =?UTF-8?q?Feat:=20=EC=B4=88=EB=8C=80=20=EB=A7=81?= =?UTF-8?q?=ED=81=AC=20=ED=99=95=EC=9D=B8=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 초대 링크를 통한 접근 시 유효한 초대 링크인지 확인 --- .../group/service/InvitationService.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index a72abcc8..c08a6ed6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.group.service; +import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.GetInvitationLinkResponseDTO; import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.ValidateInvitationResponseDTO; @@ -53,7 +54,22 @@ public GetInvitationLinkResponseDTO getGroupInvitationCode(Long groupId) { // 초대 링크를 통한 접근 시 유효한 초대 링크 확인, 해당 그룹으로 연결 public ValidateInvitationResponseDTO ValidateInvitation(String invitationLink) { - return null; + // 초대 링크를 통해 groupId와 invitation 찾기 + Long groupId = redisGroupId.opsForValue().get(INVITATION_PREFIX + invitationLink); + + // 해당하는 groupId가 없는 경우 예외 처리 + if (groupId == null) { + throw new Exception404("잘못된 접근입니다."); + } + + // 초대 링크 기간 확인 + Invitation invitation = redisInvitation.opsForValue().get(groupId); + + if (invitation == null || !invitation.isUsableAt(LocalDateTime.now())) { + throw new Exception400("이미 만료된 초대 링크입니다."); + } + + return new ValidateInvitationResponseDTO(groupId); } /* @@ -76,7 +92,7 @@ private void removeExpiredInvitations() { // 2주마다 화요일 새벽 4시에 Redis 검사 후 만료된 초대 링크 확인하고 삭제 @Scheduled(cron = "0 0 4 */14 * 2") - public void removeExpiredInvitationsJob() { + private void removeExpiredInvitationsJob() { removeExpiredInvitations(); } } From 7264c2a287bd895827bc648a7a8359a3a01c5471 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Thu, 26 Oct 2023 19:29:06 +0900 Subject: [PATCH 047/144] =?UTF-8?q?Feat=20:=20=EC=97=94=ED=8B=B0=ED=8B=B0?= =?UTF-8?q?=20=EC=96=91=EB=B0=A9=ED=96=A5=20=EB=A7=A4=ED=95=91=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 엔티티들 사이에 단방향 매핑에서 양방향 매핑으로 수정하였습니다. --- .../com/kakao/techcampus/wekiki/comment/Comment.java | 9 +++++++-- .../com/kakao/techcampus/wekiki/group/Group.java | 7 +++++++ .../techcampus/wekiki/group/member/GroupMember.java | 8 +++++--- .../com/kakao/techcampus/wekiki/history/History.java | 5 +++-- .../com/kakao/techcampus/wekiki/member/Member.java | 7 +++++++ .../com/kakao/techcampus/wekiki/page/PageInfo.java | 9 ++++++++- .../java/com/kakao/techcampus/wekiki/post/Post.java | 12 ++++++++++-- .../com/kakao/techcampus/wekiki/report/Report.java | 5 ++--- 8 files changed, 49 insertions(+), 13 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java index 3a2ed18b..fd19d47e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java @@ -1,6 +1,7 @@ package com.kakao.techcampus.wekiki.comment; import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.member.Member; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; @@ -10,6 +11,8 @@ import lombok.NoArgsConstructor; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; @Getter @Entity @@ -20,10 +23,12 @@ public class Comment { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) private GroupMember groupMember; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) private Post post; + + private String content; private LocalDateTime created_at; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/Group.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/Group.java index d6669bd0..5d2165f9 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/Group.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/Group.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.group; +import com.kakao.techcampus.wekiki.group.member.GroupMember; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -7,6 +8,8 @@ import lombok.NoArgsConstructor; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; @Getter @Entity @@ -21,6 +24,10 @@ public class Group { private Long id; private String groupName; private String groupProfileImage; + + @OneToMany(mappedBy = "group") + private List groupMembers = new ArrayList<>(); + private int memberCount; private LocalDateTime created_at; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMember.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMember.java index 880c19ef..f697b78d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMember.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMember.java @@ -17,15 +17,17 @@ @Inheritance(strategy = InheritanceType.JOINED) @Table(name = "group_member_tb") @DiscriminatorColumn(name = "member_status", discriminatorType = DiscriminatorType.STRING) -public class GroupMember { +public class +GroupMember { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) private Member member; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) private Group group; + private String nickName; private int memberLevel; private LocalDateTime created_at; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java index 2dd4cd5a..eeebb30d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java @@ -20,9 +20,10 @@ public class History { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) private GroupMember groupMember; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="POST_ID") private Post post; private String title; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java index a3821430..0316dacd 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.member; +import com.kakao.techcampus.wekiki.group.member.GroupMember; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -7,6 +8,8 @@ import lombok.NoArgsConstructor; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; @Getter @Entity @@ -21,6 +24,10 @@ public class Member { private String email; private String password; private LocalDateTime created_at; + + @OneToMany(mappedBy = "member") + private List groupMembers = new ArrayList<>(); + @Enumerated(value = EnumType.STRING) Authority authority; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java index 3d24a0cf..3e9c04c5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java @@ -1,6 +1,8 @@ package com.kakao.techcampus.wekiki.page; import com.kakao.techcampus.wekiki.group.Group; +import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -8,6 +10,8 @@ import lombok.NoArgsConstructor; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; @Getter @Entity @@ -18,9 +22,12 @@ public class PageInfo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) private Group group; private String pageName; + + @OneToMany(mappedBy = "pageInfo") + private List posts = new ArrayList<>(); private int goodCount; private int badCount; private int viewCount; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java index d3257f3c..2b40b3f6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java @@ -1,6 +1,8 @@ package com.kakao.techcampus.wekiki.post; +import com.kakao.techcampus.wekiki.comment.Comment; import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.page.PageInfo; import jakarta.persistence.*; import lombok.AccessLevel; @@ -27,11 +29,17 @@ public class Post { private int orders; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) private GroupMember groupMember; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) private PageInfo pageInfo; + @OneToMany(mappedBy = "post") + private List historys = new ArrayList<>(); + + @OneToMany(mappedBy = "post") + private List comments = new ArrayList<>(); + private String title; private String content; private LocalDateTime created_at; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java index 73e6ad88..942c35f7 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java @@ -20,10 +20,10 @@ public class Report { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) private GroupMember fromMember; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) private History history; private String content; @@ -38,5 +38,4 @@ public Report(Long id, GroupMember groupMember, History history, String content, this.created_at = created_at; } - } From a390b3e9e9be579cd1a94cca0e597a72a20e182f Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Thu, 26 Oct 2023 19:30:27 +0900 Subject: [PATCH 048/144] =?UTF-8?q?Fix=20:=20HistoryJPARepository=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 자료구조 관련해서 에러 처리하였습니다. --- .../kakao/techcampus/wekiki/history/HistoryJPARepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java index 5631c26b..21c8502e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java @@ -25,5 +25,5 @@ public interface HistoryJPARepository extends JpaRepository { Page findHistoryWithMemberByPostId(@Param("postId") Long postId, Pageable pageable); @Query("SELECT h FROM History h WHERE h.post.id = :postId ORDER BY h.created_at DESC") - Page findHistoryByPostId(@Param("postId") Long postId, Pageable pageable); + List findHistoryByPostId(@Param("postId") Long postId, Pageable pageable); } From b48f2e24831df48febb5493680012fd20e3a3bbe Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Thu, 26 Oct 2023 19:31:09 +0900 Subject: [PATCH 049/144] =?UTF-8?q?Style=20:=20PostResponse=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - history 관련해서 변수명 수정하였습니다. --- .../java/com/kakao/techcampus/wekiki/post/PostResponse.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java index 1eef2665..fe2bfe24 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java @@ -77,7 +77,7 @@ public static class historyDTO{ Long historyId; String title; String content; - LocalDateTime created_at; + LocalDateTime createdAt; public historyDTO(GroupMember groupMember,History history){ this.memberId = groupMember.getId(); @@ -85,7 +85,7 @@ public historyDTO(GroupMember groupMember,History history){ this.historyId = history.getId(); this.title = history.getTitle(); this.content = history.getContent(); - this.created_at = history.getCreated_at(); + this.createdAt = history.getCreated_at(); } } From 469e8e710ef5d79badc6f01623caa1e4ecd0ef86 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 27 Oct 2023 15:05:51 +0900 Subject: [PATCH 050/144] =?UTF-8?q?Refactor:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Group 내부 패키지 구조 변경 --- .../techcampus/wekiki/comment/Comment.java | 6 +---- .../wekiki/comment/CommentResponse.java | 2 +- .../wekiki/comment/CommentService.java | 10 ++++---- .../{ => controller}/GroupRestController.java | 10 ++++---- .../wekiki/group/{ => domain}/Group.java | 4 ++-- .../{invitation => domain}/Invitation.java | 2 +- .../OfficialGroup.java | 3 +-- .../UnOfficialClosedGroup.java | 4 +--- .../UnOfficialOpenedGroup.java | 3 +-- .../member/ActiveGroupMember.java | 4 ++-- .../{ => domain}/member/GroupMember.java | 5 ++-- .../member/InactiveGroupMember.java | 4 ++-- .../CreateUnOfficialGroupRequestDTO.java | 2 +- .../requestDTO/JoinGroupRequestDTO.java | 2 +- .../requestDTO/UpdateMyGroupPageDTO.java | 2 +- .../CreateUnOfficialGroupResponseDTO.java | 4 ++-- .../GetInvitationLinkResponseDTO.java | 4 ++-- .../MyGroupHistoryResponseDTO.java | 2 +- .../responseDTO/MyGroupInfoResponseDTO.java | 6 ++--- .../responseDTO/SearchGroupDTO.java | 8 +++---- .../responseDTO/SearchGroupInfoDTO.java | 4 ++-- .../SearchOfficialGroupResponseDTO.java | 4 ++-- .../SearchUnOfficialGroupResponseDTO.java | 4 ++-- .../ValidateInvitationResponseDTO.java | 2 +- .../{ => repository}/GroupJPARepository.java | 10 ++------ .../GroupMemberJPARepository.java | 7 ++++-- .../wekiki/group/service/GroupService.java | 24 +++++++++---------- .../group/service/InvitationService.java | 8 +++---- .../techcampus/wekiki/history/History.java | 3 +-- .../wekiki/history/HistoryJPARepository.java | 2 +- .../techcampus/wekiki/member/Member.java | 2 +- .../wekiki/member/MemberResponse.java | 4 ++-- .../techcampus/wekiki/page/PageInfo.java | 3 +-- .../techcampus/wekiki/page/PageService.java | 10 ++++---- .../kakao/techcampus/wekiki/post/Post.java | 2 +- .../wekiki/post/PostJPARepository.java | 6 +---- .../techcampus/wekiki/post/PostResponse.java | 3 +-- .../techcampus/wekiki/post/PostService.java | 10 ++++---- .../techcampus/wekiki/report/Report.java | 3 +-- 39 files changed, 87 insertions(+), 111 deletions(-) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{ => controller}/GroupRestController.java (94%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{ => domain}/Group.java (90%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{invitation => domain}/Invitation.java (94%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{officialGroup => domain}/OfficialGroup.java (85%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{unOfficialGroup/closedGroup => domain}/UnOfficialClosedGroup.java (76%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{unOfficialGroup/openedGroup => domain}/UnOfficialOpenedGroup.java (88%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{ => domain}/member/ActiveGroupMember.java (89%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{ => domain}/member/GroupMember.java (91%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{ => domain}/member/InactiveGroupMember.java (90%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{groupDTO => dto}/requestDTO/CreateUnOfficialGroupRequestDTO.java (86%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{groupDTO => dto}/requestDTO/JoinGroupRequestDTO.java (51%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{groupDTO => dto}/requestDTO/UpdateMyGroupPageDTO.java (53%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{groupDTO => dto}/responseDTO/CreateUnOfficialGroupResponseDTO.java (67%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{groupDTO => dto}/responseDTO/GetInvitationLinkResponseDTO.java (67%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{groupDTO => dto}/responseDTO/MyGroupHistoryResponseDTO.java (89%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{groupDTO => dto}/responseDTO/MyGroupInfoResponseDTO.java (84%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{groupDTO => dto}/responseDTO/SearchGroupDTO.java (79%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{groupDTO => dto}/responseDTO/SearchGroupInfoDTO.java (81%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{groupDTO => dto}/responseDTO/SearchOfficialGroupResponseDTO.java (79%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{groupDTO => dto}/responseDTO/SearchUnOfficialGroupResponseDTO.java (77%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{groupDTO => dto}/responseDTO/ValidateInvitationResponseDTO.java (78%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{ => repository}/GroupJPARepository.java (77%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/{member => repository}/GroupMemberJPARepository.java (74%) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java index fd19d47e..2967434d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java @@ -1,8 +1,6 @@ package com.kakao.techcampus.wekiki.comment; -import com.kakao.techcampus.wekiki.group.member.GroupMember; -import com.kakao.techcampus.wekiki.history.History; -import com.kakao.techcampus.wekiki.member.Member; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.AccessLevel; @@ -11,8 +9,6 @@ import lombok.NoArgsConstructor; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; @Getter @Entity diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java index e555b93c..67025151 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java @@ -1,6 +1,6 @@ package com.kakao.techcampus.wekiki.comment; -import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.post.Post; import lombok.Getter; import lombok.Setter; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java index e87717eb..55d911fd 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java @@ -2,14 +2,12 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; -import com.kakao.techcampus.wekiki.group.Group; -import com.kakao.techcampus.wekiki.group.GroupJPARepository; -import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; -import com.kakao.techcampus.wekiki.group.member.GroupMemberJPARepository; +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.member.Member; import com.kakao.techcampus.wekiki.member.MemberJPARepository; -import com.kakao.techcampus.wekiki.page.PageInfo; -import com.kakao.techcampus.wekiki.page.PageJPARepository; import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java similarity index 94% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java index c9c7e755..a08ba8b4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java @@ -1,10 +1,10 @@ -package com.kakao.techcampus.wekiki.group; +package com.kakao.techcampus.wekiki.group.controller; import com.kakao.techcampus.wekiki._core.utils.ApiUtils; -import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.CreateUnOfficialGroupRequestDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.JoinGroupRequestDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.UpdateMyGroupPageDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.*; +import com.kakao.techcampus.wekiki.group.dto.requestDTO.CreateUnOfficialGroupRequestDTO; +import com.kakao.techcampus.wekiki.group.dto.requestDTO.JoinGroupRequestDTO; +import com.kakao.techcampus.wekiki.group.dto.requestDTO.UpdateMyGroupPageDTO; +import com.kakao.techcampus.wekiki.group.dto.responseDTO.*; import com.kakao.techcampus.wekiki.group.service.GroupService; import com.kakao.techcampus.wekiki.group.service.InvitationService; import jakarta.validation.Valid; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/Group.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java similarity index 90% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/Group.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java index 8beff4ee..f6fa5424 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/Group.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java @@ -1,6 +1,6 @@ -package com.kakao.techcampus.wekiki.group; +package com.kakao.techcampus.wekiki.group.domain; -import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Invitation.java similarity index 94% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Invitation.java index 650db254..abf314da 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/invitation/Invitation.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Invitation.java @@ -1,4 +1,4 @@ -package com.kakao.techcampus.wekiki.group.invitation; +package com.kakao.techcampus.wekiki.group.domain; import org.apache.commons.lang3.RandomStringUtils; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/officialGroup/OfficialGroup.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/OfficialGroup.java similarity index 85% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/officialGroup/OfficialGroup.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/OfficialGroup.java index dc5b0d7a..e7211282 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/officialGroup/OfficialGroup.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/OfficialGroup.java @@ -1,6 +1,5 @@ -package com.kakao.techcampus.wekiki.group.officialGroup; +package com.kakao.techcampus.wekiki.group.domain; -import com.kakao.techcampus.wekiki.group.Group; import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; import lombok.AccessLevel; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/UnOfficialClosedGroup.java similarity index 76% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/UnOfficialClosedGroup.java index 33460aef..010cc2b4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/closedGroup/UnOfficialClosedGroup.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/UnOfficialClosedGroup.java @@ -1,12 +1,10 @@ -package com.kakao.techcampus.wekiki.group.unOfficialGroup.closedGroup; +package com.kakao.techcampus.wekiki.group.domain; -import com.kakao.techcampus.wekiki.group.Group; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import com.kakao.techcampus.wekiki.group.invitation.Invitation; import java.time.LocalDateTime; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/openedGroup/UnOfficialOpenedGroup.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/UnOfficialOpenedGroup.java similarity index 88% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/openedGroup/UnOfficialOpenedGroup.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/UnOfficialOpenedGroup.java index a0e62024..1da0cd88 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/unOfficialGroup/openedGroup/UnOfficialOpenedGroup.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/UnOfficialOpenedGroup.java @@ -1,6 +1,5 @@ -package com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup; +package com.kakao.techcampus.wekiki.group.domain; -import com.kakao.techcampus.wekiki.group.Group; import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; import lombok.AccessLevel; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/ActiveGroupMember.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/ActiveGroupMember.java similarity index 89% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/ActiveGroupMember.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/ActiveGroupMember.java index c2bdf0e2..7853b4fb 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/ActiveGroupMember.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/ActiveGroupMember.java @@ -1,6 +1,6 @@ -package com.kakao.techcampus.wekiki.group.member; +package com.kakao.techcampus.wekiki.group.domain.member; -import com.kakao.techcampus.wekiki.group.Group; +import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.member.Member; import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMember.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/GroupMember.java similarity index 91% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMember.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/GroupMember.java index f697b78d..1a19aa21 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMember.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/GroupMember.java @@ -1,6 +1,6 @@ -package com.kakao.techcampus.wekiki.group.member; +package com.kakao.techcampus.wekiki.group.domain.member; -import com.kakao.techcampus.wekiki.group.Group; +import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.member.Member; import jakarta.persistence.*; import lombok.AccessLevel; @@ -9,7 +9,6 @@ import lombok.NoArgsConstructor; import java.time.LocalDateTime; -import java.util.UUID; @Getter @Entity diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/InactiveGroupMember.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/InactiveGroupMember.java similarity index 90% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/InactiveGroupMember.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/InactiveGroupMember.java index 716838d7..18862943 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/InactiveGroupMember.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/InactiveGroupMember.java @@ -1,6 +1,6 @@ -package com.kakao.techcampus.wekiki.group.member; +package com.kakao.techcampus.wekiki.group.domain.member; -import com.kakao.techcampus.wekiki.group.Group; +import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.member.Member; import jakarta.persistence.DiscriminatorValue; import jakarta.persistence.Entity; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/requestDTO/CreateUnOfficialGroupRequestDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/CreateUnOfficialGroupRequestDTO.java similarity index 86% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/requestDTO/CreateUnOfficialGroupRequestDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/CreateUnOfficialGroupRequestDTO.java index 06ae011f..6d88454a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/requestDTO/CreateUnOfficialGroupRequestDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/CreateUnOfficialGroupRequestDTO.java @@ -1,4 +1,4 @@ -package com.kakao.techcampus.wekiki.group.groupDTO.requestDTO; +package com.kakao.techcampus.wekiki.group.dto.requestDTO; import com.kakao.techcampus.wekiki.group.GroupType; import jakarta.validation.constraints.NotNull; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/requestDTO/JoinGroupRequestDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/JoinGroupRequestDTO.java similarity index 51% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/requestDTO/JoinGroupRequestDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/JoinGroupRequestDTO.java index c99391fa..c9b20491 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/requestDTO/JoinGroupRequestDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/JoinGroupRequestDTO.java @@ -1,4 +1,4 @@ -package com.kakao.techcampus.wekiki.group.groupDTO.requestDTO; +package com.kakao.techcampus.wekiki.group.dto.requestDTO; public record JoinGroupRequestDTO( String nickName diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/requestDTO/UpdateMyGroupPageDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/UpdateMyGroupPageDTO.java similarity index 53% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/requestDTO/UpdateMyGroupPageDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/UpdateMyGroupPageDTO.java index 2f601ea0..4f01b2f2 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/requestDTO/UpdateMyGroupPageDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/UpdateMyGroupPageDTO.java @@ -1,4 +1,4 @@ -package com.kakao.techcampus.wekiki.group.groupDTO.requestDTO; +package com.kakao.techcampus.wekiki.group.dto.requestDTO; public record UpdateMyGroupPageDTO( String groupNickName diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/CreateUnOfficialGroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/CreateUnOfficialGroupResponseDTO.java similarity index 67% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/CreateUnOfficialGroupResponseDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/CreateUnOfficialGroupResponseDTO.java index 860e544a..4c333a35 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/CreateUnOfficialGroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/CreateUnOfficialGroupResponseDTO.java @@ -1,6 +1,6 @@ -package com.kakao.techcampus.wekiki.group.groupDTO.responseDTO; +package com.kakao.techcampus.wekiki.group.dto.responseDTO; -import com.kakao.techcampus.wekiki.group.Group; +import com.kakao.techcampus.wekiki.group.domain.Group; public record CreateUnOfficialGroupResponseDTO( String groupName, diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/GetInvitationLinkResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetInvitationLinkResponseDTO.java similarity index 67% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/GetInvitationLinkResponseDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetInvitationLinkResponseDTO.java index bfa56d9b..24c507be 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/GetInvitationLinkResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetInvitationLinkResponseDTO.java @@ -1,6 +1,6 @@ -package com.kakao.techcampus.wekiki.group.groupDTO.responseDTO; +package com.kakao.techcampus.wekiki.group.dto.responseDTO; -import com.kakao.techcampus.wekiki.group.invitation.Invitation; +import com.kakao.techcampus.wekiki.group.domain.Invitation; import lombok.Getter; import lombok.Setter; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupHistoryResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupHistoryResponseDTO.java similarity index 89% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupHistoryResponseDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupHistoryResponseDTO.java index 190e4ca7..aecf0825 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupHistoryResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupHistoryResponseDTO.java @@ -1,4 +1,4 @@ -package com.kakao.techcampus.wekiki.group.groupDTO.responseDTO; +package com.kakao.techcampus.wekiki.group.dto.responseDTO; import com.kakao.techcampus.wekiki.history.History; import lombok.Getter; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupInfoResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupInfoResponseDTO.java similarity index 84% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupInfoResponseDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupInfoResponseDTO.java index cb31f8fd..dce4aaef 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/MyGroupInfoResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupInfoResponseDTO.java @@ -1,8 +1,8 @@ -package com.kakao.techcampus.wekiki.group.groupDTO.responseDTO; +package com.kakao.techcampus.wekiki.group.dto.responseDTO; -import com.kakao.techcampus.wekiki.group.Group; -import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.history.History; import lombok.Getter; import lombok.Setter; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupDTO.java similarity index 79% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupDTO.java index 51012ee8..4c41e0d2 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupDTO.java @@ -1,8 +1,8 @@ -package com.kakao.techcampus.wekiki.group.groupDTO.responseDTO; +package com.kakao.techcampus.wekiki.group.dto.responseDTO; -import com.kakao.techcampus.wekiki.group.Group; -import com.kakao.techcampus.wekiki.group.officialGroup.OfficialGroup; -import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.domain.OfficialGroup; +import com.kakao.techcampus.wekiki.group.domain.UnOfficialOpenedGroup; import lombok.Getter; import lombok.Setter; import org.springframework.data.domain.Page; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupInfoDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupInfoDTO.java similarity index 81% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupInfoDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupInfoDTO.java index ec1af5c9..65189ace 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchGroupInfoDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupInfoDTO.java @@ -1,6 +1,6 @@ -package com.kakao.techcampus.wekiki.group.groupDTO.responseDTO; +package com.kakao.techcampus.wekiki.group.dto.responseDTO; -import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; +import com.kakao.techcampus.wekiki.group.domain.UnOfficialOpenedGroup; import lombok.Getter; import lombok.Setter; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchOfficialGroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchOfficialGroupResponseDTO.java similarity index 79% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchOfficialGroupResponseDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchOfficialGroupResponseDTO.java index 36b063e6..a5ee68b4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchOfficialGroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchOfficialGroupResponseDTO.java @@ -1,6 +1,6 @@ -package com.kakao.techcampus.wekiki.group.groupDTO.responseDTO; +package com.kakao.techcampus.wekiki.group.dto.responseDTO; -import com.kakao.techcampus.wekiki.group.officialGroup.OfficialGroup; +import com.kakao.techcampus.wekiki.group.domain.OfficialGroup; import lombok.Getter; import lombok.Setter; import org.springframework.data.domain.Page; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchUnOfficialGroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchUnOfficialGroupResponseDTO.java similarity index 77% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchUnOfficialGroupResponseDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchUnOfficialGroupResponseDTO.java index 5bdbd9ca..70d6764d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/SearchUnOfficialGroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchUnOfficialGroupResponseDTO.java @@ -1,6 +1,6 @@ -package com.kakao.techcampus.wekiki.group.groupDTO.responseDTO; +package com.kakao.techcampus.wekiki.group.dto.responseDTO; -import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; +import com.kakao.techcampus.wekiki.group.domain.UnOfficialOpenedGroup; import lombok.Getter; import lombok.Setter; import org.springframework.data.domain.Page; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/ValidateInvitationResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/ValidateInvitationResponseDTO.java similarity index 78% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/ValidateInvitationResponseDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/ValidateInvitationResponseDTO.java index bb99b6ea..afa4940a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/groupDTO/responseDTO/ValidateInvitationResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/ValidateInvitationResponseDTO.java @@ -1,4 +1,4 @@ -package com.kakao.techcampus.wekiki.group.groupDTO.responseDTO; +package com.kakao.techcampus.wekiki.group.dto.responseDTO; import lombok.Getter; import lombok.Setter; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupJPARepository.java similarity index 77% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupJPARepository.java index 36ff6c4c..ee729772 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupJPARepository.java @@ -1,9 +1,6 @@ -package com.kakao.techcampus.wekiki.group; +package com.kakao.techcampus.wekiki.group.repository; -import com.kakao.techcampus.wekiki.group.invitation.Invitation; -import com.kakao.techcampus.wekiki.group.officialGroup.OfficialGroup; -import com.kakao.techcampus.wekiki.group.unOfficialGroup.closedGroup.UnOfficialClosedGroup; -import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; +import com.kakao.techcampus.wekiki.group.domain.*; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -11,9 +8,6 @@ import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import java.util.Comparator; -import java.util.List; - @Repository public interface GroupJPARepository extends JpaRepository { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMemberJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java similarity index 74% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMemberJPARepository.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java index 6a0b1f24..413f013f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/member/GroupMemberJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java @@ -1,6 +1,9 @@ -package com.kakao.techcampus.wekiki.group.member; +package com.kakao.techcampus.wekiki.group.repository; -import com.kakao.techcampus.wekiki.group.Group; +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.InactiveGroupMember; import com.kakao.techcampus.wekiki.member.Member; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index c87d4766..d90e2e76 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -3,18 +3,18 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.error.exception.Exception500; -import com.kakao.techcampus.wekiki.group.Group; -import com.kakao.techcampus.wekiki.group.GroupJPARepository; -import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.CreateUnOfficialGroupRequestDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.JoinGroupRequestDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.requestDTO.UpdateMyGroupPageDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.*; -import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; -import com.kakao.techcampus.wekiki.group.member.GroupMemberJPARepository; -import com.kakao.techcampus.wekiki.group.member.InactiveGroupMember; -import com.kakao.techcampus.wekiki.group.officialGroup.OfficialGroup; -import com.kakao.techcampus.wekiki.group.unOfficialGroup.closedGroup.UnOfficialClosedGroup; -import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; +import com.kakao.techcampus.wekiki.group.dto.requestDTO.CreateUnOfficialGroupRequestDTO; +import com.kakao.techcampus.wekiki.group.dto.requestDTO.JoinGroupRequestDTO; +import com.kakao.techcampus.wekiki.group.dto.requestDTO.UpdateMyGroupPageDTO; +import com.kakao.techcampus.wekiki.group.dto.responseDTO.*; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; +import com.kakao.techcampus.wekiki.group.domain.member.InactiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.OfficialGroup; +import com.kakao.techcampus.wekiki.group.domain.UnOfficialClosedGroup; +import com.kakao.techcampus.wekiki.group.domain.UnOfficialOpenedGroup; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.history.HistoryJPARepository; import com.kakao.techcampus.wekiki.member.Member; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index c08a6ed6..458d996f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -2,9 +2,9 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; -import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.GetInvitationLinkResponseDTO; -import com.kakao.techcampus.wekiki.group.groupDTO.responseDTO.ValidateInvitationResponseDTO; -import com.kakao.techcampus.wekiki.group.invitation.Invitation; +import com.kakao.techcampus.wekiki.group.dto.responseDTO.GetInvitationLinkResponseDTO; +import com.kakao.techcampus.wekiki.group.dto.responseDTO.ValidateInvitationResponseDTO; +import com.kakao.techcampus.wekiki.group.domain.Invitation; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Scheduled; @@ -92,7 +92,7 @@ private void removeExpiredInvitations() { // 2주마다 화요일 새벽 4시에 Redis 검사 후 만료된 초대 링크 확인하고 삭제 @Scheduled(cron = "0 0 4 */14 * 2") - private void removeExpiredInvitationsJob() { + protected void removeExpiredInvitationsJob() { removeExpiredInvitations(); } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java index eeebb30d..ffb41848 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java @@ -1,7 +1,6 @@ package com.kakao.techcampus.wekiki.history; -import com.kakao.techcampus.wekiki.group.member.GroupMember; -import com.kakao.techcampus.wekiki.group.member.InactiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.AccessLevel; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java index 21c8502e..a0a1662d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java @@ -1,6 +1,6 @@ package com.kakao.techcampus.wekiki.history; -import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java index 0316dacd..aec12609 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java @@ -1,6 +1,6 @@ package com.kakao.techcampus.wekiki.member; -import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java index 8f5b42fd..0e55b64c 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java @@ -1,8 +1,8 @@ package com.kakao.techcampus.wekiki.member; import com.fasterxml.jackson.annotation.JsonFormat; -import com.kakao.techcampus.wekiki.group.Group; -import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java index 3e9c04c5..9a1e9cc4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java @@ -1,7 +1,6 @@ package com.kakao.techcampus.wekiki.page; -import com.kakao.techcampus.wekiki.group.Group; -import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.AccessLevel; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 83a9d2ab..cf946573 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -4,10 +4,10 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.utils.IndexUtils; import com.kakao.techcampus.wekiki._core.utils.RedisUtility; -import com.kakao.techcampus.wekiki.group.Group; -import com.kakao.techcampus.wekiki.group.GroupJPARepository; -import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; -import com.kakao.techcampus.wekiki.group.member.GroupMemberJPARepository; +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.member.Member; import com.kakao.techcampus.wekiki.member.MemberJPARepository; import com.kakao.techcampus.wekiki.post.Post; @@ -25,8 +25,6 @@ import java.util.List; import java.util.stream.Collectors; -import static com.kakao.techcampus.wekiki._core.utils.SecurityUtils.currentMember; - @RequiredArgsConstructor @Service public class PageService { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java index 2b40b3f6..d297e126 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java @@ -1,7 +1,7 @@ package com.kakao.techcampus.wekiki.post; import com.kakao.techcampus.wekiki.comment.Comment; -import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.page.PageInfo; import jakarta.persistence.*; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java index 91914a67..bc524112 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java @@ -1,13 +1,9 @@ package com.kakao.techcampus.wekiki.post; -import com.kakao.techcampus.wekiki.page.PageInfo; -import com.kakao.techcampus.wekiki.page.PageInfoResponse; -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.data.repository.query.Param; -import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import org.springframework.stereotype.Repository; import java.util.List; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java index fe2bfe24..6d64680e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java @@ -1,8 +1,7 @@ package com.kakao.techcampus.wekiki.post; -import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.history.History; -import com.kakao.techcampus.wekiki.page.PageInfo; import com.kakao.techcampus.wekiki.report.Report; import lombok.Getter; import lombok.Setter; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index 5fdf30a9..6b80b91c 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -3,11 +3,11 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; -import com.kakao.techcampus.wekiki.group.Group; -import com.kakao.techcampus.wekiki.group.GroupJPARepository; -import com.kakao.techcampus.wekiki.group.member.ActiveGroupMember; -import com.kakao.techcampus.wekiki.group.member.GroupMember; -import com.kakao.techcampus.wekiki.group.member.GroupMemberJPARepository; +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.history.HistoryJPARepository; import com.kakao.techcampus.wekiki.member.Member; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java index 942c35f7..633e0256 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java @@ -1,8 +1,7 @@ package com.kakao.techcampus.wekiki.report; -import com.kakao.techcampus.wekiki.group.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.history.History; -import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; From 93e3bfe53247f68a6840760f6d3457ca0367d08a Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 27 Oct 2023 15:22:57 +0900 Subject: [PATCH 051/144] =?UTF-8?q?Feat:=20=EA=B7=B8=EB=A3=B9=20=EB=82=B4?= =?UTF-8?q?=20=EA=B7=B8=EB=A3=B9=EC=9B=90=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 양방향 매핑으로 Group 조회 후 GroupMember 리스트 반환 --- .../group/controller/GroupRestController.java | 10 ++++++++++ .../GetGroupMembersResponseDTO.java | 19 +++++++++++++++++++ .../wekiki/group/service/GroupService.java | 18 +++++++++++++++++- 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetGroupMembersResponseDTO.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java index a08ba8b4..bdafa4f3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java @@ -130,6 +130,16 @@ public ResponseEntity ValidateInvitation(@PathVariable String invitationLink) return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } + + /* + 그룹 내 그룹원 리스트 조회 + */ + @GetMapping("{groupId}/groupMembers") + public ResponseEntity getGroupMembers(@PathVariable("groupId") Long groupId) { + GetGroupMembersResponseDTO responseDTO = groupService.getGroupMembers(groupId); + + return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); + } /* 그룹 내 본인 정보 조회 diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetGroupMembersResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetGroupMembersResponseDTO.java new file mode 100644 index 00000000..91f95b22 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetGroupMembersResponseDTO.java @@ -0,0 +1,19 @@ +package com.kakao.techcampus.wekiki.group.dto.responseDTO; + +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class GetGroupMembersResponseDTO { + + private List groupMemberList; + + public GetGroupMembersResponseDTO(Group group) { + this.groupMemberList = group.getGroupMembers(); + } +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index d90e2e76..24cbf36e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -240,6 +240,22 @@ public void joinGroup(Long groupId, Long memberId, JoinGroupRequestDTO requestDT } } + /* + 그룹 내 그룹원 리스트 조회 + */ + public GetGroupMembersResponseDTO getGroupMembers(Long groupId) { + try { + Group group = getGroupById(groupId); + + return new GetGroupMembersResponseDTO(group); + + } catch (Exception404 e) { + throw e; + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); + } + } + /* 그룹 내 마이 페이지 */ @@ -264,7 +280,7 @@ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { } catch (Exception404 e) { throw e; - } catch (Exception e) { + } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } } From 062bc95ed81578d563d0bab7b7b1fabb7b9dd595 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 27 Oct 2023 16:20:48 +0900 Subject: [PATCH 052/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EA=B0=80=EC=9E=85=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 그룹 중복 가입 예외 처리 --- .../techcampus/wekiki/group/service/GroupService.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 24cbf36e..5178ceab 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -219,6 +219,11 @@ public void joinGroup(Long groupId, Long memberId, JoinGroupRequestDTO requestDT // TODO: Redis 활용 Group group = getGroupById(groupId); + // 이미 가입한 상태일 시 예외 처리 + if (groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId, groupId).isPresent()) { + throw new Exception400("이미 가입된 회원입니다."); + } + // 재가입 회원인지 확인 InactiveGroupMember wasGroupMember = groupMemberJPARepository.findInactiveGroupMemberByMemberAndGroup(member, group); @@ -233,9 +238,9 @@ public void joinGroup(Long groupId, Long memberId, JoinGroupRequestDTO requestDT // GroupMember 저장 groupMemberJPARepository.save(groupMember); - } catch (Exception404 e) { + } catch (Exception400 | Exception404 e) { throw e; - } catch (Exception e) { + } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } } From cace0d6712d64680ed2ecc3b481f27378bc73d8a Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 27 Oct 2023 17:53:03 +0900 Subject: [PATCH 053/144] =?UTF-8?q?Refactor:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PostMapping의 유효성 검사 추가 - EntityNotForupException 수정 --- .../group/controller/GroupRestController.java | 30 +++++++++++++----- .../CreateUnOfficialGroupRequestDTO.java | 12 ++++--- .../dto/requestDTO/GroupEntryRequestDTO.java | 6 ++++ .../dto/requestDTO/JoinGroupRequestDTO.java | 3 ++ .../dto/requestDTO/UpdateMyGroupPageDTO.java | 3 ++ .../group/repository/GroupJPARepository.java | 14 ++------- .../repository/GroupMemberJPARepository.java | 2 ++ .../wekiki/group/service/GroupService.java | 31 +++++++------------ 8 files changed, 60 insertions(+), 41 deletions(-) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupEntryRequestDTO.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java index bdafa4f3..077ad57e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java @@ -1,7 +1,9 @@ package com.kakao.techcampus.wekiki.group.controller; +import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.utils.ApiUtils; import com.kakao.techcampus.wekiki.group.dto.requestDTO.CreateUnOfficialGroupRequestDTO; +import com.kakao.techcampus.wekiki.group.dto.requestDTO.GroupEntryRequestDTO; import com.kakao.techcampus.wekiki.group.dto.requestDTO.JoinGroupRequestDTO; import com.kakao.techcampus.wekiki.group.dto.requestDTO.UpdateMyGroupPageDTO; import com.kakao.techcampus.wekiki.group.dto.responseDTO.*; @@ -10,6 +12,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindingResult; import org.springframework.validation.Errors; import org.springframework.web.bind.annotation.*; @@ -30,14 +33,18 @@ public class GroupRestController { - 그룹 생성 시 기본 페이지 생성은 어떻게 하는게 좋을까 */ @PostMapping("/create") - public ResponseEntity createUnOfficialGroup( - @RequestBody @Valid CreateUnOfficialGroupRequestDTO requestDTO, Errors errors) { + public ResponseEntity createUnOfficialGroup(@RequestBody @Valid CreateUnOfficialGroupRequestDTO requestDTO, BindingResult result) { + // 유효성 검사 + if (result.hasErrors()) { + throw new Exception400(result.getFieldError().getDefaultMessage()); + } CreateUnOfficialGroupResponseDTO response = groupService.createUnOfficialGroup(requestDTO, currentMember()); return ResponseEntity.ok().body(ApiUtils.success(response)); } - + + /* 그룹 검색 */ @@ -90,9 +97,9 @@ public ResponseEntity searchGroupInfo(@PathVariable("groupId") Long groupId) - 그 후 그룹 참가로 이동 */ @PostMapping("/{groupId}/entry") - public ResponseEntity groupEntry(@PathVariable("groupId") Long groupId, @RequestParam("entrancePassword") String entrancePassword) { + public ResponseEntity groupEntry(@PathVariable("groupId") Long groupId, GroupEntryRequestDTO requestDTO) { - groupService.groupEntry(groupId, entrancePassword); + groupService.groupEntry(groupId, requestDTO); return ResponseEntity.ok().body(ApiUtils.success(null)); } @@ -101,8 +108,12 @@ public ResponseEntity groupEntry(@PathVariable("groupId") Long groupId, @Requ 그룹 참가 */ @PostMapping("/{groupId}/join") - public ResponseEntity joinGroup(@PathVariable("groupId") Long groupId, JoinGroupRequestDTO requestDTO) { + public ResponseEntity joinGroup(@PathVariable("groupId") Long groupId, JoinGroupRequestDTO requestDTO, BindingResult result) { + // 유효성 검사 + if (result.hasErrors()) { + throw new Exception400(result.getFieldError().getDefaultMessage()); + } groupService.joinGroup(groupId, currentMember(), requestDTO); @@ -159,7 +170,12 @@ public ResponseEntity myGroupPage(@PathVariable("groupId") Long groupId) { 그룹 내 본인 정보 수정 */ @PatchMapping("/{groupId}/myInfo") - public ResponseEntity updateMyGroupPage(@PathVariable("groupId") Long groupId, UpdateMyGroupPageDTO requestDTO) { + public ResponseEntity updateMyGroupPage(@PathVariable("groupId") Long groupId, UpdateMyGroupPageDTO requestDTO, BindingResult result) { + + // 유효성 검사 + if (result.hasErrors()) { + throw new Exception400(result.getFieldError().getDefaultMessage()); + } groupService.updateMyGroupPage(groupId, currentMember(), requestDTO); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/CreateUnOfficialGroupRequestDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/CreateUnOfficialGroupRequestDTO.java index 6d88454a..cc5c9d9f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/CreateUnOfficialGroupRequestDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/CreateUnOfficialGroupRequestDTO.java @@ -4,10 +4,14 @@ import jakarta.validation.constraints.NotNull; public record CreateUnOfficialGroupRequestDTO( - @NotNull GroupType groupType, - @NotNull String groupName, - @NotNull String groupImage, - @NotNull String groupNickName, + @NotNull(message = "그룹 유형을 선택해 주세요.") + GroupType groupType, + @NotNull(message = "그룹 이름을 입력해 주세요.") + String groupName, + @NotNull(message = "그룹 이미지를 첨부해 주세요.") + String groupImage, + @NotNull(message = "그룹 닉네임을 설정해 주세요.") + String groupNickName, String introduction, String entranceHint, String entrancePassword diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupEntryRequestDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupEntryRequestDTO.java new file mode 100644 index 00000000..23d79e67 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupEntryRequestDTO.java @@ -0,0 +1,6 @@ +package com.kakao.techcampus.wekiki.group.dto.requestDTO; + +public record GroupEntryRequestDTO( + String entrancePassword +) { +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/JoinGroupRequestDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/JoinGroupRequestDTO.java index c9b20491..64570e33 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/JoinGroupRequestDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/JoinGroupRequestDTO.java @@ -1,6 +1,9 @@ package com.kakao.techcampus.wekiki.group.dto.requestDTO; +import jakarta.validation.constraints.NotNull; + public record JoinGroupRequestDTO( + @NotNull(message = "그룹 닉네임을 설정해 주세요.") String nickName ) { } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/UpdateMyGroupPageDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/UpdateMyGroupPageDTO.java index 4f01b2f2..927a7eb6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/UpdateMyGroupPageDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/UpdateMyGroupPageDTO.java @@ -1,6 +1,9 @@ package com.kakao.techcampus.wekiki.group.dto.requestDTO; +import jakarta.validation.constraints.NotNull; + public record UpdateMyGroupPageDTO( + @NotNull(message = "그룹 닉네임을 설정해 주세요.") String groupNickName ) { } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupJPARepository.java index ee729772..ceb5ba23 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupJPARepository.java @@ -8,6 +8,8 @@ import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface GroupJPARepository extends JpaRepository { @@ -23,15 +25,5 @@ public interface GroupJPARepository extends JpaRepository { 비공식 공개 그룹 상세 조회 */ @Query("SELECT g FROM UnOfficialOpenedGroup g WHERE g.id = :id") - UnOfficialOpenedGroup findUnOfficialOpenedGroupById(@Param("id") Long id); - - - /* - 초대 링크 - */ - @Query("SELECT g FROM UnOfficialClosedGroup g WHERE g.id = :id") - UnOfficialClosedGroup findUnOfficialClosedGroupById(@Param("id") Long id); - - @Query("SELECT g.invitation FROM UnOfficialClosedGroup g WHERE g.id = :id") - Invitation findInvitationLinkByGroupId(@Param("id") Long id); + Optional findUnOfficialOpenedGroupById(@Param("id") Long id); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java index 413f013f..f7213b04 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java @@ -20,4 +20,6 @@ public interface GroupMemberJPARepository extends JpaRepository findGroupMemberByMemberIdAndGroupId(Long memberId, Long groupId); + + ActiveGroupMember findActiveGroupMemberByMemberIdAndGroupId(Long memberId, Long groupId); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 5178ceab..1fcaf3e6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -4,6 +4,7 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.error.exception.Exception500; import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.dto.requestDTO.GroupEntryRequestDTO; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; import com.kakao.techcampus.wekiki.group.dto.requestDTO.CreateUnOfficialGroupRequestDTO; import com.kakao.techcampus.wekiki.group.dto.requestDTO.JoinGroupRequestDTO; @@ -21,7 +22,6 @@ import com.kakao.techcampus.wekiki.member.MemberJPARepository; import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; -import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -174,11 +174,12 @@ public SearchUnOfficialGroupResponseDTO searchUnOfficialGroupByKeyword(String ke */ public SearchGroupInfoDTO getGroupInfo(Long groupId) { try { - UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId); - return new SearchGroupInfoDTO(group); + UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId) + .orElseThrow(() -> new Exception404("그룹을 찾을 수 없습니다.")); - } catch (EntityNotFoundException e) { - throw new Exception404("그룹을 찾을 수 없습니다."); + return new SearchGroupInfoDTO(group); + } catch (Exception404 e) { + throw e; } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } @@ -188,19 +189,18 @@ public SearchGroupInfoDTO getGroupInfo(Long groupId) { /* 비공식 공개 그룹 입장 */ - public void groupEntry(Long groupId, String entrancePassword) { + public void groupEntry(Long groupId, GroupEntryRequestDTO requestDTO) { try { - UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId); + UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId) + .orElseThrow(() -> new Exception404("그룹을 찾을 수 없습니다.")); // 틀린 경우, 에러 핸들링 - if(!group.getEntrancePassword().equals(entrancePassword)) { + if(!group.getEntrancePassword().equals(requestDTO.entrancePassword())) { throw new Exception400("비밀번호가 틀렸습니다."); } - } catch (Exception400 e) { + } catch (Exception400 | Exception404 e) { throw e; - } catch (EntityNotFoundException e) { - throw new Exception404("그룹을 찾을 수 없습니다."); } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } @@ -216,7 +216,6 @@ public void joinGroup(Long groupId, Long memberId, JoinGroupRequestDTO requestDT Member member = getMemberById(memberId); // 그룹 정보 확인 - // TODO: Redis 활용 Group group = getGroupById(groupId); // 이미 가입한 상태일 시 예외 처리 @@ -270,7 +269,6 @@ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { Member member = getMemberById(memberId); // 그룹 정보 확인 - // TODO: Redis 활용 Group group = getGroupById(groupId); // 그룹 멤버 확인 @@ -300,7 +298,6 @@ public MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, Member member = getMemberById(memberId); // 그룹 정보 확인 - // TODO: Redis 활용 Group group = getGroupById(groupId); // 그룹 멤버 확인 @@ -329,11 +326,9 @@ public void updateMyGroupPage(Long groupId, Long memberId, UpdateMyGroupPageDTO Member member = getMemberById(memberId); // 그룹 정보 확인 - // TODO: Redis 활용 Group group = getGroupById(groupId); // 그룹 멤버 확인 - // TODO: Redis 활용 ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); // 그룹 닉네임 변경 @@ -360,12 +355,10 @@ public void leaveGroup(Long groupId, Long memberId) { Member member = getMemberById(memberId); // 그룹 정보 확인 - // TODO: Redis 활용 Group group = getGroupById(groupId); // 그룹 멤버 확인 - // TODO: Redis 활용 - ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); + ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId); // 탈퇴 그룹 회원 생성 InactiveGroupMember inactiveGroupMember = new InactiveGroupMember(activeGroupMember); From 57df73ed62e336cb3881125d931c27b265e4bd05 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 27 Oct 2023 18:22:55 +0900 Subject: [PATCH 054/144] =?UTF-8?q?Refactor:=20ActiveGroupMember=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Member, Group 객체 대신 MemberId와 GroupId로 Repository 접근 --- .../wekiki/comment/CommentService.java | 2 +- .../repository/GroupMemberJPARepository.java | 6 +-- .../wekiki/group/service/GroupService.java | 40 +++++-------------- .../techcampus/wekiki/page/PageService.java | 2 +- .../techcampus/wekiki/post/PostService.java | 2 +- 5 files changed, 14 insertions(+), 38 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java index 55d911fd..63c1774b 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java @@ -158,7 +158,7 @@ public Group checkGroupFromGroupId(Long groupId){ } public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ - return groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId,groupId) + return groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId,groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java index f7213b04..a272269c 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java @@ -13,13 +13,9 @@ @Repository public interface GroupMemberJPARepository extends JpaRepository { - @Query("SELECT agm FROM ActiveGroupMember agm WHERE agm.member = :member AND agm.group = :group") - ActiveGroupMember findActiveGroupMemberByMemberAndGroup(Member member, Group group); @Query("SELECT iagm FROM InactiveGroupMember iagm WHERE iagm.member = :member AND iagm.group = :group") InactiveGroupMember findInactiveGroupMemberByMemberAndGroup(Member member, Group group); @Query("SELECT agm FROM ActiveGroupMember agm WHERE agm.member.id = :memberId AND agm.group.id = :groupId") - Optional findGroupMemberByMemberIdAndGroupId(Long memberId, Long groupId); - - ActiveGroupMember findActiveGroupMemberByMemberIdAndGroupId(Long memberId, Long groupId); + Optional findActiveGroupMemberByMemberIdAndGroupId(Long memberId, Long groupId); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 1fcaf3e6..e4f9bc1f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -219,7 +219,7 @@ public void joinGroup(Long groupId, Long memberId, JoinGroupRequestDTO requestDT Group group = getGroupById(groupId); // 이미 가입한 상태일 시 예외 처리 - if (groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId, groupId).isPresent()) { + if (groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId).isPresent()) { throw new Exception400("이미 가입된 회원입니다."); } @@ -265,21 +265,16 @@ public GetGroupMembersResponseDTO getGroupMembers(Long groupId) { */ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { try { - // 회원 정보 확인 - Member member = getMemberById(memberId); - - // 그룹 정보 확인 - Group group = getGroupById(groupId); - // 그룹 멤버 확인 - ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); + ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) + .orElseThrow(() -> new Exception404("해당 그룹의 회원이 아닙니다")); // 해당 멤버의 Post 기록 정보 확인(History에서 가져옴) Pageable pageable = PageRequest.of(0, 10); Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember, pageable); // 그룹 이름, 현재 닉네임, Post 기록 정보를 담은 responseDTO 반환 - return new MyGroupInfoResponseDTO(group, groupMember, myHistoryList); + return new MyGroupInfoResponseDTO(groupMember.getGroup(), groupMember, myHistoryList); } catch (Exception404 e) { throw e; @@ -294,14 +289,9 @@ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { @Transactional public MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, int page, int size) { try { - // 회원 정보 확인 - Member member = getMemberById(memberId); - - // 그룹 정보 확인 - Group group = getGroupById(groupId); - // 그룹 멤버 확인 - ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); + ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) + .orElseThrow(() -> new Exception404("해당 그룹의 회원이 아닙니다")); Pageable pageable = PageRequest.of(page, size); Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember, pageable); @@ -322,14 +312,9 @@ public MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, @Transactional public void updateMyGroupPage(Long groupId, Long memberId, UpdateMyGroupPageDTO requestDTO) { try { - // 회원 정보 확인 - Member member = getMemberById(memberId); - - // 그룹 정보 확인 - Group group = getGroupById(groupId); - // 그룹 멤버 확인 - ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberAndGroup(member, group); + ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) + .orElseThrow(() -> new Exception404("해당 그룹의 회원이 아닙니다")); // 그룹 닉네임 변경 groupMember.update(requestDTO.groupNickName()); @@ -351,14 +336,9 @@ public void updateMyGroupPage(Long groupId, Long memberId, UpdateMyGroupPageDTO @Transactional public void leaveGroup(Long groupId, Long memberId) { try { - // 회원 정보 확인 - Member member = getMemberById(memberId); - - // 그룹 정보 확인 - Group group = getGroupById(groupId); - // 그룹 멤버 확인 - ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId); + ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) + .orElseThrow(() -> new Exception404("해당 그룹의 회원이 아닙니다")); // 탈퇴 그룹 회원 생성 InactiveGroupMember inactiveGroupMember = new InactiveGroupMember(activeGroupMember); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index cf946573..8de9f002 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -349,7 +349,7 @@ public Group checkGroupFromGroupId(Long groupId){ } public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ - return groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId,groupId) + return groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId,groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index 6b80b91c..fe4e2c06 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -223,7 +223,7 @@ public Group checkGroupFromGroupId(Long groupId){ } public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ - return groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId,groupId) + return groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId,groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); } From e46ed57a19b84d29d19cab1eb3b4bbab532ee282 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 27 Oct 2023 18:31:44 +0900 Subject: [PATCH 055/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=EC=9B=90?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 현재 활동중인 회원과 탈퇴한 회원 모두를 반환하는 것을 활동중인 회원만 반환하는 것으로 수정 --- .../dto/responseDTO/GetGroupMembersResponseDTO.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetGroupMembersResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetGroupMembersResponseDTO.java index 91f95b22..3214f32f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetGroupMembersResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetGroupMembersResponseDTO.java @@ -1,19 +1,23 @@ package com.kakao.techcampus.wekiki.group.dto.responseDTO; import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import lombok.Getter; import lombok.Setter; import java.util.List; +import java.util.stream.Collectors; @Getter @Setter public class GetGroupMembersResponseDTO { - private List groupMemberList; + private List activeGroupMemberList; public GetGroupMembersResponseDTO(Group group) { - this.groupMemberList = group.getGroupMembers(); + this.activeGroupMemberList = group.getGroupMembers().stream() + .filter(groupMember -> groupMember instanceof ActiveGroupMember) + .map(groupMember -> (ActiveGroupMember) groupMember) + .collect(Collectors.toList()); } } From 59bddb120db70afae75a435d7a6d1dabf6d8744e Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Fri, 27 Oct 2023 23:17:26 +0900 Subject: [PATCH 056/144] =?UTF-8?q?Feat=20:=20Post=EB=9E=91=20Comment=20?= =?UTF-8?q?=EC=96=91=EB=B0=A9=ED=96=A5=20=EB=A7=A4=ED=95=91=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?api=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Comment 조회 부분에서 fetch join으로 comment 조회시 groupMember 도 같이 들고와서 1+N 문제해결 - Comment 생성시에 Post에 addComment 편의 메소드 추가 - Comment 삭제, 수정시 fetch join으로 groupMember도 같이 들고와 쿼리 최적화진행 --- wekiki/Dockerfile | 16 ++++++++++++++++ .../kakao/techcampus/wekiki/comment/Comment.java | 7 +++---- .../wekiki/comment/CommentJPARepository.java | 11 +++++++++-- .../wekiki/comment/CommentService.java | 10 ++++++---- .../com/kakao/techcampus/wekiki/post/Post.java | 9 +++++++-- 5 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 wekiki/Dockerfile diff --git a/wekiki/Dockerfile b/wekiki/Dockerfile new file mode 100644 index 00000000..ba724222 --- /dev/null +++ b/wekiki/Dockerfile @@ -0,0 +1,16 @@ +# Dockerfile + +# jdk17 Image Start +FROM openjdk:17 + +# 인자 설정 - JAR_File +ARG JAR_FILE=build/libs/*.jar + +# jar 파일 복제 +COPY ${JAR_FILE} app.jar + +# 인자 설정 부분과 jar 파일 복제 부분 합쳐서 진행해도 무방 +#COPY build/libs/*.jar app.jar + +# 실행 명령어 +ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java index fd19d47e..ac6afdb1 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java @@ -5,10 +5,7 @@ import com.kakao.techcampus.wekiki.member.Member; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; import java.time.LocalDateTime; import java.util.ArrayList; @@ -25,6 +22,8 @@ public class Comment { private Long id; @ManyToOne(fetch = FetchType.LAZY) private GroupMember groupMember; + + @Setter @ManyToOne(fetch = FetchType.LAZY) private Post post; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java index a40c1be8..5ae9c1ef 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.comment; +import com.kakao.techcampus.wekiki.post.Post; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -7,11 +8,17 @@ import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface CommentJPARepository extends JpaRepository { - @Query("SELECT c FROM Comment c WHERE c.post.id = :postId ORDER BY c.created_at") - Page findCommentsByPostId(@Param("postId") Long postId, Pageable pageable); + @Query("SELECT c FROM Comment c LEFT JOIN FETCH c.groupMember WHERE c.post.id = :postId ORDER BY c.created_at") + Page findCommentsByPostIdWithGroupMembers(@Param("postId") Long postId, Pageable pageable); + + @Query("SELECT c FROM Comment c LEFT JOIN FETCH c.groupMember WHERE c.id = :commentId") + Optional findCommentWithGroupMember(@Param("commentId") Long commentId); + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java index e87717eb..d18bf5cf 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java @@ -21,6 +21,7 @@ import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @RequiredArgsConstructor @@ -51,7 +52,7 @@ public CommentResponse.getCommentDTO getComment(Long memberId, Long groupId, Lon // 5. postId로 Comment 다 가져오기 Pageable pageable = PageRequest.of(pageNo, COMMENT_COUNT); - Page comments = commentJPARepository.findCommentsByPostId(postId, pageable); // TODO : fetch join (comment랑 groupmember) + Page comments = commentJPARepository.findCommentsByPostIdWithGroupMembers(postId, pageable); // 6. return DTO List commentDTOs = comments.getContent() @@ -78,10 +79,10 @@ public CommentResponse.createCommentDTO createComment(Long memberId, Long groupI // 4. comment 생성 Comment comment = Comment.builder() .groupMember(groupMember) - .post(post) .content(content) .created_at(LocalDateTime.now()) .build(); + post.addComment(comment); Comment savedComment = commentJPARepository.save(comment); // 5. return DTO @@ -170,8 +171,9 @@ public Post checkPostFromPostId(Long postId){ } public Comment checkCommentFromCommentId(Long commentId){ - return commentJPARepository.findById(commentId) - .orElseThrow(() -> new Exception404("존재하지 않는 댓글 입니다.")); + return commentJPARepository.findCommentWithGroupMember(commentId). + orElseThrow(() -> new Exception404("존재하지 않는 댓글 입니다.")); + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java index 2b40b3f6..2256c789 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java @@ -34,10 +34,10 @@ public class Post { @ManyToOne(fetch = FetchType.LAZY) private PageInfo pageInfo; - @OneToMany(mappedBy = "post") + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true) private List historys = new ArrayList<>(); - @OneToMany(mappedBy = "post") + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true) private List comments = new ArrayList<>(); private String title; @@ -74,4 +74,9 @@ public void modifyPost(GroupMember groupMember, String title, String content){ public void updateGroupMember(GroupMember groupMember) { this.groupMember = groupMember; } + + public void addComment(Comment comment){ + this.comments.add(comment); + comment.setPost(this); + } } From aa68078e88680f228f4448ac8df998b8cf2f5213 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 28 Oct 2023 00:15:29 +0900 Subject: [PATCH 057/144] =?UTF-8?q?Feat=20:=20Post=EB=9E=91=20History,Comm?= =?UTF-8?q?ent=20=EC=96=91=EB=B0=A9=ED=96=A5=20=EB=A7=A4=ED=95=91=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?api=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Post 생성시에 pageInfo에 편의 메서드 구현으로 List에 추가해줌 - Post 생성,수정시 History도 생성해서 List에 추가해줌 --- .../techcampus/wekiki/history/History.java | 7 +++--- .../techcampus/wekiki/page/PageInfo.java | 5 ++++ .../kakao/techcampus/wekiki/post/Post.java | 23 +++++++++++++++---- .../techcampus/wekiki/post/PostService.java | 13 ++++------- 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java index eeebb30d..503d80a9 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java @@ -4,10 +4,7 @@ import com.kakao.techcampus.wekiki.group.member.InactiveGroupMember; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; import java.time.LocalDateTime; @@ -22,6 +19,8 @@ public class History { private Long id; @ManyToOne(fetch = FetchType.LAZY) private GroupMember groupMember; + + @Setter @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="POST_ID") private Post post; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java index 3e9c04c5..f401c020 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java @@ -58,5 +58,10 @@ public void updatePage(){ this.updated_at = LocalDateTime.now(); } + public void addPost(Post post){ + this.posts.add(post); + post.setPageInfo(this); + } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java index 2256c789..1a7f4071 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java @@ -5,10 +5,7 @@ import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.page.PageInfo; import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; import java.time.LocalDateTime; import java.util.ArrayList; @@ -31,6 +28,8 @@ public class Post { @ManyToOne(fetch = FetchType.LAZY) private GroupMember groupMember; + + @Setter @ManyToOne(fetch = FetchType.LAZY) private PageInfo pageInfo; @@ -64,11 +63,20 @@ public void minusOrder(){ this.orders--; } - public void modifyPost(GroupMember groupMember, String title, String content){ + public History modifyPost(GroupMember groupMember, String title, String content){ this.groupMember = groupMember; this.title = title; this.content = content; this.created_at = LocalDateTime.now(); + + History newHistory = History.builder() + .post(this) + .build(); + + this.historys.add(newHistory); + newHistory.setPost(this); + + return newHistory; } public void updateGroupMember(GroupMember groupMember) { @@ -79,4 +87,9 @@ public void addComment(Comment comment){ this.comments.add(comment); comment.setPost(this); } + + public void addHistory(History history){ + this.historys.add(history); + history.setPost(this); + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index 5fdf30a9..147e997e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -70,17 +70,18 @@ public PostResponse.createPostDTO createPost(Long memberId,Long groupId,Long pag .parent(parent) .orders(order) .groupMember(groupMember) - .pageInfo(pageInfo) .title(title) .content(content) .created_at(LocalDateTime.now()) .build(); + pageInfo.addPost(newPost); Post savedPost = postJPARepository.save(newPost); // 8. 히스토리 생성 History newHistory = History.builder() .post(savedPost) .build(); + savedPost.addHistory(newHistory); historyJPARepository.save(newHistory); // 9. return DTO @@ -108,11 +109,7 @@ public PostResponse.modifyPostDTO modifyPost(Long memberId , Long groupId, Long } // 6. 다르면 Post 수정후 히스토리 생성 저장 - post.modifyPost(groupMember,title,content); - - History newHistory = History.builder() - .post(post) - .build(); + History newHistory = post.modifyPost(groupMember, title, content); historyJPARepository.save(newHistory); // 7. return DTO @@ -168,11 +165,11 @@ public PostResponse.deletePostDTO deletePost(Long memberId, Long groupId, Long p // 6. child post 존재 안하면 history + post 삭제 시키기 PostResponse.deletePostDTO response = new PostResponse.deletePostDTO(post); - historyJPARepository.deleteByPostId(postId); postJPARepository.deleteById(postId); // 7. order값 앞으로 땡기기 - postJPARepository.findPostsByPageIdAndOrderGreaterThan(post.getPageInfo().getId(), post.getOrders()); + postJPARepository.findPostsByPageIdAndOrderGreaterThan(post.getPageInfo().getId(), post.getOrders()) + .stream().forEach(p -> p.minusOrder()); // 8. return DTO; return response; From db82c255f4ce2ab9c47f05139666dc5983f577b5 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 28 Oct 2023 12:46:45 +0900 Subject: [PATCH 058/144] =?UTF-8?q?Feat=20:=20PageInfo=EB=9E=91=20Post?= =?UTF-8?q?=EC=9D=98=20=EC=96=91=EB=B0=A9=ED=96=A5=20=EB=A7=A4=ED=95=91?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20API=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 페이지 조회시 fetch join을 활용하여 성능 개선 - 페이지 생성,조회시 where문에 groupId도 추가 - 페이지 검색시 fetch join으로 1+N 문제 해결 --- .../wekiki/page/PageInfoRequest.java | 1 - .../wekiki/page/PageJPARepository.java | 24 ++++++--- .../wekiki/page/PageRestController.java | 2 +- .../techcampus/wekiki/page/PageService.java | 53 +++++++++++-------- 4 files changed, 47 insertions(+), 33 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoRequest.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoRequest.java index 73fecee7..225cbdfe 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoRequest.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoRequest.java @@ -9,7 +9,6 @@ public class PageInfoRequest { @Setter public static class createPageDTO { private String pageName; - private Long groupId; } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java index acfd5183..5f8227ab 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java @@ -13,16 +13,24 @@ @Repository public interface PageJPARepository extends JpaRepository { - @Query("SELECT p FROM PageInfo p WHERE p.pageName LIKE :keyword%") - Page findPagesByTitleContainingKeyword(String keyword, Pageable pageable); + @Query("SELECT p FROM PageInfo p WHERE p.group.id = :groupId AND p.pageName LIKE :keyword%") + Page findPagesByTitleContainingKeyword(@Param("groupId") Long groupId, @Param("keyword") String keyword, Pageable pageable); -// @Query("SELECT p FROM PageInfo p WHERE p.group.id = :groupId ORDER BY p.updated_at DESC") -// List findByGroupIdOrderByUpdatedAtDesc(Long groupId, Pageable pageable); + @Query("SELECT p FROM PageInfo p WHERE p.group.id = :groupId ORDER BY p.updated_at DESC") + List findByGroupIdOrderByUpdatedAtDesc(Long groupId, Pageable pageable); + + @Query("SELECT p FROM PageInfo p where p.group.id = :groupId AND p.pageName=:title") + Optional findByTitle(@Param("groupId") Long groupId, @Param("title") String title); + + @Query("SELECT p FROM PageInfo p LEFT JOIN FETCH p.posts ps WHERE p.group.id = :groupId AND p.pageName = :title ORDER BY ps.orders ASC") + Optional findByTitleWithPosts(@Param("groupId") Long groupId, @Param("title") String title); + + @Query("SELECT p FROM PageInfo p LEFT JOIN FETCH p.posts ps WHERE p.id = :pageId ORDER BY ps.orders ASC") + Optional findByPageIdWithPosts(@Param("pageId") Long pageId); + + @Query("SELECT p FROM PageInfo p LEFT JOIN FETCH p.posts ps WHERE p.group.id = :groupId AND p.pageName LIKE :keyword%") + Page findPagesWithPosts(@Param("groupId") Long groupId, @Param("keyword") String keyword, Pageable pageable); - @Query("SELECT p FROM PageInfo p ORDER BY p.updated_at DESC") - List findOrderByUpdatedAtDesc(Pageable pageable); - @Query("SELECT p FROM PageInfo p where p.pageName=:title") - Optional findByTitle(@Param("title") String title); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index 049d7506..9c283f8a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -39,7 +39,7 @@ public ResponseEntity getPageFromId(@PathVariable Long groupid,@PathVariable @PostMapping("/create") public ResponseEntity createPage(@PathVariable Long groupid,@RequestBody PageInfoRequest.createPageDTO request) { - PageInfoResponse.createPageDTO response = pageService.createPage(request.getPageName(), request.getGroupId(), currentMember()); + PageInfoResponse.createPageDTO response = pageService.createPage(request.getPageName(), groupid, currentMember()); return ResponseEntity.ok(ApiUtils.success(response)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 83a9d2ab..badfa56a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -25,7 +25,6 @@ import java.util.List; import java.util.stream.Collectors; -import static com.kakao.techcampus.wekiki._core.utils.SecurityUtils.currentMember; @RequiredArgsConstructor @Service @@ -55,10 +54,11 @@ public PageInfoResponse.getPageIndexDTO getPageIndex(Long groupId,Long memberId, checkGroupMember(memberId, groupId); // 4. pageId로 PageInfo 객체 들고오기 - PageInfo pageInfo = checkPageFromPageId(pageId); + PageInfo pageInfo = pageJPARepository.findByPageIdWithPosts(pageId) + .orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); // 5. 해당 groupId를 들고 있는 모든 페이지 Order 순으로 들고오기 - List posts = postJPARepository.findPostsByPageIdOrderByOrderAsc(pageId); + List posts = pageInfo.getPosts(); // 6. 목차 생성하기 HashMap indexs = indexUtils.createIndex(posts); @@ -116,11 +116,12 @@ public PageInfoResponse.getPageFromIdDTO getPageFromId(Long memberId,Long groupI // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) checkGroupMember(memberId, groupId); - // 4. 존재하는 페이지 인지 체크 - PageInfo pageInfo = checkPageFromPageId(pageId); + // 4. pageId로 PageInfo 객체 들고오기 + PageInfo pageInfo = pageJPARepository.findByPageIdWithPosts(pageId) + .orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); // 5. 해당 groupId를 들고 있는 모든 페이지 Order 순으로 들고오기 - List posts = postJPARepository.findPostsByPageIdOrderByOrderAsc(pageId); + List posts = pageInfo.getPosts(); // 6. 목차 생성하기 HashMap indexs = indexUtils.createIndex(posts); @@ -146,8 +147,8 @@ public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Lon // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) checkGroupMember(memberId, groupId); - // 4. 그룹 내 동일한 title의 Page가 존재하는지 체크 (TODO : where 문에 groupId 추가) - if(pageJPARepository.findByTitle(title).isPresent()){ + // 4. 그룹 내 동일한 title의 Page가 존재하는지 체크 + if(pageJPARepository.findByTitle(groupId,title).isPresent()){ throw new Exception400("이미 존재하는 페이지입니다."); } @@ -234,24 +235,23 @@ public PageInfoResponse.searchPageDTO searchPage(Long groupId, Long memberId, in // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) checkGroupMember(memberId, groupId); - // 4. keyword로 존재하는 page title에 keyword를 가지고 있는 페이지들 다 가져오기 (TODO : group 추가) - PageRequest pageRequest = PageRequest.of(pageNo, PAGE_COUNT); - Page pages = pageJPARepository.findPagesByTitleContainingKeyword(keyword, pageRequest); + // 4. keyword로 존재하는 page title에 keyword를 가지고 있는 페이지들 다 가져오기 + // (TODO : fetch join이랑 Pagination 함께 쓰면 페이지네이션을 애플리케이션에 들고온 다음 하게됨) + Page pages = pageJPARepository.findPagesWithPosts(groupId, keyword, PageRequest.of(pageNo, PAGE_COUNT)); - // 해당 Page들을 FK로 가지고 있는 Post들 중에 Orders가 1인 Post들 가져오기 + // 5. 해당 Page들을 FK로 가지고 있는 Post들 중에 Orders가 1인 Post들 가져오기 List res = new ArrayList<>(); + for(PageInfo p : pages.getContent()){ - List posts = postJPARepository.findFirstPost(p.getId()); + List posts = p.getPosts(); if(posts.size() == 0){ res.add(new PageInfoResponse.searchPageDTO.pageDTO(p,"")); }else{ res.add(new PageInfoResponse.searchPageDTO.pageDTO(p,posts.get(0).getContent())); } - // TODO : 성능 개선이 필요하긴 할듯 - // posts.get(0)가 존재하면 DTO 만들어서 던지기 + 고려할 점 : post의 contents만 들고 오는 방식? (흠..) } - // 4. pages로 DTO return + // 6. pages로 DTO return return new PageInfoResponse.searchPageDTO(res); } @@ -267,10 +267,9 @@ public PageInfoResponse.getRecentPageDTO getRecentPage(Long memberId , Long grou // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) checkGroupMember(memberId, groupId); - // 4. 특정 groupId를 가진 Page들 order by로 updated_at이 최신인 10개 Page 조회 (TODO : where 문에 groupId 추가) + // 4. 특정 groupId를 가진 Page들 order by로 updated_at이 최신인 10개 Page 조회 Pageable pageable = PageRequest.of(0, 10); - List recentPage = pageJPARepository.findOrderByUpdatedAtDesc(pageable); - //List recentPage = pageJPARepository.findByGroupIdOrderByUpdatedAtDesc(groupId, pageable); + List recentPage = pageJPARepository.findByGroupIdOrderByUpdatedAtDesc(groupId, pageable); // 5. return DTO List collect = recentPage.stream().map(pageInfo -> @@ -291,13 +290,12 @@ public PageInfoResponse.getPageFromIdDTO getPageFromTitle(Long memberId, Long gr // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) checkGroupMember(memberId, groupId); - // 4. groupId랑 title로 Page있는지 확인 (TODO : where 문에 groupId 추가) - PageInfo page = pageJPARepository.findByTitle(title). + // 4. groupId랑 title로 Page있는지 확인 (fetch join으로 post들 가져오기) + PageInfo page = pageJPARepository.findByTitleWithPosts(groupId,title). orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); - // 5. 해당 pageId를 들고있는 모든 페이지 Order 순으로 들고오기 - List posts = postJPARepository.findPostsByPageIdOrderByOrderAsc(page.getId()); + List posts = page.getPosts(); // 6. 목차 생성하기 HashMap indexs = indexUtils.createIndex(posts); @@ -351,6 +349,15 @@ public Group checkGroupFromGroupId(Long groupId){ } public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ + + /* + TODO : groupMember 들고올때 fetch join으로 member랑 group도 들고오기 + 여기서 + if(activeGroupMember.getMember() != null) throw new Exception404("존재하지 않는 회원입니다."); + if(activeGroupMember.getGroup() != null) throw new Exception404("존재하지 않는 그룹입니다."); + 체크 추가해주기 + */ + return groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId,groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); } From 95ac86e9df01cb3ef4c6f53a5a3125593b1ff33c Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 28 Oct 2023 12:57:43 +0900 Subject: [PATCH 059/144] =?UTF-8?q?Refactor=20:=20ResponseEntitiy<=3F>?= =?UTF-8?q?=EC=97=90=20=ED=83=80=EC=9E=85=EC=9D=84=20=EC=A0=95=ED=99=95?= =?UTF-8?q?=ED=9E=88=20=EB=AA=85=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 멘토님 피드백으로 ResponseEntitiy에 타입을 정확히 명시해주었습니다. --- .../wekiki/comment/CommentController.java | 22 +++++++------- .../wekiki/page/PageRestController.java | 29 ++++++++----------- .../wekiki/post/PostRestController.java | 19 +++++------- 3 files changed, 31 insertions(+), 39 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java index ddf01674..41888fc9 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentController.java @@ -16,9 +16,9 @@ public class CommentController { private final CommentService commentService; @GetMapping("/post/{postid}/comment") - public ResponseEntity getComment(@PathVariable Long groupid, - @PathVariable Long postid, - @RequestParam(value = "page", defaultValue = "1") int page){ + public ResponseEntity> getComment(@PathVariable Long groupid, + @PathVariable Long postid, + @RequestParam(value = "page", defaultValue = "1") int page){ CommentResponse.getCommentDTO response = commentService.getComment(currentMember(), groupid, postid, page-1); @@ -26,9 +26,9 @@ public ResponseEntity getComment(@PathVariable Long groupid, } @PostMapping("/post/{postid}/comment") - public ResponseEntity createComment(@PathVariable Long groupid, - @PathVariable Long postid, - @RequestBody CommentRequest.createComment request){ + public ResponseEntity> createComment(@PathVariable Long groupid, + @PathVariable Long postid, + @RequestBody CommentRequest.createComment request){ CommentResponse.createCommentDTO response = commentService.createComment(currentMember(), groupid, postid, request.getContent()); @@ -36,8 +36,8 @@ public ResponseEntity createComment(@PathVariable Long groupid, } @DeleteMapping("/comment/{commentid}") - public ResponseEntity deleteComment(@PathVariable Long groupid, - @PathVariable Long commentid){ + public ResponseEntity> deleteComment(@PathVariable Long groupid, + @PathVariable Long commentid){ CommentResponse.deleteCommentDTO response = commentService.deleteComment(currentMember(), groupid, commentid); @@ -46,9 +46,9 @@ public ResponseEntity deleteComment(@PathVariable Long groupid, } @PatchMapping("/comment/{commentid}") - public ResponseEntity updateComment(@PathVariable Long groupid, - @PathVariable Long commentid, - @RequestBody CommentRequest.updateComment request){ + public ResponseEntity> updateComment(@PathVariable Long groupid, + @PathVariable Long commentid, + @RequestBody CommentRequest.updateComment request){ CommentResponse.updateCommentDTO response = commentService.updateComment(currentMember(), groupid, commentid, request.getContent()); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index 9c283f8a..ac4de364 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -6,8 +6,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.List; - import static com.kakao.techcampus.wekiki._core.utils.SecurityUtils.currentMember; @RestController @@ -23,7 +21,7 @@ public class PageRestController { */ @GetMapping("/{pageid}") - public ResponseEntity getPageFromId(@PathVariable Long groupid,@PathVariable Long pageid) { + public ResponseEntity> getPageFromId(@PathVariable Long groupid, @PathVariable Long pageid) { PageInfoResponse.getPageFromIdDTO response = pageService.getPageFromId(currentMember(), groupid, pageid); @@ -37,7 +35,7 @@ public ResponseEntity getPageFromId(@PathVariable Long groupid,@PathVariable */ @PostMapping("/create") - public ResponseEntity createPage(@PathVariable Long groupid,@RequestBody PageInfoRequest.createPageDTO request) { + public ResponseEntity> createPage(@PathVariable Long groupid, @RequestBody PageInfoRequest.createPageDTO request) { PageInfoResponse.createPageDTO response = pageService.createPage(request.getPageName(), groupid, currentMember()); @@ -50,7 +48,7 @@ public ResponseEntity createPage(@PathVariable Long groupid,@RequestBody Page */ @DeleteMapping("/{pageid}") - public ResponseEntity deletePage(@PathVariable Long groupid,@PathVariable Long pageid) { + public ResponseEntity> deletePage(@PathVariable Long groupid, @PathVariable Long pageid) { PageInfoResponse.deletePageDTO response = pageService.deletePage(currentMember(),groupid, pageid); @@ -63,7 +61,7 @@ public ResponseEntity deletePage(@PathVariable Long groupid,@PathVariable Lon */ @PostMapping("/{pageid}/like") - public ResponseEntity likePage(@PathVariable Long groupid,@PathVariable Long pageid) { + public ResponseEntity> likePage(@PathVariable Long groupid, @PathVariable Long pageid) { PageInfoResponse.likePageDTO response = pageService.likePage(pageid, groupid, currentMember()); @@ -76,12 +74,11 @@ public ResponseEntity likePage(@PathVariable Long groupid,@PathVariable Long */ @PostMapping("/{pageid}/hate") - public ResponseEntity hatePage(@PathVariable Long groupid,@PathVariable Long pageid) { + public ResponseEntity> hatePage(@PathVariable Long groupid, @PathVariable Long pageid) { PageInfoResponse.hatePageDTO response = pageService.hatePage(pageid, groupid, currentMember()); return ResponseEntity.ok(ApiUtils.success(response)); - } /* @@ -90,7 +87,7 @@ public ResponseEntity hatePage(@PathVariable Long groupid,@PathVariable Long */ @GetMapping("/{pageid}/index") - public ResponseEntity getPageIndex(@PathVariable Long groupid,@PathVariable Long pageid) { + public ResponseEntity> getPageIndex(@PathVariable Long groupid, @PathVariable Long pageid) { PageInfoResponse.getPageIndexDTO response = pageService.getPageIndex(groupid,currentMember(), pageid); @@ -106,7 +103,7 @@ public ResponseEntity getPageIndex(@PathVariable Long groupid,@PathVariable L */ @GetMapping - public ResponseEntity getPageFromTitle(@PathVariable Long groupid,@RequestParam(value = "title") String title) { + public ResponseEntity> getPageFromTitle(@PathVariable Long groupid, @RequestParam(value = "title") String title) { PageInfoResponse.getPageFromIdDTO response = pageService.getPageFromTitle(currentMember(), groupid,title); @@ -120,9 +117,9 @@ public ResponseEntity getPageFromTitle(@PathVariable Long groupid,@RequestPar */ @GetMapping("/search") - public ResponseEntity searchPage(@PathVariable Long groupid, - @RequestParam(value = "keyword" , defaultValue = "") String keyword, - @RequestParam(value = "page", defaultValue = "1") int page) { + public ResponseEntity> searchPage(@PathVariable Long groupid, + @RequestParam(value = "keyword" , defaultValue = "") String keyword, + @RequestParam(value = "page", defaultValue = "1") int page) { PageInfoResponse.searchPageDTO response = pageService.searchPage(groupid, currentMember(),page - 1, keyword); @@ -135,7 +132,7 @@ public ResponseEntity searchPage(@PathVariable Long groupid, */ @GetMapping("/recent") - public ResponseEntity getRecentPage(@PathVariable Long groupid){ + public ResponseEntity> getRecentPage(@PathVariable Long groupid){ PageInfoResponse.getRecentPageDTO response = pageService.getRecentPage(currentMember(), groupid); @@ -148,12 +145,10 @@ public ResponseEntity getRecentPage(@PathVariable Long groupid){ */ @GetMapping("/link") - public ResponseEntity getPageLink(@PathVariable Long groupid, @RequestParam(value = "title") String title){ + public ResponseEntity> getPageLink(@PathVariable Long groupid, @RequestParam(value = "title") String title){ PageInfoResponse.getPageLinkDTO response = pageService.getPageLink(currentMember(), groupid, title); return ResponseEntity.ok(ApiUtils.success(response)); } - - } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java index fcbc51c3..9d267b05 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java @@ -2,8 +2,6 @@ import com.kakao.techcampus.wekiki._core.utils.ApiUtils; -import com.kakao.techcampus.wekiki.history.History; -import com.kakao.techcampus.wekiki.history.HistoryJPARepository; import com.kakao.techcampus.wekiki.report.Report; import com.kakao.techcampus.wekiki.report.ReportJPARepository; import lombok.RequiredArgsConstructor; @@ -21,8 +19,10 @@ public class PostRestController { private final PostService postService; + private final ReportJPARepository reportJPARepository; + @PostMapping("/create") - public ResponseEntity createPost(@PathVariable Long groupid, @RequestBody PostRequest.createPostDTO request) { + public ResponseEntity> createPost(@PathVariable Long groupid, @RequestBody PostRequest.createPostDTO request) { PostResponse.createPostDTO response = postService.createPost(currentMember(),groupid,request.getPageId(), request.getParentPostId(), request.getOrder(), request.getTitle(),request.getContent()); @@ -31,7 +31,7 @@ public ResponseEntity createPost(@PathVariable Long groupid, @RequestBody Pos } @PutMapping("/modify") - public ResponseEntity modifyPost(@PathVariable Long groupid,@RequestBody PostRequest.modifyPostDTO request){ + public ResponseEntity> modifyPost(@PathVariable Long groupid, @RequestBody PostRequest.modifyPostDTO request){ PostResponse.modifyPostDTO response = postService.modifyPost(currentMember(),groupid, request.getPostId(), request.getTitle(), request.getContent()); @@ -39,7 +39,7 @@ public ResponseEntity modifyPost(@PathVariable Long groupid,@RequestBody Post } @DeleteMapping("/{postid}") - public ResponseEntity deletePost(@PathVariable Long groupid, @PathVariable Long postid){ + public ResponseEntity> deletePost(@PathVariable Long groupid, @PathVariable Long postid){ PostResponse.deletePostDTO response = postService.deletePost(currentMember(), groupid, postid); @@ -47,8 +47,8 @@ public ResponseEntity deletePost(@PathVariable Long groupid, @PathVariable Lo } @GetMapping("/{postid}/history") - public ResponseEntity getPostHistory(@PathVariable Long groupid,@PathVariable Long postid - ,@RequestParam(value = "page", defaultValue = "1") int page){ + public ResponseEntity> getPostHistory(@PathVariable Long groupid, @PathVariable Long postid + , @RequestParam(value = "page", defaultValue = "1") int page){ PostResponse.getPostHistoryDTO response = postService.getPostHistory(currentMember(), groupid, postid, page - 1); @@ -56,14 +56,11 @@ public ResponseEntity getPostHistory(@PathVariable Long groupid,@PathVariable } @PostMapping("/report") - public ResponseEntity createReport(@PathVariable Long groupid , @RequestBody PostRequest.createReportDTO request){ + public ResponseEntity> createReport(@PathVariable Long groupid , @RequestBody PostRequest.createReportDTO request){ PostResponse.createReportDTO response = postService.createReport(currentMember(), groupid, request.getPostId(), request.getContent()); return ResponseEntity.ok(ApiUtils.success(response)); } - - - } From 3df7a44b01cd19a1ece49685bc22c31f67beabe8 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sun, 29 Oct 2023 20:52:10 +0900 Subject: [PATCH 060/144] =?UTF-8?q?Feat=20:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=EC=8B=9C=EC=97=90=20response=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 페이지 조회할 api 호출시에 response에 order랑 parentPostId 추가해줬습니다. --- .../kakao/techcampus/wekiki/page/PageInfoResponse.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index cd53d017..ee4d8866 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -140,11 +140,20 @@ public static class postDTO { String postTitle; String content; + int order; + Long parentPostId; + public postDTO(Post post, String index){ this.postId = post.getId(); this.index = index; this.postTitle = post.getTitle(); this.content = post.getContent(); + this.order = post.getOrders(); + if(post.getParent() != null){ + this.parentPostId = post.getParent().getId(); + }else{ + this.parentPostId = 0L; + } } } } From f589df756031cf4d00b90a313f681c5ab0597cae Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Mon, 30 Oct 2023 11:23:08 +0900 Subject: [PATCH 061/144] =?UTF-8?q?Refactor:=20DTO=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - requestDTO, responseDTO를 한 class에 모아놓음 --- .../group/controller/GroupRestController.java | 34 +++--- .../CreateUnOfficialGroupRequestDTO.java | 19 --- .../dto/requestDTO/GroupEntryRequestDTO.java | 6 - .../group/dto/requestDTO/GroupRequestDTO.java | 39 +++++++ .../dto/requestDTO/JoinGroupRequestDTO.java | 9 -- .../dto/requestDTO/UpdateMyGroupPageDTO.java | 9 -- .../CreateUnOfficialGroupResponseDTO.java | 12 -- .../GetGroupMembersResponseDTO.java | 23 ---- .../GetInvitationLinkResponseDTO.java | 15 --- .../dto/responseDTO/GroupResponseDTO.java | 110 ++++++++++++++++++ .../MyGroupHistoryResponseDTO.java | 20 ---- .../responseDTO/MyGroupInfoResponseDTO.java | 40 ------- .../group/dto/responseDTO/SearchGroupDTO.java | 38 ------ .../dto/responseDTO/SearchGroupInfoDTO.java | 28 ----- .../SearchOfficialGroupResponseDTO.java | 19 --- .../SearchUnOfficialGroupResponseDTO.java | 19 --- .../ValidateInvitationResponseDTO.java | 14 --- .../wekiki/group/service/GroupService.java | 47 ++++---- .../group/service/InvitationService.java | 11 +- 19 files changed, 191 insertions(+), 321 deletions(-) delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/CreateUnOfficialGroupRequestDTO.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupEntryRequestDTO.java create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupRequestDTO.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/JoinGroupRequestDTO.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/UpdateMyGroupPageDTO.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/CreateUnOfficialGroupResponseDTO.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetGroupMembersResponseDTO.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetInvitationLinkResponseDTO.java create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GroupResponseDTO.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupHistoryResponseDTO.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupInfoResponseDTO.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupDTO.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupInfoDTO.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchOfficialGroupResponseDTO.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchUnOfficialGroupResponseDTO.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/ValidateInvitationResponseDTO.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java index 077ad57e..5caa40c0 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java @@ -2,10 +2,7 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.utils.ApiUtils; -import com.kakao.techcampus.wekiki.group.dto.requestDTO.CreateUnOfficialGroupRequestDTO; -import com.kakao.techcampus.wekiki.group.dto.requestDTO.GroupEntryRequestDTO; -import com.kakao.techcampus.wekiki.group.dto.requestDTO.JoinGroupRequestDTO; -import com.kakao.techcampus.wekiki.group.dto.requestDTO.UpdateMyGroupPageDTO; +import com.kakao.techcampus.wekiki.group.dto.requestDTO.*; import com.kakao.techcampus.wekiki.group.dto.responseDTO.*; import com.kakao.techcampus.wekiki.group.service.GroupService; import com.kakao.techcampus.wekiki.group.service.InvitationService; @@ -13,7 +10,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.validation.BindingResult; -import org.springframework.validation.Errors; import org.springframework.web.bind.annotation.*; import static com.kakao.techcampus.wekiki._core.utils.SecurityUtils.currentMember; @@ -33,13 +29,13 @@ public class GroupRestController { - 그룹 생성 시 기본 페이지 생성은 어떻게 하는게 좋을까 */ @PostMapping("/create") - public ResponseEntity createUnOfficialGroup(@RequestBody @Valid CreateUnOfficialGroupRequestDTO requestDTO, BindingResult result) { + public ResponseEntity createUnOfficialGroup(@RequestBody @Valid GroupRequestDTO.CreateUnOfficialGroupRequestDTO requestDTO, BindingResult result) { // 유효성 검사 if (result.hasErrors()) { throw new Exception400(result.getFieldError().getDefaultMessage()); } - CreateUnOfficialGroupResponseDTO response = groupService.createUnOfficialGroup(requestDTO, currentMember()); + GroupResponseDTO.CreateUnOfficialGroupResponseDTO response = groupService.createUnOfficialGroup(requestDTO, currentMember()); return ResponseEntity.ok().body(ApiUtils.success(response)); } @@ -51,7 +47,7 @@ public ResponseEntity createUnOfficialGroup(@RequestBody @Valid CreateUnOffic @GetMapping("/search") public ResponseEntity searchGroup(@RequestParam(value = "keyword", required = false) String keyword) { - SearchGroupDTO responseDTO = groupService.searchGroupByKeyword(keyword); + GroupResponseDTO.SearchGroupDTO responseDTO = groupService.searchGroupByKeyword(keyword); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } @@ -64,7 +60,7 @@ public ResponseEntity searchOfficialGroup(@RequestParam(value = "keyword", re @RequestParam(value = "page", defaultValue = "1") int page, @RequestParam(value = "size", defaultValue = "10") int size) { - SearchOfficialGroupResponseDTO responseDTO = groupService.searchOfficialGroupByKeyword(keyword, page, size); + GroupResponseDTO.SearchOfficialGroupResponseDTO responseDTO = groupService.searchOfficialGroupByKeyword(keyword, page, size); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } @@ -77,7 +73,7 @@ public ResponseEntity searchUnOfficialGroup(@RequestParam(value = "keyword", @RequestParam(value = "page", defaultValue = "1") int page, @RequestParam(value = "size", defaultValue = "10") int size) { - SearchUnOfficialGroupResponseDTO responseDTO = groupService.searchUnOfficialGroupByKeyword(keyword, page, size); + GroupResponseDTO.SearchUnOfficialGroupResponseDTO responseDTO = groupService.searchUnOfficialGroupByKeyword(keyword, page, size); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } @@ -87,7 +83,7 @@ public ResponseEntity searchUnOfficialGroup(@RequestParam(value = "keyword", */ @GetMapping("/search/{grouId}") public ResponseEntity searchGroupInfo(@PathVariable("groupId") Long groupId) { - SearchGroupInfoDTO response = groupService.getGroupInfo(groupId); + GroupResponseDTO.SearchGroupInfoDTO response = groupService.getGroupInfo(groupId); return ResponseEntity.ok().body(ApiUtils.success(response)); } @@ -97,7 +93,7 @@ public ResponseEntity searchGroupInfo(@PathVariable("groupId") Long groupId) - 그 후 그룹 참가로 이동 */ @PostMapping("/{groupId}/entry") - public ResponseEntity groupEntry(@PathVariable("groupId") Long groupId, GroupEntryRequestDTO requestDTO) { + public ResponseEntity groupEntry(@PathVariable("groupId") Long groupId, GroupRequestDTO.GroupEntryRequestDTO requestDTO) { groupService.groupEntry(groupId, requestDTO); @@ -108,7 +104,7 @@ public ResponseEntity groupEntry(@PathVariable("groupId") Long groupId, Group 그룹 참가 */ @PostMapping("/{groupId}/join") - public ResponseEntity joinGroup(@PathVariable("groupId") Long groupId, JoinGroupRequestDTO requestDTO, BindingResult result) { + public ResponseEntity joinGroup(@PathVariable("groupId") Long groupId, GroupRequestDTO.JoinGroupRequestDTO requestDTO, BindingResult result) { // 유효성 검사 if (result.hasErrors()) { @@ -126,7 +122,7 @@ public ResponseEntity joinGroup(@PathVariable("groupId") Long groupId, JoinGr @GetMapping("/{groupId}/invitationLink") public ResponseEntity getInvitationLink(@PathVariable("groupId") Long groupId) { - GetInvitationLinkResponseDTO responseDTO = invitationService.getGroupInvitationCode(groupId); + GroupResponseDTO.GetInvitationLinkResponseDTO responseDTO = invitationService.getGroupInvitationCode(groupId); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } @@ -137,7 +133,7 @@ public ResponseEntity getInvitationLink(@PathVariable("groupId") Long groupId @GetMapping("/{invitationLink}") public ResponseEntity ValidateInvitation(@PathVariable String invitationLink) { - ValidateInvitationResponseDTO responseDTO = invitationService.ValidateInvitation(invitationLink); + GroupResponseDTO.ValidateInvitationResponseDTO responseDTO = invitationService.ValidateInvitation(invitationLink); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } @@ -147,7 +143,7 @@ public ResponseEntity ValidateInvitation(@PathVariable String invitationLink) */ @GetMapping("{groupId}/groupMembers") public ResponseEntity getGroupMembers(@PathVariable("groupId") Long groupId) { - GetGroupMembersResponseDTO responseDTO = groupService.getGroupMembers(groupId); + GroupResponseDTO.GetGroupMembersResponseDTO responseDTO = groupService.getGroupMembers(groupId); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } @@ -161,7 +157,7 @@ public ResponseEntity getGroupMembers(@PathVariable("groupId") Long groupId) @GetMapping("/{groupId}/myInfo") public ResponseEntity myGroupPage(@PathVariable("groupId") Long groupId) { - MyGroupInfoResponseDTO responseDTO = groupService.getMyGroupInfo(groupId, currentMember()); + GroupResponseDTO.MyGroupInfoResponseDTO responseDTO = groupService.getMyGroupInfo(groupId, currentMember()); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } @@ -170,7 +166,7 @@ public ResponseEntity myGroupPage(@PathVariable("groupId") Long groupId) { 그룹 내 본인 정보 수정 */ @PatchMapping("/{groupId}/myInfo") - public ResponseEntity updateMyGroupPage(@PathVariable("groupId") Long groupId, UpdateMyGroupPageDTO requestDTO, BindingResult result) { + public ResponseEntity updateMyGroupPage(@PathVariable("groupId") Long groupId, GroupRequestDTO.UpdateMyGroupPageDTO requestDTO, BindingResult result) { // 유효성 검사 if (result.hasErrors()) { @@ -191,7 +187,7 @@ public ResponseEntity myGroupHistoryPage(@PathVariable("groupId") Long groupI @RequestParam(value = "size", defaultValue = "10") int size ) { - MyGroupHistoryResponseDTO responseDTO = groupService.getMyGroupHistory(groupId, currentMember(), page, size); + GroupResponseDTO.MyGroupHistoryResponseDTO responseDTO = groupService.getMyGroupHistory(groupId, currentMember(), page, size); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/CreateUnOfficialGroupRequestDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/CreateUnOfficialGroupRequestDTO.java deleted file mode 100644 index cc5c9d9f..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/CreateUnOfficialGroupRequestDTO.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.requestDTO; - -import com.kakao.techcampus.wekiki.group.GroupType; -import jakarta.validation.constraints.NotNull; - -public record CreateUnOfficialGroupRequestDTO( - @NotNull(message = "그룹 유형을 선택해 주세요.") - GroupType groupType, - @NotNull(message = "그룹 이름을 입력해 주세요.") - String groupName, - @NotNull(message = "그룹 이미지를 첨부해 주세요.") - String groupImage, - @NotNull(message = "그룹 닉네임을 설정해 주세요.") - String groupNickName, - String introduction, - String entranceHint, - String entrancePassword -) { -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupEntryRequestDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupEntryRequestDTO.java deleted file mode 100644 index 23d79e67..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupEntryRequestDTO.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.requestDTO; - -public record GroupEntryRequestDTO( - String entrancePassword -) { -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupRequestDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupRequestDTO.java new file mode 100644 index 00000000..01e48c35 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupRequestDTO.java @@ -0,0 +1,39 @@ +package com.kakao.techcampus.wekiki.group.dto.requestDTO; + +import com.kakao.techcampus.wekiki.group.GroupType; +import jakarta.validation.constraints.NotNull; + +public class GroupRequestDTO { + + public record CreateUnOfficialGroupRequestDTO( + @NotNull(message = "그룹 유형을 선택해 주세요.") + GroupType groupType, + @NotNull(message = "그룹 이름을 입력해 주세요.") + String groupName, + @NotNull(message = "그룹 이미지를 첨부해 주세요.") + String groupImage, + @NotNull(message = "그룹 닉네임을 설정해 주세요.") + String groupNickName, + String introduction, + String entranceHint, + String entrancePassword + ) { + } + + public record GroupEntryRequestDTO( + String entrancePassword + ) { + } + + public record JoinGroupRequestDTO( + @NotNull(message = "그룹 닉네임을 설정해 주세요.") + String nickName + ) { + } + + public record UpdateMyGroupPageDTO( + @NotNull(message = "그룹 닉네임을 설정해 주세요.") + String groupNickName + ) { + } +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/JoinGroupRequestDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/JoinGroupRequestDTO.java deleted file mode 100644 index 64570e33..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/JoinGroupRequestDTO.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.requestDTO; - -import jakarta.validation.constraints.NotNull; - -public record JoinGroupRequestDTO( - @NotNull(message = "그룹 닉네임을 설정해 주세요.") - String nickName -) { -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/UpdateMyGroupPageDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/UpdateMyGroupPageDTO.java deleted file mode 100644 index 927a7eb6..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/UpdateMyGroupPageDTO.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.requestDTO; - -import jakarta.validation.constraints.NotNull; - -public record UpdateMyGroupPageDTO( - @NotNull(message = "그룹 닉네임을 설정해 주세요.") - String groupNickName -) { -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/CreateUnOfficialGroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/CreateUnOfficialGroupResponseDTO.java deleted file mode 100644 index 4c333a35..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/CreateUnOfficialGroupResponseDTO.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.responseDTO; - -import com.kakao.techcampus.wekiki.group.domain.Group; - -public record CreateUnOfficialGroupResponseDTO( - String groupName, - String groupImage -) { - public CreateUnOfficialGroupResponseDTO(Group group) { - this(group.getGroupName(), group.getGroupProfileImage()); - } -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetGroupMembersResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetGroupMembersResponseDTO.java deleted file mode 100644 index 3214f32f..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetGroupMembersResponseDTO.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.responseDTO; - -import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; -import lombok.Getter; -import lombok.Setter; - -import java.util.List; -import java.util.stream.Collectors; - -@Getter -@Setter -public class GetGroupMembersResponseDTO { - - private List activeGroupMemberList; - - public GetGroupMembersResponseDTO(Group group) { - this.activeGroupMemberList = group.getGroupMembers().stream() - .filter(groupMember -> groupMember instanceof ActiveGroupMember) - .map(groupMember -> (ActiveGroupMember) groupMember) - .collect(Collectors.toList()); - } -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetInvitationLinkResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetInvitationLinkResponseDTO.java deleted file mode 100644 index 24c507be..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GetInvitationLinkResponseDTO.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.responseDTO; - -import com.kakao.techcampus.wekiki.group.domain.Invitation; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class GetInvitationLinkResponseDTO { - private String invitationLink; - - public GetInvitationLinkResponseDTO(Invitation invitation) { - this.invitationLink = invitation.code(); - } -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GroupResponseDTO.java new file mode 100644 index 00000000..1a005367 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GroupResponseDTO.java @@ -0,0 +1,110 @@ +package com.kakao.techcampus.wekiki.group.dto.responseDTO; + +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.domain.Invitation; +import com.kakao.techcampus.wekiki.group.domain.OfficialGroup; +import com.kakao.techcampus.wekiki.group.domain.UnOfficialOpenedGroup; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.history.History; +import org.springframework.data.domain.Page; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +public class GroupResponseDTO { + public record GetInvitationLinkResponseDTO(String invitationLink) { + public GetInvitationLinkResponseDTO(Invitation invitation) { + this(invitation.code()); + } + } + + public record MyGroupInfoResponseDTO( + String groupName, + String groupNickName, + List myHistoryDTOS + ) { + public MyGroupInfoResponseDTO(Group group, GroupMember groupMember, Page histories) { + this(group.getGroupName(), groupMember.getNickName(), histories.stream().map(MyHistoryDTO::new).collect(Collectors.toList())); + } + + public record MyHistoryDTO( + String content, + LocalDateTime created_at + ) { + public MyHistoryDTO(History history) { + this(history.getContent(), history.getCreated_at()); + } + } + } + + public record SearchUnOfficialGroupResponseDTO(List unofficialOpenedGroups) { + public SearchUnOfficialGroupResponseDTO(Page unofficialOpenedGroups) { + this(unofficialOpenedGroups.stream().map(SearchGroupDTO.GroupInfoDTO::new).collect(Collectors.toList())); + } + } + + public record MyGroupHistoryResponseDTO(List myHistoryDTOS) { + public MyGroupHistoryResponseDTO(Page histories) { + this(histories.stream().map(MyGroupInfoResponseDTO.MyHistoryDTO::new).collect(Collectors.toList())); + } + } + + public record ValidateInvitationResponseDTO(Long groupId) { + } + + + public record SearchGroupInfoDTO( + String groupName, + String groupImage, + String introduction, + int memberCount, + LocalDateTime created_at, + String entranceHint + ) { + public SearchGroupInfoDTO(UnOfficialOpenedGroup group) { + this(group.getGroupName(), group.getGroupProfileImage(), group.getIntroduction(), group.getMemberCount(), group.getCreated_at(), group.getEntranceHint()); + } + } + + public record SearchOfficialGroupResponseDTO(List officialOpenedGroups) { + public SearchOfficialGroupResponseDTO(Page officialOpenedGroups) { + this(officialOpenedGroups.stream().map(SearchGroupDTO.GroupInfoDTO::new).collect(Collectors.toList())); + } + } + + public record GetGroupMembersResponseDTO(List activeGroupMemberList) { + public GetGroupMembersResponseDTO(Group group) { + this(group.getGroupMembers().stream() + .filter(groupMember -> groupMember instanceof ActiveGroupMember) + .map(groupMember -> (ActiveGroupMember) groupMember) + .collect(Collectors.toList())); + } + } + + public record CreateUnOfficialGroupResponseDTO(String groupName, String groupImage) { + public CreateUnOfficialGroupResponseDTO(Group group) { + this(group.getGroupName(), group.getGroupProfileImage()); + } + } + + public record SearchGroupDTO( + List officialGroups, + List unofficialOpenedGroups + ) { + public SearchGroupDTO(Page officialGroups, Page unofficialOpenedGroups) { + this(officialGroups.stream().map(GroupInfoDTO::new).collect(Collectors.toList()), unofficialOpenedGroups.stream().map(GroupInfoDTO::new).collect(Collectors.toList())); + } + + public record GroupInfoDTO( + String groupName, + String groupProfileImage, + int memberCount + ) { + public GroupInfoDTO(Group group) { + this(group.getGroupName(), group.getGroupProfileImage(), group.getMemberCount()); + } + } + } +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupHistoryResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupHistoryResponseDTO.java deleted file mode 100644 index aecf0825..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupHistoryResponseDTO.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.responseDTO; - -import com.kakao.techcampus.wekiki.history.History; -import lombok.Getter; -import lombok.Setter; -import org.springframework.data.domain.Page; - -import java.util.List; -import java.util.stream.Collectors; - -@Getter -@Setter -public class MyGroupHistoryResponseDTO { - private List myHistoryDTOS; - - public MyGroupHistoryResponseDTO(Page histories) { - - this.myHistoryDTOS = histories.stream().map(MyGroupInfoResponseDTO.MyHistoryDTO::new).collect(Collectors.toList()); - } -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupInfoResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupInfoResponseDTO.java deleted file mode 100644 index dce4aaef..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/MyGroupInfoResponseDTO.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.responseDTO; - - -import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; -import com.kakao.techcampus.wekiki.history.History; -import lombok.Getter; -import lombok.Setter; -import org.springframework.data.domain.Page; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -@Getter -@Setter -public class MyGroupInfoResponseDTO { - - private String groupName; - private String groupNickName; - private List myHistoryDTOS; - - public MyGroupInfoResponseDTO(Group group, GroupMember groupMember, Page histories) { - this.groupName = group.getGroupName(); - this.groupNickName = groupMember.getNickName(); - this.myHistoryDTOS = histories.stream().map(MyHistoryDTO::new).collect(Collectors.toList()); - } - - @Getter - @Setter - public static class MyHistoryDTO { - private String content; - private LocalDateTime created_at; - - public MyHistoryDTO(History history) { - this.content = history.getContent(); - this.created_at = history.getCreated_at(); - } - } -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupDTO.java deleted file mode 100644 index 4c41e0d2..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupDTO.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.responseDTO; - -import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.domain.OfficialGroup; -import com.kakao.techcampus.wekiki.group.domain.UnOfficialOpenedGroup; -import lombok.Getter; -import lombok.Setter; -import org.springframework.data.domain.Page; - -import java.util.List; -import java.util.stream.Collectors; - -@Getter -@Setter -public class SearchGroupDTO { - private List officialGroups; - private List unofficialOpenedGroups; - - public SearchGroupDTO(Page officialGroups, Page unofficialOpenedGroups) { - this.officialGroups = officialGroups.stream().map(GroupInfoDTO::new).collect(Collectors.toList()); - this.unofficialOpenedGroups = unofficialOpenedGroups.stream().map(GroupInfoDTO::new).collect(Collectors.toList()); - } - - @Getter - @Setter - public static class GroupInfoDTO { - private String groupName; - private String groupProfileImage; - private int memberCount; - - public GroupInfoDTO(Group group) { - this.groupName = group.getGroupName(); - this.groupProfileImage = group.getGroupProfileImage(); - this.memberCount = group.getMemberCount(); - } - } -} - diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupInfoDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupInfoDTO.java deleted file mode 100644 index 65189ace..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchGroupInfoDTO.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.responseDTO; - -import com.kakao.techcampus.wekiki.group.domain.UnOfficialOpenedGroup; -import lombok.Getter; -import lombok.Setter; - -import java.time.LocalDateTime; - -@Getter -@Setter -public class SearchGroupInfoDTO { - private String groupName; - private String groupImage; - private String introduction; - private int memberCount; - private LocalDateTime created_at; - private String entranceHint; - - public SearchGroupInfoDTO(UnOfficialOpenedGroup group) { - this.groupName = group.getGroupName(); - this.groupImage = group.getGroupProfileImage(); - this.introduction = group.getIntroduction(); - this.memberCount = group.getMemberCount(); - this.created_at = group.getCreated_at(); - this.entranceHint = group.getEntranceHint(); - } -} - diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchOfficialGroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchOfficialGroupResponseDTO.java deleted file mode 100644 index a5ee68b4..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchOfficialGroupResponseDTO.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.responseDTO; - -import com.kakao.techcampus.wekiki.group.domain.OfficialGroup; -import lombok.Getter; -import lombok.Setter; -import org.springframework.data.domain.Page; - -import java.util.List; -import java.util.stream.Collectors; - -@Getter -@Setter -public class SearchOfficialGroupResponseDTO { - private List officialOpenedGroups; - - public SearchOfficialGroupResponseDTO(Page officialOpenedGroups) { - this.officialOpenedGroups = officialOpenedGroups.stream().map(SearchGroupDTO.GroupInfoDTO::new).collect(Collectors.toList()); - } -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchUnOfficialGroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchUnOfficialGroupResponseDTO.java deleted file mode 100644 index 70d6764d..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/SearchUnOfficialGroupResponseDTO.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.responseDTO; - -import com.kakao.techcampus.wekiki.group.domain.UnOfficialOpenedGroup; -import lombok.Getter; -import lombok.Setter; -import org.springframework.data.domain.Page; - -import java.util.List; -import java.util.stream.Collectors; - -@Getter -@Setter -public class SearchUnOfficialGroupResponseDTO { - private List unofficialOpenedGroups; - - public SearchUnOfficialGroupResponseDTO(Page unofficialOpenedGroups) { - this.unofficialOpenedGroups = unofficialOpenedGroups.stream().map(SearchGroupDTO.GroupInfoDTO::new).collect(Collectors.toList()); - } -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/ValidateInvitationResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/ValidateInvitationResponseDTO.java deleted file mode 100644 index afa4940a..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/ValidateInvitationResponseDTO.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.kakao.techcampus.wekiki.group.dto.responseDTO; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class ValidateInvitationResponseDTO { - private Long groupId; - - public ValidateInvitationResponseDTO(Long groupId) { - this.groupId = groupId; - } -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index e4f9bc1f..fb6b6c2f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -4,11 +4,8 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.error.exception.Exception500; import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.dto.requestDTO.GroupEntryRequestDTO; +import com.kakao.techcampus.wekiki.group.dto.requestDTO.*; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; -import com.kakao.techcampus.wekiki.group.dto.requestDTO.CreateUnOfficialGroupRequestDTO; -import com.kakao.techcampus.wekiki.group.dto.requestDTO.JoinGroupRequestDTO; -import com.kakao.techcampus.wekiki.group.dto.requestDTO.UpdateMyGroupPageDTO; import com.kakao.techcampus.wekiki.group.dto.responseDTO.*; import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; @@ -47,7 +44,7 @@ public class GroupService { 비공식 그룹 생성 */ @Transactional - public CreateUnOfficialGroupResponseDTO createUnOfficialGroup(CreateUnOfficialGroupRequestDTO requestDTO, Long memberId) { + public GroupResponseDTO.CreateUnOfficialGroupResponseDTO createUnOfficialGroup(GroupRequestDTO.CreateUnOfficialGroupRequestDTO requestDTO, Long memberId) { try { // Group 생성 Group group = switch (requestDTO.groupType()) { @@ -66,7 +63,7 @@ public CreateUnOfficialGroupResponseDTO createUnOfficialGroup(CreateUnOfficialGr groupMemberJPARepository.save(groupMember); // return - return new CreateUnOfficialGroupResponseDTO(group); + return new GroupResponseDTO.CreateUnOfficialGroupResponseDTO(group); } catch (Exception400 | Exception404 e) { throw e; @@ -79,7 +76,7 @@ public CreateUnOfficialGroupResponseDTO createUnOfficialGroup(CreateUnOfficialGr /* 비공식 비공개 그룹 생성 후 반환 */ - protected UnOfficialClosedGroup buildUnOfficialClosedGroup(CreateUnOfficialGroupRequestDTO requestDTO) { + protected UnOfficialClosedGroup buildUnOfficialClosedGroup(GroupRequestDTO.CreateUnOfficialGroupRequestDTO requestDTO) { // Group 생성 return UnOfficialClosedGroup.unOfficialClosedGroupBuilder() .groupName(requestDTO.groupName()) @@ -91,7 +88,7 @@ protected UnOfficialClosedGroup buildUnOfficialClosedGroup(CreateUnOfficialGroup /* 비공식 공개 그룹 생성 후 반환 */ - protected UnOfficialOpenedGroup buildUnOfficialOpenedGroup(CreateUnOfficialGroupRequestDTO requestDTO) { + protected UnOfficialOpenedGroup buildUnOfficialOpenedGroup(GroupRequestDTO.CreateUnOfficialGroupRequestDTO requestDTO) { // Group 생성 return UnOfficialOpenedGroup.unOfficialOpenedGroupBuilder() .groupName(requestDTO.groupName()) @@ -119,7 +116,7 @@ protected ActiveGroupMember buildGroupMember(Member member, Group group, String 공식 그룹 리스트, 비공식 공개 그룹 리스트 그룹 - keyword가 포함된 모든 그룹 그룹별 리스트 */ - public SearchGroupDTO searchGroupByKeyword(String keyword) { + public GroupResponseDTO.SearchGroupDTO searchGroupByKeyword(String keyword) { try { Pageable pageable = PageRequest.of(0, 10); @@ -128,7 +125,7 @@ public SearchGroupDTO searchGroupByKeyword(String keyword) { // 비공식 공개 그룹 리스트 Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); - return new SearchGroupDTO(officialGroups, unOfficialOpenedGroups); + return new GroupResponseDTO.SearchGroupDTO(officialGroups, unOfficialOpenedGroups); } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); @@ -138,14 +135,14 @@ public SearchGroupDTO searchGroupByKeyword(String keyword) { /* 공식 그룹 추가 리스트 */ - public SearchOfficialGroupResponseDTO searchOfficialGroupByKeyword(String keyword, int page, int size) { + public GroupResponseDTO.SearchOfficialGroupResponseDTO searchOfficialGroupByKeyword(String keyword, int page, int size) { try { Pageable pageable = PageRequest.of(page, size); // 비공식 공개 그룹 리스트 Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); - return new SearchOfficialGroupResponseDTO(officialGroups); + return new GroupResponseDTO.SearchOfficialGroupResponseDTO(officialGroups); } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); @@ -155,14 +152,14 @@ public SearchOfficialGroupResponseDTO searchOfficialGroupByKeyword(String keywor /* 비공식 공개 그룹 추가 리스트 */ - public SearchUnOfficialGroupResponseDTO searchUnOfficialGroupByKeyword(String keyword, int page, int size) { + public GroupResponseDTO.SearchUnOfficialGroupResponseDTO searchUnOfficialGroupByKeyword(String keyword, int page, int size) { try { Pageable pageable = PageRequest.of(page, size); // 비공식 공개 그룹 리스트 Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); - return new SearchUnOfficialGroupResponseDTO(unOfficialOpenedGroups); + return new GroupResponseDTO.SearchUnOfficialGroupResponseDTO(unOfficialOpenedGroups); } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); @@ -172,12 +169,12 @@ public SearchUnOfficialGroupResponseDTO searchUnOfficialGroupByKeyword(String ke /* 비공식 공개 그룹 상세 정보 조회 */ - public SearchGroupInfoDTO getGroupInfo(Long groupId) { + public GroupResponseDTO.SearchGroupInfoDTO getGroupInfo(Long groupId) { try { UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId) .orElseThrow(() -> new Exception404("그룹을 찾을 수 없습니다.")); - return new SearchGroupInfoDTO(group); + return new GroupResponseDTO.SearchGroupInfoDTO(group); } catch (Exception404 e) { throw e; } catch (Exception e) { @@ -189,7 +186,7 @@ public SearchGroupInfoDTO getGroupInfo(Long groupId) { /* 비공식 공개 그룹 입장 */ - public void groupEntry(Long groupId, GroupEntryRequestDTO requestDTO) { + public void groupEntry(Long groupId, GroupRequestDTO.GroupEntryRequestDTO requestDTO) { try { UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId) .orElseThrow(() -> new Exception404("그룹을 찾을 수 없습니다.")); @@ -210,7 +207,7 @@ public void groupEntry(Long groupId, GroupEntryRequestDTO requestDTO) { 그룹 참가 (공통 부분) */ @Transactional - public void joinGroup(Long groupId, Long memberId, JoinGroupRequestDTO requestDTO) { + public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequestDTO requestDTO) { try { // 회원 정보 확인 Member member = getMemberById(memberId); @@ -247,11 +244,11 @@ public void joinGroup(Long groupId, Long memberId, JoinGroupRequestDTO requestDT /* 그룹 내 그룹원 리스트 조회 */ - public GetGroupMembersResponseDTO getGroupMembers(Long groupId) { + public GroupResponseDTO.GetGroupMembersResponseDTO getGroupMembers(Long groupId) { try { Group group = getGroupById(groupId); - return new GetGroupMembersResponseDTO(group); + return new GroupResponseDTO.GetGroupMembersResponseDTO(group); } catch (Exception404 e) { throw e; @@ -263,7 +260,7 @@ public GetGroupMembersResponseDTO getGroupMembers(Long groupId) { /* 그룹 내 마이 페이지 */ - public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { + public GroupResponseDTO.MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { try { // 그룹 멤버 확인 ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) @@ -274,7 +271,7 @@ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember, pageable); // 그룹 이름, 현재 닉네임, Post 기록 정보를 담은 responseDTO 반환 - return new MyGroupInfoResponseDTO(groupMember.getGroup(), groupMember, myHistoryList); + return new GroupResponseDTO.MyGroupInfoResponseDTO(groupMember.getGroup(), groupMember, myHistoryList); } catch (Exception404 e) { throw e; @@ -287,7 +284,7 @@ public MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { 내 문서 기여 목록 전체 보기 */ @Transactional - public MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, int page, int size) { + public GroupResponseDTO.MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, int page, int size) { try { // 그룹 멤버 확인 ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) @@ -296,7 +293,7 @@ public MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, Pageable pageable = PageRequest.of(page, size); Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember, pageable); - return new MyGroupHistoryResponseDTO(myHistoryList); + return new GroupResponseDTO.MyGroupHistoryResponseDTO(myHistoryList); } catch (Exception404 e) { throw e; @@ -310,7 +307,7 @@ public MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, 그룹 내 마이 페이지 정보 수정 */ @Transactional - public void updateMyGroupPage(Long groupId, Long memberId, UpdateMyGroupPageDTO requestDTO) { + public void updateMyGroupPage(Long groupId, Long memberId, GroupRequestDTO.UpdateMyGroupPageDTO requestDTO) { try { // 그룹 멤버 확인 ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index 458d996f..682c6084 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -2,8 +2,7 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; -import com.kakao.techcampus.wekiki.group.dto.responseDTO.GetInvitationLinkResponseDTO; -import com.kakao.techcampus.wekiki.group.dto.responseDTO.ValidateInvitationResponseDTO; +import com.kakao.techcampus.wekiki.group.dto.responseDTO.GroupResponseDTO; import com.kakao.techcampus.wekiki.group.domain.Invitation; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.RedisTemplate; @@ -29,7 +28,7 @@ public class InvitationService { - 기존에 없으면 새로 생성 - new GetInvitationLinkResponseDTO(Invitation invitation) */ - public GetInvitationLinkResponseDTO getGroupInvitationCode(Long groupId) { + public GroupResponseDTO.GetInvitationLinkResponseDTO getGroupInvitationCode(Long groupId) { String groupKey = GROUP_ID_PREFIX + groupId; @@ -48,11 +47,11 @@ public GetInvitationLinkResponseDTO getGroupInvitationCode(Long groupId) { } // 있으면 해당 초대 링크로 requestDTO 생성 - return new GetInvitationLinkResponseDTO(invitation); + return new GroupResponseDTO.GetInvitationLinkResponseDTO(invitation); } // 초대 링크를 통한 접근 시 유효한 초대 링크 확인, 해당 그룹으로 연결 - public ValidateInvitationResponseDTO ValidateInvitation(String invitationLink) { + public GroupResponseDTO.ValidateInvitationResponseDTO ValidateInvitation(String invitationLink) { // 초대 링크를 통해 groupId와 invitation 찾기 Long groupId = redisGroupId.opsForValue().get(INVITATION_PREFIX + invitationLink); @@ -69,7 +68,7 @@ public ValidateInvitationResponseDTO ValidateInvitation(String invitationLink) { throw new Exception400("이미 만료된 초대 링크입니다."); } - return new ValidateInvitationResponseDTO(groupId); + return new GroupResponseDTO.ValidateInvitationResponseDTO(groupId); } /* From c826eb601fc9c835611c469543ab42fa9429b729 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Mon, 30 Oct 2023 11:51:57 +0900 Subject: [PATCH 062/144] =?UTF-8?q?Refactor:=20DTO=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 패키지 구조 단순화 --- .../wekiki/group/dto/{requestDTO => }/GroupRequestDTO.java | 0 .../wekiki/group/dto/{responseDTO => }/GroupResponseDTO.java | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/{requestDTO => }/GroupRequestDTO.java (100%) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/{responseDTO => }/GroupResponseDTO.java (100%) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupRequestDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java similarity index 100% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/requestDTO/GroupRequestDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java similarity index 100% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/responseDTO/GroupResponseDTO.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java From 94513e7bbc207f04f19c736fa6e8faa761c4af54 Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Mon, 30 Oct 2023 18:57:26 +0900 Subject: [PATCH 063/144] =?UTF-8?q?Feat=20:=20=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80,=20=EB=82=B4=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC=ED=98=84=20-=20?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=EB=8A=94=20JWT?= =?UTF-8?q?=20=ED=86=A0=ED=81=B0=20=ED=99=95=EC=9D=B8=20=ED=9B=84=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=97=AC=EB=B6=80=EB=A1=9C=20?= =?UTF-8?q?=EA=B5=AC=EB=B6=84=ED=95=9C=20=EB=92=A4=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=A0=84=EB=8B=AC=20-=20=EB=82=B4=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EB=8A=94=20=EA=B7=B8=EB=8C=80?= =?UTF-8?q?=EB=A1=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wekiki/_core/jwt/JWTTokenProvider.java | 3 +- .../wekiki/group/GroupJPARepository.java | 8 +- .../wekiki/main/MainController.java | 21 ++++ .../wekiki/member/MemberController.java | 4 +- .../wekiki/member/MemberService.java | 107 +++++++++++++----- .../wekiki/page/PageInfoResponse.java | 30 +++++ .../wekiki/page/PageRestController.java | 2 + .../techcampus/wekiki/page/PageService.java | 32 ++++++ 8 files changed, 173 insertions(+), 34 deletions(-) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/main/MainController.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/jwt/JWTTokenProvider.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/jwt/JWTTokenProvider.java index 53bedebe..6bbe0198 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/jwt/JWTTokenProvider.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/jwt/JWTTokenProvider.java @@ -4,6 +4,7 @@ import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; +import io.jsonwebtoken.security.SignatureException; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -62,7 +63,7 @@ public boolean validateToken(String token) { try { Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token); return true; - } catch (SecurityException | MalformedJwtException e) { + } catch (SecurityException | MalformedJwtException | SignatureException e) { log.info("올바르지 않은 서명의 JWT Token 입니다.", e); } catch (ExpiredJwtException e) { log.info("만료된 JWT Token 입니다.", e); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java index 36ff6c4c..d3e5eefb 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/GroupJPARepository.java @@ -4,6 +4,8 @@ import com.kakao.techcampus.wekiki.group.officialGroup.OfficialGroup; import com.kakao.techcampus.wekiki.group.unOfficialGroup.closedGroup.UnOfficialClosedGroup; import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; +import jakarta.persistence.EntityManager; +import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -13,13 +15,17 @@ import java.util.Comparator; import java.util.List; +import java.util.Optional; @Repository public interface GroupJPARepository extends JpaRepository { - /* 그룹 검색 용 */ + @Query("select g from OfficialGroup g") + List findAllOfficialGroup(); + @Query("select g from UnOfficialOpenedGroup g") + List findAllUnOfficialOpenGroup(); @Query("SELECT g FROM OfficialGroup g WHERE g.groupName LIKE CONCAT('%', :keyword, '%')") Page findOfficialGroupsByKeyword(@Param("keyword") String keyword, Pageable pageable); @Query("SELECT g FROM UnOfficialOpenedGroup g WHERE g.groupName LIKE CONCAT('%', :keyword, '%')") diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/main/MainController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/main/MainController.java new file mode 100644 index 00000000..dd031f7c --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/main/MainController.java @@ -0,0 +1,21 @@ +package com.kakao.techcampus.wekiki.main; + +import com.kakao.techcampus.wekiki._core.utils.ApiUtils; +import com.kakao.techcampus.wekiki.page.PageInfoResponse; +import com.kakao.techcampus.wekiki.page.PageService; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class MainController { + private final PageService pageService; + @GetMapping("/main") + public ResponseEntity getMainPage() { + PageInfoResponse.mainPageDTO response = pageService.getMainPage(); + return ResponseEntity.ok(ApiUtils.success(response)); + } +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java index 99f582da..0430eba1 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java @@ -25,8 +25,8 @@ public ResponseEntity signIn(@RequestBody MemberRequest.loginRequestDTO login @GetMapping("/myinfo") public ResponseEntity myPage() { - memberService.getMyInfo(); - return ResponseEntity.ok(true); + MemberResponse.myInfoResponseDTO response = memberService.getMyInfo(); + return ResponseEntity.ok(ApiUtils.success(response)); } @DeleteMapping("/delete") diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index 53fd9a03..e421188e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -3,6 +3,8 @@ import com.kakao.techcampus.wekiki._core.error.exception.*; import com.kakao.techcampus.wekiki._core.jwt.JWTTokenProvider; import com.kakao.techcampus.wekiki._core.utils.RedisUtility; +import com.kakao.techcampus.wekiki.group.Group; +import com.kakao.techcampus.wekiki.group.member.GroupMember; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.mail.SimpleMailMessage; @@ -16,8 +18,10 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; +import java.util.List; import java.util.Optional; import java.util.Random; +import java.util.stream.Collectors; import static com.kakao.techcampus.wekiki._core.utils.SecurityUtils.currentMember; @@ -35,6 +39,13 @@ public class MemberService { public void signUp(MemberRequest.signUpRequestDTO signUpRequestDTO) { + + Optional checkMember = memberRepository.findByEmail(signUpRequestDTO.getEmail()); + if (checkMember.isPresent()){ + log.error("이미 존재하는 회원이 가입 요청하였습니다."); + throw new Exception400("이미 존재하는 회원입니다."); + } + Member member = Member.builder() .email(signUpRequestDTO.getEmail()) .password(passwordEncoder.encode(signUpRequestDTO.getPassword())) @@ -47,12 +58,14 @@ public void signUp(MemberRequest.signUpRequestDTO signUpRequestDTO) { public MemberResponse.authTokenDTO login(MemberRequest.loginRequestDTO loginDTO) { Optional loginMember = memberRepository.findByEmail(loginDTO.getEmail()); - if(loginMember.isEmpty()) + if(loginMember.isEmpty()) { + log.error("없는 회원이 로그인 요청을 하였습니다."); throw new Exception404("존재하지 않는 이메일입니다."); + } if(!passwordEncoder.matches(loginDTO.getPassword(), loginMember.get().getPassword())){ + log.error("로그인 요청 회원의 비밀번호가 틀렸습니다. User Id : " + loginMember.get().getEmail()); throw new Exception400("비밀번호가 틀렸습니다."); } - UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(loginDTO.getEmail(), loginDTO.getPassword()); AuthenticationManager manager = authenticationManagerBuilder.getObject(); @@ -60,35 +73,60 @@ public MemberResponse.authTokenDTO login(MemberRequest.loginRequestDTO loginDTO) return tokenProvider.generateToken(authentication); } - public void getMyInfo() { - Optional member = memberRepository.findById(currentMember()); - if(member.isEmpty()) - throw new Exception404("없는 회원입니다."); - // member 안의 groupMember를 뽑아낸 뒤, 그걸로 Response를 제작 - //MemberResponse.myInfoResponseDTO.myInfoGroupDTO() - //MemberResponse.myInfoResponseDTO(member.get().getName(), ) + public MemberResponse.myInfoResponseDTO getMyInfo() { + Member member; + try { + member = findMember(); + } catch (Exception404 e) { + log.error("Access Token에서 뽑아낸 회원이 존재하지 않는 회원입니다. (마이페이지 조회)"); + throw e; + } + List infoGroupDTOList = member.getGroupMembers().stream() + .map(groupMember -> { + return new MemberResponse.myInfoResponseDTO.myInfoGroupDTO(groupMember, groupMember.getGroup()); + }).collect(Collectors.toList()); + return new MemberResponse.myInfoResponseDTO(member.getName(), infoGroupDTOList); } public void cancel() { - Optional member = memberRepository.findById(currentMember()); - if(member.isEmpty()) - throw new Exception404("없는 회원입니다."); - memberRepository.delete(member.get()); + Member member; + try { + member = findMember(); + } catch (Exception404 e) { + log.error("Access Token에서 뽑아낸 회원이 존재하지 않는 회원입니다. (회원 탈퇴)"); + throw e; + } + memberRepository.delete(member); } public void changePassword(MemberRequest.changePasswordRequestDTO changePasswordDTO) { - Optional member = memberRepository.findById(currentMember()); - if(member.isEmpty()) + Member member; + try { + member = findMember(); + } catch (Exception404 e) { + log.error("Access Token에서 뽑아낸 회원이 존재하지 않는 회원입니다. (비밀번호 변경)"); + throw e; + } + /*Optional member = memberRepository.findById(currentMember()); + if(member.isEmpty()) { + log.error("Access Token에서 뽑아낸 회원이 존재하지 않는 회원입니다. (비밀번호 변경)"); throw new Exception404("없는 회원입니다."); - if(!passwordEncoder.matches(changePasswordDTO.getCurrentPassword(), member.get().getPassword())) + }*/ + if(!passwordEncoder.matches(changePasswordDTO.getCurrentPassword(), member.getPassword())) { + log.error("비밀번호 변경 요청에서의 비밀번호 확인이 틀렸습니다. User Id : " + member.getEmail()); throw new Exception400("비밀번호가 틀렸습니다."); - member.get().changePassword(passwordEncoder.encode(changePasswordDTO.getNewPassword())); + } + member.changePassword(passwordEncoder.encode(changePasswordDTO.getNewPassword())); } public void sendEmail(String email) { - Optional member = memberRepository.findById(currentMember()); - if(member.isEmpty()) - throw new Exception404("없는 회원입니다."); + Member member; + try { + member = findMember(); + } catch (Exception404 e) { + log.error("Access Token에서 뽑아낸 회원이 존재하지 않는 회원입니다. (부산대 인증 메일 전송)"); + throw e; + } Integer authNumber = makeEmailAuthNum(); redisUtility.setValues(email, Integer.toString(authNumber), 300); SimpleMailMessage simpleMailMessage = new SimpleMailMessage(); @@ -102,24 +140,25 @@ public void sendEmail(String email) { } public void checkPNUEmail(MemberRequest.checkPNUEmailRequestDTO pnuEmailRequestDTO) { - Optional member = memberRepository.findById(currentMember()); - if(member.isEmpty()) - throw new Exception404("없는 회원입니다."); - if(redisUtility.getValues(pnuEmailRequestDTO.getEmail()).equals(pnuEmailRequestDTO.getCertificationNumber())){ - /* - 부산대 인증 완료 후 GroupMember 만드는 로직 들어가면 될듯! - */ - System.out.println("인증번호가 맞았습니다!"); + Member member; + try { + member = findMember(); + } catch (Exception404 e) { + log.error("Access Token에서 뽑아낸 회원이 존재하지 않는 회원입니다. (부산대 인증 메일 확인)"); + throw e; } - else { + if(!redisUtility.getValues(pnuEmailRequestDTO.getEmail()).equals(pnuEmailRequestDTO.getCertificationNumber())){ + log.error("부산대 메일 인증 번호가 틀렸습니다. User Id : " + member.getEmail()); throw new Exception400("인증번호가 틀렸습니다."); } } public void findPassword(String email) { Optional member = memberRepository.findByEmail(email); - if(member.isEmpty()) + if(member.isEmpty()) { + log.error("가입된 회원이 존재하지 않는 이메일입니다. (비밀번호 찾기)"); throw new Exception404("없는 회원입니다."); + } String randomPassword = makeRandomPassword(); member.get().changePassword(passwordEncoder.encode(randomPassword)); SimpleMailMessage simpleMailMessage = new SimpleMailMessage(); @@ -150,4 +189,12 @@ public String makeRandomPassword() { } + private Member findMember() { + Optional member = memberRepository.findById(currentMember()); + if(member.isEmpty()) { + throw new Exception404("없는 회원입니다."); + } + return member.get(); + } + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index cd53d017..fd0764f3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -1,5 +1,8 @@ package com.kakao.techcampus.wekiki.page; +import com.kakao.techcampus.wekiki.group.Group; +import com.kakao.techcampus.wekiki.group.officialGroup.OfficialGroup; +import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; import com.kakao.techcampus.wekiki.post.Post; import lombok.Getter; import lombok.Setter; @@ -9,6 +12,33 @@ public class PageInfoResponse { + @Getter + public static class mainPageDTO { + List myGroup; + List officialGroup; + List unOfficialGroup; + public mainPageDTO(List myGroup, List officialGroup, List unOfficialGroup) { + this.myGroup = myGroup; + this.officialGroup = officialGroup; + this.unOfficialGroup = unOfficialGroup; + } + public mainPageDTO(List officialGroup, List unOfficialGroup) { + this.officialGroup = officialGroup; + this.unOfficialGroup = unOfficialGroup; + } + @Getter + public static class GroupDTO { + Long id; + String groupImage; + String groupName; + public GroupDTO(Group group) { + this.id = group.getId(); + this.groupImage =group.getGroupProfileImage(); + this.groupName = group.getGroupName(); + } + } + } + @Getter @Setter public static class deletePageDTO{ diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index 049d7506..e1719739 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -22,6 +22,8 @@ public class PageRestController { */ + + @GetMapping("/{pageid}") public ResponseEntity getPageFromId(@PathVariable Long groupid,@PathVariable Long pageid) { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 83a9d2ab..49f7efb1 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -10,12 +10,14 @@ import com.kakao.techcampus.wekiki.group.member.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.member.Member; import com.kakao.techcampus.wekiki.member.MemberJPARepository; +import com.kakao.techcampus.wekiki.member.MemberResponse; import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -23,6 +25,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import static com.kakao.techcampus.wekiki._core.utils.SecurityUtils.currentMember; @@ -41,6 +44,35 @@ public class PageService { private final RedisUtility redisUtility; final int PAGE_COUNT = 10; + @Transactional + public PageInfoResponse.mainPageDTO getMainPage() { + if(SecurityContextHolder.getContext().getAuthentication().getName().equals("anonymousUser")) { + // 로그인 안한 사람 + System.out.println("로그인 안함"); + List officialGroupList = groupJPARepository.findAllOfficialGroup().stream() + .map(PageInfoResponse.mainPageDTO.GroupDTO::new) + .collect(Collectors.toList()); + List unOfficialGroupList = groupJPARepository.findAllUnOfficialOpenGroup().stream() + .map(PageInfoResponse.mainPageDTO.GroupDTO::new) + .collect(Collectors.toList()); + return new PageInfoResponse.mainPageDTO(officialGroupList, unOfficialGroupList); + } + else { + System.out.println("로그인 함"); + Optional member = memberJPARepository.findById(currentMember()); + List myGroupList = member.get().getGroupMembers().stream() + .map(groupMember -> { + return new PageInfoResponse.mainPageDTO.GroupDTO(groupMember.getGroup()); + }).toList(); + List officialGroupList = groupJPARepository.findAllOfficialGroup().stream() + .map(PageInfoResponse.mainPageDTO.GroupDTO::new) + .collect(Collectors.toList()); + List unOfficialGroupList = groupJPARepository.findAllUnOfficialOpenGroup().stream() + .map(PageInfoResponse.mainPageDTO.GroupDTO::new) + .collect(Collectors.toList()); + return new PageInfoResponse.mainPageDTO(myGroupList, officialGroupList, unOfficialGroupList); + } + } @Transactional public PageInfoResponse.getPageIndexDTO getPageIndex(Long groupId,Long memberId, Long pageId){ From 0c9815ccc4981469760fce31b05b3db3bc4b3590 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Mon, 30 Oct 2023 19:54:41 +0900 Subject: [PATCH 064/144] =?UTF-8?q?Fix:=20DTO=20=EB=94=94=EB=A0=89?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=20=EA=B5=AC=EC=A1=B0=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 제대로 Replace가 안된 오류 수정 --- .../group/controller/GroupRestController.java | 4 +- .../wekiki/group/dto/GroupRequestDTO.java | 2 +- .../wekiki/group/dto/GroupResponseDTO.java | 4 +- .../wekiki/group/service/GroupService.java | 39 +------------------ .../group/service/InvitationService.java | 2 +- 5 files changed, 8 insertions(+), 43 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java index 5caa40c0..691b6667 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java @@ -2,8 +2,8 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.utils.ApiUtils; -import com.kakao.techcampus.wekiki.group.dto.requestDTO.*; -import com.kakao.techcampus.wekiki.group.dto.responseDTO.*; +import com.kakao.techcampus.wekiki.group.dto.GroupRequestDTO; +import com.kakao.techcampus.wekiki.group.dto.GroupResponseDTO; import com.kakao.techcampus.wekiki.group.service.GroupService; import com.kakao.techcampus.wekiki.group.service.InvitationService; import jakarta.validation.Valid; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java index 01e48c35..88bd20aa 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java @@ -1,4 +1,4 @@ -package com.kakao.techcampus.wekiki.group.dto.requestDTO; +package com.kakao.techcampus.wekiki.group.dto; import com.kakao.techcampus.wekiki.group.GroupType; import jakarta.validation.constraints.NotNull; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java index 1a005367..f6503d74 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java @@ -1,4 +1,4 @@ -package com.kakao.techcampus.wekiki.group.dto.responseDTO; +package com.kakao.techcampus.wekiki.group.dto; import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.group.domain.Invitation; @@ -23,7 +23,7 @@ public GetInvitationLinkResponseDTO(Invitation invitation) { public record MyGroupInfoResponseDTO( String groupName, String groupNickName, - List myHistoryDTOS + List myHistorgiyDTOS ) { public MyGroupInfoResponseDTO(Group group, GroupMember groupMember, Page histories) { this(group.getGroupName(), groupMember.getNickName(), histories.stream().map(MyHistoryDTO::new).collect(Collectors.toList())); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index fb6b6c2f..7db47624 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -4,9 +4,9 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.error.exception.Exception500; import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.dto.requestDTO.*; +import com.kakao.techcampus.wekiki.group.dto.GroupRequestDTO; +import com.kakao.techcampus.wekiki.group.dto.GroupResponseDTO; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; -import com.kakao.techcampus.wekiki.group.dto.responseDTO.*; import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.group.domain.member.InactiveGroupMember; @@ -367,39 +367,4 @@ protected Member getMemberById(Long memberId) { protected Group getGroupById(Long groupId) { return groupJPARepository.findById(groupId).orElseThrow(() -> new Exception404("해당 그룹을 찾을 수 없습니다.")); } - - // RedisCache를 통한 getMember, getGroup -> 근데 성능 개선에 도움이 될까? - /* - protected Member getMemberById(Long memberId) { - try { - String memberKey = "member:" + memberId; - ValueOperations operations = redisTemplate.opsForValue(); - if(redisTemplate.hasKey(memberKey)) { - return (Member) operations.get(memberKey); - } else { - Member member = memberJPARepository.findById(memberId).orElseThrow(() -> new Exception404("해당 사용자를 찾을 수 없습니다.")); - operations.set(memberKey, member); - return member; - } - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); - } - } - - protected Group getGroupById(Long groupId) { - try { - String groupKey = "group:" + groupId; - ValueOperations operations = redisTemplate.opsForValue(); - if(redisTemplate.hasKey(groupKey)) { - return (Group) operations.get(groupKey); - } else { - Group group = groupJPARepository.findById(groupId).orElseThrow(() -> new Exception404("해당 그룹을 찾을 수 없습니다.")); - operations.set(groupKey, group); - return group; - } - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); - } - } - */ } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index 682c6084..0e88e9c0 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -2,7 +2,7 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; -import com.kakao.techcampus.wekiki.group.dto.responseDTO.GroupResponseDTO; +import com.kakao.techcampus.wekiki.group.dto.GroupResponseDTO; import com.kakao.techcampus.wekiki.group.domain.Invitation; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.RedisTemplate; From 587ae29fbf2708f1281366ebfe636a6dfe83c5e8 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Mon, 30 Oct 2023 22:04:10 +0900 Subject: [PATCH 065/144] =?UTF-8?q?Fix:=20RedisUtils=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Redistemplate을 바로 주입하는게 동작을 안해서 RedisUtils를 새로 Component로 생성 --- .../wekiki/_core/utils/redis/RedisUtils.java | 36 +++++++++++++++++++ .../group/controller/GroupRestController.java | 2 +- .../group/service/InvitationService.java | 23 ++++++------ 3 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/redis/RedisUtils.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/redis/RedisUtils.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/redis/RedisUtils.java new file mode 100644 index 00000000..099c3cda --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/redis/RedisUtils.java @@ -0,0 +1,36 @@ +package com.kakao.techcampus.wekiki._core.utils.redis; + +import com.kakao.techcampus.wekiki.group.domain.Invitation; +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.util.Set; + +@Component +@RequiredArgsConstructor +public class RedisUtils { + + private final RedisTemplate redisTemplate; + + public void setInvitationValues(String key, Invitation invitation, Duration lifetime) { + redisTemplate.opsForValue().set(key, invitation, lifetime); + } + + public void setGroupIdValues(String key, Long groupId, Duration lifetime) { + redisTemplate.opsForValue().set(key, groupId, lifetime); + } + + public Object getValues(String key) { + return redisTemplate.opsForValue().get(key); + } + + public Set getKeys(String pattern) { + return redisTemplate.keys(pattern); + } + + public void deleteValues(String key) { + redisTemplate.delete(key); + } +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java index 691b6667..c274d9ba 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java @@ -130,7 +130,7 @@ public ResponseEntity getInvitationLink(@PathVariable("groupId") Long groupId /* 그룹 초대링크 유효성 검사(?) */ - @GetMapping("/{invitationLink}") + @GetMapping("/invitation/{invitationLink}") public ResponseEntity ValidateInvitation(@PathVariable String invitationLink) { GroupResponseDTO.ValidateInvitationResponseDTO responseDTO = invitationService.ValidateInvitation(invitationLink); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index 0e88e9c0..7142c844 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -2,10 +2,10 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; +import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; import com.kakao.techcampus.wekiki.group.dto.GroupResponseDTO; import com.kakao.techcampus.wekiki.group.domain.Invitation; import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -16,8 +16,7 @@ @Service public class InvitationService { - private final RedisTemplate redisInvitation; - private final RedisTemplate redisGroupId; + private final RedisUtils redisUtils; private static final String GROUP_ID_PREFIX = "group_id:"; private static final String INVITATION_PREFIX = "invitation:"; @@ -33,7 +32,7 @@ public GroupResponseDTO.GetInvitationLinkResponseDTO getGroupInvitationCode(Long String groupKey = GROUP_ID_PREFIX + groupId; // 기존 초대 링크 여부 확인 - Invitation invitation = redisInvitation.opsForValue().get(groupKey); + Invitation invitation = (Invitation) redisUtils.getValues(groupKey); // 없으면 새로 생성 후 Redis 저장 /* @@ -42,8 +41,8 @@ public GroupResponseDTO.GetInvitationLinkResponseDTO getGroupInvitationCode(Long */ if(invitation == null) { invitation = Invitation.create(groupId); - redisInvitation.opsForValue().set(groupKey, invitation, invitation.remainDuration(LocalDateTime.now())); - redisGroupId.opsForValue().set(INVITATION_PREFIX + invitation.code(), groupId, invitation.remainDuration(LocalDateTime.now())); + redisUtils.setInvitationValues(groupKey, invitation, invitation.remainDuration(LocalDateTime.now())); + redisUtils.setGroupIdValues(INVITATION_PREFIX + invitation.code(), groupId, invitation.remainDuration(LocalDateTime.now())); } // 있으면 해당 초대 링크로 requestDTO 생성 @@ -54,7 +53,7 @@ public GroupResponseDTO.GetInvitationLinkResponseDTO getGroupInvitationCode(Long public GroupResponseDTO.ValidateInvitationResponseDTO ValidateInvitation(String invitationLink) { // 초대 링크를 통해 groupId와 invitation 찾기 - Long groupId = redisGroupId.opsForValue().get(INVITATION_PREFIX + invitationLink); + Long groupId = (Long) redisUtils.getValues(INVITATION_PREFIX + invitationLink); // 해당하는 groupId가 없는 경우 예외 처리 if (groupId == null) { @@ -62,7 +61,7 @@ public GroupResponseDTO.ValidateInvitationResponseDTO ValidateInvitation(String } // 초대 링크 기간 확인 - Invitation invitation = redisInvitation.opsForValue().get(groupId); + Invitation invitation = (Invitation) redisUtils.getValues(String.valueOf(groupId)); if (invitation == null || !invitation.isUsableAt(LocalDateTime.now())) { throw new Exception400("이미 만료된 초대 링크입니다."); @@ -76,15 +75,15 @@ public GroupResponseDTO.ValidateInvitationResponseDTO ValidateInvitation(String - redisInvitation, redisGroupId는 같은 수명을 가지기 때문에 하나만 확인해서 둘 다 삭제 */ private void removeExpiredInvitations() { - Set keys = redisInvitation.keys(GROUP_ID_PREFIX + "*"); + Set keys = redisUtils.getKeys(GROUP_ID_PREFIX + "*"); for (String key : keys) { - Invitation invitation = redisInvitation.opsForValue().get(key); + Invitation invitation = (Invitation) redisUtils.getValues(key); // 초대 링크 수명이 다하면 삭제 if (invitation != null && !invitation.isUsableAt(LocalDateTime.now())) { - redisInvitation.delete(key); - redisGroupId.delete(INVITATION_PREFIX + invitation.code()); + redisUtils.deleteValues(key); + redisUtils.deleteValues(INVITATION_PREFIX + invitation.code()); } } } From 2cf87737beac5d34ae4391226f4f81367671db53 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Tue, 31 Oct 2023 01:00:06 +0900 Subject: [PATCH 066/144] =?UTF-8?q?Fix:=20=EC=9A=94=EC=B2=AD=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DTO : @RequestBody 빠진거 추가 - Query : @Param 빠진거 추가 --- .../group/controller/GroupRestController.java | 6 +-- .../repository/GroupMemberJPARepository.java | 3 +- .../wekiki/group/service/GroupService.java | 43 ++++++++----------- 3 files changed, 23 insertions(+), 29 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java index c274d9ba..4db2c368 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java @@ -93,7 +93,7 @@ public ResponseEntity searchGroupInfo(@PathVariable("groupId") Long groupId) - 그 후 그룹 참가로 이동 */ @PostMapping("/{groupId}/entry") - public ResponseEntity groupEntry(@PathVariable("groupId") Long groupId, GroupRequestDTO.GroupEntryRequestDTO requestDTO) { + public ResponseEntity groupEntry(@PathVariable("groupId") Long groupId, @RequestBody GroupRequestDTO.GroupEntryRequestDTO requestDTO) { groupService.groupEntry(groupId, requestDTO); @@ -104,7 +104,7 @@ public ResponseEntity groupEntry(@PathVariable("groupId") Long groupId, Group 그룹 참가 */ @PostMapping("/{groupId}/join") - public ResponseEntity joinGroup(@PathVariable("groupId") Long groupId, GroupRequestDTO.JoinGroupRequestDTO requestDTO, BindingResult result) { + public ResponseEntity joinGroup(@PathVariable("groupId") Long groupId, @RequestBody GroupRequestDTO.JoinGroupRequestDTO requestDTO, BindingResult result) { // 유효성 검사 if (result.hasErrors()) { @@ -166,7 +166,7 @@ public ResponseEntity myGroupPage(@PathVariable("groupId") Long groupId) { 그룹 내 본인 정보 수정 */ @PatchMapping("/{groupId}/myInfo") - public ResponseEntity updateMyGroupPage(@PathVariable("groupId") Long groupId, GroupRequestDTO.UpdateMyGroupPageDTO requestDTO, BindingResult result) { + public ResponseEntity updateMyGroupPage(@PathVariable("groupId") Long groupId, @RequestBody GroupRequestDTO.UpdateMyGroupPageDTO requestDTO, BindingResult result) { // 유효성 검사 if (result.hasErrors()) { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java index a272269c..738c85ca 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java @@ -7,6 +7,7 @@ import com.kakao.techcampus.wekiki.member.Member; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.Optional; @@ -17,5 +18,5 @@ public interface GroupMemberJPARepository extends JpaRepository findActiveGroupMemberByMemberIdAndGroupId(Long memberId, Long groupId); + Optional findActiveGroupMemberByMemberIdAndGroupId(@Param("memberId") Long memberId, @Param("groupId") Long groupId); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 7db47624..d9dd892d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -208,37 +208,30 @@ public void groupEntry(Long groupId, GroupRequestDTO.GroupEntryRequestDTO reques */ @Transactional public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequestDTO requestDTO) { - try { - // 회원 정보 확인 - Member member = getMemberById(memberId); + // 회원 정보 확인 + Member member = getMemberById(memberId); - // 그룹 정보 확인 - Group group = getGroupById(groupId); + // 그룹 정보 확인 + Group group = getGroupById(groupId); - // 이미 가입한 상태일 시 예외 처리 - if (groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId).isPresent()) { - throw new Exception400("이미 가입된 회원입니다."); - } - - // 재가입 회원인지 확인 - InactiveGroupMember wasGroupMember = groupMemberJPARepository.findInactiveGroupMemberByMemberAndGroup(member, group); - - // 재가입 회원이면 활성화, 신규 회원이면 새로 생성 - ActiveGroupMember groupMember = wasGroupMember != null ? new ActiveGroupMember(wasGroupMember) : buildGroupMember(member, group, requestDTO.nickName()); + // 이미 가입한 상태일 시 예외 처리 + if (groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId).isPresent()) { + throw new Exception400("이미 가입된 회원입니다."); + } - // 그룹 멤버 잔재 삭제 - if(wasGroupMember != null) { - groupMemberJPARepository.delete(wasGroupMember); - } + // 재가입 회원인지 확인 + InactiveGroupMember wasGroupMember = groupMemberJPARepository.findInactiveGroupMemberByMemberAndGroup(member, group); - // GroupMember 저장 - groupMemberJPARepository.save(groupMember); + // 재가입 회원이면 활성화, 신규 회원이면 새로 생성 + ActiveGroupMember groupMember = wasGroupMember != null ? new ActiveGroupMember(wasGroupMember) : buildGroupMember(member, group, requestDTO.nickName()); - } catch (Exception400 | Exception404 e) { - throw e; - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); + // 그룹 멤버 잔재 삭제 + if(wasGroupMember != null) { + groupMemberJPARepository.delete(wasGroupMember); } + + // GroupMember 저장 + groupMemberJPARepository.save(groupMember); } /* From b3f193c634abcc11ba7cda5775069f51a612e476 Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Tue, 31 Oct 2023 13:43:17 +0900 Subject: [PATCH 067/144] =?UTF-8?q?Fix=20:=20pull=20=EC=B6=A9=EB=8F=8C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B02?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kakao/techcampus/wekiki/member/MemberService.java | 2 -- .../com/kakao/techcampus/wekiki/page/PageInfoResponse.java | 4 +--- .../java/com/kakao/techcampus/wekiki/page/PageService.java | 2 ++ 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index e421188e..e3732e74 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -3,8 +3,6 @@ import com.kakao.techcampus.wekiki._core.error.exception.*; import com.kakao.techcampus.wekiki._core.jwt.JWTTokenProvider; import com.kakao.techcampus.wekiki._core.utils.RedisUtility; -import com.kakao.techcampus.wekiki.group.Group; -import com.kakao.techcampus.wekiki.group.member.GroupMember; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.mail.SimpleMailMessage; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index ddac4b86..1635dfac 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -1,8 +1,6 @@ package com.kakao.techcampus.wekiki.page; -import com.kakao.techcampus.wekiki.group.Group; -import com.kakao.techcampus.wekiki.group.officialGroup.OfficialGroup; -import com.kakao.techcampus.wekiki.group.unOfficialGroup.openedGroup.UnOfficialOpenedGroup; +import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.post.Post; import lombok.Getter; import lombok.Setter; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 3ba3928d..30843781 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -28,6 +28,8 @@ import java.util.Optional; import java.util.stream.Collectors; +import static com.kakao.techcampus.wekiki._core.utils.SecurityUtils.currentMember; + @RequiredArgsConstructor @Service public class PageService { From 7461de2820b567b1e86939d868f5a3912c7ba8c4 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Tue, 31 Oct 2023 17:29:49 +0900 Subject: [PATCH 068/144] =?UTF-8?q?Fix:=20=EC=B4=88=EB=8C=80=20=EB=A7=81?= =?UTF-8?q?=ED=81=AC=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LocalDateTime 직렬화 오류 해결 --- wekiki/build.gradle | 3 +++ .../group/controller/GroupRestController.java | 2 +- .../wekiki/group/domain/Invitation.java | 6 ++++++ .../group/service/InvitationService.java | 21 ++++++++----------- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/wekiki/build.gradle b/wekiki/build.gradle index f776b998..debfa3fd 100644 --- a/wekiki/build.gradle +++ b/wekiki/build.gradle @@ -60,6 +60,9 @@ dependencies { // Random String implementation 'org.apache.commons:commons-lang3:3.12.0' + // 날짜/시간 유형 직렬화 + implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.13.0' + // 개발 편의용 compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java index 4db2c368..241852e1 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java @@ -133,7 +133,7 @@ public ResponseEntity getInvitationLink(@PathVariable("groupId") Long groupId @GetMapping("/invitation/{invitationLink}") public ResponseEntity ValidateInvitation(@PathVariable String invitationLink) { - GroupResponseDTO.ValidateInvitationResponseDTO responseDTO = invitationService.ValidateInvitation(invitationLink); + GroupResponseDTO.ValidateInvitationResponseDTO responseDTO = invitationService.validateInvitation(invitationLink); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Invitation.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Invitation.java index abf314da..6e9af567 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Invitation.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Invitation.java @@ -1,5 +1,9 @@ package com.kakao.techcampus.wekiki.group.domain; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import org.apache.commons.lang3.RandomStringUtils; import java.time.Duration; @@ -7,6 +11,8 @@ public record Invitation( Long groupId, + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) LocalDateTime expiresAt, String code ) { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index 7142c844..47a9ca5d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -1,6 +1,5 @@ package com.kakao.techcampus.wekiki.group.service; -import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; import com.kakao.techcampus.wekiki.group.dto.GroupResponseDTO; @@ -10,6 +9,7 @@ import org.springframework.stereotype.Service; import java.time.LocalDateTime; +import java.util.Optional; import java.util.Set; @RequiredArgsConstructor @@ -50,24 +50,21 @@ public GroupResponseDTO.GetInvitationLinkResponseDTO getGroupInvitationCode(Long } // 초대 링크를 통한 접근 시 유효한 초대 링크 확인, 해당 그룹으로 연결 - public GroupResponseDTO.ValidateInvitationResponseDTO ValidateInvitation(String invitationLink) { + public GroupResponseDTO.ValidateInvitationResponseDTO validateInvitation(String invitationLink) { // 초대 링크를 통해 groupId와 invitation 찾기 - Long groupId = (Long) redisUtils.getValues(INVITATION_PREFIX + invitationLink); - - // 해당하는 groupId가 없는 경우 예외 처리 - if (groupId == null) { - throw new Exception404("잘못된 접근입니다."); - } + // groupId는 현재 Integer 타입 + Object groupId = Optional.ofNullable(redisUtils.getValues(INVITATION_PREFIX + invitationLink)) + .orElseThrow(() -> new Exception404("잘못된 접근입니다.")); // 초대 링크 기간 확인 - Invitation invitation = (Invitation) redisUtils.getValues(String.valueOf(groupId)); + Invitation invitation = (Invitation) redisUtils.getValues(GROUP_ID_PREFIX + groupId); - if (invitation == null || !invitation.isUsableAt(LocalDateTime.now())) { - throw new Exception400("이미 만료된 초대 링크입니다."); + if(invitation == null || !invitation.isUsableAt(LocalDateTime.now())) { + throw new Exception404("이미 만료된 초대 링크입니다."); } - return new GroupResponseDTO.ValidateInvitationResponseDTO(groupId); + return new GroupResponseDTO.ValidateInvitationResponseDTO(((Integer) groupId).longValue()); } /* From 129abe67714e400550612a0a8e5ebd3b96deaa9b Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Thu, 2 Nov 2023 13:36:58 +0900 Subject: [PATCH 069/144] =?UTF-8?q?Refactor:=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20DTO=EC=97=90=20=EA=B0=81=20Entity=EC=9D=98?= =?UTF-8?q?=20Id=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 모든 GroupResponseDTO에 GroupId 추가 - History 관련에서도 HistoryId 추가 --- .../group/controller/GroupRestController.java | 4 +- .../wekiki/group/dto/GroupResponseDTO.java | 110 +++++++++++------- .../wekiki/group/service/GroupService.java | 9 +- .../group/service/InvitationService.java | 2 +- 4 files changed, 78 insertions(+), 47 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java index 241852e1..159e5d48 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java @@ -81,7 +81,7 @@ public ResponseEntity searchUnOfficialGroup(@RequestParam(value = "keyword", /* 특정 공개 그룹 정보 조회 */ - @GetMapping("/search/{grouId}") + @GetMapping("/search/{groupId}") public ResponseEntity searchGroupInfo(@PathVariable("groupId") Long groupId) { GroupResponseDTO.SearchGroupInfoDTO response = groupService.getGroupInfo(groupId); @@ -143,7 +143,7 @@ public ResponseEntity ValidateInvitation(@PathVariable String invitationLink) */ @GetMapping("{groupId}/groupMembers") public ResponseEntity getGroupMembers(@PathVariable("groupId") Long groupId) { - GroupResponseDTO.GetGroupMembersResponseDTO responseDTO = groupService.getGroupMembers(groupId); + GroupResponseDTO.GetGroupMembersResponseDTO responseDTO = groupService.getGroupMembers(groupId, currentMember()); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java index f6503d74..c6006ccf 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java @@ -14,47 +14,96 @@ import java.util.stream.Collectors; public class GroupResponseDTO { - public record GetInvitationLinkResponseDTO(String invitationLink) { - public GetInvitationLinkResponseDTO(Invitation invitation) { - this(invitation.code()); - } - } - + + // 그룹 내 본인 정보 조회 public record MyGroupInfoResponseDTO( + Long groupId, String groupName, String groupNickName, - List myHistorgiyDTOS + List myHistoryDTOS ) { public MyGroupInfoResponseDTO(Group group, GroupMember groupMember, Page histories) { - this(group.getGroupName(), groupMember.getNickName(), histories.stream().map(MyHistoryDTO::new).collect(Collectors.toList())); + this(group.getId(), group.getGroupName(), groupMember.getNickName(), histories.stream().map(MyHistoryDTO::new).collect(Collectors.toList())); } public record MyHistoryDTO( + Long historyId, String content, LocalDateTime created_at ) { public MyHistoryDTO(History history) { - this(history.getContent(), history.getCreated_at()); + this(history.getId(), history.getContent(), history.getCreated_at()); } } } - public record SearchUnOfficialGroupResponseDTO(List unofficialOpenedGroups) { - public SearchUnOfficialGroupResponseDTO(Page unofficialOpenedGroups) { - this(unofficialOpenedGroups.stream().map(SearchGroupDTO.GroupInfoDTO::new).collect(Collectors.toList())); - } - } - + // 내 문서 기여 목록 조회 public record MyGroupHistoryResponseDTO(List myHistoryDTOS) { public MyGroupHistoryResponseDTO(Page histories) { this(histories.stream().map(MyGroupInfoResponseDTO.MyHistoryDTO::new).collect(Collectors.toList())); } } + + // 초대 링크 조회 + public record GetInvitationLinkResponseDTO(Long groupId, String invitationLink) { + public GetInvitationLinkResponseDTO(Long groupId, Invitation invitation) { + this(groupId, invitation.code()); + } + } + // 초대 링크를 통한 접근 public record ValidateInvitationResponseDTO(Long groupId) { } + // 그룹 검색 + public record SearchGroupDTO( + List officialGroups, + List unofficialOpenedGroups + ) { + public SearchGroupDTO(Page officialGroups, Page unofficialOpenedGroups) { + this(officialGroups.stream().map(GroupInfoDTO::new).collect(Collectors.toList()), + unofficialOpenedGroups.stream().map(OpenedGroupInfoDTO::new).collect(Collectors.toList())); + } + + public record GroupInfoDTO( + Long groupId, + String groupName, + String groupProfileImage, + int memberCount + ) { + public GroupInfoDTO(Group group) { + this(group.getId(), group.getGroupName(), group.getGroupProfileImage(), group.getMemberCount()); + } + } + + public record OpenedGroupInfoDTO( + Long groupId, + String groupName, + String groupProfileImage, + int memberCount, + String introduction + ) { + public OpenedGroupInfoDTO(UnOfficialOpenedGroup openedGroup) { + this(openedGroup.getId(), openedGroup.getGroupName(), openedGroup.getGroupProfileImage(), openedGroup.getMemberCount(), openedGroup.getIntroduction()); + } + } + } + + // 공식 그룹 추가 조회 + public record SearchOfficialGroupResponseDTO(List officialOpenedGroups) { + public SearchOfficialGroupResponseDTO(Page officialOpenedGroups) { + this(officialOpenedGroups.stream().map(SearchGroupDTO.GroupInfoDTO::new).collect(Collectors.toList())); + } + } + + // 비공식 공개 그룹 추가 조회 + public record SearchUnOfficialGroupResponseDTO(List unofficialOpenedGroups) { + public SearchUnOfficialGroupResponseDTO(Page unofficialOpenedGroups) { + this(unofficialOpenedGroups.stream().map(SearchGroupDTO.OpenedGroupInfoDTO::new).collect(Collectors.toList())); + } + } + // 그룹 정보 상세 조회 public record SearchGroupInfoDTO( String groupName, String groupImage, @@ -68,12 +117,7 @@ public SearchGroupInfoDTO(UnOfficialOpenedGroup group) { } } - public record SearchOfficialGroupResponseDTO(List officialOpenedGroups) { - public SearchOfficialGroupResponseDTO(Page officialOpenedGroups) { - this(officialOpenedGroups.stream().map(SearchGroupDTO.GroupInfoDTO::new).collect(Collectors.toList())); - } - } - + // 그룹 내 그룹원 리스트 조회 public record GetGroupMembersResponseDTO(List activeGroupMemberList) { public GetGroupMembersResponseDTO(Group group) { this(group.getGroupMembers().stream() @@ -83,28 +127,10 @@ public GetGroupMembersResponseDTO(Group group) { } } - public record CreateUnOfficialGroupResponseDTO(String groupName, String groupImage) { + // 비공식 그룹 생성 + public record CreateUnOfficialGroupResponseDTO(Long groupId, String groupName, String groupImage) { public CreateUnOfficialGroupResponseDTO(Group group) { - this(group.getGroupName(), group.getGroupProfileImage()); - } - } - - public record SearchGroupDTO( - List officialGroups, - List unofficialOpenedGroups - ) { - public SearchGroupDTO(Page officialGroups, Page unofficialOpenedGroups) { - this(officialGroups.stream().map(GroupInfoDTO::new).collect(Collectors.toList()), unofficialOpenedGroups.stream().map(GroupInfoDTO::new).collect(Collectors.toList())); - } - - public record GroupInfoDTO( - String groupName, - String groupProfileImage, - int memberCount - ) { - public GroupInfoDTO(Group group) { - this(group.getGroupName(), group.getGroupProfileImage(), group.getMemberCount()); - } + this(group.getId(), group.getGroupName(), group.getGroupProfileImage()); } } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index d9dd892d..996b1f88 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -237,13 +237,18 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ /* 그룹 내 그룹원 리스트 조회 */ - public GroupResponseDTO.GetGroupMembersResponseDTO getGroupMembers(Long groupId) { + public GroupResponseDTO.GetGroupMembersResponseDTO getGroupMembers(Long groupId, Long memberId) { try { Group group = getGroupById(groupId); + Member member = getMemberById(memberId); + + if(groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId).isEmpty()) { + throw new Exception400("해당 그룹에 대한 권한이 없습니다."); + } return new GroupResponseDTO.GetGroupMembersResponseDTO(group); - } catch (Exception404 e) { + } catch (Exception400 | Exception404 e) { throw e; } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index 47a9ca5d..753756c4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -46,7 +46,7 @@ public GroupResponseDTO.GetInvitationLinkResponseDTO getGroupInvitationCode(Long } // 있으면 해당 초대 링크로 requestDTO 생성 - return new GroupResponseDTO.GetInvitationLinkResponseDTO(invitation); + return new GroupResponseDTO.GetInvitationLinkResponseDTO(groupId, invitation); } // 초대 링크를 통한 접근 시 유효한 초대 링크 확인, 해당 그룹으로 연결 From b74776cd2e3951d020e462f72e0ab1a54d6fbd1b Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Thu, 2 Nov 2023 17:04:27 +0900 Subject: [PATCH 070/144] =?UTF-8?q?Feat=20:=20=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20=EB=82=B4?= =?UTF-8?q?=EA=B0=80=20=EC=86=8D=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20?= =?UTF-8?q?=EA=B7=B8=EB=A3=B9=EB=A7=8C=20=ED=91=9C=EC=8B=9C=20-=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=9B=84=20=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A0=91=EA=B7=BC=20=EC=8B=9C,?= =?UTF-8?q?=20=EA=B7=B8=EB=A3=B9=20=EB=91=98=EB=9F=AC=EB=B3=B4=EA=B8=B0=20?= =?UTF-8?q?=EC=B0=BD=EC=97=90=20=EB=82=B4=EA=B0=80=20=EC=86=8D=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EA=B7=B8=EB=A3=B9=EB=A7=8C=20?= =?UTF-8?q?=ED=91=9C=EC=8B=9C=EB=90=98=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kakao/techcampus/wekiki/page/PageService.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 30843781..9d4d451f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -5,6 +5,7 @@ import com.kakao.techcampus.wekiki._core.utils.IndexUtils; import com.kakao.techcampus.wekiki._core.utils.RedisUtility; import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; @@ -60,17 +61,21 @@ public PageInfoResponse.mainPageDTO getMainPage() { else { System.out.println("로그인 함"); Optional member = memberJPARepository.findById(currentMember()); - List myGroupList = member.get().getGroupMembers().stream() - .map(groupMember -> { - return new PageInfoResponse.mainPageDTO.GroupDTO(groupMember.getGroup()); - }).toList(); + if(member.isEmpty()) + throw new Exception400("없는 회원입니다."); + List myGroupList = member.get().getGroupMembers().stream().map(GroupMember::getGroup).toList(); + List myGroupIdList = myGroupList.stream().map(Group::getId).toList(); + List myGroupListDTO = myGroupList.stream() + .map(PageInfoResponse.mainPageDTO.GroupDTO::new) + .collect(Collectors.toList()); List officialGroupList = groupJPARepository.findAllOfficialGroup().stream() .map(PageInfoResponse.mainPageDTO.GroupDTO::new) .collect(Collectors.toList()); List unOfficialGroupList = groupJPARepository.findAllUnOfficialOpenGroup().stream() + .filter(tempGroup -> !myGroupIdList.contains(tempGroup.getId())) .map(PageInfoResponse.mainPageDTO.GroupDTO::new) .collect(Collectors.toList()); - return new PageInfoResponse.mainPageDTO(myGroupList, officialGroupList, unOfficialGroupList); + return new PageInfoResponse.mainPageDTO(myGroupListDTO, officialGroupList, unOfficialGroupList); } } From 6ec094f25a8f421e1b22841660968322046165ab Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Thu, 2 Nov 2023 17:06:28 +0900 Subject: [PATCH 071/144] =?UTF-8?q?Refactor=20:=20id=EB=A5=BC=20groupId?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kakao/techcampus/wekiki/page/PageInfoResponse.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index 1635dfac..7f4bb7a5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -26,11 +26,11 @@ public mainPageDTO(List officialGroup, List unOfficialGroup) } @Getter public static class GroupDTO { - Long id; + Long groupId; String groupImage; String groupName; public GroupDTO(Group group) { - this.id = group.getId(); + this.groupId = group.getId(); this.groupImage =group.getGroupProfileImage(); this.groupName = group.getGroupName(); } From d4ea00e8c1480ef2f0f0f632a0b1acd5a63a18fc Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Thu, 2 Nov 2023 17:07:42 +0900 Subject: [PATCH 072/144] =?UTF-8?q?Feat=20:=20kakao=20=EC=9D=B8=EA=B0=80?= =?UTF-8?q?=20code=20=EB=A5=BC=20=EB=B0=9B=EC=95=84=20kakao=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=ED=9A=8C=EC=9B=90=20=EC=A0=95=EB=B3=B4=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20-=20=EC=95=84=EC=A7=81=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=8A=94=20=EB=A7=88=EC=B9=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EC=95=98=EC=8A=B5=EB=8B=88=EB=8B=A4...=20?= =?UTF-8?q?=EC=9D=B8=EA=B0=80=20=EC=BD=94=EB=93=9C=EB=A5=BC=20=EB=B0=9B?= =?UTF-8?q?=EC=9D=84=20=EC=88=98=20=EC=97=86=EC=96=B4=EC=84=9C...=20-=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=EC=9D=84=20=EC=96=B4?= =?UTF-8?q?=EB=96=BB=EA=B2=8C=20=ED=95=B4=EC=95=BC=20=ED=95=A0=20=EC=A7=80?= =?UTF-8?q?=20=EA=B3=A0=EB=AF=BC=EC=9E=85=EB=8B=88=EB=8B=A4..?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wekiki/member/MemberController.java | 6 ++ .../wekiki/member/MemberResponse.java | 14 ++++ .../wekiki/member/MemberService.java | 77 +++++++++++++++++++ wekiki/src/main/resources/application.yml | 6 +- 4 files changed, 102 insertions(+), 1 deletion(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java index 0430eba1..435d000f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java @@ -23,6 +23,12 @@ public ResponseEntity signIn(@RequestBody MemberRequest.loginRequestDTO login return ResponseEntity.ok(ApiUtils.success(response)); } + @GetMapping("/kakao/signin") + public ResponseEntity kakaoLogin(@RequestParam String code) { + memberService.getKakaoInfo(code); + return ResponseEntity.ok(true); + } + @GetMapping("/myinfo") public ResponseEntity myPage() { MemberResponse.myInfoResponseDTO response = memberService.getMyInfo(); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java index 0e55b64c..4bdcc0f5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java @@ -11,6 +11,20 @@ import java.util.List; public class MemberResponse { + @Getter + @AllArgsConstructor + public static class KakaoTokenDTO{ + private String token_type; + private String access_token; + private int expires_in; + private String refresh_token; + private String refresh_token_expires_in; + } + + public static class KakaoInfoDTO { + + } + //아직 RefreshToken은 안만들었습니다 @Getter @AllArgsConstructor diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index e3732e74..88cda622 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -1,10 +1,20 @@ package com.kakao.techcampus.wekiki.member; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.util.JSONPObject; import com.kakao.techcampus.wekiki._core.error.exception.*; import com.kakao.techcampus.wekiki._core.jwt.JWTTokenProvider; import com.kakao.techcampus.wekiki._core.utils.RedisUtility; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.tomcat.util.json.JSONParser; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.security.authentication.AuthenticationManager; @@ -14,6 +24,9 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; import java.time.LocalDateTime; import java.util.List; @@ -34,6 +47,10 @@ public class MemberService { private final PasswordEncoder passwordEncoder; private final RedisUtility redisUtility; private final JavaMailSender javaMailSender; + @Value("${kakao.client.id}") + private String KAKAO_CLIENT_ID; + @Value("${kakao.redirect.uri}") + private String KAKAO_REDIRECT_URI; public void signUp(MemberRequest.signUpRequestDTO signUpRequestDTO) { @@ -195,4 +212,64 @@ private Member findMember() { return member.get(); } + public void getKakaoInfo(String code) { + + String accessToken = ""; + + try{ + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-type", "application/x-www-form-urlencoded"); + + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("grant_type", "authorization_code"); + params.add("client_id", KAKAO_CLIENT_ID); + params.add("code", code); + params.add("redirect_uri", KAKAO_REDIRECT_URI); + + RestTemplate restTemplate = new RestTemplate(); + HttpEntity> httpEntity = new HttpEntity<>(params, headers); + + ResponseEntity response = restTemplate.exchange( + "https://kauth.kakao.com/oauth/token", + HttpMethod.POST, + httpEntity, + String.class + ); + + ObjectMapper objectMapper = new ObjectMapper(); + MemberResponse.KakaoTokenDTO kakaoTokenDTO = objectMapper.readValue(response.getBody(), MemberResponse.KakaoTokenDTO.class); + accessToken = kakaoTokenDTO.getAccess_token(); + + } catch (JsonProcessingException e) { + throw new Exception500("Json 파싱 에러입니다." + e); + } + getUserInfoWithToken(accessToken); + } + + private void getUserInfoWithToken(String accessToken) { + RestTemplate restTemplate = new RestTemplate(); + + HttpHeaders headers = new HttpHeaders(); + headers.add("Authorization", "Bearer " + accessToken); + headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8"); + + HttpEntity> httpEntity = new HttpEntity<>(headers); + + ResponseEntity response = restTemplate.exchange( + "https://kapi.kakao.com/v2/user/me", + HttpMethod.POST, + httpEntity, + String.class + ); + + System.out.println(response.getBody()); + + /*ObjectMapper objectMapper = new ObjectMapper(); + try { + objectMapper.readValue(response.getBody()); + + } catch (JsonProcessingException e) { + throw new Exception500("Json 파싱 에러입니다." + e); + }*/ + } } diff --git a/wekiki/src/main/resources/application.yml b/wekiki/src/main/resources/application.yml index 83c2d618..d8ffa186 100644 --- a/wekiki/src/main/resources/application.yml +++ b/wekiki/src/main/resources/application.yml @@ -42,7 +42,11 @@ spring: enable: true jwt: secret: 7ZmA656AIOuTneygkOyZlSDquLDsm5AgMeydvOywqALdlsKJL3234jklsdjfaKJDLnflkasdf - +kakao: + client: + id: 08e6c709229f3b44a8cff2fc7168e1a2 + redirect: + uri: http://3.39.150.229:8080/auth/kakao/signin logging: level: '[com.example.kakao]': DEBUG From 1a70f05923d03dcf46ffc66c47922b498e254dce Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Thu, 2 Nov 2023 18:09:09 +0900 Subject: [PATCH 073/144] =?UTF-8?q?Refactor:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=EC=99=80=20=EC=9D=91=EB=8B=B5=20DTO=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 유효성 검사 추가 - 응답 DTO 프론트와 협의 후 수정 --- .../group/controller/GroupRestController.java | 4 +- .../techcampus/wekiki/group/domain/Group.java | 7 +++- .../wekiki/group/dto/GroupRequestDTO.java | 1 + .../wekiki/group/dto/GroupResponseDTO.java | 36 ++++++------------ .../repository/GroupMemberJPARepository.java | 2 +- .../wekiki/group/service/GroupService.java | 37 +++++++++++++++++-- .../group/service/InvitationService.java | 5 +++ 7 files changed, 61 insertions(+), 31 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java index 159e5d48..b4d59391 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java @@ -104,7 +104,7 @@ public ResponseEntity groupEntry(@PathVariable("groupId") Long groupId, @Requ 그룹 참가 */ @PostMapping("/{groupId}/join") - public ResponseEntity joinGroup(@PathVariable("groupId") Long groupId, @RequestBody GroupRequestDTO.JoinGroupRequestDTO requestDTO, BindingResult result) { + public ResponseEntity joinGroup(@PathVariable("groupId") Long groupId, @RequestBody @Valid GroupRequestDTO.JoinGroupRequestDTO requestDTO, BindingResult result) { // 유효성 검사 if (result.hasErrors()) { @@ -166,7 +166,7 @@ public ResponseEntity myGroupPage(@PathVariable("groupId") Long groupId) { 그룹 내 본인 정보 수정 */ @PatchMapping("/{groupId}/myInfo") - public ResponseEntity updateMyGroupPage(@PathVariable("groupId") Long groupId, @RequestBody GroupRequestDTO.UpdateMyGroupPageDTO requestDTO, BindingResult result) { + public ResponseEntity updateMyGroupPage(@PathVariable("groupId") Long groupId, @RequestBody @Valid GroupRequestDTO.UpdateMyGroupPageDTO requestDTO, BindingResult result) { // 유효성 검사 if (result.hasErrors()) { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java index f6fa5424..a0887262 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java @@ -36,7 +36,12 @@ public Group(Long id, String groupName, String groupProfileImage, LocalDateTime this.id = id; this.groupName = groupName; this.groupProfileImage = groupProfileImage; - this.memberCount = 1; + this.memberCount = 0; this.created_at = created_at; } + + public void addGroupMember(GroupMember groupMember) { + this.groupMembers.add(groupMember); + this.memberCount = this.groupMembers.size(); + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java index 88bd20aa..4672f3f5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java @@ -5,6 +5,7 @@ public class GroupRequestDTO { + // 그룹 생성 public record CreateUnOfficialGroupRequestDTO( @NotNull(message = "그룹 유형을 선택해 주세요.") GroupType groupType, diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java index c6006ccf..b2c11cdd 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java @@ -38,7 +38,7 @@ public MyHistoryDTO(History history) { } // 내 문서 기여 목록 조회 - public record MyGroupHistoryResponseDTO(List myHistoryDTOS) { + public record MyGroupHistoryResponseDTO(List historyList) { public MyGroupHistoryResponseDTO(Page histories) { this(histories.stream().map(MyGroupInfoResponseDTO.MyHistoryDTO::new).collect(Collectors.toList())); } @@ -58,33 +58,20 @@ public record ValidateInvitationResponseDTO(Long groupId) { // 그룹 검색 public record SearchGroupDTO( List officialGroups, - List unofficialOpenedGroups + List unofficialOpenedGroups ) { public SearchGroupDTO(Page officialGroups, Page unofficialOpenedGroups) { - this(officialGroups.stream().map(GroupInfoDTO::new).collect(Collectors.toList()), - unofficialOpenedGroups.stream().map(OpenedGroupInfoDTO::new).collect(Collectors.toList())); + this(officialGroups.stream().map(SearchGroupDTO.GroupInfoDTO::new).collect(Collectors.toList()), + unofficialOpenedGroups.stream().map(GroupInfoDTO::new).collect(Collectors.toList())); } public record GroupInfoDTO( Long groupId, String groupName, - String groupProfileImage, - int memberCount + String groupProfileImage ) { public GroupInfoDTO(Group group) { - this(group.getId(), group.getGroupName(), group.getGroupProfileImage(), group.getMemberCount()); - } - } - - public record OpenedGroupInfoDTO( - Long groupId, - String groupName, - String groupProfileImage, - int memberCount, - String introduction - ) { - public OpenedGroupInfoDTO(UnOfficialOpenedGroup openedGroup) { - this(openedGroup.getId(), openedGroup.getGroupName(), openedGroup.getGroupProfileImage(), openedGroup.getMemberCount(), openedGroup.getIntroduction()); + this(group.getId(), group.getGroupName(), group.getGroupProfileImage()); } } } @@ -97,14 +84,15 @@ public SearchOfficialGroupResponseDTO(Page officialOpenedGroups) } // 비공식 공개 그룹 추가 조회 - public record SearchUnOfficialGroupResponseDTO(List unofficialOpenedGroups) { + public record SearchUnOfficialGroupResponseDTO(List unofficialOpenedGroups) { public SearchUnOfficialGroupResponseDTO(Page unofficialOpenedGroups) { - this(unofficialOpenedGroups.stream().map(SearchGroupDTO.OpenedGroupInfoDTO::new).collect(Collectors.toList())); + this(unofficialOpenedGroups.stream().map(SearchGroupDTO.GroupInfoDTO::new).collect(Collectors.toList())); } } // 그룹 정보 상세 조회 public record SearchGroupInfoDTO( + Long groupId, String groupName, String groupImage, String introduction, @@ -113,16 +101,16 @@ public record SearchGroupInfoDTO( String entranceHint ) { public SearchGroupInfoDTO(UnOfficialOpenedGroup group) { - this(group.getGroupName(), group.getGroupProfileImage(), group.getIntroduction(), group.getMemberCount(), group.getCreated_at(), group.getEntranceHint()); + this(group.getId(), group.getGroupName(), group.getGroupProfileImage(), group.getIntroduction(), group.getMemberCount(), group.getCreated_at(), group.getEntranceHint()); } } // 그룹 내 그룹원 리스트 조회 - public record GetGroupMembersResponseDTO(List activeGroupMemberList) { + public record GetGroupMembersResponseDTO(List nickNames) { public GetGroupMembersResponseDTO(Group group) { this(group.getGroupMembers().stream() .filter(groupMember -> groupMember instanceof ActiveGroupMember) - .map(groupMember -> (ActiveGroupMember) groupMember) + .map(groupMember -> groupMember.getNickName()) .collect(Collectors.toList())); } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java index 738c85ca..956243f6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java @@ -15,7 +15,7 @@ @Repository public interface GroupMemberJPARepository extends JpaRepository { @Query("SELECT iagm FROM InactiveGroupMember iagm WHERE iagm.member = :member AND iagm.group = :group") - InactiveGroupMember findInactiveGroupMemberByMemberAndGroup(Member member, Group group); + InactiveGroupMember findInactiveGroupMemberByMemberAndGroup(@Param("member") Member member, @Param("group") Group group); @Query("SELECT agm FROM ActiveGroupMember agm WHERE agm.member.id = :memberId AND agm.group.id = :groupId") Optional findActiveGroupMemberByMemberIdAndGroupId(@Param("memberId") Long memberId, @Param("groupId") Long groupId); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 996b1f88..8ceff8e1 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -59,7 +59,11 @@ public GroupResponseDTO.CreateUnOfficialGroupResponseDTO createUnOfficialGroup(G ActiveGroupMember groupMember = buildGroupMember(member, group, requestDTO.groupNickName()); // Entity 저장 + group.addGroupMember(groupMember); + member.getGroupMembers().add(groupMember); + groupJPARepository.save(group); + memberJPARepository.save(member); groupMemberJPARepository.save(groupMember); // return @@ -142,8 +146,14 @@ public GroupResponseDTO.SearchOfficialGroupResponseDTO searchOfficialGroupByKeyw // 비공식 공개 그룹 리스트 Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); + if (officialGroups.isEmpty()) { + throw new Exception404("마지막 페이지입니다."); + } + return new GroupResponseDTO.SearchOfficialGroupResponseDTO(officialGroups); + } catch (Exception404 e) { + throw e; } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } @@ -159,8 +169,14 @@ public GroupResponseDTO.SearchUnOfficialGroupResponseDTO searchUnOfficialGroupBy // 비공식 공개 그룹 리스트 Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); + if (unOfficialOpenedGroups.isEmpty()) { + throw new Exception404("마지막 페이지입니다."); + } + return new GroupResponseDTO.SearchUnOfficialGroupResponseDTO(unOfficialOpenedGroups); + } catch (Exception404 e) { + throw e; } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); } @@ -231,6 +247,11 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ } // GroupMember 저장 + group.addGroupMember(groupMember); + member.getGroupMembers().add(groupMember); + + groupJPARepository.save(group); + memberJPARepository.save(member); groupMemberJPARepository.save(groupMember); } @@ -240,7 +261,6 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ public GroupResponseDTO.GetGroupMembersResponseDTO getGroupMembers(Long groupId, Long memberId) { try { Group group = getGroupById(groupId); - Member member = getMemberById(memberId); if(groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId).isEmpty()) { throw new Exception400("해당 그룹에 대한 권한이 없습니다."); @@ -281,7 +301,6 @@ public GroupResponseDTO.MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long /* 내 문서 기여 목록 전체 보기 */ - @Transactional public GroupResponseDTO.MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, int page, int size) { try { // 그룹 멤버 확인 @@ -311,13 +330,25 @@ public void updateMyGroupPage(Long groupId, Long memberId, GroupRequestDTO.Updat ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹의 회원이 아닙니다")); + // 변경할 닉네임 확인 + String newNickName = requestDTO.groupNickName(); + + // 빈칸이거나 기존 닉네임과 같을 시 예외 처리 + if(newNickName.isEmpty()) { + throw new Exception400("공백은 닉네임이 될 수 없습니다."); + } + + if(groupMember.getNickName().equals(newNickName)) { + throw new Exception400("기존 닉네임과 같은 닉네임입니다."); + } + // 그룹 닉네임 변경 groupMember.update(requestDTO.groupNickName()); // 저장 groupMemberJPARepository.save(groupMember); - } catch (Exception404 e) { + } catch (Exception400 | Exception404 e) { throw e; } catch (Exception e) { throw new Exception500("서버 에러가 발생했습니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index 753756c4..de447193 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -2,6 +2,7 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; +import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.group.dto.GroupResponseDTO; import com.kakao.techcampus.wekiki.group.domain.Invitation; import lombok.RequiredArgsConstructor; @@ -18,6 +19,8 @@ public class InvitationService { private final RedisUtils redisUtils; + private final GroupService groupService; + private static final String GROUP_ID_PREFIX = "group_id:"; private static final String INVITATION_PREFIX = "invitation:"; @@ -29,6 +32,8 @@ public class InvitationService { */ public GroupResponseDTO.GetInvitationLinkResponseDTO getGroupInvitationCode(Long groupId) { + groupService.getGroupById(groupId); + String groupKey = GROUP_ID_PREFIX + groupId; // 기존 초대 링크 여부 확인 From 5485c1596188fd4d910c9359de7f241e7c82f09c Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Fri, 3 Nov 2023 18:28:14 +0900 Subject: [PATCH 074/144] =?UTF-8?q?Feat=20:=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EB=8B=89=EB=84=A4=EC=9E=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kakao/techcampus/wekiki/member/Member.java | 4 ++++ .../wekiki/member/MemberController.java | 6 ++++++ .../techcampus/wekiki/member/MemberRequest.java | 5 +++++ .../techcampus/wekiki/member/MemberService.java | 16 +++++++++++----- .../techcampus/wekiki/page/PageService.java | 14 ++++++++++---- 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java index aec12609..5daddb49 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java @@ -43,4 +43,8 @@ public Member(String name, String email, String password, LocalDateTime created_ public void changePassword(String password) { this.password = password; } + + public void changeNickName(String name) { + this.name = name; + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java index 435d000f..daeaf0a4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java @@ -51,6 +51,12 @@ public ResponseEntity changePassword(@RequestBody MemberRequest.changePasswor return ResponseEntity.ok(true); } + @PatchMapping("/changename") + public ResponseEntity changeNickName(@RequestBody MemberRequest.changeNickNameRequestDTO nickNameRequestDTO) { + memberService.changeNickName(nickNameRequestDTO); + return ResponseEntity.ok(true); + } + @PostMapping("/pusanuniv") public ResponseEntity sendMail(@RequestBody MemberRequest.PNUEmailRequestDTO PNUemailRequestDTO) { memberService.sendEmail(PNUemailRequestDTO.getEmail()); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java index d83020f4..f8085230 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java @@ -24,6 +24,11 @@ public static class changePasswordRequestDTO { private String newPassword; } + @Getter + public static class changeNickNameRequestDTO { + private String newNickName; + } + @Getter public static class PNUEmailRequestDTO { private String email; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index 88cda622..ceb9947d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -114,6 +114,17 @@ public void cancel() { memberRepository.delete(member); } + public void changeNickName(MemberRequest.changeNickNameRequestDTO nickNameRequestDTO) { + Member member; + try { + member = findMember(); + } catch (Exception404 e) { + log.error("Access Token에서 뽑아낸 회원이 존재하지 않는 회원입니다. (전체 닉네임 변경)"); + throw e; + } + member.changeNickName(nickNameRequestDTO.getNewNickName()); + } + public void changePassword(MemberRequest.changePasswordRequestDTO changePasswordDTO) { Member member; try { @@ -122,11 +133,6 @@ public void changePassword(MemberRequest.changePasswordRequestDTO changePassword log.error("Access Token에서 뽑아낸 회원이 존재하지 않는 회원입니다. (비밀번호 변경)"); throw e; } - /*Optional member = memberRepository.findById(currentMember()); - if(member.isEmpty()) { - log.error("Access Token에서 뽑아낸 회원이 존재하지 않는 회원입니다. (비밀번호 변경)"); - throw new Exception404("없는 회원입니다."); - }*/ if(!passwordEncoder.matches(changePasswordDTO.getCurrentPassword(), member.getPassword())) { log.error("비밀번호 변경 요청에서의 비밀번호 확인이 틀렸습니다. User Id : " + member.getEmail()); throw new Exception400("비밀번호가 틀렸습니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 9d4d451f..17bf75d9 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -15,6 +15,7 @@ import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -33,6 +34,7 @@ @RequiredArgsConstructor @Service +@Slf4j public class PageService { private final PageJPARepository pageJPARepository; @@ -41,7 +43,6 @@ public class PageService { private final GroupMemberJPARepository groupMemberJPARepository; private final GroupJPARepository groupJPARepository; private final IndexUtils indexUtils; - private final RedisUtility redisUtility; final int PAGE_COUNT = 10; @@ -49,7 +50,7 @@ public class PageService { public PageInfoResponse.mainPageDTO getMainPage() { if(SecurityContextHolder.getContext().getAuthentication().getName().equals("anonymousUser")) { // 로그인 안한 사람 - System.out.println("로그인 안함"); + log.info("로그인하지 않은 사람의 메인 페이지 조회"); List officialGroupList = groupJPARepository.findAllOfficialGroup().stream() .map(PageInfoResponse.mainPageDTO.GroupDTO::new) .collect(Collectors.toList()); @@ -59,10 +60,13 @@ public PageInfoResponse.mainPageDTO getMainPage() { return new PageInfoResponse.mainPageDTO(officialGroupList, unOfficialGroupList); } else { - System.out.println("로그인 함"); + //로그인을 한 사람 + log.info("로그인을 한 사람의 메인 페이지 조회"); Optional member = memberJPARepository.findById(currentMember()); - if(member.isEmpty()) + if(member.isEmpty()) { + log.error("회원이 존재하지 않습니다."); throw new Exception400("없는 회원입니다."); + } List myGroupList = member.get().getGroupMembers().stream().map(GroupMember::getGroup).toList(); List myGroupIdList = myGroupList.stream().map(Group::getId).toList(); List myGroupListDTO = myGroupList.stream() @@ -70,10 +74,12 @@ public PageInfoResponse.mainPageDTO getMainPage() { .collect(Collectors.toList()); List officialGroupList = groupJPARepository.findAllOfficialGroup().stream() .map(PageInfoResponse.mainPageDTO.GroupDTO::new) + .limit(5) .collect(Collectors.toList()); List unOfficialGroupList = groupJPARepository.findAllUnOfficialOpenGroup().stream() .filter(tempGroup -> !myGroupIdList.contains(tempGroup.getId())) .map(PageInfoResponse.mainPageDTO.GroupDTO::new) + .limit(5) .collect(Collectors.toList()); return new PageInfoResponse.mainPageDTO(myGroupListDTO, officialGroupList, unOfficialGroupList); } From e5fcb81786e6b58b43cf63e710f841f59079b7f1 Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Sat, 4 Nov 2023 10:20:59 +0900 Subject: [PATCH 075/144] =?UTF-8?q?Refactor=20:=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=A7=80=ED=96=A5=EC=9C=BC=EB=A1=9C=20=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A1=B0=ED=9A=8C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wekiki/_core/jwt/JWTTokenProvider.java | 5 +- .../techcampus/wekiki/member/Member.java | 4 +- .../techcampus/wekiki/page/PageService.java | 50 ++++++++++++------- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/jwt/JWTTokenProvider.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/jwt/JWTTokenProvider.java index 6bbe0198..0a95506b 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/jwt/JWTTokenProvider.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/jwt/JWTTokenProvider.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki._core.jwt; +import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki.member.MemberResponse; import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; @@ -85,7 +86,9 @@ public Claims parseClaims(String accessToken) { public Authentication getAuthentication(String token) { Claims claims = parseClaims(token); - + if (!validateToken(token)) { + throw new Exception400("Token이 잘못되었습니다."); + } // 권한 정보가 없으면 예외 if (claims.get("auth") == null) { throw new RuntimeException("권한 정보가 없는 Token 입니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java index 5daddb49..80b67cb3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java @@ -2,6 +2,7 @@ import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -21,11 +22,12 @@ public class Member { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; + @NotNull private String email; private String password; private LocalDateTime created_at; - @OneToMany(mappedBy = "member") + @OneToMany(mappedBy = "member", cascade = CascadeType.REMOVE) private List groupMembers = new ArrayList<>(); @Enumerated(value = EnumType.STRING) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 17bf75d9..88ad33aa 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -51,12 +51,8 @@ public PageInfoResponse.mainPageDTO getMainPage() { if(SecurityContextHolder.getContext().getAuthentication().getName().equals("anonymousUser")) { // 로그인 안한 사람 log.info("로그인하지 않은 사람의 메인 페이지 조회"); - List officialGroupList = groupJPARepository.findAllOfficialGroup().stream() - .map(PageInfoResponse.mainPageDTO.GroupDTO::new) - .collect(Collectors.toList()); - List unOfficialGroupList = groupJPARepository.findAllUnOfficialOpenGroup().stream() - .map(PageInfoResponse.mainPageDTO.GroupDTO::new) - .collect(Collectors.toList()); + List officialGroupList = getOfficialGroupList(); + List unOfficialGroupList = getUnLoginUnOfficialGroupList(); return new PageInfoResponse.mainPageDTO(officialGroupList, unOfficialGroupList); } else { @@ -69,22 +65,40 @@ public PageInfoResponse.mainPageDTO getMainPage() { } List myGroupList = member.get().getGroupMembers().stream().map(GroupMember::getGroup).toList(); List myGroupIdList = myGroupList.stream().map(Group::getId).toList(); - List myGroupListDTO = myGroupList.stream() - .map(PageInfoResponse.mainPageDTO.GroupDTO::new) - .collect(Collectors.toList()); - List officialGroupList = groupJPARepository.findAllOfficialGroup().stream() - .map(PageInfoResponse.mainPageDTO.GroupDTO::new) - .limit(5) - .collect(Collectors.toList()); - List unOfficialGroupList = groupJPARepository.findAllUnOfficialOpenGroup().stream() - .filter(tempGroup -> !myGroupIdList.contains(tempGroup.getId())) - .map(PageInfoResponse.mainPageDTO.GroupDTO::new) - .limit(5) - .collect(Collectors.toList()); + List myGroupListDTO = getMyGroupList(myGroupList); + List officialGroupList = getOfficialGroupList(); + List unOfficialGroupList = getLoginUnOfficialGroupList(myGroupIdList); return new PageInfoResponse.mainPageDTO(myGroupListDTO, officialGroupList, unOfficialGroupList); } } + private List getMyGroupList (List myGroupList) { + return myGroupList.stream() + .map(PageInfoResponse.mainPageDTO.GroupDTO::new) + .collect(Collectors.toList()); + } + private List getOfficialGroupList () { + return groupJPARepository.findAllOfficialGroup().stream() + .map(PageInfoResponse.mainPageDTO.GroupDTO::new) + .limit(5) + .collect(Collectors.toList()); + } + + private List getUnLoginUnOfficialGroupList() { + return groupJPARepository.findAllUnOfficialOpenGroup().stream() + .map(PageInfoResponse.mainPageDTO.GroupDTO::new) + .limit(5) + .collect(Collectors.toList()); + } + + private List getLoginUnOfficialGroupList(List myGroupIdList) { + return groupJPARepository.findAllUnOfficialOpenGroup().stream() + .map(PageInfoResponse.mainPageDTO.GroupDTO::new) + .filter(tempGroup -> !myGroupIdList.contains(tempGroup.getGroupId())) + .limit(5) + .toList(); + } + @Transactional public PageInfoResponse.getPageIndexDTO getPageIndex(Long groupId,Long memberId, Long pageId){ From 71224ec788ede25d771fc0e2830cbd3e02b28dc5 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 4 Nov 2023 14:34:36 +0900 Subject: [PATCH 076/144] =?UTF-8?q?Feat=20:=20=ED=82=A4=EC=9B=8C=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=ED=86=B5=ED=95=9C=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EA=B2=80=EC=83=89=20api=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 해당 키워드로 시작하는 페이지만 검색하다가 해당 키워드를 포함하는 모든 페이지 검색으로 수정하였습니다. --- .../com/kakao/techcampus/wekiki/page/PageJPARepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java index 5f8227ab..75acda3d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java @@ -28,7 +28,7 @@ public interface PageJPARepository extends JpaRepository { @Query("SELECT p FROM PageInfo p LEFT JOIN FETCH p.posts ps WHERE p.id = :pageId ORDER BY ps.orders ASC") Optional findByPageIdWithPosts(@Param("pageId") Long pageId); - @Query("SELECT p FROM PageInfo p LEFT JOIN FETCH p.posts ps WHERE p.group.id = :groupId AND p.pageName LIKE :keyword%") + @Query("SELECT p FROM PageInfo p LEFT JOIN FETCH p.posts ps WHERE p.group.id = :groupId AND p.pageName LIKE %:keyword%") Page findPagesWithPosts(@Param("groupId") Long groupId, @Param("keyword") String keyword, Pageable pageable); From 94f36db8c9d3b6142c03081d679269f3cad03731 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 4 Nov 2023 14:48:17 +0900 Subject: [PATCH 077/144] =?UTF-8?q?Feat=20:=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=B2=A0=EC=9D=B4=EC=8A=A4=20=EC=B9=BC=EB=9F=BC=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Post의 content랑 History의 content 부분 String에서 TEXT로 수정하였습니다. --- .../main/java/com/kakao/techcampus/wekiki/history/History.java | 2 ++ wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java | 1 + 2 files changed, 3 insertions(+) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java index 4690be7a..5342e1cf 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java @@ -25,6 +25,8 @@ public class History { private Post post; private String title; + + @Column(columnDefinition = "TEXT") private String content; private LocalDateTime created_at; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java index 5cd840d0..4e02221b 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java @@ -40,6 +40,7 @@ public class Post { private List comments = new ArrayList<>(); private String title; + @Column(columnDefinition = "TEXT") private String content; private LocalDateTime created_at; From fecea0e6415dac4d0728d45f790b7094e136330a Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 4 Nov 2023 15:45:18 +0900 Subject: [PATCH 078/144] =?UTF-8?q?deploy=20:=20=EB=B0=B0=ED=8F=AC?= =?UTF-8?q?=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EC=84=A4=EC=A0=95=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 카카오 크램플론 배포를 위해 설정 파일 추가하였습니다. --- Dockerfile | 22 +++++++++++++++ goorm.manifest | 1 + k8s/backend.yaml | 37 +++++++++++++++++++++++++ k8s/configs/default.conf | 7 +++++ k8s/kustomization.yaml | 10 +++++++ k8s/mariadb.yaml | 59 ++++++++++++++++++++++++++++++++++++++++ k8s/nginx.yaml | 59 ++++++++++++++++++++++++++++++++++++++++ k8s/redis.yaml | 33 ++++++++++++++++++++++ 8 files changed, 228 insertions(+) create mode 100644 Dockerfile create mode 100644 goorm.manifest create mode 100644 k8s/backend.yaml create mode 100644 k8s/configs/default.conf create mode 100644 k8s/kustomization.yaml create mode 100644 k8s/mariadb.yaml create mode 100644 k8s/nginx.yaml create mode 100644 k8s/redis.yaml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..2cb72fab --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +# gradle:7.3.1-jdk17 이미지를 기반으로 함 +FROM krmp-d2hub-idock.9rum.cc/goorm/gradle:7.3.1-jdk17 + +# 작업 디렉토리 설정 +WORKDIR /home/wekiki/gradle/project + +# Spring 소스 코드를 이미지에 복사 +COPY . . + +# gradle 빌드 시 proxy 설정을 gradle.properties에 추가 +RUN echo "systemProp.http.proxyHost=krmp-proxy.9rum.cc\nsystemProp.http.proxyPort=3128\nsystemProp.https.proxyHost=krmp-proxy.9rum.cc\nsystemProp.https.proxyPort=3128" > /root/.gradle/gradle.properties + +# gradlew를 이용한 프로젝트 필드 +RUN chmod +x ./wekiki/gradlew + +RUN cd ./wekiki && ./gradlew clean build -x test + +# DATABASE_URL을 환경 변수로 삽입 +ENV DATABASE_URL=jdbc:mariadb://mariadb/krampoline + +# 빌드 결과 jar 파일을 실행 +CMD ["java", "-jar", "-Dspring.profiles.active=prod", "/home/wekiki/gradle/project/wekiki/build/libs/wekiki-0.0.1-SNAPSHOT.jar"] \ No newline at end of file diff --git a/goorm.manifest b/goorm.manifest new file mode 100644 index 00000000..2d6281d5 --- /dev/null +++ b/goorm.manifest @@ -0,0 +1 @@ +{"storage":"container","type":"jsp","detailedtype":"spring_gradle","author":"2897511940_afogg_kakao-oidc","name":"Team8_BE_deploy","description":"8조","date":"2023/10/30 19:4:55","plugins":{"goorm.plugin.jsp":[{"plugin.jsp.source_path":"src/main/java","plugin.jsp.build_path":"build/","plugin.jsp.deploy_path":"goormService/tomcat7/webapps/","plugin.jsp.spring.source_path":"src/main/java"}]},"is_user_plugin":false,"show_preview_btn":true,"author_email":"ehstjstod@naver.com","author_name":"ehstjstod","ignore_patterns":[],"project_domain":[{"id":"2897511940_afogg_kakao-oidc","url":"dyzgw-szdggtfauc.krampoline.com","port":"80"}],"visibility":2} \ No newline at end of file diff --git a/k8s/backend.yaml b/k8s/backend.yaml new file mode 100644 index 00000000..c328c7a0 --- /dev/null +++ b/k8s/backend.yaml @@ -0,0 +1,37 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: backend +spec: + selector: + matchLabels: + app: backend + template: + metadata: + labels: + app: backend + spec: + containers: + - name: backend + # 여러분의 backend image 주소를 입력해주세요. + image: krmp-d2hub-idock.9rum.cc/dev-test/repo_bbaa5bcfc676 + env: + - name: TZ + value: Asia/Seoul + - name: DATABASE_URL + value: jdbc:mariadb://mariadb:3306/krampoline + resources: + requests: + memory: 1Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: backend +spec: + selector: + app: backend + ports: + - port: 8080 + targetPort: 8080 \ No newline at end of file diff --git a/k8s/configs/default.conf b/k8s/configs/default.conf new file mode 100644 index 00000000..6096ccae --- /dev/null +++ b/k8s/configs/default.conf @@ -0,0 +1,7 @@ +server { + listen 80; + + location / { + proxy_pass http://backend.default.svc.cluster.local:8080; + } +} \ No newline at end of file diff --git a/k8s/kustomization.yaml b/k8s/kustomization.yaml new file mode 100644 index 00000000..b9cf12bd --- /dev/null +++ b/k8s/kustomization.yaml @@ -0,0 +1,10 @@ +namespace: default +resources: + - nginx.yaml + - mariadb.yaml + - backend.yaml + - redis.yaml +configMapGenerator: + - name: nginx + files: + - configs/default.conf \ No newline at end of file diff --git a/k8s/mariadb.yaml b/k8s/mariadb.yaml new file mode 100644 index 00000000..865b06bb --- /dev/null +++ b/k8s/mariadb.yaml @@ -0,0 +1,59 @@ +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: mariadb +spec: + serviceName: mariadb + selector: + matchLabels: + app: mariadb + template: + metadata: + labels: + app: mariadb + spec: + containers: + - name: mariadb + # 여러분의 mariadb image 주소를 입력해주세요. + image: mariadb + env: + - name: TZ + value: Asia/Seoul + - name: MARIADB_ROOT_PASSWORD + value: root + - name: MARIADB_DATABASE + value: krampoline + - name: MARIADB_DISABLE_UPGRADE_BACKUP + value: '1' + volumeMounts: + - mountPath: /var/lib/mysql + name: data + subPath: mysql + resources: + limits: + memory: 1Gi + readinessProbe: + tcpSocket: + port: 3306 + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: mariadb +spec: + type: ClusterIP + clusterIP: None # Headless + selector: + app: mariadb + ports: + - port: 3306 \ No newline at end of file diff --git a/k8s/nginx.yaml b/k8s/nginx.yaml new file mode 100644 index 00000000..2155470a --- /dev/null +++ b/k8s/nginx.yaml @@ -0,0 +1,59 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:latest + ports: + - containerPort: 80 + volumeMounts: + - name: nginx-config + mountPath: /etc/nginx/conf.d + volumes: + - name: nginx-config + configMap: + name: nginx + +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx-service +spec: + type: LoadBalancer + selector: + app: nginx + ports: + - protocol: TCP + port: 80 + targetPort: 80 +--- +apiVersion: networking.k8s.io/v1beta1 +kind: Ingress +metadata: + annotations: + nginx.ingress.kubernetes.io/ssl-redirect: "false" + labels: + app.kubernetes.io/managed-by: kargocd + name: nginx +spec: + rules: + - http: + paths: + - backend: + serviceName: nginx-service + servicePort: 80 + path: / + pathType: Prefix \ No newline at end of file diff --git a/k8s/redis.yaml b/k8s/redis.yaml new file mode 100644 index 00000000..7a37f95f --- /dev/null +++ b/k8s/redis.yaml @@ -0,0 +1,33 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-deployment + labels: + app: redis +spec: + replicas: 1 + selector: + matchLabels: + app: redis + template: + metadata: + labels: + app: redis + spec: + containers: + - name: redis + image: redis:latest + ports: + - containerPort: 6379 +--- +apiVersion: v1 +kind: Service +metadata: + name: redis-service +spec: + selector: + app: redis + ports: + - port: 6379 + targetPort: 6379 \ No newline at end of file From 94ebe940405f35f61dc737a43c98d40abc816cb3 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 4 Nov 2023 16:04:12 +0900 Subject: [PATCH 079/144] =?UTF-8?q?Feat=20:=20=EB=B0=B0=ED=8F=AC=ED=99=98?= =?UTF-8?q?=EA=B2=BD,=20=ED=85=8C=EC=8A=A4=ED=8A=B8=ED=99=98=EA=B2=BD=20?= =?UTF-8?q?=EB=B3=84=EB=A1=9C=20yml=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 환경에 다른 yml 파일 적용되도록 설정하였습니다. --- .../src/main/resources/application-local.yml | 49 ++++++++++++++++++ .../src/main/resources/application-prod.yml | 48 +++++++++++++++++ wekiki/src/main/resources/application.yml | 51 ++----------------- 3 files changed, 100 insertions(+), 48 deletions(-) create mode 100644 wekiki/src/main/resources/application-local.yml create mode 100644 wekiki/src/main/resources/application-prod.yml diff --git a/wekiki/src/main/resources/application-local.yml b/wekiki/src/main/resources/application-local.yml new file mode 100644 index 00000000..0a93c565 --- /dev/null +++ b/wekiki/src/main/resources/application-local.yml @@ -0,0 +1,49 @@ +server: + servlet: + encoding: + charset: utf-8 + force: true + port: 8080 + +spring: + datasource: + url: jdbc:h2:mem:test;MODE=MariaDB + driver-class-name: org.h2.Driver + username: sa + password: + h2: + console: + enabled: true + jpa: + hibernate: + ddl-auto: create + show-sql: true + properties: + hibernate: + format_sql: true + default_batch_fetch_size: 100 + open-in-view: false + data: + storage-type: redis + redis: + host: localhost + port: 6379 + #password: + mail: + host: smtp.gmail.com + port: 587 + username: ljh19980823@gmail.com + password: yyzdbabwrmhhvyhi + properties: + mail: + smtp: + auth: true + starttls: + enable: true +jwt: + secret: 7ZmA656AIOuTneygkOyZlSDquLDsm5AgMeydvOywqALdlsKJL3234jklsdjfaKJDLnflkasdf + +logging: + level: + '[com.example.kakao]': DEBUG + '[org.hibernate.type]': TRACE diff --git a/wekiki/src/main/resources/application-prod.yml b/wekiki/src/main/resources/application-prod.yml new file mode 100644 index 00000000..421ba13f --- /dev/null +++ b/wekiki/src/main/resources/application-prod.yml @@ -0,0 +1,48 @@ +server: + servlet: + encoding: + charset: utf-8 + force: true + port: 8080 + +spring: + datasource: + url: ${DATABASE_URL}?allowPublicKeyRetrieval=true&useSSL=false + driver-class-name: org.mariadb.jdbc.Driver + username: root + password: root + h2: + console: + enabled: true + jpa: + hibernate: + ddl-auto: create + show-sql: true + properties: + hibernate: + format_sql: true + default_batch_fetch_size: 100 + open-in-view: false + data: + storage-type: redis + redis: + host: redis-service + port: 6379 + mail: + host: smtp.gmail.com + port: 587 + username: ljh19980823@gmail.com + password: yyzdbabwrmhhvyhi + properties: + mail: + smtp: + auth: true + starttls: + enable: true +jwt: + secret: 7ZmA656AIOuTneygkOyZlSDquLDsm5AgMeydvOywqALdlsKJL3234jklsdjfaKJDLnflkasdf + +logging: + level: + '[com.example.kakao]': DEBUG + '[org.hibernate.type]': TRACE \ No newline at end of file diff --git a/wekiki/src/main/resources/application.yml b/wekiki/src/main/resources/application.yml index 83c2d618..7fd2554e 100644 --- a/wekiki/src/main/resources/application.yml +++ b/wekiki/src/main/resources/application.yml @@ -1,49 +1,4 @@ -server: - servlet: - encoding: - charset: utf-8 - force: true - port: 8080 - spring: - datasource: - url: jdbc:h2:mem:test;MODE=MariaDB - driver-class-name: org.h2.Driver - username: sa - password: - h2: - console: - enabled: true - jpa: - hibernate: - ddl-auto: create - show-sql: true - properties: - hibernate: - format_sql: true - default_batch_fetch_size: 100 - open-in-view: false - data: - storage-type: redis - redis: - host: localhost - port: 6379 - password: zinc - mail: - host: smtp.gmail.com - port: 587 - username: ljh19980823@gmail.com - password: yyzdbabwrmhhvyhi - properties: - mail: - smtp: - auth: true - starttls: - enable: true -jwt: - secret: 7ZmA656AIOuTneygkOyZlSDquLDsm5AgMeydvOywqALdlsKJL3234jklsdjfaKJDLnflkasdf - -logging: - level: - '[com.example.kakao]': DEBUG - '[org.hibernate.type]': TRACE + profiles: + active: + - local \ No newline at end of file From 181d37827b9db6ba3b63dd9d8ed68c8e7b7841f7 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sat, 4 Nov 2023 16:10:23 +0900 Subject: [PATCH 080/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EB=82=B4=20=EB=8B=89=EB=84=A4=EC=9E=84=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=8B=9C=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 그룹 내 똑같은 닉네임 이미 있을 경우 예외 처리 --- .../wekiki/group/repository/GroupMemberJPARepository.java | 3 +++ .../kakao/techcampus/wekiki/group/service/GroupService.java | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java index 956243f6..8339b8bf 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java @@ -19,4 +19,7 @@ public interface GroupMemberJPARepository extends JpaRepository findActiveGroupMemberByMemberIdAndGroupId(@Param("memberId") Long memberId, @Param("groupId") Long groupId); + + @Query("SELECT gm FROM GroupMember gm WHERE gm.group.id = :groupId AND gm.nickName = :nickName") + Optional findGroupMemberByNickName(@Param("groupId") Long groupId, @Param("nickName") String nickName); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 8ceff8e1..d0bb9f00 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -230,6 +230,11 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ // 그룹 정보 확인 Group group = getGroupById(groupId); + // 그룹 내 닉네임 중복 예외 처리 + if(groupMemberJPARepository.findGroupMemberByNickName(groupId, requestDTO.nickName()).isPresent()) { + throw new Exception400("해당 닉네임은 이미 사용중입니다."); + } + // 이미 가입한 상태일 시 예외 처리 if (groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId).isPresent()) { throw new Exception400("이미 가입된 회원입니다."); From 85b45e330ad3aa7489bd33c851c283719f207661 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sat, 4 Nov 2023 16:13:21 +0900 Subject: [PATCH 081/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=8B=9C=20=EC=B4=88=EB=8C=80=EB=A7=81?= =?UTF-8?q?=ED=81=AC=20=EC=83=9D=EC=84=B1=20=ED=9B=84=20response=EC=97=90?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 그룹 생성 시 초대 링크 생성 후 반환 --- .../kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java | 6 +++--- .../kakao/techcampus/wekiki/group/service/GroupService.java | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java index b2c11cdd..8df58dfd 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java @@ -116,9 +116,9 @@ public GetGroupMembersResponseDTO(Group group) { } // 비공식 그룹 생성 - public record CreateUnOfficialGroupResponseDTO(Long groupId, String groupName, String groupImage) { - public CreateUnOfficialGroupResponseDTO(Group group) { - this(group.getId(), group.getGroupName(), group.getGroupProfileImage()); + public record CreateUnOfficialGroupResponseDTO(Long groupId, String groupName, String groupImage, String invitationLink) { + public CreateUnOfficialGroupResponseDTO(Group group, GetInvitationLinkResponseDTO groupInvitationCode) { + this(group.getId(), group.getGroupName(), group.getGroupProfileImage(), groupInvitationCode.invitationLink); } } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index d0bb9f00..1893281c 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -34,6 +34,8 @@ @Service public class GroupService { + private final InvitationService invitationService; + private final GroupJPARepository groupJPARepository; private final GroupMemberJPARepository groupMemberJPARepository; private final MemberJPARepository memberJPARepository; @@ -67,7 +69,7 @@ public GroupResponseDTO.CreateUnOfficialGroupResponseDTO createUnOfficialGroup(G groupMemberJPARepository.save(groupMember); // return - return new GroupResponseDTO.CreateUnOfficialGroupResponseDTO(group); + return new GroupResponseDTO.CreateUnOfficialGroupResponseDTO(group, invitationService.getGroupInvitationCode(group.getId())); } catch (Exception400 | Exception404 e) { throw e; From 72437fcdfbb080d3c79cf3a6723121b8c554d1e2 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sat, 4 Nov 2023 16:23:10 +0900 Subject: [PATCH 082/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20=EA=B7=B8?= =?UTF-8?q?=EB=A3=B9=20=EC=9C=A0=ED=98=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 그룹 상세 조회 시 response에 GroupType 추가 --- .../wekiki/group/dto/GroupResponseDTO.java | 16 ++++++++++++++-- .../wekiki/group/service/InvitationService.java | 6 +++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java index 8df58dfd..a4f2e550 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.group.dto; +import com.kakao.techcampus.wekiki.group.GroupType; import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.group.domain.Invitation; import com.kakao.techcampus.wekiki.group.domain.OfficialGroup; @@ -7,6 +8,7 @@ import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.history.History; +import jakarta.persistence.DiscriminatorValue; import org.springframework.data.domain.Page; import java.time.LocalDateTime; @@ -98,10 +100,20 @@ public record SearchGroupInfoDTO( String introduction, int memberCount, LocalDateTime created_at, - String entranceHint + String entranceHint, + String groupType ) { public SearchGroupInfoDTO(UnOfficialOpenedGroup group) { - this(group.getId(), group.getGroupName(), group.getGroupProfileImage(), group.getIntroduction(), group.getMemberCount(), group.getCreated_at(), group.getEntranceHint()); + this( + group.getId(), + group.getGroupName(), + group.getGroupProfileImage(), + group.getIntroduction(), + group.getMemberCount(), + group.getCreated_at(), + group.getEntranceHint(), + group.getClass().getAnnotation(DiscriminatorValue.class).value() + ); } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index de447193..e7489940 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -2,9 +2,9 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; -import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.group.dto.GroupResponseDTO; import com.kakao.techcampus.wekiki.group.domain.Invitation; +import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -19,7 +19,7 @@ public class InvitationService { private final RedisUtils redisUtils; - private final GroupService groupService; + private final GroupJPARepository groupJPARepository; private static final String GROUP_ID_PREFIX = "group_id:"; private static final String INVITATION_PREFIX = "invitation:"; @@ -32,7 +32,7 @@ public class InvitationService { */ public GroupResponseDTO.GetInvitationLinkResponseDTO getGroupInvitationCode(Long groupId) { - groupService.getGroupById(groupId); + groupJPARepository.findById(groupId).orElseThrow(() -> new Exception404("해당 그룹을 찾을 수 없습니다.")); String groupKey = GROUP_ID_PREFIX + groupId; From 6dbefca7f4b853802023a8d285bddaba73cc7e2e Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sat, 4 Nov 2023 18:01:49 +0900 Subject: [PATCH 083/144] =?UTF-8?q?Refactor:=20API=20=EB=AA=85=EC=84=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - API 명세 수정 요청에 의한 response 수정 --- .../group/controller/GroupRestController.java | 12 ++++---- .../wekiki/group/dto/GroupResponseDTO.java | 8 +++--- .../wekiki/group/service/GroupService.java | 28 +++++++++++++------ .../group/service/InvitationService.java | 5 +++- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java index b4d59391..c5ae4e04 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java @@ -57,10 +57,9 @@ public ResponseEntity searchGroup(@RequestParam(value = "keyword", required = */ @GetMapping("/search/officialGroup") public ResponseEntity searchOfficialGroup(@RequestParam(value = "keyword", required = false) String keyword, - @RequestParam(value = "page", defaultValue = "1") int page, - @RequestParam(value = "size", defaultValue = "10") int size) { + @RequestParam(value = "page", defaultValue = "1") int page) { - GroupResponseDTO.SearchOfficialGroupResponseDTO responseDTO = groupService.searchOfficialGroupByKeyword(keyword, page, size); + GroupResponseDTO.SearchOfficialGroupResponseDTO responseDTO = groupService.searchOfficialGroupByKeyword(keyword, page); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } @@ -70,10 +69,9 @@ public ResponseEntity searchOfficialGroup(@RequestParam(value = "keyword", re */ @GetMapping("/search/unOfficialGroup") public ResponseEntity searchUnOfficialGroup(@RequestParam(value = "keyword", required = false) String keyword, - @RequestParam(value = "page", defaultValue = "1") int page, - @RequestParam(value = "size", defaultValue = "10") int size) { + @RequestParam(value = "page", defaultValue = "1") int page) { - GroupResponseDTO.SearchUnOfficialGroupResponseDTO responseDTO = groupService.searchUnOfficialGroupByKeyword(keyword, page, size); + GroupResponseDTO.SearchUnOfficialGroupResponseDTO responseDTO = groupService.searchUnOfficialGroupByKeyword(keyword, page); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } @@ -195,7 +193,7 @@ public ResponseEntity myGroupHistoryPage(@PathVariable("groupId") Long groupI /* 그룹 탈퇴 */ - @DeleteMapping("/{groupId}/myInfo") + @DeleteMapping("/{groupId}") public ResponseEntity leaveGroup(@PathVariable("groupId") Long groupId) { groupService.leaveGroup(groupId, currentMember()); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java index a4f2e550..ba9ffebe 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java @@ -47,14 +47,14 @@ public MyGroupHistoryResponseDTO(Page histories) { } // 초대 링크 조회 - public record GetInvitationLinkResponseDTO(Long groupId, String invitationLink) { + public record GetInvitationLinkResponseDTO(Long groupId, String inviteCode) { public GetInvitationLinkResponseDTO(Long groupId, Invitation invitation) { this(groupId, invitation.code()); } } // 초대 링크를 통한 접근 - public record ValidateInvitationResponseDTO(Long groupId) { + public record ValidateInvitationResponseDTO(Long groupId, String groupName) { } // 그룹 검색 @@ -128,9 +128,9 @@ public GetGroupMembersResponseDTO(Group group) { } // 비공식 그룹 생성 - public record CreateUnOfficialGroupResponseDTO(Long groupId, String groupName, String groupImage, String invitationLink) { + public record CreateUnOfficialGroupResponseDTO(Long groupId, String groupName, String groupImage, String inviteCode) { public CreateUnOfficialGroupResponseDTO(Group group, GetInvitationLinkResponseDTO groupInvitationCode) { - this(group.getId(), group.getGroupName(), group.getGroupProfileImage(), groupInvitationCode.invitationLink); + this(group.getId(), group.getGroupName(), group.getGroupProfileImage(), groupInvitationCode.inviteCode); } } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 1893281c..50914d46 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -42,6 +42,8 @@ public class GroupService { private final PostJPARepository postJPARepository; private final HistoryJPARepository historyJPARepository; + private static final int GROUP_SEARCH_SIZE = 16; + /* 비공식 그룹 생성 */ @@ -124,7 +126,7 @@ protected ActiveGroupMember buildGroupMember(Member member, Group group, String */ public GroupResponseDTO.SearchGroupDTO searchGroupByKeyword(String keyword) { try { - Pageable pageable = PageRequest.of(0, 10); + Pageable pageable = PageRequest.of(0, GROUP_SEARCH_SIZE); // 공식 그룹 리스트 Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); @@ -141,9 +143,9 @@ public GroupResponseDTO.SearchGroupDTO searchGroupByKeyword(String keyword) { /* 공식 그룹 추가 리스트 */ - public GroupResponseDTO.SearchOfficialGroupResponseDTO searchOfficialGroupByKeyword(String keyword, int page, int size) { + public GroupResponseDTO.SearchOfficialGroupResponseDTO searchOfficialGroupByKeyword(String keyword, int page) { try { - Pageable pageable = PageRequest.of(page, size); + Pageable pageable = PageRequest.of(page, GROUP_SEARCH_SIZE); // 비공식 공개 그룹 리스트 Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); @@ -164,9 +166,9 @@ public GroupResponseDTO.SearchOfficialGroupResponseDTO searchOfficialGroupByKeyw /* 비공식 공개 그룹 추가 리스트 */ - public GroupResponseDTO.SearchUnOfficialGroupResponseDTO searchUnOfficialGroupByKeyword(String keyword, int page, int size) { + public GroupResponseDTO.SearchUnOfficialGroupResponseDTO searchUnOfficialGroupByKeyword(String keyword, int page) { try { - Pageable pageable = PageRequest.of(page, size); + Pageable pageable = PageRequest.of(page, GROUP_SEARCH_SIZE); // 비공식 공개 그룹 리스트 Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); @@ -233,9 +235,7 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ Group group = getGroupById(groupId); // 그룹 내 닉네임 중복 예외 처리 - if(groupMemberJPARepository.findGroupMemberByNickName(groupId, requestDTO.nickName()).isPresent()) { - throw new Exception400("해당 닉네임은 이미 사용중입니다."); - } + groupNickNameCheck(groupId, requestDTO.nickName()); // 이미 가입한 상태일 시 예외 처리 if (groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId).isPresent()) { @@ -340,15 +340,19 @@ public void updateMyGroupPage(Long groupId, Long memberId, GroupRequestDTO.Updat // 변경할 닉네임 확인 String newNickName = requestDTO.groupNickName(); - // 빈칸이거나 기존 닉네임과 같을 시 예외 처리 + // 빈칸일 경우 예외 처리 if(newNickName.isEmpty()) { throw new Exception400("공백은 닉네임이 될 수 없습니다."); } + // 기존 닉네임과 같은 경우 예외 처리 if(groupMember.getNickName().equals(newNickName)) { throw new Exception400("기존 닉네임과 같은 닉네임입니다."); } + // 이미 있는 경우 예외 처리 + groupNickNameCheck(groupId, requestDTO.groupNickName()); + // 그룹 닉네임 변경 groupMember.update(requestDTO.groupNickName()); @@ -403,4 +407,10 @@ protected Member getMemberById(Long memberId) { protected Group getGroupById(Long groupId) { return groupJPARepository.findById(groupId).orElseThrow(() -> new Exception404("해당 그룹을 찾을 수 없습니다.")); } + + protected void groupNickNameCheck(Long groupId, String groupNickName) { + if(groupMemberJPARepository.findGroupMemberByNickName(groupId, groupNickName).isPresent()) { + throw new Exception400("해당 닉네임은 이미 사용중입니다."); + } + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index e7489940..9538f3a3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -2,6 +2,7 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; +import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.group.dto.GroupResponseDTO; import com.kakao.techcampus.wekiki.group.domain.Invitation; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; @@ -69,7 +70,9 @@ public GroupResponseDTO.ValidateInvitationResponseDTO validateInvitation(String throw new Exception404("이미 만료된 초대 링크입니다."); } - return new GroupResponseDTO.ValidateInvitationResponseDTO(((Integer) groupId).longValue()); + Group group = groupJPARepository.getReferenceById((Long) groupId); + + return new GroupResponseDTO.ValidateInvitationResponseDTO(((Integer) groupId).longValue(), group.getGroupName()); } /* From e5ca93849c0262d501b36fe6e9ddd00d0ab3408d Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sat, 4 Nov 2023 18:27:49 +0900 Subject: [PATCH 084/144] =?UTF-8?q?Refactor:=20=EC=B4=88=EB=8C=80=20?= =?UTF-8?q?=EB=A7=81=ED=81=AC=EB=A5=BC=20=ED=86=B5=ED=95=9C=20=EC=A0=91?= =?UTF-8?q?=EA=B7=BC=20=EC=8B=9C=20responseDTO=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 초대 링크를 통한 접근 성공 시 groupName도 추가 반환 --- .../techcampus/wekiki/group/dto/GroupResponseDTO.java | 3 +++ .../techcampus/wekiki/group/service/InvitationService.java | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java index ba9ffebe..ac330542 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java @@ -55,6 +55,9 @@ public GetInvitationLinkResponseDTO(Long groupId, Invitation invitation) { // 초대 링크를 통한 접근 public record ValidateInvitationResponseDTO(Long groupId, String groupName) { + public ValidateInvitationResponseDTO(Group group) { + this(group.getId(), group.getGroupName()); + } } // 그룹 검색 diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index 9538f3a3..8b66fa40 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.group.service; +import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; import com.kakao.techcampus.wekiki.group.domain.Group; @@ -70,9 +71,11 @@ public GroupResponseDTO.ValidateInvitationResponseDTO validateInvitation(String throw new Exception404("이미 만료된 초대 링크입니다."); } - Group group = groupJPARepository.getReferenceById((Long) groupId); + Group group = groupJPARepository.findById(((Integer) groupId).longValue()).orElseThrow( + () -> new Exception400("해당 그룹은 존재하지 않습니다.") + ); - return new GroupResponseDTO.ValidateInvitationResponseDTO(((Integer) groupId).longValue(), group.getGroupName()); + return new GroupResponseDTO.ValidateInvitationResponseDTO(group); } /* From 265857d4dfec8dea57a61dff6485428a344e96a7 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Sat, 4 Nov 2023 20:29:38 +0900 Subject: [PATCH 085/144] =?UTF-8?q?setting=20:=20yml=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 배포 yml이랑 로컬 yml 수정하였습니다. --- .../src/main/resources/application-local.yml | 6 +++ .../src/main/resources/application-prod.yml | 6 +++ wekiki/src/main/resources/application.yml | 45 ------------------- 3 files changed, 12 insertions(+), 45 deletions(-) diff --git a/wekiki/src/main/resources/application-local.yml b/wekiki/src/main/resources/application-local.yml index 0a93c565..893966d2 100644 --- a/wekiki/src/main/resources/application-local.yml +++ b/wekiki/src/main/resources/application-local.yml @@ -43,6 +43,12 @@ spring: jwt: secret: 7ZmA656AIOuTneygkOyZlSDquLDsm5AgMeydvOywqALdlsKJL3234jklsdjfaKJDLnflkasdf +kakao: + client: + id: 08e6c709229f3b44a8cff2fc7168e1a2 + redirect: + uri: http://localhost:8080/auth/kakao/signin + logging: level: '[com.example.kakao]': DEBUG diff --git a/wekiki/src/main/resources/application-prod.yml b/wekiki/src/main/resources/application-prod.yml index 421ba13f..1862bfb3 100644 --- a/wekiki/src/main/resources/application-prod.yml +++ b/wekiki/src/main/resources/application-prod.yml @@ -42,6 +42,12 @@ spring: jwt: secret: 7ZmA656AIOuTneygkOyZlSDquLDsm5AgMeydvOywqALdlsKJL3234jklsdjfaKJDLnflkasdf +kakao: + client: + id: 08e6c709229f3b44a8cff2fc7168e1a2 + redirect: + uri: ${SERVER_URL}/auth/kakao/signin + logging: level: '[com.example.kakao]': DEBUG diff --git a/wekiki/src/main/resources/application.yml b/wekiki/src/main/resources/application.yml index c4f3ccac..7fd2554e 100644 --- a/wekiki/src/main/resources/application.yml +++ b/wekiki/src/main/resources/application.yml @@ -1,49 +1,4 @@ spring: - datasource: - url: jdbc:h2:mem:test;MODE=MariaDB - driver-class-name: org.h2.Driver - username: sa - password: - h2: - console: - enabled: true - jpa: - hibernate: - ddl-auto: create - show-sql: true - properties: - hibernate: - format_sql: true - default_batch_fetch_size: 100 - open-in-view: false - data: - storage-type: redis - redis: - host: localhost - port: 6379 - password: zinc - mail: - host: smtp.gmail.com - port: 587 - username: ljh19980823@gmail.com - password: yyzdbabwrmhhvyhi - properties: - mail: - smtp: - auth: true - starttls: - enable: true -jwt: - secret: 7ZmA656AIOuTneygkOyZlSDquLDsm5AgMeydvOywqALdlsKJL3234jklsdjfaKJDLnflkasdf -kakao: - client: - id: 08e6c709229f3b44a8cff2fc7168e1a2 - redirect: - uri: http://3.39.150.229:8080/auth/kakao/signin -logging: - level: - '[com.example.kakao]': DEBUG - '[org.hibernate.type]': TRACE profiles: active: - local \ No newline at end of file From aca16ed25838439380db28b75967a2bdfec8d774 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sat, 4 Nov 2023 23:23:27 +0900 Subject: [PATCH 086/144] =?UTF-8?q?Refactor:=20=EB=82=B4=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=20=EA=B8=B0=EC=97=AC=20=EB=AA=A9=EB=A1=9D=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5DTO=201=EC=B0=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 인덱스 가져오는 부분 빼고 API 명세 수정에 따른 responseDTO 수정 --- .../wekiki/group/dto/GroupResponseDTO.java | 24 +++++++++++++++---- .../techcampus/wekiki/page/PageInfo.java | 2 -- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java index ac330542..16b344db 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java @@ -16,13 +16,13 @@ import java.util.stream.Collectors; public class GroupResponseDTO { - + // 그룹 내 본인 정보 조회 public record MyGroupInfoResponseDTO( Long groupId, String groupName, String groupNickName, - List myHistoryDTOS + List historyList ) { public MyGroupInfoResponseDTO(Group group, GroupMember groupMember, Page histories) { this(group.getId(), group.getGroupName(), groupMember.getNickName(), histories.stream().map(MyHistoryDTO::new).collect(Collectors.toList())); @@ -30,15 +30,29 @@ public MyGroupInfoResponseDTO(Group group, GroupMember groupMember, Page historyList) { public MyGroupHistoryResponseDTO(Page histories) { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java index be6db9cb..52a93fb5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java @@ -61,6 +61,4 @@ public void addPost(Post post){ this.posts.add(post); post.setPageInfo(this); } - - } From ce09562fdd438d48318176de3ebce2e3ea5561c5 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Tue, 7 Nov 2023 12:23:56 +0900 Subject: [PATCH 087/144] =?UTF-8?q?feat=20:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=EC=8B=9C=20response=EC=97=90=20isMine?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 댓글 조회시에 response에 isMine으로 본인 댓글인지 아닌지를 Boolean으로 추가해주었습니다. --- .../com/kakao/techcampus/wekiki/comment/CommentResponse.java | 4 +++- .../com/kakao/techcampus/wekiki/comment/CommentService.java | 2 +- .../com/kakao/techcampus/wekiki/post/PostRestController.java | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java index 67025151..23bac93d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java @@ -43,13 +43,15 @@ public getCommentDTO(Post post, List comments){ public static class commentDTO{ Long commentId; String nickName; + boolean isMine; int memberLevel; String content; LocalDateTime createdAt; - public commentDTO(Comment comment , GroupMember groupMember){ + public commentDTO(Comment comment , GroupMember groupMember, boolean isMine){ this.commentId = comment.getId(); this.nickName = groupMember.getNickName(); + this.isMine = isMine; this.memberLevel = groupMember.getMemberLevel(); this.content = comment.getContent(); this.createdAt = comment.getCreated_at(); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java index 9e8a2e11..3981e2ee 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java @@ -54,7 +54,7 @@ public CommentResponse.getCommentDTO getComment(Long memberId, Long groupId, Lon // 6. return DTO List commentDTOs = comments.getContent() - .stream().map(c -> new CommentResponse.getCommentDTO.commentDTO(c , c.getGroupMember())) + .stream().map(c -> new CommentResponse.getCommentDTO.commentDTO(c,c.getGroupMember(), c.getGroupMember().getId() == groupMember.getId())) .collect(Collectors.toList()); return new CommentResponse.getCommentDTO(post,commentDTOs); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java index 9d267b05..3c3ed935 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostRestController.java @@ -19,7 +19,6 @@ public class PostRestController { private final PostService postService; - private final ReportJPARepository reportJPARepository; @PostMapping("/create") public ResponseEntity> createPost(@PathVariable Long groupid, @RequestBody PostRequest.createPostDTO request) { From 6718b8a126e781e1a609633b4044b9564c3e2e78 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Tue, 7 Nov 2023 13:29:53 +0900 Subject: [PATCH 088/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=EC=8B=9C=20=EC=A1=B0=EA=B1=B4=20=EC=B6=A9?= =?UTF-8?q?=EC=A1=B1=20=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 그룹 가입 시 해당 권한이 있는지 확인 - 비공개 그룹 : 초대 링크에서 획득 - 공개 그룹 : 비밀번호 확인, 혹은 초대 링크에서 획득 --- .../group/controller/GroupRestController.java | 4 +- .../wekiki/group/service/GroupService.java | 79 +++++++++++++------ .../group/service/InvitationService.java | 11 ++- 3 files changed, 66 insertions(+), 28 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java index c5ae4e04..c218b5a8 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/controller/GroupRestController.java @@ -93,7 +93,7 @@ public ResponseEntity searchGroupInfo(@PathVariable("groupId") Long groupId) @PostMapping("/{groupId}/entry") public ResponseEntity groupEntry(@PathVariable("groupId") Long groupId, @RequestBody GroupRequestDTO.GroupEntryRequestDTO requestDTO) { - groupService.groupEntry(groupId, requestDTO); + groupService.groupEntry(groupId, currentMember(), requestDTO); return ResponseEntity.ok().body(ApiUtils.success(null)); } @@ -131,7 +131,7 @@ public ResponseEntity getInvitationLink(@PathVariable("groupId") Long groupId @GetMapping("/invitation/{invitationLink}") public ResponseEntity ValidateInvitation(@PathVariable String invitationLink) { - GroupResponseDTO.ValidateInvitationResponseDTO responseDTO = invitationService.validateInvitation(invitationLink); + GroupResponseDTO.ValidateInvitationResponseDTO responseDTO = invitationService.validateInvitation(invitationLink, currentMember()); return ResponseEntity.ok().body(ApiUtils.success(responseDTO)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 50914d46..2b06d41d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -3,6 +3,7 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.error.exception.Exception500; +import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.group.dto.GroupRequestDTO; import com.kakao.techcampus.wekiki.group.dto.GroupResponseDTO; @@ -26,14 +27,18 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.Duration; import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; @Transactional(readOnly = true) @RequiredArgsConstructor @Service public class GroupService { + private final RedisUtils redisUtils; + private final InvitationService invitationService; private final GroupJPARepository groupJPARepository; @@ -43,6 +48,8 @@ public class GroupService { private final HistoryJPARepository historyJPARepository; private static final int GROUP_SEARCH_SIZE = 16; + private static final String MEMBER_ID_PREFIX = "member_id:"; + private static final long MEMBER_ID_LIFETIME = 3L; /* 비공식 그룹 생성 @@ -206,7 +213,7 @@ public GroupResponseDTO.SearchGroupInfoDTO getGroupInfo(Long groupId) { /* 비공식 공개 그룹 입장 */ - public void groupEntry(Long groupId, GroupRequestDTO.GroupEntryRequestDTO requestDTO) { + public void groupEntry(Long groupId, Long memberId, GroupRequestDTO.GroupEntryRequestDTO requestDTO) { try { UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId) .orElseThrow(() -> new Exception404("그룹을 찾을 수 없습니다.")); @@ -216,6 +223,8 @@ public void groupEntry(Long groupId, GroupRequestDTO.GroupEntryRequestDTO reques throw new Exception400("비밀번호가 틀렸습니다."); } + redisUtils.setGroupIdValues(MEMBER_ID_PREFIX + memberId, groupId, Duration.ofHours(MEMBER_ID_LIFETIME)); + } catch (Exception400 | Exception404 e) { throw e; } catch (Exception e) { @@ -228,38 +237,60 @@ public void groupEntry(Long groupId, GroupRequestDTO.GroupEntryRequestDTO reques */ @Transactional public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequestDTO requestDTO) { - // 회원 정보 확인 - Member member = getMemberById(memberId); + try { + // 회원 정보 확인 + Member member = getMemberById(memberId); - // 그룹 정보 확인 - Group group = getGroupById(groupId); + // 그룹 정보 확인 + Group group = getGroupById(groupId); - // 그룹 내 닉네임 중복 예외 처리 - groupNickNameCheck(groupId, requestDTO.nickName()); + checkJoinPermission(memberId, groupId); - // 이미 가입한 상태일 시 예외 처리 - if (groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId).isPresent()) { - throw new Exception400("이미 가입된 회원입니다."); - } + // 그룹 내 닉네임 중복 예외 처리 + groupNickNameCheck(groupId, requestDTO.nickName()); - // 재가입 회원인지 확인 - InactiveGroupMember wasGroupMember = groupMemberJPARepository.findInactiveGroupMemberByMemberAndGroup(member, group); + // 이미 가입한 상태일 시 예외 처리 + if (groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId).isPresent()) { + throw new Exception400("이미 가입된 회원입니다."); + } - // 재가입 회원이면 활성화, 신규 회원이면 새로 생성 - ActiveGroupMember groupMember = wasGroupMember != null ? new ActiveGroupMember(wasGroupMember) : buildGroupMember(member, group, requestDTO.nickName()); + // 재가입 회원인지 확인 + InactiveGroupMember wasGroupMember = groupMemberJPARepository.findInactiveGroupMemberByMemberAndGroup(member, group); + + // 재가입 회원이면 활성화, 신규 회원이면 새로 생성 + ActiveGroupMember groupMember = wasGroupMember != null ? new ActiveGroupMember(wasGroupMember) : buildGroupMember(member, group, requestDTO.nickName()); + + // 그룹 멤버 잔재 삭제 + if(wasGroupMember != null) { + groupMemberJPARepository.delete(wasGroupMember); + } + + // GroupMember 저장 + group.addGroupMember(groupMember); + member.getGroupMembers().add(groupMember); - // 그룹 멤버 잔재 삭제 - if(wasGroupMember != null) { - groupMemberJPARepository.delete(wasGroupMember); + groupJPARepository.save(group); + memberJPARepository.save(member); + groupMemberJPARepository.save(groupMember); + + } catch (Exception400 | Exception404 e) { + throw e; + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); } + } - // GroupMember 저장 - group.addGroupMember(groupMember); - member.getGroupMembers().add(groupMember); + protected void checkJoinPermission(Long memberId, Long groupId) { + Object oGroupId = Optional.ofNullable(redisUtils.getValues(MEMBER_ID_PREFIX + memberId)) + .orElseThrow(() -> new Exception404("해당 그룹에 가입할 수 없습니다.")); + + Long lGroupId = ((Integer) oGroupId).longValue(); + + if(!lGroupId.equals(groupId)) { + throw new Exception400("현재 그룹에 가입할 수 없습니다."); + } - groupJPARepository.save(group); - memberJPARepository.save(member); - groupMemberJPARepository.save(groupMember); + redisUtils.deleteValues(MEMBER_ID_PREFIX + memberId); } /* diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index 8b66fa40..58325e51 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -11,6 +11,7 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import java.time.Duration; import java.time.LocalDateTime; import java.util.Optional; import java.util.Set; @@ -25,6 +26,8 @@ public class InvitationService { private static final String GROUP_ID_PREFIX = "group_id:"; private static final String INVITATION_PREFIX = "invitation:"; + private static final String MEMBER_ID_PREFIX = "member_id:"; + private static final long MEMBER_ID_LIFETIME = 3L; /* InvitationCode 확인 @@ -57,7 +60,7 @@ public GroupResponseDTO.GetInvitationLinkResponseDTO getGroupInvitationCode(Long } // 초대 링크를 통한 접근 시 유효한 초대 링크 확인, 해당 그룹으로 연결 - public GroupResponseDTO.ValidateInvitationResponseDTO validateInvitation(String invitationLink) { + public GroupResponseDTO.ValidateInvitationResponseDTO validateInvitation(String invitationLink, Long memberId) { // 초대 링크를 통해 groupId와 invitation 찾기 // groupId는 현재 Integer 타입 @@ -71,10 +74,14 @@ public GroupResponseDTO.ValidateInvitationResponseDTO validateInvitation(String throw new Exception404("이미 만료된 초대 링크입니다."); } - Group group = groupJPARepository.findById(((Integer) groupId).longValue()).orElseThrow( + Long lGroupId = ((Integer) groupId).longValue(); + + Group group = groupJPARepository.findById(lGroupId).orElseThrow( () -> new Exception400("해당 그룹은 존재하지 않습니다.") ); + redisUtils.setGroupIdValues(MEMBER_ID_PREFIX + memberId, lGroupId, Duration.ofHours(MEMBER_ID_LIFETIME)); + return new GroupResponseDTO.ValidateInvitationResponseDTO(group); } From 665be1eca6f46c3d4080e629b36a5cf1cd42411a Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Tue, 7 Nov 2023 13:52:53 +0900 Subject: [PATCH 089/144] =?UTF-8?q?Refactor=20:=20Page=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20API=EC=9D=98=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20?= =?UTF-8?q?=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 유효한 그룹,멤버,그룹멤버를 확인하는 과정에서 fetch join을 토해 하나의 쿼리로 해결하였습니다. - 페이지 링크 거는 부분은 데이터베이스 접근 자체를 아예 삭제하였습니다. --- .../repository/GroupMemberJPARepository.java | 5 + .../wekiki/page/PageRestController.java | 2 +- .../techcampus/wekiki/page/PageService.java | 216 +++++------------- 3 files changed, 69 insertions(+), 154 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java index 8339b8bf..fb7c63d5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java @@ -22,4 +22,9 @@ public interface GroupMemberJPARepository extends JpaRepository findGroupMemberByNickName(@Param("groupId") Long groupId, @Param("nickName") String nickName); + + // 여기다 멤버 group fetchjoin + @Query("SELECT agm FROM ActiveGroupMember agm LEFT JOIN FETCH agm.member LEFT JOIN FETCH agm.group WHERE agm.member.id = :memberId AND agm.group.id = :groupId") + Optional findActiveGroupMemberByMemberIdAndGroupIdFetchJoin(@Param("memberId") Long memberId, @Param("groupId") Long groupId); + } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java index a99031f3..f619ba78 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageRestController.java @@ -149,7 +149,7 @@ public ResponseEntity> get @GetMapping("/link") public ResponseEntity> getPageLink(@PathVariable Long groupid, @RequestParam(value = "title") String title){ - PageInfoResponse.getPageLinkDTO response = pageService.getPageLink(currentMember(), groupid, title); + PageInfoResponse.getPageLinkDTO response = pageService.getPageLink(groupid, title); return ResponseEntity.ok(ApiUtils.success(response)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 17bf75d9..c0d90323 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -11,7 +11,6 @@ import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.member.Member; import com.kakao.techcampus.wekiki.member.MemberJPARepository; -import com.kakao.techcampus.wekiki.member.MemberResponse; import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; @@ -46,6 +45,7 @@ public class PageService { private final RedisUtility redisUtility; final int PAGE_COUNT = 10; + final int RECENTLY_PAGE_COUNT = 10; @Transactional public PageInfoResponse.mainPageDTO getMainPage() { if(SecurityContextHolder.getContext().getAuthentication().getName().equals("anonymousUser")) { @@ -88,27 +88,17 @@ public PageInfoResponse.mainPageDTO getMainPage() { @Transactional public PageInfoResponse.getPageIndexDTO getPageIndex(Long groupId,Long memberId, Long pageId){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); - - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 checkGroupMember(memberId, groupId); - // 4. pageId로 PageInfo 객체 들고오기 - PageInfo pageInfo = pageJPARepository.findByPageIdWithPosts(pageId) - .orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); - - // 5. 해당 groupId를 들고 있는 모든 페이지 Order 순으로 들고오기 - List posts = pageInfo.getPosts(); + // 2. pageId로 PageInfo + Post 객체 fetch join으로 한번에 들고오기 + PageInfo pageInfo = getPageAndPostFromPageId(pageId); - // 6. 목차 생성하기 - HashMap indexs = indexUtils.createIndex(posts); + // 3. 목차 생성하기 + HashMap indexs = indexUtils.createIndex(pageInfo.getPosts()); - // 7. DTO로 return - List temp = posts.stream() + // 4. DTO로 return + List temp = pageInfo.getPosts().stream() .map(p -> new PageInfoResponse.getPageIndexDTO.postDTO(p, indexs.get(p.getId()))) .collect(Collectors.toList()); @@ -119,31 +109,25 @@ public PageInfoResponse.getPageIndexDTO getPageIndex(Long groupId,Long memberId, @Transactional public PageInfoResponse.deletePageDTO deletePage(Long memberId, Long groupId, Long pageId){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); - - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 checkGroupMember(memberId, groupId); - // 4. 존재하는 페이지 인지 체크 + // 2. 존재하는 페이지 인지 체크 PageInfo pageInfo = checkPageFromPageId(pageId); - // 5. pageId로 하위 post들이 존재하는지 확인 -> 존재하면 Exception + // 3. pageId로 하위 post들이 존재하는지 확인 -> 존재하면 Exception if(postJPARepository.existsByPageInfoId(pageId)){ throw new Exception400("글이 적혀있는 페이지는 삭제가 불가능합니다."); } - // 6. 포스트가 하나도 없으면 삭제시키기 + // 4. 포스트가 하나도 없으면 삭제시키기 PageInfoResponse.deletePageDTO response = new PageInfoResponse.deletePageDTO(pageInfo); pageJPARepository.deleteById(pageId); - // 7. redis에 페이지 목록 삭제 시켜주기 + // 5. redis에 페이지 목록 삭제 시켜주기 redisUtility.deleteValues(groupId+"_"+pageInfo.getPageName()); - // 8. return DTO + // 6. return DTO return response; } @@ -151,27 +135,17 @@ public PageInfoResponse.deletePageDTO deletePage(Long memberId, Long groupId, Lo @Transactional public PageInfoResponse.getPageFromIdDTO getPageFromId(Long memberId,Long groupId, Long pageId){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); - - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 checkGroupMember(memberId, groupId); - // 4. pageId로 PageInfo 객체 들고오기 - PageInfo pageInfo = pageJPARepository.findByPageIdWithPosts(pageId) - .orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); - - // 5. 해당 groupId를 들고 있는 모든 페이지 Order 순으로 들고오기 - List posts = pageInfo.getPosts(); + // 2. pageId로 PageInfo + Post 객체 fetch join으로 한번에 들고오기 + PageInfo pageInfo = getPageAndPostFromPageId(pageId); - // 6. 목차 생성하기 - HashMap indexs = indexUtils.createIndex(posts); + // 3. 목차 생성하기 + HashMap indexs = indexUtils.createIndex(pageInfo.getPosts()); - // 7. DTO로 return - List temp = posts.stream() + // 4. DTO로 return + List temp = pageInfo.getPosts().stream() .map(p -> new PageInfoResponse.getPageFromIdDTO.postDTO(p, indexs.get(p.getId()))) .collect(Collectors.toList()); @@ -182,23 +156,17 @@ public PageInfoResponse.getPageFromIdDTO getPageFromId(Long memberId,Long groupI @Transactional public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Long memberId){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); - // 2. 존재하는 group인지 확인하기 - Group group = checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) - checkGroupMember(memberId, groupId); - - // 4. 그룹 내 동일한 title의 Page가 존재하는지 체크 + // 2. 그룹 내 동일한 title의 Page가 존재하는지 체크 if(pageJPARepository.findByTitle(groupId,title).isPresent()){ throw new Exception400("이미 존재하는 페이지입니다."); } - // 5. Page 생성 + // 3. Page 생성 PageInfo newPageInfo = PageInfo.builder() - .group(group) + .group(activeGroupMember.getGroup()) .pageName(title) .goodCount(0) .badCount(0) @@ -221,24 +189,18 @@ public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Lon @Transactional public PageInfoResponse.likePageDTO likePage(Long pageId , Long groupId, Long memberId){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); - - // 2. 존재하는 group인지 확인하기 - Group group = checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 checkGroupMember(memberId, groupId); - // 4. 존재하는 페이지 인지 체크 + // 2. 존재하는 페이지 인지 체크 PageInfo pageInfo = checkPageFromPageId(pageId); - // 5. 페이지 goodCount 증가 + // 3. 페이지 goodCount 증가 pageInfo.plusGoodCount(); - // TODO : 6. 유저 경험치증가 or 유저 당일 페이지 좋아요 횟수 차감 + // TODO : 유저 경험치증가 or 유저 당일 페이지 좋아요 횟수 차감 - // 7. return DTO + // 4. return DTO return new PageInfoResponse.likePageDTO(pageInfo); } @@ -246,44 +208,32 @@ public PageInfoResponse.likePageDTO likePage(Long pageId , Long groupId, Long me @Transactional public PageInfoResponse.hatePageDTO hatePage(Long pageId , Long groupId, Long memberId){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); - - // 2. 존재하는 group인지 확인하기 - Group group = checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 checkGroupMember(memberId, groupId); - // 4. 존재하는 페이지 인지 체크 + // 2. 존재하는 페이지 인지 체크 PageInfo pageInfo = checkPageFromPageId(pageId); - // 5. 페이지 goodCount 증가 + // 3. 페이지 goodCount 증가 pageInfo.plusBadCount(); - // TODO : 6. 유저 경험치증가 or 유저 당일 페이지 좋아요 횟수 차감 + // TODO : 유저 경험치증가 or 유저 당일 페이지 좋아요 횟수 차감 - // 7. return DTO + // 4. return DTO return new PageInfoResponse.hatePageDTO(pageInfo); } @Transactional public PageInfoResponse.searchPageDTO searchPage(Long groupId, Long memberId, int pageNo, String keyword){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); - - // 2. 존재하는 group인지 확인하기 - Group group = checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 checkGroupMember(memberId, groupId); - // 4. keyword로 존재하는 page title에 keyword를 가지고 있는 페이지들 다 가져오기 + // 2. keyword로 존재하는 page title에 keyword를 가지고 있는 페이지들 다 가져오기 // (TODO : fetch join이랑 Pagination 함께 쓰면 페이지네이션을 애플리케이션에 들고온 다음 하게됨) Page pages = pageJPARepository.findPagesWithPosts(groupId, keyword, PageRequest.of(pageNo, PAGE_COUNT)); - // 5. 해당 Page들을 FK로 가지고 있는 Post들 중에 Orders가 1인 Post들 가져오기 + // 3. 해당 Page들을 FK로 가지고 있는 Post들 중에 Orders가 1인 Post들 가져오기 List res = new ArrayList<>(); for(PageInfo p : pages.getContent()){ @@ -302,20 +252,13 @@ public PageInfoResponse.searchPageDTO searchPage(Long groupId, Long memberId, in @Transactional public PageInfoResponse.getRecentPageDTO getRecentPage(Long memberId , Long groupId){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); - - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 checkGroupMember(memberId, groupId); - // 4. 특정 groupId를 가진 Page들 order by로 updated_at이 최신인 10개 Page 조회 - Pageable pageable = PageRequest.of(0, 10); - List recentPage = pageJPARepository.findByGroupIdOrderByUpdatedAtDesc(groupId, pageable); + // 2. 특정 groupId를 가진 Page들 order by로 updated_at이 최신인 10개 Page 조회 + List recentPage = pageJPARepository.findByGroupIdOrderByUpdatedAtDesc(groupId, PageRequest.of(0, RECENTLY_PAGE_COUNT)); - // 5. return DTO + // 3. return DTO List collect = recentPage.stream().map(pageInfo -> new PageInfoResponse.getRecentPageDTO.RecentPageDTO(pageInfo)).collect(Collectors.toList()); return new PageInfoResponse.getRecentPageDTO(collect); @@ -325,27 +268,18 @@ public PageInfoResponse.getRecentPageDTO getRecentPage(Long memberId , Long grou @Transactional public PageInfoResponse.getPageFromIdDTO getPageFromTitle(Long memberId, Long groupId, String title){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); - - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 checkGroupMember(memberId, groupId); - // 4. groupId랑 title로 Page있는지 확인 (fetch join으로 post들 가져오기) + // 2. groupId랑 title로 Page있는지 확인 (fetch join으로 post들 가져오기) PageInfo page = pageJPARepository.findByTitleWithPosts(groupId,title). orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); - // 5. 해당 pageId를 들고있는 모든 페이지 Order 순으로 들고오기 - List posts = page.getPosts(); + // 2. 목차 생성하기 + HashMap indexs = indexUtils.createIndex(page.getPosts()); - // 6. 목차 생성하기 - HashMap indexs = indexUtils.createIndex(posts); - - // 7. DTO로 return - List temp = posts.stream() + // 3. DTO로 return + List temp = page.getPosts().stream() .map(p -> new PageInfoResponse.getPageFromIdDTO.postDTO(p, indexs.get(p.getId()))) .collect(Collectors.toList()); @@ -353,61 +287,37 @@ public PageInfoResponse.getPageFromIdDTO getPageFromTitle(Long memberId, Long gr } @Transactional - public PageInfoResponse.getPageLinkDTO getPageLink(Long memberId, Long groupId, String title){ - - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); + public PageInfoResponse.getPageLinkDTO getPageLink( Long groupId, String title){ - // 2. 존재하는 group인지 확인하기 - Group group = checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) - checkGroupMember(memberId, groupId); - - // 4. redis로 groupId_title을 key로 value 받아오기 (페이지 테이블에 접근할 필요 x) + // 1. redis로 groupId_title을 key로 value 받아오기 (페이지 테이블에 접근할 필요 x) String value = redisUtility.getValues(groupId+"_"+title); + if(value == null){ throw new Exception404("존재하지 않는 페이지 입니다."); }else{ - // 5. return DTO + // 2. return DTO return new PageInfoResponse.getPageLinkDTO(Long.valueOf(value)); } - - // 4. groupId랑 title로 Page있는지 확인 - where 문에 groupId 추가 - // PageInfo page = pageJPARepository.findByTitle(title). - // orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); - - // 5. return DTO - //return new PageInfoResponse.getPageLinkDTO(page); } - public Member checkMemberFromMemberId(Long memberId){ - return memberJPARepository.findById(memberId) - .orElseThrow(()-> new Exception404("존재하지 않는 회원입니다.")); - } - - public Group checkGroupFromGroupId(Long groupId){ - return groupJPARepository.findById(groupId) - .orElseThrow(()-> new Exception404("존재하지 않는 그룹입니다.")); - } - public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ - /* - TODO : groupMember 들고올때 fetch join으로 member랑 group도 들고오기 - 여기서 - if(activeGroupMember.getMember() != null) throw new Exception404("존재하지 않는 회원입니다."); - if(activeGroupMember.getGroup() != null) throw new Exception404("존재하지 않는 그룹입니다."); - 체크 추가해주기 - */ - - return groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId,groupId) + ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); + if(activeGroupMember.getMember() == null) throw new Exception404("존재하지 않는 회원입니다."); + if(activeGroupMember.getGroup() == null) throw new Exception404("존재하지 않는 그룹입니다."); + + return activeGroupMember; } public PageInfo checkPageFromPageId(Long pageId){ return pageJPARepository.findById(pageId) .orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); } + + public PageInfo getPageAndPostFromPageId(Long pageId){ + return pageJPARepository.findByPageIdWithPosts(pageId) + .orElseThrow(() -> new Exception404("존재하지 않는 페이지 입니다.")); + } } From d9ea0ccc14fa183b3b4f83c6b384b4e839da39e1 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Tue, 7 Nov 2023 14:06:13 +0900 Subject: [PATCH 090/144] =?UTF-8?q?Fix:=20=EA=B7=B8=EB=A3=B9=20=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EC=8B=9C=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 그룹 탈퇴 시 오류 해결 --- .../techcampus/wekiki/comment/Comment.java | 4 ++++ .../wekiki/comment/CommentJPARepository.java | 5 +++-- .../wekiki/group/service/GroupService.java | 18 ++++++++++++++++++ .../techcampus/wekiki/history/History.java | 2 -- .../kakao/techcampus/wekiki/report/Report.java | 3 +++ .../wekiki/report/ReportJPARepository.java | 5 ++++- 6 files changed, 32 insertions(+), 5 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java index 07000245..78b0a3f0 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java @@ -39,4 +39,8 @@ public Comment(Long id, GroupMember groupMember, Post post, String content, Loca public void updateContent(String newContent){ this.content = newContent; } + + public void updateGroupMember(GroupMember groupMember) { + this.groupMember = groupMember; + } } \ No newline at end of file diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java index 5ae9c1ef..722f6e6e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.comment; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.post.Post; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -8,6 +9,7 @@ import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.util.List; import java.util.Optional; @Repository @@ -19,6 +21,5 @@ public interface CommentJPARepository extends JpaRepository { @Query("SELECT c FROM Comment c LEFT JOIN FETCH c.groupMember WHERE c.id = :commentId") Optional findCommentWithGroupMember(@Param("commentId") Long commentId); - - + List findAllByGroupMember(ActiveGroupMember activeGroupMember); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 2b06d41d..69d3777a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -4,6 +4,8 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.error.exception.Exception500; import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; +import com.kakao.techcampus.wekiki.comment.Comment; +import com.kakao.techcampus.wekiki.comment.CommentJPARepository; import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.group.dto.GroupRequestDTO; import com.kakao.techcampus.wekiki.group.dto.GroupResponseDTO; @@ -20,6 +22,8 @@ import com.kakao.techcampus.wekiki.member.MemberJPARepository; import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; +import com.kakao.techcampus.wekiki.report.Report; +import com.kakao.techcampus.wekiki.report.ReportJPARepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -46,6 +50,8 @@ public class GroupService { private final MemberJPARepository memberJPARepository; private final PostJPARepository postJPARepository; private final HistoryJPARepository historyJPARepository; + private final CommentJPARepository commentJPARepository; + private final ReportJPARepository reportJPARepository; private static final int GROUP_SEARCH_SIZE = 16; private static final String MEMBER_ID_PREFIX = "member_id:"; @@ -419,10 +425,22 @@ public void leaveGroup(Long groupId, Long memberId) { List historyList = historyJPARepository.findAllByGroupMember(activeGroupMember); historyList.forEach(h -> h.updateGroupMember(inactiveGroupMember)); + // Comment 그룹 멤버 변경 + List commentList = commentJPARepository.findAllByGroupMember(activeGroupMember); + commentList.forEach(c -> c.updateGroupMember(inactiveGroupMember)); + + // Reposrt 그룹 멤버 변경 + List reportList = reportJPARepository.findAllByFromMember(activeGroupMember); + reportList.forEach(r -> r.updateGroupMember(inactiveGroupMember)); + // DB 작업 groupMemberJPARepository.delete(activeGroupMember); groupMemberJPARepository.save(inactiveGroupMember); + + postJPARepository.saveAll(postList); historyJPARepository.saveAll(historyList); + commentJPARepository.saveAll(commentList); + reportJPARepository.saveAll(reportList); } catch (Exception404 e) { throw e; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java index 5342e1cf..f2c3f448 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java @@ -40,8 +40,6 @@ public History(Long id, Post post){ this.created_at = post.getCreated_at(); } - - public void updateGroupMember(GroupMember groupMember) { this.groupMember = groupMember; } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java index 633e0256..c830ebe6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java @@ -37,4 +37,7 @@ public Report(Long id, GroupMember groupMember, History history, String content, this.created_at = created_at; } + public void updateGroupMember(GroupMember groupMember) { + this.fromMember = groupMember; + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java index 098ca083..94c0a2a7 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java @@ -1,9 +1,12 @@ package com.kakao.techcampus.wekiki.report; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.post.Post; import org.springframework.data.jpa.repository.JpaRepository; -public interface ReportJPARepository extends JpaRepository { +import java.util.List; +public interface ReportJPARepository extends JpaRepository { + List findAllByFromMember(ActiveGroupMember activeGroupMember); } From c0ef2acc950ae26862129ccb4018f8b69c1ae262 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Tue, 7 Nov 2023 14:39:09 +0900 Subject: [PATCH 091/144] =?UTF-8?q?Refactor=20:=20Post=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20API=EC=9D=98=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20?= =?UTF-8?q?=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 유효한 그룹,멤버,그룹멤버를 확인하는 과정에서 fetch join을 토해 하나의 쿼리로 해결하였습니다. --- .../wekiki/history/HistoryJPARepository.java | 4 - .../techcampus/wekiki/post/PostService.java | 119 ++++++------------ 2 files changed, 40 insertions(+), 83 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java index a0a1662d..3c64ff18 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java @@ -14,10 +14,6 @@ @Repository public interface HistoryJPARepository extends JpaRepository { - @Modifying - @Query("DELETE FROM History h WHERE h.post.id = :postId") - void deleteByPostId(@Param("postId") Long postId); - List findAllByGroupMember(GroupMember groupMember); Page findAllByGroupMember(GroupMember groupMember, Pageable pageable); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index 0fcf7767..6512284d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -33,43 +33,35 @@ public class PostService { private final PageJPARepository pageJPARepository; private final PostJPARepository postJPARepository; private final HistoryJPARepository historyJPARepository; - private final MemberJPARepository memberJPARepository; private final GroupMemberJPARepository groupMemberJPARepository; - private final GroupJPARepository groupJPARepository; private final ReportJPARepository reportJPARepository; final int HISTORY_COUNT = 5; @Transactional public PostResponse.createPostDTO createPost(Long memberId,Long groupId,Long pageId, Long parentPostId, int order, String title, String content){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) - ActiveGroupMember groupMember = checkGroupMember(memberId, groupId); - - // 4. pageId로 PageInfo 객체 들고오기 + // 2. pageId로 PageInfo 객체 들고오기 PageInfo pageInfo = checkPageFromPageId(pageId); pageInfo.updatePage(); - // 5. parentPostId로 parentPost 가져오기 + // 3. parentPostId로 parentPost 가져오기 Post parent = null; if(parentPostId != 0) { parent = postJPARepository.findById(parentPostId).orElseThrow( () -> new Exception404("존재하지 않는 상위 글입니다.")); } - // 6. 같은 pageId를 가진 Post들 중에 입력받은 order보다 높은 모든 Post들의 order를 1씩 증가 + // 4. 같은 pageId를 가진 Post들 중에 입력받은 order보다 높은 모든 Post들의 order를 1씩 증가 postJPARepository.findPostsByPageIdAndOrderGreaterThan(pageId, order).stream().forEach(p -> p.plusOrder()); - // 7. Post 엔티티 생성하고 저장하기 + // 5. Post 엔티티 생성하고 저장하기 Post newPost = Post.builder() .parent(parent) .orders(order) - .groupMember(groupMember) + .groupMember(activeGroupMember) .title(title) .content(content) .created_at(LocalDateTime.now()) @@ -77,66 +69,52 @@ public PostResponse.createPostDTO createPost(Long memberId,Long groupId,Long pag pageInfo.addPost(newPost); Post savedPost = postJPARepository.save(newPost); - // 8. 히스토리 생성 + // 6. 히스토리 생성 History newHistory = History.builder() .post(savedPost) .build(); savedPost.addHistory(newHistory); historyJPARepository.save(newHistory); - // 9. return DTO + // 7. return DTO return new PostResponse.createPostDTO(savedPost); } @Transactional public PostResponse.modifyPostDTO modifyPost(Long memberId , Long groupId, Long postId , String title, String content){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); - - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) - ActiveGroupMember groupMember = checkGroupMember(memberId, groupId); + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); - // 4. postId로 post 엔티티 가져오기 + // 2. postId로 post 엔티티 가져오기 Post post = checkPostFromPostId(postId); - // 5. 현재 Post랑 내용 같은지 확인 + // 3. 현재 Post랑 내용 같은지 확인 if(post.getTitle().equals(title) && post.getContent().equals(content)){ throw new Exception400("기존 글과 동일한 글입니다."); } - // 6. 다르면 Post 수정후 히스토리 생성 저장 - History newHistory = post.modifyPost(groupMember, title, content); + // 4. 다르면 Post 수정후 히스토리 생성 저장 + History newHistory = post.modifyPost(activeGroupMember, title, content); historyJPARepository.save(newHistory); - // 7. return DTO + // 5. return DTO return new PostResponse.modifyPostDTO(post); } @Transactional public PostResponse.getPostHistoryDTO getPostHistory(Long memberId, Long groupId, Long postId , int pageNo){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); - - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 checkGroupMember(memberId, groupId); - // 4. postId로 post 엔티티 가져오기 + // 2. postId로 post 엔티티 가져오기 Post post = checkPostFromPostId(postId); - // 5. 해당 PostId로 history 모두 가져오기 시간순 + 페이지네이션 (memberId, nickName, historyId,title, content, created_at) - PageRequest pageRequest = PageRequest.of(pageNo, HISTORY_COUNT); - Page historys = historyJPARepository.findHistoryWithMemberByPostId(postId, pageRequest); - //Page historys = historyJPARepository.findHistoryByPostId(postId, pageRequest); + // 3. 해당 PostId로 history 모두 가져오기 시간순 + 페이지네이션 + Page historys = historyJPARepository.findHistoryWithMemberByPostId(postId, PageRequest.of(pageNo, HISTORY_COUNT)); - // 6. DTO로 return + // 4. DTO로 return List historyDTOs = historys.getContent().stream(). map(h -> new PostResponse.getPostHistoryDTO.historyDTO(h.getGroupMember(),h)).collect(Collectors.toList()); return new PostResponse.getPostHistoryDTO(post,historyDTOs); @@ -146,32 +124,26 @@ public PostResponse.getPostHistoryDTO getPostHistory(Long memberId, Long groupId @Transactional public PostResponse.deletePostDTO deletePost(Long memberId, Long groupId, Long postId){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); - - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 checkGroupMember(memberId, groupId); - // 4. postId로 post 엔티티 가져오기 + // 2. postId로 post 엔티티 가져오기 Post post = checkPostFromPostId(postId); - // 5. parent로 해당 postId를 가지고 있는 post가 있는지 확인 -> 존재하면 Exception + // 3. parent로 해당 postId를 가지고 있는 post가 있는지 확인 -> 존재하면 Exception if(postJPARepository.existsByParentId(postId)){ throw new Exception400("하위 글이 존재하는 글은 삭제가 불가능합니다."); } - // 6. child post 존재 안하면 history + post 삭제 시키기 + // 4. child post 존재 안하면 history + post 삭제 시키기 PostResponse.deletePostDTO response = new PostResponse.deletePostDTO(post); postJPARepository.deleteById(postId); - // 7. order값 앞으로 땡기기 + // 5. order값 앞으로 땡기기 postJPARepository.findPostsByPageIdAndOrderGreaterThan(post.getPageInfo().getId(), post.getOrders()) .stream().forEach(p -> p.minusOrder()); - // 8. return DTO; + // 6. return DTO; return response; } @@ -179,49 +151,38 @@ public PostResponse.deletePostDTO deletePost(Long memberId, Long groupId, Long p @Transactional public PostResponse.createReportDTO createReport(Long memberId, Long groupId, Long postId , String content){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) - GroupMember groupMember = checkGroupMember(memberId, groupId); - - // 4. postId로 post 엔티티 가져오기 + // 2. postId로 post 엔티티 가져오기 checkPostFromPostId(postId); - // 5. postId의 최근 히스토리 가져오기 + // 3. postId의 최근 히스토리 가져오기 List historyByPostId = historyJPARepository.findHistoryByPostId(postId, PageRequest.of(0, 1)); - // 6. report 생성 + // 4. report 생성 Report report = Report.builder() - .groupMember(groupMember) + .groupMember(activeGroupMember) .history(historyByPostId.get(0)) .content(content) .created_at(LocalDateTime.now()) .build(); Report savedReport = reportJPARepository.save(report); - // 7. return DTO + // 5. return DTO return new PostResponse.createReportDTO(savedReport); } - public Member checkMemberFromMemberId(Long memberId){ - return memberJPARepository.findById(memberId) - .orElseThrow(()-> new Exception404("존재하지 않는 회원입니다.")); - } - - public Group checkGroupFromGroupId(Long groupId){ - return groupJPARepository.findById(groupId) - .orElseThrow(()-> new Exception404("존재하지 않는 그룹입니다.")); - } - public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ - return groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId,groupId) + + ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); + if(activeGroupMember.getMember() == null) throw new Exception404("존재하지 않는 회원입니다."); + if(activeGroupMember.getGroup() == null) throw new Exception404("존재하지 않는 그룹입니다."); + + return activeGroupMember; } public PageInfo checkPageFromPageId(Long pageId){ From ba277606241d4223bda91787b1e327fb534a8ec8 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Tue, 7 Nov 2023 14:45:24 +0900 Subject: [PATCH 092/144] =?UTF-8?q?Refactor=20:=20Comment=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20API=EC=9D=98=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= =?UTF-8?q?=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 유효한 그룹,멤버,그룹멤버를 확인하는 과정에서 fetch join을 토해 하나의 쿼리로 해결하였습니다. --- .../wekiki/comment/CommentService.java | 100 ++++++------------ 1 file changed, 35 insertions(+), 65 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java index 3981e2ee..c30f16fe 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java @@ -36,25 +36,18 @@ public class CommentService { @Transactional public CommentResponse.getCommentDTO getComment(Long memberId, Long groupId, Long postId, int pageNo){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) - ActiveGroupMember groupMember = checkGroupMember(memberId, groupId); - - // 4. post 존재하는지 예외처리 + // 2. post 존재하는지 예외처리 Post post = checkPostFromPostId(postId); - // 5. postId로 Comment 다 가져오기 - Pageable pageable = PageRequest.of(pageNo, COMMENT_COUNT); - Page comments = commentJPARepository.findCommentsByPostIdWithGroupMembers(postId, pageable); + // 3. postId로 Comment 다 가져오기 + Page comments = commentJPARepository.findCommentsByPostIdWithGroupMembers(postId, PageRequest.of(pageNo, COMMENT_COUNT)); - // 6. return DTO + // 4. return DTO List commentDTOs = comments.getContent() - .stream().map(c -> new CommentResponse.getCommentDTO.commentDTO(c,c.getGroupMember(), c.getGroupMember().getId() == groupMember.getId())) + .stream().map(c -> new CommentResponse.getCommentDTO.commentDTO(c,c.getGroupMember(), c.getGroupMember().getId() == activeGroupMember.getId())) .collect(Collectors.toList()); return new CommentResponse.getCommentDTO(post,commentDTOs); } @@ -62,105 +55,82 @@ public CommentResponse.getCommentDTO getComment(Long memberId, Long groupId, Lon @Transactional public CommentResponse.createCommentDTO createComment(Long memberId, Long groupId, Long postId, String content){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); - - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) - ActiveGroupMember groupMember = checkGroupMember(memberId, groupId); + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); - // 4. post 존재하는지 예외처리 + // 2. post 존재하는지 예외처리 Post post = checkPostFromPostId(postId); - // 4. comment 생성 + // 3. comment 생성 Comment comment = Comment.builder() - .groupMember(groupMember) + .groupMember(activeGroupMember) .content(content) .created_at(LocalDateTime.now()) .build(); post.addComment(comment); Comment savedComment = commentJPARepository.save(comment); - // 5. return DTO - return new CommentResponse.createCommentDTO(savedComment,groupMember.getNickName()); + // 4. return DTO + return new CommentResponse.createCommentDTO(savedComment,activeGroupMember.getNickName()); } @Transactional public CommentResponse.deleteCommentDTO deleteComment(Long memberId, Long groupId, Long commentId){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); - - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) - ActiveGroupMember groupMember = checkGroupMember(memberId, groupId); + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); - // 4. comment 존재하는지 예외처리 + // 2. comment 존재하는지 예외처리 Comment comment = checkCommentFromCommentId(commentId); - // 5. comment 쓴 사람이 삭제하는 유저랑 일치하는지 확인 - if(comment.getGroupMember().getId() != groupMember.getId()){ + // 3. comment 쓴 사람이 삭제하는 유저랑 일치하는지 확인 + if(comment.getGroupMember().getId() != activeGroupMember.getId()){ throw new Exception400("본인이 쓴 댓글만 삭제가 가능합니다."); } - // 5. comment 삭제 + // 4. comment 삭제 CommentResponse.deleteCommentDTO response = new CommentResponse.deleteCommentDTO(comment); commentJPARepository.delete(comment); - // 6. return DTO + // 5. return DTO return response; } @Transactional public CommentResponse.updateCommentDTO updateComment(Long memberId, Long groupId, Long commentId, String updateContent){ - // 1. memberId로 Member 객체 가져오기 - checkMemberFromMemberId(memberId); + // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); - // 2. 존재하는 group인지 확인하기 - checkGroupFromGroupId(groupId); - - // 3. 해당 그룹에 속하는 Member인지 확인 (=GroupMember 확인) - ActiveGroupMember groupMember = checkGroupMember(memberId, groupId); - - // 4. comment 존재하는지 예외처리 + // 2. comment 존재하는지 예외처리 Comment comment = checkCommentFromCommentId(commentId); - // 5. comment 쓴 사람이 삭제하는 유저랑 일치하는지 확인 - if(comment.getGroupMember().getId() != groupMember.getId()){ + // 3. comment 쓴 사람이 수정하는 유저랑 일치하는지 확인 + if(comment.getGroupMember().getId() != activeGroupMember.getId()){ throw new Exception400("본인이 쓴 댓글만 수정이 가능합니다."); } - // 6. 내용 동일하면 exception + // 4. 내용 동일하면 exception if(comment.getContent().equals(updateContent)){ throw new Exception400("기존 댓글과 동일한 내용입니다."); } - // 7. 수정 + // 5. 수정 comment.updateContent(updateContent); - // 8. return DTO + // 6. return DTO return new CommentResponse.updateCommentDTO(comment); } - public Member checkMemberFromMemberId(Long memberId){ - return memberJPARepository.findById(memberId) - .orElseThrow(()-> new Exception404("존재하지 않는 회원입니다.")); - } - - public Group checkGroupFromGroupId(Long groupId){ - return groupJPARepository.findById(groupId) - .orElseThrow(()-> new Exception404("존재하지 않는 그룹입니다.")); - } - public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ - return groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId,groupId) + + ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); + if(activeGroupMember.getMember() == null) throw new Exception404("존재하지 않는 회원입니다."); + if(activeGroupMember.getGroup() == null) throw new Exception404("존재하지 않는 그룹입니다."); + + return activeGroupMember; } public Post checkPostFromPostId(Long postId){ From 4eb290d87fc61049dfa933f8074d72b535a92caf Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Tue, 7 Nov 2023 16:05:36 +0900 Subject: [PATCH 093/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 비공식 공개 그룹 뿐만이 아닌 비공개 그룹 또한 조회 가능하도록 수정 --- .../techcampus/wekiki/group/dto/GroupResponseDTO.java | 7 ++++--- .../wekiki/group/repository/GroupJPARepository.java | 2 +- .../techcampus/wekiki/group/service/GroupService.java | 3 +-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java index 16b344db..e6bb8af7 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java @@ -120,20 +120,21 @@ public record SearchGroupInfoDTO( String entranceHint, String groupType ) { - public SearchGroupInfoDTO(UnOfficialOpenedGroup group) { + public SearchGroupInfoDTO(Group group) { this( group.getId(), group.getGroupName(), group.getGroupProfileImage(), - group.getIntroduction(), + (group instanceof UnOfficialOpenedGroup) ? ((UnOfficialOpenedGroup) group).getIntroduction() : null, group.getMemberCount(), group.getCreated_at(), - group.getEntranceHint(), + (group instanceof UnOfficialOpenedGroup) ? ((UnOfficialOpenedGroup) group).getEntranceHint() : null, group.getClass().getAnnotation(DiscriminatorValue.class).value() ); } } + // 그룹 내 그룹원 리스트 조회 public record GetGroupMembersResponseDTO(List nickNames) { public GetGroupMembersResponseDTO(Group group) { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupJPARepository.java index 1a51b009..bf1e9c1a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupJPARepository.java @@ -25,7 +25,7 @@ public interface GroupJPARepository extends JpaRepository { Page findUnOfficialOpenedGroupsByKeyword(@Param("keyword") String keyword, Pageable pageable); /* - 비공식 공개 그룹 상세 조회 + 비공식 공개 그룹 입장 */ @Query("SELECT g FROM UnOfficialOpenedGroup g WHERE g.id = :id") Optional findUnOfficialOpenedGroupById(@Param("id") Long id); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 69d3777a..0a330da8 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -204,8 +204,7 @@ public GroupResponseDTO.SearchUnOfficialGroupResponseDTO searchUnOfficialGroupBy */ public GroupResponseDTO.SearchGroupInfoDTO getGroupInfo(Long groupId) { try { - UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId) - .orElseThrow(() -> new Exception404("그룹을 찾을 수 없습니다.")); + Group group = getGroupById(groupId); return new GroupResponseDTO.SearchGroupInfoDTO(group); } catch (Exception404 e) { From bf97b82d95e5c983106523fac9bb47a3c862a5f8 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Tue, 7 Nov 2023 16:38:11 +0900 Subject: [PATCH 094/144] =?UTF-8?q?Fix:=20=EA=B7=B8=EB=A3=B9=20=ED=83=88?= =?UTF-8?q?=ED=87=B4,=20=EC=9E=AC=EA=B0=80=EC=9E=85=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 그룹 탈퇴 시 activeGroupMember -> inActiveGroupMember - 그룹 재가입 시 inActiveGroupMember -> activeGroupMember - Member와 Group의 GroupMemberList에서 각각 맞는 groupMember 삭제 --- .../wekiki/comment/CommentJPARepository.java | 4 +- .../wekiki/group/service/GroupService.java | 71 ++++++++++++------- .../wekiki/history/HistoryJPARepository.java | 7 +- .../wekiki/post/PostJPARepository.java | 6 +- .../wekiki/report/ReportJPARepository.java | 6 +- 5 files changed, 59 insertions(+), 35 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java index 722f6e6e..beafcfdf 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java @@ -1,6 +1,7 @@ package com.kakao.techcampus.wekiki.comment; import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.post.Post; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -21,5 +22,6 @@ public interface CommentJPARepository extends JpaRepository { @Query("SELECT c FROM Comment c LEFT JOIN FETCH c.groupMember WHERE c.id = :commentId") Optional findCommentWithGroupMember(@Param("commentId") Long commentId); - List findAllByGroupMember(ActiveGroupMember activeGroupMember); + @Query("SELECT c FROM Comment c WHERE c.groupMember.id = :groupMemberId") + List findAllByGroupMemberId(@Param("groupMemberId") Long groupMemberId); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 0a330da8..ab65dca7 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -7,6 +7,7 @@ import com.kakao.techcampus.wekiki.comment.Comment; import com.kakao.techcampus.wekiki.comment.CommentJPARepository; import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.group.dto.GroupRequestDTO; import com.kakao.techcampus.wekiki.group.dto.GroupResponseDTO; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; @@ -200,7 +201,7 @@ public GroupResponseDTO.SearchUnOfficialGroupResponseDTO searchUnOfficialGroupBy } /* - 비공식 공개 그룹 상세 정보 조회 + 그룹 상세 정보 조회 */ public GroupResponseDTO.SearchGroupInfoDTO getGroupInfo(Long groupId) { try { @@ -220,6 +221,9 @@ public GroupResponseDTO.SearchGroupInfoDTO getGroupInfo(Long groupId) { */ public void groupEntry(Long groupId, Long memberId, GroupRequestDTO.GroupEntryRequestDTO requestDTO) { try { + getGroupById(groupId); + getMemberById(memberId); + UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId) .orElseThrow(() -> new Exception404("그룹을 찾을 수 없습니다.")); @@ -265,9 +269,8 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ // 재가입 회원이면 활성화, 신규 회원이면 새로 생성 ActiveGroupMember groupMember = wasGroupMember != null ? new ActiveGroupMember(wasGroupMember) : buildGroupMember(member, group, requestDTO.nickName()); - // 그룹 멤버 잔재 삭제 if(wasGroupMember != null) { - groupMemberJPARepository.delete(wasGroupMember); + changeAuthorization(wasGroupMember, groupMember); } // GroupMember 저장 @@ -329,7 +332,7 @@ public GroupResponseDTO.MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long // 해당 멤버의 Post 기록 정보 확인(History에서 가져옴) Pageable pageable = PageRequest.of(0, 10); - Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember, pageable); + Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember.getId(), pageable); // 그룹 이름, 현재 닉네임, Post 기록 정보를 담은 responseDTO 반환 return new GroupResponseDTO.MyGroupInfoResponseDTO(groupMember.getGroup(), groupMember, myHistoryList); @@ -351,7 +354,7 @@ public GroupResponseDTO.MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId .orElseThrow(() -> new Exception404("해당 그룹의 회원이 아닙니다")); Pageable pageable = PageRequest.of(page, size); - Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember, pageable); + Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember.getId(), pageable); return new GroupResponseDTO.MyGroupHistoryResponseDTO(myHistoryList); @@ -413,34 +416,19 @@ public void leaveGroup(Long groupId, Long memberId) { ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹의 회원이 아닙니다")); - // 탈퇴 그룹 회원 생성 - InactiveGroupMember inactiveGroupMember = new InactiveGroupMember(activeGroupMember); - - // Post의 그룹 멤버 변경 - List postList = postJPARepository.findAllByGroupMember(activeGroupMember); - postList.forEach(p -> p.updateGroupMember(inactiveGroupMember)); + Member member = getMemberById(memberId); + Group group = getGroupById(groupId); - // History 그룹 멤버 변경 - List historyList = historyJPARepository.findAllByGroupMember(activeGroupMember); - historyList.forEach(h -> h.updateGroupMember(inactiveGroupMember)); + member.getGroupMembers().remove(activeGroupMember); + group.getGroupMembers().remove(activeGroupMember); - // Comment 그룹 멤버 변경 - List commentList = commentJPARepository.findAllByGroupMember(activeGroupMember); - commentList.forEach(c -> c.updateGroupMember(inactiveGroupMember)); + // 탈퇴 그룹 회원 생성 + InactiveGroupMember inactiveGroupMember = new InactiveGroupMember(activeGroupMember); - // Reposrt 그룹 멤버 변경 - List reportList = reportJPARepository.findAllByFromMember(activeGroupMember); - reportList.forEach(r -> r.updateGroupMember(inactiveGroupMember)); + changeAuthorization(activeGroupMember, inactiveGroupMember); - // DB 작업 - groupMemberJPARepository.delete(activeGroupMember); groupMemberJPARepository.save(inactiveGroupMember); - postJPARepository.saveAll(postList); - historyJPARepository.saveAll(historyList); - commentJPARepository.saveAll(commentList); - reportJPARepository.saveAll(reportList); - } catch (Exception404 e) { throw e; } catch (Exception e) { @@ -448,6 +436,35 @@ public void leaveGroup(Long groupId, Long memberId) { } } + private void changeAuthorization(GroupMember originGroupMember, GroupMember targetGroupMember) { + + Long originGroupMemberId = originGroupMember.getId(); + + // Post의 그룹 멤버 변경 + List postList = postJPARepository.findAllByGroupMember(originGroupMemberId); + postList.forEach(p -> p.updateGroupMember(targetGroupMember)); + + // History 그룹 멤버 변경 + List historyList = historyJPARepository.findAllByGroupMemberId(originGroupMemberId); + historyList.forEach(h -> h.updateGroupMember(targetGroupMember)); + + // Comment 그룹 멤버 변경 + List commentList = commentJPARepository.findAllByGroupMemberId(originGroupMemberId); + commentList.forEach(c -> c.updateGroupMember(targetGroupMember)); + + // Reposrt 그룹 멤버 변경 + List reportList = reportJPARepository.findAllByFromMemberId(originGroupMemberId); + reportList.forEach(r -> r.updateGroupMember(targetGroupMember)); + + // DB 작업 + groupMemberJPARepository.delete(originGroupMember); + + postJPARepository.saveAll(postList); + historyJPARepository.saveAll(historyList); + commentJPARepository.saveAll(commentList); + reportJPARepository.saveAll(reportList); + } + protected Member getMemberById(Long memberId) { return memberJPARepository.findById(memberId).orElseThrow(() -> new Exception404("해당 사용자를 찾을 수 없습니다.")); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java index a0a1662d..48885067 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java @@ -18,9 +18,12 @@ public interface HistoryJPARepository extends JpaRepository { @Query("DELETE FROM History h WHERE h.post.id = :postId") void deleteByPostId(@Param("postId") Long postId); - List findAllByGroupMember(GroupMember groupMember); + @Query("SELECT h FROM History h WHERE h.groupMember.id = :groupMemberId") + List findAllByGroupMemberId(@Param("groupMemberId") Long groupMemberId); + + @Query("SELECT h FROM History h WHERE h.groupMember.id = :groupMemberId") + Page findAllByGroupMember(@Param("groupMemberId") Long groupMemberId, Pageable pageable); - Page findAllByGroupMember(GroupMember groupMember, Pageable pageable); @Query("SELECT h FROM History h JOIN FETCH h.groupMember m WHERE h.post.id = :postId ORDER BY h.created_at DESC") Page findHistoryWithMemberByPostId(@Param("postId") Long postId, Pageable pageable); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java index bc524112..33d5ae12 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java @@ -3,7 +3,6 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import org.springframework.stereotype.Repository; import java.util.List; @@ -24,11 +23,10 @@ List findPostsByPageIdAndOrderGreaterThan( boolean existsByParentId(Long parentId); - List findAllByGroupMember(GroupMember groupMember); + @Query("SELECT p FROM Post p WHERE p.groupMember.id = :groupId") + List findAllByGroupMember(@Param("groupId") Long groupId); // 해당 pageId를 가지고 있는 post들 중에 orders가 1인거 들고오기 @Query("SELECT p FROM Post p WHERE p.pageInfo.id = :pageId AND p.orders = 1") List findFirstPost(@Param("pageId") Long pageId); - - } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java index 94c0a2a7..4323e9f5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java @@ -1,12 +1,16 @@ package com.kakao.techcampus.wekiki.report; import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.post.Post; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.util.List; public interface ReportJPARepository extends JpaRepository { - List findAllByFromMember(ActiveGroupMember activeGroupMember); + @Query("SELECT r FROM Report r WHERE r.fromMember.id = :groupMemberId") + List findAllByFromMemberId(@Param("groupMemberId") Long groupMemberId); } From 045f949174c9dff47597785b6bffe90ab2f746ed Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Tue, 7 Nov 2023 17:51:30 +0900 Subject: [PATCH 095/144] =?UTF-8?q?Refactor:=20=EC=9C=A0=ED=9A=A8=EC=84=B1?= =?UTF-8?q?=20=EA=B2=80=EC=82=AC=20=EB=B0=8F=20=EA=B6=8C=ED=95=9C=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 유효성 검사 : NotBlank 사용 - 그룹 서비스 내 권환 확인 --- .../wekiki/group/dto/GroupRequestDTO.java | 9 +++++---- .../wekiki/group/service/GroupService.java | 20 +++++++++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java index 4672f3f5..3bbeffe0 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupRequestDTO.java @@ -1,6 +1,7 @@ package com.kakao.techcampus.wekiki.group.dto; import com.kakao.techcampus.wekiki.group.GroupType; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; public class GroupRequestDTO { @@ -9,11 +10,11 @@ public class GroupRequestDTO { public record CreateUnOfficialGroupRequestDTO( @NotNull(message = "그룹 유형을 선택해 주세요.") GroupType groupType, - @NotNull(message = "그룹 이름을 입력해 주세요.") + @NotBlank(message = "그룹 이름을 입력해 주세요.") String groupName, @NotNull(message = "그룹 이미지를 첨부해 주세요.") String groupImage, - @NotNull(message = "그룹 닉네임을 설정해 주세요.") + @NotBlank(message = "그룹 닉네임을 설정해 주세요.") String groupNickName, String introduction, String entranceHint, @@ -27,13 +28,13 @@ public record GroupEntryRequestDTO( } public record JoinGroupRequestDTO( - @NotNull(message = "그룹 닉네임을 설정해 주세요.") + @NotBlank(message = "그룹 닉네임을 설정해 주세요.") String nickName ) { } public record UpdateMyGroupPageDTO( - @NotNull(message = "그룹 닉네임을 설정해 주세요.") + @NotBlank(message = "그룹 닉네임을 설정해 주세요.") String groupNickName ) { } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index ab65dca7..8b508894 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -249,7 +249,6 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ try { // 회원 정보 확인 Member member = getMemberById(memberId); - // 그룹 정보 확인 Group group = getGroupById(groupId); @@ -327,8 +326,7 @@ public GroupResponseDTO.GetGroupMembersResponseDTO getGroupMembers(Long groupId, public GroupResponseDTO.MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { try { // 그룹 멤버 확인 - ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) - .orElseThrow(() -> new Exception404("해당 그룹의 회원이 아닙니다")); + ActiveGroupMember groupMember = getActiveGroupMember(groupId, memberId); // 해당 멤버의 Post 기록 정보 확인(History에서 가져옴) Pageable pageable = PageRequest.of(0, 10); @@ -350,8 +348,7 @@ public GroupResponseDTO.MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long public GroupResponseDTO.MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, int page, int size) { try { // 그룹 멤버 확인 - ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) - .orElseThrow(() -> new Exception404("해당 그룹의 회원이 아닙니다")); + ActiveGroupMember groupMember = getActiveGroupMember(groupId, memberId); Pageable pageable = PageRequest.of(page, size); Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember.getId(), pageable); @@ -373,8 +370,7 @@ public GroupResponseDTO.MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId public void updateMyGroupPage(Long groupId, Long memberId, GroupRequestDTO.UpdateMyGroupPageDTO requestDTO) { try { // 그룹 멤버 확인 - ActiveGroupMember groupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) - .orElseThrow(() -> new Exception404("해당 그룹의 회원이 아닙니다")); + ActiveGroupMember groupMember = getActiveGroupMember(groupId, memberId); // 변경할 닉네임 확인 String newNickName = requestDTO.groupNickName(); @@ -412,9 +408,7 @@ public void updateMyGroupPage(Long groupId, Long memberId, GroupRequestDTO.Updat @Transactional public void leaveGroup(Long groupId, Long memberId) { try { - // 그룹 멤버 확인 - ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) - .orElseThrow(() -> new Exception404("해당 그룹의 회원이 아닙니다")); + ActiveGroupMember activeGroupMember = getActiveGroupMember(groupId, memberId); Member member = getMemberById(memberId); Group group = getGroupById(groupId); @@ -473,6 +467,12 @@ protected Group getGroupById(Long groupId) { return groupJPARepository.findById(groupId).orElseThrow(() -> new Exception404("해당 그룹을 찾을 수 없습니다.")); } + private ActiveGroupMember getActiveGroupMember(Long groupId, Long memberId) { + // 그룹 멤버 확인 + return groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) + .orElseThrow(() -> new Exception404("해당 그룹의 회원이 아닙니다")); + } + protected void groupNickNameCheck(Long groupId, String groupNickName) { if(groupMemberJPARepository.findGroupMemberByNickName(groupId, groupNickName).isPresent()) { throw new Exception400("해당 닉네임은 이미 사용중입니다."); From f39064ab5b33c21ddc55b2d879c32a88deea1972 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Tue, 7 Nov 2023 22:44:03 +0900 Subject: [PATCH 096/144] =?UTF-8?q?Refactor:=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EB=A9=94=EC=84=B8=EC=A7=80=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 해당 그룹에 속환 회원이 아닌 경우 - 존재하지 않는 초대 링크에 접속한 경우 --- .../techcampus/wekiki/group/service/GroupService.java | 7 ++----- .../techcampus/wekiki/group/service/InvitationService.java | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 8b508894..0e925fe3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -306,10 +306,7 @@ protected void checkJoinPermission(Long memberId, Long groupId) { public GroupResponseDTO.GetGroupMembersResponseDTO getGroupMembers(Long groupId, Long memberId) { try { Group group = getGroupById(groupId); - - if(groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId).isEmpty()) { - throw new Exception400("해당 그룹에 대한 권한이 없습니다."); - } + getActiveGroupMember(groupId, memberId); return new GroupResponseDTO.GetGroupMembersResponseDTO(group); @@ -470,7 +467,7 @@ protected Group getGroupById(Long groupId) { private ActiveGroupMember getActiveGroupMember(Long groupId, Long memberId) { // 그룹 멤버 확인 return groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) - .orElseThrow(() -> new Exception404("해당 그룹의 회원이 아닙니다")); + .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다")); } protected void groupNickNameCheck(Long groupId, String groupNickName) { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index 58325e51..7f6a269f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -65,7 +65,7 @@ public GroupResponseDTO.ValidateInvitationResponseDTO validateInvitation(String // 초대 링크를 통해 groupId와 invitation 찾기 // groupId는 현재 Integer 타입 Object groupId = Optional.ofNullable(redisUtils.getValues(INVITATION_PREFIX + invitationLink)) - .orElseThrow(() -> new Exception404("잘못된 접근입니다.")); + .orElseThrow(() -> new Exception404("존재하지 않는 초대 링크입니다.")); // 초대 링크 기간 확인 Invitation invitation = (Invitation) redisUtils.getValues(GROUP_ID_PREFIX + groupId); From 33bbc7aa49e7535187b89aebc149bd656c628b9b Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Wed, 8 Nov 2023 12:08:13 +0900 Subject: [PATCH 097/144] =?UTF-8?q?Refactor=20:=20=ED=82=A4=EC=9B=8C?= =?UTF-8?q?=EB=93=9C=EA=B2=80=EC=83=89=20api=EC=97=90=EC=84=9C=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=20=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fetch join이랑 페이지네이션을 같이 사용하니 모든 fetch join 데이터를 서버로 가져와서 서버단에서 페이지네이션을 처리하는 문제가 생겼습니다. - 이를 두개의 쿼리로 나누어 먼저 페이지네이션으로 PageInfo를 가져오고, 거기에 해당하는 Post를 IN을 사용하여 가져오는 방식으로 개선하였습니다. --- .../wekiki/page/PageInfoResponse.java | 6 +-- .../wekiki/page/PageJPARepository.java | 9 +++- .../techcampus/wekiki/page/PageService.java | 46 +++++++++++++------ .../wekiki/post/PostJPARepository.java | 3 ++ 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java index 7f4bb7a5..66c0dfbb 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfoResponse.java @@ -105,9 +105,9 @@ public static class pageDTO{ String pageName; String content; - public pageDTO(PageInfo pageInfo ,String content){ - this.pageId = pageInfo.getId(); - this.pageName = pageInfo.getPageName(); + public pageDTO(Long pageId, String pageName ,String content){ + this.pageId = pageId; + this.pageName = pageName; this.content = content; } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java index 75acda3d..ea384a53 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.page; +import com.kakao.techcampus.wekiki.post.Post; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -28,9 +29,13 @@ public interface PageJPARepository extends JpaRepository { @Query("SELECT p FROM PageInfo p LEFT JOIN FETCH p.posts ps WHERE p.id = :pageId ORDER BY ps.orders ASC") Optional findByPageIdWithPosts(@Param("pageId") Long pageId); - @Query("SELECT p FROM PageInfo p LEFT JOIN FETCH p.posts ps WHERE p.group.id = :groupId AND p.pageName LIKE %:keyword%") - Page findPagesWithPosts(@Param("groupId") Long groupId, @Param("keyword") String keyword, Pageable pageable); +// @Query("SELECT p FROM PageInfo p LEFT JOIN FETCH p.posts ps WHERE p.group.id = :groupId AND p.pageName LIKE %:keyword%") +// Page findPagesWithPosts(@Param("groupId") Long groupId, @Param("keyword") String keyword, Pageable pageable); + @Query("SELECT distinct p FROM PageInfo p LEFT JOIN FETCH p.posts ps WHERE p.group.id = :groupId AND p.pageName LIKE %:keyword% AND (ps.orders = 1 or ps.orders is null)") + Page findPagesWithPosts(@Param("groupId") Long groupId, @Param("keyword") String keyword, Pageable pageable); + @Query("SELECT p FROM PageInfo p WHERE p.group.id = :groupId AND p.pageName LIKE %:keyword% ") + Page findPages(@Param("groupId") Long groupId, @Param("keyword") String keyword, Pageable pageable); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index c0d90323..5845534a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -17,7 +17,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -229,23 +228,44 @@ public PageInfoResponse.searchPageDTO searchPage(Long groupId, Long memberId, in // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 checkGroupMember(memberId, groupId); - // 2. keyword로 존재하는 page title에 keyword를 가지고 있는 페이지들 다 가져오기 - // (TODO : fetch join이랑 Pagination 함께 쓰면 페이지네이션을 애플리케이션에 들고온 다음 하게됨) - Page pages = pageJPARepository.findPagesWithPosts(groupId, keyword, PageRequest.of(pageNo, PAGE_COUNT)); + // 2. 페이지네이션 적용하여 Page 이름으로 keyword를 들고있는 페이지 들고오기 + List pages = pageJPARepository.findPages(groupId, keyword, PageRequest.of(pageNo, PAGE_COUNT)).getContent(); - // 3. 해당 Page들을 FK로 가지고 있는 Post들 중에 Orders가 1인 Post들 가져오기 + // 3. 가져온 페이지들 중에 첫 포스트 가져오기 + List posts = postJPARepository.findPostInPages(pages); + + // 4. responseDTO 만들기 List res = new ArrayList<>(); - for(PageInfo p : pages.getContent()){ - List posts = p.getPosts(); - if(posts.size() == 0){ - res.add(new PageInfoResponse.searchPageDTO.pageDTO(p,"")); - }else{ - res.add(new PageInfoResponse.searchPageDTO.pageDTO(p,posts.get(0).getContent())); + boolean flag; + for(PageInfo p : pages) { // 최대 10개 + flag = false; + for (Post po : posts) { // 최대 10개 + if (p.getId() == po.getPageInfo().getId()) { + res.add(new PageInfoResponse.searchPageDTO.pageDTO(p.getId(), p.getPageName(), po.getContent())); + flag = true; + break; + } + } + if (!flag) { + res.add(new PageInfoResponse.searchPageDTO.pageDTO(p.getId(), p.getPageName(), "")); } } - - // 6. pages로 DTO return +// Page pages = pageJPARepository.findPagesWithPosts(groupId, keyword, PageRequest.of(pageNo, PAGE_COUNT)); +// +// List res = new ArrayList<>(); +// +// for(PageInfo p : pages.getContent()){ +// if(p.getPosts().size() == 0){ +// System.out.println(p.getId() + " 페이지 : "+ p.getPageName()); +// res.add(new PageInfoResponse.searchPageDTO.pageDTO(p.getId(),p.getPageName(),"")); +// }else{ +// System.out.println(p.getId() + " 페이지 : "+ p.getPageName()+ " : " + p.getPosts().get(0).getContent()); +// res.add(new PageInfoResponse.searchPageDTO.pageDTO(p.getId(),p.getPageName(),p.getPosts().get(0).getContent())); +// } +// } + + // 5. pages로 DTO return DTO return new PageInfoResponse.searchPageDTO(res); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java index bc524112..b688f9ff 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.post; +import com.kakao.techcampus.wekiki.page.PageInfo; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -30,5 +31,7 @@ List findPostsByPageIdAndOrderGreaterThan( @Query("SELECT p FROM Post p WHERE p.pageInfo.id = :pageId AND p.orders = 1") List findFirstPost(@Param("pageId") Long pageId); + @Query("SELECT po FROM Post po WHERE po.pageInfo IN (:pages) AND po.orders = 1") + List findPostInPages(@Param("pages") List pages); } From 5dec00e950c4a22719a31d3fbb5a39bf0b33fadf Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Wed, 8 Nov 2023 12:51:30 +0900 Subject: [PATCH 098/144] =?UTF-8?q?Refactor=20:=20Redis=20=EC=9E=90?= =?UTF-8?q?=EB=A3=8C=EA=B5=AC=EC=A1=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Redis에 String 자료구조로 저장하는 부분을 Hash 자료구조로 저장하도록 수정하였습니다. --- .../wekiki/_core/config/RedisConfig.java | 2 ++ .../wekiki/_core/utils/redis/RedisUtils.java | 17 +++++++++++++++++ .../techcampus/wekiki/page/PageService.java | 16 +++++++++------- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/RedisConfig.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/RedisConfig.java index 2c82e9c3..9b840247 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/RedisConfig.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/RedisConfig.java @@ -37,6 +37,8 @@ public RedisTemplate redisTemplate() { redisTemplate.setKeySerializer(new StringRedisSerializer()); // GenericJackson2JsonRedisSerializer -> 객체를 JSON 형식으로 직렬화 redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashValueSerializer(new StringRedisSerializer()); return redisTemplate; } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/redis/RedisUtils.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/redis/RedisUtils.java index 099c3cda..08b9afde 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/redis/RedisUtils.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/utils/redis/RedisUtils.java @@ -2,6 +2,7 @@ import com.kakao.techcampus.wekiki.group.domain.Invitation; import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; @@ -14,6 +15,7 @@ public class RedisUtils { private final RedisTemplate redisTemplate; + public void setInvitationValues(String key, Invitation invitation, Duration lifetime) { redisTemplate.opsForValue().set(key, invitation, lifetime); } @@ -33,4 +35,19 @@ public Set getKeys(String pattern) { public void deleteValues(String key) { redisTemplate.delete(key); } + + public void saveKeyAndHashValue(String key, String hashKey, String value) { + HashOperations hashOperations = redisTemplate.opsForHash(); + hashOperations.put(key, hashKey, value); + } + + public String getHashValue(String key, String hashKey) { + HashOperations hashOps = redisTemplate.opsForHash(); + return hashOps.get(key, hashKey); + } + + public void deleteHashValue(String key, String hashKey) { + HashOperations hashOps = redisTemplate.opsForHash(); + hashOps.delete(key, hashKey); + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 5845534a..b5fa15ef 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -4,6 +4,7 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.utils.IndexUtils; import com.kakao.techcampus.wekiki._core.utils.RedisUtility; +import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; @@ -41,10 +42,12 @@ public class PageService { private final GroupMemberJPARepository groupMemberJPARepository; private final GroupJPARepository groupJPARepository; private final IndexUtils indexUtils; - private final RedisUtility redisUtility; + private final RedisUtils redisUtils; final int PAGE_COUNT = 10; final int RECENTLY_PAGE_COUNT = 10; + final String GROUP_PREFIX = "GROUP_"; + @Transactional public PageInfoResponse.mainPageDTO getMainPage() { if(SecurityContextHolder.getContext().getAuthentication().getName().equals("anonymousUser")) { @@ -124,7 +127,7 @@ public PageInfoResponse.deletePageDTO deletePage(Long memberId, Long groupId, Lo pageJPARepository.deleteById(pageId); // 5. redis에 페이지 목록 삭제 시켜주기 - redisUtility.deleteValues(groupId+"_"+pageInfo.getPageName()); + redisUtils.deleteHashValue(GROUP_PREFIX+groupId,pageInfo.getPageName()); // 6. return DTO return response; @@ -177,11 +180,10 @@ public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Lon // 5. Page 저장 PageInfo savedPageInfo = pageJPARepository.save(newPageInfo); - // TODO : 추후에 redis value 자료구조를 String에서 Hash로 변경 (key overhead 최소화) - // > - redisUtility.setValues(groupId+"_"+title,newPageInfo.getId().toString()); + // 6. Redis에 Hash 자료구조로 pageID 저장 + redisUtils.saveKeyAndHashValue(GROUP_PREFIX+groupId,title,newPageInfo.getId().toString()); - // 6. return DTO + // 7. return DTO return new PageInfoResponse.createPageDTO(savedPageInfo); } @@ -310,7 +312,7 @@ public PageInfoResponse.getPageFromIdDTO getPageFromTitle(Long memberId, Long gr public PageInfoResponse.getPageLinkDTO getPageLink( Long groupId, String title){ // 1. redis로 groupId_title을 key로 value 받아오기 (페이지 테이블에 접근할 필요 x) - String value = redisUtility.getValues(groupId+"_"+title); + String value = redisUtils.getHashValue(GROUP_PREFIX + groupId, title); if(value == null){ throw new Exception404("존재하지 않는 페이지 입니다."); From 3fbd35d5afab4803b5674a75b2f573921ef11c6c Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Wed, 8 Nov 2023 15:04:17 +0900 Subject: [PATCH 099/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EA=B2=80=EC=83=89=20=EC=8B=9C=20=EC=9D=91=EB=8B=B5=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GroupProfileImage가 아닌 GroupImage로 수정 --- .../com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java index e6bb8af7..09665b41 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java @@ -87,7 +87,7 @@ public SearchGroupDTO(Page officialGroups, Page Date: Wed, 8 Nov 2023 20:02:36 +0900 Subject: [PATCH 100/144] =?UTF-8?q?Feat=20:=20=EC=B9=B4=EC=B9=B4=EC=98=A4?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EA=B5=AC=ED=98=84=20&=20?= =?UTF-8?q?=EC=B9=B4=EC=B9=B4=EC=98=A4=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=ED=94=84=EB=A1=9D=EC=8B=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wekiki/_core/config/ProxyConfig.java | 27 ++++++++++ .../group/domain/member/GroupMember.java | 7 ++- .../techcampus/wekiki/member/Authority.java | 2 +- .../techcampus/wekiki/member/Member.java | 10 +++- .../wekiki/member/MemberController.java | 4 +- .../wekiki/member/MemberRequest.java | 1 + .../wekiki/member/MemberResponse.java | 13 +++++ .../wekiki/member/MemberService.java | 52 ++++++++++++++----- wekiki/src/main/resources/application.yml | 3 +- 9 files changed, 101 insertions(+), 18 deletions(-) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/ProxyConfig.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/ProxyConfig.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/ProxyConfig.java new file mode 100644 index 00000000..b855ba96 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/ProxyConfig.java @@ -0,0 +1,27 @@ +package com.kakao.techcampus.wekiki._core.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +import java.net.InetSocketAddress; +import java.net.Proxy; + +@Profile(value = {"prod"}) +@Configuration +public class ProxyConfig { + private static final String PROXY_HOST = "krmp-proxy.9rum.cc"; + private static final int PROXY_PORT = 3128; + + @Bean + public RestTemplate restTemplateWithProxy() { + SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_HOST, PROXY_PORT)); + requestFactory.setProxy(proxy); + requestFactory.setConnectTimeout(5000); + requestFactory.setReadTimeout(5000); + return new RestTemplate(requestFactory); + } +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/GroupMember.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/GroupMember.java index 1a19aa21..141675c4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/GroupMember.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/GroupMember.java @@ -2,6 +2,7 @@ import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.member.Member; +import com.kakao.techcampus.wekiki.member.MemberService; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -22,7 +23,7 @@ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) private Member member; @ManyToOne(fetch = FetchType.LAZY) private Group group; @@ -41,6 +42,10 @@ public GroupMember(Long id, Member member, Group group, String nickName, LocalDa this.created_at = created_at; } + public void changeMember(Member member) { + this.member = member; + } + // 그룹 내 정보 변경 public void update(String groupNickName) { this.nickName = groupNickName; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Authority.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Authority.java index f8b4d4fc..9569290a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Authority.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Authority.java @@ -1,5 +1,5 @@ package com.kakao.techcampus.wekiki.member; public enum Authority { - admin, user + admin, user, none } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java index 80b67cb3..95a6c38c 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.member; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; @@ -27,7 +28,7 @@ public class Member { private String password; private LocalDateTime created_at; - @OneToMany(mappedBy = "member", cascade = CascadeType.REMOVE) + @OneToMany(mappedBy = "member") private List groupMembers = new ArrayList<>(); @Enumerated(value = EnumType.STRING) @@ -49,4 +50,11 @@ public void changePassword(String password) { public void changeNickName(String name) { this.name = name; } + + public void delete(String randomPassword) { + this.name = ""; + this.email = ""; + this.password = randomPassword; + this.authority = Authority.none; + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java index daeaf0a4..25a36892 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java @@ -25,8 +25,8 @@ public ResponseEntity signIn(@RequestBody MemberRequest.loginRequestDTO login @GetMapping("/kakao/signin") public ResponseEntity kakaoLogin(@RequestParam String code) { - memberService.getKakaoInfo(code); - return ResponseEntity.ok(true); + MemberResponse.authTokenDTO response = memberService.getKakaoInfo(code); + return ResponseEntity.ok(ApiUtils.success(response)); } @GetMapping("/myinfo") diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java index f8085230..e45cbba8 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java @@ -13,6 +13,7 @@ public static class signUpRequestDTO { } @Getter + @AllArgsConstructor public static class loginRequestDTO { private String email; private String password; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java index 4bdcc0f5..76a7c28e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java @@ -12,16 +12,29 @@ public class MemberResponse { @Getter + @NoArgsConstructor @AllArgsConstructor public static class KakaoTokenDTO{ + private String id_token; private String token_type; private String access_token; private int expires_in; private String refresh_token; private String refresh_token_expires_in; + private String scope; } + @Getter + @AllArgsConstructor + @NoArgsConstructor public static class KakaoInfoDTO { + Long id; + Properties properties; + + @Getter + public class Properties { + private String nickname; + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index ceb9947d..1f33d42d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -1,15 +1,15 @@ package com.kakao.techcampus.wekiki.member; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.util.JSONPObject; import com.kakao.techcampus.wekiki._core.error.exception.*; import com.kakao.techcampus.wekiki._core.jwt.JWTTokenProvider; import com.kakao.techcampus.wekiki._core.utils.RedisUtility; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.tomcat.util.json.JSONParser; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -51,6 +51,8 @@ public class MemberService { private String KAKAO_CLIENT_ID; @Value("${kakao.redirect.uri}") private String KAKAO_REDIRECT_URI; + @Value("${kakao.client.password") + private String KAKAO_PASSWORD; public void signUp(MemberRequest.signUpRequestDTO signUpRequestDTO) { @@ -111,6 +113,13 @@ public void cancel() { log.error("Access Token에서 뽑아낸 회원이 존재하지 않는 회원입니다. (회원 탈퇴)"); throw e; } + Member cancelMember = new Member("알수없음", "", passwordEncoder.encode(makeRandomPassword()), + LocalDateTime.now(), Authority.none); + for (GroupMember g : member.getGroupMembers()) { + g.update("알수없음"); + g.changeMember(cancelMember); + } + //member.delete(passwordEncoder.encode(makeRandomPassword())); memberRepository.delete(member); } @@ -218,8 +227,8 @@ private Member findMember() { return member.get(); } - public void getKakaoInfo(String code) { - + public MemberResponse.authTokenDTO getKakaoInfo(String code) { + //리팩토링 대상...!! String accessToken = ""; try{ @@ -242,17 +251,35 @@ public void getKakaoInfo(String code) { String.class ); - ObjectMapper objectMapper = new ObjectMapper(); + System.out.println(response.getBody()); + ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); MemberResponse.KakaoTokenDTO kakaoTokenDTO = objectMapper.readValue(response.getBody(), MemberResponse.KakaoTokenDTO.class); accessToken = kakaoTokenDTO.getAccess_token(); } catch (JsonProcessingException e) { - throw new Exception500("Json 파싱 에러입니다." + e); + log.error("파싱 오류", e); + throw new Exception500("Json 파싱 에러입니다."); } - getUserInfoWithToken(accessToken); + + MemberResponse.KakaoInfoDTO kakaoInfo = getUserInfoWithToken(accessToken); + String kakaoEmail = kakaoInfo.getId() + "@wekiki.com"; + Optional kakaoMember = memberRepository.findByEmail(kakaoEmail); + if(kakaoMember.isEmpty()){ + Member member = Member.builder() + .name(kakaoInfo.getProperties().getNickname()) + .email(kakaoEmail) + .password(passwordEncoder.encode(KAKAO_PASSWORD)) + .created_at(LocalDateTime.now()) + .authority(Authority.user) + .build(); + memberRepository.save(member); + } + MemberRequest.loginRequestDTO kakaoLogin = new MemberRequest.loginRequestDTO(kakaoEmail,KAKAO_PASSWORD); + return login(kakaoLogin); } - private void getUserInfoWithToken(String accessToken) { + private MemberResponse.KakaoInfoDTO getUserInfoWithToken(String accessToken) { + MemberResponse.KakaoInfoDTO kakaoInfo = null; RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); @@ -270,12 +297,13 @@ private void getUserInfoWithToken(String accessToken) { System.out.println(response.getBody()); - /*ObjectMapper objectMapper = new ObjectMapper(); + ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); try { - objectMapper.readValue(response.getBody()); + kakaoInfo = objectMapper.readValue(response.getBody(),MemberResponse.KakaoInfoDTO.class); } catch (JsonProcessingException e) { throw new Exception500("Json 파싱 에러입니다." + e); - }*/ + } + return kakaoInfo; } } diff --git a/wekiki/src/main/resources/application.yml b/wekiki/src/main/resources/application.yml index c4f3ccac..70e3f0a2 100644 --- a/wekiki/src/main/resources/application.yml +++ b/wekiki/src/main/resources/application.yml @@ -38,8 +38,9 @@ jwt: kakao: client: id: 08e6c709229f3b44a8cff2fc7168e1a2 + password: haaland09 redirect: - uri: http://3.39.150.229:8080/auth/kakao/signin + uri: http://localhost:3000/auth/kakao/signin logging: level: '[com.example.kakao]': DEBUG From fc042167f102fa8eb17a7696edcf93c3f2625441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=8F=84=EB=88=84?= Date: Wed, 8 Nov 2023 20:21:42 +0900 Subject: [PATCH 101/144] Update application.yml --- wekiki/src/main/resources/application.yml | 48 +---------------------- 1 file changed, 1 insertion(+), 47 deletions(-) diff --git a/wekiki/src/main/resources/application.yml b/wekiki/src/main/resources/application.yml index 70e3f0a2..d9638774 100644 --- a/wekiki/src/main/resources/application.yml +++ b/wekiki/src/main/resources/application.yml @@ -1,50 +1,4 @@ spring: - datasource: - url: jdbc:h2:mem:test;MODE=MariaDB - driver-class-name: org.h2.Driver - username: sa - password: - h2: - console: - enabled: true - jpa: - hibernate: - ddl-auto: create - show-sql: true - properties: - hibernate: - format_sql: true - default_batch_fetch_size: 100 - open-in-view: false - data: - storage-type: redis - redis: - host: localhost - port: 6379 - password: zinc - mail: - host: smtp.gmail.com - port: 587 - username: ljh19980823@gmail.com - password: yyzdbabwrmhhvyhi - properties: - mail: - smtp: - auth: true - starttls: - enable: true -jwt: - secret: 7ZmA656AIOuTneygkOyZlSDquLDsm5AgMeydvOywqALdlsKJL3234jklsdjfaKJDLnflkasdf -kakao: - client: - id: 08e6c709229f3b44a8cff2fc7168e1a2 - password: haaland09 - redirect: - uri: http://localhost:3000/auth/kakao/signin -logging: - level: - '[com.example.kakao]': DEBUG - '[org.hibernate.type]': TRACE profiles: active: - - local \ No newline at end of file + - local From 7e396d3e069370a4f31bf93a7a1c61853a87d074 Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Wed, 8 Nov 2023 20:46:30 +0900 Subject: [PATCH 102/144] =?UTF-8?q?Feat=20:=20=EB=A9=94=EC=9D=BC=20proxy?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wekiki/member/MemberService.java | 24 +++++++++---------- wekiki/src/main/resources/application.yml | 4 ++++ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index 1f33d42d..e7aba2c3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -6,7 +6,6 @@ import com.kakao.techcampus.wekiki._core.error.exception.*; import com.kakao.techcampus.wekiki._core.jwt.JWTTokenProvider; import com.kakao.techcampus.wekiki._core.utils.RedisUtility; -import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -228,7 +227,6 @@ private Member findMember() { } public MemberResponse.authTokenDTO getKakaoInfo(String code) { - //리팩토링 대상...!! String accessToken = ""; try{ @@ -250,8 +248,6 @@ public MemberResponse.authTokenDTO getKakaoInfo(String code) { httpEntity, String.class ); - - System.out.println(response.getBody()); ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); MemberResponse.KakaoTokenDTO kakaoTokenDTO = objectMapper.readValue(response.getBody(), MemberResponse.KakaoTokenDTO.class); accessToken = kakaoTokenDTO.getAccess_token(); @@ -265,19 +261,23 @@ public MemberResponse.authTokenDTO getKakaoInfo(String code) { String kakaoEmail = kakaoInfo.getId() + "@wekiki.com"; Optional kakaoMember = memberRepository.findByEmail(kakaoEmail); if(kakaoMember.isEmpty()){ - Member member = Member.builder() - .name(kakaoInfo.getProperties().getNickname()) - .email(kakaoEmail) - .password(passwordEncoder.encode(KAKAO_PASSWORD)) - .created_at(LocalDateTime.now()) - .authority(Authority.user) - .build(); - memberRepository.save(member); + kakaoSignUp(kakaoInfo, kakaoEmail); } MemberRequest.loginRequestDTO kakaoLogin = new MemberRequest.loginRequestDTO(kakaoEmail,KAKAO_PASSWORD); return login(kakaoLogin); } + private void kakaoSignUp(MemberResponse.KakaoInfoDTO kakaoInfo, String kakaoEmail) { + Member member = Member.builder() + .name(kakaoInfo.getProperties().getNickname()) + .email(kakaoEmail) + .password(passwordEncoder.encode(KAKAO_PASSWORD)) + .created_at(LocalDateTime.now()) + .authority(Authority.user) + .build(); + memberRepository.save(member); + } + private MemberResponse.KakaoInfoDTO getUserInfoWithToken(String accessToken) { MemberResponse.KakaoInfoDTO kakaoInfo = null; RestTemplate restTemplate = new RestTemplate(); diff --git a/wekiki/src/main/resources/application.yml b/wekiki/src/main/resources/application.yml index 70e3f0a2..175851ff 100644 --- a/wekiki/src/main/resources/application.yml +++ b/wekiki/src/main/resources/application.yml @@ -33,6 +33,10 @@ spring: auth: true starttls: enable: true + required: true + proxy: + host: krmp-proxy.9rum.cc + port: 3182 jwt: secret: 7ZmA656AIOuTneygkOyZlSDquLDsm5AgMeydvOywqALdlsKJL3234jklsdjfaKJDLnflkasdf kakao: From 8952802d647ce5a2ddab1dd0fac42a48b47d02ac Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Wed, 8 Nov 2023 22:43:38 +0900 Subject: [PATCH 103/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EB=A9=A4=EB=B2=84=20=EA=B0=9D=EC=B2=B4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ActiveGroupMember, InactiveGroupMember 삭제 - boolean ActiveStatus를 통한 관리 --- .../techcampus/wekiki/comment/Comment.java | 2 +- .../wekiki/comment/CommentJPARepository.java | 3 - .../wekiki/comment/CommentResponse.java | 2 +- .../wekiki/comment/CommentService.java | 17 +-- .../techcampus/wekiki/group/domain/Group.java | 12 +- .../domain/{member => }/GroupMember.java | 12 +- .../domain/member/ActiveGroupMember.java | 31 ---- .../domain/member/InactiveGroupMember.java | 34 ----- .../wekiki/group/dto/GroupResponseDTO.java | 7 +- .../repository/GroupMemberJPARepository.java | 21 ++- .../wekiki/group/service/GroupService.java | 144 +++++++++--------- .../techcampus/wekiki/history/History.java | 2 +- .../wekiki/history/HistoryJPARepository.java | 1 - .../techcampus/wekiki/member/Member.java | 3 +- .../wekiki/member/MemberRequest.java | 2 + .../wekiki/member/MemberResponse.java | 2 +- .../wekiki/member/MemberService.java | 3 +- .../wekiki/page/PageJPARepository.java | 2 + .../techcampus/wekiki/page/PageService.java | 11 +- .../kakao/techcampus/wekiki/post/Post.java | 2 +- .../techcampus/wekiki/post/PostResponse.java | 2 +- .../techcampus/wekiki/post/PostService.java | 17 +-- .../techcampus/wekiki/report/Report.java | 2 +- .../wekiki/report/ReportJPARepository.java | 3 - 24 files changed, 133 insertions(+), 204 deletions(-) rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/{member => }/GroupMember.java (79%) delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/ActiveGroupMember.java delete mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/InactiveGroupMember.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java index 78b0a3f0..7273209d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java @@ -1,6 +1,6 @@ package com.kakao.techcampus.wekiki.comment; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.*; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java index beafcfdf..819e4bd5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java @@ -1,8 +1,5 @@ package com.kakao.techcampus.wekiki.comment; -import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; -import com.kakao.techcampus.wekiki.post.Post; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java index 23bac93d..71d109e7 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java @@ -1,6 +1,6 @@ package com.kakao.techcampus.wekiki.comment; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import com.kakao.techcampus.wekiki.post.Post; import lombok.Getter; import lombok.Setter; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java index c30f16fe..7dd31f6f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java @@ -2,18 +2,15 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; -import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; -import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; -import com.kakao.techcampus.wekiki.member.Member; import com.kakao.techcampus.wekiki.member.MemberJPARepository; import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -37,7 +34,7 @@ public class CommentService { public CommentResponse.getCommentDTO getComment(Long memberId, Long groupId, Long postId, int pageNo){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); + GroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. post 존재하는지 예외처리 Post post = checkPostFromPostId(postId); @@ -56,7 +53,7 @@ public CommentResponse.getCommentDTO getComment(Long memberId, Long groupId, Lon public CommentResponse.createCommentDTO createComment(Long memberId, Long groupId, Long postId, String content){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); + GroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. post 존재하는지 예외처리 Post post = checkPostFromPostId(postId); @@ -78,7 +75,7 @@ public CommentResponse.createCommentDTO createComment(Long memberId, Long groupI public CommentResponse.deleteCommentDTO deleteComment(Long memberId, Long groupId, Long commentId){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); + GroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. comment 존재하는지 예외처리 Comment comment = checkCommentFromCommentId(commentId); @@ -100,7 +97,7 @@ public CommentResponse.deleteCommentDTO deleteComment(Long memberId, Long groupI public CommentResponse.updateCommentDTO updateComment(Long memberId, Long groupId, Long commentId, String updateContent){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); + GroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. comment 존재하는지 예외처리 Comment comment = checkCommentFromCommentId(commentId); @@ -123,9 +120,9 @@ public CommentResponse.updateCommentDTO updateComment(Long memberId, Long groupI } - public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ + public GroupMember checkGroupMember(Long memberId, Long groupId){ - ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) + GroupMember activeGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); if(activeGroupMember.getMember() == null) throw new Exception404("존재하지 않는 회원입니다."); if(activeGroupMember.getGroup() == null) throw new Exception404("존재하지 않는 그룹입니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java index a0887262..277951b5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java @@ -1,6 +1,5 @@ package com.kakao.techcampus.wekiki.group.domain; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -42,6 +41,15 @@ public Group(Long id, String groupName, String groupProfileImage, LocalDateTime public void addGroupMember(GroupMember groupMember) { this.groupMembers.add(groupMember); - this.memberCount = this.groupMembers.size(); + this.memberCount++; + } + + public void minusMemberCount() { + this.memberCount--; + } + + public void removeGroupMember(GroupMember groupMember) { + this.groupMembers.remove(groupMember); + minusMemberCount(); } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/GroupMember.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/GroupMember.java similarity index 79% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/GroupMember.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/GroupMember.java index 141675c4..5e6a2856 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/GroupMember.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/GroupMember.java @@ -1,8 +1,6 @@ -package com.kakao.techcampus.wekiki.group.domain.member; +package com.kakao.techcampus.wekiki.group.domain; -import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.member.Member; -import com.kakao.techcampus.wekiki.member.MemberService; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -14,9 +12,7 @@ @Getter @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Inheritance(strategy = InheritanceType.JOINED) @Table(name = "group_member_tb") -@DiscriminatorColumn(name = "member_status", discriminatorType = DiscriminatorType.STRING) public class GroupMember { @@ -31,6 +27,7 @@ private String nickName; private int memberLevel; private LocalDateTime created_at; + boolean activeStatus; @Builder public GroupMember(Long id, Member member, Group group, String nickName, LocalDateTime created_at) { @@ -40,6 +37,7 @@ public GroupMember(Long id, Member member, Group group, String nickName, LocalDa this.nickName = nickName; this.memberLevel = 1; this.created_at = created_at; + this.activeStatus = true; } public void changeMember(Member member) { @@ -50,4 +48,8 @@ public void changeMember(Member member) { public void update(String groupNickName) { this.nickName = groupNickName; } + + public void changeStatus() { + this.activeStatus = !this.activeStatus; + } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/ActiveGroupMember.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/ActiveGroupMember.java deleted file mode 100644 index 7853b4fb..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/ActiveGroupMember.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.kakao.techcampus.wekiki.group.domain.member; - -import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.member.Member; -import jakarta.persistence.DiscriminatorValue; -import jakarta.persistence.Entity; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@Getter -@Entity -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@DiscriminatorValue("active_group_member") -public class ActiveGroupMember extends GroupMember { - - @Builder(builderMethodName = "activeGroupMemberBuilder") - public ActiveGroupMember(Long id, Member member, Group group, String nickName, LocalDateTime created_at) { - super(id, member, group, nickName, created_at); - } - - /* - 그룹 멤버 재가입 - */ - public ActiveGroupMember(InactiveGroupMember groupMember) { - super(groupMember.getId(), groupMember.getMember(), groupMember.getGroup(), groupMember.getNickName(), groupMember.getCreated_at()); - } -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/InactiveGroupMember.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/InactiveGroupMember.java deleted file mode 100644 index 18862943..00000000 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/InactiveGroupMember.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.kakao.techcampus.wekiki.group.domain.member; - -import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.member.Member; -import jakarta.persistence.DiscriminatorValue; -import jakarta.persistence.Entity; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -@Getter -@Entity -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@DiscriminatorValue("inactive_group_member") -public class InactiveGroupMember extends GroupMember { - private LocalDateTime left_at; - - @Builder(builderMethodName = "inactiveGroupMemberBuilder") - public InactiveGroupMember(Long id, Member member, Group group, String nickName, LocalDateTime created_at, LocalDateTime left_at) { - super(id, member, group, nickName, created_at); - this.left_at = left_at; - } - - /* - 그룹 멤버 탈퇴 전환 - */ - public InactiveGroupMember(ActiveGroupMember groupMember) { - super(groupMember.getId(), groupMember.getMember(), groupMember.getGroup(), groupMember.getNickName(), groupMember.getCreated_at()); - this.left_at = LocalDateTime.now(); - } -} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java index 09665b41..bff94af5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java @@ -1,12 +1,10 @@ package com.kakao.techcampus.wekiki.group.dto; -import com.kakao.techcampus.wekiki.group.GroupType; import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.group.domain.Invitation; import com.kakao.techcampus.wekiki.group.domain.OfficialGroup; import com.kakao.techcampus.wekiki.group.domain.UnOfficialOpenedGroup; -import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import com.kakao.techcampus.wekiki.history.History; import jakarta.persistence.DiscriminatorValue; import org.springframework.data.domain.Page; @@ -139,8 +137,7 @@ public SearchGroupInfoDTO(Group group) { public record GetGroupMembersResponseDTO(List nickNames) { public GetGroupMembersResponseDTO(Group group) { this(group.getGroupMembers().stream() - .filter(groupMember -> groupMember instanceof ActiveGroupMember) - .map(groupMember -> groupMember.getNickName()) + .map(GroupMember::getNickName) .collect(Collectors.toList())); } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java index fb7c63d5..6eaabfa9 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java @@ -1,30 +1,27 @@ package com.kakao.techcampus.wekiki.group.repository; -import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; -import com.kakao.techcampus.wekiki.group.domain.member.InactiveGroupMember; -import com.kakao.techcampus.wekiki.member.Member; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.util.List; import java.util.Optional; @Repository public interface GroupMemberJPARepository extends JpaRepository { - @Query("SELECT iagm FROM InactiveGroupMember iagm WHERE iagm.member = :member AND iagm.group = :group") - InactiveGroupMember findInactiveGroupMemberByMemberAndGroup(@Param("member") Member member, @Param("group") Group group); - - @Query("SELECT agm FROM ActiveGroupMember agm WHERE agm.member.id = :memberId AND agm.group.id = :groupId") - Optional findActiveGroupMemberByMemberIdAndGroupId(@Param("memberId") Long memberId, @Param("groupId") Long groupId); @Query("SELECT gm FROM GroupMember gm WHERE gm.group.id = :groupId AND gm.nickName = :nickName") Optional findGroupMemberByNickName(@Param("groupId") Long groupId, @Param("nickName") String nickName); // 여기다 멤버 group fetchjoin - @Query("SELECT agm FROM ActiveGroupMember agm LEFT JOIN FETCH agm.member LEFT JOIN FETCH agm.group WHERE agm.member.id = :memberId AND agm.group.id = :groupId") - Optional findActiveGroupMemberByMemberIdAndGroupIdFetchJoin(@Param("memberId") Long memberId, @Param("groupId") Long groupId); + @Query("SELECT gm FROM GroupMember gm LEFT JOIN FETCH gm.member LEFT JOIN FETCH gm.group WHERE gm.member.id = :memberId AND gm.group.id = :groupId") + Optional findGroupMemberByMemberIdAndGroupIdFetchJoin(@Param("memberId") Long memberId, @Param("groupId") Long groupId); + + @Query("SELECT gm FROM GroupMember gm WHERE gm.member.id = :memberId AND gm.group.id = :groupId") + GroupMember findGroupMemberByMemberIdAndGroupId(@Param("memberId") Long memberId, @Param("groupId") Long groupId); + @Query("SELECT gm FROM GroupMember gm WHERE gm.group.id = :id") + List findAllByGroupId(@Param("id") Long id); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 0e925fe3..65638d10 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -7,13 +7,11 @@ import com.kakao.techcampus.wekiki.comment.Comment; import com.kakao.techcampus.wekiki.comment.CommentJPARepository; import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import com.kakao.techcampus.wekiki.group.dto.GroupRequestDTO; import com.kakao.techcampus.wekiki.group.dto.GroupResponseDTO; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; -import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; -import com.kakao.techcampus.wekiki.group.domain.member.InactiveGroupMember; import com.kakao.techcampus.wekiki.group.domain.OfficialGroup; import com.kakao.techcampus.wekiki.group.domain.UnOfficialClosedGroup; import com.kakao.techcampus.wekiki.group.domain.UnOfficialOpenedGroup; @@ -21,6 +19,8 @@ import com.kakao.techcampus.wekiki.history.HistoryJPARepository; import com.kakao.techcampus.wekiki.member.Member; import com.kakao.techcampus.wekiki.member.MemberJPARepository; +import com.kakao.techcampus.wekiki.page.PageInfo; +import com.kakao.techcampus.wekiki.page.PageJPARepository; import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; import com.kakao.techcampus.wekiki.report.Report; @@ -49,6 +49,7 @@ public class GroupService { private final GroupJPARepository groupJPARepository; private final GroupMemberJPARepository groupMemberJPARepository; private final MemberJPARepository memberJPARepository; + private final PageJPARepository pageJPARepository; private final PostJPARepository postJPARepository; private final HistoryJPARepository historyJPARepository; private final CommentJPARepository commentJPARepository; @@ -74,7 +75,7 @@ public GroupResponseDTO.CreateUnOfficialGroupResponseDTO createUnOfficialGroup(G // MemberId로부터 Member 찾기 Member member = getMemberById(memberId); // GroupMember 생성 - ActiveGroupMember groupMember = buildGroupMember(member, group, requestDTO.groupNickName()); + GroupMember groupMember = buildGroupMember(member, group, requestDTO.groupNickName()); // Entity 저장 group.addGroupMember(groupMember); @@ -125,8 +126,8 @@ protected UnOfficialOpenedGroup buildUnOfficialOpenedGroup(GroupRequestDTO.Creat /* GroupMember 생성 후 반환 */ - protected ActiveGroupMember buildGroupMember(Member member, Group group, String groupNickName) { - return ActiveGroupMember.activeGroupMemberBuilder() + protected GroupMember buildGroupMember(Member member, Group group, String groupNickName) { + return GroupMember.builder() .member(member) .group(group) .nickName(groupNickName) @@ -255,31 +256,26 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ checkJoinPermission(memberId, groupId); // 그룹 내 닉네임 중복 예외 처리 - groupNickNameCheck(groupId, requestDTO.nickName()); + String groupNickName = requestDTO.nickName(); + groupNickNameCheck(groupId, groupNickName); - // 이미 가입한 상태일 시 예외 처리 - if (groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId).isPresent()) { - throw new Exception400("이미 가입된 회원입니다."); - } - - // 재가입 회원인지 확인 - InactiveGroupMember wasGroupMember = groupMemberJPARepository.findInactiveGroupMemberByMemberAndGroup(member, group); - - // 재가입 회원이면 활성화, 신규 회원이면 새로 생성 - ActiveGroupMember groupMember = wasGroupMember != null ? new ActiveGroupMember(wasGroupMember) : buildGroupMember(member, group, requestDTO.nickName()); + GroupMember wasGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId, groupId); if(wasGroupMember != null) { - changeAuthorization(wasGroupMember, groupMember); + // 이미 가입한 상태일 시 예외 처리 + if(wasGroupMember.isActiveStatus()) { + throw new Exception400("이미 가입된 회원입니다."); + } + + // 재가입 회원인지 확인 + wasGroupMember.changeStatus(); + + // GroupMember 저장 + saveGroupMember(member, group, wasGroupMember); + } else { + saveGroupMember(member, group, buildGroupMember(member, group, groupNickName)); } - // GroupMember 저장 - group.addGroupMember(groupMember); - member.getGroupMembers().add(groupMember); - - groupJPARepository.save(group); - memberJPARepository.save(member); - groupMemberJPARepository.save(groupMember); - } catch (Exception400 | Exception404 e) { throw e; } catch (Exception e) { @@ -287,6 +283,16 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ } } + private void saveGroupMember(Member member, Group group, GroupMember groupMember) { + // GroupMember 저장 + group.addGroupMember(groupMember); + member.getGroupMembers().add(groupMember); + + groupJPARepository.save(group); + memberJPARepository.save(member); + groupMemberJPARepository.save(groupMember); + } + protected void checkJoinPermission(Long memberId, Long groupId) { Object oGroupId = Optional.ofNullable(redisUtils.getValues(MEMBER_ID_PREFIX + memberId)) .orElseThrow(() -> new Exception404("해당 그룹에 가입할 수 없습니다.")); @@ -323,7 +329,7 @@ public GroupResponseDTO.GetGroupMembersResponseDTO getGroupMembers(Long groupId, public GroupResponseDTO.MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { try { // 그룹 멤버 확인 - ActiveGroupMember groupMember = getActiveGroupMember(groupId, memberId); + GroupMember groupMember = getActiveGroupMember(groupId, memberId); // 해당 멤버의 Post 기록 정보 확인(History에서 가져옴) Pageable pageable = PageRequest.of(0, 10); @@ -345,7 +351,7 @@ public GroupResponseDTO.MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long public GroupResponseDTO.MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, int page, int size) { try { // 그룹 멤버 확인 - ActiveGroupMember groupMember = getActiveGroupMember(groupId, memberId); + GroupMember groupMember = getActiveGroupMember(groupId, memberId); Pageable pageable = PageRequest.of(page, size); Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember.getId(), pageable); @@ -367,7 +373,7 @@ public GroupResponseDTO.MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId public void updateMyGroupPage(Long groupId, Long memberId, GroupRequestDTO.UpdateMyGroupPageDTO requestDTO) { try { // 그룹 멤버 확인 - ActiveGroupMember groupMember = getActiveGroupMember(groupId, memberId); + GroupMember groupMember = getActiveGroupMember(groupId, memberId); // 변경할 닉네임 확인 String newNickName = requestDTO.groupNickName(); @@ -404,56 +410,52 @@ public void updateMyGroupPage(Long groupId, Long memberId, GroupRequestDTO.Updat */ @Transactional public void leaveGroup(Long groupId, Long memberId) { - try { - ActiveGroupMember activeGroupMember = getActiveGroupMember(groupId, memberId); + GroupMember groupMember = getActiveGroupMember(groupId, memberId); - Member member = getMemberById(memberId); - Group group = getGroupById(groupId); + Group group = getGroupById(groupId); - member.getGroupMembers().remove(activeGroupMember); - group.getGroupMembers().remove(activeGroupMember); + if(group.getMemberCount() != 1) { + group.minusMemberCount(); + groupMember.changeStatus(); - // 탈퇴 그룹 회원 생성 - InactiveGroupMember inactiveGroupMember = new InactiveGroupMember(activeGroupMember); - - changeAuthorization(activeGroupMember, inactiveGroupMember); - - groupMemberJPARepository.save(inactiveGroupMember); + groupJPARepository.save(group); + groupMemberJPARepository.save(groupMember); - } catch (Exception404 e) { - throw e; - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); + } else { + deleteGroup(group); } } - private void changeAuthorization(GroupMember originGroupMember, GroupMember targetGroupMember) { + private void deleteGroup(Group group) { + List groupMemberList = groupMemberJPARepository.findAllByGroupId(group.getId()); - Long originGroupMemberId = originGroupMember.getId(); + for (GroupMember groupMember : groupMemberList) { + Long groupMemberId = groupMember.getId(); - // Post의 그룹 멤버 변경 - List postList = postJPARepository.findAllByGroupMember(originGroupMemberId); - postList.forEach(p -> p.updateGroupMember(targetGroupMember)); + List historyList = historyJPARepository.findAllByGroupMemberId(groupMemberId); + historyJPARepository.deleteAll(historyList); - // History 그룹 멤버 변경 - List historyList = historyJPARepository.findAllByGroupMemberId(originGroupMemberId); - historyList.forEach(h -> h.updateGroupMember(targetGroupMember)); + List reportList = reportJPARepository.findAllByFromMemberId(groupMemberId); + reportJPARepository.deleteAll(reportList); - // Comment 그룹 멤버 변경 - List commentList = commentJPARepository.findAllByGroupMemberId(originGroupMemberId); - commentList.forEach(c -> c.updateGroupMember(targetGroupMember)); + List commentList = commentJPARepository.findAllByGroupMemberId(groupMemberId); + commentJPARepository.deleteAll(commentList); - // Reposrt 그룹 멤버 변경 - List reportList = reportJPARepository.findAllByFromMemberId(originGroupMemberId); - reportList.forEach(r -> r.updateGroupMember(targetGroupMember)); + List postList = postJPARepository.findAllByGroupMember(groupMemberId); + postJPARepository.deleteAll(postList); - // DB 작업 - groupMemberJPARepository.delete(originGroupMember); + List pageInfoList = pageJPARepository.findAllByGroupMember(group.getId()); + pageJPARepository.deleteAll(pageInfoList); - postJPARepository.saveAll(postList); - historyJPARepository.saveAll(historyList); - commentJPARepository.saveAll(commentList); - reportJPARepository.saveAll(reportList); + Member member = groupMember.getMember(); + member.getGroupMembers().remove(groupMember); + memberJPARepository.save(member); + + group.removeGroupMember(groupMember); + groupMemberJPARepository.delete(groupMember); + } + + groupJPARepository.delete(group); } protected Member getMemberById(Long memberId) { @@ -464,10 +466,14 @@ protected Group getGroupById(Long groupId) { return groupJPARepository.findById(groupId).orElseThrow(() -> new Exception404("해당 그룹을 찾을 수 없습니다.")); } - private ActiveGroupMember getActiveGroupMember(Long groupId, Long memberId) { - // 그룹 멤버 확인 - return groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) - .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다")); + private GroupMember getActiveGroupMember(Long groupId, Long memberId) { + GroupMember groupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId, groupId); + + if (groupMember == null || !groupMember.isActiveStatus()) { + throw new Exception404("해당 그룹에 속한 회원이 아닙니다."); + } + + return groupMember; } protected void groupNickNameCheck(Long groupId, String groupNickName) { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java index f2c3f448..3dc299b0 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java @@ -1,6 +1,6 @@ package com.kakao.techcampus.wekiki.history; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.*; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java index 48885067..3ae813a8 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java @@ -1,6 +1,5 @@ package com.kakao.techcampus.wekiki.history; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java index 95a6c38c..7d1f76d1 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java @@ -1,7 +1,6 @@ package com.kakao.techcampus.wekiki.member; -import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import lombok.AccessLevel; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java index e45cbba8..77ac6a02 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java @@ -2,6 +2,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; @AllArgsConstructor public class MemberRequest { @@ -14,6 +15,7 @@ public static class signUpRequestDTO { @Getter @AllArgsConstructor + @NoArgsConstructor public static class loginRequestDTO { private String email; private String password; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java index 76a7c28e..7c730d80 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index 1f33d42d..a7146924 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -6,8 +6,7 @@ import com.kakao.techcampus.wekiki._core.error.exception.*; import com.kakao.techcampus.wekiki._core.jwt.JWTTokenProvider; import com.kakao.techcampus.wekiki._core.utils.RedisUtility; -import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java index ea384a53..e72c31a3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java @@ -38,4 +38,6 @@ public interface PageJPARepository extends JpaRepository { @Query("SELECT p FROM PageInfo p WHERE p.group.id = :groupId AND p.pageName LIKE %:keyword% ") Page findPages(@Param("groupId") Long groupId, @Param("keyword") String keyword, Pageable pageable); + @Query("SELECT p FROM PageInfo p WHERE p.group.id = :groupId") + List findAllByGroupMember(@Param("groupId") Long groupId); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index e9bde633..335af306 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -3,12 +3,10 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.utils.IndexUtils; -import com.kakao.techcampus.wekiki._core.utils.RedisUtility; import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; -import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.member.Member; import com.kakao.techcampus.wekiki.member.MemberJPARepository; @@ -16,7 +14,6 @@ import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; @@ -173,7 +170,7 @@ public PageInfoResponse.getPageFromIdDTO getPageFromId(Long memberId,Long groupI public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Long memberId){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); + GroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. 그룹 내 동일한 title의 Page가 존재하는지 체크 if(pageJPARepository.findByTitle(groupId,title).isPresent()){ @@ -337,9 +334,9 @@ public PageInfoResponse.getPageLinkDTO getPageLink( Long groupId, String title){ } - public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ + public GroupMember checkGroupMember(Long memberId, Long groupId){ - ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) + GroupMember activeGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); if(activeGroupMember.getMember() == null) throw new Exception404("존재하지 않는 회원입니다."); if(activeGroupMember.getGroup() == null) throw new Exception404("존재하지 않는 그룹입니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java index 4e02221b..958f6193 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java @@ -1,7 +1,7 @@ package com.kakao.techcampus.wekiki.post; import com.kakao.techcampus.wekiki.comment.Comment; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.page.PageInfo; import jakarta.persistence.*; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java index 6d64680e..a4315b31 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java @@ -1,6 +1,6 @@ package com.kakao.techcampus.wekiki.post; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.report.Report; import lombok.Getter; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index 6512284d..13e58d16 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -3,15 +3,10 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; -import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; -import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.history.HistoryJPARepository; -import com.kakao.techcampus.wekiki.member.Member; -import com.kakao.techcampus.wekiki.member.MemberJPARepository; import com.kakao.techcampus.wekiki.page.PageInfo; import com.kakao.techcampus.wekiki.page.PageJPARepository; import com.kakao.techcampus.wekiki.report.Report; @@ -41,7 +36,7 @@ public class PostService { public PostResponse.createPostDTO createPost(Long memberId,Long groupId,Long pageId, Long parentPostId, int order, String title, String content){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); + GroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. pageId로 PageInfo 객체 들고오기 PageInfo pageInfo = checkPageFromPageId(pageId); @@ -84,7 +79,7 @@ public PostResponse.createPostDTO createPost(Long memberId,Long groupId,Long pag public PostResponse.modifyPostDTO modifyPost(Long memberId , Long groupId, Long postId , String title, String content){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); + GroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. postId로 post 엔티티 가져오기 Post post = checkPostFromPostId(postId); @@ -152,7 +147,7 @@ public PostResponse.deletePostDTO deletePost(Long memberId, Long groupId, Long p public PostResponse.createReportDTO createReport(Long memberId, Long groupId, Long postId , String content){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); + GroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. postId로 post 엔티티 가져오기 checkPostFromPostId(postId); @@ -175,9 +170,9 @@ public PostResponse.createReportDTO createReport(Long memberId, Long groupId, Lo } - public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ + public GroupMember checkGroupMember(Long memberId, Long groupId){ - ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) + GroupMember activeGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); if(activeGroupMember.getMember() == null) throw new Exception404("존재하지 않는 회원입니다."); if(activeGroupMember.getGroup() == null) throw new Exception404("존재하지 않는 그룹입니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java index c830ebe6..d114ff7d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java @@ -1,6 +1,6 @@ package com.kakao.techcampus.wekiki.report; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.GroupMember; import com.kakao.techcampus.wekiki.history.History; import jakarta.persistence.*; import lombok.AccessLevel; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java index 4323e9f5..1425b814 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java @@ -1,8 +1,5 @@ package com.kakao.techcampus.wekiki.report; -import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; -import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; -import com.kakao.techcampus.wekiki.post.Post; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; From 033e74c63c80fdfc13de0459d96261d6c3301950 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Wed, 8 Nov 2023 22:47:58 +0900 Subject: [PATCH 104/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EB=A9=A4=EB=B2=84=20=ED=99=95=EC=9D=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 탈퇴한 상태인지 확인 --- .../java/com/kakao/techcampus/wekiki/comment/CommentService.java | 1 + .../main/java/com/kakao/techcampus/wekiki/page/PageService.java | 1 + .../main/java/com/kakao/techcampus/wekiki/post/PostService.java | 1 + 3 files changed, 3 insertions(+) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java index 7dd31f6f..fb61ac05 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java @@ -124,6 +124,7 @@ public GroupMember checkGroupMember(Long memberId, Long groupId){ GroupMember activeGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); + if(!activeGroupMember.isActiveStatus()) throw new Exception404("해당 그룹에 속한 회원이 아닙니다."); if(activeGroupMember.getMember() == null) throw new Exception404("존재하지 않는 회원입니다."); if(activeGroupMember.getGroup() == null) throw new Exception404("존재하지 않는 그룹입니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 335af306..66772d94 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -338,6 +338,7 @@ public GroupMember checkGroupMember(Long memberId, Long groupId){ GroupMember activeGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); + if(!activeGroupMember.isActiveStatus()) throw new Exception404("해당 그룹에 속한 회원이 아닙니다."); if(activeGroupMember.getMember() == null) throw new Exception404("존재하지 않는 회원입니다."); if(activeGroupMember.getGroup() == null) throw new Exception404("존재하지 않는 그룹입니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index 13e58d16..cb47dcdf 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -174,6 +174,7 @@ public GroupMember checkGroupMember(Long memberId, Long groupId){ GroupMember activeGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); + if(!activeGroupMember.isActiveStatus()) throw new Exception404("해당 그룹에 속한 회원이 아닙니다."); if(activeGroupMember.getMember() == null) throw new Exception404("존재하지 않는 회원입니다."); if(activeGroupMember.getGroup() == null) throw new Exception404("존재하지 않는 그룹입니다."); From 09805536efb44652914f69fdde914e501e466484 Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Wed, 8 Nov 2023 23:29:27 +0900 Subject: [PATCH 105/144] =?UTF-8?q?Feat=20:=20=EC=B9=B4=EC=B9=B4=EC=98=A4?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20Proxy=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kakao/techcampus/wekiki/_core/config/ProxyConfig.java | 1 - .../com/kakao/techcampus/wekiki/member/MemberService.java | 7 +++++-- wekiki/src/main/resources/application.yml | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/ProxyConfig.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/ProxyConfig.java index b855ba96..96a46269 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/ProxyConfig.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/ProxyConfig.java @@ -9,7 +9,6 @@ import java.net.InetSocketAddress; import java.net.Proxy; -@Profile(value = {"prod"}) @Configuration public class ProxyConfig { private static final String PROXY_HOST = "krmp-proxy.9rum.cc"; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index e7aba2c3..17637e70 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -46,6 +46,7 @@ public class MemberService { private final PasswordEncoder passwordEncoder; private final RedisUtility redisUtility; private final JavaMailSender javaMailSender; + private final RestTemplate restTemplate; @Value("${kakao.client.id}") private String KAKAO_CLIENT_ID; @Value("${kakao.redirect.uri}") @@ -240,6 +241,7 @@ public MemberResponse.authTokenDTO getKakaoInfo(String code) { params.add("redirect_uri", KAKAO_REDIRECT_URI); RestTemplate restTemplate = new RestTemplate(); + System.out.println(restTemplate.getClass()); HttpEntity> httpEntity = new HttpEntity<>(params, headers); ResponseEntity response = restTemplate.exchange( @@ -248,6 +250,7 @@ public MemberResponse.authTokenDTO getKakaoInfo(String code) { httpEntity, String.class ); + ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); MemberResponse.KakaoTokenDTO kakaoTokenDTO = objectMapper.readValue(response.getBody(), MemberResponse.KakaoTokenDTO.class); accessToken = kakaoTokenDTO.getAccess_token(); @@ -281,6 +284,8 @@ private void kakaoSignUp(MemberResponse.KakaoInfoDTO kakaoInfo, String kakaoEmai private MemberResponse.KakaoInfoDTO getUserInfoWithToken(String accessToken) { MemberResponse.KakaoInfoDTO kakaoInfo = null; RestTemplate restTemplate = new RestTemplate(); + System.out.println(restTemplate.getClass()); + HttpHeaders headers = new HttpHeaders(); headers.add("Authorization", "Bearer " + accessToken); @@ -295,8 +300,6 @@ private MemberResponse.KakaoInfoDTO getUserInfoWithToken(String accessToken) { String.class ); - System.out.println(response.getBody()); - ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); try { kakaoInfo = objectMapper.readValue(response.getBody(),MemberResponse.KakaoInfoDTO.class); diff --git a/wekiki/src/main/resources/application.yml b/wekiki/src/main/resources/application.yml index 5b9c5c63..b232792f 100644 --- a/wekiki/src/main/resources/application.yml +++ b/wekiki/src/main/resources/application.yml @@ -36,7 +36,7 @@ spring: required: true proxy: host: krmp-proxy.9rum.cc - port: 3182 + port: 3128 jwt: secret: 7ZmA656AIOuTneygkOyZlSDquLDsm5AgMeydvOywqALdlsKJL3234jklsdjfaKJDLnflkasdf kakao: From fdf05c421056b1870bf743fa724f07975b9457a7 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Wed, 8 Nov 2023 23:58:30 +0900 Subject: [PATCH 106/144] =?UTF-8?q?Fix:=20=EA=B7=B8=EB=A3=B9=20=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EC=8B=9C=20=EC=99=B8=EB=9E=98=20=ED=82=A4=20?= =?UTF-8?q?=EC=A0=9C=EC=95=BD=20=EC=A1=B0=EA=B1=B4=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Cascade.REMOVE 추가 --- .../techcampus/wekiki/comment/Comment.java | 2 +- .../wekiki/group/service/GroupService.java | 17 +++++++++++------ .../techcampus/wekiki/history/History.java | 2 +- .../kakao/techcampus/wekiki/page/PageInfo.java | 4 ++-- .../com/kakao/techcampus/wekiki/post/Post.java | 2 +- .../kakao/techcampus/wekiki/report/Report.java | 2 +- 6 files changed, 17 insertions(+), 12 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java index 7273209d..ee07248d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java @@ -16,7 +16,7 @@ public class Comment { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) private GroupMember groupMember; @Setter diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 65638d10..1f7af4c4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -257,7 +257,6 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ // 그룹 내 닉네임 중복 예외 처리 String groupNickName = requestDTO.nickName(); - groupNickNameCheck(groupId, groupNickName); GroupMember wasGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId, groupId); @@ -273,9 +272,13 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ // GroupMember 저장 saveGroupMember(member, group, wasGroupMember); } else { + groupNickNameCheck(groupId, groupNickName); + saveGroupMember(member, group, buildGroupMember(member, group, groupNickName)); } + redisUtils.deleteValues(MEMBER_ID_PREFIX + memberId); + } catch (Exception400 | Exception404 e) { throw e; } catch (Exception e) { @@ -302,8 +305,6 @@ protected void checkJoinPermission(Long memberId, Long groupId) { if(!lGroupId.equals(groupId)) { throw new Exception400("현재 그룹에 가입할 수 없습니다."); } - - redisUtils.deleteValues(MEMBER_ID_PREFIX + memberId); } /* @@ -418,6 +419,10 @@ public void leaveGroup(Long groupId, Long memberId) { group.minusMemberCount(); groupMember.changeStatus(); + Member member = getMemberById(memberId); + member.getGroupMembers().remove(groupMember); + memberJPARepository.save(member); + groupJPARepository.save(group); groupMemberJPARepository.save(groupMember); @@ -432,12 +437,12 @@ private void deleteGroup(Group group) { for (GroupMember groupMember : groupMemberList) { Long groupMemberId = groupMember.getId(); - List historyList = historyJPARepository.findAllByGroupMemberId(groupMemberId); - historyJPARepository.deleteAll(historyList); - List reportList = reportJPARepository.findAllByFromMemberId(groupMemberId); reportJPARepository.deleteAll(reportList); + List historyList = historyJPARepository.findAllByGroupMemberId(groupMemberId); + historyJPARepository.deleteAll(historyList); + List commentList = commentJPARepository.findAllByGroupMemberId(groupMemberId); commentJPARepository.deleteAll(commentList); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java index 3dc299b0..52a68b96 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java @@ -16,7 +16,7 @@ public class History { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) private GroupMember groupMember; @Setter diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java index 52a93fb5..41f7d520 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java @@ -21,11 +21,11 @@ public class PageInfo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) private Group group; private String pageName; - @OneToMany(mappedBy = "pageInfo") + @OneToMany(mappedBy = "pageInfo", cascade = CascadeType.REMOVE) private List posts = new ArrayList<>(); private int goodCount; private int badCount; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java index 958f6193..9d42013a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java @@ -26,7 +26,7 @@ public class Post { private int orders; - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) private GroupMember groupMember; @Setter diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java index d114ff7d..9d78c8d1 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java @@ -19,7 +19,7 @@ public class Report { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) private GroupMember fromMember; @ManyToOne(fetch = FetchType.LAZY) From 9141464bdbb1e8c2dcfd4f1bb138fb2bb2a60c23 Mon Sep 17 00:00:00 2001 From: JunHee Date: Thu, 9 Nov 2023 00:03:31 +0900 Subject: [PATCH 107/144] =?UTF-8?q?Revert=20"[10=EC=A3=BC=EC=B0=A8]=20?= =?UTF-8?q?=EA=B7=B8=EB=A3=B9=EB=A9=A4=EB=B2=84=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=88=98=EC=A0=95"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../techcampus/wekiki/comment/Comment.java | 4 +- .../wekiki/comment/CommentJPARepository.java | 3 + .../wekiki/comment/CommentResponse.java | 2 +- .../wekiki/comment/CommentService.java | 18 ++- .../techcampus/wekiki/group/domain/Group.java | 12 +- .../domain/member/ActiveGroupMember.java | 31 ++++ .../domain/{ => member}/GroupMember.java | 12 +- .../domain/member/InactiveGroupMember.java | 34 ++++ .../wekiki/group/dto/GroupResponseDTO.java | 7 +- .../repository/GroupMemberJPARepository.java | 21 +-- .../wekiki/group/service/GroupService.java | 147 ++++++++---------- .../techcampus/wekiki/history/History.java | 4 +- .../wekiki/history/HistoryJPARepository.java | 1 + .../techcampus/wekiki/member/Member.java | 3 +- .../wekiki/member/MemberRequest.java | 2 - .../wekiki/member/MemberResponse.java | 2 +- .../wekiki/member/MemberService.java | 3 +- .../techcampus/wekiki/page/PageInfo.java | 4 +- .../wekiki/page/PageJPARepository.java | 2 - .../techcampus/wekiki/page/PageService.java | 12 +- .../kakao/techcampus/wekiki/post/Post.java | 4 +- .../techcampus/wekiki/post/PostResponse.java | 2 +- .../techcampus/wekiki/post/PostService.java | 18 ++- .../techcampus/wekiki/report/Report.java | 4 +- .../wekiki/report/ReportJPARepository.java | 3 + 25 files changed, 209 insertions(+), 146 deletions(-) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/ActiveGroupMember.java rename wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/{ => member}/GroupMember.java (79%) create mode 100644 wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/InactiveGroupMember.java diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java index ee07248d..78b0a3f0 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java @@ -1,6 +1,6 @@ package com.kakao.techcampus.wekiki.comment; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.*; @@ -16,7 +16,7 @@ public class Comment { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) + @ManyToOne(fetch = FetchType.LAZY) private GroupMember groupMember; @Setter diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java index 819e4bd5..beafcfdf 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java @@ -1,5 +1,8 @@ package com.kakao.techcampus.wekiki.comment; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.post.Post; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java index 71d109e7..23bac93d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentResponse.java @@ -1,6 +1,6 @@ package com.kakao.techcampus.wekiki.comment; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.post.Post; import lombok.Getter; import lombok.Setter; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java index fb61ac05..c30f16fe 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java @@ -2,15 +2,18 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; +import com.kakao.techcampus.wekiki.member.Member; import com.kakao.techcampus.wekiki.member.MemberJPARepository; import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -34,7 +37,7 @@ public class CommentService { public CommentResponse.getCommentDTO getComment(Long memberId, Long groupId, Long postId, int pageNo){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - GroupMember activeGroupMember = checkGroupMember(memberId, groupId); + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. post 존재하는지 예외처리 Post post = checkPostFromPostId(postId); @@ -53,7 +56,7 @@ public CommentResponse.getCommentDTO getComment(Long memberId, Long groupId, Lon public CommentResponse.createCommentDTO createComment(Long memberId, Long groupId, Long postId, String content){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - GroupMember activeGroupMember = checkGroupMember(memberId, groupId); + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. post 존재하는지 예외처리 Post post = checkPostFromPostId(postId); @@ -75,7 +78,7 @@ public CommentResponse.createCommentDTO createComment(Long memberId, Long groupI public CommentResponse.deleteCommentDTO deleteComment(Long memberId, Long groupId, Long commentId){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - GroupMember activeGroupMember = checkGroupMember(memberId, groupId); + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. comment 존재하는지 예외처리 Comment comment = checkCommentFromCommentId(commentId); @@ -97,7 +100,7 @@ public CommentResponse.deleteCommentDTO deleteComment(Long memberId, Long groupI public CommentResponse.updateCommentDTO updateComment(Long memberId, Long groupId, Long commentId, String updateContent){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - GroupMember activeGroupMember = checkGroupMember(memberId, groupId); + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. comment 존재하는지 예외처리 Comment comment = checkCommentFromCommentId(commentId); @@ -120,11 +123,10 @@ public CommentResponse.updateCommentDTO updateComment(Long memberId, Long groupI } - public GroupMember checkGroupMember(Long memberId, Long groupId){ + public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ - GroupMember activeGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) + ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); - if(!activeGroupMember.isActiveStatus()) throw new Exception404("해당 그룹에 속한 회원이 아닙니다."); if(activeGroupMember.getMember() == null) throw new Exception404("존재하지 않는 회원입니다."); if(activeGroupMember.getGroup() == null) throw new Exception404("존재하지 않는 그룹입니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java index 277951b5..a0887262 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.group.domain; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -41,15 +42,6 @@ public Group(Long id, String groupName, String groupProfileImage, LocalDateTime public void addGroupMember(GroupMember groupMember) { this.groupMembers.add(groupMember); - this.memberCount++; - } - - public void minusMemberCount() { - this.memberCount--; - } - - public void removeGroupMember(GroupMember groupMember) { - this.groupMembers.remove(groupMember); - minusMemberCount(); + this.memberCount = this.groupMembers.size(); } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/ActiveGroupMember.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/ActiveGroupMember.java new file mode 100644 index 00000000..7853b4fb --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/ActiveGroupMember.java @@ -0,0 +1,31 @@ +package com.kakao.techcampus.wekiki.group.domain.member; + +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.member.Member; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@DiscriminatorValue("active_group_member") +public class ActiveGroupMember extends GroupMember { + + @Builder(builderMethodName = "activeGroupMemberBuilder") + public ActiveGroupMember(Long id, Member member, Group group, String nickName, LocalDateTime created_at) { + super(id, member, group, nickName, created_at); + } + + /* + 그룹 멤버 재가입 + */ + public ActiveGroupMember(InactiveGroupMember groupMember) { + super(groupMember.getId(), groupMember.getMember(), groupMember.getGroup(), groupMember.getNickName(), groupMember.getCreated_at()); + } +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/GroupMember.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/GroupMember.java similarity index 79% rename from wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/GroupMember.java rename to wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/GroupMember.java index 5e6a2856..141675c4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/GroupMember.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/GroupMember.java @@ -1,6 +1,8 @@ -package com.kakao.techcampus.wekiki.group.domain; +package com.kakao.techcampus.wekiki.group.domain.member; +import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.member.Member; +import com.kakao.techcampus.wekiki.member.MemberService; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; @@ -12,7 +14,9 @@ @Getter @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Inheritance(strategy = InheritanceType.JOINED) @Table(name = "group_member_tb") +@DiscriminatorColumn(name = "member_status", discriminatorType = DiscriminatorType.STRING) public class GroupMember { @@ -27,7 +31,6 @@ private String nickName; private int memberLevel; private LocalDateTime created_at; - boolean activeStatus; @Builder public GroupMember(Long id, Member member, Group group, String nickName, LocalDateTime created_at) { @@ -37,7 +40,6 @@ public GroupMember(Long id, Member member, Group group, String nickName, LocalDa this.nickName = nickName; this.memberLevel = 1; this.created_at = created_at; - this.activeStatus = true; } public void changeMember(Member member) { @@ -48,8 +50,4 @@ public void changeMember(Member member) { public void update(String groupNickName) { this.nickName = groupNickName; } - - public void changeStatus() { - this.activeStatus = !this.activeStatus; - } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/InactiveGroupMember.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/InactiveGroupMember.java new file mode 100644 index 00000000..18862943 --- /dev/null +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/member/InactiveGroupMember.java @@ -0,0 +1,34 @@ +package com.kakao.techcampus.wekiki.group.domain.member; + +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.member.Member; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@DiscriminatorValue("inactive_group_member") +public class InactiveGroupMember extends GroupMember { + private LocalDateTime left_at; + + @Builder(builderMethodName = "inactiveGroupMemberBuilder") + public InactiveGroupMember(Long id, Member member, Group group, String nickName, LocalDateTime created_at, LocalDateTime left_at) { + super(id, member, group, nickName, created_at); + this.left_at = left_at; + } + + /* + 그룹 멤버 탈퇴 전환 + */ + public InactiveGroupMember(ActiveGroupMember groupMember) { + super(groupMember.getId(), groupMember.getMember(), groupMember.getGroup(), groupMember.getNickName(), groupMember.getCreated_at()); + this.left_at = LocalDateTime.now(); + } +} diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java index bff94af5..09665b41 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java @@ -1,10 +1,12 @@ package com.kakao.techcampus.wekiki.group.dto; +import com.kakao.techcampus.wekiki.group.GroupType; import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.group.domain.Invitation; import com.kakao.techcampus.wekiki.group.domain.OfficialGroup; import com.kakao.techcampus.wekiki.group.domain.UnOfficialOpenedGroup; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.history.History; import jakarta.persistence.DiscriminatorValue; import org.springframework.data.domain.Page; @@ -137,7 +139,8 @@ public SearchGroupInfoDTO(Group group) { public record GetGroupMembersResponseDTO(List nickNames) { public GetGroupMembersResponseDTO(Group group) { this(group.getGroupMembers().stream() - .map(GroupMember::getNickName) + .filter(groupMember -> groupMember instanceof ActiveGroupMember) + .map(groupMember -> groupMember.getNickName()) .collect(Collectors.toList())); } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java index 6eaabfa9..fb7c63d5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/repository/GroupMemberJPARepository.java @@ -1,27 +1,30 @@ package com.kakao.techcampus.wekiki.group.repository; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.InactiveGroupMember; +import com.kakao.techcampus.wekiki.member.Member; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import java.util.List; import java.util.Optional; @Repository public interface GroupMemberJPARepository extends JpaRepository { + @Query("SELECT iagm FROM InactiveGroupMember iagm WHERE iagm.member = :member AND iagm.group = :group") + InactiveGroupMember findInactiveGroupMemberByMemberAndGroup(@Param("member") Member member, @Param("group") Group group); + + @Query("SELECT agm FROM ActiveGroupMember agm WHERE agm.member.id = :memberId AND agm.group.id = :groupId") + Optional findActiveGroupMemberByMemberIdAndGroupId(@Param("memberId") Long memberId, @Param("groupId") Long groupId); @Query("SELECT gm FROM GroupMember gm WHERE gm.group.id = :groupId AND gm.nickName = :nickName") Optional findGroupMemberByNickName(@Param("groupId") Long groupId, @Param("nickName") String nickName); // 여기다 멤버 group fetchjoin - @Query("SELECT gm FROM GroupMember gm LEFT JOIN FETCH gm.member LEFT JOIN FETCH gm.group WHERE gm.member.id = :memberId AND gm.group.id = :groupId") - Optional findGroupMemberByMemberIdAndGroupIdFetchJoin(@Param("memberId") Long memberId, @Param("groupId") Long groupId); - - @Query("SELECT gm FROM GroupMember gm WHERE gm.member.id = :memberId AND gm.group.id = :groupId") - GroupMember findGroupMemberByMemberIdAndGroupId(@Param("memberId") Long memberId, @Param("groupId") Long groupId); + @Query("SELECT agm FROM ActiveGroupMember agm LEFT JOIN FETCH agm.member LEFT JOIN FETCH agm.group WHERE agm.member.id = :memberId AND agm.group.id = :groupId") + Optional findActiveGroupMemberByMemberIdAndGroupIdFetchJoin(@Param("memberId") Long memberId, @Param("groupId") Long groupId); - @Query("SELECT gm FROM GroupMember gm WHERE gm.group.id = :id") - List findAllByGroupId(@Param("id") Long id); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 1f7af4c4..0e925fe3 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -7,11 +7,13 @@ import com.kakao.techcampus.wekiki.comment.Comment; import com.kakao.techcampus.wekiki.comment.CommentJPARepository; import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.group.dto.GroupRequestDTO; import com.kakao.techcampus.wekiki.group.dto.GroupResponseDTO; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; +import com.kakao.techcampus.wekiki.group.domain.member.InactiveGroupMember; import com.kakao.techcampus.wekiki.group.domain.OfficialGroup; import com.kakao.techcampus.wekiki.group.domain.UnOfficialClosedGroup; import com.kakao.techcampus.wekiki.group.domain.UnOfficialOpenedGroup; @@ -19,8 +21,6 @@ import com.kakao.techcampus.wekiki.history.HistoryJPARepository; import com.kakao.techcampus.wekiki.member.Member; import com.kakao.techcampus.wekiki.member.MemberJPARepository; -import com.kakao.techcampus.wekiki.page.PageInfo; -import com.kakao.techcampus.wekiki.page.PageJPARepository; import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; import com.kakao.techcampus.wekiki.report.Report; @@ -49,7 +49,6 @@ public class GroupService { private final GroupJPARepository groupJPARepository; private final GroupMemberJPARepository groupMemberJPARepository; private final MemberJPARepository memberJPARepository; - private final PageJPARepository pageJPARepository; private final PostJPARepository postJPARepository; private final HistoryJPARepository historyJPARepository; private final CommentJPARepository commentJPARepository; @@ -75,7 +74,7 @@ public GroupResponseDTO.CreateUnOfficialGroupResponseDTO createUnOfficialGroup(G // MemberId로부터 Member 찾기 Member member = getMemberById(memberId); // GroupMember 생성 - GroupMember groupMember = buildGroupMember(member, group, requestDTO.groupNickName()); + ActiveGroupMember groupMember = buildGroupMember(member, group, requestDTO.groupNickName()); // Entity 저장 group.addGroupMember(groupMember); @@ -126,8 +125,8 @@ protected UnOfficialOpenedGroup buildUnOfficialOpenedGroup(GroupRequestDTO.Creat /* GroupMember 생성 후 반환 */ - protected GroupMember buildGroupMember(Member member, Group group, String groupNickName) { - return GroupMember.builder() + protected ActiveGroupMember buildGroupMember(Member member, Group group, String groupNickName) { + return ActiveGroupMember.activeGroupMemberBuilder() .member(member) .group(group) .nickName(groupNickName) @@ -256,28 +255,30 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ checkJoinPermission(memberId, groupId); // 그룹 내 닉네임 중복 예외 처리 - String groupNickName = requestDTO.nickName(); + groupNickNameCheck(groupId, requestDTO.nickName()); - GroupMember wasGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId, groupId); - - if(wasGroupMember != null) { - // 이미 가입한 상태일 시 예외 처리 - if(wasGroupMember.isActiveStatus()) { - throw new Exception400("이미 가입된 회원입니다."); - } + // 이미 가입한 상태일 시 예외 처리 + if (groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId).isPresent()) { + throw new Exception400("이미 가입된 회원입니다."); + } - // 재가입 회원인지 확인 - wasGroupMember.changeStatus(); + // 재가입 회원인지 확인 + InactiveGroupMember wasGroupMember = groupMemberJPARepository.findInactiveGroupMemberByMemberAndGroup(member, group); - // GroupMember 저장 - saveGroupMember(member, group, wasGroupMember); - } else { - groupNickNameCheck(groupId, groupNickName); + // 재가입 회원이면 활성화, 신규 회원이면 새로 생성 + ActiveGroupMember groupMember = wasGroupMember != null ? new ActiveGroupMember(wasGroupMember) : buildGroupMember(member, group, requestDTO.nickName()); - saveGroupMember(member, group, buildGroupMember(member, group, groupNickName)); + if(wasGroupMember != null) { + changeAuthorization(wasGroupMember, groupMember); } - redisUtils.deleteValues(MEMBER_ID_PREFIX + memberId); + // GroupMember 저장 + group.addGroupMember(groupMember); + member.getGroupMembers().add(groupMember); + + groupJPARepository.save(group); + memberJPARepository.save(member); + groupMemberJPARepository.save(groupMember); } catch (Exception400 | Exception404 e) { throw e; @@ -286,16 +287,6 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ } } - private void saveGroupMember(Member member, Group group, GroupMember groupMember) { - // GroupMember 저장 - group.addGroupMember(groupMember); - member.getGroupMembers().add(groupMember); - - groupJPARepository.save(group); - memberJPARepository.save(member); - groupMemberJPARepository.save(groupMember); - } - protected void checkJoinPermission(Long memberId, Long groupId) { Object oGroupId = Optional.ofNullable(redisUtils.getValues(MEMBER_ID_PREFIX + memberId)) .orElseThrow(() -> new Exception404("해당 그룹에 가입할 수 없습니다.")); @@ -305,6 +296,8 @@ protected void checkJoinPermission(Long memberId, Long groupId) { if(!lGroupId.equals(groupId)) { throw new Exception400("현재 그룹에 가입할 수 없습니다."); } + + redisUtils.deleteValues(MEMBER_ID_PREFIX + memberId); } /* @@ -330,7 +323,7 @@ public GroupResponseDTO.GetGroupMembersResponseDTO getGroupMembers(Long groupId, public GroupResponseDTO.MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { try { // 그룹 멤버 확인 - GroupMember groupMember = getActiveGroupMember(groupId, memberId); + ActiveGroupMember groupMember = getActiveGroupMember(groupId, memberId); // 해당 멤버의 Post 기록 정보 확인(History에서 가져옴) Pageable pageable = PageRequest.of(0, 10); @@ -352,7 +345,7 @@ public GroupResponseDTO.MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long public GroupResponseDTO.MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, int page, int size) { try { // 그룹 멤버 확인 - GroupMember groupMember = getActiveGroupMember(groupId, memberId); + ActiveGroupMember groupMember = getActiveGroupMember(groupId, memberId); Pageable pageable = PageRequest.of(page, size); Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember.getId(), pageable); @@ -374,7 +367,7 @@ public GroupResponseDTO.MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId public void updateMyGroupPage(Long groupId, Long memberId, GroupRequestDTO.UpdateMyGroupPageDTO requestDTO) { try { // 그룹 멤버 확인 - GroupMember groupMember = getActiveGroupMember(groupId, memberId); + ActiveGroupMember groupMember = getActiveGroupMember(groupId, memberId); // 변경할 닉네임 확인 String newNickName = requestDTO.groupNickName(); @@ -411,56 +404,56 @@ public void updateMyGroupPage(Long groupId, Long memberId, GroupRequestDTO.Updat */ @Transactional public void leaveGroup(Long groupId, Long memberId) { - GroupMember groupMember = getActiveGroupMember(groupId, memberId); + try { + ActiveGroupMember activeGroupMember = getActiveGroupMember(groupId, memberId); - Group group = getGroupById(groupId); + Member member = getMemberById(memberId); + Group group = getGroupById(groupId); - if(group.getMemberCount() != 1) { - group.minusMemberCount(); - groupMember.changeStatus(); + member.getGroupMembers().remove(activeGroupMember); + group.getGroupMembers().remove(activeGroupMember); - Member member = getMemberById(memberId); - member.getGroupMembers().remove(groupMember); - memberJPARepository.save(member); + // 탈퇴 그룹 회원 생성 + InactiveGroupMember inactiveGroupMember = new InactiveGroupMember(activeGroupMember); - groupJPARepository.save(group); - groupMemberJPARepository.save(groupMember); + changeAuthorization(activeGroupMember, inactiveGroupMember); - } else { - deleteGroup(group); + groupMemberJPARepository.save(inactiveGroupMember); + + } catch (Exception404 e) { + throw e; + } catch (Exception e) { + throw new Exception500("서버 에러가 발생했습니다."); } } - private void deleteGroup(Group group) { - List groupMemberList = groupMemberJPARepository.findAllByGroupId(group.getId()); - - for (GroupMember groupMember : groupMemberList) { - Long groupMemberId = groupMember.getId(); + private void changeAuthorization(GroupMember originGroupMember, GroupMember targetGroupMember) { - List reportList = reportJPARepository.findAllByFromMemberId(groupMemberId); - reportJPARepository.deleteAll(reportList); + Long originGroupMemberId = originGroupMember.getId(); - List historyList = historyJPARepository.findAllByGroupMemberId(groupMemberId); - historyJPARepository.deleteAll(historyList); + // Post의 그룹 멤버 변경 + List postList = postJPARepository.findAllByGroupMember(originGroupMemberId); + postList.forEach(p -> p.updateGroupMember(targetGroupMember)); - List commentList = commentJPARepository.findAllByGroupMemberId(groupMemberId); - commentJPARepository.deleteAll(commentList); + // History 그룹 멤버 변경 + List historyList = historyJPARepository.findAllByGroupMemberId(originGroupMemberId); + historyList.forEach(h -> h.updateGroupMember(targetGroupMember)); - List postList = postJPARepository.findAllByGroupMember(groupMemberId); - postJPARepository.deleteAll(postList); + // Comment 그룹 멤버 변경 + List commentList = commentJPARepository.findAllByGroupMemberId(originGroupMemberId); + commentList.forEach(c -> c.updateGroupMember(targetGroupMember)); - List pageInfoList = pageJPARepository.findAllByGroupMember(group.getId()); - pageJPARepository.deleteAll(pageInfoList); - - Member member = groupMember.getMember(); - member.getGroupMembers().remove(groupMember); - memberJPARepository.save(member); + // Reposrt 그룹 멤버 변경 + List reportList = reportJPARepository.findAllByFromMemberId(originGroupMemberId); + reportList.forEach(r -> r.updateGroupMember(targetGroupMember)); - group.removeGroupMember(groupMember); - groupMemberJPARepository.delete(groupMember); - } + // DB 작업 + groupMemberJPARepository.delete(originGroupMember); - groupJPARepository.delete(group); + postJPARepository.saveAll(postList); + historyJPARepository.saveAll(historyList); + commentJPARepository.saveAll(commentList); + reportJPARepository.saveAll(reportList); } protected Member getMemberById(Long memberId) { @@ -471,14 +464,10 @@ protected Group getGroupById(Long groupId) { return groupJPARepository.findById(groupId).orElseThrow(() -> new Exception404("해당 그룹을 찾을 수 없습니다.")); } - private GroupMember getActiveGroupMember(Long groupId, Long memberId) { - GroupMember groupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId, groupId); - - if (groupMember == null || !groupMember.isActiveStatus()) { - throw new Exception404("해당 그룹에 속한 회원이 아닙니다."); - } - - return groupMember; + private ActiveGroupMember getActiveGroupMember(Long groupId, Long memberId) { + // 그룹 멤버 확인 + return groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupId(memberId, groupId) + .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다")); } protected void groupNickNameCheck(Long groupId, String groupNickName) { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java index 52a68b96..f2c3f448 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java @@ -1,6 +1,6 @@ package com.kakao.techcampus.wekiki.history; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.post.Post; import jakarta.persistence.*; import lombok.*; @@ -16,7 +16,7 @@ public class History { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) + @ManyToOne(fetch = FetchType.LAZY) private GroupMember groupMember; @Setter diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java index 3ae813a8..48885067 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.history; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java index 7d1f76d1..95a6c38c 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/Member.java @@ -1,6 +1,7 @@ package com.kakao.techcampus.wekiki.member; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import lombok.AccessLevel; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java index 77ac6a02..e45cbba8 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java @@ -2,7 +2,6 @@ import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.NoArgsConstructor; @AllArgsConstructor public class MemberRequest { @@ -15,7 +14,6 @@ public static class signUpRequestDTO { @Getter @AllArgsConstructor - @NoArgsConstructor public static class loginRequestDTO { private String email; private String password; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java index 7c730d80..76a7c28e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberResponse.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index a7146924..1f33d42d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -6,7 +6,8 @@ import com.kakao.techcampus.wekiki._core.error.exception.*; import com.kakao.techcampus.wekiki._core.jwt.JWTTokenProvider; import com.kakao.techcampus.wekiki._core.utils.RedisUtility; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java index 41f7d520..52a93fb5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java @@ -21,11 +21,11 @@ public class PageInfo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) + @ManyToOne(fetch = FetchType.LAZY) private Group group; private String pageName; - @OneToMany(mappedBy = "pageInfo", cascade = CascadeType.REMOVE) + @OneToMany(mappedBy = "pageInfo") private List posts = new ArrayList<>(); private int goodCount; private int badCount; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java index e72c31a3..ea384a53 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java @@ -38,6 +38,4 @@ public interface PageJPARepository extends JpaRepository { @Query("SELECT p FROM PageInfo p WHERE p.group.id = :groupId AND p.pageName LIKE %:keyword% ") Page findPages(@Param("groupId") Long groupId, @Param("keyword") String keyword, Pageable pageable); - @Query("SELECT p FROM PageInfo p WHERE p.group.id = :groupId") - List findAllByGroupMember(@Param("groupId") Long groupId); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 66772d94..e9bde633 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -3,10 +3,12 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.utils.IndexUtils; +import com.kakao.techcampus.wekiki._core.utils.RedisUtility; import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; import com.kakao.techcampus.wekiki.group.domain.Group; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.member.Member; import com.kakao.techcampus.wekiki.member.MemberJPARepository; @@ -14,6 +16,7 @@ import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; @@ -170,7 +173,7 @@ public PageInfoResponse.getPageFromIdDTO getPageFromId(Long memberId,Long groupI public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Long memberId){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - GroupMember activeGroupMember = checkGroupMember(memberId, groupId); + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. 그룹 내 동일한 title의 Page가 존재하는지 체크 if(pageJPARepository.findByTitle(groupId,title).isPresent()){ @@ -334,11 +337,10 @@ public PageInfoResponse.getPageLinkDTO getPageLink( Long groupId, String title){ } - public GroupMember checkGroupMember(Long memberId, Long groupId){ + public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ - GroupMember activeGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) + ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); - if(!activeGroupMember.isActiveStatus()) throw new Exception404("해당 그룹에 속한 회원이 아닙니다."); if(activeGroupMember.getMember() == null) throw new Exception404("존재하지 않는 회원입니다."); if(activeGroupMember.getGroup() == null) throw new Exception404("존재하지 않는 그룹입니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java index 9d42013a..4e02221b 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java @@ -1,7 +1,7 @@ package com.kakao.techcampus.wekiki.post; import com.kakao.techcampus.wekiki.comment.Comment; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.page.PageInfo; import jakarta.persistence.*; @@ -26,7 +26,7 @@ public class Post { private int orders; - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) + @ManyToOne(fetch = FetchType.LAZY) private GroupMember groupMember; @Setter diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java index a4315b31..6d64680e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostResponse.java @@ -1,6 +1,6 @@ package com.kakao.techcampus.wekiki.post; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.report.Report; import lombok.Getter; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index cb47dcdf..6512284d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -3,10 +3,15 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.Group; +import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; import com.kakao.techcampus.wekiki.history.History; import com.kakao.techcampus.wekiki.history.HistoryJPARepository; +import com.kakao.techcampus.wekiki.member.Member; +import com.kakao.techcampus.wekiki.member.MemberJPARepository; import com.kakao.techcampus.wekiki.page.PageInfo; import com.kakao.techcampus.wekiki.page.PageJPARepository; import com.kakao.techcampus.wekiki.report.Report; @@ -36,7 +41,7 @@ public class PostService { public PostResponse.createPostDTO createPost(Long memberId,Long groupId,Long pageId, Long parentPostId, int order, String title, String content){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - GroupMember activeGroupMember = checkGroupMember(memberId, groupId); + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. pageId로 PageInfo 객체 들고오기 PageInfo pageInfo = checkPageFromPageId(pageId); @@ -79,7 +84,7 @@ public PostResponse.createPostDTO createPost(Long memberId,Long groupId,Long pag public PostResponse.modifyPostDTO modifyPost(Long memberId , Long groupId, Long postId , String title, String content){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - GroupMember activeGroupMember = checkGroupMember(memberId, groupId); + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. postId로 post 엔티티 가져오기 Post post = checkPostFromPostId(postId); @@ -147,7 +152,7 @@ public PostResponse.deletePostDTO deletePost(Long memberId, Long groupId, Long p public PostResponse.createReportDTO createReport(Long memberId, Long groupId, Long postId , String content){ // 1. 존재하는 Member, Group, GroupMember 인지 fetch join으로 하나의 쿼리로 확인 - GroupMember activeGroupMember = checkGroupMember(memberId, groupId); + ActiveGroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. postId로 post 엔티티 가져오기 checkPostFromPostId(postId); @@ -170,11 +175,10 @@ public PostResponse.createReportDTO createReport(Long memberId, Long groupId, Lo } - public GroupMember checkGroupMember(Long memberId, Long groupId){ + public ActiveGroupMember checkGroupMember(Long memberId, Long groupId){ - GroupMember activeGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) + ActiveGroupMember activeGroupMember = groupMemberJPARepository.findActiveGroupMemberByMemberIdAndGroupIdFetchJoin(memberId, groupId) .orElseThrow(() -> new Exception404("해당 그룹에 속한 회원이 아닙니다.")); - if(!activeGroupMember.isActiveStatus()) throw new Exception404("해당 그룹에 속한 회원이 아닙니다."); if(activeGroupMember.getMember() == null) throw new Exception404("존재하지 않는 회원입니다."); if(activeGroupMember.getGroup() == null) throw new Exception404("존재하지 않는 그룹입니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java index 9d78c8d1..c830ebe6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java @@ -1,6 +1,6 @@ package com.kakao.techcampus.wekiki.report; -import com.kakao.techcampus.wekiki.group.domain.GroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; import com.kakao.techcampus.wekiki.history.History; import jakarta.persistence.*; import lombok.AccessLevel; @@ -19,7 +19,7 @@ public class Report { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) + @ManyToOne(fetch = FetchType.LAZY) private GroupMember fromMember; @ManyToOne(fetch = FetchType.LAZY) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java index 1425b814..4323e9f5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java @@ -1,5 +1,8 @@ package com.kakao.techcampus.wekiki.report; +import com.kakao.techcampus.wekiki.group.domain.member.ActiveGroupMember; +import com.kakao.techcampus.wekiki.group.domain.member.GroupMember; +import com.kakao.techcampus.wekiki.post.Post; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; From 440519780d0444084cd28915842cf9e081e7ca7e Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Thu, 9 Nov 2023 00:21:42 +0900 Subject: [PATCH 108/144] =?UTF-8?q?Feat=20:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=ED=83=88=ED=87=B4=20=ED=9B=84=20=EB=A9=94=EC=9D=B8,=20?= =?UTF-8?q?=EB=A7=88=EC=9D=B4=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/kakao/techcampus/wekiki/page/PageService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 66772d94..aef3660d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -62,7 +62,8 @@ public PageInfoResponse.mainPageDTO getMainPage() { log.error("회원이 존재하지 않습니다."); throw new Exception400("없는 회원입니다."); } - List myGroupList = member.get().getGroupMembers().stream().map(GroupMember::getGroup).toList(); + List myGroupList = member.get().getGroupMembers().stream() + .filter(GroupMember::isActiveStatus).map(GroupMember::getGroup).toList(); List myGroupIdList = myGroupList.stream().map(Group::getId).toList(); List myGroupListDTO = getMyGroupList(myGroupList); List officialGroupList = getOfficialGroupList(); From 3717f45bb412aa62c6f2131a04d109d747a3160d Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Thu, 9 Nov 2023 00:47:56 +0900 Subject: [PATCH 109/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=EC=9B=90?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 그룹원 조회 시 현재 활동중인 멤버만 조회 --- .../wekiki/group/dto/GroupResponseDTO.java | 1 + .../wekiki/group/service/GroupService.java | 289 +++++++----------- 2 files changed, 108 insertions(+), 182 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java index bff94af5..5fbbb53e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/dto/GroupResponseDTO.java @@ -137,6 +137,7 @@ public SearchGroupInfoDTO(Group group) { public record GetGroupMembersResponseDTO(List nickNames) { public GetGroupMembersResponseDTO(Group group) { this(group.getGroupMembers().stream() + .filter(GroupMember::isActiveStatus) .map(GroupMember::getNickName) .collect(Collectors.toList())); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 1f7af4c4..3d0418b6 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -2,7 +2,6 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; -import com.kakao.techcampus.wekiki._core.error.exception.Exception500; import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; import com.kakao.techcampus.wekiki.comment.Comment; import com.kakao.techcampus.wekiki.comment.CommentJPARepository; @@ -64,35 +63,28 @@ public class GroupService { */ @Transactional public GroupResponseDTO.CreateUnOfficialGroupResponseDTO createUnOfficialGroup(GroupRequestDTO.CreateUnOfficialGroupRequestDTO requestDTO, Long memberId) { - try { - // Group 생성 - Group group = switch (requestDTO.groupType()) { - case UNOFFICIAL_CLOSED -> buildUnOfficialClosedGroup(requestDTO); - case UNOFFICIAL_OPENED -> buildUnOfficialOpenedGroup(requestDTO); - default -> throw new Exception400("유효하지 않은 그룹 유형입니다."); - }; - - // MemberId로부터 Member 찾기 - Member member = getMemberById(memberId); - // GroupMember 생성 - GroupMember groupMember = buildGroupMember(member, group, requestDTO.groupNickName()); - - // Entity 저장 - group.addGroupMember(groupMember); - member.getGroupMembers().add(groupMember); - - groupJPARepository.save(group); - memberJPARepository.save(member); - groupMemberJPARepository.save(groupMember); + // Group 생성 + Group group = switch (requestDTO.groupType()) { + case UNOFFICIAL_CLOSED -> buildUnOfficialClosedGroup(requestDTO); + case UNOFFICIAL_OPENED -> buildUnOfficialOpenedGroup(requestDTO); + default -> throw new Exception400("유효하지 않은 그룹 유형입니다."); + }; + + // MemberId로부터 Member 찾기 + Member member = getMemberById(memberId); + // GroupMember 생성 + GroupMember groupMember = buildGroupMember(member, group, requestDTO.groupNickName()); + + // Entity 저장 + group.addGroupMember(groupMember); + member.getGroupMembers().add(groupMember); - // return - return new GroupResponseDTO.CreateUnOfficialGroupResponseDTO(group, invitationService.getGroupInvitationCode(group.getId())); + groupJPARepository.save(group); + memberJPARepository.save(member); + groupMemberJPARepository.save(groupMember); - } catch (Exception400 | Exception404 e) { - throw e; - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); - } + // return + return new GroupResponseDTO.CreateUnOfficialGroupResponseDTO(group, invitationService.getGroupInvitationCode(group.getId())); } @@ -140,80 +132,55 @@ protected GroupMember buildGroupMember(Member member, Group group, String groupN - keyword가 포함된 모든 그룹 그룹별 리스트 */ public GroupResponseDTO.SearchGroupDTO searchGroupByKeyword(String keyword) { - try { - Pageable pageable = PageRequest.of(0, GROUP_SEARCH_SIZE); - - // 공식 그룹 리스트 - Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); - // 비공식 공개 그룹 리스트 - Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); + Pageable pageable = PageRequest.of(0, GROUP_SEARCH_SIZE); - return new GroupResponseDTO.SearchGroupDTO(officialGroups, unOfficialOpenedGroups); + // 공식 그룹 리스트 + Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); + // 비공식 공개 그룹 리스트 + Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); - } + return new GroupResponseDTO.SearchGroupDTO(officialGroups, unOfficialOpenedGroups); } /* 공식 그룹 추가 리스트 */ public GroupResponseDTO.SearchOfficialGroupResponseDTO searchOfficialGroupByKeyword(String keyword, int page) { - try { - Pageable pageable = PageRequest.of(page, GROUP_SEARCH_SIZE); - - // 비공식 공개 그룹 리스트 - Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); - - if (officialGroups.isEmpty()) { - throw new Exception404("마지막 페이지입니다."); - } + Pageable pageable = PageRequest.of(page, GROUP_SEARCH_SIZE); - return new GroupResponseDTO.SearchOfficialGroupResponseDTO(officialGroups); + // 비공식 공개 그룹 리스트 + Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); - } catch (Exception404 e) { - throw e; - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); + if (officialGroups.isEmpty()) { + throw new Exception404("마지막 페이지입니다."); } + + return new GroupResponseDTO.SearchOfficialGroupResponseDTO(officialGroups); } /* 비공식 공개 그룹 추가 리스트 */ public GroupResponseDTO.SearchUnOfficialGroupResponseDTO searchUnOfficialGroupByKeyword(String keyword, int page) { - try { - Pageable pageable = PageRequest.of(page, GROUP_SEARCH_SIZE); - - // 비공식 공개 그룹 리스트 - Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); - - if (unOfficialOpenedGroups.isEmpty()) { - throw new Exception404("마지막 페이지입니다."); - } + Pageable pageable = PageRequest.of(page, GROUP_SEARCH_SIZE); - return new GroupResponseDTO.SearchUnOfficialGroupResponseDTO(unOfficialOpenedGroups); + // 비공식 공개 그룹 리스트 + Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); - } catch (Exception404 e) { - throw e; - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); + if (unOfficialOpenedGroups.isEmpty()) { + throw new Exception404("마지막 페이지입니다."); } + + return new GroupResponseDTO.SearchUnOfficialGroupResponseDTO(unOfficialOpenedGroups); } /* 그룹 상세 정보 조회 */ public GroupResponseDTO.SearchGroupInfoDTO getGroupInfo(Long groupId) { - try { - Group group = getGroupById(groupId); - - return new GroupResponseDTO.SearchGroupInfoDTO(group); - } catch (Exception404 e) { - throw e; - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); - } + Group group = getGroupById(groupId); + + return new GroupResponseDTO.SearchGroupInfoDTO(group); } @@ -221,25 +188,18 @@ public GroupResponseDTO.SearchGroupInfoDTO getGroupInfo(Long groupId) { 비공식 공개 그룹 입장 */ public void groupEntry(Long groupId, Long memberId, GroupRequestDTO.GroupEntryRequestDTO requestDTO) { - try { - getGroupById(groupId); - getMemberById(memberId); - - UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId) - .orElseThrow(() -> new Exception404("그룹을 찾을 수 없습니다.")); - - // 틀린 경우, 에러 핸들링 - if(!group.getEntrancePassword().equals(requestDTO.entrancePassword())) { - throw new Exception400("비밀번호가 틀렸습니다."); - } + getGroupById(groupId); + getMemberById(memberId); - redisUtils.setGroupIdValues(MEMBER_ID_PREFIX + memberId, groupId, Duration.ofHours(MEMBER_ID_LIFETIME)); + UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId) + .orElseThrow(() -> new Exception404("그룹을 찾을 수 없습니다.")); - } catch (Exception400 | Exception404 e) { - throw e; - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); + // 틀린 경우, 에러 핸들링 + if(!group.getEntrancePassword().equals(requestDTO.entrancePassword())) { + throw new Exception400("비밀번호가 틀렸습니다."); } + + redisUtils.setGroupIdValues(MEMBER_ID_PREFIX + memberId, groupId, Duration.ofHours(MEMBER_ID_LIFETIME)); } /* @@ -247,43 +207,36 @@ public void groupEntry(Long groupId, Long memberId, GroupRequestDTO.GroupEntryRe */ @Transactional public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequestDTO requestDTO) { - try { - // 회원 정보 확인 - Member member = getMemberById(memberId); - // 그룹 정보 확인 - Group group = getGroupById(groupId); - - checkJoinPermission(memberId, groupId); - - // 그룹 내 닉네임 중복 예외 처리 - String groupNickName = requestDTO.nickName(); - - GroupMember wasGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId, groupId); + // 회원 정보 확인 + Member member = getMemberById(memberId); + // 그룹 정보 확인 + Group group = getGroupById(groupId); - if(wasGroupMember != null) { - // 이미 가입한 상태일 시 예외 처리 - if(wasGroupMember.isActiveStatus()) { - throw new Exception400("이미 가입된 회원입니다."); - } + checkJoinPermission(memberId, groupId); - // 재가입 회원인지 확인 - wasGroupMember.changeStatus(); + // 그룹 내 닉네임 중복 예외 처리 + String groupNickName = requestDTO.nickName(); - // GroupMember 저장 - saveGroupMember(member, group, wasGroupMember); - } else { - groupNickNameCheck(groupId, groupNickName); + GroupMember wasGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId, groupId); - saveGroupMember(member, group, buildGroupMember(member, group, groupNickName)); + if(wasGroupMember != null) { + // 이미 가입한 상태일 시 예외 처리 + if(wasGroupMember.isActiveStatus()) { + throw new Exception400("이미 가입된 회원입니다."); } - redisUtils.deleteValues(MEMBER_ID_PREFIX + memberId); + // 재가입 회원인지 확인 + wasGroupMember.changeStatus(); - } catch (Exception400 | Exception404 e) { - throw e; - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); + // GroupMember 저장 + saveGroupMember(member, group, wasGroupMember); + } else { + groupNickNameCheck(groupId, groupNickName); + + saveGroupMember(member, group, buildGroupMember(member, group, groupNickName)); } + + redisUtils.deleteValues(MEMBER_ID_PREFIX + memberId); } private void saveGroupMember(Member member, Group group, GroupMember groupMember) { @@ -311,59 +264,38 @@ protected void checkJoinPermission(Long memberId, Long groupId) { 그룹 내 그룹원 리스트 조회 */ public GroupResponseDTO.GetGroupMembersResponseDTO getGroupMembers(Long groupId, Long memberId) { - try { - Group group = getGroupById(groupId); - getActiveGroupMember(groupId, memberId); - - return new GroupResponseDTO.GetGroupMembersResponseDTO(group); + Group group = getGroupById(groupId); + getActiveGroupMember(groupId, memberId); - } catch (Exception400 | Exception404 e) { - throw e; - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); - } + return new GroupResponseDTO.GetGroupMembersResponseDTO(group); } /* 그룹 내 마이 페이지 */ public GroupResponseDTO.MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long memberId) { - try { - // 그룹 멤버 확인 - GroupMember groupMember = getActiveGroupMember(groupId, memberId); - - // 해당 멤버의 Post 기록 정보 확인(History에서 가져옴) - Pageable pageable = PageRequest.of(0, 10); - Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember.getId(), pageable); + // 그룹 멤버 확인 + GroupMember groupMember = getActiveGroupMember(groupId, memberId); - // 그룹 이름, 현재 닉네임, Post 기록 정보를 담은 responseDTO 반환 - return new GroupResponseDTO.MyGroupInfoResponseDTO(groupMember.getGroup(), groupMember, myHistoryList); + // 해당 멤버의 Post 기록 정보 확인(History에서 가져옴) + Pageable pageable = PageRequest.of(0, 10); + Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember.getId(), pageable); - } catch (Exception404 e) { - throw e; - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); - } + // 그룹 이름, 현재 닉네임, Post 기록 정보를 담은 responseDTO 반환 + return new GroupResponseDTO.MyGroupInfoResponseDTO(groupMember.getGroup(), groupMember, myHistoryList); } /* 내 문서 기여 목록 전체 보기 */ public GroupResponseDTO.MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId, Long memberId, int page, int size) { - try { - // 그룹 멤버 확인 - GroupMember groupMember = getActiveGroupMember(groupId, memberId); - - Pageable pageable = PageRequest.of(page, size); - Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember.getId(), pageable); + // 그룹 멤버 확인 + GroupMember groupMember = getActiveGroupMember(groupId, memberId); - return new GroupResponseDTO.MyGroupHistoryResponseDTO(myHistoryList); + Pageable pageable = PageRequest.of(page, size); + Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember.getId(), pageable); - } catch (Exception404 e) { - throw e; - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); - } + return new GroupResponseDTO.MyGroupHistoryResponseDTO(myHistoryList); } @@ -372,37 +304,30 @@ public GroupResponseDTO.MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId */ @Transactional public void updateMyGroupPage(Long groupId, Long memberId, GroupRequestDTO.UpdateMyGroupPageDTO requestDTO) { - try { - // 그룹 멤버 확인 - GroupMember groupMember = getActiveGroupMember(groupId, memberId); - - // 변경할 닉네임 확인 - String newNickName = requestDTO.groupNickName(); + // 그룹 멤버 확인 + GroupMember groupMember = getActiveGroupMember(groupId, memberId); - // 빈칸일 경우 예외 처리 - if(newNickName.isEmpty()) { - throw new Exception400("공백은 닉네임이 될 수 없습니다."); - } + // 변경할 닉네임 확인 + String newNickName = requestDTO.groupNickName(); - // 기존 닉네임과 같은 경우 예외 처리 - if(groupMember.getNickName().equals(newNickName)) { - throw new Exception400("기존 닉네임과 같은 닉네임입니다."); - } + // 빈칸일 경우 예외 처리 + if(newNickName.isEmpty()) { + throw new Exception400("공백은 닉네임이 될 수 없습니다."); + } - // 이미 있는 경우 예외 처리 - groupNickNameCheck(groupId, requestDTO.groupNickName()); + // 기존 닉네임과 같은 경우 예외 처리 + if(groupMember.getNickName().equals(newNickName)) { + throw new Exception400("기존 닉네임과 같은 닉네임입니다."); + } - // 그룹 닉네임 변경 - groupMember.update(requestDTO.groupNickName()); + // 이미 있는 경우 예외 처리 + groupNickNameCheck(groupId, requestDTO.groupNickName()); - // 저장 - groupMemberJPARepository.save(groupMember); + // 그룹 닉네임 변경 + groupMember.update(requestDTO.groupNickName()); - } catch (Exception400 | Exception404 e) { - throw e; - } catch (Exception e) { - throw new Exception500("서버 에러가 발생했습니다."); - } + // 저장 + groupMemberJPARepository.save(groupMember); } From 13049e0700b76f6c1dfa849a271e450e9dbe11d5 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Thu, 9 Nov 2023 01:16:02 +0900 Subject: [PATCH 110/144] =?UTF-8?q?Fix:=20Cascade=20=EC=A0=84=EB=9E=B5=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove 삭제 --- .../main/java/com/kakao/techcampus/wekiki/comment/Comment.java | 2 +- .../main/java/com/kakao/techcampus/wekiki/history/History.java | 2 +- .../main/java/com/kakao/techcampus/wekiki/page/PageInfo.java | 2 +- wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java | 2 +- .../main/java/com/kakao/techcampus/wekiki/report/Report.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java index ee07248d..7273209d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java @@ -16,7 +16,7 @@ public class Comment { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) + @ManyToOne(fetch = FetchType.LAZY) private GroupMember groupMember; @Setter diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java index 52a68b96..3dc299b0 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/History.java @@ -16,7 +16,7 @@ public class History { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) + @ManyToOne(fetch = FetchType.LAZY) private GroupMember groupMember; @Setter diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java index 41f7d520..6e6cbbcb 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageInfo.java @@ -21,7 +21,7 @@ public class PageInfo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) + @ManyToOne(fetch = FetchType.LAZY) private Group group; private String pageName; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java index 9d42013a..958f6193 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/Post.java @@ -26,7 +26,7 @@ public class Post { private int orders; - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) + @ManyToOne(fetch = FetchType.LAZY) private GroupMember groupMember; @Setter diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java index 9d78c8d1..d114ff7d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/Report.java @@ -19,7 +19,7 @@ public class Report { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) + @ManyToOne(fetch = FetchType.LAZY) private GroupMember fromMember; @ManyToOne(fetch = FetchType.LAZY) From 470614edade14b8371369366a70771a27a37880b Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Thu, 9 Nov 2023 02:40:54 +0900 Subject: [PATCH 111/144] =?UTF-8?q?Fix=20:=20=ED=94=84=EB=A1=A0=ED=8A=B8?= =?UTF-8?q?=20=EA=B4=80=EB=A0=A8=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kakao/techcampus/wekiki/member/MemberController.java | 3 ++- .../kakao/techcampus/wekiki/member/MemberRequest.java | 9 +++++++++ .../kakao/techcampus/wekiki/member/MemberService.java | 2 ++ .../com/kakao/techcampus/wekiki/page/PageService.java | 6 +++--- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java index 25a36892..2f5ba741 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java @@ -1,6 +1,7 @@ package com.kakao.techcampus.wekiki.member; import com.kakao.techcampus.wekiki._core.utils.ApiUtils; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -12,7 +13,7 @@ public class MemberController { private final MemberService memberService; @PostMapping("/signup") - public ResponseEntity signUp(@RequestBody MemberRequest.signUpRequestDTO signUpRequestDTO) { + public ResponseEntity signUp(@Valid @RequestBody MemberRequest.signUpRequestDTO signUpRequestDTO) { memberService.signUp(signUpRequestDTO); return ResponseEntity.ok(true); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java index 77ac6a02..8823a3f1 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java @@ -1,15 +1,24 @@ package com.kakao.techcampus.wekiki.member; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import org.springframework.security.core.parameters.P; @AllArgsConstructor public class MemberRequest { @Getter public static class signUpRequestDTO { + @NotNull + @Pattern(regexp = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$", message = "(계정@도메인.최상위도메인 형식)") private String email; + @NotNull + @Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*[0-9]).{8,20}$", message = "(8~20자 영문과 숫자)") private String password; + @NotNull + @Pattern(regexp = "^[가-힣a-zA-Z]{2,10}$", message = "(2~10자 한글, 영어)") private String nickName; } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index a0c7acef..edcf2a89 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -99,6 +99,7 @@ public MemberResponse.myInfoResponseDTO getMyInfo() { throw e; } List infoGroupDTOList = member.getGroupMembers().stream() + .filter(GroupMember::isActiveStatus) .map(groupMember -> { return new MemberResponse.myInfoResponseDTO.myInfoGroupDTO(groupMember, groupMember.getGroup()); }).collect(Collectors.toList()); @@ -118,6 +119,7 @@ public void cancel() { for (GroupMember g : member.getGroupMembers()) { g.update("알수없음"); g.changeMember(cancelMember); + g.changeStatus(); } //member.delete(passwordEncoder.encode(makeRandomPassword())); memberRepository.delete(member); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index aef3660d..7e093d5d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -80,14 +80,14 @@ private List getMyGroupList (List private List getOfficialGroupList () { return groupJPARepository.findAllOfficialGroup().stream() .map(PageInfoResponse.mainPageDTO.GroupDTO::new) - .limit(5) + .limit(3) .collect(Collectors.toList()); } private List getUnLoginUnOfficialGroupList() { return groupJPARepository.findAllUnOfficialOpenGroup().stream() .map(PageInfoResponse.mainPageDTO.GroupDTO::new) - .limit(5) + .limit(8) .collect(Collectors.toList()); } @@ -95,7 +95,7 @@ private List getLoginUnOfficialGroupList( return groupJPARepository.findAllUnOfficialOpenGroup().stream() .map(PageInfoResponse.mainPageDTO.GroupDTO::new) .filter(tempGroup -> !myGroupIdList.contains(tempGroup.getGroupId())) - .limit(5) + .limit(8) .toList(); } From 972bfb91fd9296bb76883fa8be6174efc657ef15 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Thu, 9 Nov 2023 02:41:42 +0900 Subject: [PATCH 112/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=ED=83=88=ED=87=B4=20=EC=8B=9C=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kakao/techcampus/wekiki/group/domain/GroupMember.java | 2 +- .../com/kakao/techcampus/wekiki/group/service/GroupService.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/GroupMember.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/GroupMember.java index 5e6a2856..8db3107e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/GroupMember.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/GroupMember.java @@ -27,7 +27,7 @@ private String nickName; private int memberLevel; private LocalDateTime created_at; - boolean activeStatus; + private boolean activeStatus; @Builder public GroupMember(Long id, Member member, Group group, String nickName, LocalDateTime created_at) { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 3d0418b6..753a9908 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -227,6 +227,7 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ // 재가입 회원인지 확인 wasGroupMember.changeStatus(); + wasGroupMember.update(requestDTO.nickName()); // GroupMember 저장 saveGroupMember(member, group, wasGroupMember); @@ -343,6 +344,7 @@ public void leaveGroup(Long groupId, Long memberId) { if(group.getMemberCount() != 1) { group.minusMemberCount(); groupMember.changeStatus(); + groupMember.update("알수없음"); Member member = getMemberById(memberId); member.getGroupMembers().remove(groupMember); From 85fe830a766c973f3ecbb43b35142249c47ce96e Mon Sep 17 00:00:00 2001 From: JunHee Date: Thu, 9 Nov 2023 03:15:24 +0900 Subject: [PATCH 113/144] Update README.md --- README.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b2d9e7c2..2ebf2a3f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,30 @@ # Team8_BE -8조 + +## 프로젝트 소개 +스크린샷 2023-11-09 오전 3 08 11 + +||설명| +|-----------|----| +|제목 |위키키| +|개발 목적| 그룹별로 자신들만의 나무위키를 만들고, 기록하고자 하는 사람들을 위해 프로젝트를 만들었습니다. | +|개발 기간|2023.09 - 2023.11| + +## 팀원 +| [이준희](https://github.com/Jun2-Lee) | [김돈우](https://github.com/kimdonwoo) | [황인욱](https://github.com/INUK-ai)| +|----------|----------|----------| +| | | | + + + + + + + + + + + + ## 카카오 테크 캠퍼스 3단계 진행 보드
From d0538b5ac9351a16923a783299226e4b6f85b09d Mon Sep 17 00:00:00 2001 From: JunHee Date: Thu, 9 Nov 2023 03:32:57 +0900 Subject: [PATCH 114/144] Update README.md --- README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2ebf2a3f..0999e20d 100644 --- a/README.md +++ b/README.md @@ -14,18 +14,68 @@ |----------|----------|----------| | | | | +
+## 주요기능 +<주요 기능 적기> +## 문서 +|문서 목록| +|----| +[GitHub (FE)](https://github.com/Step3-kakao-tech-campus/Team8_FE) +[ERD](https://www.notion.so/ERD-e0a43b03115d4551a6138d7b98c43e68) +[API 문서](https://www.notion.so/API-e6a2fe24cffe4c54ad9815f32dd8790b) +[와이어프레임](https://www.figma.com/file/HrjwnC0UfzYJjmwaBRg7uj/8%EC%A1%B0-%EC%99%80%EC%9D%B4%EC%96%B4-%ED%94%84%EB%A0%88%EC%9E%84-Web-%2F-Mobile?type=design&node-id=0-1&mode=design&t=wkU2aDHsx0pHTvYT-0) +## 기술 스택 +**Spring Boot** : 3.1.4 +- **Spring Security** +- **JPA** +- **Lombok** +- **Actuator** +- **JWT** +- **Validation** +**Java** : 17 +**DB** +- 테스트/로컬 용 : H2 +- 배포용 : MariaDB 최신 버전 + +**redis** + + +## How to Use + +``` +git clone https://github.com/Step3-kakao-tech-campus/Team8_BE.git +// 깃헙 주소 클론 +// 그 뒤 로컬 저장소로 이동 +./gradlew build +// 프로젝트 빌드 +java -jar ./build/libs/wekiki-0.0.1-SNAPSHOT.jar +// 빌드 파일 실행 +``` + + + + + + + + + + + +
+카카오 테크 캠퍼스 3단계 진행 보드 +
-## 카카오 테크 캠퍼스 3단계 진행 보드
@@ -273,6 +323,9 @@ UI 컴포넌트의 명칭과 이를 구현하는 능력은 필수적인 커뮤
+
+
+ --- From d937386ec39155a639f7c3cf17ab9a4e11e18791 Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Thu, 9 Nov 2023 15:30:04 +0900 Subject: [PATCH 115/144] =?UTF-8?q?Feat=20:=20=EC=B9=B4=EC=B9=B4=EC=98=A4?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=94=84=EB=A1=9D=EC=8B=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wekiki/member/MemberService.java | 21 +++++++++++++++---- wekiki/src/main/resources/application.yml | 3 --- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index edcf2a89..02e85d41 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -14,6 +14,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; +import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.security.authentication.AuthenticationManager; @@ -27,6 +28,8 @@ import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; +import java.net.InetSocketAddress; +import java.net.Proxy; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -53,6 +56,8 @@ public class MemberService { private String KAKAO_REDIRECT_URI; @Value("${kakao.client.password") private String KAKAO_PASSWORD; + private static final String PROXY_HOST = "krmp-proxy.9rum.cc"; + private static final int PROXY_PORT = 3128; public void signUp(MemberRequest.signUpRequestDTO signUpRequestDTO) { @@ -231,7 +236,7 @@ private Member findMember() { public MemberResponse.authTokenDTO getKakaoInfo(String code) { String accessToken = ""; - + log.info("카카오 엑세스 토큰 발급 시작"); try{ HttpHeaders headers = new HttpHeaders(); headers.add("Content-type", "application/x-www-form-urlencoded"); @@ -242,7 +247,10 @@ public MemberResponse.authTokenDTO getKakaoInfo(String code) { params.add("code", code); params.add("redirect_uri", KAKAO_REDIRECT_URI); - RestTemplate restTemplate = new RestTemplate(); + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_HOST, PROXY_PORT)); + SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); + requestFactory.setProxy(proxy); + RestTemplate restTemplate = new RestTemplate(requestFactory); System.out.println(restTemplate.getClass()); HttpEntity> httpEntity = new HttpEntity<>(params, headers); @@ -252,11 +260,11 @@ public MemberResponse.authTokenDTO getKakaoInfo(String code) { httpEntity, String.class ); + log.info("카카오 엑세스 토큰 발급 완료"); ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); MemberResponse.KakaoTokenDTO kakaoTokenDTO = objectMapper.readValue(response.getBody(), MemberResponse.KakaoTokenDTO.class); accessToken = kakaoTokenDTO.getAccess_token(); - } catch (JsonProcessingException e) { log.error("파싱 오류", e); throw new Exception500("Json 파싱 에러입니다."); @@ -285,7 +293,12 @@ private void kakaoSignUp(MemberResponse.KakaoInfoDTO kakaoInfo, String kakaoEmai private MemberResponse.KakaoInfoDTO getUserInfoWithToken(String accessToken) { MemberResponse.KakaoInfoDTO kakaoInfo = null; - RestTemplate restTemplate = new RestTemplate(); + + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_HOST, PROXY_PORT)); + SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); + requestFactory.setProxy(proxy); + + RestTemplate restTemplate = new RestTemplate(requestFactory); System.out.println(restTemplate.getClass()); diff --git a/wekiki/src/main/resources/application.yml b/wekiki/src/main/resources/application.yml index b232792f..7169003f 100644 --- a/wekiki/src/main/resources/application.yml +++ b/wekiki/src/main/resources/application.yml @@ -34,9 +34,6 @@ spring: starttls: enable: true required: true - proxy: - host: krmp-proxy.9rum.cc - port: 3128 jwt: secret: 7ZmA656AIOuTneygkOyZlSDquLDsm5AgMeydvOywqALdlsKJL3234jklsdjfaKJDLnflkasdf kakao: From aad3024477796d2d3bec4bec2c4c81aa14c176fe Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Thu, 9 Nov 2023 15:39:47 +0900 Subject: [PATCH 116/144] =?UTF-8?q?Refactor=20:=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kakao/techcampus/wekiki/_core/config/ProxyConfig.java | 2 +- .../java/com/kakao/techcampus/wekiki/member/MemberService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/ProxyConfig.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/ProxyConfig.java index 96a46269..7233e111 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/ProxyConfig.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/config/ProxyConfig.java @@ -15,7 +15,7 @@ public class ProxyConfig { private static final int PROXY_PORT = 3128; @Bean - public RestTemplate restTemplateWithProxy() { + public RestTemplate restTemplate() { SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_HOST, PROXY_PORT)); requestFactory.setProxy(proxy); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index 02e85d41..d26a075e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -9,6 +9,7 @@ import com.kakao.techcampus.wekiki.group.domain.GroupMember; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -49,7 +50,6 @@ public class MemberService { private final PasswordEncoder passwordEncoder; private final RedisUtility redisUtility; private final JavaMailSender javaMailSender; - private final RestTemplate restTemplate; @Value("${kakao.client.id}") private String KAKAO_CLIENT_ID; @Value("${kakao.redirect.uri}") From e457300a71e988b9d8a1ab13fe25f8fb4b7f8c75 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Thu, 9 Nov 2023 18:48:23 +0900 Subject: [PATCH 117/144] =?UTF-8?q?Refactor:=20=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=EB=A9=94=EC=84=B8=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 각 필요한 memberId, groupId 추가 --- log/error/error-2023-11-09.log | 51 +++++ log/info/info-2023-11-09.log | 182 ++++++++++++++++++ log/warn/warn-2023-11-09.log | 63 ++++++ .../wekiki/group/service/GroupService.java | 98 +++++++++- .../src/main/resources/console-appender.xml | 7 + .../main/resources/file-error-appender.xml | 19 ++ .../src/main/resources/file-info-appender.xml | 19 ++ .../src/main/resources/file-warn-appender.xml | 19 ++ wekiki/src/main/resources/logback-spring.xml | 27 +++ 9 files changed, 477 insertions(+), 8 deletions(-) create mode 100644 log/error/error-2023-11-09.log create mode 100644 log/info/info-2023-11-09.log create mode 100644 log/warn/warn-2023-11-09.log create mode 100644 wekiki/src/main/resources/console-appender.xml create mode 100644 wekiki/src/main/resources/file-error-appender.xml create mode 100644 wekiki/src/main/resources/file-info-appender.xml create mode 100644 wekiki/src/main/resources/file-warn-appender.xml create mode 100644 wekiki/src/main/resources/logback-spring.xml diff --git a/log/error/error-2023-11-09.log b/log/error/error-2023-11-09.log new file mode 100644 index 00000000..dbb6a8ca --- /dev/null +++ b/log/error/error-2023-11-09.log @@ -0,0 +1,51 @@ +[2023-11-09 03:36:58:152700] [restartedMain] ERROR [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory:426] - Failed to initialize JPA EntityManagerFactory: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'javax.persistence.jdbc.url', 'hibernate.connection.url', or 'hibernate.dialect') +[2023-11-09 03:36:58:152900] [restartedMain] ERROR [org.springframework.boot.SpringApplication.reportFailure:827] - Application run failed +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'javax.persistence.jdbc.url', 'hibernate.connection.url', or 'hibernate.dialect') + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1158) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) + at com.kakao.techcampus.wekiki.WekikiApplication.main(WekikiApplication.java:10) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:568) + at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) +Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'javax.persistence.jdbc.url', 'hibernate.connection.url', or 'hibernate.dialect') + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:277) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:239) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:216) + at org.hibernate.boot.model.relational.Database.(Database.java:45) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:231) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:199) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:169) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1380) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1451) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1817) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766) + ... 21 common frames omitted +Caused by: org.hibernate.HibernateException: Unable to determine Dialect without JDBC metadata (please set 'javax.persistence.jdbc.url', 'hibernate.connection.url', or 'hibernate.dialect') + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:188) + at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:87) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:274) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:34) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:119) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + ... 36 common frames omitted diff --git a/log/info/info-2023-11-09.log b/log/info/info-2023-11-09.log new file mode 100644 index 00000000..c9b5dd63 --- /dev/null +++ b/log/info/info-2023-11-09.log @@ -0,0 +1,182 @@ +[2023-11-09 03:36:55:149936] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarting:51] - Starting WekikiApplication using Java 17.0.7 with PID 14820 (D:\카카오 테크 캠퍼스\Wikiki\wekiki\out\production\classes started by arheo in D:\카카오 테크 캠퍼스\Wikiki) +[2023-11-09 03:36:55:149938] [restartedMain] INFO  [org.springframework.boot.SpringApplication.logStartupProfileInfo:643] - The following 1 profile is active: "prod" +[2023-11-09 03:36:57:151884] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode +[2023-11-09 03:36:57:151885] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data JPA repositories in DEFAULT mode. +[2023-11-09 03:36:57:151956] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 70 ms. Found 8 JPA repository interfaces. +[2023-11-09 03:36:57:151962] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode +[2023-11-09 03:36:57:151962] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +[2023-11-09 03:36:57:151973] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.comment.CommentJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:36:57:151974] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:36:57:151974] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:36:57:151975] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.history.HistoryJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:36:57:151976] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.member.MemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:36:57:151976] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.page.PageJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:36:57:151977] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.post.PostJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:36:57:151977] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.report.ReportJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:36:57:151978] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 14 ms. Found 0 Redis repository interfaces. +[2023-11-09 03:36:58:152315] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize:108] - Tomcat initialized with port(s): 8080 (http) +[2023-11-09 03:36:58:152317] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing ProtocolHandler ["http-nio-8080"] +[2023-11-09 03:36:58:152318] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting service [Tomcat] +[2023-11-09 03:36:58:152318] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting Servlet engine: [Apache Tomcat/10.1.13] +[2023-11-09 03:36:58:152376] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring embedded WebApplicationContext +[2023-11-09 03:36:58:152377] [restartedMain] INFO  [org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.prepareWebApplicationContext:291] - Root WebApplicationContext: initialization completed in 2433 ms +[2023-11-09 03:36:58:152462] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:110] - HikariPool-2 - Starting... +[2023-11-09 03:36:58:152645] [restartedMain] INFO  [org.hibernate.jpa.internal.util.LogHelper.logPersistenceUnitInformation:31] - HHH000204: Processing PersistenceUnitInfo [name: default] +[2023-11-09 03:36:58:152676] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy +[2023-11-09 03:36:58:152676] [restartedMain] INFO  [org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo.addTransformer:87] - No LoadTimeWeaver setup: ignoring JPA class transformer +[2023-11-09 03:36:58:152679] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:110] - HikariPool-2 - Starting... +[2023-11-09 03:36:58:152818] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Stopping service [Tomcat] +[2023-11-09 03:36:58:152840] [restartedMain] INFO  [org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLogger.logMessage:82] - + +Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. +[2023-11-09 03:38:12:1992] [background-preinit] INFO  [org.hibernate.validator.internal.util.Version.:21] - HV000001: Hibernate Validator 8.0.1.Final +[2023-11-09 03:38:12:2076] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarting:51] - Starting WekikiApplication using Java 17.0.7 with PID 12116 (D:\카카오 테크 캠퍼스\Wikiki\wekiki\out\production\classes started by arheo in D:\카카오 테크 캠퍼스\Wikiki) +[2023-11-09 03:38:12:2078] [restartedMain] INFO  [org.springframework.boot.SpringApplication.logStartupProfileInfo:643] - The following 1 profile is active: "prod" +[2023-11-09 03:38:12:2195] [restartedMain] INFO  [org.springframework.boot.logging.DeferredLog.logTo:250] - Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable +[2023-11-09 03:38:12:2195] [restartedMain] INFO  [org.springframework.boot.logging.DeferredLog.logTo:250] - For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' +[2023-11-09 03:38:15:4671] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode +[2023-11-09 03:38:15:4679] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data JPA repositories in DEFAULT mode. +[2023-11-09 03:38:15:5158] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 449 ms. Found 8 JPA repository interfaces. +[2023-11-09 03:38:15:5190] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode +[2023-11-09 03:38:15:5193] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +[2023-11-09 03:38:15:5226] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.comment.CommentJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:38:15:5229] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:38:15:5229] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:38:15:5230] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.history.HistoryJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:38:15:5230] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.member.MemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:38:15:5232] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.page.PageJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:38:15:5232] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.post.PostJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:38:15:5232] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.report.ReportJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:38:15:5233] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 23 ms. Found 0 Redis repository interfaces. +[2023-11-09 03:38:17:6854] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize:108] - Tomcat initialized with port(s): 8080 (http) +[2023-11-09 03:38:17:6883] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing ProtocolHandler ["http-nio-8080"] +[2023-11-09 03:38:17:6890] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting service [Tomcat] +[2023-11-09 03:38:17:6892] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting Servlet engine: [Apache Tomcat/10.1.13] +[2023-11-09 03:38:17:7108] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring embedded WebApplicationContext +[2023-11-09 03:38:17:7108] [restartedMain] INFO  [org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.prepareWebApplicationContext:291] - Root WebApplicationContext: initialization completed in 4912 ms +[2023-11-09 03:38:17:7378] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:110] - HikariPool-1 - Starting... +[2023-11-09 03:38:18:8111] [restartedMain] INFO  [com.zaxxer.hikari.pool.HikariPool.checkFailFast:565] - HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:test user=SA +[2023-11-09 03:38:18:8116] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:123] - HikariPool-1 - Start completed. +[2023-11-09 03:38:18:8141] [restartedMain] INFO  [org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.logDataSources:88] - H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:test' +[2023-11-09 03:38:19:8975] [restartedMain] INFO  [org.hibernate.jpa.internal.util.LogHelper.logPersistenceUnitInformation:31] - HHH000204: Processing PersistenceUnitInfo [name: default] +[2023-11-09 03:38:19:9143] [restartedMain] INFO  [org.hibernate.Version.logVersion:44] - HHH000412: Hibernate ORM core version 6.2.9.Final +[2023-11-09 03:38:19:9148] [restartedMain] INFO  [org.hibernate.cfg.Environment.:191] - HHH000406: Using bytecode reflection optimizer +[2023-11-09 03:38:20:9523] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy +[2023-11-09 03:38:20:9909] [restartedMain] INFO  [org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo.addTransformer:87] - No LoadTimeWeaver setup: ignoring JPA class transformer +[2023-11-09 03:38:21:10719] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy +[2023-11-09 03:38:23:12664] [restartedMain] INFO  [org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator.initiateService:51] - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] +[2023-11-09 03:38:23:12843] [restartedMain] INFO  [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory:437] - Initialized JPA EntityManagerFactory for persistence unit 'default' +[2023-11-09 03:38:23:13503] [restartedMain] INFO  [org.springframework.data.jpa.repository.query.QueryEnhancerFactory.:47] - Hibernate is in classpath; If applicable, HQL parser will be used. +[2023-11-09 03:38:26:16280] [restartedMain] INFO  [org.springframework.security.web.DefaultSecurityFilterChain.:54] - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@6266514f, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@120d634a, org.springframework.security.web.context.SecurityContextHolderFilter@48b1cc4, org.springframework.security.web.header.HeaderWriterFilter@417a72c, org.springframework.security.web.authentication.logout.LogoutFilter@1b311e61, com.kakao.techcampus.wekiki._core.jwt.JWTTokenFilter@7a64296a, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@25ac6dd9, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@6d76c1db, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@7f04d285, org.springframework.security.web.session.SessionManagementFilter@4cce2364, org.springframework.security.web.access.ExceptionTranslationFilter@5d43f22a, org.springframework.security.web.access.intercept.AuthorizationFilter@7230456c] +[2023-11-09 03:38:28:17669] [restartedMain] INFO  [org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer.startServer:59] - LiveReload server is running on port 35729 +[2023-11-09 03:38:28:17680] [restartedMain] INFO  [org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver.:58] - Exposing 1 endpoint(s) beneath base path '/actuator' +[2023-11-09 03:38:28:17811] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting ProtocolHandler ["http-nio-8080"] +[2023-11-09 03:38:28:17860] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start:220] - Tomcat started on port(s): 8080 (http) with context path '' +[2023-11-09 03:38:28:17893] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarted:57] - Started WekikiApplication in 17.304 seconds (process running for 18.961) +[2023-11-09 03:38:28:18466] [RMI TCP Connection(7)-192.168.0.45] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring DispatcherServlet 'dispatcherServlet' +[2023-11-09 03:38:28:18468] [RMI TCP Connection(7)-192.168.0.45] INFO  [org.springframework.web.servlet.FrameworkServlet.initServletBean:532] - Initializing Servlet 'dispatcherServlet' +[2023-11-09 03:38:28:18471] [RMI TCP Connection(7)-192.168.0.45] INFO  [org.springframework.web.servlet.FrameworkServlet.initServletBean:554] - Completed initialization in 3 ms +[2023-11-09 03:41:31:201484] [SpringApplicationShutdownHook] INFO  [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.destroy:650] - Closing JPA EntityManagerFactory for persistence unit 'default' +[2023-11-09 03:41:32:201927] [SpringApplicationShutdownHook] INFO  [com.zaxxer.hikari.HikariDataSource.close:350] - HikariPool-1 - Shutdown initiated... +[2023-11-09 03:41:32:201940] [SpringApplicationShutdownHook] INFO  [com.zaxxer.hikari.HikariDataSource.close:352] - HikariPool-1 - Shutdown completed. +[2023-11-09 03:42:28:2194] [background-preinit] INFO  [org.hibernate.validator.internal.util.Version.:21] - HV000001: Hibernate Validator 8.0.1.Final +[2023-11-09 03:42:28:2289] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarting:51] - Starting WekikiApplication using Java 17.0.7 with PID 9348 (D:\카카오 테크 캠퍼스\Wikiki\wekiki\out\production\classes started by arheo in D:\카카오 테크 캠퍼스\Wikiki) +[2023-11-09 03:42:28:2292] [restartedMain] INFO  [org.springframework.boot.SpringApplication.logStartupProfileInfo:643] - The following 1 profile is active: "prod" +[2023-11-09 03:42:28:2420] [restartedMain] INFO  [org.springframework.boot.logging.DeferredLog.logTo:250] - Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable +[2023-11-09 03:42:28:2421] [restartedMain] INFO  [org.springframework.boot.logging.DeferredLog.logTo:250] - For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' +[2023-11-09 03:42:34:8432] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode +[2023-11-09 03:42:34:8436] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data JPA repositories in DEFAULT mode. +[2023-11-09 03:42:35:8936] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 480 ms. Found 8 JPA repository interfaces. +[2023-11-09 03:42:35:8969] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode +[2023-11-09 03:42:35:8972] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +[2023-11-09 03:42:35:9009] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.comment.CommentJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:42:35:9012] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:42:35:9013] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:42:35:9014] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.history.HistoryJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:42:35:9015] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.member.MemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:42:35:9015] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.page.PageJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:42:35:9016] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.post.PostJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:42:35:9017] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.report.ReportJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:42:35:9018] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 26 ms. Found 0 Redis repository interfaces. +[2023-11-09 03:42:37:11281] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize:108] - Tomcat initialized with port(s): 8080 (http) +[2023-11-09 03:42:37:11301] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing ProtocolHandler ["http-nio-8080"] +[2023-11-09 03:42:37:11306] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting service [Tomcat] +[2023-11-09 03:42:37:11306] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting Servlet engine: [Apache Tomcat/10.1.13] +[2023-11-09 03:42:38:11501] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring embedded WebApplicationContext +[2023-11-09 03:42:38:11502] [restartedMain] INFO  [org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.prepareWebApplicationContext:291] - Root WebApplicationContext: initialization completed in 9080 ms +[2023-11-09 03:42:38:11788] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:110] - HikariPool-1 - Starting... +[2023-11-09 03:42:38:12369] [restartedMain] INFO  [com.zaxxer.hikari.pool.HikariPool.checkFailFast:565] - HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:test user=SA +[2023-11-09 03:42:38:12375] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:123] - HikariPool-1 - Start completed. +[2023-11-09 03:42:38:12401] [restartedMain] INFO  [org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.logDataSources:88] - H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:test' +[2023-11-09 03:42:40:13695] [restartedMain] INFO  [org.hibernate.jpa.internal.util.LogHelper.logPersistenceUnitInformation:31] - HHH000204: Processing PersistenceUnitInfo [name: default] +[2023-11-09 03:42:40:13877] [restartedMain] INFO  [org.hibernate.Version.logVersion:44] - HHH000412: Hibernate ORM core version 6.2.9.Final +[2023-11-09 03:42:40:13883] [restartedMain] INFO  [org.hibernate.cfg.Environment.:191] - HHH000406: Using bytecode reflection optimizer +[2023-11-09 03:42:40:14300] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy +[2023-11-09 03:42:41:14708] [restartedMain] INFO  [org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo.addTransformer:87] - No LoadTimeWeaver setup: ignoring JPA class transformer +[2023-11-09 03:42:42:15593] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy +[2023-11-09 03:42:44:18050] [restartedMain] INFO  [org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator.initiateService:51] - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] +[2023-11-09 03:42:44:18283] [restartedMain] INFO  [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory:437] - Initialized JPA EntityManagerFactory for persistence unit 'default' +[2023-11-09 03:42:45:19148] [restartedMain] INFO  [org.springframework.data.jpa.repository.query.QueryEnhancerFactory.:47] - Hibernate is in classpath; If applicable, HQL parser will be used. +[2023-11-09 03:42:48:22223] [restartedMain] INFO  [org.springframework.security.web.DefaultSecurityFilterChain.:54] - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@511dde8a, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@307f0225, org.springframework.security.web.context.SecurityContextHolderFilter@4c5a1b1f, org.springframework.security.web.header.HeaderWriterFilter@4d55ba96, org.springframework.security.web.authentication.logout.LogoutFilter@37bfb3e5, com.kakao.techcampus.wekiki._core.jwt.JWTTokenFilter@101ddcce, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@70815ff8, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@7044e0b5, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@4b4885dd, org.springframework.security.web.session.SessionManagementFilter@69b02f4b, org.springframework.security.web.access.ExceptionTranslationFilter@27d157f8, org.springframework.security.web.access.intercept.AuthorizationFilter@d6d9dd9] +[2023-11-09 03:42:50:23820] [restartedMain] INFO  [org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer.startServer:59] - LiveReload server is running on port 35729 +[2023-11-09 03:42:50:23833] [restartedMain] INFO  [org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver.:58] - Exposing 1 endpoint(s) beneath base path '/actuator' +[2023-11-09 03:42:50:24002] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting ProtocolHandler ["http-nio-8080"] +[2023-11-09 03:42:50:24057] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start:220] - Tomcat started on port(s): 8080 (http) with context path '' +[2023-11-09 03:42:50:24094] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarted:57] - Started WekikiApplication in 23.51 seconds (process running for 25.634) +[2023-11-09 03:42:51:24955] [RMI TCP Connection(4)-192.168.0.45] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring DispatcherServlet 'dispatcherServlet' +[2023-11-09 03:42:51:24956] [RMI TCP Connection(4)-192.168.0.45] INFO  [org.springframework.web.servlet.FrameworkServlet.initServletBean:532] - Initializing Servlet 'dispatcherServlet' +[2023-11-09 03:42:51:24959] [RMI TCP Connection(4)-192.168.0.45] INFO  [org.springframework.web.servlet.FrameworkServlet.initServletBean:554] - Completed initialization in 3 ms +[2023-11-09 03:44:31:125055] [SpringApplicationShutdownHook] INFO  [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.destroy:650] - Closing JPA EntityManagerFactory for persistence unit 'default' +[2023-11-09 03:44:31:125453] [SpringApplicationShutdownHook] INFO  [com.zaxxer.hikari.HikariDataSource.close:350] - HikariPool-1 - Shutdown initiated... +[2023-11-09 03:44:31:125466] [SpringApplicationShutdownHook] INFO  [com.zaxxer.hikari.HikariDataSource.close:352] - HikariPool-1 - Shutdown completed. +[2023-11-09 03:46:18:2528] [background-preinit] INFO  [org.hibernate.validator.internal.util.Version.:21] - HV000001: Hibernate Validator 8.0.1.Final +[2023-11-09 03:46:18:2692] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarting:51] - Starting WekikiApplication using Java 17.0.7 with PID 6724 (D:\카카오 테크 캠퍼스\Wikiki\wekiki\out\production\classes started by arheo in D:\카카오 테크 캠퍼스\Wikiki) +[2023-11-09 03:46:18:2698] [restartedMain] INFO  [org.springframework.boot.SpringApplication.logStartupProfileInfo:643] - The following 1 profile is active: "prod" +[2023-11-09 03:46:18:3106] [restartedMain] INFO  [org.springframework.boot.logging.DeferredLog.logTo:250] - Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable +[2023-11-09 03:46:18:3107] [restartedMain] INFO  [org.springframework.boot.logging.DeferredLog.logTo:250] - For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' +[2023-11-09 03:46:28:12861] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode +[2023-11-09 03:46:28:12866] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data JPA repositories in DEFAULT mode. +[2023-11-09 03:46:29:13447] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 559 ms. Found 8 JPA repository interfaces. +[2023-11-09 03:46:29:13485] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode +[2023-11-09 03:46:29:13488] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +[2023-11-09 03:46:29:13621] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.comment.CommentJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:46:29:13633] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:46:29:13638] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:46:29:13641] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.history.HistoryJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:46:29:13643] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.member.MemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:46:29:13660] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.page.PageJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:46:29:13661] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.post.PostJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:46:29:13662] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.report.ReportJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 03:46:29:13662] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 130 ms. Found 0 Redis repository interfaces. +[2023-11-09 03:46:31:16022] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize:108] - Tomcat initialized with port(s): 8080 (http) +[2023-11-09 03:46:31:16042] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing ProtocolHandler ["http-nio-8080"] +[2023-11-09 03:46:31:16047] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting service [Tomcat] +[2023-11-09 03:46:31:16048] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting Servlet engine: [Apache Tomcat/10.1.13] +[2023-11-09 03:46:31:16240] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring embedded WebApplicationContext +[2023-11-09 03:46:31:16241] [restartedMain] INFO  [org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.prepareWebApplicationContext:291] - Root WebApplicationContext: initialization completed in 13133 ms +[2023-11-09 03:46:32:16501] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:110] - HikariPool-1 - Starting... +[2023-11-09 03:46:32:17239] [restartedMain] INFO  [com.zaxxer.hikari.pool.HikariPool.checkFailFast:565] - HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:test user=SA +[2023-11-09 03:46:32:17244] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:123] - HikariPool-1 - Start completed. +[2023-11-09 03:46:32:17269] [restartedMain] INFO  [org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.logDataSources:88] - H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:test' +[2023-11-09 03:46:34:18376] [restartedMain] INFO  [org.hibernate.jpa.internal.util.LogHelper.logPersistenceUnitInformation:31] - HHH000204: Processing PersistenceUnitInfo [name: default] +[2023-11-09 03:46:34:18604] [restartedMain] INFO  [org.hibernate.Version.logVersion:44] - HHH000412: Hibernate ORM core version 6.2.9.Final +[2023-11-09 03:46:34:18611] [restartedMain] INFO  [org.hibernate.cfg.Environment.:191] - HHH000406: Using bytecode reflection optimizer +[2023-11-09 03:46:34:19149] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy +[2023-11-09 03:46:35:19617] [restartedMain] INFO  [org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo.addTransformer:87] - No LoadTimeWeaver setup: ignoring JPA class transformer +[2023-11-09 03:46:36:20589] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy +[2023-11-09 03:46:39:23764] [restartedMain] INFO  [org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator.initiateService:51] - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] +[2023-11-09 03:46:39:23937] [restartedMain] INFO  [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory:437] - Initialized JPA EntityManagerFactory for persistence unit 'default' +[2023-11-09 03:46:41:25386] [restartedMain] INFO  [org.springframework.data.jpa.repository.query.QueryEnhancerFactory.:47] - Hibernate is in classpath; If applicable, HQL parser will be used. +[2023-11-09 03:46:44:28384] [restartedMain] INFO  [org.springframework.security.web.DefaultSecurityFilterChain.:54] - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@1dfa906e, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@384290, org.springframework.security.web.context.SecurityContextHolderFilter@6b85d8d4, org.springframework.security.web.header.HeaderWriterFilter@7c4c24f2, org.springframework.security.web.authentication.logout.LogoutFilter@2c2348fc, com.kakao.techcampus.wekiki._core.jwt.JWTTokenFilter@3ce14b3f, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@4bf95bf8, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@6378eded, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@4061e206, org.springframework.security.web.session.SessionManagementFilter@426e5e22, org.springframework.security.web.access.ExceptionTranslationFilter@4302a6c4, org.springframework.security.web.access.intercept.AuthorizationFilter@52e9f6cf] +[2023-11-09 03:46:45:30072] [restartedMain] INFO  [org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer.startServer:59] - LiveReload server is running on port 35729 +[2023-11-09 03:46:45:30089] [restartedMain] INFO  [org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver.:58] - Exposing 1 endpoint(s) beneath base path '/actuator' +[2023-11-09 03:46:45:30252] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting ProtocolHandler ["http-nio-8080"] +[2023-11-09 03:46:46:30298] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start:220] - Tomcat started on port(s): 8080 (http) with context path '' +[2023-11-09 03:46:46:30331] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarted:57] - Started WekikiApplication in 29.704 seconds (process running for 31.885) +[2023-11-09 03:46:46:30887] [RMI TCP Connection(2)-192.168.0.45] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring DispatcherServlet 'dispatcherServlet' +[2023-11-09 03:46:46:30888] [RMI TCP Connection(2)-192.168.0.45] INFO  [org.springframework.web.servlet.FrameworkServlet.initServletBean:532] - Initializing Servlet 'dispatcherServlet' +[2023-11-09 03:46:46:30893] [RMI TCP Connection(2)-192.168.0.45] INFO  [org.springframework.web.servlet.FrameworkServlet.initServletBean:554] - Completed initialization in 5 ms +[2023-11-09 03:49:07:171409] [http-nio-8080-exec-9] INFO  [com.kakao.techcampus.wekiki.group.service.GroupService.groupEntry:222] - 비밀번호 불일치 +[2023-11-09 03:50:42:266479] [SpringApplicationShutdownHook] INFO  [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.destroy:650] - Closing JPA EntityManagerFactory for persistence unit 'default' +[2023-11-09 03:50:42:266926] [SpringApplicationShutdownHook] INFO  [com.zaxxer.hikari.HikariDataSource.close:350] - HikariPool-1 - Shutdown initiated... +[2023-11-09 03:50:42:266953] [SpringApplicationShutdownHook] INFO  [com.zaxxer.hikari.HikariDataSource.close:352] - HikariPool-1 - Shutdown completed. diff --git a/log/warn/warn-2023-11-09.log b/log/warn/warn-2023-11-09.log new file mode 100644 index 00000000..ab45cc59 --- /dev/null +++ b/log/warn/warn-2023-11-09.log @@ -0,0 +1,63 @@ +[2023-11-09 03:36:58:152680] [restartedMain] WARN  [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService:244] - HHH000342: Could not obtain connection to query metadata +java.lang.RuntimeException: Driver org.mariadb.jdbc.Driver claims to not accept jdbcUrl, ${DATABASE_URL}?allowPublicKeyRetrieval=true&useSSL=false + at com.zaxxer.hikari.util.DriverDataSource.(DriverDataSource.java:110) + at com.zaxxer.hikari.pool.PoolBase.initializeDataSource(PoolBase.java:326) + at com.zaxxer.hikari.pool.PoolBase.(PoolBase.java:112) + at com.zaxxer.hikari.pool.HikariPool.(HikariPool.java:93) + at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) + at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:316) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:152) + at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:34) + at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:119) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:239) + at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:216) + at org.hibernate.boot.model.relational.Database.(Database.java:45) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:231) + at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:199) + at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:169) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1380) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1451) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1817) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1158) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) + at com.kakao.techcampus.wekiki.WekikiApplication.main(WekikiApplication.java:10) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:568) + at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) +[2023-11-09 03:36:58:152701] [restartedMain] WARN  [org.springframework.context.support.AbstractApplicationContext.refresh:616] - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'javax.persistence.jdbc.url', 'hibernate.connection.url', or 'hibernate.dialect') +[2023-11-09 03:38:24:14403] [restartedMain] WARN  [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.post.PostJPARepository +[2023-11-09 03:38:25:15350] [restartedMain] WARN  [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.page.PageJPARepository +[2023-11-09 03:40:09:119174] [http-nio-8080-exec-2] WARN  [org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException:207] - Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity com.kakao.techcampus.wekiki.member.MemberController.signUp(com.kakao.techcampus.wekiki.member.MemberRequest$signUpRequestDTO): [Field error in object 'signUpRequestDTO' on field 'password': rejected value [1234!]; codes [Pattern.signUpRequestDTO.password,Pattern.password,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [signUpRequestDTO.password,password]; arguments []; default message [password],[Ljakarta.validation.constraints.Pattern$Flag;@45662a21,^(?=.*[a-zA-Z])(?=.*[0-9]).{8,20}$]; default message [(8~20자 영문과 숫자)]] ] +[2023-11-09 03:41:32:201788] [SpringApplicationShutdownHook] WARN  [org.springframework.beans.factory.support.DisposableBeanAdapter.destroy:210] - Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214] +[2023-11-09 03:42:46:20493] [restartedMain] WARN  [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.post.PostJPARepository +[2023-11-09 03:42:47:21175] [restartedMain] WARN  [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.page.PageJPARepository +[2023-11-09 03:42:57:31170] [http-nio-8080-exec-2] WARN  [org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException:207] - Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity com.kakao.techcampus.wekiki.member.MemberController.signUp(com.kakao.techcampus.wekiki.member.MemberRequest$signUpRequestDTO): [Field error in object 'signUpRequestDTO' on field 'password': rejected value [1234!]; codes [Pattern.signUpRequestDTO.password,Pattern.password,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [signUpRequestDTO.password,password]; arguments []; default message [password],[Ljakarta.validation.constraints.Pattern$Flag;@253e3632,^(?=.*[a-zA-Z])(?=.*[0-9]).{8,20}$]; default message [(8~20자 영문과 숫자)]] ] +[2023-11-09 03:44:31:125314] [SpringApplicationShutdownHook] WARN  [org.springframework.beans.factory.support.DisposableBeanAdapter.destroy:210] - Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214] +[2023-11-09 03:46:42:26565] [restartedMain] WARN  [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.post.PostJPARepository +[2023-11-09 03:46:43:27315] [restartedMain] WARN  [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.page.PageJPARepository +[2023-11-09 03:48:14:118808] [http-nio-8080-exec-4] WARN  [org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException:207] - Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity com.kakao.techcampus.wekiki.member.MemberController.signUp(com.kakao.techcampus.wekiki.member.MemberRequest$signUpRequestDTO): [Field error in object 'signUpRequestDTO' on field 'nickName': rejected value [회원2]; codes [Pattern.signUpRequestDTO.nickName,Pattern.nickName,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [signUpRequestDTO.nickName,nickName]; arguments []; default message [nickName],[Ljakarta.validation.constraints.Pattern$Flag;@1a1cdc42,^[가-힣a-zA-Z]{2,10}$]; default message [(2~10자 한글, 영어)]] ] +[2023-11-09 03:49:07:171423] [http-nio-8080-exec-9] WARN  [org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException:207] - Resolved [com.kakao.techcampus.wekiki._core.error.exception.Exception400: 비밀번호가 틀렸습니다.] +[2023-11-09 03:50:42:266796] [SpringApplicationShutdownHook] WARN  [org.springframework.beans.factory.support.DisposableBeanAdapter.destroy:210] - Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214] diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 753a9908..f97aaadc 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -25,6 +25,7 @@ import com.kakao.techcampus.wekiki.report.Report; import com.kakao.techcampus.wekiki.report.ReportJPARepository; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -36,6 +37,7 @@ import java.util.List; import java.util.Optional; +@Slf4j @Transactional(readOnly = true) @RequiredArgsConstructor @Service @@ -63,17 +65,21 @@ public class GroupService { */ @Transactional public GroupResponseDTO.CreateUnOfficialGroupResponseDTO createUnOfficialGroup(GroupRequestDTO.CreateUnOfficialGroupRequestDTO requestDTO, Long memberId) { + // Group 생성 Group group = switch (requestDTO.groupType()) { case UNOFFICIAL_CLOSED -> buildUnOfficialClosedGroup(requestDTO); case UNOFFICIAL_OPENED -> buildUnOfficialOpenedGroup(requestDTO); default -> throw new Exception400("유효하지 않은 그룹 유형입니다."); }; + log.debug("그룹 생성 완료"); // MemberId로부터 Member 찾기 Member member = getMemberById(memberId); // GroupMember 생성 GroupMember groupMember = buildGroupMember(member, group, requestDTO.groupNickName()); + + log.debug("GroupMember 생성 완료"); // Entity 저장 group.addGroupMember(groupMember); @@ -82,6 +88,8 @@ public GroupResponseDTO.CreateUnOfficialGroupResponseDTO createUnOfficialGroup(G groupJPARepository.save(group); memberJPARepository.save(member); groupMemberJPARepository.save(groupMember); + + log.debug("Entity 저장 완료"); // return return new GroupResponseDTO.CreateUnOfficialGroupResponseDTO(group, invitationService.getGroupInvitationCode(group.getId())); @@ -138,6 +146,8 @@ public GroupResponseDTO.SearchGroupDTO searchGroupByKeyword(String keyword) { Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); // 비공식 공개 그룹 리스트 Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); + + log.debug("그룹 리스트 조회 완료"); return new GroupResponseDTO.SearchGroupDTO(officialGroups, unOfficialOpenedGroups); } @@ -148,10 +158,13 @@ public GroupResponseDTO.SearchGroupDTO searchGroupByKeyword(String keyword) { public GroupResponseDTO.SearchOfficialGroupResponseDTO searchOfficialGroupByKeyword(String keyword, int page) { Pageable pageable = PageRequest.of(page, GROUP_SEARCH_SIZE); - // 비공식 공개 그룹 리스트 + // 공식 그룹 리스트 Page officialGroups = groupJPARepository.findOfficialGroupsByKeyword(keyword, pageable); + log.debug("공식 그룹 리스트 조회 완료"); + if (officialGroups.isEmpty()) { + log.info("공식 그룹 마지막 페이지"); throw new Exception404("마지막 페이지입니다."); } @@ -167,7 +180,10 @@ public GroupResponseDTO.SearchUnOfficialGroupResponseDTO searchUnOfficialGroupBy // 비공식 공개 그룹 리스트 Page unOfficialOpenedGroups = groupJPARepository.findUnOfficialOpenedGroupsByKeyword(keyword, pageable); + log.debug("공개 그룹 리스트 조회 완료"); + if (unOfficialOpenedGroups.isEmpty()) { + log.info("비공식 공개 그룹 마지막 페이지"); throw new Exception404("마지막 페이지입니다."); } @@ -179,6 +195,8 @@ public GroupResponseDTO.SearchUnOfficialGroupResponseDTO searchUnOfficialGroupBy */ public GroupResponseDTO.SearchGroupInfoDTO getGroupInfo(Long groupId) { Group group = getGroupById(groupId); + + log.debug("그룹 상세 정보 조회 완료"); return new GroupResponseDTO.SearchGroupInfoDTO(group); } @@ -192,12 +210,20 @@ public void groupEntry(Long groupId, Long memberId, GroupRequestDTO.GroupEntryRe getMemberById(memberId); UnOfficialOpenedGroup group = groupJPARepository.findUnOfficialOpenedGroupById(groupId) - .orElseThrow(() -> new Exception404("그룹을 찾을 수 없습니다.")); + .orElseThrow(() -> { + log.info("그룹 조회 실패 " + memberId + " 번 회원, " + groupId + " 번 그룹"); + return new Exception404("그룹을 찾을 수 없습니다."); + }); + + log.debug("그룹 조회 완료"); // 틀린 경우, 에러 핸들링 if(!group.getEntrancePassword().equals(requestDTO.entrancePassword())) { + log.info("비밀번호 불일치 " + memberId + " 번 회원, " + groupId + " 번 그룹"); throw new Exception400("비밀번호가 틀렸습니다."); } + + log.debug("비밀번호 인증 완료"); redisUtils.setGroupIdValues(MEMBER_ID_PREFIX + memberId, groupId, Duration.ofHours(MEMBER_ID_LIFETIME)); } @@ -213,8 +239,9 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ Group group = getGroupById(groupId); checkJoinPermission(memberId, groupId); + + log.debug("가입 권한 확인 완료"); - // 그룹 내 닉네임 중복 예외 처리 String groupNickName = requestDTO.nickName(); GroupMember wasGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId, groupId); @@ -222,10 +249,10 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ if(wasGroupMember != null) { // 이미 가입한 상태일 시 예외 처리 if(wasGroupMember.isActiveStatus()) { + log.info("이미 가입된 회원 " + memberId + " 번 회원, " + groupId + " 번 그룹"); throw new Exception400("이미 가입된 회원입니다."); } - // 재가입 회원인지 확인 wasGroupMember.changeStatus(); wasGroupMember.update(requestDTO.nickName()); @@ -233,9 +260,13 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ saveGroupMember(member, group, wasGroupMember); } else { groupNickNameCheck(groupId, groupNickName); + + log.debug("그룹 닉네임 중복 확인 완료"); saveGroupMember(member, group, buildGroupMember(member, group, groupNickName)); } + + log.debug("그룹 참가 완료"); redisUtils.deleteValues(MEMBER_ID_PREFIX + memberId); } @@ -248,15 +279,21 @@ private void saveGroupMember(Member member, Group group, GroupMember groupMember groupJPARepository.save(group); memberJPARepository.save(member); groupMemberJPARepository.save(groupMember); + + log.debug("그룹 멤버 저장 완료"); } protected void checkJoinPermission(Long memberId, Long groupId) { Object oGroupId = Optional.ofNullable(redisUtils.getValues(MEMBER_ID_PREFIX + memberId)) - .orElseThrow(() -> new Exception404("해당 그룹에 가입할 수 없습니다.")); + .orElseThrow(() -> { + log.info("그룹 가입 권한 없음 " + memberId + " 번 회원, " + groupId + " 번 그룹"); + throw new Exception404("해당 그룹에 가입할 수 없습니다."); + }); Long lGroupId = ((Integer) oGroupId).longValue(); if(!lGroupId.equals(groupId)) { + log.info("현재 그룹에 대한 가입 권한 없음 " + memberId + " 번 회원, " + groupId + " 번 그룹"); throw new Exception400("현재 그룹에 가입할 수 없습니다."); } } @@ -267,6 +304,8 @@ protected void checkJoinPermission(Long memberId, Long groupId) { public GroupResponseDTO.GetGroupMembersResponseDTO getGroupMembers(Long groupId, Long memberId) { Group group = getGroupById(groupId); getActiveGroupMember(groupId, memberId); + + log.debug("그룹원 리스트 조회 완료"); return new GroupResponseDTO.GetGroupMembersResponseDTO(group); } @@ -281,6 +320,8 @@ public GroupResponseDTO.MyGroupInfoResponseDTO getMyGroupInfo(Long groupId, Long // 해당 멤버의 Post 기록 정보 확인(History에서 가져옴) Pageable pageable = PageRequest.of(0, 10); Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember.getId(), pageable); + + log.debug("히스토리 조회 완료"); // 그룹 이름, 현재 닉네임, Post 기록 정보를 담은 responseDTO 반환 return new GroupResponseDTO.MyGroupInfoResponseDTO(groupMember.getGroup(), groupMember, myHistoryList); @@ -296,6 +337,8 @@ public GroupResponseDTO.MyGroupHistoryResponseDTO getMyGroupHistory(Long groupId Pageable pageable = PageRequest.of(page, size); Page myHistoryList = historyJPARepository.findAllByGroupMember(groupMember.getId(), pageable); + log.debug("히스토리 조회 완료"); + return new GroupResponseDTO.MyGroupHistoryResponseDTO(myHistoryList); } @@ -313,11 +356,13 @@ public void updateMyGroupPage(Long groupId, Long memberId, GroupRequestDTO.Updat // 빈칸일 경우 예외 처리 if(newNickName.isEmpty()) { + log.info("공백 닉네임 " + memberId + " 번 회원, " + groupId + " 번 그룹"); throw new Exception400("공백은 닉네임이 될 수 없습니다."); } // 기존 닉네임과 같은 경우 예외 처리 if(groupMember.getNickName().equals(newNickName)) { + log.info("기존과 동일한 닉네임 " + memberId + " 번 회원, " + groupId + " 번 그룹"); throw new Exception400("기존 닉네임과 같은 닉네임입니다."); } @@ -329,6 +374,8 @@ public void updateMyGroupPage(Long groupId, Long memberId, GroupRequestDTO.Updat // 저장 groupMemberJPARepository.save(groupMember); + + log.debug("그룹 닉네임 변경 완료"); } @@ -352,6 +399,8 @@ public void leaveGroup(Long groupId, Long memberId) { groupJPARepository.save(group); groupMemberJPARepository.save(groupMember); + + log.debug("그룹 탈퇴 완료"); } else { deleteGroup(group); @@ -360,56 +409,89 @@ public void leaveGroup(Long groupId, Long memberId) { private void deleteGroup(Group group) { List groupMemberList = groupMemberJPARepository.findAllByGroupId(group.getId()); + + log.debug("그룹 멤버 조회 완료"); for (GroupMember groupMember : groupMemberList) { Long groupMemberId = groupMember.getId(); List reportList = reportJPARepository.findAllByFromMemberId(groupMemberId); reportJPARepository.deleteAll(reportList); + + log.debug("리포트 삭제 완료"); List historyList = historyJPARepository.findAllByGroupMemberId(groupMemberId); historyJPARepository.deleteAll(historyList); + log.debug("히스토리 삭제 완료"); + List commentList = commentJPARepository.findAllByGroupMemberId(groupMemberId); commentJPARepository.deleteAll(commentList); + log.debug("댓글 삭제 완료"); + List postList = postJPARepository.findAllByGroupMember(groupMemberId); postJPARepository.deleteAll(postList); + log.debug("포스트 삭제 완료"); + List pageInfoList = pageJPARepository.findAllByGroupMember(group.getId()); pageJPARepository.deleteAll(pageInfoList); + log.debug("페이지 삭제 완료"); + Member member = groupMember.getMember(); member.getGroupMembers().remove(groupMember); memberJPARepository.save(member); + log.debug("회원 내 그룹 멤버 삭제 완료"); + group.removeGroupMember(groupMember); groupMemberJPARepository.delete(groupMember); + + log.debug("그룹 멤버 삭제 완료"); } groupJPARepository.delete(group); + + log.debug("그룹 삭제 완료"); } protected Member getMemberById(Long memberId) { - return memberJPARepository.findById(memberId).orElseThrow(() -> new Exception404("해당 사용자를 찾을 수 없습니다.")); + return memberJPARepository.findById(memberId).orElseThrow(() -> { + log.info("사용자 조회 불가 " + memberId + " 번 회원"); + throw new Exception404("해당 사용자를 찾을 수 없습니다."); + }); } protected Group getGroupById(Long groupId) { - return groupJPARepository.findById(groupId).orElseThrow(() -> new Exception404("해당 그룹을 찾을 수 없습니다.")); + return groupJPARepository.findById(groupId).orElseThrow(() -> { + log.info("그룹 조회 불가 " + groupId + " 번 그룹"); + throw new Exception404("해당 그룹을 찾을 수 없습니다."); + }); } private GroupMember getActiveGroupMember(Long groupId, Long memberId) { GroupMember groupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId, groupId); - if (groupMember == null || !groupMember.isActiveStatus()) { + if (groupMember == null) { + log.info("권한 없는 그룹 접근 " + memberId + " 번 회원, " + groupId + " 번 그룹"); + throw new Exception404("해당 그룹에 속한 회원이 아닙니다."); + } + + if(!groupMember.isActiveStatus()) { + log.info("탈퇴한 그룹 접근 " + memberId + " 번 회원, " + groupId + " 번 그룹"); throw new Exception404("해당 그룹에 속한 회원이 아닙니다."); } + + log.debug("그룹 멤버 조회 완료"); return groupMember; } protected void groupNickNameCheck(Long groupId, String groupNickName) { if(groupMemberJPARepository.findGroupMemberByNickName(groupId, groupNickName).isPresent()) { + log.info(groupId + " 번 그룹에서 사용 중인 닉네임"); throw new Exception400("해당 닉네임은 이미 사용중입니다."); } } diff --git a/wekiki/src/main/resources/console-appender.xml b/wekiki/src/main/resources/console-appender.xml new file mode 100644 index 00000000..48ec4fcb --- /dev/null +++ b/wekiki/src/main/resources/console-appender.xml @@ -0,0 +1,7 @@ + + + + ${LOG_PATTERN} + + + diff --git a/wekiki/src/main/resources/file-error-appender.xml b/wekiki/src/main/resources/file-error-appender.xml new file mode 100644 index 00000000..b0392406 --- /dev/null +++ b/wekiki/src/main/resources/file-error-appender.xml @@ -0,0 +1,19 @@ + + + ./log/error/error-${BY_DATE}.log + + ERROR + ACCEPT + DENY + + + ${LOG_PATTERN} + + + ./backup/error/error-%d{yyyy-MM-dd}.%i.log + 100MB + 30 + 3GB + + + diff --git a/wekiki/src/main/resources/file-info-appender.xml b/wekiki/src/main/resources/file-info-appender.xml new file mode 100644 index 00000000..3def19a6 --- /dev/null +++ b/wekiki/src/main/resources/file-info-appender.xml @@ -0,0 +1,19 @@ + + + ./log/info/info-${BY_DATE}.log + + INFO + ACCEPT + DENY + + + ${LOG_PATTERN} + + + ./backup/info/info-%d{yyyy-MM-dd}.%i.log + 100MB + 30 + 3GB + + + diff --git a/wekiki/src/main/resources/file-warn-appender.xml b/wekiki/src/main/resources/file-warn-appender.xml new file mode 100644 index 00000000..20368704 --- /dev/null +++ b/wekiki/src/main/resources/file-warn-appender.xml @@ -0,0 +1,19 @@ + + + ./log/warn/warn-${BY_DATE}.log + + WARN + ACCEPT + DENY + + + ${LOG_PATTERN} + + + ./backup/warn/warn-%d{yyyy-MM-dd}.%i.log + 100MB + 30 + 3GB + + + diff --git a/wekiki/src/main/resources/logback-spring.xml b/wekiki/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..5118d722 --- /dev/null +++ b/wekiki/src/main/resources/logback-spring.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + From 801ef944e3fcf92cd6852bee368c8174ae5e7609 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Thu, 9 Nov 2023 19:22:55 +0900 Subject: [PATCH 118/144] =?UTF-8?q?Refactor=20:=20API=20=ED=98=B8=EC=B6=9C?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=20=EB=82=A8=EA=B8=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 페이지, 포스트, 댓글 관련 API 호출시, 로그를 더 자세히 남겼습니다. --- .../wekiki/comment/CommentService.java | 9 +++++++-- .../techcampus/wekiki/page/PageService.java | 19 ++++++++++++------- .../techcampus/wekiki/post/PostService.java | 8 ++++++++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java index fb61ac05..16adc965 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentService.java @@ -9,6 +9,7 @@ import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; @@ -21,13 +22,12 @@ @RequiredArgsConstructor @Service +@Slf4j public class CommentService { private final CommentJPARepository commentJPARepository; private final PostJPARepository postJPARepository; - private final MemberJPARepository memberJPARepository; private final GroupMemberJPARepository groupMemberJPARepository; - private final GroupJPARepository groupJPARepository; final int COMMENT_COUNT = 10; @Transactional @@ -46,6 +46,8 @@ public CommentResponse.getCommentDTO getComment(Long memberId, Long groupId, Lon List commentDTOs = comments.getContent() .stream().map(c -> new CommentResponse.getCommentDTO.commentDTO(c,c.getGroupMember(), c.getGroupMember().getId() == activeGroupMember.getId())) .collect(Collectors.toList()); + + log.info(memberId + " 님이 " + groupId + " 그룹에 "+ postId +" 포스트의 댓글을 조회합니다."); return new CommentResponse.getCommentDTO(post,commentDTOs); } @@ -68,6 +70,7 @@ public CommentResponse.createCommentDTO createComment(Long memberId, Long groupI Comment savedComment = commentJPARepository.save(comment); // 4. return DTO + log.info(memberId + " 님이 " + groupId + " 그룹에 "+ postId +" 포스트의 댓글을 생성합니다."); return new CommentResponse.createCommentDTO(savedComment,activeGroupMember.getNickName()); } @@ -90,6 +93,7 @@ public CommentResponse.deleteCommentDTO deleteComment(Long memberId, Long groupI commentJPARepository.delete(comment); // 5. return DTO + log.info(memberId + " 님이 " + groupId + " 그룹에 "+ commentId +" 댓글을 삭제합니다."); return response; } @@ -116,6 +120,7 @@ public CommentResponse.updateCommentDTO updateComment(Long memberId, Long groupI comment.updateContent(updateContent); // 6. return DTO + log.info(memberId + " 님이 " + groupId + " 그룹에 "+ commentId +" 댓글을 수정합니다."); return new CommentResponse.updateCommentDTO(comment); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java index 7e093d5d..4eed79f9 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageService.java @@ -116,6 +116,7 @@ public PageInfoResponse.getPageIndexDTO getPageIndex(Long groupId,Long memberId, .map(p -> new PageInfoResponse.getPageIndexDTO.postDTO(p, indexs.get(p.getId()))) .collect(Collectors.toList()); + log.info(memberId + " 님이 " + groupId + "의 " + pageId + " 페이지 목차 조회 API를 호출하였습니다. "); return new PageInfoResponse.getPageIndexDTO(pageInfo, temp); } @@ -142,6 +143,7 @@ public PageInfoResponse.deletePageDTO deletePage(Long memberId, Long groupId, Lo redisUtils.deleteHashValue(GROUP_PREFIX+groupId,pageInfo.getPageName()); // 6. return DTO + log.info(memberId + " 님이 " + groupId + "의 " + pageId + " 페이지 삭제 API를 호출하였습니다. "); return response; } @@ -163,6 +165,7 @@ public PageInfoResponse.getPageFromIdDTO getPageFromId(Long memberId,Long groupI .map(p -> new PageInfoResponse.getPageFromIdDTO.postDTO(p, indexs.get(p.getId()))) .collect(Collectors.toList()); + log.info(memberId + " 님이 " + groupId + "의 " + pageId + " 페이지 조회 API를 호출하였습니다. "); return new PageInfoResponse.getPageFromIdDTO(pageInfo, temp); } @@ -196,6 +199,7 @@ public PageInfoResponse.createPageDTO createPage(String title, Long groupId, Lon redisUtils.saveKeyAndHashValue(GROUP_PREFIX+groupId,title,newPageInfo.getId().toString()); // 7. return DTO + log.info(memberId + " 님이 " + groupId + " 그룹에서 " + title + " 페이지를 생성하였습니다."); return new PageInfoResponse.createPageDTO(savedPageInfo); } @@ -211,9 +215,8 @@ public PageInfoResponse.likePageDTO likePage(Long pageId , Long groupId, Long me // 3. 페이지 goodCount 증가 pageInfo.plusGoodCount(); - // TODO : 유저 경험치증가 or 유저 당일 페이지 좋아요 횟수 차감 - // 4. return DTO + log.info(memberId + " 님이 " + groupId + " 그룹에서 " + pageId + " 페이지 좋아요를 눌렀습니다."); return new PageInfoResponse.likePageDTO(pageInfo); } @@ -230,9 +233,8 @@ public PageInfoResponse.hatePageDTO hatePage(Long pageId , Long groupId, Long me // 3. 페이지 goodCount 증가 pageInfo.plusBadCount(); - // TODO : 유저 경험치증가 or 유저 당일 페이지 좋아요 횟수 차감 - // 4. return DTO + log.info(memberId + " 님이 " + groupId + " 그룹에서 " + pageId + " 페이지 싫어요를 눌렀습니다."); return new PageInfoResponse.hatePageDTO(pageInfo); } @@ -271,15 +273,14 @@ public PageInfoResponse.searchPageDTO searchPage(Long groupId, Long memberId, in // // for(PageInfo p : pages.getContent()){ // if(p.getPosts().size() == 0){ -// System.out.println(p.getId() + " 페이지 : "+ p.getPageName()); // res.add(new PageInfoResponse.searchPageDTO.pageDTO(p.getId(),p.getPageName(),"")); // }else{ -// System.out.println(p.getId() + " 페이지 : "+ p.getPageName()+ " : " + p.getPosts().get(0).getContent()); // res.add(new PageInfoResponse.searchPageDTO.pageDTO(p.getId(),p.getPageName(),p.getPosts().get(0).getContent())); // } // } // 5. pages로 DTO return DTO + log.info(memberId + " 님이 " + groupId + " 그룹에서 " + keyword + " 키워드로 페이지 검색을 요청하였습니다."); return new PageInfoResponse.searchPageDTO(res); } @@ -295,6 +296,8 @@ public PageInfoResponse.getRecentPageDTO getRecentPage(Long memberId , Long grou // 3. return DTO List collect = recentPage.stream().map(pageInfo -> new PageInfoResponse.getRecentPageDTO.RecentPageDTO(pageInfo)).collect(Collectors.toList()); + + log.info(memberId + " 님이 " + groupId + " 그룹에서 최근 변경/생성된 페이지 10개을 조회합니다."); return new PageInfoResponse.getRecentPageDTO(collect); } @@ -317,14 +320,16 @@ public PageInfoResponse.getPageFromIdDTO getPageFromTitle(Long memberId, Long gr .map(p -> new PageInfoResponse.getPageFromIdDTO.postDTO(p, indexs.get(p.getId()))) .collect(Collectors.toList()); + log.info(memberId + " 님이 " + groupId + " 그룹에서 "+ title + " 페이지를 조회합니다."); return new PageInfoResponse.getPageFromIdDTO(page, temp); } @Transactional - public PageInfoResponse.getPageLinkDTO getPageLink( Long groupId, String title){ + public PageInfoResponse.getPageLinkDTO getPageLink(Long groupId, String title){ // 1. redis로 groupId_title을 key로 value 받아오기 (페이지 테이블에 접근할 필요 x) String value = redisUtils.getHashValue(GROUP_PREFIX + groupId, title); + log.info(groupId + " 그룹에서 " + title + " 페이지의 링크를 요청합니다."); if(value == null){ throw new Exception404("존재하지 않는 페이지 입니다."); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index cb47dcdf..d76d46ae 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -12,6 +12,7 @@ import com.kakao.techcampus.wekiki.report.Report; import com.kakao.techcampus.wekiki.report.ReportJPARepository; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; @@ -23,6 +24,7 @@ @RequiredArgsConstructor @Service +@Slf4j public class PostService { private final PageJPARepository pageJPARepository; @@ -72,6 +74,7 @@ public PostResponse.createPostDTO createPost(Long memberId,Long groupId,Long pag historyJPARepository.save(newHistory); // 7. return DTO + log.info(memberId + " 님이 " + groupId + " 그룹의 " + pageId + " 페이지에 "+ title+" 포스트를 생성하였습니다."); return new PostResponse.createPostDTO(savedPost); } @@ -94,6 +97,7 @@ public PostResponse.modifyPostDTO modifyPost(Long memberId , Long groupId, Long historyJPARepository.save(newHistory); // 5. return DTO + log.info(memberId + " 님이 " + groupId + " 그룹에 "+ title+" 포스트를 수정하였습니다."); return new PostResponse.modifyPostDTO(post); } @@ -112,6 +116,8 @@ public PostResponse.getPostHistoryDTO getPostHistory(Long memberId, Long groupId // 4. DTO로 return List historyDTOs = historys.getContent().stream(). map(h -> new PostResponse.getPostHistoryDTO.historyDTO(h.getGroupMember(),h)).collect(Collectors.toList()); + + log.info(memberId + " 님이 " + groupId + " 그룹에 "+ postId +" 포스트의 히스토리를 조회합니다."); return new PostResponse.getPostHistoryDTO(post,historyDTOs); } @@ -139,6 +145,7 @@ public PostResponse.deletePostDTO deletePost(Long memberId, Long groupId, Long p .stream().forEach(p -> p.minusOrder()); // 6. return DTO; + log.info(memberId + " 님이 " + groupId + " 그룹에 "+ postId +" 포스트를 삭제합니다."); return response; } @@ -165,6 +172,7 @@ public PostResponse.createReportDTO createReport(Long memberId, Long groupId, Lo Report savedReport = reportJPARepository.save(report); // 5. return DTO + log.info(memberId + " 님이 " + groupId + " 그룹에 "+ postId +" 포스트를 신고합니다."); return new PostResponse.createReportDTO(savedReport); } From 53f1221904a3e90361fbe8638c761338c73e4e7b Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Thu, 9 Nov 2023 19:44:10 +0900 Subject: [PATCH 119/144] =?UTF-8?q?Feat=20:=20=ED=8F=AC=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=EC=8B=9C=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=8B=9C=EA=B0=84=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 포스트 수정시에도 페이지 수정 시간이 변경되도록 수정하였습니다. --- .../wekiki/post/PostJPARepository.java | 4 ++++ .../techcampus/wekiki/post/PostService.java | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java index 7da766c7..f0192912 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java @@ -7,6 +7,7 @@ import org.springframework.stereotype.Repository; import java.util.List; +import java.util.Optional; @Repository public interface PostJPARepository extends JpaRepository { @@ -20,6 +21,9 @@ List findPostsByPageIdAndOrderGreaterThan( @Query("SELECT p FROM Post p WHERE p.pageInfo.id = :pageId ORDER BY p.orders ASC") List findPostsByPageIdOrderByOrderAsc(@Param("pageId") Long pageId); + @Query("SELECT po FROM Post po JOIN FETCH po.pageInfo WHERE po.id = :postId ") + Optional findPostWithPageFromPostId(@Param("postId") Long postId); + boolean existsByPageInfoId(Long pageInfoId); boolean existsByParentId(Long parentId); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java index d76d46ae..42211f40 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostService.java @@ -85,18 +85,21 @@ public PostResponse.modifyPostDTO modifyPost(Long memberId , Long groupId, Long GroupMember activeGroupMember = checkGroupMember(memberId, groupId); // 2. postId로 post 엔티티 가져오기 - Post post = checkPostFromPostId(postId); + Post post = checkPostFromPostIdWithPage(postId); + + // 3. page 최근 수정 시간 바꾸기 + post.getPageInfo().updatePage(); - // 3. 현재 Post랑 내용 같은지 확인 + // 4. 현재 Post랑 내용 같은지 확인 if(post.getTitle().equals(title) && post.getContent().equals(content)){ throw new Exception400("기존 글과 동일한 글입니다."); } - // 4. 다르면 Post 수정후 히스토리 생성 저장 + // 5. 다르면 Post 수정후 히스토리 생성 저장 History newHistory = post.modifyPost(activeGroupMember, title, content); historyJPARepository.save(newHistory); - // 5. return DTO + // 6. return DTO log.info(memberId + " 님이 " + groupId + " 그룹에 "+ title+" 포스트를 수정하였습니다."); return new PostResponse.modifyPostDTO(post); } @@ -199,4 +202,9 @@ public Post checkPostFromPostId(Long postId){ .orElseThrow(() -> new Exception404("존재하지 않는 글 입니다.")); } + public Post checkPostFromPostIdWithPage(Long postId){ + return postJPARepository.findPostWithPageFromPostId(postId) + .orElseThrow(() -> new Exception404("존재하지 않는 글 입니다.")); + } + } From da46caaf2e02637de524c2b961420ee77954b8f3 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Thu, 9 Nov 2023 19:45:26 +0900 Subject: [PATCH 120/144] =?UTF-8?q?Feat=20:=20Comment=20content=EC=B9=BC?= =?UTF-8?q?=EB=9F=BC=20TEXT=20=ED=83=80=EC=9E=85=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Comment content칼럼 TEXT 타입으로 수정하였습니다. --- .../main/java/com/kakao/techcampus/wekiki/comment/Comment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java index 7273209d..ee6784ad 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/Comment.java @@ -23,7 +23,7 @@ public class Comment { @ManyToOne(fetch = FetchType.LAZY) private Post post; - + @Column(columnDefinition = "TEXT") private String content; private LocalDateTime created_at; From deec55a3480f3dcb24d24bd6063727ad99a084bc Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Thu, 9 Nov 2023 20:11:09 +0900 Subject: [PATCH 121/144] =?UTF-8?q?Refactor:=20=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=EC=A0=84=EB=9E=B5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - File에서는 색상 코드 사용 불가 -> 색상 코드 삭제 - console에서는 com.kakao.techcampus.wekiki 내부의 log.debug와 root 내부의 log.info 레벨까지 --- wekiki/src/main/resources/console-appender.xml | 2 +- wekiki/src/main/resources/file-error-appender.xml | 2 +- wekiki/src/main/resources/file-info-appender.xml | 2 +- wekiki/src/main/resources/file-warn-appender.xml | 2 +- wekiki/src/main/resources/logback-spring.xml | 5 ++++- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/wekiki/src/main/resources/console-appender.xml b/wekiki/src/main/resources/console-appender.xml index 48ec4fcb..f2c7486d 100644 --- a/wekiki/src/main/resources/console-appender.xml +++ b/wekiki/src/main/resources/console-appender.xml @@ -1,7 +1,7 @@ - ${LOG_PATTERN} + ${CONSOLE_LOG_PATTERN} diff --git a/wekiki/src/main/resources/file-error-appender.xml b/wekiki/src/main/resources/file-error-appender.xml index b0392406..1cde9789 100644 --- a/wekiki/src/main/resources/file-error-appender.xml +++ b/wekiki/src/main/resources/file-error-appender.xml @@ -7,7 +7,7 @@ DENY - ${LOG_PATTERN} + ${FILE_LOG_PATTERN} ./backup/error/error-%d{yyyy-MM-dd}.%i.log diff --git a/wekiki/src/main/resources/file-info-appender.xml b/wekiki/src/main/resources/file-info-appender.xml index 3def19a6..60d0aa3e 100644 --- a/wekiki/src/main/resources/file-info-appender.xml +++ b/wekiki/src/main/resources/file-info-appender.xml @@ -7,7 +7,7 @@ DENY - ${LOG_PATTERN} + ${FILE_LOG_PATTERN} ./backup/info/info-%d{yyyy-MM-dd}.%i.log diff --git a/wekiki/src/main/resources/file-warn-appender.xml b/wekiki/src/main/resources/file-warn-appender.xml index 20368704..6dbb1025 100644 --- a/wekiki/src/main/resources/file-warn-appender.xml +++ b/wekiki/src/main/resources/file-warn-appender.xml @@ -7,7 +7,7 @@ DENY - ${LOG_PATTERN} + ${FILE_LOG_PATTERN} ./backup/warn/warn-%d{yyyy-MM-dd}.%i.log diff --git a/wekiki/src/main/resources/logback-spring.xml b/wekiki/src/main/resources/logback-spring.xml index 5118d722..b5ffef3c 100644 --- a/wekiki/src/main/resources/logback-spring.xml +++ b/wekiki/src/main/resources/logback-spring.xml @@ -2,12 +2,15 @@ - + + From 9ec4882aa74908a7ae9485b3faef8a4ed00b89e5 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Thu, 9 Nov 2023 20:31:13 +0900 Subject: [PATCH 122/144] =?UTF-8?q?Refactor:=20=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- log/error/error-2023-11-09.log | 51 --------- log/info/info-2023-11-09.log | 182 --------------------------------- log/warn/warn-2023-11-09.log | 63 ------------ 3 files changed, 296 deletions(-) delete mode 100644 log/error/error-2023-11-09.log delete mode 100644 log/info/info-2023-11-09.log delete mode 100644 log/warn/warn-2023-11-09.log diff --git a/log/error/error-2023-11-09.log b/log/error/error-2023-11-09.log deleted file mode 100644 index dbb6a8ca..00000000 --- a/log/error/error-2023-11-09.log +++ /dev/null @@ -1,51 +0,0 @@ -[2023-11-09 03:36:58:152700] [restartedMain] ERROR [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory:426] - Failed to initialize JPA EntityManagerFactory: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'javax.persistence.jdbc.url', 'hibernate.connection.url', or 'hibernate.dialect') -[2023-11-09 03:36:58:152900] [restartedMain] ERROR [org.springframework.boot.SpringApplication.reportFailure:827] - Application run failed -org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'javax.persistence.jdbc.url', 'hibernate.connection.url', or 'hibernate.dialect') - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) - at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) - at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) - at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) - at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) - at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1158) - at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) - at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) - at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) - at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) - at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) - at com.kakao.techcampus.wekiki.WekikiApplication.main(WekikiApplication.java:10) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) - at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.base/java.lang.reflect.Method.invoke(Method.java:568) - at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) -Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'javax.persistence.jdbc.url', 'hibernate.connection.url', or 'hibernate.dialect') - at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:277) - at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:239) - at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:216) - at org.hibernate.boot.model.relational.Database.(Database.java:45) - at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:231) - at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:199) - at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:169) - at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1380) - at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1451) - at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) - at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) - at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) - at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) - at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1817) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766) - ... 21 common frames omitted -Caused by: org.hibernate.HibernateException: Unable to determine Dialect without JDBC metadata (please set 'javax.persistence.jdbc.url', 'hibernate.connection.url', or 'hibernate.dialect') - at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:188) - at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:87) - at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:274) - at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:34) - at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:119) - at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) - ... 36 common frames omitted diff --git a/log/info/info-2023-11-09.log b/log/info/info-2023-11-09.log deleted file mode 100644 index c9b5dd63..00000000 --- a/log/info/info-2023-11-09.log +++ /dev/null @@ -1,182 +0,0 @@ -[2023-11-09 03:36:55:149936] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarting:51] - Starting WekikiApplication using Java 17.0.7 with PID 14820 (D:\카카오 테크 캠퍼스\Wikiki\wekiki\out\production\classes started by arheo in D:\카카오 테크 캠퍼스\Wikiki) -[2023-11-09 03:36:55:149938] [restartedMain] INFO  [org.springframework.boot.SpringApplication.logStartupProfileInfo:643] - The following 1 profile is active: "prod" -[2023-11-09 03:36:57:151884] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode -[2023-11-09 03:36:57:151885] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data JPA repositories in DEFAULT mode. -[2023-11-09 03:36:57:151956] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 70 ms. Found 8 JPA repository interfaces. -[2023-11-09 03:36:57:151962] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode -[2023-11-09 03:36:57:151962] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data Redis repositories in DEFAULT mode. -[2023-11-09 03:36:57:151973] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.comment.CommentJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:36:57:151974] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:36:57:151974] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:36:57:151975] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.history.HistoryJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:36:57:151976] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.member.MemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:36:57:151976] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.page.PageJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:36:57:151977] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.post.PostJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:36:57:151977] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.report.ReportJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:36:57:151978] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 14 ms. Found 0 Redis repository interfaces. -[2023-11-09 03:36:58:152315] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize:108] - Tomcat initialized with port(s): 8080 (http) -[2023-11-09 03:36:58:152317] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing ProtocolHandler ["http-nio-8080"] -[2023-11-09 03:36:58:152318] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting service [Tomcat] -[2023-11-09 03:36:58:152318] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting Servlet engine: [Apache Tomcat/10.1.13] -[2023-11-09 03:36:58:152376] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring embedded WebApplicationContext -[2023-11-09 03:36:58:152377] [restartedMain] INFO  [org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.prepareWebApplicationContext:291] - Root WebApplicationContext: initialization completed in 2433 ms -[2023-11-09 03:36:58:152462] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:110] - HikariPool-2 - Starting... -[2023-11-09 03:36:58:152645] [restartedMain] INFO  [org.hibernate.jpa.internal.util.LogHelper.logPersistenceUnitInformation:31] - HHH000204: Processing PersistenceUnitInfo [name: default] -[2023-11-09 03:36:58:152676] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy -[2023-11-09 03:36:58:152676] [restartedMain] INFO  [org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo.addTransformer:87] - No LoadTimeWeaver setup: ignoring JPA class transformer -[2023-11-09 03:36:58:152679] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:110] - HikariPool-2 - Starting... -[2023-11-09 03:36:58:152818] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Stopping service [Tomcat] -[2023-11-09 03:36:58:152840] [restartedMain] INFO  [org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLogger.logMessage:82] - - -Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. -[2023-11-09 03:38:12:1992] [background-preinit] INFO  [org.hibernate.validator.internal.util.Version.:21] - HV000001: Hibernate Validator 8.0.1.Final -[2023-11-09 03:38:12:2076] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarting:51] - Starting WekikiApplication using Java 17.0.7 with PID 12116 (D:\카카오 테크 캠퍼스\Wikiki\wekiki\out\production\classes started by arheo in D:\카카오 테크 캠퍼스\Wikiki) -[2023-11-09 03:38:12:2078] [restartedMain] INFO  [org.springframework.boot.SpringApplication.logStartupProfileInfo:643] - The following 1 profile is active: "prod" -[2023-11-09 03:38:12:2195] [restartedMain] INFO  [org.springframework.boot.logging.DeferredLog.logTo:250] - Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable -[2023-11-09 03:38:12:2195] [restartedMain] INFO  [org.springframework.boot.logging.DeferredLog.logTo:250] - For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' -[2023-11-09 03:38:15:4671] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode -[2023-11-09 03:38:15:4679] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data JPA repositories in DEFAULT mode. -[2023-11-09 03:38:15:5158] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 449 ms. Found 8 JPA repository interfaces. -[2023-11-09 03:38:15:5190] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode -[2023-11-09 03:38:15:5193] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data Redis repositories in DEFAULT mode. -[2023-11-09 03:38:15:5226] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.comment.CommentJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:38:15:5229] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:38:15:5229] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:38:15:5230] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.history.HistoryJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:38:15:5230] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.member.MemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:38:15:5232] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.page.PageJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:38:15:5232] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.post.PostJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:38:15:5232] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.report.ReportJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:38:15:5233] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 23 ms. Found 0 Redis repository interfaces. -[2023-11-09 03:38:17:6854] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize:108] - Tomcat initialized with port(s): 8080 (http) -[2023-11-09 03:38:17:6883] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing ProtocolHandler ["http-nio-8080"] -[2023-11-09 03:38:17:6890] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting service [Tomcat] -[2023-11-09 03:38:17:6892] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting Servlet engine: [Apache Tomcat/10.1.13] -[2023-11-09 03:38:17:7108] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring embedded WebApplicationContext -[2023-11-09 03:38:17:7108] [restartedMain] INFO  [org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.prepareWebApplicationContext:291] - Root WebApplicationContext: initialization completed in 4912 ms -[2023-11-09 03:38:17:7378] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:110] - HikariPool-1 - Starting... -[2023-11-09 03:38:18:8111] [restartedMain] INFO  [com.zaxxer.hikari.pool.HikariPool.checkFailFast:565] - HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:test user=SA -[2023-11-09 03:38:18:8116] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:123] - HikariPool-1 - Start completed. -[2023-11-09 03:38:18:8141] [restartedMain] INFO  [org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.logDataSources:88] - H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:test' -[2023-11-09 03:38:19:8975] [restartedMain] INFO  [org.hibernate.jpa.internal.util.LogHelper.logPersistenceUnitInformation:31] - HHH000204: Processing PersistenceUnitInfo [name: default] -[2023-11-09 03:38:19:9143] [restartedMain] INFO  [org.hibernate.Version.logVersion:44] - HHH000412: Hibernate ORM core version 6.2.9.Final -[2023-11-09 03:38:19:9148] [restartedMain] INFO  [org.hibernate.cfg.Environment.:191] - HHH000406: Using bytecode reflection optimizer -[2023-11-09 03:38:20:9523] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy -[2023-11-09 03:38:20:9909] [restartedMain] INFO  [org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo.addTransformer:87] - No LoadTimeWeaver setup: ignoring JPA class transformer -[2023-11-09 03:38:21:10719] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy -[2023-11-09 03:38:23:12664] [restartedMain] INFO  [org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator.initiateService:51] - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] -[2023-11-09 03:38:23:12843] [restartedMain] INFO  [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory:437] - Initialized JPA EntityManagerFactory for persistence unit 'default' -[2023-11-09 03:38:23:13503] [restartedMain] INFO  [org.springframework.data.jpa.repository.query.QueryEnhancerFactory.:47] - Hibernate is in classpath; If applicable, HQL parser will be used. -[2023-11-09 03:38:26:16280] [restartedMain] INFO  [org.springframework.security.web.DefaultSecurityFilterChain.:54] - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@6266514f, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@120d634a, org.springframework.security.web.context.SecurityContextHolderFilter@48b1cc4, org.springframework.security.web.header.HeaderWriterFilter@417a72c, org.springframework.security.web.authentication.logout.LogoutFilter@1b311e61, com.kakao.techcampus.wekiki._core.jwt.JWTTokenFilter@7a64296a, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@25ac6dd9, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@6d76c1db, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@7f04d285, org.springframework.security.web.session.SessionManagementFilter@4cce2364, org.springframework.security.web.access.ExceptionTranslationFilter@5d43f22a, org.springframework.security.web.access.intercept.AuthorizationFilter@7230456c] -[2023-11-09 03:38:28:17669] [restartedMain] INFO  [org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer.startServer:59] - LiveReload server is running on port 35729 -[2023-11-09 03:38:28:17680] [restartedMain] INFO  [org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver.:58] - Exposing 1 endpoint(s) beneath base path '/actuator' -[2023-11-09 03:38:28:17811] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting ProtocolHandler ["http-nio-8080"] -[2023-11-09 03:38:28:17860] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start:220] - Tomcat started on port(s): 8080 (http) with context path '' -[2023-11-09 03:38:28:17893] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarted:57] - Started WekikiApplication in 17.304 seconds (process running for 18.961) -[2023-11-09 03:38:28:18466] [RMI TCP Connection(7)-192.168.0.45] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring DispatcherServlet 'dispatcherServlet' -[2023-11-09 03:38:28:18468] [RMI TCP Connection(7)-192.168.0.45] INFO  [org.springframework.web.servlet.FrameworkServlet.initServletBean:532] - Initializing Servlet 'dispatcherServlet' -[2023-11-09 03:38:28:18471] [RMI TCP Connection(7)-192.168.0.45] INFO  [org.springframework.web.servlet.FrameworkServlet.initServletBean:554] - Completed initialization in 3 ms -[2023-11-09 03:41:31:201484] [SpringApplicationShutdownHook] INFO  [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.destroy:650] - Closing JPA EntityManagerFactory for persistence unit 'default' -[2023-11-09 03:41:32:201927] [SpringApplicationShutdownHook] INFO  [com.zaxxer.hikari.HikariDataSource.close:350] - HikariPool-1 - Shutdown initiated... -[2023-11-09 03:41:32:201940] [SpringApplicationShutdownHook] INFO  [com.zaxxer.hikari.HikariDataSource.close:352] - HikariPool-1 - Shutdown completed. -[2023-11-09 03:42:28:2194] [background-preinit] INFO  [org.hibernate.validator.internal.util.Version.:21] - HV000001: Hibernate Validator 8.0.1.Final -[2023-11-09 03:42:28:2289] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarting:51] - Starting WekikiApplication using Java 17.0.7 with PID 9348 (D:\카카오 테크 캠퍼스\Wikiki\wekiki\out\production\classes started by arheo in D:\카카오 테크 캠퍼스\Wikiki) -[2023-11-09 03:42:28:2292] [restartedMain] INFO  [org.springframework.boot.SpringApplication.logStartupProfileInfo:643] - The following 1 profile is active: "prod" -[2023-11-09 03:42:28:2420] [restartedMain] INFO  [org.springframework.boot.logging.DeferredLog.logTo:250] - Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable -[2023-11-09 03:42:28:2421] [restartedMain] INFO  [org.springframework.boot.logging.DeferredLog.logTo:250] - For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' -[2023-11-09 03:42:34:8432] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode -[2023-11-09 03:42:34:8436] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data JPA repositories in DEFAULT mode. -[2023-11-09 03:42:35:8936] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 480 ms. Found 8 JPA repository interfaces. -[2023-11-09 03:42:35:8969] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode -[2023-11-09 03:42:35:8972] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data Redis repositories in DEFAULT mode. -[2023-11-09 03:42:35:9009] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.comment.CommentJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:42:35:9012] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:42:35:9013] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:42:35:9014] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.history.HistoryJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:42:35:9015] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.member.MemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:42:35:9015] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.page.PageJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:42:35:9016] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.post.PostJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:42:35:9017] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.report.ReportJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:42:35:9018] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 26 ms. Found 0 Redis repository interfaces. -[2023-11-09 03:42:37:11281] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize:108] - Tomcat initialized with port(s): 8080 (http) -[2023-11-09 03:42:37:11301] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing ProtocolHandler ["http-nio-8080"] -[2023-11-09 03:42:37:11306] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting service [Tomcat] -[2023-11-09 03:42:37:11306] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting Servlet engine: [Apache Tomcat/10.1.13] -[2023-11-09 03:42:38:11501] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring embedded WebApplicationContext -[2023-11-09 03:42:38:11502] [restartedMain] INFO  [org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.prepareWebApplicationContext:291] - Root WebApplicationContext: initialization completed in 9080 ms -[2023-11-09 03:42:38:11788] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:110] - HikariPool-1 - Starting... -[2023-11-09 03:42:38:12369] [restartedMain] INFO  [com.zaxxer.hikari.pool.HikariPool.checkFailFast:565] - HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:test user=SA -[2023-11-09 03:42:38:12375] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:123] - HikariPool-1 - Start completed. -[2023-11-09 03:42:38:12401] [restartedMain] INFO  [org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.logDataSources:88] - H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:test' -[2023-11-09 03:42:40:13695] [restartedMain] INFO  [org.hibernate.jpa.internal.util.LogHelper.logPersistenceUnitInformation:31] - HHH000204: Processing PersistenceUnitInfo [name: default] -[2023-11-09 03:42:40:13877] [restartedMain] INFO  [org.hibernate.Version.logVersion:44] - HHH000412: Hibernate ORM core version 6.2.9.Final -[2023-11-09 03:42:40:13883] [restartedMain] INFO  [org.hibernate.cfg.Environment.:191] - HHH000406: Using bytecode reflection optimizer -[2023-11-09 03:42:40:14300] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy -[2023-11-09 03:42:41:14708] [restartedMain] INFO  [org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo.addTransformer:87] - No LoadTimeWeaver setup: ignoring JPA class transformer -[2023-11-09 03:42:42:15593] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy -[2023-11-09 03:42:44:18050] [restartedMain] INFO  [org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator.initiateService:51] - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] -[2023-11-09 03:42:44:18283] [restartedMain] INFO  [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory:437] - Initialized JPA EntityManagerFactory for persistence unit 'default' -[2023-11-09 03:42:45:19148] [restartedMain] INFO  [org.springframework.data.jpa.repository.query.QueryEnhancerFactory.:47] - Hibernate is in classpath; If applicable, HQL parser will be used. -[2023-11-09 03:42:48:22223] [restartedMain] INFO  [org.springframework.security.web.DefaultSecurityFilterChain.:54] - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@511dde8a, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@307f0225, org.springframework.security.web.context.SecurityContextHolderFilter@4c5a1b1f, org.springframework.security.web.header.HeaderWriterFilter@4d55ba96, org.springframework.security.web.authentication.logout.LogoutFilter@37bfb3e5, com.kakao.techcampus.wekiki._core.jwt.JWTTokenFilter@101ddcce, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@70815ff8, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@7044e0b5, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@4b4885dd, org.springframework.security.web.session.SessionManagementFilter@69b02f4b, org.springframework.security.web.access.ExceptionTranslationFilter@27d157f8, org.springframework.security.web.access.intercept.AuthorizationFilter@d6d9dd9] -[2023-11-09 03:42:50:23820] [restartedMain] INFO  [org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer.startServer:59] - LiveReload server is running on port 35729 -[2023-11-09 03:42:50:23833] [restartedMain] INFO  [org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver.:58] - Exposing 1 endpoint(s) beneath base path '/actuator' -[2023-11-09 03:42:50:24002] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting ProtocolHandler ["http-nio-8080"] -[2023-11-09 03:42:50:24057] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start:220] - Tomcat started on port(s): 8080 (http) with context path '' -[2023-11-09 03:42:50:24094] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarted:57] - Started WekikiApplication in 23.51 seconds (process running for 25.634) -[2023-11-09 03:42:51:24955] [RMI TCP Connection(4)-192.168.0.45] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring DispatcherServlet 'dispatcherServlet' -[2023-11-09 03:42:51:24956] [RMI TCP Connection(4)-192.168.0.45] INFO  [org.springframework.web.servlet.FrameworkServlet.initServletBean:532] - Initializing Servlet 'dispatcherServlet' -[2023-11-09 03:42:51:24959] [RMI TCP Connection(4)-192.168.0.45] INFO  [org.springframework.web.servlet.FrameworkServlet.initServletBean:554] - Completed initialization in 3 ms -[2023-11-09 03:44:31:125055] [SpringApplicationShutdownHook] INFO  [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.destroy:650] - Closing JPA EntityManagerFactory for persistence unit 'default' -[2023-11-09 03:44:31:125453] [SpringApplicationShutdownHook] INFO  [com.zaxxer.hikari.HikariDataSource.close:350] - HikariPool-1 - Shutdown initiated... -[2023-11-09 03:44:31:125466] [SpringApplicationShutdownHook] INFO  [com.zaxxer.hikari.HikariDataSource.close:352] - HikariPool-1 - Shutdown completed. -[2023-11-09 03:46:18:2528] [background-preinit] INFO  [org.hibernate.validator.internal.util.Version.:21] - HV000001: Hibernate Validator 8.0.1.Final -[2023-11-09 03:46:18:2692] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarting:51] - Starting WekikiApplication using Java 17.0.7 with PID 6724 (D:\카카오 테크 캠퍼스\Wikiki\wekiki\out\production\classes started by arheo in D:\카카오 테크 캠퍼스\Wikiki) -[2023-11-09 03:46:18:2698] [restartedMain] INFO  [org.springframework.boot.SpringApplication.logStartupProfileInfo:643] - The following 1 profile is active: "prod" -[2023-11-09 03:46:18:3106] [restartedMain] INFO  [org.springframework.boot.logging.DeferredLog.logTo:250] - Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable -[2023-11-09 03:46:18:3107] [restartedMain] INFO  [org.springframework.boot.logging.DeferredLog.logTo:250] - For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' -[2023-11-09 03:46:28:12861] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode -[2023-11-09 03:46:28:12866] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data JPA repositories in DEFAULT mode. -[2023-11-09 03:46:29:13447] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 559 ms. Found 8 JPA repository interfaces. -[2023-11-09 03:46:29:13485] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode -[2023-11-09 03:46:29:13488] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data Redis repositories in DEFAULT mode. -[2023-11-09 03:46:29:13621] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.comment.CommentJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:46:29:13633] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:46:29:13638] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:46:29:13641] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.history.HistoryJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:46:29:13643] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.member.MemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:46:29:13660] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.page.PageJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:46:29:13661] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.post.PostJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:46:29:13662] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.report.ReportJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 03:46:29:13662] [restartedMain] INFO  [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 130 ms. Found 0 Redis repository interfaces. -[2023-11-09 03:46:31:16022] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize:108] - Tomcat initialized with port(s): 8080 (http) -[2023-11-09 03:46:31:16042] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing ProtocolHandler ["http-nio-8080"] -[2023-11-09 03:46:31:16047] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting service [Tomcat] -[2023-11-09 03:46:31:16048] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting Servlet engine: [Apache Tomcat/10.1.13] -[2023-11-09 03:46:31:16240] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring embedded WebApplicationContext -[2023-11-09 03:46:31:16241] [restartedMain] INFO  [org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.prepareWebApplicationContext:291] - Root WebApplicationContext: initialization completed in 13133 ms -[2023-11-09 03:46:32:16501] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:110] - HikariPool-1 - Starting... -[2023-11-09 03:46:32:17239] [restartedMain] INFO  [com.zaxxer.hikari.pool.HikariPool.checkFailFast:565] - HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:test user=SA -[2023-11-09 03:46:32:17244] [restartedMain] INFO  [com.zaxxer.hikari.HikariDataSource.getConnection:123] - HikariPool-1 - Start completed. -[2023-11-09 03:46:32:17269] [restartedMain] INFO  [org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.logDataSources:88] - H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:test' -[2023-11-09 03:46:34:18376] [restartedMain] INFO  [org.hibernate.jpa.internal.util.LogHelper.logPersistenceUnitInformation:31] - HHH000204: Processing PersistenceUnitInfo [name: default] -[2023-11-09 03:46:34:18604] [restartedMain] INFO  [org.hibernate.Version.logVersion:44] - HHH000412: Hibernate ORM core version 6.2.9.Final -[2023-11-09 03:46:34:18611] [restartedMain] INFO  [org.hibernate.cfg.Environment.:191] - HHH000406: Using bytecode reflection optimizer -[2023-11-09 03:46:34:19149] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy -[2023-11-09 03:46:35:19617] [restartedMain] INFO  [org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo.addTransformer:87] - No LoadTimeWeaver setup: ignoring JPA class transformer -[2023-11-09 03:46:36:20589] [restartedMain] INFO  [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy -[2023-11-09 03:46:39:23764] [restartedMain] INFO  [org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator.initiateService:51] - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] -[2023-11-09 03:46:39:23937] [restartedMain] INFO  [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory:437] - Initialized JPA EntityManagerFactory for persistence unit 'default' -[2023-11-09 03:46:41:25386] [restartedMain] INFO  [org.springframework.data.jpa.repository.query.QueryEnhancerFactory.:47] - Hibernate is in classpath; If applicable, HQL parser will be used. -[2023-11-09 03:46:44:28384] [restartedMain] INFO  [org.springframework.security.web.DefaultSecurityFilterChain.:54] - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@1dfa906e, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@384290, org.springframework.security.web.context.SecurityContextHolderFilter@6b85d8d4, org.springframework.security.web.header.HeaderWriterFilter@7c4c24f2, org.springframework.security.web.authentication.logout.LogoutFilter@2c2348fc, com.kakao.techcampus.wekiki._core.jwt.JWTTokenFilter@3ce14b3f, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@4bf95bf8, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@6378eded, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@4061e206, org.springframework.security.web.session.SessionManagementFilter@426e5e22, org.springframework.security.web.access.ExceptionTranslationFilter@4302a6c4, org.springframework.security.web.access.intercept.AuthorizationFilter@52e9f6cf] -[2023-11-09 03:46:45:30072] [restartedMain] INFO  [org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer.startServer:59] - LiveReload server is running on port 35729 -[2023-11-09 03:46:45:30089] [restartedMain] INFO  [org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver.:58] - Exposing 1 endpoint(s) beneath base path '/actuator' -[2023-11-09 03:46:45:30252] [restartedMain] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Starting ProtocolHandler ["http-nio-8080"] -[2023-11-09 03:46:46:30298] [restartedMain] INFO  [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start:220] - Tomcat started on port(s): 8080 (http) with context path '' -[2023-11-09 03:46:46:30331] [restartedMain] INFO  [org.springframework.boot.StartupInfoLogger.logStarted:57] - Started WekikiApplication in 29.704 seconds (process running for 31.885) -[2023-11-09 03:46:46:30887] [RMI TCP Connection(2)-192.168.0.45] INFO  [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring DispatcherServlet 'dispatcherServlet' -[2023-11-09 03:46:46:30888] [RMI TCP Connection(2)-192.168.0.45] INFO  [org.springframework.web.servlet.FrameworkServlet.initServletBean:532] - Initializing Servlet 'dispatcherServlet' -[2023-11-09 03:46:46:30893] [RMI TCP Connection(2)-192.168.0.45] INFO  [org.springframework.web.servlet.FrameworkServlet.initServletBean:554] - Completed initialization in 5 ms -[2023-11-09 03:49:07:171409] [http-nio-8080-exec-9] INFO  [com.kakao.techcampus.wekiki.group.service.GroupService.groupEntry:222] - 비밀번호 불일치 -[2023-11-09 03:50:42:266479] [SpringApplicationShutdownHook] INFO  [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.destroy:650] - Closing JPA EntityManagerFactory for persistence unit 'default' -[2023-11-09 03:50:42:266926] [SpringApplicationShutdownHook] INFO  [com.zaxxer.hikari.HikariDataSource.close:350] - HikariPool-1 - Shutdown initiated... -[2023-11-09 03:50:42:266953] [SpringApplicationShutdownHook] INFO  [com.zaxxer.hikari.HikariDataSource.close:352] - HikariPool-1 - Shutdown completed. diff --git a/log/warn/warn-2023-11-09.log b/log/warn/warn-2023-11-09.log deleted file mode 100644 index ab45cc59..00000000 --- a/log/warn/warn-2023-11-09.log +++ /dev/null @@ -1,63 +0,0 @@ -[2023-11-09 03:36:58:152680] [restartedMain] WARN  [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService:244] - HHH000342: Could not obtain connection to query metadata -java.lang.RuntimeException: Driver org.mariadb.jdbc.Driver claims to not accept jdbcUrl, ${DATABASE_URL}?allowPublicKeyRetrieval=true&useSSL=false - at com.zaxxer.hikari.util.DriverDataSource.(DriverDataSource.java:110) - at com.zaxxer.hikari.pool.PoolBase.initializeDataSource(PoolBase.java:326) - at com.zaxxer.hikari.pool.PoolBase.(PoolBase.java:112) - at com.zaxxer.hikari.pool.HikariPool.(HikariPool.java:93) - at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) - at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) - at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:316) - at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:152) - at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:34) - at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:119) - at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) - at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:239) - at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:216) - at org.hibernate.boot.model.relational.Database.(Database.java:45) - at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:231) - at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:199) - at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:169) - at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1380) - at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1451) - at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) - at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) - at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) - at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) - at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1817) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) - at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) - at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) - at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) - at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) - at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1158) - at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) - at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) - at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) - at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) - at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) - at com.kakao.techcampus.wekiki.WekikiApplication.main(WekikiApplication.java:10) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) - at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.base/java.lang.reflect.Method.invoke(Method.java:568) - at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) -[2023-11-09 03:36:58:152701] [restartedMain] WARN  [org.springframework.context.support.AbstractApplicationContext.refresh:616] - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'javax.persistence.jdbc.url', 'hibernate.connection.url', or 'hibernate.dialect') -[2023-11-09 03:38:24:14403] [restartedMain] WARN  [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.post.PostJPARepository -[2023-11-09 03:38:25:15350] [restartedMain] WARN  [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.page.PageJPARepository -[2023-11-09 03:40:09:119174] [http-nio-8080-exec-2] WARN  [org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException:207] - Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity com.kakao.techcampus.wekiki.member.MemberController.signUp(com.kakao.techcampus.wekiki.member.MemberRequest$signUpRequestDTO): [Field error in object 'signUpRequestDTO' on field 'password': rejected value [1234!]; codes [Pattern.signUpRequestDTO.password,Pattern.password,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [signUpRequestDTO.password,password]; arguments []; default message [password],[Ljakarta.validation.constraints.Pattern$Flag;@45662a21,^(?=.*[a-zA-Z])(?=.*[0-9]).{8,20}$]; default message [(8~20자 영문과 숫자)]] ] -[2023-11-09 03:41:32:201788] [SpringApplicationShutdownHook] WARN  [org.springframework.beans.factory.support.DisposableBeanAdapter.destroy:210] - Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214] -[2023-11-09 03:42:46:20493] [restartedMain] WARN  [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.post.PostJPARepository -[2023-11-09 03:42:47:21175] [restartedMain] WARN  [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.page.PageJPARepository -[2023-11-09 03:42:57:31170] [http-nio-8080-exec-2] WARN  [org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException:207] - Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity com.kakao.techcampus.wekiki.member.MemberController.signUp(com.kakao.techcampus.wekiki.member.MemberRequest$signUpRequestDTO): [Field error in object 'signUpRequestDTO' on field 'password': rejected value [1234!]; codes [Pattern.signUpRequestDTO.password,Pattern.password,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [signUpRequestDTO.password,password]; arguments []; default message [password],[Ljakarta.validation.constraints.Pattern$Flag;@253e3632,^(?=.*[a-zA-Z])(?=.*[0-9]).{8,20}$]; default message [(8~20자 영문과 숫자)]] ] -[2023-11-09 03:44:31:125314] [SpringApplicationShutdownHook] WARN  [org.springframework.beans.factory.support.DisposableBeanAdapter.destroy:210] - Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214] -[2023-11-09 03:46:42:26565] [restartedMain] WARN  [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.post.PostJPARepository -[2023-11-09 03:46:43:27315] [restartedMain] WARN  [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.page.PageJPARepository -[2023-11-09 03:48:14:118808] [http-nio-8080-exec-4] WARN  [org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException:207] - Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity com.kakao.techcampus.wekiki.member.MemberController.signUp(com.kakao.techcampus.wekiki.member.MemberRequest$signUpRequestDTO): [Field error in object 'signUpRequestDTO' on field 'nickName': rejected value [회원2]; codes [Pattern.signUpRequestDTO.nickName,Pattern.nickName,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [signUpRequestDTO.nickName,nickName]; arguments []; default message [nickName],[Ljakarta.validation.constraints.Pattern$Flag;@1a1cdc42,^[가-힣a-zA-Z]{2,10}$]; default message [(2~10자 한글, 영어)]] ] -[2023-11-09 03:49:07:171423] [http-nio-8080-exec-9] WARN  [org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logException:207] - Resolved [com.kakao.techcampus.wekiki._core.error.exception.Exception400: 비밀번호가 틀렸습니다.] -[2023-11-09 03:50:42:266796] [SpringApplicationShutdownHook] WARN  [org.springframework.beans.factory.support.DisposableBeanAdapter.destroy:210] - Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214] From 06d0b492797daadc9d37b07eda587d353ce565ff Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Thu, 9 Nov 2023 20:31:47 +0900 Subject: [PATCH 123/144] =?UTF-8?q?Refactor:=20gitignore=EC=97=90=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=ED=8C=8C=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wekiki/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/wekiki/.gitignore b/wekiki/.gitignore index f42cae99..70e7b6a6 100644 --- a/wekiki/.gitignore +++ b/wekiki/.gitignore @@ -45,6 +45,7 @@ out/ # Log file *.log +**/*.log # BlueJ files *.ctxt From 0e8d5f1dac5d94a847fae5f5c09d80db0dc970cc Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 10 Nov 2023 11:40:24 +0900 Subject: [PATCH 124/144] =?UTF-8?q?Refactor:=20=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=98=88=EC=99=B8=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - InvitationService 내 로그 추가 - 그룹 추가 검색 시 마지막 페이지는 예외 처리가 아닌 빈 리스트만 전달 --- log/error/error-2023-11-09.log | 0 log/info/info-2023-11-09.log | 50 +++++++++++++++++++ log/warn/warn-2023-11-09.log | 3 ++ .../wekiki/group/service/GroupService.java | 3 +- .../group/service/InvitationService.java | 38 ++++++++++++-- 5 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 log/error/error-2023-11-09.log create mode 100644 log/info/info-2023-11-09.log create mode 100644 log/warn/warn-2023-11-09.log diff --git a/log/error/error-2023-11-09.log b/log/error/error-2023-11-09.log new file mode 100644 index 00000000..e69de29b diff --git a/log/info/info-2023-11-09.log b/log/info/info-2023-11-09.log new file mode 100644 index 00000000..e4fa8636 --- /dev/null +++ b/log/info/info-2023-11-09.log @@ -0,0 +1,50 @@ +[2023-11-09 20:32:36:1657] [background-preinit] INFO [org.hibernate.validator.internal.util.Version.:21] - HV000001: Hibernate Validator 8.0.1.Final +[2023-11-09 20:32:37:1753] [restartedMain] INFO [org.springframework.boot.StartupInfoLogger.logStarting:51] - Starting WekikiApplication using Java 17.0.7 with PID 13828 (D:\카카오 테크 캠퍼스\Wikiki\wekiki\out\production\classes started by arheo in D:\카카오 테크 캠퍼스\Wikiki) +[2023-11-09 20:32:37:1754] [restartedMain] INFO [org.springframework.boot.SpringApplication.logStartupProfileInfo:643] - The following 1 profile is active: "local" +[2023-11-09 20:32:37:1862] [restartedMain] INFO [org.springframework.boot.logging.DeferredLog.logTo:250] - Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable +[2023-11-09 20:32:37:1865] [restartedMain] INFO [org.springframework.boot.logging.DeferredLog.logTo:250] - For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' +[2023-11-09 20:32:41:5761] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode +[2023-11-09 20:32:41:5764] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data JPA repositories in DEFAULT mode. +[2023-11-09 20:32:41:6099] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 325 ms. Found 8 JPA repository interfaces. +[2023-11-09 20:32:41:6124] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode +[2023-11-09 20:32:41:6127] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +[2023-11-09 20:32:41:6151] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.comment.CommentJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 20:32:41:6153] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 20:32:41:6153] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 20:32:41:6154] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.history.HistoryJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 20:32:41:6154] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.member.MemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 20:32:41:6154] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.page.PageJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 20:32:41:6155] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.post.PostJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 20:32:41:6155] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.report.ReportJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2023-11-09 20:32:41:6155] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 15 ms. Found 0 Redis repository interfaces. +[2023-11-09 20:32:42:7286] [restartedMain] INFO [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize:108] - Tomcat initialized with port(s): 8080 (http) +[2023-11-09 20:32:42:7300] [restartedMain] INFO [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing ProtocolHandler ["http-nio-8080"] +[2023-11-09 20:32:42:7304] [restartedMain] INFO [org.apache.juli.logging.DirectJDKLog.log:173] - Starting service [Tomcat] +[2023-11-09 20:32:42:7304] [restartedMain] INFO [org.apache.juli.logging.DirectJDKLog.log:173] - Starting Servlet engine: [Apache Tomcat/10.1.13] +[2023-11-09 20:32:42:7425] [restartedMain] INFO [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring embedded WebApplicationContext +[2023-11-09 20:32:42:7457] [restartedMain] INFO [org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.prepareWebApplicationContext:291] - Root WebApplicationContext: initialization completed in 5590 ms +[2023-11-09 20:32:42:7603] [restartedMain] INFO [com.zaxxer.hikari.HikariDataSource.getConnection:110] - HikariPool-1 - Starting... +[2023-11-09 20:32:43:7940] [restartedMain] INFO [com.zaxxer.hikari.pool.HikariPool.checkFailFast:565] - HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:test user=SA +[2023-11-09 20:32:43:7944] [restartedMain] INFO [com.zaxxer.hikari.HikariDataSource.getConnection:123] - HikariPool-1 - Start completed. +[2023-11-09 20:32:43:7963] [restartedMain] INFO [org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.logDataSources:88] - H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:test' +[2023-11-09 20:32:44:8877] [restartedMain] INFO [org.hibernate.jpa.internal.util.LogHelper.logPersistenceUnitInformation:31] - HHH000204: Processing PersistenceUnitInfo [name: default] +[2023-11-09 20:32:44:8995] [restartedMain] INFO [org.hibernate.Version.logVersion:44] - HHH000412: Hibernate ORM core version 6.2.9.Final +[2023-11-09 20:32:44:9001] [restartedMain] INFO [org.hibernate.cfg.Environment.:191] - HHH000406: Using bytecode reflection optimizer +[2023-11-09 20:32:44:9283] [restartedMain] INFO [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy +[2023-11-09 20:32:44:9624] [restartedMain] INFO [org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo.addTransformer:87] - No LoadTimeWeaver setup: ignoring JPA class transformer +[2023-11-09 20:32:45:10189] [restartedMain] INFO [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy +[2023-11-09 20:32:46:11541] [restartedMain] INFO [org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator.initiateService:51] - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] +[2023-11-09 20:32:46:11664] [restartedMain] INFO [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory:437] - Initialized JPA EntityManagerFactory for persistence unit 'default' +[2023-11-09 20:32:47:12144] [restartedMain] INFO [org.springframework.data.jpa.repository.query.QueryEnhancerFactory.:47] - Hibernate is in classpath; If applicable, HQL parser will be used. +[2023-11-09 20:32:49:13865] [restartedMain] INFO [org.springframework.security.web.DefaultSecurityFilterChain.:54] - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@4d852dd0, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@395553b, org.springframework.security.web.context.SecurityContextHolderFilter@2313e93b, org.springframework.security.web.header.HeaderWriterFilter@113a6ad6, org.springframework.security.web.authentication.logout.LogoutFilter@23db507b, com.kakao.techcampus.wekiki._core.jwt.JWTTokenFilter@1ef875bb, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@5f39521a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@4ecffe3f, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@203d815d, org.springframework.security.web.session.SessionManagementFilter@2eb325e, org.springframework.security.web.access.ExceptionTranslationFilter@1399dc87, org.springframework.security.web.access.intercept.AuthorizationFilter@42219fe4] +[2023-11-09 20:32:50:14902] [restartedMain] INFO [org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer.startServer:59] - LiveReload server is running on port 35729 +[2023-11-09 20:32:50:14910] [restartedMain] INFO [org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver.:58] - Exposing 1 endpoint(s) beneath base path '/actuator' +[2023-11-09 20:32:50:14998] [restartedMain] INFO [org.apache.juli.logging.DirectJDKLog.log:173] - Starting ProtocolHandler ["http-nio-8080"] +[2023-11-09 20:32:50:15030] [restartedMain] INFO [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start:220] - Tomcat started on port(s): 8080 (http) with context path '' +[2023-11-09 20:32:50:15053] [restartedMain] INFO [org.springframework.boot.StartupInfoLogger.logStarted:57] - Started WekikiApplication in 14.533 seconds (process running for 16.379) +[2023-11-09 20:33:00:25400] [http-nio-8080-exec-2] INFO [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring DispatcherServlet 'dispatcherServlet' +[2023-11-09 20:33:00:25401] [http-nio-8080-exec-2] INFO [org.springframework.web.servlet.FrameworkServlet.initServletBean:532] - Initializing Servlet 'dispatcherServlet' +[2023-11-09 20:33:00:25403] [http-nio-8080-exec-2] INFO [org.springframework.web.servlet.FrameworkServlet.initServletBean:554] - Completed initialization in 2 ms +[2023-11-09 20:33:09:34246] [SpringApplicationShutdownHook] INFO [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.destroy:650] - Closing JPA EntityManagerFactory for persistence unit 'default' +[2023-11-09 20:33:10:34717] [SpringApplicationShutdownHook] INFO [com.zaxxer.hikari.HikariDataSource.close:350] - HikariPool-1 - Shutdown initiated... +[2023-11-09 20:33:10:34733] [SpringApplicationShutdownHook] INFO [com.zaxxer.hikari.HikariDataSource.close:352] - HikariPool-1 - Shutdown completed. diff --git a/log/warn/warn-2023-11-09.log b/log/warn/warn-2023-11-09.log new file mode 100644 index 00000000..7e22e187 --- /dev/null +++ b/log/warn/warn-2023-11-09.log @@ -0,0 +1,3 @@ +[2023-11-09 20:32:48:12775] [restartedMain] WARN [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.post.PostJPARepository +[2023-11-09 20:32:48:13201] [restartedMain] WARN [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.page.PageJPARepository +[2023-11-09 20:33:09:34573] [SpringApplicationShutdownHook] WARN [org.springframework.beans.factory.support.DisposableBeanAdapter.destroy:210] - Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214] diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index f97aaadc..395f762a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -72,6 +72,7 @@ public GroupResponseDTO.CreateUnOfficialGroupResponseDTO createUnOfficialGroup(G case UNOFFICIAL_OPENED -> buildUnOfficialOpenedGroup(requestDTO); default -> throw new Exception400("유효하지 않은 그룹 유형입니다."); }; + log.debug("그룹 생성 완료"); // MemberId로부터 Member 찾기 @@ -165,7 +166,6 @@ public GroupResponseDTO.SearchOfficialGroupResponseDTO searchOfficialGroupByKeyw if (officialGroups.isEmpty()) { log.info("공식 그룹 마지막 페이지"); - throw new Exception404("마지막 페이지입니다."); } return new GroupResponseDTO.SearchOfficialGroupResponseDTO(officialGroups); @@ -184,7 +184,6 @@ public GroupResponseDTO.SearchUnOfficialGroupResponseDTO searchUnOfficialGroupBy if (unOfficialOpenedGroups.isEmpty()) { log.info("비공식 공개 그룹 마지막 페이지"); - throw new Exception404("마지막 페이지입니다."); } return new GroupResponseDTO.SearchUnOfficialGroupResponseDTO(unOfficialOpenedGroups); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java index 7f6a269f..36dbc250 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/InvitationService.java @@ -8,6 +8,7 @@ import com.kakao.techcampus.wekiki.group.domain.Invitation; import com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -16,6 +17,7 @@ import java.util.Optional; import java.util.Set; +@Slf4j @RequiredArgsConstructor @Service public class InvitationService { @@ -37,7 +39,12 @@ public class InvitationService { */ public GroupResponseDTO.GetInvitationLinkResponseDTO getGroupInvitationCode(Long groupId) { - groupJPARepository.findById(groupId).orElseThrow(() -> new Exception404("해당 그룹을 찾을 수 없습니다.")); + groupJPARepository.findById(groupId).orElseThrow(() -> { + log.info("존재하지 않는 그룹 접근 " + groupId + " 번 그룹"); + throw new Exception404("해당 그룹을 찾을 수 없습니다."); + }); + + log.debug("그룹 조회 완료"); String groupKey = GROUP_ID_PREFIX + groupId; @@ -53,8 +60,12 @@ public GroupResponseDTO.GetInvitationLinkResponseDTO getGroupInvitationCode(Long invitation = Invitation.create(groupId); redisUtils.setInvitationValues(groupKey, invitation, invitation.remainDuration(LocalDateTime.now())); redisUtils.setGroupIdValues(INVITATION_PREFIX + invitation.code(), groupId, invitation.remainDuration(LocalDateTime.now())); + + log.debug("invitation Redis 저장 완료"); } + log.debug("invitation 조회 완료"); + // 있으면 해당 초대 링크로 requestDTO 생성 return new GroupResponseDTO.GetInvitationLinkResponseDTO(groupId, invitation); } @@ -65,22 +76,35 @@ public GroupResponseDTO.ValidateInvitationResponseDTO validateInvitation(String // 초대 링크를 통해 groupId와 invitation 찾기 // groupId는 현재 Integer 타입 Object groupId = Optional.ofNullable(redisUtils.getValues(INVITATION_PREFIX + invitationLink)) - .orElseThrow(() -> new Exception404("존재하지 않는 초대 링크입니다.")); + .orElseThrow(() -> { + log.info(invitationLink + "에 해당하는 그룹이 조회 불가"); + throw new Exception404("존재하지 않는 초대 링크입니다."); + }); + + log.debug("초대링크에 해당하는 그룹 조회 완료"); // 초대 링크 기간 확인 Invitation invitation = (Invitation) redisUtils.getValues(GROUP_ID_PREFIX + groupId); if(invitation == null || !invitation.isUsableAt(LocalDateTime.now())) { + log.info(groupId + " 번 그룹의 만료된 초대 링크 사용"); throw new Exception404("이미 만료된 초대 링크입니다."); } + + log.debug("해당 그룹의 초대 링크 유효 기간 확인 완료"); Long lGroupId = ((Integer) groupId).longValue(); - Group group = groupJPARepository.findById(lGroupId).orElseThrow( - () -> new Exception400("해당 그룹은 존재하지 않습니다.") - ); + Group group = groupJPARepository.findById(lGroupId).orElseThrow(() -> { + log.info(groupId + " 번 그룹은 존재하지 않는 그룹"); + throw new Exception400("해당 그룹은 존재하지 않습니다."); + }); + + log.debug("그룹 조회 완료"); redisUtils.setGroupIdValues(MEMBER_ID_PREFIX + memberId, lGroupId, Duration.ofHours(MEMBER_ID_LIFETIME)); + + log.debug("회원 가입 권한 저장 완료"); return new GroupResponseDTO.ValidateInvitationResponseDTO(group); } @@ -91,6 +115,8 @@ public GroupResponseDTO.ValidateInvitationResponseDTO validateInvitation(String */ private void removeExpiredInvitations() { Set keys = redisUtils.getKeys(GROUP_ID_PREFIX + "*"); + + log.debug("Redis 내의 초대 링크 관련 key 리스트 조회 완료"); for (String key : keys) { Invitation invitation = (Invitation) redisUtils.getValues(key); @@ -101,6 +127,8 @@ private void removeExpiredInvitations() { redisUtils.deleteValues(INVITATION_PREFIX + invitation.code()); } } + + log.debug("Redis 내의 만료된 초대 링크 관련 값들 삭제 완료"); } // 2주마다 화요일 새벽 4시에 Redis 검사 후 만료된 초대 링크 확인하고 삭제 From 349484f3ea309da553aaa6f170d8ce2179313c8d Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 10 Nov 2023 11:48:41 +0900 Subject: [PATCH 125/144] =?UTF-8?q?Refactor:=20gitignore=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - log 파일 관련 수정 --- wekiki/.gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wekiki/.gitignore b/wekiki/.gitignore index 70e7b6a6..058a048f 100644 --- a/wekiki/.gitignore +++ b/wekiki/.gitignore @@ -46,6 +46,10 @@ out/ # Log file *.log **/*.log +log/error/*.log +log/info/*.log +log/warn/*.log + # BlueJ files *.ctxt From f100c45e5b841a1a9583cff73abbb51ef1b6e2a8 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 10 Nov 2023 11:54:19 +0900 Subject: [PATCH 126/144] =?UTF-8?q?Refactor:=20gitignore=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EA=B4=80=EB=A0=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wekiki/.gitignore | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/wekiki/.gitignore b/wekiki/.gitignore index 058a048f..3eddf96f 100644 --- a/wekiki/.gitignore +++ b/wekiki/.gitignore @@ -45,10 +45,7 @@ out/ # Log file *.log -**/*.log -log/error/*.log -log/info/*.log -log/warn/*.log +**/log/**/*.log # BlueJ files From 365042161f1f7c6d863c5f9a233ff9d62e76ca3a Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 10 Nov 2023 12:56:03 +0900 Subject: [PATCH 127/144] =?UTF-8?q?Fix:=20=EA=B7=B8=EB=A3=B9=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 그룹 삭제 시 오류 해결 --- .../wekiki/comment/CommentJPARepository.java | 3 -- .../techcampus/wekiki/group/domain/Group.java | 2 +- .../wekiki/group/service/GroupService.java | 51 +++++++++---------- .../wekiki/history/HistoryJPARepository.java | 3 -- .../wekiki/page/PageJPARepository.java | 2 +- .../wekiki/post/PostJPARepository.java | 3 -- .../wekiki/report/ReportJPARepository.java | 4 +- 7 files changed, 27 insertions(+), 41 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java index 819e4bd5..d80dcb73 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java @@ -18,7 +18,4 @@ public interface CommentJPARepository extends JpaRepository { @Query("SELECT c FROM Comment c LEFT JOIN FETCH c.groupMember WHERE c.id = :commentId") Optional findCommentWithGroupMember(@Param("commentId") Long commentId); - - @Query("SELECT c FROM Comment c WHERE c.groupMember.id = :groupMemberId") - List findAllByGroupMemberId(@Param("groupMemberId") Long groupMemberId); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java index 277951b5..27510041 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java @@ -24,7 +24,7 @@ public class Group { private String groupName; private String groupProfileImage; - @OneToMany(mappedBy = "group") + @OneToMany(mappedBy = "group", cascade = CascadeType.REMOVE) private List groupMembers = new ArrayList<>(); private int memberCount; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 395f762a..aea3e215 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -407,53 +407,48 @@ public void leaveGroup(Long groupId, Long memberId) { } private void deleteGroup(Group group) { - List groupMemberList = groupMemberJPARepository.findAllByGroupId(group.getId()); - - log.debug("그룹 멤버 조회 완료"); + List pageList = pageJPARepository.findAllByGroupId(group.getId()); - for (GroupMember groupMember : groupMemberList) { - Long groupMemberId = groupMember.getId(); - - List reportList = reportJPARepository.findAllByFromMemberId(groupMemberId); - reportJPARepository.deleteAll(reportList); - - log.debug("리포트 삭제 완료"); + for(PageInfo pageInfo : pageList) { + for(Post post : pageInfo.getPosts()) { + commentJPARepository.deleteAll(post.getComments()); - List historyList = historyJPARepository.findAllByGroupMemberId(groupMemberId); - historyJPARepository.deleteAll(historyList); + log.debug(post.getId() + " 번 post의 모든 comment 삭제 완료"); - log.debug("히스토리 삭제 완료"); + for(History history : post.getHistorys()) { + List reportList = reportJPARepository.findALLByHistoryId(history.getId()); + reportJPARepository.deleteAll(reportList); - List commentList = commentJPARepository.findAllByGroupMemberId(groupMemberId); - commentJPARepository.deleteAll(commentList); + log.debug(history.getId() + " 번 history의 모든 report 삭제 완료"); + } - log.debug("댓글 삭제 완료"); + historyJPARepository.deleteAll(post.getHistorys()); - List postList = postJPARepository.findAllByGroupMember(groupMemberId); - postJPARepository.deleteAll(postList); + log.debug(post.getId() + " 번 post의 모든 history 삭제 완료"); + } - log.debug("포스트 삭제 완료"); + postJPARepository.deleteAll(pageInfo.getPosts()); - List pageInfoList = pageJPARepository.findAllByGroupMember(group.getId()); - pageJPARepository.deleteAll(pageInfoList); + log.debug(pageInfo.getId() + " 번 page의 모든 post 삭제 완료"); + } - log.debug("페이지 삭제 완료"); + pageJPARepository.deleteAll(pageList); + for(GroupMember groupMember : group.getGroupMembers()) { Member member = groupMember.getMember(); member.getGroupMembers().remove(groupMember); memberJPARepository.save(member); - log.debug("회원 내 그룹 멤버 삭제 완료"); + log.debug(member.getId() + " 번 회원의 groupMember 삭제 완료"); + } - group.removeGroupMember(groupMember); - groupMemberJPARepository.delete(groupMember); + groupMemberJPARepository.deleteAll(group.getGroupMembers()); - log.debug("그룹 멤버 삭제 완료"); - } + log.debug(group.getId() + " 번 group의 모든 groupMember 삭제 완료"); groupJPARepository.delete(group); - log.debug("그룹 삭제 완료"); + log.debug("group 삭제 완료"); } protected Member getMemberById(Long memberId) { diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java index 3ae813a8..f0c3807f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java @@ -17,9 +17,6 @@ public interface HistoryJPARepository extends JpaRepository { @Query("DELETE FROM History h WHERE h.post.id = :postId") void deleteByPostId(@Param("postId") Long postId); - @Query("SELECT h FROM History h WHERE h.groupMember.id = :groupMemberId") - List findAllByGroupMemberId(@Param("groupMemberId") Long groupMemberId); - @Query("SELECT h FROM History h WHERE h.groupMember.id = :groupMemberId") Page findAllByGroupMember(@Param("groupMemberId") Long groupMemberId, Pageable pageable); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java index e72c31a3..48ecd87a 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/page/PageJPARepository.java @@ -39,5 +39,5 @@ public interface PageJPARepository extends JpaRepository { Page findPages(@Param("groupId") Long groupId, @Param("keyword") String keyword, Pageable pageable); @Query("SELECT p FROM PageInfo p WHERE p.group.id = :groupId") - List findAllByGroupMember(@Param("groupId") Long groupId); + List findAllByGroupId(@Param("groupId") Long groupId); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java index f0192912..b43511c5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/post/PostJPARepository.java @@ -28,9 +28,6 @@ List findPostsByPageIdAndOrderGreaterThan( boolean existsByParentId(Long parentId); - @Query("SELECT p FROM Post p WHERE p.groupMember.id = :groupId") - List findAllByGroupMember(@Param("groupId") Long groupId); - // 해당 pageId를 가지고 있는 post들 중에 orders가 1인거 들고오기 @Query("SELECT p FROM Post p WHERE p.pageInfo.id = :pageId AND p.orders = 1") List findFirstPost(@Param("pageId") Long pageId); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java index 1425b814..f6bba894 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java @@ -8,6 +8,6 @@ public interface ReportJPARepository extends JpaRepository { - @Query("SELECT r FROM Report r WHERE r.fromMember.id = :groupMemberId") - List findAllByFromMemberId(@Param("groupMemberId") Long groupMemberId); + @Query("SELECT r FROM Report r WHERE r.history.id = :historyId") + List findALLByHistoryId(@Param("historyId") Long historyId); } From 79baca26023e46a825abe3708b8be0ee2605fbd2 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 10 Nov 2023 15:31:04 +0900 Subject: [PATCH 128/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 그룹 삭제 수정 --- .../wekiki/comment/CommentJPARepository.java | 2 ++ .../wekiki/group/service/GroupService.java | 20 +++---------------- .../wekiki/history/HistoryJPARepository.java | 1 + .../wekiki/report/ReportJPARepository.java | 6 ++++++ 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java index d80dcb73..f1c8ecc4 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/comment/CommentJPARepository.java @@ -1,8 +1,10 @@ package com.kakao.techcampus.wekiki.comment; +import com.kakao.techcampus.wekiki.post.Post; 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.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index aea3e215..6b8c0684 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -36,6 +36,7 @@ import java.time.LocalDateTime; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; @Slf4j @Transactional(readOnly = true) @@ -411,20 +412,9 @@ private void deleteGroup(Group group) { for(PageInfo pageInfo : pageList) { for(Post post : pageInfo.getPosts()) { - commentJPARepository.deleteAll(post.getComments()); + reportJPARepository.deleteReportsByHistoryInQuery(post.getHistorys()); - log.debug(post.getId() + " 번 post의 모든 comment 삭제 완료"); - - for(History history : post.getHistorys()) { - List reportList = reportJPARepository.findALLByHistoryId(history.getId()); - reportJPARepository.deleteAll(reportList); - - log.debug(history.getId() + " 번 history의 모든 report 삭제 완료"); - } - - historyJPARepository.deleteAll(post.getHistorys()); - - log.debug(post.getId() + " 번 post의 모든 history 삭제 완료"); + log.debug(post.getId() + " 번 post의 모든 report 삭제 완료"); } postJPARepository.deleteAll(pageInfo.getPosts()); @@ -442,10 +432,6 @@ private void deleteGroup(Group group) { log.debug(member.getId() + " 번 회원의 groupMember 삭제 완료"); } - groupMemberJPARepository.deleteAll(group.getGroupMembers()); - - log.debug(group.getId() + " 번 group의 모든 groupMember 삭제 완료"); - groupJPARepository.delete(group); log.debug("group 삭제 완료"); diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java index f0c3807f..016d90b8 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/history/HistoryJPARepository.java @@ -1,5 +1,6 @@ package com.kakao.techcampus.wekiki.history; +import com.kakao.techcampus.wekiki.post.Post; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java index f6bba894..7e294ae0 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/report/ReportJPARepository.java @@ -1,6 +1,8 @@ package com.kakao.techcampus.wekiki.report; +import com.kakao.techcampus.wekiki.history.History; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -10,4 +12,8 @@ public interface ReportJPARepository extends JpaRepository { @Query("SELECT r FROM Report r WHERE r.history.id = :historyId") List findALLByHistoryId(@Param("historyId") Long historyId); + + @Modifying + @Query("DELETE FROM Report r WHERE r.history IN :historys") + void deleteReportsByHistoryInQuery(@Param("historys") List historys); } From 2935fc81c0f47ed71b1231c760313c4c63b7d2ba Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 10 Nov 2023 16:14:19 +0900 Subject: [PATCH 129/144] =?UTF-8?q?Refactor:=20GroupService=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 사용하지 않는 import문 삭제 --- .../kakao/techcampus/wekiki/group/service/GroupService.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 6b8c0684..868aee8b 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -3,8 +3,6 @@ import com.kakao.techcampus.wekiki._core.error.exception.Exception400; import com.kakao.techcampus.wekiki._core.error.exception.Exception404; import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; -import com.kakao.techcampus.wekiki.comment.Comment; -import com.kakao.techcampus.wekiki.comment.CommentJPARepository; import com.kakao.techcampus.wekiki.group.domain.Group; import com.kakao.techcampus.wekiki.group.domain.GroupMember; import com.kakao.techcampus.wekiki.group.dto.GroupRequestDTO; @@ -22,7 +20,6 @@ import com.kakao.techcampus.wekiki.page.PageJPARepository; import com.kakao.techcampus.wekiki.post.Post; import com.kakao.techcampus.wekiki.post.PostJPARepository; -import com.kakao.techcampus.wekiki.report.Report; import com.kakao.techcampus.wekiki.report.ReportJPARepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -36,7 +33,6 @@ import java.time.LocalDateTime; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; @Slf4j @Transactional(readOnly = true) @@ -54,7 +50,6 @@ public class GroupService { private final PageJPARepository pageJPARepository; private final PostJPARepository postJPARepository; private final HistoryJPARepository historyJPARepository; - private final CommentJPARepository commentJPARepository; private final ReportJPARepository reportJPARepository; private static final int GROUP_SEARCH_SIZE = 16; From 79d8d0b8967a9dfb5483c7fa8ba5fc7edc569964 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 10 Nov 2023 16:23:32 +0900 Subject: [PATCH 130/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Group 내부 안쓰는 메소드 삭제 - GroupService 내부 리팩토링 --- .../kakao/techcampus/wekiki/group/domain/Group.java | 5 ----- .../wekiki/group/service/GroupService.java | 12 +++++------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java index 27510041..b9a4137d 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/domain/Group.java @@ -47,9 +47,4 @@ public void addGroupMember(GroupMember groupMember) { public void minusMemberCount() { this.memberCount--; } - - public void removeGroupMember(GroupMember groupMember) { - this.groupMembers.remove(groupMember); - minusMemberCount(); - } } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 868aee8b..af6623a1 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -66,7 +66,10 @@ public GroupResponseDTO.CreateUnOfficialGroupResponseDTO createUnOfficialGroup(G Group group = switch (requestDTO.groupType()) { case UNOFFICIAL_CLOSED -> buildUnOfficialClosedGroup(requestDTO); case UNOFFICIAL_OPENED -> buildUnOfficialOpenedGroup(requestDTO); - default -> throw new Exception400("유효하지 않은 그룹 유형입니다."); + default -> { + log.info("그룹 생성 실패 " + memberId + " 번 회원"); + throw new Exception400("유효하지 않은 그룹 유형입니다."); + } }; log.debug("그룹 생성 완료"); @@ -79,12 +82,7 @@ public GroupResponseDTO.CreateUnOfficialGroupResponseDTO createUnOfficialGroup(G log.debug("GroupMember 생성 완료"); // Entity 저장 - group.addGroupMember(groupMember); - member.getGroupMembers().add(groupMember); - - groupJPARepository.save(group); - memberJPARepository.save(member); - groupMemberJPARepository.save(groupMember); + saveGroupMember(member, group, groupMember); log.debug("Entity 저장 완료"); From cbc027193a9b024c998832b96411858becd40b6a Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 10 Nov 2023 16:50:38 +0900 Subject: [PATCH 131/144] =?UTF-8?q?Refactor:=20=EA=B7=B8=EB=A3=B9=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kakao/techcampus/wekiki/group/service/GroupService.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index af6623a1..892f33b2 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -409,10 +409,6 @@ private void deleteGroup(Group group) { log.debug(post.getId() + " 번 post의 모든 report 삭제 완료"); } - - postJPARepository.deleteAll(pageInfo.getPosts()); - - log.debug(pageInfo.getId() + " 번 page의 모든 post 삭제 완료"); } pageJPARepository.deleteAll(pageList); From ddffd2e7bf5fdc2866c82c1fff531561c5389a38 Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Fri, 10 Nov 2023 19:02:09 +0900 Subject: [PATCH 132/144] =?UTF-8?q?Refactor:=20log=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- log/error/error-2023-11-09.log | 0 log/info/info-2023-11-09.log | 50 ---------------------------------- log/warn/warn-2023-11-09.log | 3 -- 3 files changed, 53 deletions(-) delete mode 100644 log/error/error-2023-11-09.log delete mode 100644 log/info/info-2023-11-09.log delete mode 100644 log/warn/warn-2023-11-09.log diff --git a/log/error/error-2023-11-09.log b/log/error/error-2023-11-09.log deleted file mode 100644 index e69de29b..00000000 diff --git a/log/info/info-2023-11-09.log b/log/info/info-2023-11-09.log deleted file mode 100644 index e4fa8636..00000000 --- a/log/info/info-2023-11-09.log +++ /dev/null @@ -1,50 +0,0 @@ -[2023-11-09 20:32:36:1657] [background-preinit] INFO [org.hibernate.validator.internal.util.Version.:21] - HV000001: Hibernate Validator 8.0.1.Final -[2023-11-09 20:32:37:1753] [restartedMain] INFO [org.springframework.boot.StartupInfoLogger.logStarting:51] - Starting WekikiApplication using Java 17.0.7 with PID 13828 (D:\카카오 테크 캠퍼스\Wikiki\wekiki\out\production\classes started by arheo in D:\카카오 테크 캠퍼스\Wikiki) -[2023-11-09 20:32:37:1754] [restartedMain] INFO [org.springframework.boot.SpringApplication.logStartupProfileInfo:643] - The following 1 profile is active: "local" -[2023-11-09 20:32:37:1862] [restartedMain] INFO [org.springframework.boot.logging.DeferredLog.logTo:250] - Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable -[2023-11-09 20:32:37:1865] [restartedMain] INFO [org.springframework.boot.logging.DeferredLog.logTo:250] - For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' -[2023-11-09 20:32:41:5761] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode -[2023-11-09 20:32:41:5764] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data JPA repositories in DEFAULT mode. -[2023-11-09 20:32:41:6099] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 325 ms. Found 8 JPA repository interfaces. -[2023-11-09 20:32:41:6124] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationDelegate.multipleStoresDetected:291] - Multiple Spring Data modules found, entering strict repository configuration mode -[2023-11-09 20:32:41:6127] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:138] - Bootstrapping Spring Data Redis repositories in DEFAULT mode. -[2023-11-09 20:32:41:6151] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.comment.CommentJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 20:32:41:6153] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 20:32:41:6153] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.group.repository.GroupMemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 20:32:41:6154] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.history.HistoryJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 20:32:41:6154] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.member.MemberJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 20:32:41:6154] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.page.PageJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 20:32:41:6155] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.post.PostJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 20:32:41:6155] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.isStrictRepositoryCandidate:320] - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.kakao.techcampus.wekiki.report.ReportJPARepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2023-11-09 20:32:41:6155] [restartedMain] INFO [org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn:208] - Finished Spring Data repository scanning in 15 ms. Found 0 Redis repository interfaces. -[2023-11-09 20:32:42:7286] [restartedMain] INFO [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize:108] - Tomcat initialized with port(s): 8080 (http) -[2023-11-09 20:32:42:7300] [restartedMain] INFO [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing ProtocolHandler ["http-nio-8080"] -[2023-11-09 20:32:42:7304] [restartedMain] INFO [org.apache.juli.logging.DirectJDKLog.log:173] - Starting service [Tomcat] -[2023-11-09 20:32:42:7304] [restartedMain] INFO [org.apache.juli.logging.DirectJDKLog.log:173] - Starting Servlet engine: [Apache Tomcat/10.1.13] -[2023-11-09 20:32:42:7425] [restartedMain] INFO [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring embedded WebApplicationContext -[2023-11-09 20:32:42:7457] [restartedMain] INFO [org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.prepareWebApplicationContext:291] - Root WebApplicationContext: initialization completed in 5590 ms -[2023-11-09 20:32:42:7603] [restartedMain] INFO [com.zaxxer.hikari.HikariDataSource.getConnection:110] - HikariPool-1 - Starting... -[2023-11-09 20:32:43:7940] [restartedMain] INFO [com.zaxxer.hikari.pool.HikariPool.checkFailFast:565] - HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:test user=SA -[2023-11-09 20:32:43:7944] [restartedMain] INFO [com.zaxxer.hikari.HikariDataSource.getConnection:123] - HikariPool-1 - Start completed. -[2023-11-09 20:32:43:7963] [restartedMain] INFO [org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.logDataSources:88] - H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:test' -[2023-11-09 20:32:44:8877] [restartedMain] INFO [org.hibernate.jpa.internal.util.LogHelper.logPersistenceUnitInformation:31] - HHH000204: Processing PersistenceUnitInfo [name: default] -[2023-11-09 20:32:44:8995] [restartedMain] INFO [org.hibernate.Version.logVersion:44] - HHH000412: Hibernate ORM core version 6.2.9.Final -[2023-11-09 20:32:44:9001] [restartedMain] INFO [org.hibernate.cfg.Environment.:191] - HHH000406: Using bytecode reflection optimizer -[2023-11-09 20:32:44:9283] [restartedMain] INFO [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy -[2023-11-09 20:32:44:9624] [restartedMain] INFO [org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo.addTransformer:87] - No LoadTimeWeaver setup: ignoring JPA class transformer -[2023-11-09 20:32:45:10189] [restartedMain] INFO [org.hibernate.bytecode.internal.BytecodeProviderInitiator.buildBytecodeProvider:53] - HHH000021: Bytecode provider name : bytebuddy -[2023-11-09 20:32:46:11541] [restartedMain] INFO [org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator.initiateService:51] - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] -[2023-11-09 20:32:46:11664] [restartedMain] INFO [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory:437] - Initialized JPA EntityManagerFactory for persistence unit 'default' -[2023-11-09 20:32:47:12144] [restartedMain] INFO [org.springframework.data.jpa.repository.query.QueryEnhancerFactory.:47] - Hibernate is in classpath; If applicable, HQL parser will be used. -[2023-11-09 20:32:49:13865] [restartedMain] INFO [org.springframework.security.web.DefaultSecurityFilterChain.:54] - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@4d852dd0, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@395553b, org.springframework.security.web.context.SecurityContextHolderFilter@2313e93b, org.springframework.security.web.header.HeaderWriterFilter@113a6ad6, org.springframework.security.web.authentication.logout.LogoutFilter@23db507b, com.kakao.techcampus.wekiki._core.jwt.JWTTokenFilter@1ef875bb, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@5f39521a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@4ecffe3f, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@203d815d, org.springframework.security.web.session.SessionManagementFilter@2eb325e, org.springframework.security.web.access.ExceptionTranslationFilter@1399dc87, org.springframework.security.web.access.intercept.AuthorizationFilter@42219fe4] -[2023-11-09 20:32:50:14902] [restartedMain] INFO [org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer.startServer:59] - LiveReload server is running on port 35729 -[2023-11-09 20:32:50:14910] [restartedMain] INFO [org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver.:58] - Exposing 1 endpoint(s) beneath base path '/actuator' -[2023-11-09 20:32:50:14998] [restartedMain] INFO [org.apache.juli.logging.DirectJDKLog.log:173] - Starting ProtocolHandler ["http-nio-8080"] -[2023-11-09 20:32:50:15030] [restartedMain] INFO [org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start:220] - Tomcat started on port(s): 8080 (http) with context path '' -[2023-11-09 20:32:50:15053] [restartedMain] INFO [org.springframework.boot.StartupInfoLogger.logStarted:57] - Started WekikiApplication in 14.533 seconds (process running for 16.379) -[2023-11-09 20:33:00:25400] [http-nio-8080-exec-2] INFO [org.apache.juli.logging.DirectJDKLog.log:173] - Initializing Spring DispatcherServlet 'dispatcherServlet' -[2023-11-09 20:33:00:25401] [http-nio-8080-exec-2] INFO [org.springframework.web.servlet.FrameworkServlet.initServletBean:532] - Initializing Servlet 'dispatcherServlet' -[2023-11-09 20:33:00:25403] [http-nio-8080-exec-2] INFO [org.springframework.web.servlet.FrameworkServlet.initServletBean:554] - Completed initialization in 2 ms -[2023-11-09 20:33:09:34246] [SpringApplicationShutdownHook] INFO [org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.destroy:650] - Closing JPA EntityManagerFactory for persistence unit 'default' -[2023-11-09 20:33:10:34717] [SpringApplicationShutdownHook] INFO [com.zaxxer.hikari.HikariDataSource.close:350] - HikariPool-1 - Shutdown initiated... -[2023-11-09 20:33:10:34733] [SpringApplicationShutdownHook] INFO [com.zaxxer.hikari.HikariDataSource.close:352] - HikariPool-1 - Shutdown completed. diff --git a/log/warn/warn-2023-11-09.log b/log/warn/warn-2023-11-09.log deleted file mode 100644 index 7e22e187..00000000 --- a/log/warn/warn-2023-11-09.log +++ /dev/null @@ -1,3 +0,0 @@ -[2023-11-09 20:32:48:12775] [restartedMain] WARN [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.post.PostJPARepository -[2023-11-09 20:32:48:13201] [restartedMain] WARN [org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass:123] - Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.kakao.techcampus.wekiki.page.PageJPARepository -[2023-11-09 20:33:09:34573] [SpringApplicationShutdownHook] WARN [org.springframework.beans.factory.support.DisposableBeanAdapter.destroy:210] - Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214] From 1fd2e755e7c8aa53610107c364d566a84c6f2a8a Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Fri, 10 Nov 2023 19:31:42 +0900 Subject: [PATCH 133/144] =?UTF-8?q?setting=20:=20=EB=B0=B0=ED=8F=AC=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 최종 배포를 위한 설정 파일 수정하였습니다 --- Dockerfile | 3 ++ k8s/backend.yaml | 2 +- k8s/configs/default.conf | 4 +++ k8s/configs/secret.conf | 12 ++++++++ k8s/frontend.yaml | 65 ++++++++++++++++++++++++++++++++++++++++ k8s/kustomization.yaml | 1 + k8s/nginx.yaml | 20 ++++++------- 7 files changed, 96 insertions(+), 11 deletions(-) create mode 100644 k8s/configs/secret.conf create mode 100644 k8s/frontend.yaml diff --git a/Dockerfile b/Dockerfile index 2cb72fab..4af8beb0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,5 +18,8 @@ RUN cd ./wekiki && ./gradlew clean build -x test # DATABASE_URL을 환경 변수로 삽입 ENV DATABASE_URL=jdbc:mariadb://mariadb/krampoline +ENV SERVER_URL=https://kb70bd6b8a3f6a.user-app.krampoline.com + + # 빌드 결과 jar 파일을 실행 CMD ["java", "-jar", "-Dspring.profiles.active=prod", "/home/wekiki/gradle/project/wekiki/build/libs/wekiki-0.0.1-SNAPSHOT.jar"] \ No newline at end of file diff --git a/k8s/backend.yaml b/k8s/backend.yaml index c328c7a0..04cda568 100644 --- a/k8s/backend.yaml +++ b/k8s/backend.yaml @@ -15,7 +15,7 @@ spec: containers: - name: backend # 여러분의 backend image 주소를 입력해주세요. - image: krmp-d2hub-idock.9rum.cc/dev-test/repo_bbaa5bcfc676 + image: krmp-d2hub-idock.9rum.cc/dev-test/repo_2be7005816e6 env: - name: TZ value: Asia/Seoul diff --git a/k8s/configs/default.conf b/k8s/configs/default.conf index 6096ccae..95ea323e 100644 --- a/k8s/configs/default.conf +++ b/k8s/configs/default.conf @@ -2,6 +2,10 @@ server { listen 80; location / { + proxy_pass http://frontend.default.svc.cluster.local:3000; + } + + location /api/ { proxy_pass http://backend.default.svc.cluster.local:8080; } } \ No newline at end of file diff --git a/k8s/configs/secret.conf b/k8s/configs/secret.conf new file mode 100644 index 00000000..4f2b55c3 --- /dev/null +++ b/k8s/configs/secret.conf @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Secret +metadata: + name: my-secret +data: + REACT_APP_API_URL: "aHR0cHM6Ly9rYjcwYmQ2YjhhM2Y2YS51c2VyLWFwcC5rcmFtcG9saW5lLmNvbQ==" + REACT_APP_BUCKET_NAME: "d2VraWtpYnVja2V0" + REACT_APP_REGION: "YXAtbm9ydGhlYXN0LTI=" + REACT_APP_ACCESS_KEY_ID: "QUtJQVVOUEhESlRMNUVPV0RDNFc=" + REACT_APP_SECRET_ACCESS_KEY: "OEJaWkVyeittV2JqKzA0WmJFVkxLdDl2ckdJRldtRGhseWdlMHpULw==" + REACT_APP_KAKAO_REDIRECT_URL: "aHR0cDovL2xvY2FsaG9zdDozMDAwL2F1dGgva2FrYW8vc2lnbmlu" + REACT_APP_KAKAO_REST_API_KEY: "MDhlNmM3MDkyMjlmM2I0NGE4Y2ZmMmZjNzE2OGUxYTI=" \ No newline at end of file diff --git a/k8s/frontend.yaml b/k8s/frontend.yaml new file mode 100644 index 00000000..5b803f5e --- /dev/null +++ b/k8s/frontend.yaml @@ -0,0 +1,65 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontend +spec: + selector: + matchLabels: + app: frontend + template: + metadata: + labels: + app: frontend + spec: + containers: + - name: frontend + # 여러분의 frontend image 주소를 입력해주세요. + image: krmp-d2hub-idock.9rum.cc/dev-test/repo_cf91e1e9b807 + env: + - name: REACT_APP_API_URL + valueFrom: + secretKeyRef: + name: my-secret + key: REACT_APP_API_URL + - name: REACT_APP_BUCKET_NAME + valueFrom: + secretKeyRef: + name: my-secret + key: REACT_APP_BUCKET_NAME + - name: REACT_APP_REGION + valueFrom: + secretKeyRef: + name: my-secret + key: REACT_APP_REGION + - name: REACT_APP_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: my-secret + key: REACT_APP_ACCESS_KEY_ID + - name: REACT_APP_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: my-secret + key: REACT_APP_SECRET_ACCESS_KEY + - name: REACT_APP_KAKAO_REDIRECT_URL + valueFrom: + secretKeyRef: + name: my-secret + key: REACT_APP_KAKAO_REDIRECT_URL + - name: REACT_APP_KAKAO_REST_API_KEY + valueFrom: + secretKeyRef: + name: my-secret + key: REACT_APP_KAKAO_REST_API_KEY +--- +apiVersion: v1 +kind: Service +metadata: + name: frontend +spec: + selector: + app: frontend + ports: + - port: 3000 + targetPort: 3000 \ No newline at end of file diff --git a/k8s/kustomization.yaml b/k8s/kustomization.yaml index b9cf12bd..00c95a3c 100644 --- a/k8s/kustomization.yaml +++ b/k8s/kustomization.yaml @@ -4,6 +4,7 @@ resources: - mariadb.yaml - backend.yaml - redis.yaml + - frontend.yaml configMapGenerator: - name: nginx files: diff --git a/k8s/nginx.yaml b/k8s/nginx.yaml index 2155470a..7ca1c4dd 100644 --- a/k8s/nginx.yaml +++ b/k8s/nginx.yaml @@ -14,17 +14,17 @@ spec: app: nginx spec: containers: - - name: nginx - image: nginx:latest - ports: - - containerPort: 80 - volumeMounts: - - name: nginx-config - mountPath: /etc/nginx/conf.d + - name: nginx + image: nginx:latest + ports: + - containerPort: 80 + volumeMounts: + - name: nginx-config + mountPath: /etc/nginx/conf.d volumes: - - name: nginx-config - configMap: - name: nginx + - name: nginx-config + configMap: + name: nginx --- apiVersion: v1 From c34f6c3f61de15e06c8dde3fd5699970d529ca65 Mon Sep 17 00:00:00 2001 From: kimdonwoo Date: Fri, 10 Nov 2023 19:37:00 +0900 Subject: [PATCH 134/144] =?UTF-8?q?setting=20:=20=EB=B0=B0=ED=8F=AC=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?(secret.yaml)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 최종 배포를 위한 설정 파일 수정하였습니다 --- k8s/configs/{secret.conf => secret.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename k8s/configs/{secret.conf => secret.yaml} (100%) diff --git a/k8s/configs/secret.conf b/k8s/configs/secret.yaml similarity index 100% rename from k8s/configs/secret.conf rename to k8s/configs/secret.yaml From a2a44910db026ebe6941612b16ba166ba84b8cb1 Mon Sep 17 00:00:00 2001 From: Jun2-Lee Date: Sat, 11 Nov 2023 13:19:25 +0900 Subject: [PATCH 135/144] =?UTF-8?q?Feat=20:=20=EC=B5=9C=EC=A2=85=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=20=ED=95=B8=EB=93=A4=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kakao/techcampus/wekiki/_core/jwt/JWTTokenProvider.java | 2 +- .../kakao/techcampus/wekiki/member/MemberController.java | 6 +++--- .../com/kakao/techcampus/wekiki/member/MemberRequest.java | 6 +++++- .../com/kakao/techcampus/wekiki/member/MemberService.java | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/jwt/JWTTokenProvider.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/jwt/JWTTokenProvider.java index b76681db..115afcc5 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/jwt/JWTTokenProvider.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/_core/jwt/JWTTokenProvider.java @@ -56,7 +56,7 @@ public MemberResponse.authTokenDTO generateToken(Authentication authentication) //암호화 .signWith(secretKey, SignatureAlgorithm.HS256) .compact(); - + log.info("위키키 엑세스 토큰 발급 완료" + accessToken); return new MemberResponse.authTokenDTO("Bearer", accessToken, accessTokenValidTime); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java index 2f5ba741..703d2d9e 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberController.java @@ -47,19 +47,19 @@ public ResponseEntity cancel() { */ @PatchMapping("/password/change") - public ResponseEntity changePassword(@RequestBody MemberRequest.changePasswordRequestDTO changePasswordRequestDTO) { + public ResponseEntity changePassword(@RequestBody @Valid MemberRequest.changePasswordRequestDTO changePasswordRequestDTO) { memberService.changePassword(changePasswordRequestDTO); return ResponseEntity.ok(true); } @PatchMapping("/changename") - public ResponseEntity changeNickName(@RequestBody MemberRequest.changeNickNameRequestDTO nickNameRequestDTO) { + public ResponseEntity changeNickName(@RequestBody @Valid MemberRequest.changeNickNameRequestDTO nickNameRequestDTO) { memberService.changeNickName(nickNameRequestDTO); return ResponseEntity.ok(true); } @PostMapping("/pusanuniv") - public ResponseEntity sendMail(@RequestBody MemberRequest.PNUEmailRequestDTO PNUemailRequestDTO) { + public ResponseEntity sendMail(@RequestBody @Valid MemberRequest.PNUEmailRequestDTO PNUemailRequestDTO) { memberService.sendEmail(PNUemailRequestDTO.getEmail()); return ResponseEntity.ok(true); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java index 8823a3f1..8709a18f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberRequest.java @@ -18,7 +18,7 @@ public static class signUpRequestDTO { @Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*[0-9]).{8,20}$", message = "(8~20자 영문과 숫자)") private String password; @NotNull - @Pattern(regexp = "^[가-힣a-zA-Z]{2,10}$", message = "(2~10자 한글, 영어)") + @Pattern(regexp = "^[가-힣a-zA-Z]{1,10}$", message = "(1~10자 한글, 영어)") private String nickName; } @@ -33,21 +33,25 @@ public static class loginRequestDTO { @Getter public static class changePasswordRequestDTO { private String currentPassword; + @Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*[0-9]).{8,20}$", message = "(8~20자 영문과 숫자)") private String newPassword; } @Getter public static class changeNickNameRequestDTO { + @Pattern(regexp = "^[가-힣a-zA-Z]{1,10}$", message = "(1~10자 한글, 영어)") private String newNickName; } @Getter public static class PNUEmailRequestDTO { + @Pattern(regexp = "^[A-Za-z0-9._%+-]+@pusan\\.ac\\.kr$") private String email; } @Getter public static class checkPNUEmailRequestDTO { + @Pattern(regexp = "^[A-Za-z0-9._%+-]+@pusan\\.ac\\.kr$") private String email; private String certificationNumber; } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index d26a075e..c07b334f 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -9,7 +9,6 @@ import com.kakao.techcampus.wekiki.group.domain.GroupMember; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -274,6 +273,7 @@ public MemberResponse.authTokenDTO getKakaoInfo(String code) { String kakaoEmail = kakaoInfo.getId() + "@wekiki.com"; Optional kakaoMember = memberRepository.findByEmail(kakaoEmail); if(kakaoMember.isEmpty()){ + log.info("없는 회원이니 카카오 회원가입을 진행합니다."); kakaoSignUp(kakaoInfo, kakaoEmail); } MemberRequest.loginRequestDTO kakaoLogin = new MemberRequest.loginRequestDTO(kakaoEmail,KAKAO_PASSWORD); From 25dfe53e176c7147bbdf3453a0a7c50bbff93fae Mon Sep 17 00:00:00 2001 From: INUK-ai Date: Sat, 11 Nov 2023 13:45:29 +0900 Subject: [PATCH 136/144] =?UTF-8?q?Refactor:=20=EB=B6=80=EC=82=B0=EB=8C=80?= =?UTF-8?q?=20=EA=B7=B8=EB=A3=B9=20=EA=B0=80=EC=9E=85=20=EC=8B=9C=20?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=EA=B6=8C=ED=95=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 부산대 그룹 이메일 인증 시 가입 권한 설정 - 그룹 내 중복 닉네임 검사 수정 --- .../techcampus/wekiki/group/service/GroupService.java | 9 +++------ .../kakao/techcampus/wekiki/member/MemberService.java | 9 ++++++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java index 892f33b2..4e7a6196 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/group/service/GroupService.java @@ -19,7 +19,6 @@ import com.kakao.techcampus.wekiki.page.PageInfo; import com.kakao.techcampus.wekiki.page.PageJPARepository; import com.kakao.techcampus.wekiki.post.Post; -import com.kakao.techcampus.wekiki.post.PostJPARepository; import com.kakao.techcampus.wekiki.report.ReportJPARepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -48,7 +47,6 @@ public class GroupService { private final GroupMemberJPARepository groupMemberJPARepository; private final MemberJPARepository memberJPARepository; private final PageJPARepository pageJPARepository; - private final PostJPARepository postJPARepository; private final HistoryJPARepository historyJPARepository; private final ReportJPARepository reportJPARepository; @@ -236,6 +234,9 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ log.debug("가입 권한 확인 완료"); String groupNickName = requestDTO.nickName(); + groupNickNameCheck(groupId, groupNickName); + + log.debug("그룹 닉네임 중복 확인 완료"); GroupMember wasGroupMember = groupMemberJPARepository.findGroupMemberByMemberIdAndGroupId(memberId, groupId); @@ -252,10 +253,6 @@ public void joinGroup(Long groupId, Long memberId, GroupRequestDTO.JoinGroupRequ // GroupMember 저장 saveGroupMember(member, group, wasGroupMember); } else { - groupNickNameCheck(groupId, groupNickName); - - log.debug("그룹 닉네임 중복 확인 완료"); - saveGroupMember(member, group, buildGroupMember(member, group, groupNickName)); } diff --git a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java index d26a075e..0e24de99 100644 --- a/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java +++ b/wekiki/src/main/java/com/kakao/techcampus/wekiki/member/MemberService.java @@ -6,10 +6,10 @@ import com.kakao.techcampus.wekiki._core.error.exception.*; import com.kakao.techcampus.wekiki._core.jwt.JWTTokenProvider; import com.kakao.techcampus.wekiki._core.utils.RedisUtility; +import com.kakao.techcampus.wekiki._core.utils.redis.RedisUtils; import com.kakao.techcampus.wekiki.group.domain.GroupMember; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -31,6 +31,7 @@ import java.net.InetSocketAddress; import java.net.Proxy; +import java.time.Duration; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -49,6 +50,7 @@ public class MemberService { private final AuthenticationManagerBuilder authenticationManagerBuilder; private final PasswordEncoder passwordEncoder; private final RedisUtility redisUtility; + private final RedisUtils redisUtils; private final JavaMailSender javaMailSender; @Value("${kakao.client.id}") private String KAKAO_CLIENT_ID; @@ -58,6 +60,9 @@ public class MemberService { private String KAKAO_PASSWORD; private static final String PROXY_HOST = "krmp-proxy.9rum.cc"; private static final int PROXY_PORT = 3128; + private static final String MEMBER_ID_PREFIX = "member_id:"; + private static final long MEMBER_ID_LIFETIME = 3L; + private static final long PNU_GROUP_ID = 8L; public void signUp(MemberRequest.signUpRequestDTO signUpRequestDTO) { @@ -188,6 +193,8 @@ public void checkPNUEmail(MemberRequest.checkPNUEmailRequestDTO pnuEmailRequestD log.error("부산대 메일 인증 번호가 틀렸습니다. User Id : " + member.getEmail()); throw new Exception400("인증번호가 틀렸습니다."); } + + redisUtils.setGroupIdValues(MEMBER_ID_PREFIX + member.getId(), PNU_GROUP_ID, Duration.ofHours(MEMBER_ID_LIFETIME)); } public void findPassword(String email) { From 88b6b9671a36bc32651751b879f89e6600c0008c Mon Sep 17 00:00:00 2001 From: JunHee Date: Sat, 11 Nov 2023 14:11:57 +0900 Subject: [PATCH 137/144] Update README.md --- README.md | 352 +++++++++++++----------------------------------------- 1 file changed, 86 insertions(+), 266 deletions(-) diff --git a/README.md b/README.md index 0999e20d..5838dc13 100644 --- a/README.md +++ b/README.md @@ -1,331 +1,151 @@ # Team8_BE +스크린샷 2023-11-11 오후 1 41 12 ## 프로젝트 소개 -스크린샷 2023-11-09 오전 3 08 11 +
+ +

image + + +

+ ||설명| |-----------|----| |제목 |위키키| |개발 목적| 그룹별로 자신들만의 나무위키를 만들고, 기록하고자 하는 사람들을 위해 프로젝트를 만들었습니다. | -|개발 기간|2023.09 - 2023.11| +|개발 기간|2023.09 - 2023.11| +
+ +
## 팀원 +
+ | [이준희](https://github.com/Jun2-Lee) | [김돈우](https://github.com/kimdonwoo) | [황인욱](https://github.com/INUK-ai)| -|----------|----------|----------| +|:----------:|:----------:|:----------:| | | | | +| 회원, 인증 | 페이지, 게시글 | 그룹 | -
- -## 주요기능 -<주요 기능 적기> - -## 문서 -|문서 목록| -|----| -[GitHub (FE)](https://github.com/Step3-kakao-tech-campus/Team8_FE) -[ERD](https://www.notion.so/ERD-e0a43b03115d4551a6138d7b98c43e68) -[API 문서](https://www.notion.so/API-e6a2fe24cffe4c54ad9815f32dd8790b) -[와이어프레임](https://www.figma.com/file/HrjwnC0UfzYJjmwaBRg7uj/8%EC%A1%B0-%EC%99%80%EC%9D%B4%EC%96%B4-%ED%94%84%EB%A0%88%EC%9E%84-Web-%2F-Mobile?type=design&node-id=0-1&mode=design&t=wkU2aDHsx0pHTvYT-0) - - -## 기술 스택 -**Spring Boot** : 3.1.4 - -- **Spring Security** -- **JPA** -- **Lombok** -- **Actuator** -- **JWT** -- **Validation** - -**Java** : 17 - -**DB** - -- 테스트/로컬 용 : H2 -- 배포용 : MariaDB 최신 버전 - -**redis** - - -## How to Use - -``` -git clone https://github.com/Step3-kakao-tech-campus/Team8_BE.git -// 깃헙 주소 클론 -// 그 뒤 로컬 저장소로 이동 -./gradlew build -// 프로젝트 빌드 -java -jar ./build/libs/wekiki-0.0.1-SNAPSHOT.jar -// 빌드 파일 실행 -``` - - - - - - - - +
+
-
-카카오 테크 캠퍼스 3단계 진행 보드 -
+## 배포 링크 +> **프론트 서버** : https://kb70bd6b8a3f6a.user-app.krampoline.com/ +**백엔드 서버** : https://kb70bd6b8a3f6a.user-app.krampoline.com/api/ +
+## 주요기능 +### 그룹 생성 +- 사용자는 그룹을 생성하고 관리할 수 있습니다. 그룹의 이름, 대표 사진, 공개 여부 등을 설정할 수 있습니다. -
+### 그룹 가입 및 초대 -## 배포와 관련하여 +- 사용자는 그룹에 가입하거나 초대를 받아 그룹에 참여할 수 있습니다. 초대코드를 통해 그룹 가입을 할 수 있습니다. -``` +### 그룹원 관리 -최종 배포는 크램폴린으로 배포해야 합니다. +- 그룹의 멤버 리스트를 확인하고 관리할 수 있습니다. 그룹원 초대, 탈퇴 등의 기능이 제공됩니다. -하지만 배포 환경의 불편함이 있는 경우를 고려하여 +### 페이지 관리 -임의의 배포를 위해 타 배포 환경을 자유롭게 이용해도 됩니다. (단, 금액적인 지원은 어렵습니다.) +- 그룹 내에서 페이지를 생성하고 수정할 수 있습니다. 각 페이지는 제목, 내용, 목차 등을 가지고 있습니다. -아래는 추가적인 설정을 통해 (체험판, 혹은 프리 티어 등)무료로 클라우드 배포가 가능한 서비스입니다. +### 히스토리 조회 -ex ) AWS(아마존), GCP(구글), Azure(마이크로소프트), Cloudtype +- 그룹 내에서 변경된 최근 페이지의 히스토리를 확인할 수 있습니다. -``` -## Notice +### 댓글 기능 -``` -필요 산출물들은 수료 기준에 영향을 주는 것은 아니지만, -주차 별 산출물을 기반으로 평가가 이루어 집니다. - -주차 별 평가 점수는 추 후 최종 평가에 최종 합산 점수로 포함됩니다. -``` +- 사용자는 페이지에 댓글을 작성하고 수정, 삭제할 수 있습니다. -![레포지토리 운영-001 (1)](https://github.com/Step3-kakao-tech-campus/practice/assets/138656575/acb0dccd-0441-4200-999a-981865535d5f) -![image](https://github.com/Step3-kakao-tech-campus/practice/assets/138656575/b42cbc06-c5e7-4806-8477-63dfa8e807a0) +### 문서 기여 목록 -[git flowchart_FE.pdf](https://github.com/Step3-kakao-tech-campus/practice/files/12521045/git.flowchart_FE.pdf) +- 사용자는 그룹 내에서 자신이 기여한 문서의 목록을 확인할 수 있습니다. +### 검색 기능 -
+- 사용자는 메인 페이지에서 그룹을 검색할 수 있으며, 그룹 내에서는 페이지를 검색할 수 있습니다. +- 검색 결과를 확인하고 해당 페이지로 이동할 수 있습니다. -## 필요 산출물 -
-Step3. Week-1 -
- -✅**1주차** - -``` - - 5 Whys - - 마켓 리서치 - - 페르소나 & 저니맵 - - 와이어 프레임 - - 칸반보드 -``` - -
-
+### 회원가입 및 로그인 ---- +- 사용자는 카카오 로그인을 통해 로그인 하거나, 회원가입을 통해 계정을 생성하고 로그인하여 서비스를 이용할 수 있습니다. -
-Step3. Week-2 -
- -✅**2주차** - -``` - - ERD 설계서 - - - API 명세서 -``` - -
-
+
---- +## 프로젝트 구조도 -
-Step3. Week-3 -
- -✅**3주차** - -``` - - 최종 기획안 -``` - -
-
---- +
-
-Step3. Week-4 -
- -✅**4주차** - -``` - - 4주차 github - - - 4주차 노션 -``` - -
-
+## 문서 +|문서 목록| +|----| +[GitHub (FE)](https://github.com/Step3-kakao-tech-campus/Team8_FE) +[API 문서](https://www.notion.so/API-e6a2fe24cffe4c54ad9815f32dd8790b) +[와이어프레임](https://www.figma.com/file/HrjwnC0UfzYJjmwaBRg7uj/8%EC%A1%B0-%EC%99%80%EC%9D%B4%EC%96%B4-%ED%94%84%EB%A0%88%EC%9E%84-Web-%2F-Mobile?type=design&node-id=0-1&mode=design&t=wkU2aDHsx0pHTvYT-0) ---- -
-Step3. Week-5 -
- -✅**5주차** - -``` - - 5주차 github - - - 5주차 노션 -``` - -
-
+
---- +## ERD -
-Step3. Week-6 -
- -✅**6주차** - -``` - - 6주차 github - - - 중간발표자료 - - - 피어리뷰시트 -``` - -
-
---- +
-
-Step3. Week-7 -
- -✅**7주차** - -``` - - 7주차 github - - - 7주차 노션 -``` - -
-
+## 기술 스택 +**Spring Boot** : 3.1.4 ---- +- **Spring Security** +- **JPA** +- **Lombok** +- **Actuator** +- **JWT** +- **Validation** -
-Step3. Week-8 -
- -✅**8주차** - -``` - - 중간고사 - -``` - -
-
+**Java** : 17 ---- +**DB** + +- 테스트/로컬 용 : H2 +- 배포용 : MariaDB 최신 버전 -
-Step3. Week-9 -
- -✅**9주차** - -``` - - 9주차 github - - - 9주차 노션 -``` - -
-
+**redis** ---- +
-
-Step3. Week-10 -
- -✅**10주차** - -``` - - 10주차 github - - - 테스트 시나리오 명세서 - - - 테스트 결과 보고서 -``` - -
-
+## Feature ---- -
-Step3. Week-11 -
- -✅**11주차** - -``` - - 최종 기획안 - - - 배포 인스턴스 링크 -``` - -
-
+
---- -## **과제 상세 : 수강생들이 과제를 진행할 때, 유념해야할 것** +## How to Use ``` -1. README.md 파일은 동료 개발자에게 프로젝트에 쉽게 랜딩하도록 돕는 중요한 소통 수단입니다. -해당 프로젝트에 대해 아무런 지식이 없는 동료들에게 설명하는 것처럼 쉽고, 간결하게 작성해주세요. - -2. 좋은 개발자는 디자이너, 기획자, 마케터 등 여러 포지션에 있는 분들과 소통을 잘합니다. -UI 컴포넌트의 명칭과 이를 구현하는 능력은 필수적인 커뮤니케이션 스킬이자 필요사항이니 어떤 상황에서 해당 컴포넌트를 사용하면 좋을지 고민하며 코드를 작성해보세요. - +git clone https://github.com/Step3-kakao-tech-campus/Team8_BE.git +// 깃헙 주소 클론 +// 그 뒤 로컬 저장소로 이동 +./gradlew build +// 프로젝트 빌드 +java -jar ./build/libs/wekiki-0.0.1-SNAPSHOT.jar +// 빌드 파일 실행 ``` -
-## **코드리뷰 관련: review branch로 PR시, 아래 내용을 포함하여 코멘트 남겨주세요.** +
-**1. PR 제목과 내용을 아래와 같이 작성 해주세요.** +## License +MIT License -> PR 제목 : 부산대_0조_아이템명_0주차 -> +Copyright (c) 2023 [1기] 카카오 테크 캠퍼스 (3단계) 프로젝트 8조 -
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -
-
- - +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. ---- +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From add86cd033ae133e4d243b9529fc3ec9d98e0614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=8F=84=EB=88=84?= Date: Sat, 11 Nov 2023 15:04:06 +0900 Subject: [PATCH 138/144] Update application.yml --- wekiki/src/main/resources/application.yml | 47 ----------------------- 1 file changed, 47 deletions(-) diff --git a/wekiki/src/main/resources/application.yml b/wekiki/src/main/resources/application.yml index 7169003f..d9638774 100644 --- a/wekiki/src/main/resources/application.yml +++ b/wekiki/src/main/resources/application.yml @@ -1,51 +1,4 @@ spring: - datasource: - url: jdbc:h2:mem:test;MODE=MariaDB - driver-class-name: org.h2.Driver - username: sa - password: - h2: - console: - enabled: true - jpa: - hibernate: - ddl-auto: create - show-sql: true - properties: - hibernate: - format_sql: true - default_batch_fetch_size: 100 - open-in-view: false - data: - storage-type: redis - redis: - host: localhost - port: 6379 - password: zinc - mail: - host: smtp.gmail.com - port: 587 - username: ljh19980823@gmail.com - password: yyzdbabwrmhhvyhi - properties: - mail: - smtp: - auth: true - starttls: - enable: true - required: true -jwt: - secret: 7ZmA656AIOuTneygkOyZlSDquLDsm5AgMeydvOywqALdlsKJL3234jklsdjfaKJDLnflkasdf -kakao: - client: - id: 08e6c709229f3b44a8cff2fc7168e1a2 - password: haaland09 - redirect: - uri: http://localhost:3000/auth/kakao/signin -logging: - level: - '[com.example.kakao]': DEBUG - '[org.hibernate.type]': TRACE profiles: active: - local From 2826b5875b4ba46648024adb71ef88b3ee56062e Mon Sep 17 00:00:00 2001 From: JunHee Date: Sat, 11 Nov 2023 15:32:06 +0900 Subject: [PATCH 139/144] =?UTF-8?q?Junhee=20=EB=A6=AC=EB=93=9C=EB=AF=B8=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=EB=81=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5838dc13..113d134e 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,8 @@ ## ERD +![image](https://github.com/Step3-kakao-tech-campus/Team8_BE/assets/80378041/d3e49985-9543-4e3e-9035-47fe2d4c234c) +
@@ -119,7 +121,10 @@
## Feature - +### 회원 탈퇴 +- 회원 탈퇴 시, 회원이 작성했던 글, 댓글, 작성내역 등의 정보를 유지합니다 +- 해당 정보를 유지하기 위해, 회원 탈퇴 시 회원과 관련된 groupMember에 외래키를 더미 회원을 만들어서 연결해줍니다. +- 탈퇴한 회원은 Database에서 사라지게 되며, 해당 회원이 작성했던 기록들에는 '알수없음'으로 표기됩니다.
From 0ed05318149d8929776110a3d56e3da6b90f207a Mon Sep 17 00:00:00 2001 From: INUK-ai <64780539+INUK-ai@users.noreply.github.com> Date: Sat, 11 Nov 2023 18:09:04 +0900 Subject: [PATCH 140/144] =?UTF-8?q?Refactor:=20ReadMe=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - INUK ReadMe 파일 수정 완료 --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/README.md b/README.md index 113d134e..90bffaf6 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,29 @@ - 해당 정보를 유지하기 위해, 회원 탈퇴 시 회원과 관련된 groupMember에 외래키를 더미 회원을 만들어서 연결해줍니다. - 탈퇴한 회원은 Database에서 사라지게 되며, 해당 회원이 작성했던 기록들에는 '알수없음'으로 표기됩니다. +### 그룹 생성 +- 신뢰성이 높은 그룹과 폐쇄성이 높은 그룹의 수요가 각각 존재할 것이라 생각해 총 3가지 그룹으로 분류하였습니다 + - 인증이 필요하여 신뢰성을 높인 공식 그룹 + - 공개적인 정보 공유 그룹인 비공식 공개 그룹 + - 폐쇄되어 정보를 공유하는 비공식 비공개 그룹 + +### 그룹 참가 +- 공식 그룹은 해당하는 인증 방식을 통해 가입 권한을 얻을 수 있습니다 +- 비공식 공개 그룹은 해당 그룹에 설정된 비밀번호를 맞추거나 초대 링크를 통해 가입 권한을 얻을 수 있습니다 +- 비공식 비공개 그룹은 초대 링크를 통한 접근으로 가입 권한을 얻을 수 있습니다. + - 초대 링크는 일정 기간 동안 해당 링크를 타고 들어오는 사용자들에게 가입 권한을 줍니다 + - Redis에 해당 key 값을 저장하고 일정 주기로 만료된 초대 링크를 찾아 Redis에서 삭제합니다 + +### 그룹 탈퇴 +- 그룹 탈퇴 시 해당 그룹에 남아있는 사람의 존재 여부를 확인한 후 그룹 탈퇴와 나아가 그룹 삭제까지 수행합니다 + - GroupMember가 남아있는 경우 : 그룹 탈퇴 + - 해당 그룹과 회원 사이의 그룹 멤버의 ActiveStatus를 False로 변경하는 것으로 + - 최대한 DB 접근 없이 그 GroupMember의 내역들을 유지하였습니다 + - 또한 재가입의 경우 해당 GroupMember의 ActiveStatus를 True로 변경하여 기존의 내역들을 열람 가능토록 하였습니다 + - GroupMember가 남아있지 않은 경우 : 그룹 삭제 + - 해당 그룹에 남아있는 모든 비활성 GroupMember, Page에 관해 삭제 후 Group 삭제를 진행하였습니다 + +
From 382b12142cad20bbc504cf9190d5c8ec0de3f391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=8F=84=EB=88=84?= Date: Sat, 11 Nov 2023 20:24:28 +0900 Subject: [PATCH 141/144] Update README.md --- README.md | 57 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 90bffaf6..7f479974 100644 --- a/README.md +++ b/README.md @@ -127,8 +127,8 @@ - 탈퇴한 회원은 Database에서 사라지게 되며, 해당 회원이 작성했던 기록들에는 '알수없음'으로 표기됩니다. ### 그룹 생성 -- 신뢰성이 높은 그룹과 폐쇄성이 높은 그룹의 수요가 각각 존재할 것이라 생각해 총 3가지 그룹으로 분류하였습니다 - - 인증이 필요하여 신뢰성을 높인 공식 그룹 +신뢰성이 높은 그룹과 폐쇄성이 높은 그룹의 수요가 각각 존재할 것이라 생각해 총 3가지 그룹으로 분류하였습니다 + - 인증이 필요하여 신뢰성을 높인 공식 그룹 (ex. 부산대학교 그룹) - 공개적인 정보 공유 그룹인 비공식 공개 그룹 - 폐쇄되어 정보를 공유하는 비공식 비공개 그룹 @@ -140,14 +140,59 @@ - Redis에 해당 key 값을 저장하고 일정 주기로 만료된 초대 링크를 찾아 Redis에서 삭제합니다 ### 그룹 탈퇴 -- 그룹 탈퇴 시 해당 그룹에 남아있는 사람의 존재 여부를 확인한 후 그룹 탈퇴와 나아가 그룹 삭제까지 수행합니다 +그룹 탈퇴 시 해당 그룹에 남아있는 사람의 존재 여부를 확인한 후 그룹 탈퇴와 나아가 그룹 삭제까지 수행합니다 - GroupMember가 남아있는 경우 : 그룹 탈퇴 - - 해당 그룹과 회원 사이의 그룹 멤버의 ActiveStatus를 False로 변경하는 것으로 - - 최대한 DB 접근 없이 그 GroupMember의 내역들을 유지하였습니다 - - 또한 재가입의 경우 해당 GroupMember의 ActiveStatus를 True로 변경하여 기존의 내역들을 열람 가능토록 하였습니다 + - 해당 그룹과 회원 사이의 그룹 멤버의 ActiveStatus를 False로 변경하는 것으로 최대한 DB 접근 없이 그 GroupMember의 내역들을 유지하였습니다 + - 또한 재가입의 경우 해당 GroupMember의 ActiveStatus를 True로 변경하여 기존의 내역들을 열람 가능하도록 하였습니다 - GroupMember가 남아있지 않은 경우 : 그룹 삭제 - 해당 그룹에 남아있는 모든 비활성 GroupMember, Page에 관해 삭제 후 Group 삭제를 진행하였습니다 +### 페이지와 글(Post) +위키키 서비스는 그룹원들끼리 사용할 수 있는 위키식 게시판을 제공하는 서비스입니다. +따라서 그룹 안에 여러 개의 페이지가 존재하며, 각 페이지 안에는 여러 개의 글들을 트리구조로 작성을 할 수 있습니다. + +- 페이지와 관련된 기능으로는 다음과 같습니다. + - 페이지 조회/생성/삭제 + - 페이지 좋아요/싫어요 + - 페이지 키워드 검색 + - 최근 바뀐 페이지 목차 조회 + - 페이지 링크 걸기 + +- 글과 관련된 기능으로는 다음과 같습니다. + - 글 작성/수정/삭제 + - 글 히스토리 조회 + - 댓글 조회/작성/수정/삭제 + - 글 신고 + +### 페이지 조회 +특정 페이지에 들어가면, 해당 페이지에 속한 모든 글들을 제공해줍니다. 글들이 트리구조로 이루어져 있으며, 각 글들에 해당하는 목차도 제공하고 있습니다. +글 생성시에 1.1과 1.2 사이에 글을 추가하게 되면 기존 1.2는 1.3으로 밀리며 새로운 1.2가 생기게 됩니다. 직접 DB에 각 글들에 대해 목차라는 칼럼을 생성하여 넣어주게 되면, 유연하게 목차를 생성하기가 어렵다고 판단하여 +글 생성시에 Index를 저장하는 방식이 아닌 조회시에 Index를 계산하여 응답해주는 방식으로 구현하였습니다. + +IndexUtils 라는 클래스를 하나 생성하여 @Component를 설정하여 컨테이너에 등록해주었습니다. 해당 클래스에 있는 HashMap createIndex(List posts) 메소드를 사용하여 트리 구조로 구성된 글들을 DFS를 통해 목차를 생성해줍니다. + +### 페이지 링크 걸기 +위키키 서비스에서 같은 그룹 내에 있는 페이지들 사이에 이동할 수 있는 링크를 설정할 수 있도록 설계하였습니다. 사용자에게 링크를 걸려고하는 페이지가 해당 그룹 내에 존재하는지 실시간으로 확인시켜줍니다. +글자의 변화를 실시간으로 감지하여 요청을 날리기 때문에 서버에 순간적으로 많은 요청이 오게 됩니다. 모든 요청마다 RDBMS를 접근을 하게 되면 부하가 너무 심할 것으로 예상하고 이 부분을 Redis를 활용하여 개선하였습니다. + +처음에는 redis에 string 자료구조를 사용하여 groupId_pageTitle을 key로 pageId값을 value로 해서 저장하였습니다. 1000개의 그룹이 존재하고, 각 그룹이 500개의 페이지를 차지하고 있을 때, redis의 메모리 사용량을 확인해보니 26.71MB를 차지하고 있었습니다. 해당 서비스에서 DB 부하를 줄이고 빠른 응답을 위해 Redis를 영구적인 저장공간으로 사용했기 때문에 최대한 메모리 사용량을 줄이기 위해 노력했습니다. + +Redis는 Key 값에 대해서 Overhead가 발생하기 때문에, Key의 갯수를 줄일 수 있다면 메모리사용량을 줄일 수 있을 것이라고 판단했습니다. Redis의 저장을 Hash 자료구조로 변경하여 groupId를 key로 하고 PageTitle을 HashKey로 pageId를 value으로 수정하였습니다. 1000개의 그룹이 존재하고, 각 그룹이 500개의 페이지를 차지하고 있을 때, redis의 메모리 사용량을 확인해보니 9.86MB 만큼 차지하고 있었습니다. + +즉, 약 250% 정도의 저장공간을 감소시킬 수 있었습니다. + +Hash 자료구조는 hashKey가 512개를 넘어가면 zip 자료구조에서 hashtable로 변경되기 때문에 하나의 그룹에 페이지가 512개를 넘어가게되면 메모리 사용량이 갑자기 증가하는 문제가 있었지만, 증가해도 String 자료구조로 저장했을 때와 메모리 사용량이 비슷하며, 그러한 그룹들이 많이 생기지 않을 것으로 예상하고 해당 방법을 채택하였습니다. + +### 페이지 키워드 검색 +페이지 키워드 검색시에는 해당 그룹내에서 키워드를 포함하고 있는 모든 페이지들을 페이지네이션으로 제공하였습니다. 또한 페이지 안에서 제일 위에 있는 글의 내용도 함께 보여주도록 구현을 하였습니다. + +구현을 하는 과정에서 페이지와 가장 상단에 있는 글들을 보여주기 위해 Fetch join과 Pagination을 동시에 사용하였는데, 밑에 글과 같은 경고 문구가 나타났습니다. fetch join 쿼리 결과를 전부 메모리에 적재한 뒤, Pagination 작업을 어플리케이션 레벨에서 처리한다는 경고였습니다. 추후에 글들이 많이 쌓이게 되었을 때, 성능상으로 치명적이라고 판단을 하고 이 부분을 2개의 쿼리를 통해 해결하였습니다. + +``` +HHH000104: firstResult/maxResults specified with collection fetch; applying in memory! +``` +먼저 DB로부터 그룹 내에 해당 키워드를 포함하는 페이지 10개를 받아오는 select 쿼리를 날렸습니다. 그리고 나서 해당 페이지ID를 PK로 가지고 있으며, 가장 상단에 있는(Order = 1)인 Post들을 IN연산자를 활용하여 +조회하는 쿼리를 날려서 해결하였습니다.
From 03cd416a6aca6dbcebf726a0f7ac5d9f44034ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=8F=84=EB=88=84?= Date: Sat, 11 Nov 2023 21:15:25 +0900 Subject: [PATCH 142/144] Update README.md --- README.md | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7f479974..ab58cf8b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Team8_BE 스크린샷 2023-11-11 오후 1 41 12 + + ## 프로젝트 소개
@@ -13,13 +15,31 @@ ||설명| |-----------|----| |제목 |위키키| -|개발 목적| 그룹별로 자신들만의 나무위키를 만들고, 기록하고자 하는 사람들을 위해 프로젝트를 만들었습니다. | -|개발 기간|2023.09 - 2023.11| +|개발 목적| 우리만의 추억을 함께 기록하고, 즐거운 순간을 공유하며 소중한 경험을 함께 만들어보세요! 위키키는 친구, 동료와 함께 다양한 활동을 기록하며 우리만의 특별한 공간을 만들 수 있는 그룹형 커뮤니티 서비스입니다. | +|개발 기간|2023.09.25 ~ 2023.11.11|
-## 팀원 +### 서비스 특징 + +1. 그룹 기반의 다양한 활동 기록 📝 + + 서로의 추억과 경험을 기록하고 페이지 별 목차를 통해 정보에 편리하게 접근하세요. + +2. 편리한 그룹원 초대 및 편집 권한 📨 + + 그룹을 손쉽게 생성하고 초대링크를 통해 친구나 동료를 초대하세요. 모든 그룹원에게 페이지 편집 권한이 있어 함께 만들어가는 즐거움을 누릴 수 있습니다. + +3. 비공개 그룹 옵션 🔐 + + 원하는 경우 비공개 그룹으로 설정하여 오직 그룹원끼리만 접근할 수 있도록 하세요. 우리만의 기록 공간을 안전하게 유지할 수 있습니다. + +위키키를 통해 함께 즐거운 순간을 기록하고 공유하는 새로운 경험을 만나보세요. 다양한 활동을 즐기며 소중한 추억을 함께 쌓아가는 여정을 시작해보세요! + +
+ +## 백엔드 팀 소개
| [이준희](https://github.com/Jun2-Lee) | [김돈우](https://github.com/kimdonwoo) | [황인욱](https://github.com/INUK-ai)| From e2e8050867031c3d93024fe240c417b31fa6ab4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=8F=84=EB=88=84?= Date: Sat, 11 Nov 2023 22:13:27 +0900 Subject: [PATCH 143/144] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 프로젝트 구조도 추가 --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ab58cf8b..5a6bd931 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ ||설명| |-----------|----| -|제목 |위키키| +|제목 |[위키키](https://kb70bd6b8a3f6a.user-app.krampoline.com)| |개발 목적| 우리만의 추억을 함께 기록하고, 즐거운 순간을 공유하며 소중한 경험을 함께 만들어보세요! 위키키는 친구, 동료와 함께 다양한 활동을 기록하며 우리만의 특별한 공간을 만들 수 있는 그룹형 커뮤니티 서비스입니다. | |개발 기간|2023.09.25 ~ 2023.11.11|
@@ -100,10 +100,13 @@ ## 프로젝트 구조도 +![구조도 drawio](https://github.com/Step3-kakao-tech-campus/Team8_BE/assets/81402944/11ef488b-8a20-4f41-8c59-53f4af16c38b) +
## 문서 + |문서 목록| |----| [GitHub (FE)](https://github.com/Step3-kakao-tech-campus/Team8_FE) From 5f761e5390b5b6f4f0c4795815eb2844afc49d3a Mon Sep 17 00:00:00 2001 From: INUK-ai <64780539+INUK-ai@users.noreply.github.com> Date: Sat, 11 Nov 2023 22:18:18 +0900 Subject: [PATCH 144/144] =?UTF-8?q?Docs:=20README.md=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 황인욱 마지막 README 수정 --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index ab58cf8b..5bdac4ea 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,7 @@ - 비공식 비공개 그룹은 초대 링크를 통한 접근으로 가입 권한을 얻을 수 있습니다. - 초대 링크는 일정 기간 동안 해당 링크를 타고 들어오는 사용자들에게 가입 권한을 줍니다 - Redis에 해당 key 값을 저장하고 일정 주기로 만료된 초대 링크를 찾아 Redis에서 삭제합니다 +- 가입 권한은 Redis에 해당 회원에게 권한을 얻은 groupId를 저장하여 확인하였습니다. ### 그룹 탈퇴 그룹 탈퇴 시 해당 그룹에 남아있는 사람의 존재 여부를 확인한 후 그룹 탈퇴와 나아가 그룹 삭제까지 수행합니다 @@ -214,6 +215,13 @@ HHH000104: firstResult/maxResults specified with collection fetch; applying in m 먼저 DB로부터 그룹 내에 해당 키워드를 포함하는 페이지 10개를 받아오는 select 쿼리를 날렸습니다. 그리고 나서 해당 페이지ID를 PK로 가지고 있으며, 가장 상단에 있는(Order = 1)인 Post들을 IN연산자를 활용하여 조회하는 쿼리를 날려서 해결하였습니다. +### 로깅 +- Logback을 사용하여 로그를 생성하였습니다 +- !Prod 환경 파일에서 실행될 경우 Console 창에 debug 레벨까지의 log를 생성하였습니다 +- Prod 환경 파일에서 실행될 경우 ./log 디렉토리 내부에 info, warn, error 레벨 로그 파일들을 각각 생성하여 저장하였습니다 + - 각 레벨의 로그 파일들은 maxFileSize 100MB, maxHisotry 30일, totalSizeCap은 3GB + - 로그 포맷은 [%d{yyyy-MM-dd HH:mm:ss}:%-4relative] [%thread] %-5level [%C.%M:%L] - %msg%n 로 설정하였습니다 +