diff --git a/api/src/main/java/run/halo/app/infra/SystemInfo.java b/api/src/main/java/run/halo/app/infra/SystemInfo.java new file mode 100644 index 0000000000..d184ef18f2 --- /dev/null +++ b/api/src/main/java/run/halo/app/infra/SystemInfo.java @@ -0,0 +1,40 @@ +package run.halo.app.infra; + +import com.github.zafarkhaja.semver.Version; +import java.net.URL; +import java.util.Locale; +import java.util.TimeZone; +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@Accessors(chain = true) +public class SystemInfo { + private String title; + + private String subtitle; + + private String logo; + + private String favicon; + + private URL url; + + private Version version; + + private SeoProp seo; + + private Locale locale; + + private TimeZone timeZone; + + private String activatedThemeName; + + @Data + @Accessors(chain = true) + public static class SeoProp { + private boolean blockSpiders; + private String keywords; + private String description; + } +} diff --git a/api/src/main/java/run/halo/app/infra/SystemInfoGetter.java b/api/src/main/java/run/halo/app/infra/SystemInfoGetter.java new file mode 100644 index 0000000000..293ada78e0 --- /dev/null +++ b/api/src/main/java/run/halo/app/infra/SystemInfoGetter.java @@ -0,0 +1,7 @@ +package run.halo.app.infra; + +import java.util.function.Supplier; +import reactor.core.publisher.Mono; + +public interface SystemInfoGetter extends Supplier> { +} diff --git a/application/src/main/java/run/halo/app/infra/SystemInfoGetterImpl.java b/application/src/main/java/run/halo/app/infra/SystemInfoGetterImpl.java new file mode 100644 index 0000000000..ad2bfd1364 --- /dev/null +++ b/application/src/main/java/run/halo/app/infra/SystemInfoGetterImpl.java @@ -0,0 +1,71 @@ +package run.halo.app.infra; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.Locale; +import java.util.TimeZone; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.reactive.WebFluxProperties; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +@Component +@RequiredArgsConstructor +public class SystemInfoGetterImpl implements SystemInfoGetter { + private final SystemConfigurableEnvironmentFetcher environmentFetcher; + private final SystemVersionSupplier systemVersionSupplier; + private final ExternalUrlSupplier externalUrlSupplier; + private final ServerProperties serverProperties; + private final WebFluxProperties webFluxProperties; + + @Override + public Mono get() { + var systemInfo = new SystemInfo() + .setVersion(systemVersionSupplier.get()) + .setUrl(getExternalUrl()) + // TODO populate locale and timezone from system settings in the future + .setLocale(Locale.getDefault()) + .setTimeZone(TimeZone.getDefault()); + + var basicMono = + environmentFetcher.fetch(SystemSetting.Basic.GROUP, SystemSetting.Basic.class) + .doOnNext(basic -> systemInfo.setTitle(basic.getTitle()) + .setSubtitle(basic.getSubtitle()) + .setLogo(basic.getLogo()) + .setFavicon(basic.getFavicon()) + ); + + var seoMono = environmentFetcher.fetch(SystemSetting.Seo.GROUP, SystemSetting.Seo.class) + .doOnNext(seo -> systemInfo.setSeo(new SystemInfo.SeoProp() + .setBlockSpiders(BooleanUtils.isTrue(seo.blockSpiders)) + .setKeywords(seo.getKeywords()) + .setDescription(seo.getDescription()) + )); + + var themeMono = + environmentFetcher.fetch(SystemSetting.Theme.GROUP, SystemSetting.Theme.class) + .doOnNext(theme -> systemInfo.setActivatedThemeName(theme.getActive())); + return Mono.when(basicMono, seoMono, themeMono) + .thenReturn(systemInfo); + } + + private URL getExternalUrl() { + var url = externalUrlSupplier.getRaw(); + if (url != null) { + return url; + } + var port = serverProperties.getPort(); + var basePath = StringUtils.defaultIfBlank(webFluxProperties.getBasePath(), "/"); + try { + var uriStr = "http://localhost:" + port + basePath; + return URI.create(StringUtils.removeEnd(uriStr, "/")).toURL(); + } catch (MalformedURLException e) { + // Should not happen + throw new RuntimeException("Cannot create URL from server properties.", e); + } + } +} diff --git a/application/src/main/java/run/halo/app/plugin/SharedApplicationContextFactory.java b/application/src/main/java/run/halo/app/plugin/SharedApplicationContextFactory.java index e8e23316c7..77766304fb 100644 --- a/application/src/main/java/run/halo/app/plugin/SharedApplicationContextFactory.java +++ b/application/src/main/java/run/halo/app/plugin/SharedApplicationContextFactory.java @@ -17,6 +17,7 @@ import run.halo.app.infra.BackupRootGetter; import run.halo.app.infra.ExternalLinkProcessor; import run.halo.app.infra.ExternalUrlSupplier; +import run.halo.app.infra.SystemInfoGetter; import run.halo.app.notification.NotificationCenter; import run.halo.app.notification.NotificationReasonEmitter; import run.halo.app.plugin.extensionpoint.ExtensionGetter; @@ -97,6 +98,10 @@ public static ApplicationContext create(ApplicationContext rootContext) { .ifUnique(userDetailsService -> beanFactory.registerSingleton("userDetailsService", userDetailsService) ); + rootContext.getBeanProvider(SystemInfoGetter.class) + .ifUnique(systemInfoGetter -> + beanFactory.registerSingleton("systemInfoGetter", systemInfoGetter) + ); // TODO add more shared instance here sharedContext.refresh();