Refactor comment creation

pull/146/head
johnniang 2019-04-24 11:04:02 +08:00
parent 85ba526a1d
commit 1c9f561f22
7 changed files with 92 additions and 125 deletions

View File

@ -1,5 +1,6 @@
package run.halo.app.model.params; package run.halo.app.model.params;
import org.hibernate.validator.constraints.URL;
import run.halo.app.model.dto.base.InputConverter; import run.halo.app.model.dto.base.InputConverter;
import run.halo.app.model.entity.Comment; import run.halo.app.model.entity.Comment;
import lombok.Data; import lombok.Data;

View File

@ -1,18 +1,18 @@
package run.halo.app.service; package run.halo.app.service;
import run.halo.app.model.entity.Comment;
import run.halo.app.model.enums.CommentStatus;
import run.halo.app.model.params.CommentQuery;
import run.halo.app.model.vo.CommentWithParentVO;
import run.halo.app.model.vo.CommentWithPostVO;
import run.halo.app.model.vo.CommentVO;
import run.halo.app.service.base.CrudService;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import run.halo.app.model.entity.Comment;
import run.halo.app.model.enums.CommentStatus;
import run.halo.app.model.params.CommentParam;
import run.halo.app.model.params.CommentQuery;
import run.halo.app.model.vo.CommentVO;
import run.halo.app.model.vo.CommentWithParentVO;
import run.halo.app.model.vo.CommentWithPostVO;
import run.halo.app.service.base.CrudService;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -54,7 +54,7 @@ public interface CommentService extends CrudService<Comment, Long> {
* Pages comments. * Pages comments.
* *
* @param commentQuery comment query must not be null * @param commentQuery comment query must not be null
* @param pageable page info must not be null * @param pageable page info must not be null
* @return a page of comment * @return a page of comment
*/ */
@NonNull @NonNull
@ -81,12 +81,11 @@ public interface CommentService extends CrudService<Comment, Long> {
/** /**
* Creates a comment by comment param. * Creates a comment by comment param.
* *
* @param comment comment must not be null * @param commentParam comment param must not be null
* @param request http servlet request must not be null
* @return created comment * @return created comment
*/ */
@NonNull @NonNull
Comment createBy(@NonNull Comment comment, @NonNull HttpServletRequest request); Comment createBy(@NonNull CommentParam commentParam);
/** /**
* Lists comment vos by post id. * Lists comment vos by post id.

View File

@ -1,9 +1,7 @@
package run.halo.app.service.impl; package run.halo.app.service.impl;
import cn.hutool.core.util.URLUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.servlet.ServletUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.*; import org.springframework.data.domain.*;
@ -19,12 +17,16 @@ import org.springframework.web.util.HtmlUtils;
import run.halo.app.event.comment.CommentNewEvent; import run.halo.app.event.comment.CommentNewEvent;
import run.halo.app.event.comment.CommentPassEvent; import run.halo.app.event.comment.CommentPassEvent;
import run.halo.app.event.comment.CommentReplyEvent; import run.halo.app.event.comment.CommentReplyEvent;
import run.halo.app.exception.NotFoundException;
import run.halo.app.model.dto.post.PostMinimalOutputDTO; import run.halo.app.model.dto.post.PostMinimalOutputDTO;
import run.halo.app.model.entity.Comment; import run.halo.app.model.entity.Comment;
import run.halo.app.model.entity.Post; import run.halo.app.model.entity.Post;
import run.halo.app.model.entity.User;
import run.halo.app.model.enums.CommentStatus; import run.halo.app.model.enums.CommentStatus;
import run.halo.app.model.params.CommentParam;
import run.halo.app.model.params.CommentQuery; import run.halo.app.model.params.CommentQuery;
import run.halo.app.model.projection.CommentCountProjection; 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.properties.CommentProperties;
import run.halo.app.model.support.CommentPage; import run.halo.app.model.support.CommentPage;
import run.halo.app.model.vo.CommentVO; import run.halo.app.model.vo.CommentVO;
@ -37,11 +39,11 @@ import run.halo.app.security.context.SecurityContextHolder;
import run.halo.app.service.CommentService; import run.halo.app.service.CommentService;
import run.halo.app.service.OptionService; import run.halo.app.service.OptionService;
import run.halo.app.service.base.AbstractCrudService; import run.halo.app.service.base.AbstractCrudService;
import run.halo.app.utils.OwoUtil;
import run.halo.app.utils.ServiceUtils; import run.halo.app.utils.ServiceUtils;
import run.halo.app.utils.ServletUtils;
import run.halo.app.utils.ValidationUtils;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import javax.servlet.http.HttpServletRequest;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -149,53 +151,65 @@ public class CommentServiceImpl extends AbstractCrudService<Comment, Long> imple
} }
@Override @Override
public Comment createBy(Comment comment, HttpServletRequest request) { public Comment createBy(CommentParam commentParam) {
Assert.notNull(comment, "Comment must not be null"); Assert.notNull(commentParam, "Comment param must not be null");
Assert.notNull(request, "Http servlet request must not be null");
// Set some default value
comment.setContent(OwoUtil.parseOwo(formatContent(comment.getContent())));
comment.setIpAddress(ServletUtil.getClientIP(request));
comment.setUserAgent(ServletUtil.getHeaderIgnoreCase(request, HttpHeaders.USER_AGENT));
// Check user login status and set this field // Check user login status and set this field
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) { if (authentication != null) {
// If the user is login User user = authentication.getDetail().getUser();
commentParam.setAuthor(StringUtils.isEmpty(user.getNickname()) ? user.getUsername() : user.getNickname());
commentParam.setEmail(user.getEmail());
commentParam.setAuthorUrl(optionService.getByPropertyOfNullable(BlogProperties.BLOG_URL));
}
// Validate the comment param manually
ValidationUtils.validate(commentParam);
// Check post id
boolean isPostExist = postRepository.existsById(commentParam.getPostId());
if (!isPostExist) {
throw new NotFoundException("The post with id " + commentParam.getPostId() + " was not found");
}
// Check parent id
if (!ServiceUtils.isEmptyId(commentParam.getParentId())) {
mustExistById(commentParam.getParentId());
}
// Convert to comment
Comment comment = commentParam.convertTo();
// Set some default values
comment.setIpAddress(ServletUtils.getRequestIp());
comment.setUserAgent(ServletUtils.getHeaderIgnoreCase(HttpHeaders.USER_AGENT));
comment.setGavatarMd5(DigestUtils.md5Hex(comment.getEmail()));
if (authentication != null) {
// Comment of blogger
comment.setIsAdmin(true); comment.setIsAdmin(true);
comment.setStatus(CommentStatus.PUBLISHED); comment.setStatus(CommentStatus.PUBLISHED);
} else { } else {
// Comment of guest
// Handle comment status // Handle comment status
Boolean needAudit = optionService.getByPropertyOrDefault(CommentProperties.NEW_NEED_CHECK, Boolean.class, true); Boolean needAudit = optionService.getByPropertyOrDefault(CommentProperties.NEW_NEED_CHECK, Boolean.class, true);
if (needAudit) { comment.setStatus(needAudit ? CommentStatus.AUDITING : CommentStatus.PUBLISHED);
comment.setStatus(CommentStatus.AUDITING);
} else {
comment.setStatus(CommentStatus.PUBLISHED);
}
}
comment.setAuthor(HtmlUtils.htmlEscape(comment.getAuthor()));
comment.setGavatarMd5(SecureUtil.md5(comment.getEmail()));
if (StringUtils.isNotBlank(comment.getAuthorUrl())) {
// Normalize the author url and set it
comment.setAuthorUrl(URLUtil.normalize(comment.getAuthorUrl()));
} }
// Create comment
Comment createdComment = create(comment); Comment createdComment = create(comment);
// TODO Handle email sending if (ServiceUtils.isEmptyId(createdComment.getParentId())) {
if (authentication == null) {
if (createdComment.getParentId() == null || createdComment.getParentId() == 0) { // New comment of guest
// New comment eventPublisher.publishEvent(new CommentNewEvent(this, createdComment.getId()));
eventPublisher.publishEvent(new CommentNewEvent(this, createdComment.getId())); }
} else { } else {
// Reply comment // Reply comment
eventPublisher.publishEvent(new CommentReplyEvent(this, createdComment.getId())); eventPublisher.publishEvent(new CommentReplyEvent(this, createdComment.getId()));
} }
return createdComment; return createdComment;
} }

View File

@ -1,5 +1,6 @@
package run.halo.app.utils; package run.halo.app.utils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@ -105,4 +106,14 @@ public class ServiceUtils {
return resultMap; return resultMap;
} }
/**
* Checks if the given number id is empty id.
*
* @param id the given number id
* @return true if the given number id is empty id; false otherwise
*/
public static boolean isEmptyId(@Nullable Number id) {
return id == null || id.longValue() <= 0;
}
} }

