mirror of https://github.com/halo-dev/halo
refactor: default is approved to reply to comments on the console-side (#3363)
#### What type of PR is this? /kind improvement /area core /milestone 2.3.x #### What this PR does / why we need it: Console 端创建回复不再需要审核 但需要注意的是目前无法区分是否为管理员,所以如果具有评论管理权限的用户在主题端登录回复还是需要审核。 #### Which issue(s) this PR fixes: Fixes #3353 #### Special notes for your reviewer: how to test it? 1. 在主题端创建评论和回复都需要审核 2. 在 console 端回复不需要审核 /cc @halo-dev/sig-halo #### Does this PR introduce a user-facing change? ```release-note Console 端创建回复不再需要审核 ```pull/3370/head v2.3.0-rc.1
parent
f1ec6ceeab
commit
adff2a7194
|
@ -18,8 +18,6 @@ import run.halo.app.core.extension.service.UserService;
|
|||
import run.halo.app.extension.Extension;
|
||||
import run.halo.app.extension.ListResult;
|
||||
import run.halo.app.extension.ReactiveExtensionClient;
|
||||
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
|
||||
import run.halo.app.infra.exception.AccessDeniedException;
|
||||
|
||||
/**
|
||||
* A default implementation of {@link ReplyService}.
|
||||
|
@ -32,13 +30,12 @@ import run.halo.app.infra.exception.AccessDeniedException;
|
|||
public class ReplyServiceImpl implements ReplyService {
|
||||
|
||||
private final ReactiveExtensionClient client;
|
||||
private final SystemConfigurableEnvironmentFetcher environmentFetcher;
|
||||
private final UserService userService;
|
||||
|
||||
@Override
|
||||
public Mono<Reply> create(String commentName, Reply reply) {
|
||||
return client.fetch(Comment.class, commentName)
|
||||
.flatMap(comment -> {
|
||||
return client.get(Comment.class, commentName)
|
||||
.map(comment -> {
|
||||
// Boolean allowNotification = reply.getSpec().getAllowNotification();
|
||||
// TODO send notification if allowNotification is true
|
||||
reply.getSpec().setCommentName(commentName);
|
||||
|
@ -51,28 +48,14 @@ public class ReplyServiceImpl implements ReplyService {
|
|||
if (reply.getSpec().getCreationTime() == null) {
|
||||
reply.getSpec().setCreationTime(Instant.now());
|
||||
}
|
||||
return environmentFetcher.fetchComment()
|
||||
.map(commentSetting -> {
|
||||
if (Boolean.FALSE.equals(commentSetting.getEnable())) {
|
||||
throw new AccessDeniedException(
|
||||
"The comment function has been turned off.",
|
||||
"problemDetail.comment.turnedOff", null);
|
||||
}
|
||||
if (checkReplyOwner(reply, commentSetting.getSystemUserOnly())) {
|
||||
throw new AccessDeniedException("Allow only system users to comment.",
|
||||
"problemDetail.comment.systemUsersOnly", null);
|
||||
}
|
||||
reply.getSpec().setApproved(
|
||||
Boolean.FALSE.equals(commentSetting.getRequireReviewForNew()));
|
||||
// fix https://github.com/halo-dev/halo/issues/2951
|
||||
reply.getSpec().setHidden(false);
|
||||
|
||||
if (BooleanUtils.isTrue(reply.getSpec().getApproved())
|
||||
&& reply.getSpec().getApprovedTime() == null) {
|
||||
reply.getSpec().setApprovedTime(Instant.now());
|
||||
}
|
||||
return reply;
|
||||
});
|
||||
if (reply.getSpec().getApproved() == null) {
|
||||
reply.getSpec().setApproved(false);
|
||||
}
|
||||
if (BooleanUtils.isTrue(reply.getSpec().getApproved())
|
||||
&& reply.getSpec().getApprovedTime() == null) {
|
||||
reply.getSpec().setApprovedTime(Instant.now());
|
||||
}
|
||||
return reply;
|
||||
})
|
||||
.flatMap(replyToUse -> {
|
||||
if (replyToUse.getSpec().getOwner() != null) {
|
||||
|
@ -85,21 +68,9 @@ public class ReplyServiceImpl implements ReplyService {
|
|||
return replyToUse;
|
||||
})
|
||||
.switchIfEmpty(
|
||||
Mono.error(new IllegalStateException("Reply owner must not be null.")));
|
||||
Mono.error(new IllegalArgumentException("Reply owner must not be null.")));
|
||||
})
|
||||
.flatMap(client::create)
|
||||
.switchIfEmpty(Mono.error(
|
||||
new IllegalArgumentException(
|
||||
String.format("Comment not found for name [%s].", commentName)))
|
||||
);
|
||||
}
|
||||
|
||||
private boolean checkReplyOwner(Reply reply, Boolean onlySystemUser) {
|
||||
Comment.CommentOwner owner = reply.getSpec().getOwner();
|
||||
if (Boolean.TRUE.equals(onlySystemUser)) {
|
||||
return owner != null && Comment.CommentOwner.KIND_EMAIL.equals(owner.getKind());
|
||||
}
|
||||
return false;
|
||||
.flatMap(client::create);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,6 +6,7 @@ import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;
|
|||
import static org.springdoc.core.fn.builders.requestbody.Builder.requestBodyBuilder;
|
||||
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
import java.time.Instant;
|
||||
import org.springdoc.core.fn.builders.schema.Builder;
|
||||
import org.springdoc.webflux.core.fn.SpringdocRouteBuilder;
|
||||
import org.springframework.http.MediaType;
|
||||
|
@ -116,8 +117,15 @@ public class CommentEndpoint implements CustomEndpoint {
|
|||
return request.bodyToMono(ReplyRequest.class)
|
||||
.flatMap(replyRequest -> {
|
||||
Reply reply = replyRequest.toReply();
|
||||
// Create via console without audit
|
||||
reply.getSpec().setApproved(true);
|
||||
reply.getSpec().setApprovedTime(Instant.now());
|
||||
reply.getSpec().setIpAddress(IpAddressUtils.getIpAddress(request));
|
||||
reply.getSpec().setUserAgent(HaloUtils.userAgentFrom(request));
|
||||
// fix gh-2951
|
||||
if (reply.getSpec().getHidden() == null) {
|
||||
reply.getSpec().setHidden(false);
|
||||
}
|
||||
return replyService.create(commentName, reply);
|
||||
})
|
||||
.flatMap(comment -> ServerResponse.ok().bodyValue(comment));
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package run.halo.app.theme.endpoint;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
import static org.apache.commons.lang3.BooleanUtils.isFalse;
|
||||
import static org.apache.commons.lang3.BooleanUtils.isTrue;
|
||||
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
|
||||
import static org.springdoc.core.fn.builders.content.Builder.contentBuilder;
|
||||
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;
|
||||
|
@ -9,6 +12,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
|||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springdoc.core.fn.builders.schema.Builder;
|
||||
import org.springdoc.webflux.core.fn.SpringdocRouteBuilder;
|
||||
|
@ -32,6 +36,8 @@ import run.halo.app.extension.ListResult;
|
|||
import run.halo.app.extension.Ref;
|
||||
import run.halo.app.extension.router.IListRequest;
|
||||
import run.halo.app.extension.router.QueryParamBuildUtil;
|
||||
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
|
||||
import run.halo.app.infra.exception.AccessDeniedException;
|
||||
import run.halo.app.infra.utils.HaloUtils;
|
||||
import run.halo.app.infra.utils.IpAddressUtils;
|
||||
import run.halo.app.theme.finders.CommentFinder;
|
||||
|
@ -42,25 +48,13 @@ import run.halo.app.theme.finders.vo.ReplyVo;
|
|||
* Endpoint for {@link CommentFinder}.
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class CommentFinderEndpoint implements CustomEndpoint {
|
||||
|
||||
private final CommentFinder commentFinder;
|
||||
private final CommentService commentService;
|
||||
private final ReplyService replyService;
|
||||
|
||||
/**
|
||||
* Construct a {@link CommentFinderEndpoint} instance.
|
||||
*
|
||||
* @param commentFinder comment finder
|
||||
* @param commentService comment service to create comment
|
||||
* @param replyService reply service to create reply
|
||||
*/
|
||||
public CommentFinderEndpoint(CommentFinder commentFinder, CommentService commentService,
|
||||
ReplyService replyService) {
|
||||
this.commentFinder = commentFinder;
|
||||
this.commentService = commentService;
|
||||
this.replyService = replyService;
|
||||
}
|
||||
private final SystemConfigurableEnvironmentFetcher environmentFetcher;
|
||||
|
||||
@Override
|
||||
public RouterFunction<ServerResponse> endpoint() {
|
||||
|
@ -158,15 +152,41 @@ public class CommentFinderEndpoint implements CustomEndpoint {
|
|||
Reply reply = replyRequest.toReply();
|
||||
reply.getSpec().setIpAddress(IpAddressUtils.getIpAddress(request));
|
||||
reply.getSpec().setUserAgent(HaloUtils.userAgentFrom(request));
|
||||
return replyService.create(commentName, reply);
|
||||
// fix gh-2951
|
||||
reply.getSpec().setHidden(false);
|
||||
return environmentFetcher.fetchComment()
|
||||
.map(commentSetting -> {
|
||||
if (isFalse(commentSetting.getEnable())) {
|
||||
throw new AccessDeniedException(
|
||||
"The comment function has been turned off.",
|
||||
"problemDetail.comment.turnedOff", null);
|
||||
}
|
||||
if (checkReplyOwner(reply, commentSetting.getSystemUserOnly())) {
|
||||
throw new AccessDeniedException("Allow only system users to comment.",
|
||||
"problemDetail.comment.systemUsersOnly", null);
|
||||
}
|
||||
reply.getSpec()
|
||||
.setApproved(isFalse(commentSetting.getRequireReviewForNew()));
|
||||
return reply;
|
||||
})
|
||||
.defaultIfEmpty(reply);
|
||||
})
|
||||
.flatMap(reply -> replyService.create(commentName, reply))
|
||||
.flatMap(comment -> ServerResponse.ok().bodyValue(comment));
|
||||
}
|
||||
|
||||
private boolean checkReplyOwner(Reply reply, Boolean onlySystemUser) {
|
||||
Comment.CommentOwner owner = reply.getSpec().getOwner();
|
||||
if (isTrue(onlySystemUser)) {
|
||||
return owner != null && Comment.CommentOwner.KIND_EMAIL.equals(owner.getKind());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Mono<ServerResponse> listComments(ServerRequest request) {
|
||||
CommentQuery commentQuery = new CommentQuery(request.queryParams());
|
||||
return commentFinder.list(commentQuery.toRef(), commentQuery.getPage(),
|
||||
commentQuery.getSize())
|
||||
commentQuery.getSize())
|
||||
.flatMap(list -> ServerResponse.ok().bodyValue(list));
|
||||
}
|
||||
|
||||
|
@ -196,7 +216,7 @@ public class CommentFinderEndpoint implements CustomEndpoint {
|
|||
return queryParams.getFirst("group");
|
||||
}
|
||||
|
||||
@Schema(required = true, description = "The comment subject version.")
|
||||
@Schema(requiredMode = REQUIRED, description = "The comment subject version.")
|
||||
public String getVersion() {
|
||||
return emptyToNull(queryParams.getFirst("version"));
|
||||
}
|
||||
|
@ -206,7 +226,7 @@ public class CommentFinderEndpoint implements CustomEndpoint {
|
|||
*
|
||||
* @return comment subject ref kind
|
||||
*/
|
||||
@Schema(required = true, description = "The comment subject kind.")
|
||||
@Schema(requiredMode = REQUIRED, description = "The comment subject kind.")
|
||||
public String getKind() {
|
||||
String kind = emptyToNull(queryParams.getFirst("kind"));
|
||||
if (kind == null) {
|
||||
|
@ -220,7 +240,7 @@ public class CommentFinderEndpoint implements CustomEndpoint {
|
|||
*
|
||||
* @return comment subject ref name
|
||||
*/
|
||||
@Schema(required = true, description = "The comment subject name.")
|
||||
@Schema(requiredMode = REQUIRED, description = "The comment subject name.")
|
||||
public String getName() {
|
||||
String name = emptyToNull(queryParams.getFirst("name"));
|
||||
if (name == null) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
@ -26,6 +27,7 @@ import run.halo.app.core.extension.content.Comment;
|
|||
import run.halo.app.core.extension.content.Reply;
|
||||
import run.halo.app.extension.ListResult;
|
||||
import run.halo.app.extension.Ref;
|
||||
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
|
||||
import run.halo.app.theme.finders.CommentFinder;
|
||||
|
||||
/**
|
||||
|
@ -42,6 +44,9 @@ class CommentFinderEndpointTest {
|
|||
@Mock
|
||||
private CommentService commentService;
|
||||
|
||||
@Mock
|
||||
private SystemConfigurableEnvironmentFetcher environmentFetcher;
|
||||
|
||||
@Mock
|
||||
private ReplyService replyService;
|
||||
|
||||
|
@ -52,6 +57,7 @@ class CommentFinderEndpointTest {
|
|||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
lenient().when(environmentFetcher.fetchComment()).thenReturn(Mono.empty());
|
||||
webTestClient = WebTestClient
|
||||
.bindToRouterFunction(commentFinderEndpoint.endpoint())
|
||||
.build();
|
||||
|
|
Loading…
Reference in New Issue