Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
import run.halo.app.content.PostService;
import run.halo.app.core.extension.content.Post;
import run.halo.app.core.extension.content.SinglePage;
import run.halo.app.core.user.service.RoleService;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.AnonymousUserConst;
import run.halo.app.infra.exception.NotFoundException;
import run.halo.app.security.authorization.AuthorityUtils;
import run.halo.app.theme.DefaultTemplateEnum;
import run.halo.app.theme.ViewNameResolver;
import run.halo.app.theme.dialect.HaloTrackerProcessor;
Expand All @@ -41,6 +43,8 @@
@RequiredArgsConstructor
public class PreviewRouterFunction {
static final String SNAPSHOT_NAME_PARAM = "snapshotName";
static final String POST_VIEW_ROLE_NAME = "role-template-view-posts";
static final String SINGLE_PAGE_VIEW_ROLE_NAME = "role-template-view-singlepages";

private final ReactiveExtensionClient client;

Expand All @@ -52,6 +56,8 @@ public class PreviewRouterFunction {

private final PostService postService;

private final RoleService roleService;

private final SinglePageConversionService singlePageConversionService;

@Bean
Expand All @@ -71,7 +77,7 @@ private Mono<ServerResponse> previewPost(ServerRequest request) {
.orElse(post.getSpec().getHeadSnapshot());
return convertToPostVo(post, snapshotName);
})
.flatMap(post -> canPreview(post.getContributors())
.flatMap(post -> canPreview(post.getContributors(), POST_VIEW_ROLE_NAME)
.doOnNext(canPreview -> {
if (!canPreview) {
throw new NotFoundException("Post not found.");
Expand Down Expand Up @@ -138,7 +144,7 @@ private Mono<ServerResponse> previewSinglePage(ServerRequest request) {
status.setLastModifyTime(Instant.now());
}
})
.flatMap(singlePageVo -> canPreview(singlePageVo.getContributors())
.flatMap(singlePageVo -> canPreview(singlePageVo.getContributors(), SINGLE_PAGE_VIEW_ROLE_NAME)
.doOnNext(canPreview -> {
if (!canPreview) {
throw new NotFoundException("Single page not found.");
Expand All @@ -158,11 +164,21 @@ private Mono<ServerResponse> previewSinglePage(ServerRequest request) {
});
}

private Mono<Boolean> canPreview(List<ContributorVo> contributors) {
private Mono<Boolean> canPreview(List<ContributorVo> contributors, String viewRoleName) {
Assert.notNull(contributors, "The contributors must not be null");
Set<String> contributorNames =
contributors.stream().map(ContributorVo::getName).collect(Collectors.toSet());
return currentAuthenticatedUserName().map(contributorNames::contains).defaultIfEmpty(false);
return ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
.filter(authentication -> !AnonymousUserConst.isAnonymousUser(authentication.getName()))
.flatMap(authentication -> {
if (contributorNames.contains(authentication.getName())) {
return Mono.just(true);
}
var roles = AuthorityUtils.authoritiesToRoles(authentication.getAuthorities());
return roleService.contains(roles, Set.of(viewRoleName));
})
.defaultIfEmpty(false);
}

Mono<String> currentAuthenticatedUserName() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand All @@ -25,6 +26,7 @@
import run.halo.app.content.PostService;
import run.halo.app.core.extension.content.Post;
import run.halo.app.core.extension.content.SinglePage;
import run.halo.app.core.user.service.RoleService;
import run.halo.app.extension.Metadata;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.AnonymousUserConst;
Expand Down Expand Up @@ -61,6 +63,9 @@ class PreviewRouterFunctionTest {
@Mock
PostService postService;

@Mock
RoleService roleService;

@Mock
SinglePageConversionService singlePageConversionService;

Expand Down Expand Up @@ -118,6 +123,35 @@ public Mono<Void> render(Map<String, ?> model, MediaType contentType, ServerWebE
verify(client).fetch(eq(Post.class), eq("post1"));
}

@Test
@WithMockUser(username = "admin", authorities = "ROLE_role-template-view-posts")
void previewPostWithViewPermission() {
when(viewResolver.resolveViewName(any(), any())).thenReturn(Mono.just(new EmptyView()));

Post post = new Post();
post.setMetadata(new Metadata());
post.getMetadata().setName("post1");
post.setSpec(new Post.PostSpec());
post.getSpec().setHeadSnapshot("snapshot1");
when(client.fetch(Post.class, "post1")).thenReturn(Mono.just(post));

PostVo postVo = PostVo.from(post);
postVo.setContributors(
List.of(ContributorVo.builder().name("other-user").build()));
when(postPublicQueryService.convertToVo(post, "snapshot1")).thenReturn(Mono.just(postVo));
when(roleService.contains(Set.of("role-template-view-posts"), Set.of("role-template-view-posts")))
.thenReturn(Mono.just(true));
when(postViewNameResolver.resolveViewNameOrDefault(any(ServerRequest.class), eq(postVo)))
.thenReturn(Mono.just("postView"));

webTestClient
.get()
.uri("/preview/posts/post1")
.exchange()
.expectStatus()
.isOk();
}

@Test
public void previewPostWhenUnAuthenticated() {
webTestClient
Expand Down Expand Up @@ -165,6 +199,35 @@ public Mono<Void> render(Map<String, ?> model, MediaType contentType, ServerWebE
verify(client).fetch(eq(SinglePage.class), eq("page1"));
}

@Test
@WithMockUser(username = "admin", authorities = "ROLE_role-template-view-singlepages")
void previewSinglePageWithViewPermission() {
when(viewResolver.resolveViewName(any(), any())).thenReturn(Mono.just(new EmptyView()));

SinglePage singlePage = new SinglePage();
singlePage.setMetadata(new Metadata());
singlePage.getMetadata().setName("page1");
singlePage.setSpec(new SinglePage.SinglePageSpec());
singlePage.getSpec().setHeadSnapshot("snapshot1");
when(client.fetch(SinglePage.class, "page1")).thenReturn(Mono.just(singlePage));

SinglePageVo singlePageVo = SinglePageVo.from(singlePage);
singlePageVo.setContributors(
List.of(ContributorVo.builder().name("other-user").build()));
when(singlePageConversionService.convertToVo(singlePage, "snapshot1")).thenReturn(Mono.just(singlePageVo));
when(roleService.contains(Set.of("role-template-view-singlepages"), Set.of("role-template-view-singlepages")))
.thenReturn(Mono.just(true));
when(viewNameResolver.resolveViewNameOrDefault(any(ServerRequest.class), any(), eq("page")))
.thenReturn(Mono.just("pageView"));

webTestClient
.get()
.uri("/preview/singlepages/page1")
.exchange()
.expectStatus()
.isOk();
}

@Test
public void previewSinglePageWhenUnAuthenticated() {
webTestClient
Expand Down
Loading