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; package run.halo.app.plugin.extensionpoint;
import java.util.List;
import org.pf4j.ExtensionPoint; import org.pf4j.ExtensionPoint;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@ -34,4 +35,14 @@ public interface ExtensionGetter {
* @return a bunch of extension points. * @return a bunch of extension points.
*/ */
<T extends ExtensionPoint> Flux<T> getExtensions(Class<T> extensionPointClass); <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.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.user.service.RoleService;
import run.halo.app.core.extension.service.UserService; import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.ReactiveExtensionClient; import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.metrics.CounterService; import run.halo.app.metrics.CounterService;
import run.halo.app.metrics.MeterUtils; import run.halo.app.metrics.MeterUtils;

View File

@ -17,8 +17,8 @@ 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.content.Comment; import run.halo.app.core.extension.content.Comment;
import run.halo.app.core.extension.service.RoleService; import run.halo.app.core.user.service.RoleService;
import run.halo.app.core.extension.service.UserService; import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.Extension; import run.halo.app.extension.Extension;
import run.halo.app.extension.ListOptions; import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ListResult; import run.halo.app.extension.ListResult;

View File

@ -22,8 +22,8 @@ import reactor.core.publisher.Mono;
import reactor.util.retry.Retry; import reactor.util.retry.Retry;
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.user.service.RoleService;
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.ListOptions;
import run.halo.app.extension.ListResult; import run.halo.app.extension.ListResult;
import run.halo.app.extension.PageRequest; 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.Post;
import run.halo.app.core.extension.content.Snapshot; import run.halo.app.core.extension.content.Snapshot;
import run.halo.app.core.extension.content.Tag; 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.ListOptions;
import run.halo.app.extension.ListResult; import run.halo.app.extension.ListResult;
import run.halo.app.extension.MetadataOperator; 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.Post;
import run.halo.app.core.extension.content.SinglePage; import run.halo.app.core.extension.content.SinglePage;
import run.halo.app.core.extension.content.Snapshot; 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.ListResult;
import run.halo.app.extension.ReactiveExtensionClient; import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.extension.Ref; 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.core.io.Resource;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import reactor.core.publisher.Mono; 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.ExternalLinkProcessor;
import run.halo.app.infra.exception.NotFoundException; 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 io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder; 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 java.nio.file.StandardOpenOption.CREATE_NEW;
import static run.halo.app.infra.utils.FileNameUtils.randomFileName; 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.Attachment.AttachmentSpec;
import run.halo.app.core.extension.attachment.Constant; import run.halo.app.core.extension.attachment.Constant;
import run.halo.app.core.extension.attachment.Policy; 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.ConfigMap;
import run.halo.app.extension.Metadata; import run.halo.app.extension.Metadata;
import run.halo.app.infra.ExternalUrlSupplier; 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.NOT_REQUIRED;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.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; 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.ThumbnailGenerator;
import run.halo.app.core.attachment.ThumbnailSigner; import run.halo.app.core.attachment.ThumbnailSigner;
import run.halo.app.core.attachment.ThumbnailSize; 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.ListOptions;
import run.halo.app.extension.ListResult; import run.halo.app.extension.ListResult;
import run.halo.app.extension.Metadata; 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.ThumbnailService;
import run.halo.app.core.attachment.ThumbnailSigner; import run.halo.app.core.attachment.ThumbnailSigner;
import run.halo.app.core.attachment.ThumbnailSize; 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.ListOptions;
import run.halo.app.extension.ListResult; import run.halo.app.extension.ListResult;
import run.halo.app.extension.Metadata; import run.halo.app.extension.Metadata;

View File

@ -1,7 +1,7 @@
package run.halo.app.core.attachment.reconciler; package run.halo.app.core.attachment.reconciler;
import static org.springframework.data.domain.Sort.Order.desc; 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.MetadataUtil.nullSafeAnnotations;
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;
@ -23,9 +23,9 @@ import run.halo.app.core.attachment.AttachmentRootGetter;
import run.halo.app.core.attachment.AttachmentUtils; import run.halo.app.core.attachment.AttachmentUtils;
import run.halo.app.core.attachment.LocalThumbnailService; import run.halo.app.core.attachment.LocalThumbnailService;
import run.halo.app.core.attachment.ThumbnailGenerator; 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.Attachment;
import run.halo.app.core.extension.attachment.Constant; 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.ExtensionClient;
import run.halo.app.extension.ExtensionUtil; import run.halo.app.extension.ExtensionUtil;
import run.halo.app.extension.ListOptions; 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.server.ServerWebExchange;
import org.springframework.web.util.pattern.PathPattern; import org.springframework.web.util.pattern.PathPattern;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import run.halo.app.console.WebSocketUtils; import run.halo.app.infra.console.WebSocketUtils;
public class WebSocketHandlerMapping extends AbstractHandlerMapping public class WebSocketHandlerMapping extends AbstractHandlerMapping
implements WebSocketEndpointManager, InitializingBean { 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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder; 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 org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import run.halo.app.core.extension.AuthProvider; 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.AuthProviderService;
import run.halo.app.security.ListedAuthProvider; 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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.content.Builder.contentBuilder; 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.content.comment.ReplyService;
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.endpoint.CustomEndpoint;
import run.halo.app.extension.ListResult; import run.halo.app.extension.ListResult;
import run.halo.app.infra.utils.HaloUtils; import run.halo.app.infra.utils.HaloUtils;
import run.halo.app.infra.utils.IpAddressUtils; 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.HashMap;
import java.util.LinkedList; 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.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.extension.GroupVersion; import run.halo.app.extension.GroupVersion;
public class CustomEndpointsBuilder { 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.NOT_REQUIRED;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.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 reactor.util.retry.Retry;
import run.halo.app.core.extension.Plugin; import run.halo.app.core.extension.Plugin;
import run.halo.app.core.extension.Setting; import run.halo.app.core.extension.Setting;
import run.halo.app.core.extension.service.PluginService; import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.core.extension.service.SettingConfigService; import run.halo.app.core.user.service.SettingConfigService;
import run.halo.app.core.extension.theme.SettingUtils;
import run.halo.app.extension.ConfigMap; import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.ListOptions; import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ReactiveExtensionClient; import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.extension.router.IListRequest; import run.halo.app.extension.router.IListRequest;
import run.halo.app.extension.router.SortableRequest; import run.halo.app.extension.router.SortableRequest;
import run.halo.app.infra.ReactiveUrlDataBufferFetcher; import run.halo.app.infra.ReactiveUrlDataBufferFetcher;
import run.halo.app.infra.utils.SettingUtils;
import run.halo.app.plugin.PluginNotFoundException; import run.halo.app.plugin.PluginNotFoundException;
import run.halo.app.plugin.PluginService;
@Slf4j @Slf4j
@Component @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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.content.Builder.contentBuilder; 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.PostRequest;
import run.halo.app.content.PostService; import run.halo.app.content.PostService;
import run.halo.app.core.extension.content.Post; 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.ListResult;
import run.halo.app.extension.MetadataUtil; import run.halo.app.extension.MetadataUtil;
import run.halo.app.extension.ReactiveExtensionClient; 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 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.ReplyQuery;
import run.halo.app.content.comment.ReplyService; import run.halo.app.content.comment.ReplyService;
import run.halo.app.core.extension.content.Reply; 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.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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.content.Builder.contentBuilder; 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.content.SinglePageService;
import run.halo.app.core.extension.content.Post; import run.halo.app.core.extension.content.Post;
import run.halo.app.core.extension.content.SinglePage; 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.ListResult;
import run.halo.app.extension.MetadataUtil; import run.halo.app.extension.MetadataUtil;
import run.halo.app.extension.ReactiveExtensionClient; 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 org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static run.halo.app.extension.index.query.QueryFactory.and; 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.Counter;
import run.halo.app.core.extension.User; import run.halo.app.core.extension.User;
import run.halo.app.core.extension.content.Post; 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.ListOptions;
import run.halo.app.extension.PageRequestImpl; import run.halo.app.extension.PageRequestImpl;
import run.halo.app.extension.ReactiveExtensionClient; 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 io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder; 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 org.springframework.web.server.ServerWebInputException;
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.endpoint.CustomEndpoint;
import run.halo.app.extension.ConfigMap; import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.ReactiveExtensionClient; import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.InitializationStateGetter; 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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder; 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 org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import run.halo.app.core.extension.content.Tag; 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.ListOptions;
import run.halo.app.extension.ListResult; import run.halo.app.extension.ListResult;
import run.halo.app.extension.PageRequestImpl; 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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.content.Builder.contentBuilder; 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.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono; 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.DownvotedEvent;
import run.halo.app.event.post.UpvotedEvent; import run.halo.app.event.post.UpvotedEvent;
import run.halo.app.event.post.VisitedEvent; 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 io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; 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.Role;
import run.halo.app.core.extension.User; import run.halo.app.core.extension.User;
import run.halo.app.core.extension.attachment.Attachment; 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.AttachmentService;
import run.halo.app.core.extension.service.EmailVerificationService; import run.halo.app.core.user.service.EmailVerificationService;
import run.halo.app.core.extension.service.RoleService; import run.halo.app.core.user.service.RoleService;
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.ListOptions;
import run.halo.app.extension.ListResult; import run.halo.app.extension.ListResult;
import run.halo.app.extension.Metadata; 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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder; 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 io.swagger.v3.oas.annotations.enums.ParameterIn;
import lombok.RequiredArgsConstructor; 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 io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import static org.apache.commons.lang3.BooleanUtils.isFalse; 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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder; 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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder; 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.springdoc.core.fn.builders.operation.Builder;
import org.springframework.web.server.ServerWebExchange; 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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder; 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.Collection;
import java.util.List; 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.NOT_REQUIRED;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.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 reactor.core.publisher.Mono;
import run.halo.app.core.extension.User; import run.halo.app.core.extension.User;
import run.halo.app.core.extension.endpoint.CustomEndpoint; import run.halo.app.core.extension.endpoint.CustomEndpoint;
import run.halo.app.core.extension.service.EmailPasswordRecoveryService; import run.halo.app.core.user.service.EmailPasswordRecoveryService;
import run.halo.app.core.extension.service.EmailVerificationService; import run.halo.app.core.user.service.EmailVerificationService;
import run.halo.app.core.extension.service.UserService; import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.GroupVersion; import run.halo.app.extension.GroupVersion;
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher; import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
import run.halo.app.infra.SystemSetting; 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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder; 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.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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder; 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 io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder; 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.NOT_REQUIRED;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder; 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.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder; 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 java.util.Map;
import lombok.AllArgsConstructor; 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 lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.BooleanUtils; 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.addFinalizers;
import static run.halo.app.extension.ExtensionUtil.removeFinalizers; 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 org.apache.commons.lang3.ObjectUtils.defaultIfNull;
import static run.halo.app.extension.ExtensionUtil.addFinalizers; 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.time.Duration;
import java.util.Objects; 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.core.extension.Plugin.PluginStatus.nullSafeConditions;
import static run.halo.app.extension.ExtensionUtil.addFinalizers; 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.Plugin;
import run.halo.app.core.extension.ReverseProxy; import run.halo.app.core.extension.ReverseProxy;
import run.halo.app.core.extension.Setting; 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.ConfigMap;
import run.halo.app.extension.ExtensionClient; import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.ExtensionUtil; 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.ConditionList;
import run.halo.app.infra.ConditionStatus; import run.halo.app.infra.ConditionStatus;
import run.halo.app.infra.utils.PathUtils; 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.infra.utils.YamlUnstructuredLoader;
import run.halo.app.plugin.PluginConst; import run.halo.app.plugin.PluginConst;
import run.halo.app.plugin.PluginProperties; 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; 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 java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.commons.lang3.BooleanUtils.TRUE; 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 org.apache.commons.lang3.ObjectUtils.defaultIfNull;
import static run.halo.app.extension.ExtensionUtil.addFinalizers; 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.HashSet;
import java.util.Map; 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; 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 java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.web.util.UriUtils.encodePath; 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.HashMap;
import java.util.HashSet; 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.addFinalizers;
import static run.halo.app.extension.ExtensionUtil.removeFinalizers; 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 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.AnnotationSetting;
import run.halo.app.core.extension.Setting; import run.halo.app.core.extension.Setting;
import run.halo.app.core.extension.Theme; 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.ExtensionClient;
import run.halo.app.extension.MetadataUtil; import run.halo.app.extension.MetadataUtil;
import run.halo.app.extension.controller.Controller; 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.ThemeRootGetter;
import run.halo.app.infra.exception.ThemeUninstallException; import run.halo.app.infra.exception.ThemeUninstallException;
import run.halo.app.infra.utils.JsonUtils; import run.halo.app.infra.utils.JsonUtils;
import run.halo.app.infra.utils.SettingUtils;
import run.halo.app.infra.utils.VersionUtils; 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.addFinalizers;
import static run.halo.app.extension.ExtensionUtil.defaultSort; 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.UserConnection;
import run.halo.app.core.extension.attachment.Attachment; import run.halo.app.core.extension.attachment.Attachment;
import run.halo.app.core.extension.service.AttachmentService; import run.halo.app.core.extension.service.AttachmentService;
import run.halo.app.core.extension.service.RoleService; import run.halo.app.core.user.service.RoleService;
import run.halo.app.core.extension.service.UserService; import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.ExtensionClient; import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.ListOptions; import run.halo.app.extension.ListOptions;
import run.halo.app.extension.controller.Controller; 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.defaultSort;
import static run.halo.app.extension.ExtensionUtil.notDeleting; 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 reactor.core.publisher.Mono;
import run.halo.app.infra.exception.AccessDeniedException; 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 reactor.core.publisher.Mono;
import run.halo.app.infra.exception.EmailVerificationFailed; 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.Collection;
import java.util.Map; 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 com.fasterxml.jackson.databind.node.ObjectNode;
import reactor.core.publisher.Mono; 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 java.util.Set;
import reactor.core.publisher.Flux; 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.asc;
import static org.springframework.data.domain.Sort.Order.desc; 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.URI;
import java.net.URL; 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.Cache;
import com.google.common.cache.CacheBuilder; 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.User;
import run.halo.app.core.extension.notification.Reason; import run.halo.app.core.extension.notification.Reason;
import run.halo.app.core.extension.notification.Subscription; import run.halo.app.core.extension.notification.Subscription;
import run.halo.app.core.extension.service.EmailPasswordRecoveryService; import run.halo.app.core.user.service.EmailPasswordRecoveryService;
import run.halo.app.core.extension.service.UserService; import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.GroupVersion; import run.halo.app.extension.GroupVersion;
import run.halo.app.extension.ReactiveExtensionClient; import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.ExternalLinkProcessor; 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.Cache;
import com.google.common.cache.CacheBuilder; 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.User;
import run.halo.app.core.extension.notification.Reason; import run.halo.app.core.extension.notification.Reason;
import run.halo.app.core.extension.notification.Subscription; import run.halo.app.core.extension.notification.Subscription;
import run.halo.app.core.extension.service.EmailVerificationService; import run.halo.app.core.user.service.EmailVerificationService;
import run.halo.app.core.extension.service.UserService; import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.GroupVersion; import run.halo.app.extension.GroupVersion;
import run.halo.app.extension.MetadataUtil; import run.halo.app.extension.MetadataUtil;
import run.halo.app.extension.ReactiveExtensionClient; 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 com.fasterxml.jackson.databind.node.ObjectNode;
import java.time.Duration; import java.time.Duration;
@ -9,11 +9,11 @@ import org.springframework.util.Assert;
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.Setting; import run.halo.app.core.extension.Setting;
import run.halo.app.core.extension.service.SettingConfigService; import run.halo.app.core.user.service.SettingConfigService;
import run.halo.app.core.extension.theme.SettingUtils;
import run.halo.app.extension.ConfigMap; import run.halo.app.extension.ConfigMap;
import run.halo.app.extension.Metadata; import run.halo.app.extension.Metadata;
import run.halo.app.extension.ReactiveExtensionClient; import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.utils.SettingUtils;
/** /**
* {@link Setting} related {@link ConfigMap} service implementation. * {@link Setting} related {@link ConfigMap} service implementation.

View File

@ -26,9 +26,9 @@ public class DefaultSystemVersionSupplier implements SystemVersionSupplier {
public Version get() { public Version get() {
var properties = buildProperties.getIfUnique(); var properties = buildProperties.getIfUnique();
if (properties == null) { if (properties == null) {
return Version.valueOf(DEFAULT_VERSION); return Version.parse(DEFAULT_VERSION);
} }
var projectVersion = Objects.toString(properties.getVersion(), 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.stereotype.Component;
import org.springframework.util.ResourceUtils; import org.springframework.util.ResourceUtils;
import org.springframework.util.StreamUtils; 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.HaloProperties;
import run.halo.app.infra.properties.ThemeProperties; import run.halo.app.infra.properties.ThemeProperties;
import run.halo.app.infra.utils.FileUtils; import run.halo.app.infra.utils.FileUtils;
import run.halo.app.theme.service.ThemeService;
@Slf4j @Slf4j
@Component @Component

View File

@ -20,6 +20,8 @@ import org.springframework.context.ApplicationListener;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import run.halo.app.content.Stats; 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.AnnotationSetting;
import run.halo.app.core.extension.AuthProvider; import run.halo.app.core.extension.AuthProvider;
import run.halo.app.core.extension.Counter; 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.UserConnection.UserConnectionSpec;
import run.halo.app.core.extension.attachment.Attachment; import run.halo.app.core.extension.attachment.Attachment;
import run.halo.app.core.extension.attachment.Group; 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.Policy;
import run.halo.app.core.extension.attachment.PolicyTemplate; 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.Category;
import run.halo.app.core.extension.content.Comment; import run.halo.app.core.extension.content.Comment;
import run.halo.app.core.extension.content.Post; 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.Connection;
import io.r2dbc.spi.ConnectionFactory; 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; 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.Closeable;
import java.io.IOException; 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.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; 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.annotation.JsonInclude;
import com.fasterxml.jackson.databind.MapperFeature; 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; 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.util.ResourceUtils.FILE_URL_PREFIX;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept; import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
@ -12,6 +12,7 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.WebProperties; import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxRegistrations;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 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.function.server.ServerResponse;
import org.springframework.web.reactive.resource.EncodedResourceResolver; import org.springframework.web.reactive.resource.EncodedResourceResolver;
import org.springframework.web.reactive.resource.PathResourceResolver; 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.ViewResolutionResultHandler;
import org.springframework.web.reactive.result.view.ViewResolver; import org.springframework.web.reactive.result.view.ViewResolver;
import reactor.core.publisher.Mono; 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.WebSocketHandlerMapping;
import run.halo.app.core.endpoint.console.CustomEndpointsBuilder;
import run.halo.app.core.extension.endpoint.CustomEndpoint; 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.AttachmentProperties;
import run.halo.app.infra.properties.HaloProperties; 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.plugin.extensionpoint.ExtensionGetter;
import run.halo.app.webfilter.AdditionalWebFilterChainProxy;
@Configuration @Configuration
public class WebFluxConfig implements WebFluxConfigurer { public class WebFluxConfig implements WebFluxConfigurer {
@ -67,6 +70,19 @@ public class WebFluxConfig implements WebFluxConfigurer {
this.applicationContext = applicationContext; 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 @Bean
ServerResponse.Context context(CodecConfigurer codec, ServerResponse.Context context(CodecConfigurer codec,
ViewResolutionResultHandler resultHandler) { 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.config.Customizer.withDefaults;
import static org.springframework.security.web.server.authentication.ServerWebExchangeDelegatingReactiveAuthenticationManagerResolver.builder; 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.session.config.annotation.web.server.EnableSpringWebSession;
import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.reactive.function.server.ServerResponse;
import run.halo.app.core.extension.service.RoleService; import run.halo.app.core.user.service.RoleService;
import run.halo.app.core.extension.service.UserService; import run.halo.app.core.user.service.UserService;
import run.halo.app.extension.ReactiveExtensionClient; import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.AnonymousUserConst; import run.halo.app.infra.AnonymousUserConst;
import run.halo.app.infra.properties.HaloProperties; 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 lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.buffer.DataBuffer; 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.RequestPredicate;
import org.springframework.web.reactive.function.server.ServerRequest; 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.match;
import static org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher.MatchResult.notMatch; 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.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.web.server.ServerWebExchange; 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 java.util.Objects;
import org.springframework.http.HttpHeaders; 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; 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.ConfigMap;
import run.halo.app.extension.ExtensionClient; import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.Metadata; import run.halo.app.extension.Metadata;
import run.halo.app.infra.utils.JsonParseException;
import run.halo.app.infra.utils.JsonUtils;
@UtilityClass @UtilityClass
public class SettingUtils { public class SettingUtils {

View File

@ -41,7 +41,7 @@ public class VersionUtils {
try { try {
return StringUtils.isBlank(constraint) return StringUtils.isBlank(constraint)
|| "*".equals(constraint) || "*".equals(constraint)
|| Version.valueOf(version).satisfies(constraint); || Version.parse(version).satisfies(constraint);
} catch (Exception e) { } catch (Exception e) {
throw new ServerWebInputException("Illegal requires version expression.", null, 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 lombok.Setter;
import org.springframework.core.annotation.AnnotationAwareOrderComparator; 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.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine; import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context; import org.thymeleaf.context.Context;
@ -40,13 +42,16 @@ public class DefaultNotificationTemplateRender implements NotificationTemplateRe
@Override @Override
public Mono<String> render(String template, Map<String, Object> model) { public Mono<String> render(String template, Map<String, Object> model) {
var context = new Context(Locale.getDefault(), 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() var globalAttributeMono = getBasicSetting()
.doOnNext(basic -> { .doOnNext(basic -> {
var site = new HashMap<>(); var site = new HashMap<>();
site.put("title", basic.getTitle()); site.put("title", basic.getTitle());
site.put("logo", basic.getLogo()); site.put("logo", basic.getLogo());
site.put("subtitle", basic.getSubtitle()); site.put("subtitle", basic.getSubtitle());
site.put("url", externalUrlSupplier.getRaw()); site.put("url", externalUrl);
context.setVariable("site", site); context.setVariable("site", site);
}); });
return Mono.when(globalAttributeMono) 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.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono; 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.CustomEndpoint;
import run.halo.app.core.extension.endpoint.CustomEndpointsBuilder; import run.halo.app.infra.SecureServerRequest;
/** /**
* Aggregated router function built from all custom endpoints. * Aggregated router function built from all custom endpoints.
@ -28,7 +29,7 @@ public class AggregatedRouterFunction implements RouterFunction<ServerResponse>
@Override @Override
public Mono<HandlerFunction<ServerResponse>> route(ServerRequest request) { public Mono<HandlerFunction<ServerResponse>> route(ServerRequest request) {
return aggregated.route(request); return aggregated.route(new SecureServerRequest(request));
} }
@Override @Override

View File

@ -11,6 +11,7 @@ import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import run.halo.app.infra.SecureServerRequest;
/** /**
* A composite {@link RouterFunction} implementation for plugin. * A composite {@link RouterFunction} implementation for plugin.
@ -31,8 +32,9 @@ public class DefaultPluginRouterFunctionRegistry
@Override @Override
@NonNull @NonNull
public Mono<HandlerFunction<ServerResponse>> route(@NonNull ServerRequest request) { public Mono<HandlerFunction<ServerResponse>> route(@NonNull ServerRequest request) {
var secureRequest = new SecureServerRequest(request);
return Flux.fromIterable(this.routerFunctions) return Flux.fromIterable(this.routerFunctions)
.concatMap(routerFunction -> routerFunction.route(request)) .concatMap(routerFunction -> routerFunction.route(secureRequest))
.next(); .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 java.nio.file.Path;
import org.springframework.core.io.Resource; 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.StandardCopyOption.REPLACE_EXISTING;
import static java.nio.file.StandardOpenOption.CREATE; 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.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.FileSystemUtils; import org.springframework.util.FileSystemUtils;
import org.springframework.util.StreamUtils;
import org.springframework.web.server.ServerWebInputException; import org.springframework.web.server.ServerWebInputException;
import reactor.core.Exceptions; import reactor.core.Exceptions;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
@ -48,7 +49,6 @@ import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers; import reactor.core.scheduler.Schedulers;
import reactor.util.retry.Retry; import reactor.util.retry.Retry;
import run.halo.app.core.extension.Plugin; 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.extension.ReactiveExtensionClient;
import run.halo.app.infra.SystemVersionSupplier; import run.halo.app.infra.SystemVersionSupplier;
import run.halo.app.infra.exception.PluginAlreadyExistsException; 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.exception.UnsatisfiedAttributeValueException;
import run.halo.app.infra.utils.FileUtils; import run.halo.app.infra.utils.FileUtils;
import run.halo.app.infra.utils.VersionUtils; 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; import run.halo.app.plugin.resources.BundleResourceUtils;
@Slf4j @Slf4j
@ -229,61 +223,73 @@ public class PluginServiceImpl implements PluginService, InitializingBean, Dispo
@Override @Override
public Flux<DataBuffer> uglifyJsBundle() { public Flux<DataBuffer> uglifyJsBundle() {
var startedPlugins = List.copyOf(pluginManager.getStartedPlugins()); var startedPlugins = List.copyOf(pluginManager.getStartedPlugins());
String plugins = """ var dataBufferFactory = DefaultDataBufferFactory.sharedInstance;
this.enabledPlugins = [%s] var end = Mono.fromSupplier(
""".formatted(startedPlugins.stream() () -> {
.map(plugin -> """ var sb = new StringBuilder("this.enabledPlugins = [");
{ var iterator = startedPlugins.iterator();
"name": "%s", while (iterator.hasNext()) {
"version": "%s" var plugin = iterator.next();
} sb.append("""
""".formatted(plugin.getPluginId(), plugin.getDescriptor().getVersion()) {"name":"%s","version":"%s"}\
"""
.formatted(
plugin.getPluginId(),
plugin.getDescriptor().getVersion()
) )
.collect(Collectors.joining(", "))); );
return Flux.fromIterable(startedPlugins) if (iterator.hasNext()) {
.mapNotNull(pluginWrapper -> { sb.append(',');
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();
} }
}) }
.concatWith(Flux.defer(() -> { sb.append(']');
var dataBuffer = DefaultDataBufferFactory.sharedInstance return dataBufferFactory.wrap(sb.toString().getBytes(StandardCharsets.UTF_8));
.wrap(plugins.getBytes(StandardCharsets.UTF_8)); });
return Flux.just(dataBuffer); 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 @Override
public Flux<DataBuffer> uglifyCssBundle() { public Flux<DataBuffer> uglifyCssBundle() {
return Flux.fromIterable(pluginManager.getStartedPlugins()) return Flux.fromIterable(pluginManager.getStartedPlugins())
.mapNotNull(pluginWrapper -> { .sort(Comparator.comparing(PluginWrapper::getPluginId))
String pluginName = pluginWrapper.getPluginId(); .concatMap(pluginWrapper -> {
return BundleResourceUtils.getJsBundleResource(pluginManager, pluginName, var pluginId = pluginWrapper.getPluginId();
BundleResourceUtils.CSS_BUNDLE); var dataBufferFactory = DefaultDataBufferFactory.sharedInstance;
}) return Mono.<Resource>fromSupplier(() -> BundleResourceUtils.getJsBundleResource(
.flatMap(resource -> { pluginManager, pluginId, BundleResourceUtils.CSS_BUNDLE
try { ))
return DataBufferUtils.read(resource, DefaultDataBufferFactory.sharedInstance, .filter(Resource::isReadable)
(int) resource.contentLength()); .flatMapMany(resource -> {
} catch (IOException e) { var head = Mono.<DataBuffer>fromSupplier(() -> dataBufferFactory.wrap(
log.error("Failed to read plugin css bundle resource", e); ("/* Generated from plugin " + pluginId + " */\n").getBytes()
return Flux.empty(); ));
} 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(); Version version = systemVersion.get();
// validate the plugin version // validate the plugin version
// only use the nominal system version to compare, the format is like MAJOR.MINOR.PATCH // 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(); String requires = newPlugin.getSpec().getRequires();
if (!VersionUtils.satisfiesRequires(systemVersion, requires)) { if (!VersionUtils.satisfiesRequires(systemVersion, requires)) {
throw new UnsatisfiedAttributeValueException(String.format( 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 static run.halo.app.extension.index.query.QueryFactory.equal;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.pf4j.ExtensionPoint; import org.pf4j.ExtensionPoint;
import org.pf4j.PluginManager; import org.pf4j.PluginManager;
@ -41,6 +44,16 @@ public class DefaultExtensionGetter implements ExtensionGetter {
.sort(new AnnotationAwareOrderComparator()); .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 @Override
public <T extends ExtensionPoint> Mono<T> getEnabledExtension(Class<T> extensionPoint) { public <T extends ExtensionPoint> Mono<T> getEnabledExtension(Class<T> extensionPoint) {
return getEnabledExtensions(extensionPoint).next(); 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.User;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import run.halo.app.core.extension.service.RoleService; import run.halo.app.core.user.service.RoleService;
import run.halo.app.core.extension.service.UserService; import run.halo.app.core.user.service.UserService;
import run.halo.app.infra.exception.UserNotFoundException; import run.halo.app.infra.exception.UserNotFoundException;
import run.halo.app.security.authentication.login.HaloUser; import run.halo.app.security.authentication.login.HaloUser;
import run.halo.app.security.authentication.twofactor.TwoFactorUtils; import run.halo.app.security.authentication.twofactor.TwoFactorUtils;

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