Merge remote-tracking branch 'upstream/main' into refactor/setting-config-update

pull/6661/head
guqing 2024-09-24 11:17:13 +08:00
commit 9000ad3bb7
191 changed files with 1485 additions and 658 deletions

View File

@ -1,5 +1,6 @@
package run.halo.app.plugin.extensionpoint;
import java.util.List;
import org.pf4j.ExtensionPoint;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@ -34,4 +35,14 @@ public interface ExtensionGetter {
* @return a bunch of extension points.
*/
<T extends ExtensionPoint> Flux<T> getExtensions(Class<T> extensionPointClass);
/**
* Get all extensions according to extension point class.
*
* @param extensionPointClass extension point class
* @param <T> type of extension point
* @return a bunch of extension points.
*/
<T extends ExtensionPoint> List<T> getExtensionList(Class<T> extensionPointClass);
}

View File

@ -0,0 +1,41 @@
package run.halo.app.theme.dialect;
import org.pf4j.ExtensionPoint;
import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.model.IProcessableElementTag;
import reactor.core.publisher.Mono;
/**
* An extension point for post-processing element tag.
*
* @author johnniang
* @since 2.20.0
*/
public interface ElementTagPostProcessor extends ExtensionPoint {
/**
* <p>
* Execute the processor.
* </p>
* <p>
* The {@link IProcessableElementTag} object argument is immutable, so all modifications to
* this object or any
* instructions to be given to the engine should be done through the specified
* {@link org.thymeleaf.model.IModelFactory} model factory in context.
* </p>
* <p>
* Don't forget to return the new tag after processing or
* {@link reactor.core.publisher.Mono#empty()} if not processable.
* </p>
*
* @param context the template context.
* @param tag the event this processor is executing on.
* @return a {@link reactor.core.publisher.Mono} that will complete when processing finishes
* or empty mono if not support.
*/
Mono<IProcessableElementTag> process(
ITemplateContext context,
final IProcessableElementTag tag
);
}

View File

@ -8,8 +8,8 @@ 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.core.user.service.RoleService;
import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.metrics.CounterService;
import run.halo.app.metrics.MeterUtils;

View File

@ -17,8 +17,8 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
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.core.user.service.RoleService;
import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.Extension;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ListResult;

View File

@ -22,8 +22,8 @@ import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
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.core.user.service.RoleService;
import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.PageRequest;

View File

@ -34,7 +34,7 @@ import run.halo.app.core.extension.content.Category;
import run.halo.app.core.extension.content.Post;
import run.halo.app.core.extension.content.Snapshot;
import run.halo.app.core.extension.content.Tag;
import run.halo.app.core.extension.service.UserService;
import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.MetadataOperator;

View File

@ -28,7 +28,7 @@ import run.halo.app.content.Stats;
import run.halo.app.core.extension.content.Post;
import run.halo.app.core.extension.content.SinglePage;
import run.halo.app.core.extension.content.Snapshot;
import run.halo.app.core.extension.service.UserService;
import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.extension.Ref;

View File

@ -6,7 +6,7 @@ import java.nio.file.Path;
import org.springframework.core.io.Resource;
import org.springframework.lang.NonNull;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.attachment.LocalThumbnail;
import run.halo.app.core.attachment.extension.LocalThumbnail;
import run.halo.app.infra.ExternalLinkProcessor;
import run.halo.app.infra.exception.NotFoundException;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.attachment.endpoint;
package run.halo.app.core.attachment.endpoint;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.attachment.endpoint;
package run.halo.app.core.attachment.endpoint;
import static java.nio.file.StandardOpenOption.CREATE_NEW;
import static run.halo.app.infra.utils.FileNameUtils.randomFileName;
@ -41,6 +41,7 @@ import run.halo.app.core.extension.attachment.Attachment;
import run.halo.app.core.extension.attachment.Attachment.AttachmentSpec;
import run.halo.app.core.extension.attachment.Constant;
import run.halo.app.core.extension.attachment.Policy;
import run.halo.app.core.extension.attachment.endpoint.AttachmentHandler;
import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.Metadata;
import run.halo.app.infra.ExternalUrlSupplier;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.attachment;
package run.halo.app.core.attachment.extension;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.attachment;
package run.halo.app.core.attachment.extension;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;

View File

@ -38,7 +38,7 @@ import run.halo.app.core.attachment.LocalThumbnailService;
import run.halo.app.core.attachment.ThumbnailGenerator;
import run.halo.app.core.attachment.ThumbnailSigner;
import run.halo.app.core.attachment.ThumbnailSize;
import run.halo.app.core.extension.attachment.LocalThumbnail;
import run.halo.app.core.attachment.extension.LocalThumbnail;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.Metadata;

View File

@ -20,7 +20,7 @@ import run.halo.app.core.attachment.ThumbnailProvider.ThumbnailContext;
import run.halo.app.core.attachment.ThumbnailService;
import run.halo.app.core.attachment.ThumbnailSigner;
import run.halo.app.core.attachment.ThumbnailSize;
import run.halo.app.core.extension.attachment.Thumbnail;
import run.halo.app.core.attachment.extension.Thumbnail;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.Metadata;

View File

