More beacon fixes

This commit is contained in:
crschnick 2024-06-17 12:28:37 +00:00
parent 2810dc4372
commit 33577ca7c1
16 changed files with 86 additions and 79 deletions

View file

@ -1,16 +1,14 @@
package io.xpipe.app.beacon;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
import io.xpipe.app.core.AppResources;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.MarkdownHelper;
import io.xpipe.beacon.BeaconConfig;
import io.xpipe.beacon.BeaconInterface;
import io.xpipe.core.util.XPipeInstallation;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
import lombok.Getter;
import java.io.IOException;
@ -52,7 +50,7 @@ public class AppBeaconServer {
port = BeaconConfig.getUsedPort();
propertyPort = true;
} else {
port = AppPrefs.get().httpServerPort().getValue();
port = XPipeInstallation.getDefaultBeaconPort();
propertyPort = false;
}
INSTANCE = new AppBeaconServer(port, propertyPort);

View file

@ -1,8 +1,10 @@
package io.xpipe.app.beacon;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.beacon.*;
import io.xpipe.core.util.JacksonMapper;
@ -25,6 +27,16 @@ public class BeaconRequestHandler<T> implements HttpHandler {
@Override
public void handle(HttpExchange exchange) {
if (OperationMode.isInShutdown()) {
return;
}
if (beaconInterface.requiresCompletedStartup()) {
while (OperationMode.isInStartup()) {
ThreadHelper.sleep(100);
}
}
if (!AppPrefs.get().disableApiAuthentication().get() && beaconInterface.requiresAuthentication()) {
var auth = exchange.getRequestHeaders().getFirst("Authorization");
if (auth == null) {

View file

@ -1,17 +1,17 @@
package io.xpipe.app.beacon.impl;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.util.AskpassAlert;
import io.xpipe.app.util.SecretManager;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.BeaconServerException;
import io.xpipe.beacon.api.AskpassExchange;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
public class AskpassExchangeImpl extends AskpassExchange {
@Override
public boolean requiresCompletedStartup() {
return false;
}
@Override
public Object handle(HttpExchange exchange, Request msg) {
if (msg.getRequest() == null) {

View file

@ -1,19 +1,13 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.BeaconServerException;
import io.xpipe.beacon.api.DaemonFocusExchange;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.beacon.api.DaemonFocusExchange;
public class DaemonFocusExchangeImpl extends DaemonFocusExchange {
@Override
public Object handle(HttpExchange exchange, Request msg) {
OperationMode.switchUp(OperationMode.map(msg.getMode()));
return Response.builder().build();
}

View file

@ -1,17 +1,14 @@
package io.xpipe.app.beacon.impl;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.launcher.LauncherInput;
import io.xpipe.app.util.PlatformState;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.BeaconServerException;
import io.xpipe.beacon.api.DaemonOpenExchange;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
public class DaemonOpenExchangeImpl extends DaemonOpenExchange {
@Override
public Object handle(HttpExchange exchange, Request msg)
throws BeaconServerException {

View file

@ -1,16 +1,16 @@
package io.xpipe.app.beacon.impl;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.BeaconServerException;
import io.xpipe.beacon.api.DaemonStatusExchange;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
public class DaemonStatusExchangeImpl extends DaemonStatusExchange {
@Override
public boolean requiresCompletedStartup() {
return false;
}
@Override
public Object handle(HttpExchange exchange, Request body) {
String mode;

View file

@ -1,17 +1,17 @@
package io.xpipe.app.beacon.impl;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.BeaconServerException;
import io.xpipe.beacon.api.DaemonStopExchange;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
public class DaemonStopExchangeImpl extends DaemonStopExchange {
@Override
public boolean requiresCompletedStartup() {
return false;
}
@Override
public Object handle(HttpExchange exchange, Request msg) {
ThreadHelper.runAsync(() -> {

View file

@ -1,16 +1,16 @@
package io.xpipe.app.beacon.impl;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.core.AppProperties;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.BeaconServerException;
import io.xpipe.beacon.api.DaemonVersionExchange;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
public class DaemonVersionExchangeImpl extends DaemonVersionExchange {
@Override
public boolean requiresCompletedStartup() {
return false;
}
@Override
public Object handle(HttpExchange exchange, Request msg) {
var jvmVersion = System.getProperty("java.vm.vendor") + " "

View file

@ -1,20 +1,22 @@
package io.xpipe.app.beacon.impl;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.beacon.BeaconSession;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.beacon.BeaconAuthMethod;
import io.xpipe.beacon.BeaconClientException;
import io.xpipe.beacon.BeaconServerException;
import io.xpipe.beacon.api.HandshakeExchange;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import java.util.UUID;
public class HandshakeExchangeImpl extends HandshakeExchange {
@Override
public boolean requiresCompletedStartup() {
return false;
}
@Override
public Object handle(HttpExchange exchange, Request body)
throws BeaconClientException {

View file

@ -1,5 +1,6 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.fxcomps.Comp;
@ -9,11 +10,9 @@ import io.xpipe.app.fxcomps.augment.Augment;
import io.xpipe.app.fxcomps.impl.IconButtonComp;
import io.xpipe.app.fxcomps.impl.TooltipAugment;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.update.UpdateAvailableAlert;
import io.xpipe.app.update.XPipeDistributionType;
import io.xpipe.app.util.Hyperlinks;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.Property;
@ -162,7 +161,7 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
var b = new IconButtonComp(
"mdi2c-code-json",
() -> Hyperlinks.open("http://localhost:"
+ AppPrefs.get().httpServerPort().getValue()))
+ AppBeaconServer.get().getPort()))
.tooltipKey("api")
.apply(simpleBorders)
.accessibleTextKey("api");

View file

@ -126,8 +126,8 @@ public abstract class OperationMode {
var usedArgs = parseProperties(args);
setup(args);
LauncherCommand.runLauncher(usedArgs);
inStartup = false;
AppDesktopIntegration.setupDesktopIntegrations();
inStartup = false;
}
public static void switchToAsync(OperationMode newMode) {

View file

@ -14,15 +14,12 @@ import io.xpipe.app.terminal.ExternalTerminalType;
import io.xpipe.app.util.PasswordLockSecretValue;
import io.xpipe.core.util.InPlaceSecretValue;
import io.xpipe.core.util.ModuleHelper;
import io.xpipe.core.util.XPipeInstallation;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.beans.value.ObservableBooleanValue;
import javafx.beans.value.ObservableDoubleValue;
import javafx.beans.value.ObservableStringValue;
import javafx.beans.value.ObservableValue;
import lombok.Getter;
import lombok.Value;
@ -122,17 +119,11 @@ public class AppPrefs {
private final StringProperty lockCrypt =
mapVaultSpecific(new SimpleStringProperty(), "workspaceLock", String.class);
final Property<Integer> httpServerPort = map(
new SimpleObjectProperty<>(XPipeInstallation.getDefaultBeaconPort()), "httpServerPort", Integer.class);
final StringProperty apiKey =
mapVaultSpecific(new SimpleStringProperty(UUID.randomUUID().toString()), "apiKey", String.class);
final BooleanProperty disableApiAuthentication =
map(new SimpleBooleanProperty(false), "disableApiAuthentication", Boolean.class);
public ObservableValue<Integer> httpServerPort() {
return httpServerPort;
}
public ObservableStringValue apiKey() {
return apiKey;
}

View file

@ -1,6 +1,5 @@
package io.xpipe.app.prefs;
import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.util.OptionsBuilder;
@ -17,9 +16,6 @@ public class HttpApiCategory extends AppPrefsCategory {
return new OptionsBuilder()
.addTitle("httpServerConfiguration")
.sub(new OptionsBuilder()
.nameAndDescription("httpServerPort")
.addInteger(prefs.httpServerPort)
.disable(AppBeaconServer.get().isPropertyPort())
.nameAndDescription("apiKey")
.addString(prefs.apiKey)
.nameAndDescription("disableApiAuthentication")

View file

@ -1,11 +1,9 @@
package io.xpipe.beacon;
import io.xpipe.core.util.ModuleLayerLoader;
import com.sun.net.httpserver.HttpExchange;
import io.xpipe.core.util.ModuleLayerLoader;
import lombok.SneakyThrows;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.ServiceLoader;
@ -63,6 +61,10 @@ public abstract class BeaconInterface<T> {
return (Class<T>) Class.forName(name);
}
public boolean requiresCompletedStartup() {
return true;
}
public boolean requiresAuthentication() {
return true;
}

View file

@ -1,14 +1,5 @@
package io.xpipe.core.util;
import io.xpipe.core.dialog.BaseQueryElement;
import io.xpipe.core.dialog.BusyElement;
import io.xpipe.core.dialog.ChoiceElement;
import io.xpipe.core.dialog.HeaderElement;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellDialect;
import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.store.LocalStore;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.core.JsonGenerator;
@ -18,11 +9,21 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.ArrayType;
import io.xpipe.core.dialog.BaseQueryElement;
import io.xpipe.core.dialog.BusyElement;
import io.xpipe.core.dialog.ChoiceElement;
import io.xpipe.core.dialog.HeaderElement;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellDialect;
import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.store.LocalStore;
import io.xpipe.core.store.StorePath;
import java.io.IOException;
import java.lang.reflect.WildcardType;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Stream;
public class CoreJacksonModule extends SimpleModule {
@ -68,6 +69,25 @@ public class CoreJacksonModule extends SimpleModule {
context.addDeserializers(_deserializers);
}
public static class StorePathSerializer extends JsonSerializer<StorePath> {
@Override
public void serialize(StorePath value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
var ar = value.getNames().toArray(String[]::new);
jgen.writeArray(ar, 0, ar.length);
}
}
public static class StorePathDeserializer extends JsonDeserializer<StorePath> {
@Override
public StorePath deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JavaType javaType = JacksonMapper.getDefault().getTypeFactory().constructCollectionLikeType(List.class, String.class);
List<String> list = JacksonMapper.getDefault().readValue(p, javaType);
return new StorePath(list);
}
}
public static class CharsetSerializer extends JsonSerializer<Charset> {
@Override

View file

@ -461,10 +461,6 @@ stickToTop=Keep on top
orderAheadOf=Order ahead of ...
httpServer=HTTP server
httpServerConfiguration=HTTP server configuration
#context: networking
httpServerPort=Port
#context: networking
httpServerPortDescription=The port on which the HTTP server will listen on.\n\nNote that if you change this, any other applications that interact with the server need to be configured to use the new port as well.\n\nRequires a restart to apply.
apiKey=API key
apiKeyDescription=The API key to authenticate XPipe daemon API requests. For more information on how to authenticate, see the general API documentation.\n\nRequires a restart to apply.
disableApiAuthentication=Disable API authentication