From d9aec2e986337203193d8eab887ad16ca4491c01 Mon Sep 17 00:00:00 2001 From: kirillius Date: Mon, 6 Oct 2025 14:21:45 +0300 Subject: [PATCH] =?UTF-8?q?=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=20=D1=81=D0=BB=D1=83=D0=B6=D0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/pom.xml | 32 +++++++ .../main/java/ru/kirillius/pf/sdn/App.java | 6 ++ .../kirillius/pf/sdn/InMemoryLogHandler.java | 4 + .../ru/kirillius/pf/sdn/web/RPC/Auth.java | 6 ++ .../ru/kirillius/pf/sdn/web/RPC/System.java | 30 +++++++ app/src/main/resources/htdocs/index.html | 10 --- .../java/ru/kirillius/pf/sdn/core/Config.java | 84 +++++++++++++++++-- 7 files changed, 155 insertions(+), 17 deletions(-) delete mode 100644 app/src/main/resources/htdocs/index.html diff --git a/app/pom.xml b/app/pom.xml index 586ab55..5ecc83d 100644 --- a/app/pom.xml +++ b/app/pom.xml @@ -89,6 +89,7 @@ exec-maven-plugin 3.5.0 + prepare-package @@ -102,6 +103,37 @@ + + + npm-install + prepare-package + + exec + + + npm + + install + + ${project.basedir}/../webui + + + + + npm-build + prepare-package + + exec + + + npm + + run + build + + ${project.basedir}/../webui + + diff --git a/app/src/main/java/ru/kirillius/pf/sdn/App.java b/app/src/main/java/ru/kirillius/pf/sdn/App.java index 81f80c5..16ebd9e 100644 --- a/app/src/main/java/ru/kirillius/pf/sdn/App.java +++ b/app/src/main/java/ru/kirillius/pf/sdn/App.java @@ -5,12 +5,14 @@ import lombok.SneakyThrows; import ru.kirillius.pf.sdn.External.API.Components.FRR; import ru.kirillius.pf.sdn.External.API.Components.OVPN; import ru.kirillius.pf.sdn.External.API.Components.TDNS; +import ru.kirillius.pf.sdn.External.API.GitSubscription; import ru.kirillius.pf.sdn.External.API.HEInfoProvider; import ru.kirillius.pf.sdn.core.*; import ru.kirillius.pf.sdn.core.Auth.AuthManager; import ru.kirillius.pf.sdn.core.Auth.TokenService; import ru.kirillius.pf.sdn.core.Networking.BGPInfoService; import ru.kirillius.pf.sdn.core.Networking.NetworkingService; +import ru.kirillius.pf.sdn.core.Subscription.RepositoryConfig; import ru.kirillius.pf.sdn.core.Subscription.SubscriptionService; import ru.kirillius.pf.sdn.core.Util.Wait; import ru.kirillius.pf.sdn.web.WebService; @@ -19,6 +21,7 @@ import ru.kirillius.utils.logging.SystemLogger; import java.io.Closeable; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; @@ -55,6 +58,9 @@ public class App implements Context, Closeable { loadedConfig = Config.load(launcherConfig.getConfigFile()); } catch (IOException e) { loadedConfig = new Config(); + loadedConfig.setSubscriptions(new ArrayList<>(List.of( + new RepositoryConfig("updates", GitSubscription.class, "https://git.kirillius.ru/kirillius/protected-resources-list.git") + ))); try { Config.store(loadedConfig, launcherConfig.getConfigFile()); } catch (IOException ex) { diff --git a/app/src/main/java/ru/kirillius/pf/sdn/InMemoryLogHandler.java b/app/src/main/java/ru/kirillius/pf/sdn/InMemoryLogHandler.java index 71b28b7..06dcc0a 100644 --- a/app/src/main/java/ru/kirillius/pf/sdn/InMemoryLogHandler.java +++ b/app/src/main/java/ru/kirillius/pf/sdn/InMemoryLogHandler.java @@ -29,6 +29,10 @@ public class InMemoryLogHandler extends Handler { return Collections.unmodifiableCollection(queue); } + public static void clear() { + queue.clear(); + } + /** * Stores the formatted message in the buffer, trimming old entries when full. */ diff --git a/app/src/main/java/ru/kirillius/pf/sdn/web/RPC/Auth.java b/app/src/main/java/ru/kirillius/pf/sdn/web/RPC/Auth.java index ba635a1..21b716f 100644 --- a/app/src/main/java/ru/kirillius/pf/sdn/web/RPC/Auth.java +++ b/app/src/main/java/ru/kirillius/pf/sdn/web/RPC/Auth.java @@ -36,6 +36,12 @@ public class Auth implements RPC { return JSONUtility.serializeCollection(context.getServiceManager().getService(TokenService.class).getTokens(), AuthToken.class, null); } + @ProtectedMethod + @JRPCMethod + public void changePassword(@JRPCArgument(name = "password") String password) { + context.getServiceManager().getService(AuthManager.class).updatePassword(password); + } + /** * Removes a token identified by its raw value. */ diff --git a/app/src/main/java/ru/kirillius/pf/sdn/web/RPC/System.java b/app/src/main/java/ru/kirillius/pf/sdn/web/RPC/System.java index 65b3680..7c82cc5 100644 --- a/app/src/main/java/ru/kirillius/pf/sdn/web/RPC/System.java +++ b/app/src/main/java/ru/kirillius/pf/sdn/web/RPC/System.java @@ -5,6 +5,8 @@ import org.json.JSONObject; import ru.kirillius.json.JSONUtility; import ru.kirillius.json.rpc.Annotations.JRPCArgument; import ru.kirillius.json.rpc.Annotations.JRPCMethod; +import ru.kirillius.pf.sdn.External.API.GitSubscription; +import ru.kirillius.pf.sdn.InMemoryLogHandler; import ru.kirillius.pf.sdn.core.*; import ru.kirillius.pf.sdn.web.ProtectedMethod; @@ -51,6 +53,14 @@ public class System implements RPC { return JSONUtility.serializeStructure(context.getConfig()); } + @ProtectedMethod + @JRPCMethod + public void setConfig(@JRPCArgument(name = "config") JSONObject json) { + var config = JSONUtility.deserializeStructure(json, Config.class); + context.getConfig().merge(config); + } + + /** * Indicates whether the configuration has unsaved changes. */ @@ -109,6 +119,14 @@ public class System implements RPC { updateService.updateApp(); } + @ProtectedMethod + @JRPCMethod + public JSONArray getRepositoryTypes() { + var array = new JSONArray(); + array.put(GitSubscription.class.getName()); + return array; + } + /** * Returns the list of enabled component class names. */ @@ -171,4 +189,16 @@ public class System implements RPC { context.getServiceManager().getService(ComponentHandlerService.class).reloadComponents(cls); context.getConfig().getComponentsConfig().getConfig(cls); } + + @ProtectedMethod + @JRPCMethod + public JSONArray getLogs() { + return JSONUtility.serializeCollection(InMemoryLogHandler.getMessages(), String.class, null); + } + + @ProtectedMethod + @JRPCMethod + public void clearLogs() { + InMemoryLogHandler.clear(); + } } diff --git a/app/src/main/resources/htdocs/index.html b/app/src/main/resources/htdocs/index.html deleted file mode 100644 index 4a4ea78..0000000 --- a/app/src/main/resources/htdocs/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Title - - -test ok - - \ No newline at end of file diff --git a/core/src/main/java/ru/kirillius/pf/sdn/core/Config.java b/core/src/main/java/ru/kirillius/pf/sdn/core/Config.java index 5e716a5..a83159b 100644 --- a/core/src/main/java/ru/kirillius/pf/sdn/core/Config.java +++ b/core/src/main/java/ru/kirillius/pf/sdn/core/Config.java @@ -24,16 +24,25 @@ import java.util.UUID; @NoArgsConstructor @JSONSerializable public class Config { + /** + * Update subscriptions every N hours + */ @Getter @Setter @JSONProperty private volatile int updateSubscriptionsInterval = 6; + /** + * Remember downloaded ASN prefixes + */ @Getter @Setter @JSONProperty private volatile boolean cachingAS = true; + /** + * Update ASN prefixes every N hours + */ @Getter @Setter @JSONProperty @@ -41,77 +50,138 @@ public class Config { @Getter private volatile File loadedConfigFile = null; + /** + * Web interface host + */ @Setter @Getter @JSONProperty private volatile String host = "0.0.0.0"; + /** + * Path where to store temporary data + */ + + @Setter @Getter @JSONProperty private volatile File cacheDirectory = new File("./.cache"); + /** + * List of subscription sources + */ @Setter @Getter @JSONArrayProperty(type = RepositoryConfig.class) - private volatile List subscriptions = Collections.emptyList(); + private volatile List subscriptions = new ArrayList<>(); + /** + * List of subscribed resources + */ @Setter @Getter @JSONArrayProperty(type = String.class) private volatile List subscribedResources = Collections.emptyList(); - + /** + * Config of every component + */ @Setter @Getter @JSONProperty(required = false) private volatile ComponentConfigStorage componentsConfig = new ComponentConfigStorage(); + /** + * List of enabled components + */ @Setter @Getter @JSONArrayProperty(type = Class.class, required = false) private volatile List>> enabledComponents = new ArrayList<>(); - + /** + * Special hash salt for password hashing + */ @Setter @Getter @JSONProperty private volatile String passwordSalt = UUID.randomUUID().toString(); + /** + * Password hash + */ @Setter @Getter @JSONProperty private volatile String passwordHash = ""; - + /** + * Web service listen port + */ @Setter @Getter @JSONProperty private volatile int httpPort = 8081; + /** + * Use special algorithm to minify prefix count + */ @Setter @Getter @JSONProperty private volatile boolean mergeSubnets = true; - + /** + * Display debug info in logs + */ @Setter @Getter @JSONProperty private volatile boolean displayDebuggingInfo = true; - + /** + * Merge two subnets into one bigger subnet when new subnet will be used more or equals this percents + */ @Setter @Getter @JSONProperty private volatile int mergeSubnetsWithUsage = 51; + /** + * Custom routing config + */ @Setter @Getter @JSONProperty private volatile NetworkResourceBundle customResources = new NetworkResourceBundle(); - + /** + * Ignore these resources + */ @Setter @Getter @JSONProperty private volatile NetworkResourceBundle filteredResources = new NetworkResourceBundle(); + public void merge(Config other) { + if (other == null) { + return; + } + + setUpdateSubscriptionsInterval(other.getUpdateSubscriptionsInterval()); + setCachingAS(other.isCachingAS()); + setUpdateASInterval(other.getUpdateASInterval()); + setHost(other.getHost()); + setCacheDirectory(other.getCacheDirectory()); + setSubscriptions(other.getSubscriptions()); + setSubscribedResources(other.getSubscribedResources()); + setEnabledComponents(other.getEnabledComponents()); + setPasswordSalt(other.getPasswordSalt()); + setPasswordHash(other.getPasswordHash()); + setHttpPort(other.getHttpPort()); + setMergeSubnets(other.isMergeSubnets()); + setDisplayDebuggingInfo(other.isDisplayDebuggingInfo()); + setMergeSubnetsWithUsage(other.getMergeSubnetsWithUsage()); + setCustomResources(other.getCustomResources()); + setFilteredResources(other.getFilteredResources()); + } + /** * Persists the given configuration into the supplied file as JSON. */