diff --git a/src/main/java/cc/ryanc/halo/service/LogsService.java b/src/main/java/cc/ryanc/halo/service/LogsService.java index 750d5bd1e..acbe78611 100644 --- a/src/main/java/cc/ryanc/halo/service/LogsService.java +++ b/src/main/java/cc/ryanc/halo/service/LogsService.java @@ -4,6 +4,7 @@ import cc.ryanc.halo.model.domain.Logs; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import javax.servlet.http.HttpServletRequest; import java.util.List; import java.util.Optional; @@ -20,17 +21,11 @@ public interface LogsService { /** * 保存日志 * - * @param logs logs - * @return Logs + * @param logTitle logTitle + * @param logContent logContent + * @param request request */ - Logs saveByLogs(Logs logs); - - /** - * 根据编号移除 - * - * @param logsId logsId - */ - void removeByLogsId(Long logsId); + void save(String logTitle, String logContent, HttpServletRequest request); /** * 移除所有日志 diff --git a/src/main/java/cc/ryanc/halo/service/impl/AttachmentServiceImpl.java b/src/main/java/cc/ryanc/halo/service/impl/AttachmentServiceImpl.java index 071bffea4..f11b6b607 100644 --- a/src/main/java/cc/ryanc/halo/service/impl/AttachmentServiceImpl.java +++ b/src/main/java/cc/ryanc/halo/service/impl/AttachmentServiceImpl.java @@ -223,7 +223,6 @@ public class AttachmentServiceImpl implements AttachmentService { fileSmallPath.append("_small."); fileSmallPath.append(fileSuffix); - String size = HaloUtils.parseSize(new File(fullPath.toString()).length()); String wh = HaloUtils.getImageWh(new File(fullPath.toString())); @@ -258,7 +257,7 @@ public class AttachmentServiceImpl implements AttachmentService { String domain = HaloConst.OPTIONS.get("qiniu_domain"); String bucket = HaloConst.OPTIONS.get("qiniu_bucket"); String smallUrl = HaloConst.OPTIONS.get("qiniu_small_url"); - if (accessKey == null || secretKey == null || domain == null || bucket == null) { + if (StrUtil.isEmpty(accessKey) || StrUtil.isEmpty(secretKey) || StrUtil.isEmpty(domain) || StrUtil.isEmpty(bucket)) { return resultMap; } Auth auth = Auth.create(accessKey, secretKey); @@ -318,7 +317,7 @@ public class AttachmentServiceImpl implements AttachmentService { String domain = HaloConst.OPTIONS.get("upyun_oss_domain"); String operator = HaloConst.OPTIONS.get("upyun_oss_operator"); String smallUrl = HaloConst.OPTIONS.get("upyun_oss_small"); - if (ossSrc == null || ossPwd == null || domain == null || bucket == null || operator == null) { + if (StrUtil.isEmpty(ossSrc) || StrUtil.isEmpty(ossPwd) || StrUtil.isEmpty(domain) || StrUtil.isEmpty(bucket) || StrUtil.isEmpty(operator)) { return resultMap; } String fileName = file.getOriginalFilename(); @@ -363,7 +362,7 @@ public class AttachmentServiceImpl implements AttachmentService { String accessKey = HaloConst.OPTIONS.get("qiniu_access_key"); String secretKey = HaloConst.OPTIONS.get("qiniu_secret_key"); String bucket = HaloConst.OPTIONS.get("qiniu_bucket"); - if (accessKey == null || secretKey == null || bucket == null) { + if (StrUtil.isEmpty(accessKey) || StrUtil.isEmpty(secretKey) || StrUtil.isEmpty(bucket)) { return false; } Auth auth = Auth.create(accessKey, secretKey); @@ -391,7 +390,7 @@ public class AttachmentServiceImpl implements AttachmentService { String ossPwd = HaloConst.OPTIONS.get("upyun_oss_pwd"); String bucket = HaloConst.OPTIONS.get("upyun_oss_bucket"); String operator = HaloConst.OPTIONS.get("upyun_oss_operator"); - if (ossSrc == null || ossPwd == null || bucket == null || operator == null) { + if (StrUtil.isEmpty(ossSrc) || StrUtil.isEmpty(ossPwd) || StrUtil.isEmpty(bucket) || StrUtil.isEmpty(operator)) { return false; } UpYun upYun = new UpYun(bucket, operator, ossPwd); diff --git a/src/main/java/cc/ryanc/halo/service/impl/LogsServiceImpl.java b/src/main/java/cc/ryanc/halo/service/impl/LogsServiceImpl.java index 7148bbfca..859e714c2 100644 --- a/src/main/java/cc/ryanc/halo/service/impl/LogsServiceImpl.java +++ b/src/main/java/cc/ryanc/halo/service/impl/LogsServiceImpl.java @@ -3,11 +3,14 @@ package cc.ryanc.halo.service.impl; import cc.ryanc.halo.model.domain.Logs; import cc.ryanc.halo.repository.LogsRepository; import cc.ryanc.halo.service.LogsService; +import cn.hutool.extra.servlet.ServletUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; +import javax.servlet.http.HttpServletRequest; +import java.util.Date; import java.util.List; import java.util.Optional; @@ -28,23 +31,18 @@ public class LogsServiceImpl implements LogsService { /** * 保存日志 * - * @param logs logs - * @return Logs + * @param logTitle logTitle + * @param logContent logContent + * @param request request */ @Override - public Logs saveByLogs(Logs logs) { - return logsRepository.save(logs); - } - - /** - * 根据编号移除 - * - * @param logsId logsId - */ - @Override - public void removeByLogsId(Long logsId) { - Optional logs = this.findLogsByLogsId(logsId); - logsRepository.delete(logs.get()); + public void save(String logTitle, String logContent, HttpServletRequest request) { + Logs logs = new Logs(); + logs.setLogTitle(logTitle); + logs.setLogContent(logContent); + logs.setLogCreated(new Date()); + logs.setLogIp(ServletUtil.getClientIP(request)); + logsRepository.save(logs); } /** diff --git a/src/main/java/cc/ryanc/halo/web/controller/admin/AdminController.java b/src/main/java/cc/ryanc/halo/web/controller/admin/AdminController.java index 1acbfead7..56beb2890 100755 --- a/src/main/java/cc/ryanc/halo/web/controller/admin/AdminController.java +++ b/src/main/java/cc/ryanc/halo/web/controller/admin/AdminController.java @@ -20,7 +20,6 @@ import cn.hutool.core.lang.Validator; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; -import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.http.HtmlUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -160,7 +159,7 @@ public class AdminController extends BaseController { session.setAttribute(HaloConst.USER_SESSION_KEY, aUser); //重置用户的登录状态为正常 userService.updateUserNormal(); - logsService.saveByLogs(new Logs(LogsRecord.LOGIN, LogsRecord.LOGIN_SUCCESS, ServletUtil.getClientIP(request), DateUtil.date())); + logsService.save(LogsRecord.LOGIN, LogsRecord.LOGIN_SUCCESS, request); log.info("User {} login succeeded.", aUser.getUserDisplayName()); return new JsonResult(ResultCodeEnum.SUCCESS.getCode(), localeMessageUtil.getMessage("code.admin.login.success")); } else { @@ -170,14 +169,7 @@ public class AdminController extends BaseController { if (errorCount >= CommonParamsEnum.FIVE.getValue()) { userService.updateUserLoginEnable(TrueFalseEnum.FALSE.getDesc()); } - logsService.saveByLogs( - new Logs( - LogsRecord.LOGIN, - LogsRecord.LOGIN_ERROR + "[" + HtmlUtil.escape(loginName) + "," + HtmlUtil.escape(loginPwd) + "]", - ServletUtil.getClientIP(request), - DateUtil.date() - ) - ); + logsService.save(LogsRecord.LOGIN, LogsRecord.LOGIN_ERROR + "[" + HtmlUtil.escape(loginName) + "," + HtmlUtil.escape(loginPwd) + "]", request); Object[] args = {(5 - errorCount)}; return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.login.failed", args)); } @@ -193,7 +185,7 @@ public class AdminController extends BaseController { public String logOut(HttpSession session) { User user = (User) session.getAttribute(HaloConst.USER_SESSION_KEY); session.removeAttribute(HaloConst.USER_SESSION_KEY); - logsService.saveByLogs(new Logs(LogsRecord.LOGOUT, user.getUserName(), ServletUtil.getClientIP(request), DateUtil.date())); + logsService.save(LogsRecord.LOGOUT, user.getUserName(), request); log.info("User {} has logged out", user.getUserName()); return "redirect:/admin/login"; } diff --git a/src/main/java/cc/ryanc/halo/web/controller/admin/AttachmentController.java b/src/main/java/cc/ryanc/halo/web/controller/admin/AttachmentController.java index 640aa0851..4cfe04184 100755 --- a/src/main/java/cc/ryanc/halo/web/controller/admin/AttachmentController.java +++ b/src/main/java/cc/ryanc/halo/web/controller/admin/AttachmentController.java @@ -1,7 +1,6 @@ package cc.ryanc.halo.web.controller.admin; import cc.ryanc.halo.model.domain.Attachment; -import cc.ryanc.halo.model.domain.Logs; import cc.ryanc.halo.model.dto.JsonResult; import cc.ryanc.halo.model.dto.LogsRecord; import cc.ryanc.halo.model.enums.PostTypeEnum; @@ -11,7 +10,6 @@ import cc.ryanc.halo.service.LogsService; import cc.ryanc.halo.utils.LocaleMessageUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.servlet.ServletUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; @@ -116,13 +114,12 @@ public class AttachmentController { public Map upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) { Map result = new HashMap<>(3); - System.out.println("源地址" + file.getOriginalFilename() + "类型" + file.getContentType() + "文件名" + file.getName() + "文件大小" + file.getSize()); if (!file.isEmpty()) { try { Map resultMap = attachmentService.upload(file, request); if (resultMap == null || resultMap.isEmpty()) { - log.error("文件上传失败"); - result.put("success", 0); + log.error("File upload failed"); + result.put("success", ResultCodeEnum.FAIL.getCode()); result.put("message", localeMessageUtil.getMessage("code.admin.attachment.upload-failed")); return result; } @@ -139,16 +136,14 @@ public class AttachmentController { attachment.setAttachLocation(resultMap.get("location")); attachmentService.saveByAttachment(attachment); log.info("Upload file {} to {} successfully", resultMap.get("fileName"), resultMap.get("filePath")); - logsService.saveByLogs( - new Logs(LogsRecord.UPLOAD_FILE, resultMap.get("fileName"), ServletUtil.getClientIP(request), DateUtil.date()) - ); - result.put("success", 1); + result.put("success", ResultCodeEnum.SUCCESS.getCode()); result.put("message", localeMessageUtil.getMessage("code.admin.attachment.upload-success")); result.put("url", attachment.getAttachPath()); result.put("filename", resultMap.get("filePath")); + logsService.save(LogsRecord.UPLOAD_FILE, resultMap.get("fileName"), request); } catch (Exception e) { log.error("Upload file failed:{}", e.getMessage()); - result.put("success", 0); + result.put("success", ResultCodeEnum.FAIL.getCode()); result.put("message", localeMessageUtil.getMessage("code.admin.attachment.upload-failed")); } } else { @@ -216,9 +211,7 @@ public class AttachmentController { } if (flag) { log.info("Delete file {} successfully!", delFileName); - logsService.saveByLogs( - new Logs(LogsRecord.REMOVE_FILE, delFileName, ServletUtil.getClientIP(request), DateUtil.date()) - ); + logsService.save(LogsRecord.REMOVE_FILE, delFileName, request); } else { log.error("Deleting attachment {} failed!", delFileName); return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.common.delete-failed")); diff --git a/src/main/java/cc/ryanc/halo/web/controller/admin/CommentController.java b/src/main/java/cc/ryanc/halo/web/controller/admin/CommentController.java index 7f4489e30..f29e824ac 100755 --- a/src/main/java/cc/ryanc/halo/web/controller/admin/CommentController.java +++ b/src/main/java/cc/ryanc/halo/web/controller/admin/CommentController.java @@ -1,283 +1,283 @@ -package cc.ryanc.halo.web.controller.admin; - -import cc.ryanc.halo.model.domain.Comment; -import cc.ryanc.halo.model.domain.Post; -import cc.ryanc.halo.model.domain.User; -import cc.ryanc.halo.model.dto.HaloConst; -import cc.ryanc.halo.model.dto.JsonResult; -import cc.ryanc.halo.model.enums.*; -import cc.ryanc.halo.service.CommentService; -import cc.ryanc.halo.service.MailService; -import cc.ryanc.halo.service.PostService; -import cc.ryanc.halo.utils.OwoUtil; -import cc.ryanc.halo.web.controller.core.BaseController; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.lang.Validator; -import cn.hutool.core.util.StrUtil; -import cn.hutool.crypto.SecureUtil; -import cn.hutool.extra.servlet.ServletUtil; -import cn.hutool.http.HtmlUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.*; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; -import java.util.HashMap; -import java.util.Map; - -/** - *
- *     后台评论管理控制器
- * 
- * - * @author : RYAN0UP - * @date : 2017/12/10 - */ -@Slf4j -@Controller -@RequestMapping(value = "/admin/comments") -public class CommentController extends BaseController { - - @Autowired - private CommentService commentService; - - @Autowired - private MailService mailService; - - @Autowired - private PostService postService; - - /** - * 渲染评论管理页面 - * - * @param model model - * @param status status 评论状态 - * @param page page 当前页码 - * @param size size 每页显示条数 - * @return 模板路径admin/admin_comment - */ - @GetMapping - public String comments(Model model, - @RequestParam(value = "status", defaultValue = "0") Integer status, - @RequestParam(value = "page", defaultValue = "0") Integer page, - @RequestParam(value = "size", defaultValue = "10") Integer size) { - Sort sort = new Sort(Sort.Direction.DESC, "commentDate"); - Pageable pageable = PageRequest.of(page, size, sort); - Page comments = commentService.findAllComments(status, pageable); - model.addAttribute("comments", comments); - model.addAttribute("publicCount", commentService.getCountByStatus(CommentStatusEnum.PUBLISHED.getCode())); - model.addAttribute("checkCount", commentService.getCountByStatus(CommentStatusEnum.CHECKING.getCode())); - model.addAttribute("trashCount", commentService.getCountByStatus(CommentStatusEnum.RECYCLE.getCode())); - model.addAttribute("status", status); - return "admin/admin_comment"; - } - - /** - * 将评论移到回收站 - * - * @param commentId 评论编号 - * @param status 评论状态 - * @return 重定向到/admin/comments - */ - @GetMapping(value = "/throw") - public String moveToTrash(@RequestParam("commentId") Long commentId, - @RequestParam("status") String status, - @RequestParam(value = "page", defaultValue = "0") Integer page) { - try { - commentService.updateCommentStatus(commentId, CommentStatusEnum.RECYCLE.getCode()); - } catch (Exception e) { - log.error("Delete comment failed: {}", e.getMessage()); - } - return "redirect:/admin/comments?status=" + status + "&page=" + page; - } - - /** - * 将评论改变为发布状态 - * - * @param commentId 评论编号 - * @param status 评论状态 - * @param session session - * @return 重定向到/admin/comments - */ - @GetMapping(value = "/revert") - public String moveToPublish(@RequestParam("commentId") Long commentId, - @RequestParam("status") Integer status, - HttpSession session) { - Comment comment = commentService.updateCommentStatus(commentId, CommentStatusEnum.PUBLISHED.getCode()); - Post post = comment.getPost(); - User user = (User) session.getAttribute(HaloConst.USER_SESSION_KEY); - - //判断是否启用邮件服务 - new NoticeToAuthor(comment, post, user, status).start(); - return "redirect:/admin/comments?status=" + status; - } - - /** - * 删除评论 - * - * @param commentId commentId 评论编号 - * @param status status 评论状态 - * @param page 当前页码 - * @return string 重定向到/admin/comments - */ - @GetMapping(value = "/remove") - public String moveToAway(@RequestParam("commentId") Long commentId, - @RequestParam("status") Integer status, - @RequestParam(value = "page", defaultValue = "0") Integer page) { - try { - commentService.removeByCommentId(commentId); - } catch (Exception e) { - log.error("Delete comment failed: {}", e.getMessage()); - } - return "redirect:/admin/comments?status=" + status + "&page=" + page; - } - - - /** - * 管理员回复评论 - * - * @param commentId 被回复的评论 - * @param commentContent 回复的内容 - * @return JsonResult - */ - @PostMapping(value = "/reply") - @ResponseBody - public JsonResult replyComment(@RequestParam("commentId") Long commentId, - @RequestParam("postId") Long postId, - @RequestParam("commentContent") String commentContent, - @RequestParam("userAgent") String userAgent, - HttpServletRequest request, - HttpSession session) { - try { - Post post = postService.findByPostId(postId).orElse(new Post()); - - //博主信息 - User user = (User) session.getAttribute(HaloConst.USER_SESSION_KEY); - - //被回复的评论 - Comment lastComment = commentService.findCommentById(commentId).orElse(new Comment()); - - //修改被回复的评论的状态 - lastComment.setCommentStatus(CommentStatusEnum.PUBLISHED.getCode()); - commentService.saveByComment(lastComment); - - //保存评论 - Comment comment = new Comment(); - comment.setPost(post); - comment.setCommentAuthor(user.getUserDisplayName()); - comment.setCommentAuthorEmail(user.getUserEmail()); - comment.setCommentAuthorUrl(HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp())); - comment.setCommentAuthorIp(ServletUtil.getClientIP(request)); - comment.setCommentAuthorAvatarMd5(SecureUtil.md5(user.getUserEmail())); - comment.setCommentDate(DateUtil.date()); - String lastContent = "@" + lastComment.getCommentAuthor() + " "; - comment.setCommentContent(lastContent + OwoUtil.markToImg(HtmlUtil.escape(commentContent).replace("<br/>", "
"))); - comment.setCommentAgent(userAgent); - comment.setCommentParent(commentId); - comment.setCommentStatus(CommentStatusEnum.PUBLISHED.getCode()); - comment.setIsAdmin(1); - commentService.saveByComment(comment); - - //邮件通知 - new EmailToAuthor(comment, lastComment, post, user, commentContent).start(); - return new JsonResult(ResultCodeEnum.SUCCESS.getCode()); - } catch (Exception e) { - log.error("Reply to comment failed: {}", e.getMessage()); - return new JsonResult(ResultCodeEnum.FAIL.getCode()); - } - } - - /** - * 异步发送邮件回复给评论者 - */ - class EmailToAuthor extends Thread { - - private Comment comment; - private Comment lastComment; - private Post post; - private User user; - private String commentContent; - - private EmailToAuthor(Comment comment, Comment lastComment, Post post, User user, String commentContent) { - this.comment = comment; - this.lastComment = lastComment; - this.post = post; - this.user = user; - this.commentContent = commentContent; - } - - @Override - public void run() { - if (StrUtil.equals(HaloConst.OPTIONS.get(BlogPropertiesEnum.SMTP_EMAIL_ENABLE.getProp()), TrueFalseEnum.TRUE.getDesc()) && StrUtil.equals(HaloConst.OPTIONS.get(BlogPropertiesEnum.COMMENT_REPLY_NOTICE.getProp()), TrueFalseEnum.TRUE.getDesc())) { - if (Validator.isEmail(lastComment.getCommentAuthorEmail())) { - Map map = new HashMap<>(8); - map.put("blogTitle", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_TITLE.getProp())); - map.put("commentAuthor", lastComment.getCommentAuthor()); - map.put("pageName", lastComment.getPost().getPostTitle()); - if (StrUtil.equals(post.getPostType(), PostTypeEnum.POST_TYPE_POST.getDesc())) { - map.put("pageUrl", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp()) + "/archives/" + post.getPostUrl() + "#comment-id-" + comment.getCommentId()); - } else { - map.put("pageUrl", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp()) + "/p/" + post.getPostUrl() + "#comment-id-" + comment.getCommentId()); - } - map.put("commentContent", lastComment.getCommentContent()); - map.put("replyAuthor", user.getUserDisplayName()); - map.put("replyContent", commentContent); - map.put("blogUrl", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp())); - mailService.sendTemplateMail( - lastComment.getCommentAuthorEmail(), "您在" + HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp()) + "的评论有了新回复", map, "common/mail_template/mail_reply.ftl"); - } - } - } - } - - /** - * 异步通知评论者审核通过 - */ - class NoticeToAuthor extends Thread { - - private Comment comment; - private Post post; - private User user; - private Integer status; - - private NoticeToAuthor(Comment comment, Post post, User user, Integer status) { - this.comment = comment; - this.post = post; - this.user = user; - this.status = status; - } - - @Override - public void run() { - if (StrUtil.equals(HaloConst.OPTIONS.get(BlogPropertiesEnum.SMTP_EMAIL_ENABLE.getProp()), TrueFalseEnum.TRUE.getDesc()) && StrUtil.equals(HaloConst.OPTIONS.get(BlogPropertiesEnum.COMMENT_REPLY_NOTICE.getProp()), TrueFalseEnum.TRUE.getDesc())) { - try { - if (status == 1 && Validator.isEmail(comment.getCommentAuthorEmail())) { - Map map = new HashMap<>(6); - if (StrUtil.equals(post.getPostType(), PostTypeEnum.POST_TYPE_POST.getDesc())) { - map.put("pageUrl", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp()) + "/archives/" + post.getPostUrl() + "#comment-id-" + comment.getCommentId()); - } else { - map.put("pageUrl", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp()) + "/p/" + post.getPostUrl() + "#comment-id-" + comment.getCommentId()); - } - map.put("pageName", post.getPostTitle()); - map.put("commentContent", comment.getCommentContent()); - map.put("blogUrl", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp())); - map.put("blogTitle", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_TITLE.getProp())); - map.put("author", user.getUserDisplayName()); - mailService.sendTemplateMail( - comment.getCommentAuthorEmail(), - "您在" + HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp()) + "的评论已审核通过!", map, "common/mail_template/mail_passed.ftl"); - } - } catch (Exception e) { - log.error("Mail server not configured: {}", e.getMessage()); - } - } - } - } -} +package cc.ryanc.halo.web.controller.admin; + +import cc.ryanc.halo.model.domain.Comment; +import cc.ryanc.halo.model.domain.Post; +import cc.ryanc.halo.model.domain.User; +import cc.ryanc.halo.model.dto.HaloConst; +import cc.ryanc.halo.model.dto.JsonResult; +import cc.ryanc.halo.model.enums.*; +import cc.ryanc.halo.service.CommentService; +import cc.ryanc.halo.service.MailService; +import cc.ryanc.halo.service.PostService; +import cc.ryanc.halo.utils.OwoUtil; +import cc.ryanc.halo.web.controller.core.BaseController; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.lang.Validator; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.extra.servlet.ServletUtil; +import cn.hutool.http.HtmlUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.util.HashMap; +import java.util.Map; + +/** + *
+ *     后台评论管理控制器
+ * 
+ * + * @author : RYAN0UP + * @date : 2017/12/10 + */ +@Slf4j +@Controller +@RequestMapping(value = "/admin/comments") +public class CommentController extends BaseController { + + @Autowired + private CommentService commentService; + + @Autowired + private MailService mailService; + + @Autowired + private PostService postService; + + /** + * 渲染评论管理页面 + * + * @param model model + * @param status status 评论状态 + * @param page page 当前页码 + * @param size size 每页显示条数 + * @return 模板路径admin/admin_comment + */ + @GetMapping + public String comments(Model model, + @RequestParam(value = "status", defaultValue = "0") Integer status, + @RequestParam(value = "page", defaultValue = "0") Integer page, + @RequestParam(value = "size", defaultValue = "10") Integer size) { + Sort sort = new Sort(Sort.Direction.DESC, "commentDate"); + Pageable pageable = PageRequest.of(page, size, sort); + Page comments = commentService.findAllComments(status, pageable); + model.addAttribute("comments", comments); + model.addAttribute("publicCount", commentService.getCountByStatus(CommentStatusEnum.PUBLISHED.getCode())); + model.addAttribute("checkCount", commentService.getCountByStatus(CommentStatusEnum.CHECKING.getCode())); + model.addAttribute("trashCount", commentService.getCountByStatus(CommentStatusEnum.RECYCLE.getCode())); + model.addAttribute("status", status); + return "admin/admin_comment"; + } + + /** + * 将评论移到回收站 + * + * @param commentId 评论编号 + * @param status 评论状态 + * @return 重定向到/admin/comments + */ + @GetMapping(value = "/throw") + public String moveToTrash(@RequestParam("commentId") Long commentId, + @RequestParam("status") String status, + @RequestParam(value = "page", defaultValue = "0") Integer page) { + try { + commentService.updateCommentStatus(commentId, CommentStatusEnum.RECYCLE.getCode()); + } catch (Exception e) { + log.error("Delete comment failed: {}", e.getMessage()); + } + return "redirect:/admin/comments?status=" + status + "&page=" + page; + } + + /** + * 将评论改变为发布状态 + * + * @param commentId 评论编号 + * @param status 评论状态 + * @param session session + * @return 重定向到/admin/comments + */ + @GetMapping(value = "/revert") + public String moveToPublish(@RequestParam("commentId") Long commentId, + @RequestParam("status") Integer status, + HttpSession session) { + Comment comment = commentService.updateCommentStatus(commentId, CommentStatusEnum.PUBLISHED.getCode()); + Post post = comment.getPost(); + User user = (User) session.getAttribute(HaloConst.USER_SESSION_KEY); + + //判断是否启用邮件服务 + new NoticeToAuthor(comment, post, user, status).start(); + return "redirect:/admin/comments?status=" + status; + } + + /** + * 删除评论 + * + * @param commentId commentId 评论编号 + * @param status status 评论状态 + * @param page 当前页码 + * @return string 重定向到/admin/comments + */ + @GetMapping(value = "/remove") + public String moveToAway(@RequestParam("commentId") Long commentId, + @RequestParam("status") Integer status, + @RequestParam(value = "page", defaultValue = "0") Integer page) { + try { + commentService.removeByCommentId(commentId); + } catch (Exception e) { + log.error("Delete comment failed: {}", e.getMessage()); + } + return "redirect:/admin/comments?status=" + status + "&page=" + page; + } + + + /** + * 管理员回复评论 + * + * @param commentId 被回复的评论 + * @param commentContent 回复的内容 + * @return JsonResult + */ + @PostMapping(value = "/reply") + @ResponseBody + public JsonResult replyComment(@RequestParam("commentId") Long commentId, + @RequestParam("postId") Long postId, + @RequestParam("commentContent") String commentContent, + @RequestParam("userAgent") String userAgent, + HttpServletRequest request, + HttpSession session) { + try { + Post post = postService.findByPostId(postId).orElse(new Post()); + + //博主信息 + User user = (User) session.getAttribute(HaloConst.USER_SESSION_KEY); + + //被回复的评论 + Comment lastComment = commentService.findCommentById(commentId).orElse(new Comment()); + + //修改被回复的评论的状态 + lastComment.setCommentStatus(CommentStatusEnum.PUBLISHED.getCode()); + commentService.saveByComment(lastComment); + + //保存评论 + Comment comment = new Comment(); + comment.setPost(post); + comment.setCommentAuthor(user.getUserDisplayName()); + comment.setCommentAuthorEmail(user.getUserEmail()); + comment.setCommentAuthorUrl(HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp())); + comment.setCommentAuthorIp(ServletUtil.getClientIP(request)); + comment.setCommentAuthorAvatarMd5(SecureUtil.md5(user.getUserEmail())); + comment.setCommentDate(DateUtil.date()); + String lastContent = "@" + lastComment.getCommentAuthor() + " "; + comment.setCommentContent(lastContent + OwoUtil.markToImg(HtmlUtil.escape(commentContent).replace("<br/>", "
"))); + comment.setCommentAgent(userAgent); + comment.setCommentParent(commentId); + comment.setCommentStatus(CommentStatusEnum.PUBLISHED.getCode()); + comment.setIsAdmin(1); + commentService.saveByComment(comment); + + //邮件通知 + new EmailToAuthor(comment, lastComment, post, user, commentContent).start(); + return new JsonResult(ResultCodeEnum.SUCCESS.getCode()); + } catch (Exception e) { + log.error("Reply to comment failed: {}", e.getMessage()); + return new JsonResult(ResultCodeEnum.FAIL.getCode()); + } + } + + /** + * 异步发送邮件回复给评论者 + */ + class EmailToAuthor extends Thread { + + private Comment comment; + private Comment lastComment; + private Post post; + private User user; + private String commentContent; + + private EmailToAuthor(Comment comment, Comment lastComment, Post post, User user, String commentContent) { + this.comment = comment; + this.lastComment = lastComment; + this.post = post; + this.user = user; + this.commentContent = commentContent; + } + + @Override + public void run() { + if (StrUtil.equals(HaloConst.OPTIONS.get(BlogPropertiesEnum.SMTP_EMAIL_ENABLE.getProp()), TrueFalseEnum.TRUE.getDesc()) && StrUtil.equals(HaloConst.OPTIONS.get(BlogPropertiesEnum.COMMENT_REPLY_NOTICE.getProp()), TrueFalseEnum.TRUE.getDesc())) { + if (Validator.isEmail(lastComment.getCommentAuthorEmail())) { + Map map = new HashMap<>(8); + map.put("blogTitle", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_TITLE.getProp())); + map.put("commentAuthor", lastComment.getCommentAuthor()); + map.put("pageName", lastComment.getPost().getPostTitle()); + if (StrUtil.equals(post.getPostType(), PostTypeEnum.POST_TYPE_POST.getDesc())) { + map.put("pageUrl", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp()) + "/archives/" + post.getPostUrl() + "#comment-id-" + comment.getCommentId()); + } else { + map.put("pageUrl", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp()) + "/p/" + post.getPostUrl() + "#comment-id-" + comment.getCommentId()); + } + map.put("commentContent", lastComment.getCommentContent()); + map.put("replyAuthor", user.getUserDisplayName()); + map.put("replyContent", commentContent); + map.put("blogUrl", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp())); + mailService.sendTemplateMail( + lastComment.getCommentAuthorEmail(), "您在" + HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp()) + "的评论有了新回复", map, "common/mail_template/mail_reply.ftl"); + } + } + } + } + + /** + * 异步通知评论者审核通过 + */ + class NoticeToAuthor extends Thread { + + private Comment comment; + private Post post; + private User user; + private Integer status; + + private NoticeToAuthor(Comment comment, Post post, User user, Integer status) { + this.comment = comment; + this.post = post; + this.user = user; + this.status = status; + } + + @Override + public void run() { + if (StrUtil.equals(HaloConst.OPTIONS.get(BlogPropertiesEnum.SMTP_EMAIL_ENABLE.getProp()), TrueFalseEnum.TRUE.getDesc()) && StrUtil.equals(HaloConst.OPTIONS.get(BlogPropertiesEnum.COMMENT_REPLY_NOTICE.getProp()), TrueFalseEnum.TRUE.getDesc())) { + try { + if (status == 1 && Validator.isEmail(comment.getCommentAuthorEmail())) { + Map map = new HashMap<>(6); + if (StrUtil.equals(post.getPostType(), PostTypeEnum.POST_TYPE_POST.getDesc())) { + map.put("pageUrl", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp()) + "/archives/" + post.getPostUrl() + "#comment-id-" + comment.getCommentId()); + } else { + map.put("pageUrl", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp()) + "/p/" + post.getPostUrl() + "#comment-id-" + comment.getCommentId()); + } + map.put("pageName", post.getPostTitle()); + map.put("commentContent", comment.getCommentContent()); + map.put("blogUrl", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp())); + map.put("blogTitle", HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_TITLE.getProp())); + map.put("author", user.getUserDisplayName()); + mailService.sendTemplateMail( + comment.getCommentAuthorEmail(), + "您在" + HaloConst.OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp()) + "的评论已审核通过!", map, "common/mail_template/mail_passed.ftl"); + } + } catch (Exception e) { + log.error("Mail server not configured: {}", e.getMessage()); + } + } + } + } +} diff --git a/src/main/java/cc/ryanc/halo/web/controller/admin/PageController.java b/src/main/java/cc/ryanc/halo/web/controller/admin/PageController.java index f3b27cd9f..860d8d7bc 100755 --- a/src/main/java/cc/ryanc/halo/web/controller/admin/PageController.java +++ b/src/main/java/cc/ryanc/halo/web/controller/admin/PageController.java @@ -1,6 +1,9 @@ package cc.ryanc.halo.web.controller.admin; -import cc.ryanc.halo.model.domain.*; +import cc.ryanc.halo.model.domain.Gallery; +import cc.ryanc.halo.model.domain.Link; +import cc.ryanc.halo.model.domain.Post; +import cc.ryanc.halo.model.domain.User; import cc.ryanc.halo.model.dto.HaloConst; import cc.ryanc.halo.model.dto.JsonResult; import cc.ryanc.halo.model.dto.LogsRecord; @@ -17,7 +20,6 @@ import cc.ryanc.halo.utils.MarkdownUtils; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.servlet.ServletUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.propertyeditors.CustomDateEditor; @@ -211,7 +213,7 @@ public class PageController { @GetMapping(value = "/new") public String newPage(Model model) { List customTpls = HaloUtils.getCustomTpl(HaloConst.OPTIONS.get(BlogPropertiesEnum.THEME.getProp())); - model.addAttribute("customTpls",customTpls); + model.addAttribute("customTpls", customTpls); return "admin/admin_page_md_editor"; } @@ -247,7 +249,7 @@ public class PageController { post.setPostThumbnail("/static/images/thumbnail/thumbnail-" + RandomUtil.randomInt(1, 10) + ".jpg"); } postService.saveByPost(post); - logsService.saveByLogs(new Logs(LogsRecord.PUSH_PAGE, post.getPostTitle(), ServletUtil.getClientIP(request), DateUtil.date())); + logsService.save(LogsRecord.PUSH_PAGE, post.getPostTitle(), request); return new JsonResult(ResultCodeEnum.SUCCESS.getCode(), msg); } catch (Exception e) { log.error("Save page failed: {}", e.getMessage()); @@ -267,7 +269,7 @@ public class PageController { Optional post = postService.findByPostId(pageId); List customTpls = HaloUtils.getCustomTpl(HaloConst.OPTIONS.get(BlogPropertiesEnum.THEME.getProp())); model.addAttribute("post", post.orElse(new Post())); - model.addAttribute("customTpls",customTpls); + model.addAttribute("customTpls", customTpls); return "admin/admin_page_md_editor"; } diff --git a/src/main/java/cc/ryanc/halo/web/controller/admin/PostController.java b/src/main/java/cc/ryanc/halo/web/controller/admin/PostController.java index 9eb1e8fba..db6ad36c2 100755 --- a/src/main/java/cc/ryanc/halo/web/controller/admin/PostController.java +++ b/src/main/java/cc/ryanc/halo/web/controller/admin/PostController.java @@ -1,6 +1,9 @@ package cc.ryanc.halo.web.controller.admin; -import cc.ryanc.halo.model.domain.*; +import cc.ryanc.halo.model.domain.Category; +import cc.ryanc.halo.model.domain.Post; +import cc.ryanc.halo.model.domain.Tag; +import cc.ryanc.halo.model.domain.User; import cc.ryanc.halo.model.dto.HaloConst; import cc.ryanc.halo.model.dto.JsonResult; import cc.ryanc.halo.model.dto.LogsRecord; @@ -19,7 +22,6 @@ import cc.ryanc.halo.web.controller.core.BaseController; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.http.HtmlUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -213,7 +215,7 @@ public class PostController extends BaseController { post.setPostThumbnail("/static/images/thumbnail/thumbnail-" + RandomUtil.randomInt(1, 10) + ".jpg"); } postService.saveByPost(post); - logsService.saveByLogs(new Logs(LogsRecord.PUSH_POST, post.getPostTitle(), ServletUtil.getClientIP(request), DateUtil.date())); + logsService.save(LogsRecord.PUSH_POST, post.getPostTitle(), request); return new JsonResult(ResultCodeEnum.SUCCESS.getCode(), msg); } catch (Exception e) { log.error("Save article failed: {}", e.getMessage()); @@ -268,7 +270,7 @@ public class PostController extends BaseController { try { Optional post = postService.findByPostId(postId); postService.removeByPostId(postId); - logsService.saveByLogs(new Logs(LogsRecord.REMOVE_POST, post.get().getPostTitle(), ServletUtil.getClientIP(request), DateUtil.date())); + logsService.save(LogsRecord.REMOVE_POST, post.get().getPostTitle(), request); } catch (Exception e) { log.error("Delete article failed: {}", e.getMessage()); } diff --git a/src/main/java/cc/ryanc/halo/web/controller/admin/ThemeController.java b/src/main/java/cc/ryanc/halo/web/controller/admin/ThemeController.java index 576ee4c37..5a3df144f 100755 --- a/src/main/java/cc/ryanc/halo/web/controller/admin/ThemeController.java +++ b/src/main/java/cc/ryanc/halo/web/controller/admin/ThemeController.java @@ -1,313 +1,306 @@ -package cc.ryanc.halo.web.controller.admin; - -import cc.ryanc.halo.model.domain.Logs; -import cc.ryanc.halo.model.dto.HaloConst; -import cc.ryanc.halo.model.dto.JsonResult; -import cc.ryanc.halo.model.dto.LogsRecord; -import cc.ryanc.halo.model.enums.BlogPropertiesEnum; -import cc.ryanc.halo.model.enums.ResultCodeEnum; -import cc.ryanc.halo.model.enums.TrueFalseEnum; -import cc.ryanc.halo.service.LogsService; -import cc.ryanc.halo.service.OptionsService; -import cc.ryanc.halo.utils.HaloUtils; -import cc.ryanc.halo.utils.LocaleMessageUtil; -import cc.ryanc.halo.web.controller.core.BaseController; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.io.file.FileReader; -import cn.hutool.core.io.file.FileWriter; -import cn.hutool.core.util.RuntimeUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.core.util.ZipUtil; -import cn.hutool.extra.servlet.ServletUtil; -import freemarker.template.Configuration; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.util.ResourceUtils; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.servlet.http.HttpServletRequest; -import java.io.File; -import java.io.FileNotFoundException; -import java.util.List; - -/** - *
- *     后台主题管理控制器
- * 
- * - * @author : RYAN0UP - * @date : 2017/12/16 - */ -@Slf4j -@Controller -@RequestMapping(value = "/admin/themes") -public class ThemeController extends BaseController { - - private static final String NOT_FOUND_GIT = "-bash: git: command not found"; - - @Autowired - private OptionsService optionsService; - - @Autowired - private LogsService logsService; - - @Autowired - private Configuration configuration; - - @Autowired - private LocaleMessageUtil localeMessageUtil; - - /** - * 渲染主题设置页面 - * - * @param model model - * @return 模板路径admin/admin_theme - */ - @GetMapping - public String themes(Model model) { - model.addAttribute("activeTheme", BaseController.THEME); - if (null != HaloConst.THEMES) { - model.addAttribute("themes", HaloConst.THEMES); - } - return "admin/admin_theme"; - } - - /** - * 激活主题 - * - * @param siteTheme 主题名称 - * @param request request - * @return JsonResult - */ - @GetMapping(value = "/set") - @ResponseBody - @CacheEvict(value = "posts", allEntries = true, beforeInvocation = true) - public JsonResult activeTheme(@RequestParam("siteTheme") String siteTheme, - HttpServletRequest request) { - try { - //保存主题设置项 - optionsService.saveOption(BlogPropertiesEnum.THEME.getProp(), siteTheme); - //设置主题 - BaseController.THEME = siteTheme; - HaloConst.OPTIONS.clear(); - HaloConst.OPTIONS = optionsService.findAllOptions(); - configuration.setSharedVariable("themeName", siteTheme); - configuration.setSharedVariable("options", HaloConst.OPTIONS); - log.info("Changed theme to {}", siteTheme); - logsService.saveByLogs( - new Logs(LogsRecord.CHANGE_THEME, "更换为" + siteTheme, ServletUtil.getClientIP(request), DateUtil.date()) - ); - return new JsonResult(ResultCodeEnum.SUCCESS.getCode(), localeMessageUtil.getMessage("code.admin.theme.change-success", new Object[]{siteTheme})); - } catch (Exception e) { - return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.change-failed")); - } - } - - - /** - * 上传主题 - * - * @param file 文件 - * @return JsonResult - */ - @RequestMapping(value = "/upload", method = RequestMethod.POST) - @ResponseBody - public JsonResult uploadTheme(@RequestParam("file") MultipartFile file, - HttpServletRequest request) { - try { - if (!file.isEmpty()) { - //获取项目根路径 - File basePath = new File(ResourceUtils.getURL("classpath:").getPath()); - File themePath = new File(basePath.getAbsolutePath(), new StringBuffer("templates/themes/").append(file.getOriginalFilename()).toString()); - file.transferTo(themePath); - log.info("Upload topic success, path is " + themePath.getAbsolutePath()); - logsService.saveByLogs( - new Logs(LogsRecord.UPLOAD_THEME, file.getOriginalFilename(), ServletUtil.getClientIP(request), DateUtil.date()) - ); - ZipUtil.unzip(themePath, new File(basePath.getAbsolutePath(), "templates/themes/")); - FileUtil.del(themePath); - HaloConst.THEMES.clear(); - HaloConst.THEMES = HaloUtils.getThemes(); - } else { - log.error("Upload theme failed, no file selected"); - return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.upload-no-file")); - } - } catch (Exception e) { - log.error("Upload theme failed: {}", e.getMessage()); - return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.upload-failed")); - } - return new JsonResult(ResultCodeEnum.SUCCESS.getCode(), localeMessageUtil.getMessage("code.admin.theme.upload-success")); - } - - /** - * 删除主题 - * - * @param themeName 主题文件夹名 - * @return string 重定向到/admin/themes - */ - @GetMapping(value = "/remove") - public String removeTheme(@RequestParam("themeName") String themeName) { - try { - File basePath = new File(ResourceUtils.getURL("classpath:").getPath()); - File themePath = new File(basePath.getAbsolutePath(), "templates/themes/" + themeName); - FileUtil.del(themePath); - HaloConst.THEMES.clear(); - HaloConst.THEMES = HaloUtils.getThemes(); - } catch (Exception e) { - log.error("Delete theme failed: {}", e.getMessage()); - } - return "redirect:/admin/themes"; - } - - /** - * 安装主题弹出层 - * - * @return 目录路径admin/widget/_theme-install - */ - @GetMapping(value = "/install") - public String install() { - return "admin/widget/_theme-install"; - } - - /** - * 在线拉取主题 - * - * @param remoteAddr 远程地址 - * @param themeName 主题名称 - * @return JsonResult - */ - @PostMapping(value = "/clone") - @ResponseBody - public JsonResult cloneFromRemote(@RequestParam(value = "remoteAddr") String remoteAddr, - @RequestParam(value = "themeName") String themeName) { - if (StrUtil.isBlank(remoteAddr) || StrUtil.isBlank(themeName)) { - return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.common.info-no-complete")); - } - try { - File basePath = new File(ResourceUtils.getURL("classpath:").getPath()); - File themePath = new File(basePath.getAbsolutePath(), "templates/themes"); - String cmdResult = RuntimeUtil.execForStr("git clone " + remoteAddr + " " + themePath.getAbsolutePath() + "/" + themeName); - if (NOT_FOUND_GIT.equals(cmdResult)) { - return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.no-git")); - } - HaloConst.THEMES.clear(); - HaloConst.THEMES = HaloUtils.getThemes(); - } catch (FileNotFoundException e) { - log.error("Cloning theme failed: {}", e.getMessage()); - return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.clone-theme-failed") + e.getMessage()); - } - return new JsonResult(ResultCodeEnum.SUCCESS.getCode(), localeMessageUtil.getMessage("code.admin.common.install-success")); - } - - /** - * 更新主题 - * - * @param themeName 主题名 - * @return JsonResult - */ - @GetMapping(value = "/pull") - @ResponseBody - public JsonResult pullFromRemote(@RequestParam(value = "themeName") String themeName) { - try { - File basePath = new File(ResourceUtils.getURL("classpath:").getPath()); - File themePath = new File(basePath.getAbsolutePath(), "templates/themes"); - String cmdResult = RuntimeUtil.execForStr("cd " + themePath.getAbsolutePath() + "/" + themeName + " && git pull"); - if (NOT_FOUND_GIT.equals(cmdResult)) { - return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.no-git")); - } - HaloConst.THEMES.clear(); - HaloConst.THEMES = HaloUtils.getThemes(); - } catch (Exception e) { - log.error("Update theme failed: {}", e.getMessage()); - return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.update-theme-failed") + e.getMessage()); - } - return new JsonResult(ResultCodeEnum.SUCCESS.getCode(), localeMessageUtil.getMessage("code.admin.common.update-success")); - } - - /** - * 跳转到主题设置 - * - * @param theme theme名称 - */ - @GetMapping(value = "/options") - public String setting(Model model, - @RequestParam("theme") String theme, - @RequestParam("hasUpdate") String hasUpdate) { - model.addAttribute("themeDir", theme); - if (StrUtil.equals(hasUpdate, TrueFalseEnum.TRUE.getDesc())) { - model.addAttribute("hasUpdate", true); - } else { - model.addAttribute("hasUpdate", false); - } - return "themes/" + theme + "/module/options"; - } - - /** - * 编辑主题 - * - * @param model model - * @return 模板路径admin/admin_theme-editor - */ - @GetMapping(value = "/editor") - public String editor(Model model) { - List tpls = HaloUtils.getTplName(BaseController.THEME); - model.addAttribute("tpls", tpls); - return "admin/admin_theme-editor"; - } - - /** - * 获取模板文件内容 - * - * @param tplName 模板文件名 - * @return 模板内容 - */ - @GetMapping(value = "/getTpl", produces = "text/text;charset=UTF-8") - @ResponseBody - public String getTplContent(@RequestParam("tplName") String tplName) { - String tplContent = ""; - try { - //获取项目根路径 - File basePath = new File(ResourceUtils.getURL("classpath:").getPath()); - //获取主题路径 - File themesPath = new File(basePath.getAbsolutePath(), new StringBuffer("templates/themes/").append(BaseController.THEME).append("/").append(tplName).toString()); - FileReader fileReader = new FileReader(themesPath); - tplContent = fileReader.readString(); - } catch (Exception e) { - log.error("Get template file error: {}", e.getMessage()); - } - return tplContent; - } - - /** - * 保存修改模板 - * - * @param tplName 模板名称 - * @param tplContent 模板内容 - * @return JsonResult - */ - @PostMapping(value = "/editor/save") - @ResponseBody - public JsonResult saveTpl(@RequestParam("tplName") String tplName, - @RequestParam("tplContent") String tplContent) { - if (StrUtil.isBlank(tplContent)) { - return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.edit.no-content")); - } - try { - //获取项目根路径 - File basePath = new File(ResourceUtils.getURL("classpath:").getPath()); - //获取主题路径 - File tplPath = new File(basePath.getAbsolutePath(), new StringBuffer("templates/themes/").append(BaseController.THEME).append("/").append(tplName).toString()); - FileWriter fileWriter = new FileWriter(tplPath); - fileWriter.write(tplContent); - } catch (Exception e) { - log.error("Template save failed: {}", e.getMessage()); - return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.common.save-failed")); - } - return new JsonResult(ResultCodeEnum.SUCCESS.getCode(), localeMessageUtil.getMessage("code.admin.common.save-success")); - } -} +package cc.ryanc.halo.web.controller.admin; + +import cc.ryanc.halo.model.dto.HaloConst; +import cc.ryanc.halo.model.dto.JsonResult; +import cc.ryanc.halo.model.dto.LogsRecord; +import cc.ryanc.halo.model.enums.BlogPropertiesEnum; +import cc.ryanc.halo.model.enums.ResultCodeEnum; +import cc.ryanc.halo.model.enums.TrueFalseEnum; +import cc.ryanc.halo.service.LogsService; +import cc.ryanc.halo.service.OptionsService; +import cc.ryanc.halo.utils.HaloUtils; +import cc.ryanc.halo.utils.LocaleMessageUtil; +import cc.ryanc.halo.web.controller.core.BaseController; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileReader; +import cn.hutool.core.io.file.FileWriter; +import cn.hutool.core.util.RuntimeUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.ZipUtil; +import freemarker.template.Configuration; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.ResourceUtils; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.List; + +/** + *
+ *     后台主题管理控制器
+ * 
+ * + * @author : RYAN0UP + * @date : 2017/12/16 + */ +@Slf4j +@Controller +@RequestMapping(value = "/admin/themes") +public class ThemeController extends BaseController { + + private static final String NOT_FOUND_GIT = "-bash: git: command not found"; + + @Autowired + private OptionsService optionsService; + + @Autowired + private LogsService logsService; + + @Autowired + private Configuration configuration; + + @Autowired + private LocaleMessageUtil localeMessageUtil; + + /** + * 渲染主题设置页面 + * + * @param model model + * @return 模板路径admin/admin_theme + */ + @GetMapping + public String themes(Model model) { + model.addAttribute("activeTheme", BaseController.THEME); + if (null != HaloConst.THEMES) { + model.addAttribute("themes", HaloConst.THEMES); + } + return "admin/admin_theme"; + } + + /** + * 激活主题 + * + * @param siteTheme 主题名称 + * @param request request + * @return JsonResult + */ + @GetMapping(value = "/set") + @ResponseBody + @CacheEvict(value = "posts", allEntries = true, beforeInvocation = true) + public JsonResult activeTheme(@RequestParam("siteTheme") String siteTheme, + HttpServletRequest request) { + try { + //保存主题设置项 + optionsService.saveOption(BlogPropertiesEnum.THEME.getProp(), siteTheme); + //设置主题 + BaseController.THEME = siteTheme; + HaloConst.OPTIONS.clear(); + HaloConst.OPTIONS = optionsService.findAllOptions(); + configuration.setSharedVariable("themeName", siteTheme); + configuration.setSharedVariable("options", HaloConst.OPTIONS); + log.info("Changed theme to {}", siteTheme); + logsService.save(LogsRecord.CHANGE_THEME, "更换为" + siteTheme, request); + return new JsonResult(ResultCodeEnum.SUCCESS.getCode(), localeMessageUtil.getMessage("code.admin.theme.change-success", new Object[]{siteTheme})); + } catch (Exception e) { + return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.change-failed")); + } + } + + + /** + * 上传主题 + * + * @param file 文件 + * @return JsonResult + */ + @RequestMapping(value = "/upload", method = RequestMethod.POST) + @ResponseBody + public JsonResult uploadTheme(@RequestParam("file") MultipartFile file, + HttpServletRequest request) { + try { + if (!file.isEmpty()) { + //获取项目根路径 + File basePath = new File(ResourceUtils.getURL("classpath:").getPath()); + File themePath = new File(basePath.getAbsolutePath(), new StringBuffer("templates/themes/").append(file.getOriginalFilename()).toString()); + file.transferTo(themePath); + log.info("Upload topic success, path is " + themePath.getAbsolutePath()); + logsService.save(LogsRecord.UPLOAD_THEME, file.getOriginalFilename(), request); + ZipUtil.unzip(themePath, new File(basePath.getAbsolutePath(), "templates/themes/")); + FileUtil.del(themePath); + HaloConst.THEMES.clear(); + HaloConst.THEMES = HaloUtils.getThemes(); + } else { + log.error("Upload theme failed, no file selected"); + return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.upload-no-file")); + } + } catch (Exception e) { + log.error("Upload theme failed: {}", e.getMessage()); + return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.upload-failed")); + } + return new JsonResult(ResultCodeEnum.SUCCESS.getCode(), localeMessageUtil.getMessage("code.admin.theme.upload-success")); + } + + /** + * 删除主题 + * + * @param themeName 主题文件夹名 + * @return string 重定向到/admin/themes + */ + @GetMapping(value = "/remove") + public String removeTheme(@RequestParam("themeName") String themeName) { + try { + File basePath = new File(ResourceUtils.getURL("classpath:").getPath()); + File themePath = new File(basePath.getAbsolutePath(), "templates/themes/" + themeName); + FileUtil.del(themePath); + HaloConst.THEMES.clear(); + HaloConst.THEMES = HaloUtils.getThemes(); + } catch (Exception e) { + log.error("Delete theme failed: {}", e.getMessage()); + } + return "redirect:/admin/themes"; + } + + /** + * 安装主题弹出层 + * + * @return 目录路径admin/widget/_theme-install + */ + @GetMapping(value = "/install") + public String install() { + return "admin/widget/_theme-install"; + } + + /** + * 在线拉取主题 + * + * @param remoteAddr 远程地址 + * @param themeName 主题名称 + * @return JsonResult + */ + @PostMapping(value = "/clone") + @ResponseBody + public JsonResult cloneFromRemote(@RequestParam(value = "remoteAddr") String remoteAddr, + @RequestParam(value = "themeName") String themeName) { + if (StrUtil.isBlank(remoteAddr) || StrUtil.isBlank(themeName)) { + return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.common.info-no-complete")); + } + try { + File basePath = new File(ResourceUtils.getURL("classpath:").getPath()); + File themePath = new File(basePath.getAbsolutePath(), "templates/themes"); + String cmdResult = RuntimeUtil.execForStr("git clone " + remoteAddr + " " + themePath.getAbsolutePath() + "/" + themeName); + if (NOT_FOUND_GIT.equals(cmdResult)) { + return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.no-git")); + } + HaloConst.THEMES.clear(); + HaloConst.THEMES = HaloUtils.getThemes(); + } catch (FileNotFoundException e) { + log.error("Cloning theme failed: {}", e.getMessage()); + return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.clone-theme-failed") + e.getMessage()); + } + return new JsonResult(ResultCodeEnum.SUCCESS.getCode(), localeMessageUtil.getMessage("code.admin.common.install-success")); + } + + /** + * 更新主题 + * + * @param themeName 主题名 + * @return JsonResult + */ + @GetMapping(value = "/pull") + @ResponseBody + public JsonResult pullFromRemote(@RequestParam(value = "themeName") String themeName) { + try { + File basePath = new File(ResourceUtils.getURL("classpath:").getPath()); + File themePath = new File(basePath.getAbsolutePath(), "templates/themes"); + String cmdResult = RuntimeUtil.execForStr("cd " + themePath.getAbsolutePath() + "/" + themeName + " && git pull"); + if (NOT_FOUND_GIT.equals(cmdResult)) { + return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.no-git")); + } + HaloConst.THEMES.clear(); + HaloConst.THEMES = HaloUtils.getThemes(); + } catch (Exception e) { + log.error("Update theme failed: {}", e.getMessage()); + return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.update-theme-failed") + e.getMessage()); + } + return new JsonResult(ResultCodeEnum.SUCCESS.getCode(), localeMessageUtil.getMessage("code.admin.common.update-success")); + } + + /** + * 跳转到主题设置 + * + * @param theme theme名称 + */ + @GetMapping(value = "/options") + public String setting(Model model, + @RequestParam("theme") String theme, + @RequestParam("hasUpdate") String hasUpdate) { + model.addAttribute("themeDir", theme); + if (StrUtil.equals(hasUpdate, TrueFalseEnum.TRUE.getDesc())) { + model.addAttribute("hasUpdate", true); + } else { + model.addAttribute("hasUpdate", false); + } + return "themes/" + theme + "/module/options"; + } + + /** + * 编辑主题 + * + * @param model model + * @return 模板路径admin/admin_theme-editor + */ + @GetMapping(value = "/editor") + public String editor(Model model) { + List tpls = HaloUtils.getTplName(BaseController.THEME); + model.addAttribute("tpls", tpls); + return "admin/admin_theme-editor"; + } + + /** + * 获取模板文件内容 + * + * @param tplName 模板文件名 + * @return 模板内容 + */ + @GetMapping(value = "/getTpl", produces = "text/text;charset=UTF-8") + @ResponseBody + public String getTplContent(@RequestParam("tplName") String tplName) { + String tplContent = ""; + try { + //获取项目根路径 + File basePath = new File(ResourceUtils.getURL("classpath:").getPath()); + //获取主题路径 + File themesPath = new File(basePath.getAbsolutePath(), new StringBuffer("templates/themes/").append(BaseController.THEME).append("/").append(tplName).toString()); + FileReader fileReader = new FileReader(themesPath); + tplContent = fileReader.readString(); + } catch (Exception e) { + log.error("Get template file error: {}", e.getMessage()); + } + return tplContent; + } + + /** + * 保存修改模板 + * + * @param tplName 模板名称 + * @param tplContent 模板内容 + * @return JsonResult + */ + @PostMapping(value = "/editor/save") + @ResponseBody + public JsonResult saveTpl(@RequestParam("tplName") String tplName, + @RequestParam("tplContent") String tplContent) { + if (StrUtil.isBlank(tplContent)) { + return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.theme.edit.no-content")); + } + try { + //获取项目根路径 + File basePath = new File(ResourceUtils.getURL("classpath:").getPath()); + //获取主题路径 + File tplPath = new File(basePath.getAbsolutePath(), new StringBuffer("templates/themes/").append(BaseController.THEME).append("/").append(tplName).toString()); + FileWriter fileWriter = new FileWriter(tplPath); + fileWriter.write(tplContent); + } catch (Exception e) { + log.error("Template save failed: {}", e.getMessage()); + return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.common.save-failed")); + } + return new JsonResult(ResultCodeEnum.SUCCESS.getCode(), localeMessageUtil.getMessage("code.admin.common.save-success")); + } +} diff --git a/src/main/java/cc/ryanc/halo/web/controller/api/ApiPostController.java b/src/main/java/cc/ryanc/halo/web/controller/api/ApiPostController.java index 9dcd711bd..16bfcdc59 100644 --- a/src/main/java/cc/ryanc/halo/web/controller/api/ApiPostController.java +++ b/src/main/java/cc/ryanc/halo/web/controller/api/ApiPostController.java @@ -75,6 +75,7 @@ public class ApiPostController { public JsonResult posts(@PathVariable(value = "postId") Long postId) { Post post = postService.findByPostId(postId, PostTypeEnum.POST_TYPE_POST.getDesc()); if (null != post) { + postService.cacheViews(post.getPostId()); return new JsonResult(ResponseStatusEnum.SUCCESS.getCode(), ResponseStatusEnum.SUCCESS.getMsg(), post); } else { return new JsonResult(ResponseStatusEnum.NOTFOUND.getCode(), ResponseStatusEnum.NOTFOUND.getMsg()); diff --git a/src/main/java/cc/ryanc/halo/web/controller/core/InstallController.java b/src/main/java/cc/ryanc/halo/web/controller/core/InstallController.java index b68fb551e..beb2d7314 100644 --- a/src/main/java/cc/ryanc/halo/web/controller/core/InstallController.java +++ b/src/main/java/cc/ryanc/halo/web/controller/core/InstallController.java @@ -11,7 +11,6 @@ import cc.ryanc.halo.utils.MarkdownUtils; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; -import cn.hutool.extra.servlet.ServletUtil; import freemarker.template.Configuration; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -160,7 +159,7 @@ public class InstallController { optionsService.saveOption(BlogPropertiesEnum.IS_INSTALL.getProp(), TrueFalseEnum.TRUE.getDesc()); //语言设置 - optionsService.saveOption(BlogPropertiesEnum.BLOG_LOCALE.getProp(),blogLocale); + optionsService.saveOption(BlogPropertiesEnum.BLOG_LOCALE.getProp(), blogLocale); //保存博客标题和博客地址设置 optionsService.saveOption(BlogPropertiesEnum.BLOG_TITLE.getProp(), blogTitle); optionsService.saveOption(BlogPropertiesEnum.BLOG_URL.getProp(), blogUrl); @@ -169,7 +168,7 @@ public class InstallController { optionsService.saveOption(BlogPropertiesEnum.THEME.getProp(), "anatole"); //建立网站时间 - optionsService.saveOption(BlogPropertiesEnum.BLOG_START.getProp(), DateUtil.format(DateUtil.date(),"yyyy-MM-dd")); + optionsService.saveOption(BlogPropertiesEnum.BLOG_START.getProp(), DateUtil.format(DateUtil.date(), "yyyy-MM-dd")); //默认不配置邮件系统 optionsService.saveOption(BlogPropertiesEnum.SMTP_EMAIL_ENABLE.getProp(), TrueFalseEnum.FALSE.getDesc()); @@ -180,14 +179,7 @@ public class InstallController { optionsService.saveOption(BlogPropertiesEnum.COMMENT_REPLY_NOTICE.getProp(), TrueFalseEnum.FALSE.getDesc()); //更新日志 - logsService.saveByLogs( - new Logs( - LogsRecord.INSTALL, - "安装成功,欢迎使用Halo。", - ServletUtil.getClientIP(request), - DateUtil.date() - ) - ); + logsService.save(LogsRecord.INSTALL, "安装成功,欢迎使用Halo。", request); Menu menuIndex = new Menu(); menuIndex.setMenuName("首页");