@ -1,7 +1,7 @@
package run.halo.app.core.attachment.reconciler;
import static org.springframework.data.domain.Sort.Order.desc;
import static run.halo.app.core.extension.attachment.LocalThumbnail.REQUEST_TO_GENERATE_ANNO;
import static run.halo.app.core.attachment.extension.LocalThumbnail.REQUEST_TO_GENERATE_ANNO;
import static run.halo.app.extension.MetadataUtil.nullSafeAnnotations;
import static run.halo.app.extension.index.query.QueryFactory.and;
import static run.halo.app.extension.index.query.QueryFactory.equal;
@ -23,9 +23,9 @@ import run.halo.app.core.attachment.AttachmentRootGetter;
import run.halo.app.core.attachment.AttachmentUtils;
import run.halo.app.core.attachment.LocalThumbnailService;
import run.halo.app.core.attachment.ThumbnailGenerator;
import run.halo.app.core.attachment.extension.LocalThumbnail;
import run.halo.app.core.extension.attachment.Attachment;
import run.halo.app.core.extension.attachment.Constant;
import run.halo.app.core.extension.attachment.LocalThumbnail;
import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.ExtensionUtil;
import run.halo.app.extension.ListOptions;

View File

@ -19,7 +19,7 @@ import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.pattern.PathPattern;
import reactor.core.publisher.Mono;
import run.halo.app.console.WebSocketUtils;
import run.halo.app.infra.console.WebSocketUtils;
public class WebSocketHandlerMapping extends AbstractHandlerMapping
implements WebSocketEndpointManager, InitializingBean {

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.endpoint;
package run.halo.app.core.endpoint.console;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;
@ -12,6 +12,7 @@ import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.AuthProvider;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.security.AuthProviderService;
import run.halo.app.security.ListedAuthProvider;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.endpoint;
package run.halo.app.core.endpoint.console;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.content.Builder.contentBuilder;
@ -23,6 +23,7 @@ import run.halo.app.content.comment.ReplyRequest;
import run.halo.app.content.comment.ReplyService;
import run.halo.app.core.extension.content.Comment;
import run.halo.app.core.extension.content.Reply;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.extension.ListResult;
import run.halo.app.infra.utils.HaloUtils;
import run.halo.app.infra.utils.IpAddressUtils;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.endpoint;
package run.halo.app.core.endpoint.console;
import java.util.HashMap;
import java.util.LinkedList;
@ -9,6 +9,7 @@ import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.extension.GroupVersion;
public class CustomEndpointsBuilder {

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.endpoint;
package run.halo.app.core.endpoint.console;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
@ -62,16 +62,17 @@ import reactor.core.scheduler.Schedulers;
import reactor.util.retry.Retry;
import run.halo.app.core.extension.Plugin;
import run.halo.app.core.extension.Setting;
import run.halo.app.core.extension.service.PluginService;
import run.halo.app.core.extension.service.SettingConfigService;
import run.halo.app.core.extension.theme.SettingUtils;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.core.user.service.SettingConfigService;
import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.extension.router.IListRequest;
import run.halo.app.extension.router.SortableRequest;
import run.halo.app.infra.ReactiveUrlDataBufferFetcher;
import run.halo.app.infra.utils.SettingUtils;
import run.halo.app.plugin.PluginNotFoundException;
import run.halo.app.plugin.PluginService;
@Slf4j
@Component

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.endpoint;
package run.halo.app.core.endpoint.console;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.content.Builder.contentBuilder;
@ -37,6 +37,7 @@ import run.halo.app.content.PostQuery;
import run.halo.app.content.PostRequest;
import run.halo.app.content.PostService;
import run.halo.app.core.extension.content.Post;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.MetadataUtil;
import run.halo.app.extension.ReactiveExtensionClient;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.endpoint;
package run.halo.app.core.endpoint.console;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
@ -12,6 +12,7 @@ import run.halo.app.content.comment.ListedReply;
import run.halo.app.content.comment.ReplyQuery;
import run.halo.app.content.comment.ReplyService;
import run.halo.app.core.extension.content.Reply;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.extension.ListResult;
/**

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.endpoint;
package run.halo.app.core.endpoint.console;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.content.Builder.contentBuilder;
@ -33,6 +33,7 @@ import run.halo.app.content.SinglePageRequest;
import run.halo.app.content.SinglePageService;
import run.halo.app.core.extension.content.Post;
import run.halo.app.core.extension.content.SinglePage;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.MetadataUtil;
import run.halo.app.extension.ReactiveExtensionClient;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.endpoint;
package run.halo.app.core.endpoint.console;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static run.halo.app.extension.index.query.QueryFactory.and;
@ -15,6 +15,7 @@ import reactor.core.publisher.Mono;
import run.halo.app.core.extension.Counter;
import run.halo.app.core.extension.User;
import run.halo.app.core.extension.content.Post;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.PageRequestImpl;
import run.halo.app.extension.ReactiveExtensionClient;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.endpoint;
package run.halo.app.core.endpoint.console;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
@ -25,6 +25,7 @@ import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebInputException;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.InitializationStateGetter;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.endpoint;
package run.halo.app.core.endpoint.console;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;
@ -19,6 +19,7 @@ import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.content.Tag;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.PageRequestImpl;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.endpoint;
package run.halo.app.core.endpoint.console;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.content.Builder.contentBuilder;
@ -16,6 +16,7 @@ import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.event.post.DownvotedEvent;
import run.halo.app.event.post.UpvotedEvent;
import run.halo.app.event.post.VisitedEvent;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.endpoint;
package run.halo.app.core.endpoint.console;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
@ -70,10 +70,11 @@ import reactor.util.retry.Retry;
import run.halo.app.core.extension.Role;
import run.halo.app.core.extension.User;
import run.halo.app.core.extension.attachment.Attachment;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.core.extension.service.AttachmentService;
import run.halo.app.core.extension.service.EmailVerificationService;
import run.halo.app.core.extension.service.RoleService;
import run.halo.app.core.extension.service.UserService;
import run.halo.app.core.user.service.EmailVerificationService;
import run.halo.app.core.user.service.RoleService;
import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.Metadata;

View File

@ -1,8 +1,8 @@
package run.halo.app.theme.endpoint;
package run.halo.app.core.endpoint.theme;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;
import static run.halo.app.theme.endpoint.PublicApiUtils.toAnotherListResult;
import static run.halo.app.core.endpoint.theme.PublicApiUtils.toAnotherListResult;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import lombok.RequiredArgsConstructor;

View File

@ -1,4 +1,4 @@
package run.halo.app.theme.endpoint;
package run.halo.app.core.endpoint.theme;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import static org.apache.commons.lang3.BooleanUtils.isFalse;

View File

@ -1,4 +1,4 @@
package run.halo.app.theme.endpoint;
package run.halo.app.core.endpoint.theme;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;

View File

@ -1,4 +1,4 @@
package run.halo.app.theme.endpoint;
package run.halo.app.core.endpoint.theme;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;

View File

@ -1,4 +1,4 @@
package run.halo.app.theme.endpoint;
package run.halo.app.core.endpoint.theme;
import org.springdoc.core.fn.builders.operation.Builder;
import org.springframework.web.server.ServerWebExchange;

View File

@ -1,4 +1,4 @@
package run.halo.app.theme.endpoint;
package run.halo.app.core.endpoint.theme;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;

View File

@ -1,4 +1,4 @@
package run.halo.app.theme.endpoint;
package run.halo.app.core.endpoint.theme;
import java.util.Collection;
import java.util.List;

View File

@ -1,4 +1,4 @@
package run.halo.app.theme.endpoint;
package run.halo.app.core.endpoint.theme;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
@ -30,9 +30,9 @@ import org.springframework.web.server.ServerWebInputException;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.User;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.core.extension.service.EmailPasswordRecoveryService;
import run.halo.app.core.extension.service.EmailVerificationService;
import run.halo.app.core.extension.service.UserService;
import run.halo.app.core.user.service.EmailPasswordRecoveryService;
import run.halo.app.core.user.service.EmailVerificationService;
import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.GroupVersion;
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
import run.halo.app.infra.SystemSetting;

View File

@ -1,4 +1,4 @@
package run.halo.app.theme.endpoint;
package run.halo.app.core.endpoint.theme;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;

View File

@ -1,4 +1,4 @@
package run.halo.app.theme.endpoint;
package run.halo.app.core.endpoint.theme;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;

View File

@ -1,4 +1,4 @@
package run.halo.app.theme.endpoint;
package run.halo.app.core.endpoint.theme;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;

View File

@ -1,4 +1,4 @@
package run.halo.app.theme.endpoint;
package run.halo.app.core.endpoint.theme;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;

View File

@ -1,4 +1,4 @@
package run.halo.app.endpoint.uc.content;
package run.halo.app.core.endpoint.uc;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;

View File

@ -1,4 +1,4 @@
package run.halo.app.endpoint.uc.content;
package run.halo.app.core.endpoint.uc;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;

View File

@ -1,4 +1,4 @@
package run.halo.app.endpoint.uc.content;
package run.halo.app.core.endpoint.uc;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import java.util.Map;
import lombok.AllArgsConstructor;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.BooleanUtils;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import static run.halo.app.extension.ExtensionUtil.addFinalizers;
import static run.halo.app.extension.ExtensionUtil.removeFinalizers;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
import static run.halo.app.extension.ExtensionUtil.addFinalizers;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import java.time.Duration;
import java.util.Objects;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import static run.halo.app.core.extension.Plugin.PluginStatus.nullSafeConditions;
import static run.halo.app.extension.ExtensionUtil.addFinalizers;
@ -44,7 +44,6 @@ import org.springframework.web.util.UriComponentsBuilder;
import run.halo.app.core.extension.Plugin;
import run.halo.app.core.extension.ReverseProxy;
import run.halo.app.core.extension.Setting;
import run.halo.app.core.extension.theme.SettingUtils;
import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.ExtensionUtil;
@ -59,6 +58,7 @@ import run.halo.app.infra.Condition;
import run.halo.app.infra.ConditionList;
import run.halo.app.infra.ConditionStatus;
import run.halo.app.infra.utils.PathUtils;
import run.halo.app.infra.utils.SettingUtils;
import run.halo.app.infra.utils.YamlUnstructuredLoader;
import run.halo.app.plugin.PluginConst;
import run.halo.app.plugin.PluginProperties;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import static run.halo.app.extension.index.query.QueryFactory.startsWith;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.commons.lang3.BooleanUtils.TRUE;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
import static run.halo.app.extension.ExtensionUtil.addFinalizers;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import java.util.HashSet;
import java.util.Map;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import static java.util.Objects.deepEquals;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.web.util.UriUtils.encodePath;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import java.util.HashMap;
import java.util.HashSet;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import static run.halo.app.extension.ExtensionUtil.addFinalizers;
import static run.halo.app.extension.ExtensionUtil.removeFinalizers;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
@ -17,7 +17,6 @@ import org.springframework.util.FileSystemUtils;
import run.halo.app.core.extension.AnnotationSetting;
import run.halo.app.core.extension.Setting;
import run.halo.app.core.extension.Theme;
import run.halo.app.core.extension.theme.SettingUtils;
import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.MetadataUtil;
import run.halo.app.extension.controller.Controller;
@ -30,6 +29,7 @@ import run.halo.app.infra.SystemVersionSupplier;
import run.halo.app.infra.ThemeRootGetter;
import run.halo.app.infra.exception.ThemeUninstallException;
import run.halo.app.infra.utils.JsonUtils;
import run.halo.app.infra.utils.SettingUtils;
import run.halo.app.infra.utils.VersionUtils;
/**

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.reconciler;
package run.halo.app.core.reconciler;
import static run.halo.app.extension.ExtensionUtil.addFinalizers;
import static run.halo.app.extension.ExtensionUtil.defaultSort;
@ -23,8 +23,8 @@ import run.halo.app.core.extension.User;
import run.halo.app.core.extension.UserConnection;
import run.halo.app.core.extension.attachment.Attachment;
import run.halo.app.core.extension.service.AttachmentService;
import run.halo.app.core.extension.service.RoleService;
import run.halo.app.core.extension.service.UserService;
import run.halo.app.core.user.service.RoleService;
import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.controller.Controller;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.service;
package run.halo.app.core.user.service;
import static run.halo.app.extension.ExtensionUtil.defaultSort;
import static run.halo.app.extension.ExtensionUtil.notDeleting;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.service;
package run.halo.app.core.user.service;
import reactor.core.publisher.Mono;
import run.halo.app.infra.exception.AccessDeniedException;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.service;
package run.halo.app.core.user.service;
import reactor.core.publisher.Mono;
import run.halo.app.infra.exception.EmailVerificationFailed;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.service;
package run.halo.app.core.user.service;
import java.util.Collection;
import java.util.Map;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.service;
package run.halo.app.core.user.service;
import com.fasterxml.jackson.databind.node.ObjectNode;
import reactor.core.publisher.Mono;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.service;
package run.halo.app.core.user.service;
import java.util.Set;
import reactor.core.publisher.Flux;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.service;
package run.halo.app.core.user.service;
import static org.springframework.data.domain.Sort.Order.asc;
import static org.springframework.data.domain.Sort.Order.desc;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.service.impl;
package run.halo.app.core.user.service.impl;
import java.net.URI;
import java.net.URL;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.service.impl;
package run.halo.app.core.user.service.impl;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
@ -18,8 +18,8 @@ import reactor.util.retry.Retry;
import run.halo.app.core.extension.User;
import run.halo.app.core.extension.notification.Reason;
import run.halo.app.core.extension.notification.Subscription;
import run.halo.app.core.extension.service.EmailPasswordRecoveryService;
import run.halo.app.core.extension.service.UserService;
import run.halo.app.core.user.service.EmailPasswordRecoveryService;
import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.GroupVersion;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.ExternalLinkProcessor;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.service.impl;
package run.halo.app.core.user.service.impl;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
@ -19,8 +19,8 @@ import reactor.util.retry.Retry;
import run.halo.app.core.extension.User;
import run.halo.app.core.extension.notification.Reason;
import run.halo.app.core.extension.notification.Subscription;
import run.halo.app.core.extension.service.EmailVerificationService;
import run.halo.app.core.extension.service.UserService;
import run.halo.app.core.user.service.EmailVerificationService;
import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.GroupVersion;
import run.halo.app.extension.MetadataUtil;
import run.halo.app.extension.ReactiveExtensionClient;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.service.impl;
package run.halo.app.core.user.service.impl;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.time.Duration;
@ -9,11 +9,11 @@ import org.springframework.util.Assert;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
import run.halo.app.core.extension.Setting;
import run.halo.app.core.extension.service.SettingConfigService;
import run.halo.app.core.extension.theme.SettingUtils;
import run.halo.app.core.user.service.SettingConfigService;
import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.Metadata;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.utils.SettingUtils;
/**
* {@link Setting} related {@link ConfigMap} service implementation.

View File

@ -26,9 +26,9 @@ public class DefaultSystemVersionSupplier implements SystemVersionSupplier {
public Version get() {
var properties = buildProperties.getIfUnique();
if (properties == null) {
return Version.valueOf(DEFAULT_VERSION);
return Version.parse(DEFAULT_VERSION);
}
var projectVersion = Objects.toString(properties.getVersion(), DEFAULT_VERSION);
return Version.valueOf(projectVersion);
return Version.parse(projectVersion);
}
}

View File

@ -10,10 +10,10 @@ import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StreamUtils;
import run.halo.app.core.extension.theme.ThemeService;
import run.halo.app.infra.properties.HaloProperties;
import run.halo.app.infra.properties.ThemeProperties;
import run.halo.app.infra.utils.FileUtils;
import run.halo.app.theme.service.ThemeService;
@Slf4j
@Component

View File

@ -20,6 +20,8 @@ import org.springframework.context.ApplicationListener;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import run.halo.app.content.Stats;
import run.halo.app.core.attachment.extension.LocalThumbnail;
import run.halo.app.core.attachment.extension.Thumbnail;
import run.halo.app.core.extension.AnnotationSetting;
import run.halo.app.core.extension.AuthProvider;
import run.halo.app.core.extension.Counter;
@ -38,10 +40,8 @@ import run.halo.app.core.extension.UserConnection;
import run.halo.app.core.extension.UserConnection.UserConnectionSpec;
import run.halo.app.core.extension.attachment.Attachment;
import run.halo.app.core.extension.attachment.Group;
import run.halo.app.core.extension.attachment.LocalThumbnail;
import run.halo.app.core.extension.attachment.Policy;
import run.halo.app.core.extension.attachment.PolicyTemplate;
import run.halo.app.core.extension.attachment.Thumbnail;
import run.halo.app.core.extension.content.Category;
import run.halo.app.core.extension.content.Comment;
import run.halo.app.core.extension.content.Post;

View File

@ -0,0 +1,26 @@
package run.halo.app.infra;
import org.springframework.lang.NonNull;
import org.springframework.web.reactive.HandlerResult;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* Secure request mapping handler adapter.
*
* @author johnniang
* @since 2.20.0
*/
public class SecureRequestMappingHandlerAdapter extends RequestMappingHandlerAdapter {
@Override
@NonNull
public Mono<HandlerResult> handle(
@NonNull ServerWebExchange exchange,
@NonNull Object handler
) {
return super.handle(new SecureServerWebExchange(exchange), handler);
}
}

View File

@ -0,0 +1,31 @@
package run.halo.app.infra;
import org.springframework.lang.NonNull;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.support.ServerRequestWrapper;
import org.springframework.web.server.ServerWebExchange;
/**
* Secure server request without application context available.
*
* @author johnniang
* @since 2.20.0
*/
public class SecureServerRequest extends ServerRequestWrapper {
/**
* Create a new {@code ServerRequestWrapper} that wraps the given request.
*
* @param delegate the request to wrap
*/
public SecureServerRequest(ServerRequest delegate) {
super(delegate);
}
@Override
@NonNull
public ServerWebExchange exchange() {
return new SecureServerWebExchange(super.exchange());
}
}

View File

@ -0,0 +1,25 @@
package run.halo.app.infra;
import org.springframework.context.ApplicationContext;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerWebExchangeDecorator;
/**
* Secure server web exchange without application context available.
*
* @author johnniang
* @since 2.20.0
*/
public class SecureServerWebExchange extends ServerWebExchangeDecorator {
public SecureServerWebExchange(ServerWebExchange delegate) {
super(delegate);
}
@Override
public ApplicationContext getApplicationContext() {
// Always return null to prevent access to application context
return null;
}
}

View File

@ -1,4 +1,4 @@
package run.halo.app.actuator;
package run.halo.app.infra.actuator;
import io.r2dbc.spi.Connection;
import io.r2dbc.spi.ConnectionFactory;

View File

@ -1,4 +1,4 @@
package run.halo.app.actuator;
package run.halo.app.infra.actuator;
import static org.apache.commons.lang3.BooleanUtils.isTrue;

View File

@ -1,4 +1,4 @@
package run.halo.app.actuator;
package run.halo.app.infra.actuator;
import java.io.Closeable;
import java.io.IOException;

View File

@ -1,4 +1,4 @@
package run.halo.app.config;
package run.halo.app.infra.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;

View File

@ -1,4 +1,4 @@
package run.halo.app.config;
package run.halo.app.infra.config;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.MapperFeature;

View File

@ -1,4 +1,4 @@
package run.halo.app.config;
package run.halo.app.infra.config;
import static org.springdoc.core.utils.Constants.SPRINGDOC_ENABLED;

View File

@ -1,4 +1,4 @@
package run.halo.app.config;
package run.halo.app.infra.config;
import static org.springframework.util.ResourceUtils.FILE_URL_PREFIX;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
@ -12,6 +12,7 @@ import java.util.List;
import java.util.Objects;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxRegistrations;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -33,18 +34,20 @@ import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.resource.EncodedResourceResolver;
import org.springframework.web.reactive.resource.PathResourceResolver;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.reactive.result.view.ViewResolutionResultHandler;
import org.springframework.web.reactive.result.view.ViewResolver;
import reactor.core.publisher.Mono;
import run.halo.app.console.ProxyFilter;
import run.halo.app.console.WebSocketRequestPredicate;
import run.halo.app.core.endpoint.WebSocketHandlerMapping;
import run.halo.app.core.endpoint.console.CustomEndpointsBuilder;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.core.extension.endpoint.CustomEndpointsBuilder;
import run.halo.app.infra.SecureRequestMappingHandlerAdapter;
import run.halo.app.infra.console.ProxyFilter;
import run.halo.app.infra.console.WebSocketRequestPredicate;
import run.halo.app.infra.properties.AttachmentProperties;
import run.halo.app.infra.properties.HaloProperties;
import run.halo.app.infra.webfilter.AdditionalWebFilterChainProxy;
import run.halo.app.plugin.extensionpoint.ExtensionGetter;
import run.halo.app.webfilter.AdditionalWebFilterChainProxy;
@Configuration
public class WebFluxConfig implements WebFluxConfigurer {
@ -67,6 +70,19 @@ public class WebFluxConfig implements WebFluxConfigurer {
this.applicationContext = applicationContext;
}
@Bean
WebFluxRegistrations webFluxRegistrations() {
return new WebFluxRegistrations() {
@Override
public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
// Because we have no chance to customize ServerWebExchangeMethodArgumentResolver,
// we have to use SecureRequestMappingHandlerAdapter to replace a secure
// ServerWebExchange.
return new SecureRequestMappingHandlerAdapter();
}
};
}
@Bean
ServerResponse.Context context(CodecConfigurer codec,
ViewResolutionResultHandler resultHandler) {

View File

@ -1,4 +1,4 @@
package run.halo.app.config;
package run.halo.app.infra.config;
import static org.springframework.security.config.Customizer.withDefaults;
import static org.springframework.security.web.server.authentication.ServerWebExchangeDelegatingReactiveAuthenticationManagerResolver.builder;
@ -22,8 +22,8 @@ import org.springframework.session.MapSession;
import org.springframework.session.config.annotation.web.server.EnableSpringWebSession;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import run.halo.app.core.extension.service.RoleService;
import run.halo.app.core.extension.service.UserService;
import run.halo.app.core.user.service.RoleService;
import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.AnonymousUserConst;
import run.halo.app.infra.properties.HaloProperties;

View File

@ -1,4 +1,4 @@
package run.halo.app.console;
package run.halo.app.infra.console;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.buffer.DataBuffer;

View File

@ -1,6 +1,6 @@
package run.halo.app.console;
package run.halo.app.infra.console;
import static run.halo.app.console.WebSocketUtils.isWebSocketUpgrade;
import static run.halo.app.infra.console.WebSocketUtils.isWebSocketUpgrade;
import org.springframework.web.reactive.function.server.RequestPredicate;
import org.springframework.web.reactive.function.server.ServerRequest;

View File

@ -1,8 +1,8 @@
package run.halo.app.console;
package run.halo.app.infra.console;
import static org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher.MatchResult.match;
import static org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher.MatchResult.notMatch;
import static run.halo.app.console.WebSocketUtils.isWebSocketUpgrade;
import static run.halo.app.infra.console.WebSocketUtils.isWebSocketUpgrade;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.web.server.ServerWebExchange;

View File

@ -1,4 +1,4 @@
package run.halo.app.console;
package run.halo.app.infra.console;
import java.util.Objects;
import org.springframework.http.HttpHeaders;

View File

@ -0,0 +1,62 @@
package run.halo.app.infra.utils;
import java.time.Duration;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* Utility class for reactive.
*
* @author johnniang
* @since 2.20.0
*/
public enum ReactiveUtils {
;
private static final Duration DEFAULT_TIMEOUT = Duration.ofMinutes(1);
/**
* Resolve reactive value by blocking operation.
*
* @param value the normal value or reactive value
* @return the resolved value
*/
@Nullable
public static Object blockReactiveValue(@Nullable Object value) {
return blockReactiveValue(value, DEFAULT_TIMEOUT);
}
/**
* Resolve reactive value by blocking operation.
*
* @param value the normal value or reactive value
* @param timeout the timeout of blocking operation
* @return the resolved value
*/
@Nullable
public static Object blockReactiveValue(@Nullable Object value, @NonNull Duration timeout) {
if (value == null) {
return null;
}
Class<?> clazz = value.getClass();
if (Mono.class.isAssignableFrom(clazz)) {
return ((Mono<?>) value).blockOptional(timeout).orElse(null);
}
if (Flux.class.isAssignableFrom(clazz)) {
return ((Flux<?>) value).collectList().block(timeout);
}
return value;
}
/**
* Check if the class is a reactive type.
*
* @param clazz the class to check
* @return true if the class is a reactive type, false otherwise
*/
public static boolean isReactiveType(@NonNull Class<?> clazz) {
return Mono.class.isAssignableFrom(clazz) || Flux.class.isAssignableFrom(clazz);
}
}

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.theme;
package run.halo.app.infra.utils;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
@ -21,8 +21,6 @@ import run.halo.app.core.extension.Setting;
import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.Metadata;
import run.halo.app.infra.utils.JsonParseException;
import run.halo.app.infra.utils.JsonUtils;
@UtilityClass
public class SettingUtils {

View File

@ -41,7 +41,7 @@ public class VersionUtils {
try {
return StringUtils.isBlank(constraint)
|| "*".equals(constraint)
|| Version.valueOf(version).satisfies(constraint);
|| Version.parse(version).satisfies(constraint);
} catch (Exception e) {
throw new ServerWebInputException("Illegal requires version expression.", null, e);
}

View File

@ -1,4 +1,4 @@
package run.halo.app.webfilter;
package run.halo.app.infra.webfilter;
import lombok.Setter;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;

View File

@ -0,0 +1,59 @@
package run.halo.app.infra.webfilter;
import static run.halo.app.theme.ThemeLocaleContextResolver.LANGUAGE_COOKIE_NAME;
import static run.halo.app.theme.ThemeLocaleContextResolver.LANGUAGE_PARAMETER_NAME;
import java.util.Locale;
import java.util.Set;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseCookie;
import org.springframework.lang.NonNull;
import org.springframework.security.web.server.util.matcher.AndServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.MediaTypeServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher.MatchResult;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
@Component
public class LocaleChangeWebFilter implements WebFilter {
private final ServerWebExchangeMatcher matcher;
public LocaleChangeWebFilter() {
var pathMatcher = ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, "/**");
var textHtmlMatcher = new MediaTypeServerWebExchangeMatcher(MediaType.TEXT_HTML);
textHtmlMatcher.setIgnoredMediaTypes(Set.of(MediaType.ALL));
matcher = new AndServerWebExchangeMatcher(pathMatcher, textHtmlMatcher);
}
@Override
@NonNull
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
var request = exchange.getRequest();
return matcher.matches(exchange)
.filter(MatchResult::isMatch)
.doOnNext(result -> {
var language = request
.getQueryParams()
.getFirst(LANGUAGE_PARAMETER_NAME);
if (StringUtils.hasText(language)) {
var locale = Locale.forLanguageTag(language);
exchange.getResponse()
.addCookie(ResponseCookie.from(LANGUAGE_COOKIE_NAME, locale.toLanguageTag())
.path("/")
.secure(true)
.build()
);
}
})
.then(Mono.defer(() -> chain.filter(exchange)));
}
}

View File

@ -5,7 +5,9 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
@ -40,13 +42,16 @@ public class DefaultNotificationTemplateRender implements NotificationTemplateRe
@Override
public Mono<String> render(String template, Map<String, Object> model) {
var context = new Context(Locale.getDefault(), model);
var externalUrl = Optional.ofNullable(externalUrlSupplier.getRaw())
.map(url -> StringUtils.removeEnd(url.toString(), "/"))
.orElse(StringUtils.EMPTY);
var globalAttributeMono = getBasicSetting()
.doOnNext(basic -> {
var site = new HashMap<>();
site.put("title", basic.getTitle());
site.put("logo", basic.getLogo());
site.put("subtitle", basic.getSubtitle());
site.put("url", externalUrlSupplier.getRaw());
site.put("url", externalUrl);
context.setVariable("site", site);
});
return Mono.when(globalAttributeMono)

View File

@ -7,8 +7,9 @@ import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import run.halo.app.core.endpoint.console.CustomEndpointsBuilder;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.core.extension.endpoint.CustomEndpointsBuilder;
import run.halo.app.infra.SecureServerRequest;
/**
* Aggregated router function built from all custom endpoints.
@ -28,7 +29,7 @@ public class AggregatedRouterFunction implements RouterFunction<ServerResponse>
@Override
public Mono<HandlerFunction<ServerResponse>> route(ServerRequest request) {
return aggregated.route(request);
return aggregated.route(new SecureServerRequest(request));
}
@Override

View File

@ -11,6 +11,7 @@ import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import run.halo.app.infra.SecureServerRequest;
/**
* A composite {@link RouterFunction} implementation for plugin.
@ -31,8 +32,9 @@ public class DefaultPluginRouterFunctionRegistry
@Override
@NonNull
public Mono<HandlerFunction<ServerResponse>> route(@NonNull ServerRequest request) {
var secureRequest = new SecureServerRequest(request);
return Flux.fromIterable(this.routerFunctions)
.concatMap(routerFunction -> routerFunction.route(request))
.concatMap(routerFunction -> routerFunction.route(secureRequest))
.next();
}

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.service;
package run.halo.app.plugin;
import java.nio.file.Path;
import org.springframework.core.io.Resource;

View File

@ -1,4 +1,4 @@
package run.halo.app.core.extension.service.impl;
package run.halo.app.plugin;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import static java.nio.file.StandardOpenOption.CREATE;
@ -40,6 +40,7 @@ import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.StreamUtils;
import org.springframework.web.server.ServerWebInputException;
import reactor.core.Exceptions;
import reactor.core.publisher.Flux;
@ -48,7 +49,6 @@ import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;
import reactor.util.retry.Retry;
import run.halo.app.core.extension.Plugin;
import run.halo.app.core.extension.service.PluginService;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.SystemVersionSupplier;
import run.halo.app.infra.exception.PluginAlreadyExistsException;
@ -59,12 +59,6 @@ import run.halo.app.infra.exception.PluginInstallationException;
import run.halo.app.infra.exception.UnsatisfiedAttributeValueException;
import run.halo.app.infra.utils.FileUtils;
import run.halo.app.infra.utils.VersionUtils;
import run.halo.app.plugin.PluginConst;
import run.halo.app.plugin.PluginUtils;
import run.halo.app.plugin.PluginsRootGetter;
import run.halo.app.plugin.SpringPluginManager;
import run.halo.app.plugin.YamlPluginDescriptorFinder;
import run.halo.app.plugin.YamlPluginFinder;
import run.halo.app.plugin.resources.BundleResourceUtils;
@Slf4j
@ -229,61 +223,73 @@ public class PluginServiceImpl implements PluginService, InitializingBean, Dispo
@Override
public Flux<DataBuffer> uglifyJsBundle() {
var startedPlugins = List.copyOf(pluginManager.getStartedPlugins());
String plugins = """
this.enabledPlugins = [%s]
""".formatted(startedPlugins.stream()
.map(plugin -> """
{
"name": "%s",
"version": "%s"
}
""".formatted(plugin.getPluginId(), plugin.getDescriptor().getVersion())
var dataBufferFactory = DefaultDataBufferFactory.sharedInstance;
var end = Mono.fromSupplier(
() -> {
var sb = new StringBuilder("this.enabledPlugins = [");
var iterator = startedPlugins.iterator();
while (iterator.hasNext()) {
var plugin = iterator.next();
sb.append("""
{"name":"%s","version":"%s"}\
"""
.formatted(
plugin.getPluginId(),
plugin.getDescriptor().getVersion()
)
.collect(Collectors.joining(", ")));
return Flux.fromIterable(startedPlugins)
.mapNotNull(pluginWrapper -> {
var pluginName = pluginWrapper.getPluginId();
return BundleResourceUtils.getJsBundleResource(pluginManager, pluginName,
BundleResourceUtils.JS_BUNDLE);
})
.flatMap(resource -> {
try {
// Specifying bufferSize as resource content length is
// to append line breaks at the end of each plugin
return DataBufferUtils.read(resource, DefaultDataBufferFactory.sharedInstance,
(int) resource.contentLength())
.doOnNext(dataBuffer -> {
// add a new line after each plugin bundle to avoid syntax error
dataBuffer.write("\n".getBytes(StandardCharsets.UTF_8));
});
} catch (IOException e) {
log.error("Failed to read plugin bundle resource", e);
return Flux.empty();
);
if (iterator.hasNext()) {
sb.append(',');
}
})
.concatWith(Flux.defer(() -> {
var dataBuffer = DefaultDataBufferFactory.sharedInstance
.wrap(plugins.getBytes(StandardCharsets.UTF_8));
return Flux.just(dataBuffer);
}));
}
sb.append(']');
return dataBufferFactory.wrap(sb.toString().getBytes(StandardCharsets.UTF_8));
});
var body = Flux.fromIterable(startedPlugins)
.sort(Comparator.comparing(PluginWrapper::getPluginId))
.concatMap(pluginWrapper -> {
var pluginId = pluginWrapper.getPluginId();
return Mono.<Resource>fromSupplier(
() -> BundleResourceUtils.getJsBundleResource(
pluginManager, pluginId, BundleResourceUtils.JS_BUNDLE
)
)
.filter(Resource::isReadable)
.flatMapMany(resource -> {
var head = Mono.<DataBuffer>fromSupplier(
() -> dataBufferFactory.wrap(
("// Generated from plugin " + pluginId + "\n").getBytes()
));
var content = DataBufferUtils.read(
resource, dataBufferFactory, StreamUtils.BUFFER_SIZE
);
var tail = Mono.fromSupplier(() -> dataBufferFactory.wrap("\n".getBytes()));
return Flux.concat(head, content, tail);
});
});
return Flux.concat(body, end);
}
@Override
public Flux<DataBuffer> uglifyCssBundle() {
return Flux.fromIterable(pluginManager.getStartedPlugins())
.mapNotNull(pluginWrapper -> {
String pluginName = pluginWrapper.getPluginId();
return BundleResourceUtils.getJsBundleResource(pluginManager, pluginName,
BundleResourceUtils.CSS_BUNDLE);
})
.flatMap(resource -> {
try {
return DataBufferUtils.read(resource, DefaultDataBufferFactory.sharedInstance,
(int) resource.contentLength());
} catch (IOException e) {
log.error("Failed to read plugin css bundle resource", e);
return Flux.empty();
}
.sort(Comparator.comparing(PluginWrapper::getPluginId))
.concatMap(pluginWrapper -> {
var pluginId = pluginWrapper.getPluginId();
var dataBufferFactory = DefaultDataBufferFactory.sharedInstance;
return Mono.<Resource>fromSupplier(() -> BundleResourceUtils.getJsBundleResource(
pluginManager, pluginId, BundleResourceUtils.CSS_BUNDLE
))
.filter(Resource::isReadable)
.flatMapMany(resource -> {
var head = Mono.<DataBuffer>fromSupplier(() -> dataBufferFactory.wrap(
("/* Generated from plugin " + pluginId + " */\n").getBytes()
));
var content = DataBufferUtils.read(
resource, dataBufferFactory, StreamUtils.BUFFER_SIZE);
var tail = Mono.fromSupplier(() -> dataBufferFactory.wrap("\n".getBytes()));
return Flux.concat(head, content, tail);
});
});
}
@ -463,7 +469,7 @@ public class PluginServiceImpl implements PluginService, InitializingBean, Dispo
Version version = systemVersion.get();
// validate the plugin version
// only use the nominal system version to compare, the format is like MAJOR.MINOR.PATCH
String systemVersion = version.getNormalVersion();
String systemVersion = version.toStableVersion().toString();
String requires = newPlugin.getSpec().getRequires();
if (!VersionUtils.satisfiesRequires(systemVersion, requires)) {
throw new UnsatisfiedAttributeValueException(String.format(

View File

@ -2,7 +2,10 @@ package run.halo.app.plugin.extensionpoint;
import static run.halo.app.extension.index.query.QueryFactory.equal;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.pf4j.ExtensionPoint;
import org.pf4j.PluginManager;
@ -41,6 +44,16 @@ public class DefaultExtensionGetter implements ExtensionGetter {
.sort(new AnnotationAwareOrderComparator());
}
@Override
public <T extends ExtensionPoint> List<T> getExtensionList(Class<T> extensionPoint) {
var extensions = new LinkedList<T>();
Optional.ofNullable(pluginManager.getExtensions(extensionPoint))
.ifPresent(extensions::addAll);
extensions.addAll(beanFactory.getBeanProvider(extensionPoint).orderedStream().toList());
extensions.sort(new AnnotationAwareOrderComparator());
return extensions;
}
@Override
public <T extends ExtensionPoint> Mono<T> getEnabledExtension(Class<T> extensionPoint) {
return getEnabledExtensions(extensionPoint).next();

View File

@ -13,8 +13,8 @@ import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.service.RoleService;
import run.halo.app.core.extension.service.UserService;
import run.halo.app.core.user.service.RoleService;
import run.halo.app.core.user.service.UserService;
import run.halo.app.infra.exception.UserNotFoundException;
import run.halo.app.security.authentication.login.HaloUser;
import run.halo.app.security.authentication.twofactor.TwoFactorUtils;

Some files were not shown because too many files have changed in this diff Show More