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.
*/