diff --git a/.gitignore b/.gitignore index 1f6cf1bae4..db223874fd 100755 --- a/.gitignore +++ b/.gitignore @@ -74,4 +74,5 @@ application-local.properties !application/src/test/resources/themes/*.zip !application/src/main/resources/themes/*.zip application/src/main/resources/console/ +application/src/main/resources/uc/ application/src/main/resources/presets/ diff --git a/application/src/main/java/run/halo/app/config/WebFluxConfig.java b/application/src/main/java/run/halo/app/config/WebFluxConfig.java index 0fb0cea992..7bb8f6193a 100644 --- a/application/src/main/java/run/halo/app/config/WebFluxConfig.java +++ b/application/src/main/java/run/halo/app/config/WebFluxConfig.java @@ -29,14 +29,13 @@ import org.springframework.web.reactive.config.WebFluxConfigurer; import org.springframework.web.reactive.function.BodyInserters; 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 org.springframework.web.reactive.resource.EncodedResourceResolver; import org.springframework.web.reactive.resource.PathResourceResolver; 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.ConsoleProxyFilter; +import run.halo.app.console.ProxyFilter; import run.halo.app.console.WebSocketRequestPredicate; import run.halo.app.core.extension.endpoint.CustomEndpoint; import run.halo.app.core.extension.endpoint.CustomEndpointsBuilder; @@ -104,11 +103,21 @@ RouterFunction consoleIndexRedirection() { .and(path("/console/**").and(path("/console/assets/**").negate())) .and(accept(MediaType.TEXT_HTML)) .and(new WebSocketRequestPredicate().negate()); - return route(consolePredicate, this::serveConsoleIndex); + return route(consolePredicate, + request -> this.serveIndex(haloProp.getConsole().getLocation() + "index.html")); } - private Mono serveConsoleIndex(ServerRequest request) { - var indexLocation = haloProp.getConsole().getLocation() + "index.html"; + @Bean + RouterFunction ucIndexRedirect() { + var consolePredicate = method(HttpMethod.GET) + .and(path("/uc/**").and(path("/uc/assets/**").negate())) + .and(accept(MediaType.TEXT_HTML)) + .and(new WebSocketRequestPredicate().negate()); + return route(consolePredicate, + request -> this.serveIndex(haloProp.getUc().getLocation() + "index.html")); + } + + private Mono serveIndex(String indexLocation) { var indexResource = applicationContext.getResource(indexLocation); try { return ServerResponse.ok() @@ -142,6 +151,15 @@ public void addResourceHandlers(ResourceHandlerRegistry registry) { .addResolver(new EncodedResourceResolver()) .addResolver(new PathResourceResolver()); + // For uc assets + registry.addResourceHandler("/uc/assets/**") + .addResourceLocations(haloProp.getUc().getLocation() + "assets/") + .setCacheControl(cacheControl) + .setUseLastModified(useLastModified) + .resourceChain(true) + .addResolver(new EncodedResourceResolver()) + .addResolver(new PathResourceResolver()); + // Additional resource mappings var staticResources = haloProp.getAttachment().getResourceMappings(); staticResources.forEach(staticResource -> { @@ -172,7 +190,14 @@ public void addResourceHandlers(ResourceHandlerRegistry registry) { @ConditionalOnProperty(name = "halo.console.proxy.enabled", havingValue = "true") @Bean - ConsoleProxyFilter consoleProxyFilter() { - return new ConsoleProxyFilter(haloProp); + ProxyFilter consoleProxyFilter() { + return new ProxyFilter("/console/**", haloProp.getConsole().getProxy()); + } + + + @ConditionalOnProperty(name = "halo.uc.proxy.enabled", havingValue = "true") + @Bean + ProxyFilter ucProxyFilter() { + return new ProxyFilter("/uc/**", haloProp.getUc().getProxy()); } } diff --git a/application/src/main/java/run/halo/app/console/ConsoleProxyFilter.java b/application/src/main/java/run/halo/app/console/ProxyFilter.java similarity index 87% rename from application/src/main/java/run/halo/app/console/ConsoleProxyFilter.java rename to application/src/main/java/run/halo/app/console/ProxyFilter.java index 512a79b031..854d810ab1 100644 --- a/application/src/main/java/run/halo/app/console/ConsoleProxyFilter.java +++ b/application/src/main/java/run/halo/app/console/ProxyFilter.java @@ -13,11 +13,10 @@ import org.springframework.web.server.WebFilterChain; import org.springframework.web.util.UriComponentsBuilder; import reactor.core.publisher.Mono; -import run.halo.app.infra.properties.ConsoleProperties.ProxyProperties; -import run.halo.app.infra.properties.HaloProperties; +import run.halo.app.infra.properties.ProxyProperties; @Slf4j -public class ConsoleProxyFilter implements WebFilter { +public class ProxyFilter implements WebFilter { private final ProxyProperties proxyProperties; @@ -25,14 +24,15 @@ public class ConsoleProxyFilter implements WebFilter { private final WebClient webClient; - public ConsoleProxyFilter(HaloProperties haloProperties) { - this.proxyProperties = haloProperties.getConsole().getProxy(); - var consoleMatcher = ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, "/console/**"); + public ProxyFilter(String pattern, ProxyProperties proxyProperties) { + this.proxyProperties = proxyProperties; + var consoleMatcher = ServerWebExchangeMatchers.pathMatchers(HttpMethod.GET, pattern); consoleMatcher = new AndServerWebExchangeMatcher(consoleMatcher, new NegatedServerWebExchangeMatcher(new WebSocketServerWebExchangeMatcher())); this.consoleMatcher = consoleMatcher; this.webClient = WebClient.create(proxyProperties.getEndpoint().toString()); - log.info("Initialized ConsoleProxyFilter to proxy console"); + log.debug("Initialized ProxyFilter to proxy {} to endpoint {}", pattern, + proxyProperties.getEndpoint()); } @Override diff --git a/application/src/main/java/run/halo/app/core/extension/service/DefaultRoleService.java b/application/src/main/java/run/halo/app/core/extension/service/DefaultRoleService.java index 567685b4bb..a9f98f0a35 100644 --- a/application/src/main/java/run/halo/app/core/extension/service/DefaultRoleService.java +++ b/application/src/main/java/run/halo/app/core/extension/service/DefaultRoleService.java @@ -54,7 +54,7 @@ public Mono contains(Collection source, Collection cand if (source.contains(SuperAdminInitializer.SUPER_ROLE_NAME)) { return Mono.just(true); } - return listDependencies(new HashSet<>(source), shouldFilterHidden(true)) + return listDependencies(new HashSet<>(source), shouldFilterHidden(false)) .map(role -> role.getMetadata().getName()) .collect(Collectors.toSet()) .map(roleNames -> roleNames.containsAll(candidates)); diff --git a/application/src/main/java/run/halo/app/infra/properties/ConsoleProperties.java b/application/src/main/java/run/halo/app/infra/properties/ConsoleProperties.java index dda8be00dc..8bf245a459 100644 --- a/application/src/main/java/run/halo/app/infra/properties/ConsoleProperties.java +++ b/application/src/main/java/run/halo/app/infra/properties/ConsoleProperties.java @@ -1,7 +1,6 @@ package run.halo.app.infra.properties; import jakarta.validation.Valid; -import java.net.URI; import lombok.Data; @Data @@ -12,17 +11,4 @@ public class ConsoleProperties { @Valid private ProxyProperties proxy = new ProxyProperties(); - @Data - public static class ProxyProperties { - - /** - * Console endpoint in development environment to be proxied. e.g.: http://localhost:8090/ - */ - private URI endpoint; - - /** - * Indicates if the proxy behaviour is enabled. Default is false - */ - private boolean enabled = false; - } } diff --git a/application/src/main/java/run/halo/app/infra/properties/HaloProperties.java b/application/src/main/java/run/halo/app/infra/properties/HaloProperties.java index 5a29cf2316..b3b01db4e6 100644 --- a/application/src/main/java/run/halo/app/infra/properties/HaloProperties.java +++ b/application/src/main/java/run/halo/app/infra/properties/HaloProperties.java @@ -54,6 +54,9 @@ public class HaloProperties implements Validator { @Valid private final ConsoleProperties console = new ConsoleProperties(); + @Valid + private final UcProperties uc = new UcProperties(); + @Valid private final ThemeProperties theme = new ThemeProperties(); diff --git a/application/src/main/java/run/halo/app/infra/properties/ProxyProperties.java b/application/src/main/java/run/halo/app/infra/properties/ProxyProperties.java new file mode 100644 index 0000000000..275180de28 --- /dev/null +++ b/application/src/main/java/run/halo/app/infra/properties/ProxyProperties.java @@ -0,0 +1,18 @@ +package run.halo.app.infra.properties; + +import java.net.URI; +import lombok.Data; + +@Data +public class ProxyProperties { + + /** + * Console endpoint in development environment to be proxied. e.g.: http://localhost:8090/ + */ + private URI endpoint; + + /** + * Indicates if the proxy behaviour is enabled. Default is false + */ + private boolean enabled = false; +} diff --git a/application/src/main/java/run/halo/app/infra/properties/UcProperties.java b/application/src/main/java/run/halo/app/infra/properties/UcProperties.java new file mode 100644 index 0000000000..46fd7c2ad0 --- /dev/null +++ b/application/src/main/java/run/halo/app/infra/properties/UcProperties.java @@ -0,0 +1,14 @@ +package run.halo.app.infra.properties; + +import jakarta.validation.Valid; +import lombok.Data; + +@Data +public class UcProperties { + + private String location = "classpath:/uc/"; + + @Valid + private ProxyProperties proxy = new ProxyProperties(); + +} diff --git a/application/src/main/resources/application-dev.yaml b/application/src/main/resources/application-dev.yaml index fe6250e8ed..ddc6b95210 100644 --- a/application/src/main/resources/application-dev.yaml +++ b/application/src/main/resources/application-dev.yaml @@ -19,6 +19,10 @@ halo: proxy: endpoint: http://localhost:3000/ enabled: true + uc: + proxy: + endpoint: http://localhost:4000/ + enabled: true plugin: runtime-mode: development # development, deployment work-dir: ${user.home}/halo2-dev