From d0ca7bd9d0debca875489ac6f59ee90f82da4eaa Mon Sep 17 00:00:00 2001 From: guqing <38999863+guqing@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:19:49 +0800 Subject: [PATCH] feat: Add comment assembler for theme render (#1729) * feat: Add comment assembler for theme render * fix: code style * fix: page converter * refactor: clear sensitive field value --- .../content/api/JournalController.java | 30 ++-- .../content/api/PostController.java | 30 ++-- .../content/api/SheetController.java | 31 ++-- .../freemarker/tag/CommentTagDirective.java | 11 +- .../comment/BaseCommentAssembler.java | 140 ++++++++++++++++++ .../JournalCommentRenderAssembler.java | 85 +++++++++++ .../comment/PostCommentRenderAssembler.java | 91 ++++++++++++ .../comment/SheetCommentRenderAssembler.java | 93 ++++++++++++ .../app/service/base/BaseCommentService.java | 10 -- .../service/impl/BaseCommentServiceImpl.java | 65 +------- .../run/halo/app/it/PostCommentApiTest.java | 2 +- 11 files changed, 476 insertions(+), 112 deletions(-) create mode 100644 src/main/java/run/halo/app/service/assembler/comment/JournalCommentRenderAssembler.java create mode 100644 src/main/java/run/halo/app/service/assembler/comment/PostCommentRenderAssembler.java create mode 100644 src/main/java/run/halo/app/service/assembler/comment/SheetCommentRenderAssembler.java diff --git a/src/main/java/run/halo/app/controller/content/api/JournalController.java b/src/main/java/run/halo/app/controller/content/api/JournalController.java index a5fb3b689..cf4ee5a2f 100644 --- a/src/main/java/run/halo/app/controller/content/api/JournalController.java +++ b/src/main/java/run/halo/app/controller/content/api/JournalController.java @@ -34,7 +34,7 @@ import run.halo.app.model.vo.CommentWithHasChildrenVO; import run.halo.app.service.JournalCommentService; import run.halo.app.service.JournalService; import run.halo.app.service.OptionService; -import run.halo.app.service.assembler.comment.JournalCommentAssembler; +import run.halo.app.service.assembler.comment.JournalCommentRenderAssembler; /** * Content journal controller. @@ -49,18 +49,18 @@ public class JournalController { private final JournalService journalService; - private final JournalCommentAssembler journalCommentAssembler; + private final JournalCommentRenderAssembler journalCommentRenderAssembler; private final JournalCommentService journalCommentService; private final OptionService optionService; public JournalController(JournalService journalService, - JournalCommentAssembler journalCommentAssembler, + JournalCommentRenderAssembler journalCommentRenderAssembler, JournalCommentService journalCommentService, OptionService optionService) { this.journalService = journalService; - this.journalCommentAssembler = journalCommentAssembler; + this.journalCommentRenderAssembler = journalCommentRenderAssembler; this.journalCommentService = journalCommentService; this.optionService = optionService; } @@ -85,8 +85,11 @@ public class JournalController { @PathVariable("journalId") Integer journalId, @RequestParam(name = "page", required = false, defaultValue = "0") int page, @SortDefault(sort = "createTime", direction = DESC) Sort sort) { - return journalCommentService.pageTopCommentsBy(journalId, CommentStatus.PUBLISHED, - PageRequest.of(page, optionService.getCommentPageSize(), sort)); + Page comments = + journalCommentService.pageTopCommentsBy(journalId, CommentStatus.PUBLISHED, + PageRequest.of(page, optionService.getCommentPageSize(), sort)); + comments.forEach(journalCommentRenderAssembler::clearSensitiveField); + return comments; } @GetMapping("{journalId:\\d+}/comments/{commentParentId:\\d+}/children") @@ -97,7 +100,7 @@ public class JournalController { List postComments = journalCommentService .listChildrenBy(journalId, commentParentId, CommentStatus.PUBLISHED, sort); // Convert to base comment dto - return journalCommentAssembler.convertTo(postComments); + return journalCommentRenderAssembler.convertTo(postComments); } @GetMapping("{journalId:\\d+}/comments/tree_view") @@ -105,8 +108,10 @@ public class JournalController { public Page listCommentsTree(@PathVariable("journalId") Integer journalId, @RequestParam(name = "page", required = false, defaultValue = "0") int page, @SortDefault(sort = "createTime", direction = DESC) Sort sort) { - return journalCommentService + Page comments = journalCommentService .pageVosBy(journalId, PageRequest.of(page, optionService.getCommentPageSize(), sort)); + comments.getContent().forEach(journalCommentRenderAssembler::clearSensitiveField); + return comments; } @GetMapping("{journalId:\\d+}/comments/list_view") @@ -114,8 +119,11 @@ public class JournalController { public Page listComments(@PathVariable("journalId") Integer journalId, @RequestParam(name = "page", required = false, defaultValue = "0") int page, @SortDefault(sort = "createTime", direction = DESC) Sort sort) { - return journalCommentService.pageWithParentVoBy(journalId, - PageRequest.of(page, optionService.getCommentPageSize(), sort)); + Page comments = + journalCommentService.pageWithParentVoBy(journalId, + PageRequest.of(page, optionService.getCommentPageSize(), sort)); + comments.getContent().forEach(journalCommentRenderAssembler::clearSensitiveField); + return comments; } @PostMapping("comments") @@ -126,7 +134,7 @@ public class JournalController { // Escape content journalCommentParam.setContent(HtmlUtils .htmlEscape(journalCommentParam.getContent(), StandardCharsets.UTF_8.displayName())); - return journalCommentAssembler.convertTo( + return journalCommentRenderAssembler.convertTo( journalCommentService.createBy(journalCommentParam)); } diff --git a/src/main/java/run/halo/app/controller/content/api/PostController.java b/src/main/java/run/halo/app/controller/content/api/PostController.java index a23708c9b..330a3c405 100644 --- a/src/main/java/run/halo/app/controller/content/api/PostController.java +++ b/src/main/java/run/halo/app/controller/content/api/PostController.java @@ -42,7 +42,7 @@ import run.halo.app.service.OptionService; import run.halo.app.service.PostCommentService; import run.halo.app.service.PostService; import run.halo.app.service.assembler.PostRenderAssembler; -import run.halo.app.service.assembler.comment.PostCommentAssembler; +import run.halo.app.service.assembler.comment.PostCommentRenderAssembler; /** * Content post controller. @@ -58,7 +58,7 @@ public class PostController { private final PostService postService; - private final PostCommentAssembler postCommentAssembler; + private final PostCommentRenderAssembler postCommentRenderAssembler; private final PostCommentService postCommentService; @@ -69,12 +69,12 @@ public class PostController { private final PostAuthentication postAuthentication; public PostController(PostService postService, - PostCommentAssembler postCommentAssembler, + PostCommentRenderAssembler postCommentRenderAssembler, PostCommentService postCommentService, OptionService optionService, PostRenderAssembler postRenderAssembler, PostAuthentication postAuthentication) { this.postService = postService; - this.postCommentAssembler = postCommentAssembler; + this.postCommentRenderAssembler = postCommentRenderAssembler; this.postCommentService = postCommentService; this.optionService = optionService; this.postRenderAssembler = postRenderAssembler; @@ -194,8 +194,11 @@ public class PostController { @RequestParam(name = "page", required = false, defaultValue = "0") int page, @SortDefault(sort = "createTime", direction = DESC) Sort sort) { checkAuthenticate(postId); - return postCommentService.pageTopCommentsBy(postId, CommentStatus.PUBLISHED, - PageRequest.of(page, optionService.getCommentPageSize(), sort)); + Page comments = + postCommentService.pageTopCommentsBy(postId, CommentStatus.PUBLISHED, + PageRequest.of(page, optionService.getCommentPageSize(), sort)); + comments.getContent().forEach(postCommentRenderAssembler::clearSensitiveField); + return comments; } @GetMapping("{postId:\\d+}/comments/{commentParentId:\\d+}/children") @@ -208,7 +211,7 @@ public class PostController { .listChildrenBy(postId, commentParentId, CommentStatus.PUBLISHED, sort); // Convert to base comment dto - return postCommentAssembler.convertTo(postComments); + return postCommentRenderAssembler.convertTo(postComments); } @GetMapping("{postId:\\d+}/comments/tree_view") @@ -217,8 +220,10 @@ public class PostController { @RequestParam(name = "page", required = false, defaultValue = "0") int page, @SortDefault(sort = "createTime", direction = DESC) Sort sort) { checkAuthenticate(postId); - return postCommentService + Page comments = postCommentService .pageVosBy(postId, PageRequest.of(page, optionService.getCommentPageSize(), sort)); + comments.getContent().forEach(postCommentRenderAssembler::clearSensitiveField); + return comments; } @GetMapping("{postId:\\d+}/comments/list_view") @@ -227,8 +232,11 @@ public class PostController { @RequestParam(name = "page", required = false, defaultValue = "0") int page, @SortDefault(sort = "createTime", direction = DESC) Sort sort) { checkAuthenticate(postId); - return postCommentService.pageWithParentVoBy(postId, - PageRequest.of(page, optionService.getCommentPageSize(), sort)); + Page comments = + postCommentService.pageWithParentVoBy(postId, + PageRequest.of(page, optionService.getCommentPageSize(), sort)); + comments.getContent().forEach(postCommentRenderAssembler::clearSensitiveField); + return comments; } @PostMapping("comments") @@ -241,7 +249,7 @@ public class PostController { // Escape content postCommentParam.setContent(HtmlUtils .htmlEscape(postCommentParam.getContent(), StandardCharsets.UTF_8.displayName())); - return postCommentAssembler.convertTo(postCommentService.createBy(postCommentParam)); + return postCommentRenderAssembler.convertTo(postCommentService.createBy(postCommentParam)); } @PostMapping("{postId:\\d+}/likes") diff --git a/src/main/java/run/halo/app/controller/content/api/SheetController.java b/src/main/java/run/halo/app/controller/content/api/SheetController.java index b93a56e41..bc136d1e8 100644 --- a/src/main/java/run/halo/app/controller/content/api/SheetController.java +++ b/src/main/java/run/halo/app/controller/content/api/SheetController.java @@ -35,7 +35,7 @@ import run.halo.app.service.OptionService; import run.halo.app.service.SheetCommentService; import run.halo.app.service.SheetService; import run.halo.app.service.assembler.SheetRenderAssembler; -import run.halo.app.service.assembler.comment.SheetCommentAssembler; +import run.halo.app.service.assembler.comment.SheetCommentRenderAssembler; /** * Content sheet controller. @@ -48,7 +48,7 @@ import run.halo.app.service.assembler.comment.SheetCommentAssembler; @RequestMapping("/api/content/sheets") public class SheetController { - private final SheetCommentAssembler sheetCommentAssembler; + private final SheetCommentRenderAssembler sheetCommentRenderAssembler; private final SheetService sheetService; @@ -59,12 +59,12 @@ public class SheetController { private final OptionService optionService; public SheetController( - SheetCommentAssembler sheetCommentAssembler, + SheetCommentRenderAssembler sheetCommentRenderAssembler, SheetService sheetService, SheetRenderAssembler sheetRenderAssembler, SheetCommentService sheetCommentService, OptionService optionService) { - this.sheetCommentAssembler = sheetCommentAssembler; + this.sheetCommentRenderAssembler = sheetCommentRenderAssembler; this.sheetService = sheetService; this.sheetRenderAssembler = sheetRenderAssembler; this.sheetCommentService = sheetCommentService; @@ -134,8 +134,11 @@ public class SheetController { public Page listTopComments(@PathVariable("sheetId") Integer sheetId, @RequestParam(name = "page", required = false, defaultValue = "0") int page, @SortDefault(sort = "createTime", direction = DESC) Sort sort) { - return sheetCommentService.pageTopCommentsBy(sheetId, CommentStatus.PUBLISHED, - PageRequest.of(page, optionService.getCommentPageSize(), sort)); + Page comments = + sheetCommentService.pageTopCommentsBy(sheetId, CommentStatus.PUBLISHED, + PageRequest.of(page, optionService.getCommentPageSize(), sort)); + comments.forEach(sheetCommentRenderAssembler::clearSensitiveField); + return comments; } @GetMapping("{sheetId:\\d+}/comments/{commentParentId:\\d+}/children") @@ -146,7 +149,7 @@ public class SheetController { List sheetComments = sheetCommentService .listChildrenBy(sheetId, commentParentId, CommentStatus.PUBLISHED, sort); // Convert to base comment dto - return sheetCommentAssembler.convertTo(sheetComments); + return sheetCommentRenderAssembler.convertTo(sheetComments); } @@ -155,8 +158,10 @@ public class SheetController { public Page listCommentsTree(@PathVariable("sheetId") Integer sheetId, @RequestParam(name = "page", required = false, defaultValue = "0") int page, @SortDefault(sort = "createTime", direction = DESC) Sort sort) { - return sheetCommentService + Page comments = sheetCommentService .pageVosBy(sheetId, PageRequest.of(page, optionService.getCommentPageSize(), sort)); + comments.getContent().forEach(sheetCommentRenderAssembler::clearSensitiveField); + return comments; } @GetMapping("{sheetId:\\d+}/comments/list_view") @@ -164,8 +169,11 @@ public class SheetController { public Page listComments(@PathVariable("sheetId") Integer sheetId, @RequestParam(name = "page", required = false, defaultValue = "0") int page, @SortDefault(sort = "createTime", direction = DESC) Sort sort) { - return sheetCommentService.pageWithParentVoBy(sheetId, - PageRequest.of(page, optionService.getCommentPageSize(), sort)); + Page comments = + sheetCommentService.pageWithParentVoBy(sheetId, + PageRequest.of(page, optionService.getCommentPageSize(), sort)); + comments.getContent().forEach(sheetCommentRenderAssembler::clearSensitiveField); + return comments; } @PostMapping("comments") @@ -176,6 +184,7 @@ public class SheetController { // Escape content sheetCommentParam.setContent(HtmlUtils .htmlEscape(sheetCommentParam.getContent(), StandardCharsets.UTF_8.displayName())); - return sheetCommentAssembler.convertTo(sheetCommentService.createBy(sheetCommentParam)); + return sheetCommentRenderAssembler.convertTo( + sheetCommentService.createBy(sheetCommentParam)); } } diff --git a/src/main/java/run/halo/app/core/freemarker/tag/CommentTagDirective.java b/src/main/java/run/halo/app/core/freemarker/tag/CommentTagDirective.java index 5dfa36ffc..55e97ec3b 100644 --- a/src/main/java/run/halo/app/core/freemarker/tag/CommentTagDirective.java +++ b/src/main/java/run/halo/app/core/freemarker/tag/CommentTagDirective.java @@ -15,12 +15,13 @@ import run.halo.app.model.entity.PostComment; import run.halo.app.model.enums.CommentStatus; import run.halo.app.model.support.HaloConst; import run.halo.app.service.PostCommentService; -import run.halo.app.service.assembler.comment.PostCommentAssembler; +import run.halo.app.service.assembler.comment.PostCommentRenderAssembler; /** * Freemarker custom tag of comment. * * @author ryanwang + * @author guqing * @date 2019-03-22 */ @Component @@ -28,12 +29,12 @@ public class CommentTagDirective implements TemplateDirectiveModel { private final PostCommentService postCommentService; - private final PostCommentAssembler postCommentAssembler; + private final PostCommentRenderAssembler postCommentRenderAssembler; public CommentTagDirective(Configuration configuration, PostCommentService postCommentService, - PostCommentAssembler postCommentAssembler) { + PostCommentRenderAssembler postCommentRenderAssembler) { this.postCommentService = postCommentService; - this.postCommentAssembler = postCommentAssembler; + this.postCommentRenderAssembler = postCommentRenderAssembler; configuration.setSharedVariable("commentTag", this); } @@ -52,7 +53,7 @@ public class CommentTagDirective implements TemplateDirectiveModel { postCommentService.pageLatest(top, CommentStatus.PUBLISHED); env.setVariable("comments", builder.build() - .wrap(postCommentAssembler.convertToWithPostVo(postComments))); + .wrap(postCommentRenderAssembler.convertToWithPostVo(postComments))); break; case "count": env.setVariable("count", builder.build().wrap(postCommentService.count())); diff --git a/src/main/java/run/halo/app/service/assembler/comment/BaseCommentAssembler.java b/src/main/java/run/halo/app/service/assembler/comment/BaseCommentAssembler.java index 1ae79fa27..5bee87d02 100644 --- a/src/main/java/run/halo/app/service/assembler/comment/BaseCommentAssembler.java +++ b/src/main/java/run/halo/app/service/assembler/comment/BaseCommentAssembler.java @@ -1,13 +1,18 @@ package run.halo.app.service.assembler.comment; +import java.util.ArrayDeque; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; import java.util.List; import java.util.Objects; +import java.util.Queue; import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -15,7 +20,9 @@ import org.springframework.util.CollectionUtils; import run.halo.app.model.dto.BaseCommentDTO; import run.halo.app.model.entity.BaseComment; import run.halo.app.model.properties.CommentProperties; +import run.halo.app.model.support.CommentPage; import run.halo.app.model.vo.BaseCommentVO; +import run.halo.app.model.vo.BaseCommentWithParentVO; import run.halo.app.service.OptionService; /** @@ -24,6 +31,7 @@ import run.halo.app.service.OptionService; * @author guqing * @date 2022-03-08 */ +@Slf4j public abstract class BaseCommentAssembler { private final OptionService optionService; @@ -102,6 +110,47 @@ public abstract class BaseCommentAssembler { return topVirtualComment.getChildren(); } + /** + * Lists comment vos by list of COMMENT. + * + * @param comments comments must not be null + * @param pageable page info must not be null + * @return a page of comment vo + */ + @NonNull + public Page pageVosBy(@NonNull List comments, + @NonNull Pageable pageable) { + Assert.notNull(comments, "Comments must not be null"); + Assert.notNull(pageable, "Page info must not be null"); + + Comparator commentComparator = + buildCommentComparator(pageable.getSortOr(Sort.by(Sort.Direction.DESC, "createTime"))); + + // Convert to vo + List topComments = convertToVo(comments, commentComparator); + + List pageContent; + + // Calc the shear index + int startIndex = pageable.getPageNumber() * pageable.getPageSize(); + if (startIndex >= topComments.size() || startIndex < 0) { + pageContent = Collections.emptyList(); + } else { + int endIndex = startIndex + pageable.getPageSize(); + if (endIndex > topComments.size()) { + endIndex = topComments.size(); + } + + log.debug("Top comments size: [{}]", topComments.size()); + log.debug("Start index: [{}]", startIndex); + log.debug("End index: [{}]", endIndex); + + pageContent = topComments.subList(startIndex, endIndex); + } + + return new CommentPage<>(pageContent, pageable, topComments.size(), comments.size()); + } + /** * Concretes comment tree. * @@ -165,4 +214,95 @@ public abstract class BaseCommentAssembler { return gravatarSource + gravatarMd5 + "?s=256&d=" + gravatarDefault; } + + /** + * Builds a comment comparator. + * + * @param sort sort info + * @return comment comparator + */ + protected Comparator buildCommentComparator(Sort sort) { + return (currentComment, toCompareComment) -> { + Assert.notNull(currentComment, "Current comment must not be null"); + Assert.notNull(toCompareComment, "Comment to compare must not be null"); + + // Get sort order + Sort.Order order = sort.filter(anOrder -> "id".equals(anOrder.getProperty())) + .get() + .findFirst() + .orElseGet(() -> Sort.Order.desc("id")); + + // Init sign + int sign = order.getDirection().isAscending() ? 1 : -1; + + // Compare id property + return sign * currentComment.getId().compareTo(toCompareComment.getId()); + }; + } + + /** + * clear sensitive field value for theme render. + * + * @param comment comment + */ + public void clearSensitiveField(@Nullable COMMENT comment) { + if (comment == null) { + return; + } + comment.setIpAddress(null); + comment.setEmail(null); + } + + /** + * clear sensitive field value for theme render. + * + * @param comment comment tree + */ + public void clearSensitiveField(@Nullable BaseCommentDTO comment) { + if (comment == null) { + return; + } + comment.setIpAddress(null); + comment.setEmail(null); + } + + /** + * clear sensitive field value for theme render. + * + * @param commentTree comment tree + */ + public void clearSensitiveField(@Nullable BaseCommentVO commentTree) { + if (commentTree == null) { + return; + } + Queue queue = new ArrayDeque<>(); + queue.add(commentTree); + while (!queue.isEmpty()) { + BaseCommentVO comment = queue.poll(); + comment.setIpAddress(null); + comment.setEmail(null); + + if (!CollectionUtils.isEmpty(comment.getChildren())) { + queue.addAll(comment.getChildren()); + } + } + } + + /** + * clear sensitive field value for theme render. + * + * @param comment comment + */ + public void clearSensitiveField(@Nullable BaseCommentWithParentVO comment) { + if (comment == null) { + return; + } + BaseCommentWithParentVO parent = comment.getParent(); + if (parent != null) { + parent.setIpAddress(null); + parent.setEmail(null); + } + comment.setIpAddress(null); + comment.setEmail(null); + } } diff --git a/src/main/java/run/halo/app/service/assembler/comment/JournalCommentRenderAssembler.java b/src/main/java/run/halo/app/service/assembler/comment/JournalCommentRenderAssembler.java new file mode 100644 index 000000000..63e27a299 --- /dev/null +++ b/src/main/java/run/halo/app/service/assembler/comment/JournalCommentRenderAssembler.java @@ -0,0 +1,85 @@ +package run.halo.app.service.assembler.comment; + +import java.util.Comparator; +import java.util.List; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import run.halo.app.model.dto.BaseCommentDTO; +import run.halo.app.model.entity.JournalComment; +import run.halo.app.model.vo.BaseCommentVO; +import run.halo.app.model.vo.JournalCommentWithJournalVO; +import run.halo.app.repository.JournalRepository; +import run.halo.app.service.OptionService; + +/** + * Journal comment assembler for theme render. + * + * @author guqing + * @date 2022-03-09 + */ +@Component +public class JournalCommentRenderAssembler extends JournalCommentAssembler { + public JournalCommentRenderAssembler(OptionService optionService, + JournalRepository journalRepository) { + super(optionService, journalRepository); + } + + @NonNull + @Override + public BaseCommentDTO convertTo(@NonNull JournalComment comment) { + clearSensitiveField(comment); + return super.convertTo(comment); + } + + @NonNull + @Override + public List convertTo(List journalComments) { + journalComments.forEach(this::clearSensitiveField); + return super.convertTo(journalComments); + } + + @NonNull + @Override + public Page convertTo(Page journalComments) { + journalComments.getContent().forEach(this::clearSensitiveField); + return super.convertTo(journalComments); + } + + @Override + public List convertToVo(List journalComments, + Comparator comparator) { + if (!CollectionUtils.isEmpty(journalComments)) { + journalComments.forEach(this::clearSensitiveField); + } + return super.convertToVo(journalComments, comparator); + } + + @NonNull + @Override + public List convertToWithJournalVo( + List journalComments) { + if (!CollectionUtils.isEmpty(journalComments)) { + journalComments.forEach(this::clearSensitiveField); + } + return super.convertToWithJournalVo(journalComments); + } + + @NonNull + @Override + public Page convertToWithJournalVo( + @NonNull Page journalCommentPage) { + journalCommentPage.getContent().forEach(this::clearSensitiveField); + return super.convertToWithJournalVo(journalCommentPage); + } + + @NonNull + @Override + public Page pageVosBy(@NonNull List journalComments, + @NonNull Pageable pageable) { + journalComments.forEach(this::clearSensitiveField); + return super.pageVosBy(journalComments, pageable); + } +} diff --git a/src/main/java/run/halo/app/service/assembler/comment/PostCommentRenderAssembler.java b/src/main/java/run/halo/app/service/assembler/comment/PostCommentRenderAssembler.java new file mode 100644 index 000000000..0ec46f170 --- /dev/null +++ b/src/main/java/run/halo/app/service/assembler/comment/PostCommentRenderAssembler.java @@ -0,0 +1,91 @@ +package run.halo.app.service.assembler.comment; + +import java.util.Comparator; +import java.util.List; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import run.halo.app.model.dto.BaseCommentDTO; +import run.halo.app.model.entity.PostComment; +import run.halo.app.model.vo.BaseCommentVO; +import run.halo.app.model.vo.PostCommentWithPostVO; +import run.halo.app.repository.PostRepository; +import run.halo.app.service.OptionService; + +/** + * Post comment assembler for theme render. + * + * @author guqing + * @date 2022-03-09 + */ +@Component +public class PostCommentRenderAssembler extends PostCommentAssembler { + + public PostCommentRenderAssembler(OptionService optionService, + PostRepository postRepository) { + super(optionService, postRepository); + } + + @NonNull + @Override + public BaseCommentDTO convertTo(@NonNull PostComment comment) { + clearSensitiveField(comment); + return super.convertTo(comment); + } + + @NonNull + @Override + public List convertTo(@NonNull List postComments) { + postComments.forEach(this::clearSensitiveField); + return super.convertTo(postComments); + } + + @NonNull + @Override + public Page convertTo(@NonNull Page postComments) { + postComments.forEach(this::clearSensitiveField); + return super.convertTo(postComments); + } + + @Override + public List convertToVo(List postComments, + Comparator comparator) { + if (!CollectionUtils.isEmpty(postComments)) { + postComments.forEach(this::clearSensitiveField); + } + return super.convertToVo(postComments, comparator); + } + + @NonNull + @Override + public Page convertToWithPostVo(@NonNull Page commentPage) { + commentPage.getContent().forEach(this::clearSensitiveField); + return super.convertToWithPostVo(commentPage); + } + + @NonNull + @Override + public PostCommentWithPostVO convertToWithPostVo(@NonNull PostComment comment) { + this.clearSensitiveField(comment); + return super.convertToWithPostVo(comment); + } + + @NonNull + @Override + public List convertToWithPostVo(List postComments) { + if (!CollectionUtils.isEmpty(postComments)) { + postComments.forEach(this::clearSensitiveField); + } + return super.convertToWithPostVo(postComments); + } + + @NonNull + @Override + public Page pageVosBy(@NonNull List postComments, + @NonNull Pageable pageable) { + postComments.forEach(this::clearSensitiveField); + return super.pageVosBy(postComments, pageable); + } +} diff --git a/src/main/java/run/halo/app/service/assembler/comment/SheetCommentRenderAssembler.java b/src/main/java/run/halo/app/service/assembler/comment/SheetCommentRenderAssembler.java new file mode 100644 index 000000000..6b5cb7a06 --- /dev/null +++ b/src/main/java/run/halo/app/service/assembler/comment/SheetCommentRenderAssembler.java @@ -0,0 +1,93 @@ +package run.halo.app.service.assembler.comment; + +import java.util.Comparator; +import java.util.List; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import run.halo.app.model.dto.BaseCommentDTO; +import run.halo.app.model.entity.SheetComment; +import run.halo.app.model.vo.BaseCommentVO; +import run.halo.app.model.vo.SheetCommentWithSheetVO; +import run.halo.app.repository.SheetRepository; +import run.halo.app.service.OptionService; + +/** + * Sheet comment assembler for theme render. + * + * @author guqing + * @date 2022-03-09 + */ +@Component +public class SheetCommentRenderAssembler extends SheetCommentAssembler { + + public SheetCommentRenderAssembler(OptionService optionService, + SheetRepository sheetRepository) { + super(optionService, sheetRepository); + } + + @NonNull + @Override + public BaseCommentDTO convertTo(@NonNull SheetComment comment) { + clearSensitiveField(comment); + return super.convertTo(comment); + } + + @NonNull + @Override + public List convertTo(@NonNull List sheetComments) { + sheetComments.forEach(this::clearSensitiveField); + return super.convertTo(sheetComments); + } + + @NonNull + @Override + public Page convertTo(@NonNull Page sheetComments) { + sheetComments.getContent().forEach(this::clearSensitiveField); + return super.convertTo(sheetComments); + } + + @Override + public List convertToVo(List sheetComments, + Comparator comparator) { + if (!CollectionUtils.isEmpty(sheetComments)) { + sheetComments.forEach(this::clearSensitiveField); + } + return super.convertToVo(sheetComments, comparator); + } + + @NonNull + @Override + public SheetCommentWithSheetVO convertToWithSheetVo(@NonNull SheetComment comment) { + clearSensitiveField(comment); + return super.convertToWithSheetVo(comment); + } + + @NonNull + @Override + public List convertToWithSheetVo( + List sheetComments) { + if (!CollectionUtils.isEmpty(sheetComments)) { + sheetComments.forEach(this::clearSensitiveField); + } + return super.convertToWithSheetVo(sheetComments); + } + + @NonNull + @Override + public Page convertToWithSheetVo( + @NonNull Page sheetCommentPage) { + sheetCommentPage.getContent().forEach(this::clearSensitiveField); + return super.convertToWithSheetVo(sheetCommentPage); + } + + @NonNull + @Override + public Page pageVosBy(@NonNull List sheetComments, + @NonNull Pageable pageable) { + sheetComments.forEach(this::clearSensitiveField); + return super.pageVosBy(sheetComments, pageable); + } +} diff --git a/src/main/java/run/halo/app/service/base/BaseCommentService.java b/src/main/java/run/halo/app/service/base/BaseCommentService.java index 957c56c85..7ab042893 100644 --- a/src/main/java/run/halo/app/service/base/BaseCommentService.java +++ b/src/main/java/run/halo/app/service/base/BaseCommentService.java @@ -94,16 +94,6 @@ public interface BaseCommentService @NonNull Page pageVosBy(@NonNull Integer postId, @NonNull Pageable pageable); - /** - * Lists comment vos by list of COMMENT. - * - * @param comments comments must not be null - * @param pageable page info must not be null - * @return a page of comment vo - */ - @NonNull - Page pageVosBy(@NonNull List comments, @NonNull Pageable pageable); - /** * Lists comment with parent vo. * diff --git a/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java b/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java index f3d3424b0..315585434 100644 --- a/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java @@ -42,7 +42,6 @@ import run.halo.app.model.projection.CommentChildrenCountProjection; import run.halo.app.model.projection.CommentCountProjection; import run.halo.app.model.properties.BlogProperties; import run.halo.app.model.properties.CommentProperties; -import run.halo.app.model.support.CommentPage; import run.halo.app.model.vo.BaseCommentVO; import run.halo.app.model.vo.BaseCommentWithParentVO; import run.halo.app.model.vo.CommentWithHasChildrenVO; @@ -142,42 +141,7 @@ public abstract class BaseCommentServiceImpl // List all the top comments (Caution: This list will be cleared) List comments = baseCommentRepository.findAllByPostId(postId); - return pageVosBy(comments, pageable); - } - - @Override - @NonNull - public Page pageVosBy(@NonNull List comments, - @NonNull Pageable pageable) { - Assert.notNull(comments, "Comments must not be null"); - Assert.notNull(pageable, "Page info must not be null"); - - Comparator commentComparator = - buildCommentComparator(pageable.getSortOr(Sort.by(Sort.Direction.DESC, "createTime"))); - - // Convert to vo - List topComments = commentAssembler.convertToVo(comments, commentComparator); - - List pageContent; - - // Calc the shear index - int startIndex = pageable.getPageNumber() * pageable.getPageSize(); - if (startIndex >= topComments.size() || startIndex < 0) { - pageContent = Collections.emptyList(); - } else { - int endIndex = startIndex + pageable.getPageSize(); - if (endIndex > topComments.size()) { - endIndex = topComments.size(); - } - - log.debug("Top comments size: [{}]", topComments.size()); - log.debug("Start index: [{}]", startIndex); - log.debug("End index: [{}]", endIndex); - - pageContent = topComments.subList(startIndex, endIndex); - } - - return new CommentPage<>(pageContent, pageable, topComments.size(), comments.size()); + return commentAssembler.pageVosBy(comments, pageable); } @Override @@ -192,7 +156,7 @@ public abstract class BaseCommentServiceImpl List comments = baseCommentRepository.findAllByPostIdAndStatus(postId, CommentStatus.PUBLISHED); - return pageVosBy(comments, pageable); + return commentAssembler.pageVosBy(comments, pageable); } @Override @@ -501,31 +465,6 @@ public abstract class BaseCommentServiceImpl }; } - /** - * Builds a comment comparator. - * - * @param sort sort info - * @return comment comparator - */ - protected Comparator buildCommentComparator(Sort sort) { - return (currentComment, toCompareComment) -> { - Assert.notNull(currentComment, "Current comment must not be null"); - Assert.notNull(toCompareComment, "Comment to compare must not be null"); - - // Get sort order - Sort.Order order = sort.filter(anOrder -> "id".equals(anOrder.getProperty())) - .get() - .findFirst() - .orElseGet(() -> Sort.Order.desc("id")); - - // Init sign - int sign = order.getDirection().isAscending() ? 1 : -1; - - // Compare id property - return sign * currentComment.getId().compareTo(toCompareComment.getId()); - }; - } - @Override @NonNull public Page pageTopCommentsBy(@NonNull Integer targetId, diff --git a/src/test/java/run/halo/app/it/PostCommentApiTest.java b/src/test/java/run/halo/app/it/PostCommentApiTest.java index cfb350a32..534ec52e5 100644 --- a/src/test/java/run/halo/app/it/PostCommentApiTest.java +++ b/src/test/java/run/halo/app/it/PostCommentApiTest.java @@ -112,6 +112,6 @@ public class PostCommentApiTest extends BaseApiTest { Assertions.assertEquals(HttpStatus.OK, result.getStatusCode()); Assertions.assertEquals(COMMENT_AUTHOR_TEST, comment.getAuthor()); Assertions.assertEquals(COMMENT_CONTENT_TEST, comment.getContent()); - Assertions.assertEquals(COMMENT_VALID_EMAIL_TEST, comment.getEmail()); + Assertions.assertNull(comment.getEmail()); } }