From f5d957edc160a43ab6c3becc6352b26fe9557c53 Mon Sep 17 00:00:00 2001 From: ruibaby Date: Thu, 19 Dec 2019 17:49:07 +0800 Subject: [PATCH] refactor: refactor post preview and private post view. --- .../controller/admin/api/AdminController.java | 7 +++ .../controller/admin/api/PostController.java | 9 ++-- .../controller/admin/api/SheetController.java | 9 ++-- .../content/ContentArchiveController.java | 46 ++++++------------- .../content/ContentSheetController.java | 23 ++++------ .../halo/app/model/support/StaticFile.java | 2 +- .../run/halo/app/service/AdminService.java | 13 +++++- .../app/service/impl/AdminServiceImpl.java | 32 +++++++++++++ .../impl/StaticStorageServiceImpl.java | 5 +- 9 files changed, 89 insertions(+), 57 deletions(-) diff --git a/src/main/java/run/halo/app/controller/admin/api/AdminController.java b/src/main/java/run/halo/app/controller/admin/api/AdminController.java index cf2f40c7a..543f436d4 100644 --- a/src/main/java/run/halo/app/controller/admin/api/AdminController.java +++ b/src/main/java/run/halo/app/controller/admin/api/AdminController.java @@ -16,6 +16,7 @@ import run.halo.app.security.token.AuthToken; import run.halo.app.service.AdminService; import run.halo.app.service.OptionService; +import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; /** @@ -124,4 +125,10 @@ public class AdminController { public BaseResponse getLogFiles(@RequestParam("lines") Long lines) { return BaseResponse.ok(HttpStatus.OK.getReasonPhrase(), adminService.getLogFiles(lines)); } + + @GetMapping(value = "halo/logfile/download") + @ApiOperation("Download halo log file.") + public void downloadLogFiles(@RequestParam("lines") Long lines, HttpServletResponse response) { + adminService.downloadLogFiles(lines, response); + } } diff --git a/src/main/java/run/halo/app/controller/admin/api/PostController.java b/src/main/java/run/halo/app/controller/admin/api/PostController.java index b72a6e36b..f269a3def 100644 --- a/src/main/java/run/halo/app/controller/admin/api/PostController.java +++ b/src/main/java/run/halo/app/controller/admin/api/PostController.java @@ -20,6 +20,9 @@ import run.halo.app.service.OptionService; import run.halo.app.service.PostService; import javax.validation.Valid; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.concurrent.TimeUnit; @@ -156,15 +159,15 @@ public class PostController { @GetMapping(value = {"preview/{postId:\\d+}", "{postId:\\d+}/preview"}) @ApiOperation("Get preview link") - public String preview(@PathVariable("postId") Integer postId) { + public String preview(@PathVariable("postId") Integer postId) throws UnsupportedEncodingException { Post post = postService.getById(postId); String token = IdUtil.simpleUUID(); // cache preview token - cacheStore.putAny("preview-post-token-" + postId, token, 10, TimeUnit.MINUTES); + cacheStore.putAny(token, token, 10, TimeUnit.MINUTES); // build preview post url and return - return String.format("%s/archives/%s?preview=true&token=%s", optionService.getBlogBaseUrl(), post.getUrl(), token); + return String.format("%s/archives/%s?token=%s", optionService.getBlogBaseUrl(), URLEncoder.encode(post.getUrl(), StandardCharsets.UTF_8.name()), token); } } diff --git a/src/main/java/run/halo/app/controller/admin/api/SheetController.java b/src/main/java/run/halo/app/controller/admin/api/SheetController.java index a6409f419..f7301151e 100644 --- a/src/main/java/run/halo/app/controller/admin/api/SheetController.java +++ b/src/main/java/run/halo/app/controller/admin/api/SheetController.java @@ -17,6 +17,9 @@ import run.halo.app.service.OptionService; import run.halo.app.service.SheetService; import javax.validation.Valid; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.concurrent.TimeUnit; @@ -111,15 +114,15 @@ public class SheetController { } @GetMapping("preview/{sheetId:\\d+}") - public String preview(@PathVariable("sheetId") Integer sheetId) { + public String preview(@PathVariable("sheetId") Integer sheetId) throws UnsupportedEncodingException { Sheet sheet = sheetService.getById(sheetId); String token = IdUtil.simpleUUID(); // cache preview token - cacheStore.putAny("preview-sheet-token-" + sheetId, token, 10, TimeUnit.MINUTES); + cacheStore.putAny(token, token, 10, TimeUnit.MINUTES); // build preview post url and return - return String.format("%s/s/%s?preview=true&token=%s", optionService.getBlogBaseUrl(), sheet.getUrl(), token); + return String.format("%s/s/%s?token=%s", optionService.getBlogBaseUrl(), URLEncoder.encode(sheet.getUrl(), StandardCharsets.UTF_8.name()), token); } } diff --git a/src/main/java/run/halo/app/controller/content/ContentArchiveController.java b/src/main/java/run/halo/app/controller/content/ContentArchiveController.java index 689d2611a..eca524359 100644 --- a/src/main/java/run/halo/app/controller/content/ContentArchiveController.java +++ b/src/main/java/run/halo/app/controller/content/ContentArchiveController.java @@ -3,6 +3,7 @@ package run.halo.app.controller.content; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.PageUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -13,7 +14,6 @@ import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import run.halo.app.cache.StringCacheStore; import run.halo.app.cache.lock.CacheLock; -import run.halo.app.exception.BadRequestException; import run.halo.app.exception.ForbiddenException; import run.halo.app.exception.NotFoundException; import run.halo.app.model.entity.Category; @@ -122,41 +122,26 @@ public class ContentArchiveController { */ @GetMapping("{url}") public String post(@PathVariable("url") String url, - @RequestParam(value = "preview", required = false, defaultValue = "false") boolean preview, - @RequestParam(value = "intimate", required = false, defaultValue = "false") boolean intimate, @RequestParam(value = "token", required = false) String token, @RequestParam(value = "cp", defaultValue = "1") Integer cp, @SortDefault(sort = "createTime", direction = DESC) Sort sort, Model model) { - Post post; - if (preview) { - post = postService.getByUrl(url); - } else if (intimate) { - post = postService.getBy(PostStatus.INTIMATE, url); - } else { + Post post = postService.getByUrl(url); + + if (post.getStatus().equals(PostStatus.INTIMATE) && StringUtils.isEmpty(token)) { + String redirect = String.format("%s/archives/%s/password", optionService.getBlogBaseUrl(), post.getUrl()); + return "redirect:" + redirect; + } + + if (StringUtils.isEmpty(token)) { post = postService.getBy(PostStatus.PUBLISHED, url); - } - - // if this is a preview url. - if (preview) { - // render markdown to html when preview post - post.setFormatContent(MarkdownUtils.renderHtml(post.getOriginalContent())); - - // verify token - String cachedToken = cacheStore.getAny("preview-post-token-" + post.getId(), String.class).orElseThrow(() -> new NotFoundException("该文章的预览链接不存在或已过期")); - - if (!cachedToken.equals(token)) { - throw new BadRequestException("预览 Token 错误"); - } - } - - // if this is a intimate url. - if (intimate) { + } else { // verify token String cachedToken = cacheStore.getAny(token, String.class).orElseThrow(() -> new ForbiddenException("您没有该文章的访问权限")); if (!cachedToken.equals(token)) { throw new ForbiddenException("您没有该文章的访问权限"); } + post.setFormatContent(MarkdownUtils.renderHtml(post.getOriginalContent())); } postService.getNextPost(post.getCreateTime()).ifPresent(nextPost -> model.addAttribute("nextPost", nextPost)); @@ -175,11 +160,6 @@ public class ContentArchiveController { model.addAttribute("metas", postMetaService.convertToMap(metas)); model.addAttribute("comments", comments); - if (preview) { - // refresh timeUnit - cacheStore.putAny("preview-post-token-" + post.getId(), token, 10, TimeUnit.MINUTES); - } - return themeService.render("post"); } @@ -201,14 +181,14 @@ public class ContentArchiveController { @RequestParam(value = "password") String password) { Post post = postService.getBy(PostStatus.INTIMATE, url); if (null == post) { - throw new ForbiddenException("没有查询到该文章信息"); + throw new NotFoundException("查询不到该文章的信息").setErrorData(url); } if (password.equals(post.getPassword())) { String token = IdUtil.simpleUUID(); cacheStore.putAny(token, token, 10, TimeUnit.SECONDS); - String redirect = String.format("%s/archives/%s?intimate=true&token=%s", optionService.getBlogBaseUrl(), post.getUrl(), token); + String redirect = String.format("%s/archives/%s?token=%s", optionService.getBlogBaseUrl(), post.getUrl(), token); return "redirect:" + redirect; } else { String redirect = String.format("%s/archives/%s/password", optionService.getBlogBaseUrl(), post.getUrl()); diff --git a/src/main/java/run/halo/app/controller/content/ContentSheetController.java b/src/main/java/run/halo/app/controller/content/ContentSheetController.java index e11849051..eacb222e4 100644 --- a/src/main/java/run/halo/app/controller/content/ContentSheetController.java +++ b/src/main/java/run/halo/app/controller/content/ContentSheetController.java @@ -1,5 +1,6 @@ package run.halo.app.controller.content; +import org.apache.commons.lang3.StringUtils; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -20,8 +21,6 @@ import run.halo.app.model.vo.BaseCommentVO; import run.halo.app.service.*; import run.halo.app.utils.MarkdownUtils; -import java.util.concurrent.TimeUnit; - import static org.springframework.data.domain.Sort.Direction.DESC; /** @@ -110,39 +109,35 @@ public class ContentSheetController { */ @GetMapping(value = "/s/{url}") public String sheet(@PathVariable(value = "url") String url, - @RequestParam(value = "preview", required = false, defaultValue = "false") boolean preview, @RequestParam(value = "token", required = false) String token, @RequestParam(value = "cp", defaultValue = "1") Integer cp, @SortDefault(sort = "createTime", direction = DESC) Sort sort, Model model) { - Sheet sheet = sheetService.getBy(preview ? PostStatus.DRAFT : PostStatus.PUBLISHED, url); - if (preview) { - // render markdown to html when preview post + Sheet sheet = sheetService.getByUrl(url); + + if (StringUtils.isEmpty(token)) { + sheet = sheetService.getBy(PostStatus.PUBLISHED, url); + } else { + // render markdown to html when preview sheet sheet.setFormatContent(MarkdownUtils.renderHtml(sheet.getOriginalContent())); // verify token - String cachedToken = cacheStore.getAny("preview-sheet-token-" + sheet.getId(), String.class).orElseThrow(() -> new ForbiddenException("该页面的预览链接不存在或已过期")); + String cachedToken = cacheStore.getAny(token, String.class).orElseThrow(() -> new ForbiddenException("您没有该页面的访问权限")); if (!cachedToken.equals(token)) { - throw new ForbiddenException("该页面的预览链接不存在或已过期"); + throw new ForbiddenException("您没有该页面的访问权限"); } } Page comments = sheetCommentService.pageVosBy(sheet.getId(), PageRequest.of(cp, optionService.getCommentPageSize(), sort)); - // sheet and post all can use model.addAttribute("sheet", sheetService.convertToDetail(sheet)); model.addAttribute("post", sheetService.convertToDetail(sheet)); model.addAttribute("is_sheet", true); model.addAttribute("comments", comments); - if (preview) { - // refresh timeUnit - cacheStore.putAny("preview-sheet-token-" + sheet.getId(), token, 10, TimeUnit.MINUTES); - } - if (themeService.templateExists(ThemeService.CUSTOM_SHEET_PREFIX + sheet.getTemplate() + HaloConst.SUFFIX_FTL)) { return themeService.render(ThemeService.CUSTOM_SHEET_PREFIX + sheet.getTemplate()); } diff --git a/src/main/java/run/halo/app/model/support/StaticFile.java b/src/main/java/run/halo/app/model/support/StaticFile.java index 4ff3baf69..e1de4146a 100644 --- a/src/main/java/run/halo/app/model/support/StaticFile.java +++ b/src/main/java/run/halo/app/model/support/StaticFile.java @@ -24,7 +24,7 @@ public class StaticFile implements Comparator { private Boolean isFile; - private String mediaType; + private String mimeType; private Long createTime; diff --git a/src/main/java/run/halo/app/service/AdminService.java b/src/main/java/run/halo/app/service/AdminService.java index 741893edf..122d33424 100644 --- a/src/main/java/run/halo/app/service/AdminService.java +++ b/src/main/java/run/halo/app/service/AdminService.java @@ -7,6 +7,8 @@ import run.halo.app.model.params.LoginParam; import run.halo.app.model.params.ResetPasswordParam; import run.halo.app.security.token.AuthToken; +import javax.servlet.http.HttpServletResponse; + /** * Admin service interface. * @@ -98,7 +100,7 @@ public interface AdminService { * * @param content new content */ - void updateApplicationConfig(String content); + void updateApplicationConfig(@NonNull String content); /** * Get halo logs content. @@ -106,5 +108,12 @@ public interface AdminService { * @param lines lines * @return logs content. */ - String getLogFiles(Long lines); + String getLogFiles(@NonNull Long lines); + + /** + * Download halo log file. + * + * @param lines lines. + */ + void downloadLogFiles(@NonNull Long lines, @NonNull HttpServletResponse response); } diff --git a/src/main/java/run/halo/app/service/impl/AdminServiceImpl.java b/src/main/java/run/halo/app/service/impl/AdminServiceImpl.java index a8162c1bd..f75e38588 100644 --- a/src/main/java/run/halo/app/service/impl/AdminServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/AdminServiceImpl.java @@ -1,5 +1,6 @@ package run.halo.app.service.impl; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.file.FileReader; import cn.hutool.core.lang.Validator; import cn.hutool.core.util.RandomUtil; @@ -37,6 +38,9 @@ import run.halo.app.service.*; import run.halo.app.utils.FileUtils; import run.halo.app.utils.HaloUtils; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; @@ -457,6 +461,8 @@ public class AdminServiceImpl implements AdminService { @Override public void updateApplicationConfig(String content) { + Assert.notNull(content, "Content must not be null"); + Path path = Paths.get(haloProperties.getWorkDir(), APPLICATION_CONFIG_NAME); try { Files.write(path, content.getBytes(StandardCharsets.UTF_8)); @@ -467,6 +473,7 @@ public class AdminServiceImpl implements AdminService { @Override public String getLogFiles(Long lines) { + Assert.notNull(lines, "Lines must not be null"); File file = new File(haloProperties.getWorkDir(), LOG_PATH); @@ -517,4 +524,29 @@ public class AdminServiceImpl implements AdminService { } return result.toString(); } + + @Override + public void downloadLogFiles(Long lines, HttpServletResponse response) { + Assert.notNull(lines, "Lines must not be null"); + Assert.notNull(response, "HttpServletResponse must not be null"); + + String logFiles = getLogFiles(lines); + String fileName = "halo-log-" + + DateUtil.format(DateUtil.date(), "yyyy-MM-dd-HH-mm-ss") + + ".log"; + response.setContentType("application/force-download"); + response.setHeader("Content-Disposition", "attachment; filename=" + fileName); + ServletOutputStream outputStream; + BufferedOutputStream bufferedOutputStream; + try { + outputStream = response.getOutputStream(); + bufferedOutputStream = new BufferedOutputStream(outputStream); + bufferedOutputStream.write(logFiles.getBytes(StandardCharsets.UTF_8)); + bufferedOutputStream.flush(); + bufferedOutputStream.close(); + outputStream.close(); + } catch (IOException e) { + throw new ServiceException("日志下载失败", e); + } + } } diff --git a/src/main/java/run/halo/app/service/impl/StaticStorageServiceImpl.java b/src/main/java/run/halo/app/service/impl/StaticStorageServiceImpl.java index 8574d475d..40ea905b4 100644 --- a/src/main/java/run/halo/app/service/impl/StaticStorageServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/StaticStorageServiceImpl.java @@ -13,6 +13,7 @@ import run.halo.app.model.support.StaticFile; import run.halo.app.service.StaticStorageService; import run.halo.app.utils.FileUtils; +import javax.activation.MimetypesFileTypeMap; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -34,8 +35,9 @@ public class StaticStorageServiceImpl implements StaticStorageService { private final HaloProperties haloProperties; - public StaticStorageServiceImpl(HaloProperties haloProperties) { + public StaticStorageServiceImpl(HaloProperties haloProperties) throws IOException { staticDir = Paths.get(haloProperties.getWorkDir(), STATIC_FOLDER); + FileUtils.createIfAbsent(staticDir); this.haloProperties = haloProperties; } @@ -66,6 +68,7 @@ public class StaticStorageServiceImpl implements StaticStorageService { } catch (IOException e) { e.printStackTrace(); } + staticFile.setMimeType(MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(path.toFile())); if (Files.isDirectory(path)) { staticFile.setChildren(listStaticFileTree(path)); }