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 2e965514dd..057efa11d2 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 @@ -2,12 +2,16 @@ import static org.springframework.data.domain.Sort.Direction.DESC; +import cn.hutool.core.util.IdUtil; import io.swagger.annotations.ApiOperation; import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.concurrent.TimeUnit; import javax.validation.Valid; +import org.apache.http.client.utils.URIBuilder; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; @@ -20,10 +24,12 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import run.halo.app.cache.AbstractStringCacheStore; import run.halo.app.model.dto.post.BasePostDetailDTO; import run.halo.app.model.dto.post.BasePostMinimalDTO; import run.halo.app.model.dto.post.BasePostSimpleDTO; import run.halo.app.model.entity.Post; +import run.halo.app.model.enums.PostPermalinkType; import run.halo.app.model.enums.PostStatus; import run.halo.app.model.params.PostContentParam; import run.halo.app.model.params.PostParam; @@ -46,12 +52,15 @@ public class PostController { private final PostService postService; - private final OptionService optionService; + private final AbstractStringCacheStore cacheStore; + private final OptionService optionService; public PostController(PostService postService, + AbstractStringCacheStore cacheStore, OptionService optionService) { this.postService = postService; + this.cacheStore = cacheStore; this.optionService = optionService; } @@ -172,13 +181,18 @@ public List deletePermanentlyInBatch(@RequestBody List ids) { @GetMapping(value = {"preview/{postId:\\d+}", "{postId:\\d+}/preview"}) @ApiOperation("Gets a post preview link") public String preview(@PathVariable("postId") Integer postId) - throws UnsupportedEncodingException { + throws UnsupportedEncodingException, URISyntaxException { Post post = postService.getById(postId); post.setSlug(URLEncoder.encode(post.getSlug(), StandardCharsets.UTF_8.name())); BasePostMinimalDTO postMinimalDTO = postService.convertToMinimal(post); + String token = IdUtil.simpleUUID(); + + // cache preview token + cacheStore.putAny(token, token, 10, TimeUnit.MINUTES); + StringBuilder previewUrl = new StringBuilder(); if (!optionService.isEnabledAbsolutePath()) { @@ -188,6 +202,8 @@ public String preview(@PathVariable("postId") Integer postId) previewUrl.append(postMinimalDTO.getFullPath()); // build preview post url and return - return previewUrl.toString(); + return new URIBuilder(previewUrl.toString()) + .addParameter("token", token) + .build().toString(); } } diff --git a/src/main/java/run/halo/app/controller/content/model/PostModel.java b/src/main/java/run/halo/app/controller/content/model/PostModel.java index 50d37886ec..3fbea0da51 100644 --- a/src/main/java/run/halo/app/controller/content/model/PostModel.java +++ b/src/main/java/run/halo/app/controller/content/model/PostModel.java @@ -3,6 +3,7 @@ import static run.halo.app.model.support.HaloConst.POST_PASSWORD_TEMPLATE; import static run.halo.app.model.support.HaloConst.SUFFIX_FTL; +import cn.hutool.core.util.StrUtil; import java.util.List; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; @@ -13,6 +14,8 @@ import org.springframework.stereotype.Component; import org.springframework.ui.Model; import run.halo.app.cache.AbstractStringCacheStore; +import run.halo.app.exception.ForbiddenException; +import run.halo.app.exception.NotFoundException; import run.halo.app.model.entity.Category; import run.halo.app.model.entity.Post; import run.halo.app.model.entity.PostMeta; @@ -85,9 +88,27 @@ public PostModel(PostService postService, } public String content(Post post, String token, Model model) { + if (PostStatus.RECYCLE.equals(post.getStatus())) { + // Articles in the recycle bin are not allowed to be accessed. + throw new NotFoundException("查询不到该文章的信息"); + } else if (StrUtil.isNotEmpty(token)) { + // If the token is not empty, it means it is an admin request, + // then verify the token. + + // verify token + String cachedToken = cacheStore.getAny(token, String.class) + .orElseThrow(() -> new ForbiddenException("您没有该文章的访问权限")); + if (!cachedToken.equals(token)) { + throw new ForbiddenException("您没有该文章的访问权限"); + } + } else if (PostStatus.DRAFT.equals(post.getStatus())) { + // Drafts are not allowed bo be accessed by outsiders. + throw new NotFoundException("查询不到该文章的信息"); + } else if (PostStatus.INTIMATE.equals(post.getStatus()) + && !authenticationService.postAuthentication(post, null) + ) { + // Encrypted articles must has the correct password before they can be accessed. - if (post.getStatus().equals(PostStatus.INTIMATE) - && !authenticationService.postAuthentication(post, null)) { model.addAttribute("slug", post.getSlug()); model.addAttribute("type", EncryptTypeEnum.POST.getName()); if (themeService.templateExists(POST_PASSWORD_TEMPLATE + SUFFIX_FTL)) {