Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: comments from users with comment management permission could exempt from review #5529

Merged
merged 12 commits into from Mar 22, 2024
1 change: 1 addition & 0 deletions api/src/main/java/run/halo/app/infra/SystemSetting.java
Expand Up @@ -99,6 +99,7 @@ public static class Comment {
public static final String GROUP = "comment";
Boolean enable;
Boolean requireReviewForNew;
Boolean autoApproveAdminComment;
mashirot marked this conversation as resolved.
Show resolved Hide resolved
Boolean systemUserOnly;
}

Expand Down
Expand Up @@ -5,7 +5,9 @@
import static run.halo.app.extension.index.query.QueryFactory.isNull;

import java.time.Instant;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull;
Expand All @@ -16,6 +18,7 @@
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.User;
import run.halo.app.core.extension.content.Comment;
import run.halo.app.core.extension.service.RoleService;
import run.halo.app.core.extension.service.UserService;
import run.halo.app.extension.Extension;
import run.halo.app.extension.ListOptions;
Expand All @@ -42,6 +45,7 @@ public class CommentServiceImpl implements CommentService {

private final ReactiveExtensionClient client;
private final UserService userService;
private final RoleService roleService;
private final ExtensionComponentsFinder extensionComponentsFinder;

private final SystemConfigurableEnvironmentFetcher environmentFetcher;
Expand All @@ -50,12 +54,14 @@ public class CommentServiceImpl implements CommentService {
public CommentServiceImpl(ReactiveExtensionClient client,
UserService userService, ExtensionComponentsFinder extensionComponentsFinder,
SystemConfigurableEnvironmentFetcher environmentFetcher,
CounterService counterService) {
CounterService counterService, RoleService roleService
) {
this.client = client;
this.userService = userService;
this.extensionComponentsFinder = extensionComponentsFinder;
this.environmentFetcher = environmentFetcher;
this.counterService = counterService;
this.roleService = roleService;
}

@Override
Expand Down Expand Up @@ -113,13 +119,32 @@ public Mono<Comment> create(Comment comment) {
}
// populate owner from current user
return fetchCurrentUser()
.map(this::toCommentOwner)
.map(owner -> {
comment.getSpec().setOwner(owner);
return comment;
})
.switchIfEmpty(
Mono.error(new IllegalStateException("The owner must not be null.")));
.flatMap(currentUser -> ReactiveSecurityContextHolder.getContext()
.doOnNext(securityContext -> {
if (commentSetting.getAutoApproveAdminComment()) {
var authentication = securityContext.getAuthentication();
var roles = authentication.getAuthorities().stream()
// remove prefix: ROLE_
.map(o -> o.getAuthority().substring(5))
mashirot marked this conversation as resolved.
Show resolved Hide resolved
.collect(Collectors.toSet());
roleService.contains(roles, Set.of("role-template-manage-comments"))
mashirot marked this conversation as resolved.
Show resolved Hide resolved
.doOnNext(result -> {
if (result) {
comment.getSpec().setApproved(true);
comment.getSpec().setApprovedTime(Instant.now());
}
})
.subscribe();
mashirot marked this conversation as resolved.
Show resolved Hide resolved
}
})
.flatMap(securityContext -> Mono.just(toCommentOwner(currentUser)))
.map(owner -> {
comment.getSpec().setOwner(owner);
return comment;
})
.switchIfEmpty(
Mono.error(new IllegalStateException("The owner must not be null."))
));
})
.flatMap(client::create);
}
Expand Down
Expand Up @@ -6,8 +6,10 @@
import static run.halo.app.extension.router.selector.SelectorUtil.labelAndFieldSelectorToPredicate;

import java.time.Instant;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.data.domain.Sort;
Expand All @@ -19,6 +21,7 @@
import run.halo.app.core.extension.User;
import run.halo.app.core.extension.content.Comment;
import run.halo.app.core.extension.content.Reply;
import run.halo.app.core.extension.service.RoleService;
import run.halo.app.core.extension.service.UserService;
import run.halo.app.extension.Extension;
import run.halo.app.extension.ListOptions;
Expand All @@ -27,11 +30,12 @@
import run.halo.app.extension.PageRequestImpl;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.extension.router.selector.FieldSelector;
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
import run.halo.app.metrics.CounterService;
import run.halo.app.metrics.MeterUtils;

/**
* A default implementation of {@link ReplyService}.
* A default implementation of {@link run.halo.app.content.comment.ReplyService}.
*
* @author guqing
* @since 2.0.0
Expand All @@ -42,7 +46,9 @@ public class ReplyServiceImpl implements ReplyService {

private final ReactiveExtensionClient client;
private final UserService userService;
private final RoleService roleService;
private final CounterService counterService;
private final SystemConfigurableEnvironmentFetcher environmentFetcher;

@Override
public Mono<Reply> create(String commentName, Reply reply) {
Expand Down Expand Up @@ -75,10 +81,35 @@ public Mono<Reply> create(String commentName, Reply reply) {
}
// populate owner from current user
return fetchCurrentUser()
.map(user -> {
replyToUse.getSpec().setOwner(toCommentOwner(user));
return replyToUse;
})
.flatMap(user ->
environmentFetcher.fetchComment()
.flatMap(commentSetting ->
ReactiveSecurityContextHolder.getContext()
.doOnNext(securityContext -> {
if (commentSetting.getAutoApproveAdminComment()) {
mashirot marked this conversation as resolved.
Show resolved Hide resolved
var authentication =
securityContext.getAuthentication();
var roles = authentication.getAuthorities().stream()
// remove prefix: ROLE_
.map(o -> o.getAuthority().substring(5))
mashirot marked this conversation as resolved.
Show resolved Hide resolved
.collect(Collectors.toSet());
roleService.contains(roles,
Set.of("role-template-manage-comments"))
.doOnNext(result -> {
if (result) {
reply.getSpec().setApproved(true);
reply.getSpec()
.setApprovedTime(Instant.now());
}
})
.subscribe();
mashirot marked this conversation as resolved.
Show resolved Hide resolved
}
})
.flatMap(securityContext -> {
replyToUse.getSpec().setOwner(toCommentOwner(user));
return Mono.just(replyToUse);
})
))
.switchIfEmpty(
Mono.error(new IllegalArgumentException("Reply owner must not be null.")));
})
Expand Down
5 changes: 5 additions & 0 deletions application/src/main/resources/extensions/system-setting.yaml
Expand Up @@ -125,6 +125,11 @@ spec:
value: true
label: "新评论审核"
help: 开启之后,新评论需要管理员审核后才会显示
- $formkit: checkbox
mashirot marked this conversation as resolved.
Show resolved Hide resolved
name: autoApproveAdminComment
value: false
label: "管理员评论免审核"
help: 开启之后,有评论管理权限的用户发布的评论不需要审核
- $formkit: checkbox
name: systemUserOnly
value: true
Expand Down
Expand Up @@ -249,6 +249,7 @@ private static SystemSetting.Comment getCommentSetting() {
SystemSetting.Comment commentSetting = new SystemSetting.Comment();
commentSetting.setEnable(true);
commentSetting.setSystemUserOnly(true);
commentSetting.setAutoApproveAdminComment(false);
mashirot marked this conversation as resolved.
Show resolved Hide resolved
commentSetting.setRequireReviewForNew(true);
return commentSetting;
}
Expand Down