View File

@ -43,4 +43,15 @@ public class ServletUtils {
return getCurrentRequest().map(ServletUtil::getClientIP).orElse(null); return getCurrentRequest().map(ServletUtil::getClientIP).orElse(null);
} }
/**
* Gets request header.
*
* @param header http header name
* @return http header of null
*/
@Nullable
public static String getHeaderIgnoreCase(String header) {
return getCurrentRequest().map(request -> ServletUtil.getHeaderIgnoreCase(request, header)).orElse(null);
}
} }

View File

@ -1,25 +1,18 @@
package run.halo.app.web.controller.admin.api; package run.halo.app.web.controller.admin.api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault; import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import run.halo.app.model.dto.CommentDTO; import run.halo.app.model.dto.CommentDTO;
import run.halo.app.model.entity.Comment; import run.halo.app.model.entity.Comment;
import run.halo.app.model.entity.User;
import run.halo.app.model.enums.CommentStatus; import run.halo.app.model.enums.CommentStatus;
import run.halo.app.model.params.CommentParam; import run.halo.app.model.params.CommentParam;
import run.halo.app.model.params.CommentQuery; import run.halo.app.model.params.CommentQuery;
import run.halo.app.model.properties.BlogProperties;
import run.halo.app.model.vo.CommentWithPostVO; import run.halo.app.model.vo.CommentWithPostVO;
import run.halo.app.service.CommentService; import run.halo.app.service.CommentService;
import run.halo.app.service.OptionService;
import run.halo.app.service.PostService;
import run.halo.app.utils.ValidationUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.List; import java.util.List;
import static org.springframework.data.domain.Sort.Direction.DESC; import static org.springframework.data.domain.Sort.Direction.DESC;
@ -36,16 +29,8 @@ public class CommentController {
private final CommentService commentService; private final CommentService commentService;
private final PostService postService; public CommentController(CommentService commentService) {
private final OptionService optionService;
public CommentController(CommentService commentService,
PostService postService,
OptionService optionService) {
this.commentService = commentService; this.commentService = commentService;
this.postService = postService;
this.optionService = optionService;
} }
@GetMapping @GetMapping
@ -68,24 +53,9 @@ public class CommentController {
} }
@PostMapping @PostMapping
public CommentDTO createBy(@RequestBody CommentParam commentParam, HttpServletRequest request, User user) { @ApiOperation("Creates a comment (new or reply)")
// Set some default info public CommentDTO createBy(@RequestBody CommentParam commentParam) {
commentParam.setAuthor(StringUtils.isEmpty(user.getNickname()) ? user.getUsername() : user.getNickname()); return new CommentDTO().convertFrom(commentService.createBy(commentParam));
commentParam.setEmail(user.getEmail());
commentParam.setAuthorUrl(optionService.getByPropertyOfNullable(BlogProperties.BLOG_URL));
// Validate the comment param manually
ValidationUtils.validate(commentParam);
// Check post id
postService.mustExistById(commentParam.getPostId());
// Check parent id
if (commentParam.getParentId() != null && commentParam.getParentId() > 0) {
commentService.mustExistById(commentParam.getParentId());
}
return new CommentDTO().convertFrom(commentService.createBy(commentParam.convertTo(), request));
} }
@PutMapping("{commentId:\\d+}/status/{status}") @PutMapping("{commentId:\\d+}/status/{status}")

