mirror of https://github.com/halo-dev/halo
refactor: optimize comment and reply logic to reduce duplicate code (#6542)
#### What type of PR is this? /kind improvement /area core /milestone 2.19.x #### What this PR does / why we need it: 优化评论和回复的逻辑并减少重复代码 #### Does this PR introduce a user-facing change? ```release-note None ```pull/6548/head
parent
0a13981c0d
commit
ad267ebed7
|
@ -0,0 +1,77 @@
|
||||||
|
package run.halo.app.content.comment;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
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.content.Reply;
|
||||||
|
import run.halo.app.core.extension.service.RoleService;
|
||||||
|
import run.halo.app.core.extension.service.UserService;
|
||||||
|
import run.halo.app.extension.ReactiveExtensionClient;
|
||||||
|
import run.halo.app.metrics.CounterService;
|
||||||
|
import run.halo.app.metrics.MeterUtils;
|
||||||
|
import run.halo.app.security.authorization.AuthorityUtils;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public abstract class AbstractCommentService {
|
||||||
|
protected final RoleService roleService;
|
||||||
|
protected final ReactiveExtensionClient client;
|
||||||
|
protected final UserService userService;
|
||||||
|
protected final CounterService counterService;
|
||||||
|
|
||||||
|
protected Mono<User> fetchCurrentUser() {
|
||||||
|
return ReactiveSecurityContextHolder.getContext()
|
||||||
|
.map(securityContext -> securityContext.getAuthentication().getName())
|
||||||
|
.flatMap(username -> client.fetch(User.class, username));
|
||||||
|
}
|
||||||
|
|
||||||
|
Mono<Boolean> hasCommentManagePermission() {
|
||||||
|
return ReactiveSecurityContextHolder.getContext()
|
||||||
|
.flatMap(securityContext -> {
|
||||||
|
var authentication = securityContext.getAuthentication();
|
||||||
|
var roles = AuthorityUtils.authoritiesToRoles(authentication.getAuthorities());
|
||||||
|
return roleService.contains(roles,
|
||||||
|
Set.of(AuthorityUtils.COMMENT_MANAGEMENT_ROLE_NAME));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Comment.CommentOwner toCommentOwner(User user) {
|
||||||
|
Comment.CommentOwner owner = new Comment.CommentOwner();
|
||||||
|
owner.setKind(User.KIND);
|
||||||
|
owner.setName(user.getMetadata().getName());
|
||||||
|
owner.setDisplayName(user.getSpec().getDisplayName());
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Mono<OwnerInfo> getOwnerInfo(Comment.CommentOwner owner) {
|
||||||
|
if (User.KIND.equals(owner.getKind())) {
|
||||||
|
return userService.getUserOrGhost(owner.getName())
|
||||||
|
.map(OwnerInfo::from);
|
||||||
|
}
|
||||||
|
if (Comment.CommentOwner.KIND_EMAIL.equals(owner.getKind())) {
|
||||||
|
return Mono.just(OwnerInfo.from(owner));
|
||||||
|
}
|
||||||
|
return Mono.error(new IllegalStateException("Unsupported owner kind: " + owner.getKind()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Mono<CommentStats> fetchCommentStats(String commentName) {
|
||||||
|
return this.fetchStats(MeterUtils.nameOf(Comment.class, commentName));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Mono<CommentStats> fetchReplyStats(String replyName) {
|
||||||
|
return this.fetchStats(MeterUtils.nameOf(Reply.class, replyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<CommentStats> fetchStats(String meterName) {
|
||||||
|
Assert.notNull(meterName, "The reply must not be null.");
|
||||||
|
return counterService.getByName(meterName)
|
||||||
|
.map(counter -> CommentStats.builder()
|
||||||
|
.upvote(counter.getUpvote())
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.switchIfEmpty(Mono.fromSupplier(CommentStats::empty));
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,19 +6,16 @@ import static run.halo.app.extension.index.query.QueryFactory.isNull;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.springframework.dao.OptimisticLockingFailureException;
|
import org.springframework.dao.OptimisticLockingFailureException;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.util.retry.Retry;
|
import reactor.util.retry.Retry;
|
||||||
import run.halo.app.core.extension.User;
|
|
||||||
import run.halo.app.core.extension.content.Comment;
|
import run.halo.app.core.extension.content.Comment;
|
||||||
import run.halo.app.core.extension.service.RoleService;
|
import run.halo.app.core.extension.service.RoleService;
|
||||||
import run.halo.app.core.extension.service.UserService;
|
import run.halo.app.core.extension.service.UserService;
|
||||||
|
@ -33,9 +30,7 @@ import run.halo.app.extension.router.selector.FieldSelector;
|
||||||
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
|
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
|
||||||
import run.halo.app.infra.exception.AccessDeniedException;
|
import run.halo.app.infra.exception.AccessDeniedException;
|
||||||
import run.halo.app.metrics.CounterService;
|
import run.halo.app.metrics.CounterService;
|
||||||
import run.halo.app.metrics.MeterUtils;
|
|
||||||
import run.halo.app.plugin.extensionpoint.ExtensionGetter;
|
import run.halo.app.plugin.extensionpoint.ExtensionGetter;
|
||||||
import run.halo.app.security.authorization.AuthorityUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comment service implementation.
|
* Comment service implementation.
|
||||||
|
@ -44,28 +39,17 @@ import run.halo.app.security.authorization.AuthorityUtils;
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class CommentServiceImpl implements CommentService {
|
public class CommentServiceImpl extends AbstractCommentService implements CommentService {
|
||||||
|
|
||||||
private final ReactiveExtensionClient client;
|
|
||||||
private final UserService userService;
|
|
||||||
private final RoleService roleService;
|
|
||||||
private final ExtensionGetter extensionGetter;
|
private final ExtensionGetter extensionGetter;
|
||||||
|
|
||||||
private final SystemConfigurableEnvironmentFetcher environmentFetcher;
|
private final SystemConfigurableEnvironmentFetcher environmentFetcher;
|
||||||
private final CounterService counterService;
|
|
||||||
|
|
||||||
public CommentServiceImpl(ReactiveExtensionClient client,
|
public CommentServiceImpl(RoleService roleService, ReactiveExtensionClient client,
|
||||||
UserService userService,
|
UserService userService, CounterService counterService, ExtensionGetter extensionGetter,
|
||||||
SystemConfigurableEnvironmentFetcher environmentFetcher,
|
SystemConfigurableEnvironmentFetcher environmentFetcher) {
|
||||||
CounterService counterService, RoleService roleService,
|
super(roleService, client, userService, counterService);
|
||||||
ExtensionGetter extensionGetter
|
|
||||||
) {
|
|
||||||
this.client = client;
|
|
||||||
this.userService = userService;
|
|
||||||
this.environmentFetcher = environmentFetcher;
|
|
||||||
this.counterService = counterService;
|
|
||||||
this.roleService = roleService;
|
|
||||||
this.extensionGetter = extensionGetter;
|
this.extensionGetter = extensionGetter;
|
||||||
|
this.environmentFetcher = environmentFetcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -116,38 +100,36 @@ public class CommentServiceImpl implements CommentService {
|
||||||
}
|
}
|
||||||
|
|
||||||
comment.getSpec().setHidden(false);
|
comment.getSpec().setHidden(false);
|
||||||
|
return Mono.just(comment);
|
||||||
// return if the comment owner is not null
|
|
||||||
if (comment.getSpec().getOwner() != null) {
|
|
||||||
return Mono.just(comment);
|
|
||||||
}
|
|
||||||
// populate owner from current user
|
|
||||||
return fetchCurrentUser()
|
|
||||||
.flatMap(currentUser -> ReactiveSecurityContextHolder.getContext()
|
|
||||||
.flatMap(securityContext -> {
|
|
||||||
var authentication = securityContext.getAuthentication();
|
|
||||||
var roles = AuthorityUtils.authoritiesToRoles(
|
|
||||||
authentication.getAuthorities());
|
|
||||||
return roleService.contains(roles,
|
|
||||||
Set.of(AuthorityUtils.COMMENT_MANAGEMENT_ROLE_NAME))
|
|
||||||
.doOnNext(result -> {
|
|
||||||
if (result) {
|
|
||||||
comment.getSpec().setApproved(true);
|
|
||||||
comment.getSpec().setApprovedTime(Instant.now());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.thenReturn(toCommentOwner(currentUser));
|
|
||||||
}))
|
|
||||||
.map(owner -> {
|
|
||||||
comment.getSpec().setOwner(owner);
|
|
||||||
return comment;
|
|
||||||
})
|
|
||||||
.switchIfEmpty(
|
|
||||||
Mono.error(new IllegalStateException("The owner must not be null.")));
|
|
||||||
})
|
})
|
||||||
|
.flatMap(populatedComment -> Mono.when(populateOwner(populatedComment),
|
||||||
|
populateApproveState(populatedComment))
|
||||||
|
.thenReturn(populatedComment)
|
||||||
|
)
|
||||||
.flatMap(client::create);
|
.flatMap(client::create);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Mono<Void> populateApproveState(Comment comment) {
|
||||||
|
return hasCommentManagePermission()
|
||||||
|
.filter(Boolean::booleanValue)
|
||||||
|
.doOnNext(hasPermission -> {
|
||||||
|
comment.getSpec().setApproved(true);
|
||||||
|
comment.getSpec().setApprovedTime(Instant.now());
|
||||||
|
})
|
||||||
|
.then();
|
||||||
|
}
|
||||||
|
|
||||||
|
Mono<Void> populateOwner(Comment comment) {
|
||||||
|
if (comment.getSpec().getOwner() != null) {
|
||||||
|
return Mono.empty();
|
||||||
|
}
|
||||||
|
return fetchCurrentUser()
|
||||||
|
.switchIfEmpty(Mono.error(new IllegalStateException("The owner must not be null.")))
|
||||||
|
.map(this::toCommentOwner)
|
||||||
|
.doOnNext(owner -> comment.getSpec().setOwner(owner))
|
||||||
|
.then();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> removeBySubject(@NonNull Ref subjectRef) {
|
public Mono<Void> removeBySubject(@NonNull Ref subjectRef) {
|
||||||
Assert.notNull(subjectRef, "The subjectRef must not be null.");
|
Assert.notNull(subjectRef, "The subjectRef must not be null.");
|
||||||
|
@ -197,55 +179,19 @@ public class CommentServiceImpl implements CommentService {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Comment.CommentOwner toCommentOwner(User user) {
|
|
||||||
Comment.CommentOwner owner = new Comment.CommentOwner();
|
|
||||||
owner.setKind(User.KIND);
|
|
||||||
owner.setName(user.getMetadata().getName());
|
|
||||||
owner.setDisplayName(user.getSpec().getDisplayName());
|
|
||||||
return owner;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Mono<User> fetchCurrentUser() {
|
|
||||||
return ReactiveSecurityContextHolder.getContext()
|
|
||||||
.map(securityContext -> securityContext.getAuthentication().getName())
|
|
||||||
.flatMap(username -> client.fetch(User.class, username));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Mono<ListedComment> toListedComment(Comment comment) {
|
private Mono<ListedComment> toListedComment(Comment comment) {
|
||||||
var builder = ListedComment.builder().comment(comment);
|
var builder = ListedComment.builder().comment(comment);
|
||||||
// not empty
|
// not empty
|
||||||
var ownerInfoMono = getCommentOwnerInfo(comment.getSpec().getOwner())
|
var ownerInfoMono = getOwnerInfo(comment.getSpec().getOwner())
|
||||||
.doOnNext(builder::owner);
|
.doOnNext(builder::owner);
|
||||||
var subjectMono = getCommentSubject(comment.getSpec().getSubjectRef())
|
var subjectMono = getCommentSubject(comment.getSpec().getSubjectRef())
|
||||||
.doOnNext(builder::subject);
|
.doOnNext(builder::subject);
|
||||||
var statsMono = fetchStats(comment.getMetadata().getName())
|
var statsMono = fetchCommentStats(comment.getMetadata().getName())
|
||||||
.doOnNext(builder::stats);
|
.doOnNext(builder::stats);
|
||||||
return Mono.when(ownerInfoMono, subjectMono, statsMono)
|
return Mono.when(ownerInfoMono, subjectMono, statsMono)
|
||||||
.then(Mono.fromSupplier(builder::build));
|
.then(Mono.fromSupplier(builder::build));
|
||||||
}
|
}
|
||||||
|
|
||||||
Mono<CommentStats> fetchStats(String commentName) {
|
|
||||||
Assert.notNull(commentName, "The commentName must not be null.");
|
|
||||||
return counterService.getByName(MeterUtils.nameOf(Comment.class, commentName))
|
|
||||||
.map(counter -> CommentStats.builder()
|
|
||||||
.upvote(counter.getUpvote())
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
.defaultIfEmpty(CommentStats.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Mono<OwnerInfo> getCommentOwnerInfo(Comment.CommentOwner owner) {
|
|
||||||
if (User.KIND.equals(owner.getKind())) {
|
|
||||||
return userService.getUserOrGhost(owner.getName())
|
|
||||||
.map(OwnerInfo::from);
|
|
||||||
}
|
|
||||||
if (Comment.CommentOwner.KIND_EMAIL.equals(owner.getKind())) {
|
|
||||||
return Mono.just(OwnerInfo.from(owner));
|
|
||||||
}
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"Unsupported owner kind: " + owner.getKind());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Mono<Extension> getCommentSubject(Ref ref) {
|
Mono<Extension> getCommentSubject(Ref ref) {
|
||||||
return extensionGetter.getExtensions(CommentSubject.class)
|
return extensionGetter.getExtensions(CommentSubject.class)
|
||||||
|
|
|
@ -3,29 +3,22 @@ package run.halo.app.content.comment;
|
||||||
import static run.halo.app.extension.index.query.QueryFactory.and;
|
import static run.halo.app.extension.index.query.QueryFactory.and;
|
||||||
import static run.halo.app.extension.index.query.QueryFactory.equal;
|
import static run.halo.app.extension.index.query.QueryFactory.equal;
|
||||||
import static run.halo.app.extension.index.query.QueryFactory.isNull;
|
import static run.halo.app.extension.index.query.QueryFactory.isNull;
|
||||||
import static run.halo.app.security.authorization.AuthorityUtils.COMMENT_MANAGEMENT_ROLE_NAME;
|
|
||||||
import static run.halo.app.security.authorization.AuthorityUtils.authoritiesToRoles;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.reactivestreams.Publisher;
|
import org.reactivestreams.Publisher;
|
||||||
import org.springframework.dao.OptimisticLockingFailureException;
|
import org.springframework.dao.OptimisticLockingFailureException;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.util.retry.Retry;
|
import reactor.util.retry.Retry;
|
||||||
import run.halo.app.core.extension.User;
|
|
||||||
import run.halo.app.core.extension.content.Comment;
|
import run.halo.app.core.extension.content.Comment;
|
||||||
import run.halo.app.core.extension.content.Reply;
|
import run.halo.app.core.extension.content.Reply;
|
||||||
import run.halo.app.core.extension.service.RoleService;
|
import run.halo.app.core.extension.service.RoleService;
|
||||||
|
@ -37,7 +30,6 @@ import run.halo.app.extension.PageRequestImpl;
|
||||||
import run.halo.app.extension.ReactiveExtensionClient;
|
import run.halo.app.extension.ReactiveExtensionClient;
|
||||||
import run.halo.app.extension.router.selector.FieldSelector;
|
import run.halo.app.extension.router.selector.FieldSelector;
|
||||||
import run.halo.app.metrics.CounterService;
|
import run.halo.app.metrics.CounterService;
|
||||||
import run.halo.app.metrics.MeterUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A default implementation of {@link ReplyService}.
|
* A default implementation of {@link ReplyService}.
|
||||||
|
@ -46,13 +38,12 @@ import run.halo.app.metrics.MeterUtils;
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
public class ReplyServiceImpl extends AbstractCommentService implements ReplyService {
|
||||||
public class ReplyServiceImpl implements ReplyService {
|
|
||||||
|
|
||||||
private final ReactiveExtensionClient client;
|
public ReplyServiceImpl(RoleService roleService, ReactiveExtensionClient client,
|
||||||
private final UserService userService;
|
UserService userService, CounterService counterService) {
|
||||||
private final RoleService roleService;
|
super(roleService, client, userService, counterService);
|
||||||
private final CounterService counterService;
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Reply> create(String commentName, Reply reply) {
|
public Mono<Reply> create(String commentName, Reply reply) {
|
||||||
|
@ -74,6 +65,12 @@ public class ReplyServiceImpl implements ReplyService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<Comment> approveComment(Comment comment) {
|
private Mono<Comment> approveComment(Comment comment) {
|
||||||
|
return hasCommentManagePermission()
|
||||||
|
.filter(Boolean::booleanValue)
|
||||||
|
.flatMap(hasPermission -> doApproveComment(comment));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<Comment> doApproveComment(Comment comment) {
|
||||||
UnaryOperator<Comment> updateFunc = commentToUpdate -> {
|
UnaryOperator<Comment> updateFunc = commentToUpdate -> {
|
||||||
commentToUpdate.getSpec().setApproved(true);
|
commentToUpdate.getSpec().setApproved(true);
|
||||||
commentToUpdate.getSpec().setApprovedTime(Instant.now());
|
commentToUpdate.getSpec().setApprovedTime(Instant.now());
|
||||||
|
@ -85,6 +82,12 @@ public class ReplyServiceImpl implements ReplyService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<Void> approveReply(String replyName) {
|
private Mono<Void> approveReply(String replyName) {
|
||||||
|
return hasCommentManagePermission()
|
||||||
|
.filter(Boolean::booleanValue)
|
||||||
|
.flatMap(hasPermission -> doApproveReply(replyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<Void> doApproveReply(String replyName) {
|
||||||
return Mono.defer(() -> client.fetch(Reply.class, replyName)
|
return Mono.defer(() -> client.fetch(Reply.class, replyName)
|
||||||
.flatMap(reply -> {
|
.flatMap(reply -> {
|
||||||
reply.getSpec().setApproved(true);
|
reply.getSpec().setApproved(true);
|
||||||
|
@ -144,15 +147,6 @@ public class ReplyServiceImpl implements ReplyService {
|
||||||
return Mono.when(steps).thenReturn(reply);
|
return Mono.when(steps).thenReturn(reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mono<Boolean> hasCommentManagePermission() {
|
|
||||||
return ReactiveSecurityContextHolder.getContext()
|
|
||||||
.map(SecurityContext::getAuthentication)
|
|
||||||
.flatMap(authentication -> {
|
|
||||||
var roles = authoritiesToRoles(authentication.getAuthorities());
|
|
||||||
return roleService.contains(roles, Set.of(COMMENT_MANAGEMENT_ROLE_NAME));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<ListResult<ListedReply>> list(ReplyQuery query) {
|
public Mono<ListResult<ListedReply>> list(ReplyQuery query) {
|
||||||
return client.listBy(Reply.class, query.toListOptions(), query.toPageRequest())
|
return client.listBy(Reply.class, query.toListOptions(), query.toPageRequest())
|
||||||
|
@ -209,52 +203,14 @@ public class ReplyServiceImpl implements ReplyService {
|
||||||
private Mono<ListedReply> toListedReply(Reply reply) {
|
private Mono<ListedReply> toListedReply(Reply reply) {
|
||||||
ListedReply.ListedReplyBuilder builder = ListedReply.builder()
|
ListedReply.ListedReplyBuilder builder = ListedReply.builder()
|
||||||
.reply(reply);
|
.reply(reply);
|
||||||
return getOwnerInfo(reply)
|
return getOwnerInfo(reply.getSpec().getOwner())
|
||||||
.map(ownerInfo -> {
|
.map(ownerInfo -> {
|
||||||
builder.owner(ownerInfo);
|
builder.owner(ownerInfo);
|
||||||
return builder;
|
return builder;
|
||||||
})
|
})
|
||||||
.map(ListedReply.ListedReplyBuilder::build)
|
.map(ListedReply.ListedReplyBuilder::build)
|
||||||
.flatMap(listedReply -> fetchStats(reply)
|
.flatMap(listedReply -> fetchReplyStats(reply.getMetadata().getName())
|
||||||
.doOnNext(listedReply::setStats)
|
.doOnNext(listedReply::setStats)
|
||||||
.thenReturn(listedReply));
|
.thenReturn(listedReply));
|
||||||
}
|
}
|
||||||
|
|
||||||
Mono<CommentStats> fetchStats(Reply reply) {
|
|
||||||
Assert.notNull(reply, "The reply must not be null.");
|
|
||||||
String name = reply.getMetadata().getName();
|
|
||||||
return counterService.getByName(MeterUtils.nameOf(Reply.class, name))
|
|
||||||
.map(counter -> CommentStats.builder()
|
|
||||||
.upvote(counter.getUpvote())
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
.defaultIfEmpty(CommentStats.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Mono<OwnerInfo> getOwnerInfo(Reply reply) {
|
|
||||||
Comment.CommentOwner owner = reply.getSpec().getOwner();
|
|
||||||
if (User.KIND.equals(owner.getKind())) {
|
|
||||||
return userService.getUserOrGhost(owner.getName())
|
|
||||||
.map(OwnerInfo::from);
|
|
||||||
}
|
|
||||||
if (Comment.CommentOwner.KIND_EMAIL.equals(owner.getKind())) {
|
|
||||||
return Mono.just(OwnerInfo.from(owner));
|
|
||||||
}
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"Unsupported owner kind: " + owner.getKind());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Comment.CommentOwner toCommentOwner(User user) {
|
|
||||||
Comment.CommentOwner owner = new Comment.CommentOwner();
|
|
||||||
owner.setKind(User.KIND);
|
|
||||||
owner.setName(user.getMetadata().getName());
|
|
||||||
owner.setDisplayName(user.getSpec().getDisplayName());
|
|
||||||
return owner;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Mono<User> fetchCurrentUser() {
|
|
||||||
return ReactiveSecurityContextHolder.getContext()
|
|
||||||
.map(securityContext -> securityContext.getAuthentication().getName())
|
|
||||||
.flatMap(username -> client.fetch(User.class, username));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue