From 4f3f2bbfd2664a3146177ca19f491a8ee960171a Mon Sep 17 00:00:00 2001 From: crschnick Date: Fri, 21 Jun 2024 18:20:35 +0000 Subject: [PATCH] Various fixes --- app/build.gradle | 2 +- .../xpipe/app/comp/base/ListBoxViewComp.java | 2 +- .../xpipe/app/comp/base/ListSelectorComp.java | 2 +- .../app/comp/store/StoreSectionComp.java | 2 +- .../xpipe/app/core/AppExtensionManager.java | 18 +++++++++- .../io/xpipe/app/issue/UserReportComp.java | 1 + .../app/util/LicenseConnectionLimit.java | 30 ---------------- .../io/xpipe/app/util/LicensedFeature.java | 6 +--- .../io/xpipe/app/resources/misc/api.md | 2 ++ .../resources/style/error-handler-comp.css | 2 +- .../app/resources/style/store-entry-comp.css | 4 +-- .../resources/style/store-mini-section.css | 6 +--- .../io/xpipe/app/resources/style/style.css | 8 +++++ .../base/service/AbstractServiceStore.java | 3 +- .../ext/base/service/ServiceLicenseCheck.java | 35 ------------------- openapi.yaml | 2 ++ 16 files changed, 41 insertions(+), 84 deletions(-) delete mode 100644 app/src/main/java/io/xpipe/app/util/LicenseConnectionLimit.java delete mode 100644 ext/base/src/main/java/io/xpipe/ext/base/service/ServiceLicenseCheck.java diff --git a/app/build.gradle b/app/build.gradle index b7788035..613c5fe1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -51,7 +51,7 @@ dependencies { api files("$rootDir/gradle/gradle_scripts/markdowngenerator-1.3.1.1.jar") api files("$rootDir/gradle/gradle_scripts/vernacular-1.16.jar") api 'info.picocli:picocli:4.7.6' - api ('org.kohsuke:github-api:1.321') { + api ('org.kohsuke:github-api:1.322') { exclude group: 'org.apache.commons', module: 'commons-lang3' } api 'org.apache.commons:commons-lang3:3.14.0' diff --git a/app/src/main/java/io/xpipe/app/comp/base/ListBoxViewComp.java b/app/src/main/java/io/xpipe/app/comp/base/ListBoxViewComp.java index fc7bdda0..c2c96770 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/ListBoxViewComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/ListBoxViewComp.java @@ -41,7 +41,7 @@ public class ListBoxViewComp extends Comp> { Map cache = new IdentityHashMap<>(); VBox vbox = new VBox(); - vbox.getStyleClass().add("content"); + vbox.getStyleClass().add("list-box-content"); vbox.setFocusTraversable(false); refresh(vbox, shown, all, cache, false); diff --git a/app/src/main/java/io/xpipe/app/comp/base/ListSelectorComp.java b/app/src/main/java/io/xpipe/app/comp/base/ListSelectorComp.java index 3bafb76a..c0c5f70e 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/ListSelectorComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/ListSelectorComp.java @@ -34,7 +34,7 @@ public class ListSelectorComp extends SimpleComp { protected Region createSimple() { var vbox = new VBox(); vbox.setSpacing(8); - vbox.getStyleClass().add("content"); + vbox.getStyleClass().add("list-content"); var cbs = new ArrayList(); for (var v : values) { var cb = new CheckBox(null); diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreSectionComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreSectionComp.java index 16bdba27..1c147133 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreSectionComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreSectionComp.java @@ -151,7 +151,7 @@ public class StoreSectionComp extends Comp> { topEntryList, Comp.separator().hide(expanded.not()), new HorizontalComp(List.of(content)) - .styleClass("content") + .styleClass("children-content") .apply(struc -> struc.get().setFillHeight(true)) .hide(Bindings.or( Bindings.not(section.getWrapper().getExpanded()), diff --git a/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java b/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java index a3061cec..28bbc553 100644 --- a/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java +++ b/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java @@ -46,6 +46,7 @@ public class AppExtensionManager { INSTANCE.determineExtensionDirectories(); INSTANCE.loadBaseExtension(); INSTANCE.loadAllExtensions(); + INSTANCE.loadUaccExtension(); } if (load) { @@ -139,7 +140,7 @@ public class AppExtensionManager { } private void loadAllExtensions() { - for (var ext : List.of("jdbc", "proc", "uacc")) { + for (var ext : List.of("jdbc", "proc")) { var extension = findAndParseExtension(ext, baseLayer) .orElseThrow(() -> ExtensionException.corrupt("Missing module " + ext)); loadedExtensions.add(extension); @@ -154,6 +155,21 @@ public class AppExtensionManager { .layer(); } + + private void loadUaccExtension() { + var extension = findAndParseExtension("uacc", extendedLayer) + .orElseThrow(() -> ExtensionException.corrupt("Missing module uacc")); + loadedExtensions.add(extension); + leafModuleLayers.add(extension.getModule().getLayer()); + + var scl = ClassLoader.getSystemClassLoader(); + var cfs = leafModuleLayers.stream().map(ModuleLayer::configuration).toList(); + var finder = ModuleFinder.ofSystem(); + var cf = Configuration.resolve(finder, cfs, finder, List.of()); + extendedLayer = ModuleLayer.defineModulesWithOneLoader(cf, leafModuleLayers, scl) + .layer(); + } + private Optional findAndParseExtension(String name, ModuleLayer parent) { var inModulePath = ModuleLayer.boot().findModule("io.xpipe.ext." + name); if (inModulePath.isPresent()) { diff --git a/app/src/main/java/io/xpipe/app/issue/UserReportComp.java b/app/src/main/java/io/xpipe/app/issue/UserReportComp.java index f11478d2..431b965a 100644 --- a/app/src/main/java/io/xpipe/app/issue/UserReportComp.java +++ b/app/src/main/java/io/xpipe/app/issue/UserReportComp.java @@ -106,6 +106,7 @@ public class UserReportComp extends SimpleComp { layout.setCenter(reportSection); layout.setBottom(buttons); layout.getStyleClass().add("error-report"); + layout.getStyleClass().add("background"); layout.setPrefWidth(600); layout.setPrefHeight(550); return layout; diff --git a/app/src/main/java/io/xpipe/app/util/LicenseConnectionLimit.java b/app/src/main/java/io/xpipe/app/util/LicenseConnectionLimit.java deleted file mode 100644 index ed07e2df..00000000 --- a/app/src/main/java/io/xpipe/app/util/LicenseConnectionLimit.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.xpipe.app.util; - -import io.xpipe.app.storage.DataStorage; -import io.xpipe.core.store.DataStore; - -public abstract class LicenseConnectionLimit { - - private final int limit; - private final LicensedFeature feature; - - public LicenseConnectionLimit(int limit, LicensedFeature feature) { - this.limit = limit; - this.feature = feature; - } - - protected abstract boolean matches(DataStore store); - - public void checkLimit() { - if (feature.isSupported()) { - return; - } - - var found = DataStorage.get().getStoreEntries().stream() - .filter(entry -> entry.getValidity().isUsable() && matches(entry.getStore())) - .toList(); - if (found.size() > limit) { - throw new LicenseRequiredException(feature, limit); - } - } -} diff --git a/app/src/main/java/io/xpipe/app/util/LicensedFeature.java b/app/src/main/java/io/xpipe/app/util/LicensedFeature.java index 768e503f..9ade0795 100644 --- a/app/src/main/java/io/xpipe/app/util/LicensedFeature.java +++ b/app/src/main/java/io/xpipe/app/util/LicensedFeature.java @@ -26,9 +26,5 @@ public interface LicensedFeature { boolean isPreviewSupported(); - default void throwIfUnsupported() throws LicenseRequiredException { - if (!isSupported()) { - throw new LicenseRequiredException(this); - } - } + void throwIfUnsupported() throws LicenseRequiredException; } diff --git a/app/src/main/resources/io/xpipe/app/resources/misc/api.md b/app/src/main/resources/io/xpipe/app/resources/misc/api.md index 6e975ee1..52c00a92 100644 --- a/app/src/main/resources/io/xpipe/app/resources/misc/api.md +++ b/app/src/main/resources/io/xpipe/app/resources/misc/api.md @@ -64,6 +64,8 @@ Prior to sending requests to the API, you first have to establish a new API sess In the response you will receive a session token that you can use to authenticate during this session. This is done so that the daemon knows what kind of clients are connected and can manage individual capabilities for clients. +If your client is running on the same system as the daemon, you can choose the local authentication method to avoid having to deal with API keys. +If your client does not have file system access, e.g. if it is running remotely, then you have to use an API key. Note that for development you can also turn off the required authentication in the XPipe settings menu, allowing you to send unauthenticated requests. diff --git a/app/src/main/resources/io/xpipe/app/resources/style/error-handler-comp.css b/app/src/main/resources/io/xpipe/app/resources/style/error-handler-comp.css index 2c5b7559..f554f5f4 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/error-handler-comp.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/error-handler-comp.css @@ -20,7 +20,7 @@ -fx-spacing: 0.3em; } -.error-report .attachments .attachment-list .content { +.error-report .attachments .attachment-list .list-box-content { -fx-padding: 0.5em 1em; } diff --git a/app/src/main/resources/io/xpipe/app/resources/style/store-entry-comp.css b/app/src/main/resources/io/xpipe/app/resources/style/store-entry-comp.css index 0fd65f19..77235336 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/store-entry-comp.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/store-entry-comp.css @@ -99,7 +99,7 @@ -fx-border-insets: 0px; } -.store-entry-section-comp > .content { +.store-entry-section-comp > .children-content { -fx-padding: 5px 0 5px 25px; } @@ -130,7 +130,7 @@ -fx-background-radius: 0; } -.store-entry-section-comp .list-box-view-comp .content { +.store-entry-section-comp .list-box-view-comp .list-box-content { -fx-spacing: 0.2em; } diff --git a/app/src/main/resources/io/xpipe/app/resources/style/store-mini-section.css b/app/src/main/resources/io/xpipe/app/resources/style/store-mini-section.css index 472674c8..06372a56 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/store-mini-section.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/store-mini-section.css @@ -1,7 +1,3 @@ -.store-mini-list-comp > * > * > .children-content { - -fx-spacing: 0.5em; -} - .store-mini-list-comp:root { -fx-border-color: transparent; -fx-background-color: transparent; @@ -118,7 +114,7 @@ -fx-border-color: -color-border-default; } -.store-section-mini-comp .list-box-view-comp .children-content { +.store-section-mini-comp:root .list-box-view-comp .list-box-content { -fx-spacing: 0.4em; } diff --git a/app/src/main/resources/io/xpipe/app/resources/style/style.css b/app/src/main/resources/io/xpipe/app/resources/style/style.css index f9620ee7..5ca46f97 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/style.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/style.css @@ -17,6 +17,14 @@ -fx-background-color: derive(-color-bg-default, -9%); } +.root:dark.background { + -fx-background-color: derive(-color-bg-default, 1%); +} + +.root:light.background { + -fx-background-color: derive(-color-bg-default, -9%); +} + .root:seamless-frame.layout > .background { -fx-background-insets: 5 0 0 0; -fx-border-insets: 5 0 0 0; diff --git a/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStore.java b/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStore.java index c0ebccf0..4e47171f 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStore.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStore.java @@ -2,6 +2,7 @@ package io.xpipe.ext.base.service; import io.xpipe.app.storage.DataStoreEntryRef; import io.xpipe.app.util.HostHelper; +import io.xpipe.app.util.LicenseProvider; import io.xpipe.app.util.Validators; import io.xpipe.core.store.*; import io.xpipe.core.util.JacksonizedValue; @@ -32,7 +33,7 @@ public abstract class AbstractServiceStore extends JacksonizedValue @Override public NetworkTunnelSession newSession() throws Exception { - ServiceLicenseCheck.check(); + LicenseProvider.get().getFeature("services").throwIfUnsupported(); var l = localPort != null ? localPort : HostHelper.findRandomOpenPortOnAllLocalInterfaces(); return getHost().getStore().sessionChain(l, remotePort); } diff --git a/ext/base/src/main/java/io/xpipe/ext/base/service/ServiceLicenseCheck.java b/ext/base/src/main/java/io/xpipe/ext/base/service/ServiceLicenseCheck.java deleted file mode 100644 index 427bad7a..00000000 --- a/ext/base/src/main/java/io/xpipe/ext/base/service/ServiceLicenseCheck.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.xpipe.ext.base.service; - -import io.xpipe.app.util.LicenseConnectionLimit; -import io.xpipe.app.util.LicenseProvider; -import io.xpipe.app.util.LicensedFeature; -import io.xpipe.core.store.DataStore; - -public class ServiceLicenseCheck { - - public static LicensedFeature getFeature() { - return LicenseProvider.get().getFeature("services"); - } - - public static void check() { - if (getFeature().isSupported()) { - return; - } - - var limit = getConnectionLimit(); - limit.checkLimit(); - } - - public static LicenseConnectionLimit getConnectionLimit() { - // We check before starting a new service - return new LicenseConnectionLimit(0, getFeature()) { - - @Override - protected boolean matches(DataStore store) { - return store instanceof AbstractServiceStore abstractServiceStore - && abstractServiceStore.requiresTunnel() - && abstractServiceStore.isSessionRunning(); - } - }; - } -} diff --git a/openapi.yaml b/openapi.yaml index 7b60b47e..d00f5fd8 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -39,6 +39,8 @@ paths: In the response you will receive a session token that you can use to authenticate during this session. This is done so that the daemon knows what kind of clients are connected and can manage individual capabilities for clients. + If your client is running on the same system as the daemon, you can choose the local authentication method to avoid having to deal with API keys. + If your client does not have file system access, e.g. if it is running remotely, then you have to use an API key. Note that for development you can also turn off the required authentication in the XPipe settings menu, allowing you to send unauthenticated requests. operationId: handshake