View File

@ -1,23 +1,13 @@
package run.halo.app.web.controller.content.api; package run.halo.app.web.controller.content.api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import run.halo.app.model.dto.CommentDTO;
import run.halo.app.model.entity.User;
import run.halo.app.model.params.CommentParam;
import run.halo.app.model.properties.BlogProperties;
import run.halo.app.security.authentication.Authentication;
import run.halo.app.security.context.SecurityContextHolder;
import run.halo.app.service.CommentService;
import run.halo.app.service.OptionService;
import run.halo.app.service.PostService;
import run.halo.app.utils.ValidationUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import run.halo.app.model.dto.CommentDTO;
import javax.servlet.http.HttpServletRequest; import run.halo.app.model.params.CommentParam;
import run.halo.app.service.CommentService;
/** /**
* Portal comment controller. * Portal comment controller.
@ -31,42 +21,13 @@ public class CommentController {
private final CommentService commentService; private final CommentService commentService;
private final OptionService optionService; public CommentController(CommentService commentService) {
private final PostService postService;
public CommentController(CommentService commentService,
OptionService optionService,
PostService postService) {
this.commentService = commentService; this.commentService = commentService;
this.optionService = optionService;
this.postService = postService;
} }
@PostMapping @PostMapping
@ApiOperation("Comments a post") @ApiOperation("Comments a post")
public CommentDTO comment(@RequestBody CommentParam commentParam, HttpServletRequest request) { public CommentDTO comment(@RequestBody CommentParam commentParam) {
// Get authentication return new CommentDTO().convertFrom(commentService.createBy(commentParam));
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
User user = authentication.getDetail().getUser();
// If the admin is login
commentParam.setAuthor(StringUtils.isEmpty(user.getNickname()) ? user.getUsername() : user.getNickname());
commentParam.setEmail(user.getEmail());
commentParam.setAuthorUrl(optionService.getByPropertyOfNullable(BlogProperties.BLOG_URL));
}
// Validate the comment param manually
ValidationUtils.validate(commentParam);
// Check post id
postService.mustExistById(commentParam.getPostId());
// Check parent id
if (commentParam.getParentId() != null && commentParam.getParentId() > 0) {
commentService.mustExistById(commentParam.getParentId());
}
return new CommentDTO().convertFrom(commentService.createBy(commentParam.convertTo(), request));
} }
} }