Various fixes

This commit is contained in:
crschnick 2024-06-21 18:20:35 +00:00
parent 2d67443f22
commit 4f3f2bbfd2
16 changed files with 41 additions and 84 deletions

View file

@ -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'

View file

@ -41,7 +41,7 @@ public class ListBoxViewComp<T> extends Comp<CompStructure<ScrollPane>> {
Map<T, Region> 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);

View file

@ -34,7 +34,7 @@ public class ListSelectorComp<T> 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<CheckBox>();
for (var v : values) {
var cb = new CheckBox(null);

View file

@ -151,7 +151,7 @@ public class StoreSectionComp extends Comp<CompStructure<VBox>> {
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()),

View file

@ -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<Extension> findAndParseExtension(String name, ModuleLayer parent) {
var inModulePath = ModuleLayer.boot().findModule("io.xpipe.ext." + name);
if (inModulePath.isPresent()) {

View file

@ -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;

View file

@ -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);
}
}
}

View file

@ -26,9 +26,5 @@ public interface LicensedFeature {
boolean isPreviewSupported();
default void throwIfUnsupported() throws LicenseRequiredException {
if (!isSupported()) {
throw new LicenseRequiredException(this);
}
}
void throwIfUnsupported() throws LicenseRequiredException;
}

View file

@ -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.

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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();
}
};
}
}

View file

@ -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