diff --git a/cms-api/src/main/java/com/condation/cms/api/ServerProperties.java b/cms-api/src/main/java/com/condation/cms/api/ServerProperties.java index 340b71d63..7bbe13498 100644 --- a/cms-api/src/main/java/com/condation/cms/api/ServerProperties.java +++ b/cms-api/src/main/java/com/condation/cms/api/ServerProperties.java @@ -22,7 +22,7 @@ * #L% */ import java.nio.file.Path; -import java.util.Map; +import java.util.List; /** * @@ -45,4 +45,10 @@ public interface ServerProperties { public IPCProperties ipc(); public PerformanceProperties performance(); + + public List moduleRepositories (); + + public List themeRepositories (); + + public List extensionRepositories (); } diff --git a/cms-core/config/server.toml b/cms-core/config/server.toml index 307219437..bc0d0e42e 100644 --- a/cms-core/config/server.toml +++ b/cms-core/config/server.toml @@ -20,4 +20,9 @@ pool_enabled = false test = ["eins", "zwei"] [map] -test = {"key1"="value2", "key2"="value2"} \ No newline at end of file +test = {"key1"="value2", "key2"="value2"} + +[urls] +themes = ["https://mythemes.com"] +extensions = ["https://myextensions.com"] +modules = ["https://mymodules.com"] \ No newline at end of file diff --git a/cms-core/src/main/java/com/condation/cms/core/configuration/ConfigManagement.java b/cms-core/src/main/java/com/condation/cms/core/configuration/ConfigManagement.java index 62af7e00b..af57f0764 100644 --- a/cms-core/src/main/java/com/condation/cms/core/configuration/ConfigManagement.java +++ b/cms-core/src/main/java/com/condation/cms/core/configuration/ConfigManagement.java @@ -25,9 +25,7 @@ import com.condation.cms.api.configuration.Configuration; import com.condation.cms.api.configuration.configs.ServerConfiguration; import com.condation.cms.api.configuration.configs.SiteConfiguration; -import com.condation.cms.core.configuration.configs.MediaConfiguration; import com.condation.cms.core.configuration.configs.SimpleConfiguration; -import com.condation.cms.core.configuration.configs.TaxonomyConfiguration; import com.condation.cms.core.configuration.properties.ExtendedServerProperties; import com.condation.cms.core.configuration.properties.ExtendedSiteProperties; import java.util.HashMap; diff --git a/cms-core/src/main/java/com/condation/cms/core/configuration/properties/ExtendedServerProperties.java b/cms-core/src/main/java/com/condation/cms/core/configuration/properties/ExtendedServerProperties.java index c2b101ea1..45abb68c1 100644 --- a/cms-core/src/main/java/com/condation/cms/core/configuration/properties/ExtendedServerProperties.java +++ b/cms-core/src/main/java/com/condation/cms/core/configuration/properties/ExtendedServerProperties.java @@ -30,6 +30,8 @@ import com.condation.cms.api.utils.ServerUtil; import com.condation.cms.core.configuration.configs.SimpleConfiguration; import java.nio.file.Path; +import java.util.Collections; +import java.util.List; /** * @@ -92,6 +94,21 @@ public String env() { public boolean dev() { return !Constants.Environments.PROD.equals(env()); } + + @Override + public List moduleRepositories() { + return (List) configuration.getOrDefault("urls.modules", Collections.emptyList()); + } + + @Override + public List themeRepositories() { + return (List) configuration.getOrDefault("urls.themes", Collections.emptyList()); + } + + @Override + public List extensionRepositories() { + return (List) configuration.getOrDefault("urls.extensions", Collections.emptyList()); + } public static record Server (int port, String ip) { diff --git a/cms-core/src/test/java/com/condation/cms/core/configuration/ConfigurationTest.java b/cms-core/src/test/java/com/condation/cms/core/configuration/ConfigurationTest.java index cabb58c35..774bad313 100644 --- a/cms-core/src/test/java/com/condation/cms/core/configuration/ConfigurationTest.java +++ b/cms-core/src/test/java/com/condation/cms/core/configuration/ConfigurationTest.java @@ -123,6 +123,20 @@ public void test_properties () { Assertions.assertThat(serverProperties.serverPort()).isEqualTo(1010); } + @Test + public void test_urls () { + var serverProperties = new ExtendedServerProperties(configuration); + + Assertions.assertThat(serverProperties.extensionRepositories()) + .containsExactly("https://myextensions.com"); + + Assertions.assertThat(serverProperties.moduleRepositories()) + .containsExactly("https://mymodules.com"); + + Assertions.assertThat(serverProperties.themeRepositories()) + .containsExactly("https://mythemes.com"); + } + @Data @NoArgsConstructor public static class Server { diff --git a/cms-extensions/src/main/java/com/condation/cms/extensions/repository/RemoteModuleRepository.java b/cms-extensions/src/main/java/com/condation/cms/extensions/repository/RemoteModuleRepository.java index 62a4845d1..137fd80f2 100644 --- a/cms-extensions/src/main/java/com/condation/cms/extensions/repository/RemoteModuleRepository.java +++ b/cms-extensions/src/main/java/com/condation/cms/extensions/repository/RemoteModuleRepository.java @@ -30,17 +30,13 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.PosixFilePermissions; +import java.util.List; import java.util.Optional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.SystemUtils; import org.yaml.snakeyaml.Yaml; -/** - * - * @author t.marx - * @param - */ @Slf4j @RequiredArgsConstructor public class RemoteModuleRepository { @@ -51,70 +47,66 @@ public class RemoteModuleRepository { .build(); private final Class type; - private final String baseUrl; + private final List baseUrls; public boolean exists(String id) { - try { - var moduleInfoUrl = baseUrl + "/main/%s/%s.yaml" - .formatted(id, id); - - URI uri = URI.create(moduleInfoUrl); - HttpRequest request = HttpRequest.newBuilder(uri).build(); - return client.send(request, HttpResponse.BodyHandlers.ofString()).statusCode() == 200; - } catch (IOException | InterruptedException ex) { - log.error("", ex); + for (String baseUrl : baseUrls) { + try { + String moduleInfoUrl = baseUrl + "/%s/%s.yaml".formatted(id, id); + URI uri = URI.create(moduleInfoUrl); + HttpRequest request = HttpRequest.newBuilder(uri).build(); + int status = client.send(request, HttpResponse.BodyHandlers.ofString()).statusCode(); + if (status == 200) { + return true; + } + } catch (IOException | InterruptedException ex) { + log.warn("Failed checking existence at {}: {}", baseUrl, ex.getMessage()); + } } - return false; } public Optional getInfo(String extension) { - try { - var moduleInfoUrl = baseUrl + "/main/%s/%s.yaml" - .formatted(extension, extension); - - URI uri = URI.create(moduleInfoUrl); - HttpRequest request = HttpRequest.newBuilder(uri) - .build(); - final HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - if (response.statusCode() != 200) { - return Optional.empty(); + for (String baseUrl : baseUrls) { + try { + String moduleInfoUrl = baseUrl + "/%s/%s.yaml".formatted(extension, extension); + URI uri = URI.create(moduleInfoUrl); + HttpRequest request = HttpRequest.newBuilder(uri).build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() == 200) { + String content = response.body(); + return Optional.of(new Yaml().loadAs(content, type)); + } + } catch (IOException | InterruptedException ex) { + log.warn("Failed loading info from {}: {}", baseUrl, ex.getMessage()); } - String content = response.body(); - - return Optional.of(new Yaml().loadAs(content, type)); - } catch (IOException | InterruptedException ex) { - log.error("", ex); } - return Optional.empty(); } public void download(String url, Path target) { - try { Path tempDirectory = Files.createTempDirectory("modules"); if (SystemUtils.IS_OS_UNIX) { Files.setPosixFilePermissions(tempDirectory, PosixFilePermissions.fromString("rwx------")); } else { - var f = tempDirectory.toFile(); + File f = tempDirectory.toFile(); f.setReadable(true, true); f.setWritable(true, true); f.setExecutable(true, true); } - var request = HttpRequest.newBuilder(URI.create(url)).GET().build(); + HttpRequest request = HttpRequest.newBuilder(URI.create(url)).GET().build(); HttpResponse response = client.send( request, HttpResponse.BodyHandlers.ofFile(tempDirectory.resolve(System.currentTimeMillis() + ".zip"))); - var downloaded = response.body(); - + Path downloaded = response.body(); File moduleTempDir = InstallationHelper.unpackArchive(downloaded.toFile(), tempDirectory.toFile()); - InstallationHelper.moveDirectoy(moduleTempDir, target.resolve(moduleTempDir.getName()).toFile()); + } catch (Exception ex) { - log.error("", ex); + log.error("Error downloading module: {}", ex.getMessage(), ex); throw new RuntimeException("error downloading module"); } } diff --git a/cms-extensions/src/main/java/com/condation/cms/extensions/repository/RemoteRepository.java b/cms-extensions/src/main/java/com/condation/cms/extensions/repository/RemoteRepository.java index 2d17de462..3969aa5c8 100644 --- a/cms-extensions/src/main/java/com/condation/cms/extensions/repository/RemoteRepository.java +++ b/cms-extensions/src/main/java/com/condation/cms/extensions/repository/RemoteRepository.java @@ -22,70 +22,73 @@ * #L% */ - import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse.BodyHandlers; +import java.util.List; import java.util.Optional; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.yaml.snakeyaml.Yaml; -/** - * - * @author t.marx - */ @Slf4j +@RequiredArgsConstructor public class RemoteRepository { - HttpClient client = HttpClient.newHttpClient(); - - public boolean exists (String extension) { - try { - var moduleInfoUrl = "https://raw.githubusercontent.com/CondationCMS/extension-registry/main/%s/%s.yaml" - .formatted(extension, extension); - - URI uri = URI.create(moduleInfoUrl); - HttpRequest request = HttpRequest.newBuilder(uri).build(); - return client.send(request, BodyHandlers.ofString()).statusCode() == 200; - } catch (IOException | InterruptedException ex) { - log.error("", ex); - } - - return false; + private final HttpClient client = HttpClient.newHttpClient(); + private final List baseUrls; + + public boolean exists(String extension) { + return baseUrls.stream().anyMatch(baseUrl -> { + String url = baseUrl + "%s%s/%s.yaml".formatted( + baseUrl.endsWith("/") ? "" : "/", + extension, + extension); + try { + HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build(); + int statusCode = client.send(request, BodyHandlers.ofString()).statusCode(); + return statusCode == 200; + } catch (IOException | InterruptedException ex) { + log.warn("Failed checking existence at {}: {}", url, ex.getMessage()); + return false; + } + }); } - - public Optional getContent (String extension) { - try { - var moduleInfoUrl = "https://raw.githubusercontent.com/CondationCMS/extension-registry/main/%s/%s.js" - .formatted(extension, extension); - - URI uri = URI.create(moduleInfoUrl); - HttpRequest request = HttpRequest.newBuilder(uri).build(); - return Optional.of(client.send(request, BodyHandlers.ofString()).body()); - } catch (IOException | InterruptedException ex) { - log.error("", ex); + + public Optional getContent(String extension) { + for (String baseUrl : baseUrls) { + String url = baseUrl + "%s%s/%s.js".formatted( + baseUrl.endsWith("/") ? "" : "/", + extension, + extension); + try { + HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build(); + String body = client.send(request, BodyHandlers.ofString()).body(); + return Optional.ofNullable(body); + } catch (IOException | InterruptedException ex) { + log.warn("Failed loading content from {}: {}", url, ex.getMessage()); + } } - return Optional.empty(); } - - public Optional getInfo (String extension) { - try { - var moduleInfoUrl = "https://raw.githubusercontent.com/CondationCMS/extension-registry/main/%s/%s.yaml" - .formatted(extension, extension); - - URI uri = URI.create(moduleInfoUrl); - HttpRequest request = HttpRequest.newBuilder(uri).build(); - String content = client.send(request, BodyHandlers.ofString()).body(); - - - return Optional.of(new Yaml().loadAs(content, ExtensionInfo.class)); - } catch (IOException | InterruptedException ex) { - log.error("", ex); + + public Optional getInfo(String extension) { + for (String baseUrl : baseUrls) { + String url = baseUrl + "%s%s/%s.yaml".formatted( + baseUrl.endsWith("/") ? "" : "/", + extension, + extension); + try { + HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build(); + String content = client.send(request, BodyHandlers.ofString()).body(); + ExtensionInfo info = new Yaml().loadAs(content, ExtensionInfo.class); + return Optional.of(info); + } catch (IOException | InterruptedException ex) { + log.warn("Failed loading info from {}: {}", url, ex.getMessage()); + } } - return Optional.empty(); } } diff --git a/cms-extensions/src/test/java/com/condation/cms/extensions/repository/RemoteModuleRepositoryTest.java b/cms-extensions/src/test/java/com/condation/cms/extensions/repository/RemoteModuleRepositoryTest.java index 35ac26672..7ffcd250a 100644 --- a/cms-extensions/src/test/java/com/condation/cms/extensions/repository/RemoteModuleRepositoryTest.java +++ b/cms-extensions/src/test/java/com/condation/cms/extensions/repository/RemoteModuleRepositoryTest.java @@ -4,7 +4,7 @@ * #%L * cms-extensions * %% - * Copyright (C) 2023 - 2024 CondationCMS + * Copyright (C) 2023 - 2025 CondationCMS * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as @@ -22,52 +22,112 @@ * #L% */ +import com.sun.net.httpserver.HttpServer; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.*; -import com.condation.cms.extensions.repository.RemoteModuleRepository; -import com.condation.cms.extensions.repository.ModuleInfo; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.Test; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Optional; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; -/** - * - * @author t.marx - */ -public class RemoteModuleRepositoryTest { - - - RemoteModuleRepository moduleRepository = new RemoteModuleRepository<>( - ModuleInfo.class, - "https://raw.githubusercontent.com/CondationCMS/module-registry" - ); - - @Test - public void test_exist() { - Assertions.assertThat(moduleRepository.exists("none-module")).isFalse(); - - Assertions.assertThat(moduleRepository.exists("downloads-module")).isTrue(); - } - - @Test - public void test_info() { - Assertions.assertThat(moduleRepository.getInfo("none-module")).isEmpty(); - - Assertions.assertThat(moduleRepository.getInfo("downloads-module")) - .isPresent() - .get() - .isInstanceOf(ModuleInfo.class) - ; - } - - @Test - public void test_download() throws IOException { - var moduleInfo = moduleRepository.getInfo("downloads-module").get(); - - var modulesPath = Path.of("target/modules-" + System.currentTimeMillis()); - Files.createDirectories(modulesPath); - - moduleRepository.download(moduleInfo.getFile(), modulesPath); +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class RemoteModuleRepositoryTest { + + private HttpServer server1; + private HttpServer server2; + + private String baseUrl1; + private String baseUrl2; + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class DummyExtensionInfo { + String name; + String version; } + + @BeforeAll + void setupServers() throws IOException { + server1 = HttpServer.create(new InetSocketAddress(0), 0); + server2 = HttpServer.create(new InetSocketAddress(0), 0); + + int port1 = server1.getAddress().getPort(); + int port2 = server2.getAddress().getPort(); + + baseUrl1 = "http://localhost:" + port1 + "/main"; + baseUrl2 = "http://localhost:" + port2 + "/main"; + + // Server 1: only provides moduleA + server1.createContext("/main/moduleA/moduleA.yaml", exchange -> { + String yaml = "name: ModuleA\nversion: 1.0"; + exchange.sendResponseHeaders(200, yaml.getBytes().length); + try (OutputStream os = exchange.getResponseBody()) { + os.write(yaml.getBytes(StandardCharsets.UTF_8)); + } + }); + + // Server 2: only provides moduleB + server2.createContext("/main/moduleB/moduleB.yaml", exchange -> { + String yaml = "name: ModuleB\nversion: 2.0"; + exchange.sendResponseHeaders(200, yaml.getBytes().length); + try (OutputStream os = exchange.getResponseBody()) { + os.write(yaml.getBytes(StandardCharsets.UTF_8)); + } + }); + + server1.start(); + server2.start(); + } + + @AfterAll + void tearDown() { + server1.stop(0); + server2.stop(0); + } + + @Test + void shouldLoadModuleFromFirstRepository() { + var repo = new RemoteModuleRepository<>(DummyExtensionInfo.class, List.of(baseUrl1, baseUrl2)); + + Optional result = repo.getInfo("moduleA"); + + Assertions.assertThat(result) + .isPresent() + .get() + .satisfies(info -> { + Assertions.assertThat(info.getName()).isEqualTo("ModuleA"); + Assertions.assertThat(info.getVersion()).isEqualTo("1.0"); + }); + } + + @Test + void shouldLoadModuleFromSecondRepositoryIfNotInFirst() { + var repo = new RemoteModuleRepository<>(DummyExtensionInfo.class, List.of(baseUrl1, baseUrl2)); + + Optional result = repo.getInfo("moduleB"); + + Assertions.assertThat(result) + .isPresent() + .get() + .satisfies(info -> { + Assertions.assertThat(info.getName()).isEqualTo("ModuleB"); + Assertions.assertThat(info.getVersion()).isEqualTo("2.0"); + }); + } + + @Test + void shouldReturnEmptyIfModuleNotFoundInAnyRepository() { + var repo = new RemoteModuleRepository<>(DummyExtensionInfo.class, List.of(baseUrl1, baseUrl2)); + + Optional result = repo.getInfo("unknownModule"); + + Assertions.assertThat(result).isNotPresent(); + } } diff --git a/cms-extensions/src/test/java/com/condation/cms/extensions/repository/RepositoryTest.java b/cms-extensions/src/test/java/com/condation/cms/extensions/repository/RepositoryTest.java index ba9c7f2ab..d1d5b402b 100644 --- a/cms-extensions/src/test/java/com/condation/cms/extensions/repository/RepositoryTest.java +++ b/cms-extensions/src/test/java/com/condation/cms/extensions/repository/RepositoryTest.java @@ -23,8 +23,8 @@ */ -import com.condation.cms.extensions.repository.RemoteRepository; -import org.assertj.core.api.Assertions; +import java.util.List; + import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -35,7 +35,7 @@ public class RepositoryTest { @Test public void getInfo() { - RemoteRepository repository = new RemoteRepository(); + RemoteRepository repository = new RemoteRepository(List.of("https://raw.githubusercontent.com/CondationCMS/extension-registry/main")); var info = repository.getInfo("test-extension"); diff --git a/cms-server/src/main/java/com/condation/cms/cli/commands/extensions/AbstractExtensionCommand.java b/cms-server/src/main/java/com/condation/cms/cli/commands/extensions/AbstractExtensionCommand.java index da57199e7..7b0ec27a6 100644 --- a/cms-server/src/main/java/com/condation/cms/cli/commands/extensions/AbstractExtensionCommand.java +++ b/cms-server/src/main/java/com/condation/cms/cli/commands/extensions/AbstractExtensionCommand.java @@ -21,28 +21,58 @@ * . * #L% */ - - - import com.condation.cms.CMSServer; +import com.condation.cms.api.ServerProperties; +import com.condation.cms.core.configuration.ConfigurationFactory; +import com.condation.cms.core.configuration.properties.ExtendedServerProperties; import com.condation.cms.extensions.repository.RemoteRepository; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; /** * * @author t.marx */ +@Slf4j public abstract class AbstractExtensionCommand { + public static final String DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/CondationCMS/extension-registry/main"; + @Getter - private RemoteRepository repository = new RemoteRepository(); + private RemoteRepository repository = new RemoteRepository(getRepositories()); + + private List getRepositories() { + List repos = new ArrayList<>(); + repos.add(DEFAULT_REGISTRY_URL); + + try { + ServerProperties properties = new ExtendedServerProperties(ConfigurationFactory.serverConfiguration()); + + if (properties.extensionRepositories()!= null) { + var modUrls = properties.extensionRepositories().stream().map(url -> { + if (url.endsWith("/")) { + return url.substring(0, url.length() - 1); + } + return url; + }).toList(); + repos.addAll(modUrls); + } + } catch (IOException e) { + log.error("", e); + } + + return repos; + } public boolean isCompatibleWithServer(String extension) { var info = repository.getInfo(extension); if (info.isEmpty()) { throw new RuntimeException("extension not found"); } - + return CMSServer.getVersion().satisfies(info.get().getCompatibility()); } } diff --git a/cms-server/src/main/java/com/condation/cms/cli/commands/extensions/InfoCommand.java b/cms-server/src/main/java/com/condation/cms/cli/commands/extensions/InfoCommand.java index f0f764439..c4283a27c 100644 --- a/cms-server/src/main/java/com/condation/cms/cli/commands/extensions/InfoCommand.java +++ b/cms-server/src/main/java/com/condation/cms/cli/commands/extensions/InfoCommand.java @@ -36,9 +36,7 @@ * @author t.marx */ @CommandLine.Command(name = "info") -public class InfoCommand implements Runnable { - - RemoteRepository repository = new RemoteRepository(); +public class InfoCommand extends AbstractExtensionCommand implements Runnable { @CommandLine.Parameters( paramLabel = "", @@ -54,12 +52,12 @@ public void run() { System.err.println("please provide extension name"); return; } - if (!repository.exists(extension)) { + if (!getRepository().exists(extension)) { System.err.printf("extension %s not found\r\n", extension); return; } - final Optional extInfo = repository.getInfo(extension); + final Optional extInfo = getRepository().getInfo(extension); var info = extInfo.get(); System.out.println("extension: " + info.getId()); diff --git a/cms-server/src/main/java/com/condation/cms/cli/commands/extensions/InstallCommand.java b/cms-server/src/main/java/com/condation/cms/cli/commands/extensions/InstallCommand.java index 0d7daebdb..dcd31ee41 100644 --- a/cms-server/src/main/java/com/condation/cms/cli/commands/extensions/InstallCommand.java +++ b/cms-server/src/main/java/com/condation/cms/cli/commands/extensions/InstallCommand.java @@ -44,7 +44,6 @@ @CommandLine.Command(name = "install") public class InstallCommand extends AbstractExtensionCommand implements Runnable { - RemoteRepository repository = new RemoteRepository(); @CommandLine.Parameters( paramLabel = "", @@ -72,13 +71,13 @@ public void run() { return; } - if (repository.exists(extension)) { + if (getRepository().exists(extension)) { if (!isCompatibleWithServer(extension)) { throw new RuntimeException("the extension is not compatible with server version"); } - Optional content = repository.getContent(extension); + Optional content = getRepository().getContent(extension); if (content.isEmpty()) { System.err.println("the extension content not found"); return; diff --git a/cms-server/src/main/java/com/condation/cms/cli/commands/modules/AbstractModuleCommand.java b/cms-server/src/main/java/com/condation/cms/cli/commands/modules/AbstractModuleCommand.java index be7ac516b..f312b66fd 100644 --- a/cms-server/src/main/java/com/condation/cms/cli/commands/modules/AbstractModuleCommand.java +++ b/cms-server/src/main/java/com/condation/cms/cli/commands/modules/AbstractModuleCommand.java @@ -25,13 +25,18 @@ import com.condation.cms.CMSServer; +import com.condation.cms.api.ServerProperties; import com.condation.cms.api.utils.ServerUtil; +import com.condation.cms.core.configuration.ConfigurationFactory; +import com.condation.cms.core.configuration.properties.ExtendedServerProperties; import com.condation.cms.extensions.repository.ModuleInfo; import com.condation.cms.extensions.repository.RemoteModuleRepository; import java.io.IOException; import java.io.StringReader; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import java.util.Properties; import lombok.Getter; @@ -44,11 +49,35 @@ @Slf4j public abstract class AbstractModuleCommand { - public static final String DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/CondationCMS/module-registry"; + public static final String DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/CondationCMS/module-registry/main"; @Getter - private RemoteModuleRepository repository = new RemoteModuleRepository(ModuleInfo.class, DEFAULT_REGISTRY_URL); + private RemoteModuleRepository repository = new RemoteModuleRepository(ModuleInfo.class, getRepositories()); + private List getRepositories () { + List repos = new ArrayList<>(); + repos.add(DEFAULT_REGISTRY_URL); + + try { + ServerProperties properties = new ExtendedServerProperties(ConfigurationFactory.serverConfiguration()); + + if (properties.moduleRepositories() != null) { + var modUrls = properties.moduleRepositories().stream().map(url -> { + if (url.endsWith("/")) { + return url.substring(0, url.length() - 1); + } + return url; + }).toList(); + repos.addAll(modUrls); + } + } catch (IOException e) { + log.error("", e); + } + + + return repos; + } + public boolean isCompatibleWithServer(String extension) { var info = repository.getInfo(extension); if (info.isEmpty()) { diff --git a/cms-server/src/main/java/com/condation/cms/cli/commands/themes/AbstractThemeCommand.java b/cms-server/src/main/java/com/condation/cms/cli/commands/themes/AbstractThemeCommand.java index 53a2a3b58..36edf93ca 100644 --- a/cms-server/src/main/java/com/condation/cms/cli/commands/themes/AbstractThemeCommand.java +++ b/cms-server/src/main/java/com/condation/cms/cli/commands/themes/AbstractThemeCommand.java @@ -25,14 +25,18 @@ import com.condation.cms.CMSServer; import com.condation.cms.api.Constants; +import com.condation.cms.api.ServerProperties; import com.condation.cms.api.utils.ServerUtil; import com.condation.cms.core.configuration.ConfigurationFactory; +import com.condation.cms.core.configuration.properties.ExtendedServerProperties; import com.condation.cms.core.configuration.properties.ExtendedThemeProperties; import com.condation.cms.extensions.repository.ModuleInfo; import com.condation.cms.extensions.repository.RemoteModuleRepository; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -44,11 +48,35 @@ @Slf4j public abstract class AbstractThemeCommand { - public static final String DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/CondationCMS/theme-registry"; + public static final String DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/CondationCMS/theme-registry/main"; @Getter - private RemoteModuleRepository repository = new RemoteModuleRepository(ModuleInfo.class, DEFAULT_REGISTRY_URL); + private RemoteModuleRepository repository = new RemoteModuleRepository(ModuleInfo.class, getRepositories()); + private List getRepositories () { + List repos = new ArrayList<>(); + repos.add(DEFAULT_REGISTRY_URL); + + try { + ServerProperties properties = new ExtendedServerProperties(ConfigurationFactory.serverConfiguration()); + + if (properties.themeRepositories() != null) { + var modUrls = properties.moduleRepositories().stream().map(url -> { + if (url.endsWith("/")) { + return url.substring(0, url.length() - 1); + } + return url; + }).toList(); + repos.addAll(modUrls); + } + } catch (IOException e) { + log.error("", e); + } + + + return repos; + } + protected static Path getThemeFolder (String theme) { return ServerUtil.getPath(Constants.Folders.THEMES).resolve(theme); } diff --git a/cms-server/src/test/java/com/condation/cms/cli/commands/extensions/InfoCommandTest.java b/cms-server/src/test/java/com/condation/cms/cli/commands/extensions/InfoCommandTest.java index 80b45dbd9..0ef685dce 100644 --- a/cms-server/src/test/java/com/condation/cms/cli/commands/extensions/InfoCommandTest.java +++ b/cms-server/src/test/java/com/condation/cms/cli/commands/extensions/InfoCommandTest.java @@ -24,7 +24,6 @@ -import com.condation.cms.cli.commands.extensions.InfoCommand; import org.junit.jupiter.api.Test; /**