diff --git a/app/src/main/java/io/xpipe/app/beacon/BeaconRequestHandler.java b/app/src/main/java/io/xpipe/app/beacon/BeaconRequestHandler.java index 5e5e813b6..f754de24e 100644 --- a/app/src/main/java/io/xpipe/app/beacon/BeaconRequestHandler.java +++ b/app/src/main/java/io/xpipe/app/beacon/BeaconRequestHandler.java @@ -39,6 +39,10 @@ public class BeaconRequestHandler implements HttpHandler { } } + if (beaconInterface.requiresEnabledApi() && !AppPrefs.get().enableHttpApi().get()) { + throw ErrorEvent.expected(new IllegalStateException("HTTP API is not enabled in the settings menu")); + } + if (!AppPrefs.get().disableApiAuthentication().get() && beaconInterface.requiresAuthentication()) { var auth = exchange.getRequestHeaders().getFirst("Authorization"); if (auth == null) { diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/AskpassExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/AskpassExchangeImpl.java index 9c6cd9e28..b19b14a5a 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/AskpassExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/AskpassExchangeImpl.java @@ -36,4 +36,9 @@ public class AskpassExchangeImpl extends AskpassExchange { } return Response.builder().value(secret.inPlace()).build(); } + + @Override + public boolean requiresEnabledApi() { + return false; + } } diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/DaemonFocusExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/DaemonFocusExchangeImpl.java index f673e0726..4b1b2f178 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/DaemonFocusExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/DaemonFocusExchangeImpl.java @@ -12,4 +12,9 @@ public class DaemonFocusExchangeImpl extends DaemonFocusExchange { OperationMode.switchUp(OperationMode.map(msg.getMode())); return Response.builder().build(); } + + @Override + public boolean requiresEnabledApi() { + return false; + } } diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/DaemonModeExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/DaemonModeExchangeImpl.java index 238f64a19..e0f63b2a2 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/DaemonModeExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/DaemonModeExchangeImpl.java @@ -25,4 +25,9 @@ public class DaemonModeExchangeImpl extends DaemonModeExchange { .usedMode(OperationMode.map(OperationMode.get())) .build(); } + + @Override + public boolean requiresEnabledApi() { + return false; + } } diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/DaemonOpenExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/DaemonOpenExchangeImpl.java index 82ef09a20..a8bf0df51 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/DaemonOpenExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/DaemonOpenExchangeImpl.java @@ -21,4 +21,9 @@ public class DaemonOpenExchangeImpl extends DaemonOpenExchange { LauncherInput.handle(msg.getArguments()); return Response.builder().build(); } + + @Override + public boolean requiresEnabledApi() { + return false; + } } diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/DaemonStatusExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/DaemonStatusExchangeImpl.java index 64405df62..f001dd18e 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/DaemonStatusExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/DaemonStatusExchangeImpl.java @@ -23,4 +23,9 @@ public class DaemonStatusExchangeImpl extends DaemonStatusExchange { return Response.builder().mode(mode).build(); } + + @Override + public boolean requiresEnabledApi() { + return false; + } } diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/DaemonStopExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/DaemonStopExchangeImpl.java index 9c42a81e7..40cfe5c29 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/DaemonStopExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/DaemonStopExchangeImpl.java @@ -21,4 +21,9 @@ public class DaemonStopExchangeImpl extends DaemonStopExchange { }); return Response.builder().success(true).build(); } + + @Override + public boolean requiresEnabledApi() { + return false; + } } diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/DaemonVersionExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/DaemonVersionExchangeImpl.java index ad69b0479..2613fd72c 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/DaemonVersionExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/DaemonVersionExchangeImpl.java @@ -31,4 +31,9 @@ public class DaemonVersionExchangeImpl extends DaemonVersionExchange { .pro(pro) .build(); } + + @Override + public boolean requiresEnabledApi() { + return false; + } } diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/HandshakeExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/HandshakeExchangeImpl.java index 0e0d0d34a..7a5209ffb 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/HandshakeExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/HandshakeExchangeImpl.java @@ -42,4 +42,9 @@ public class HandshakeExchangeImpl extends HandshakeExchange { return false; } + + @Override + public boolean requiresEnabledApi() { + return false; + } } diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/SshLaunchExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/SshLaunchExchangeImpl.java index e0ea5d9e1..134c8ccea 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/SshLaunchExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/SshLaunchExchangeImpl.java @@ -2,7 +2,6 @@ package io.xpipe.app.beacon.impl; import com.sun.net.httpserver.HttpExchange; import io.xpipe.app.util.TerminalLauncherManager; -import io.xpipe.beacon.BeaconClientException; import io.xpipe.beacon.api.SshLaunchExchange; import io.xpipe.core.process.ProcessControlProvider; import io.xpipe.core.process.ShellDialects; @@ -35,4 +34,9 @@ public class SshLaunchExchangeImpl extends SshLaunchExchange { .buildBaseParts(null); return Response.builder().command(c).build(); } + + @Override + public boolean requiresEnabledApi() { + return false; + } } diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/TerminalLaunchExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/TerminalLaunchExchangeImpl.java index afb39bf33..1d732bbb9 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/TerminalLaunchExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/TerminalLaunchExchangeImpl.java @@ -12,4 +12,9 @@ public class TerminalLaunchExchangeImpl extends TerminalLaunchExchange { var r = TerminalLauncherManager.performLaunch(msg.getRequest()); return Response.builder().targetFile(r).build(); } + + @Override + public boolean requiresEnabledApi() { + return false; + } } diff --git a/app/src/main/java/io/xpipe/app/beacon/impl/TerminalWaitExchangeImpl.java b/app/src/main/java/io/xpipe/app/beacon/impl/TerminalWaitExchangeImpl.java index d486e0274..4f6729c5d 100644 --- a/app/src/main/java/io/xpipe/app/beacon/impl/TerminalWaitExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/beacon/impl/TerminalWaitExchangeImpl.java @@ -13,4 +13,9 @@ public class TerminalWaitExchangeImpl extends TerminalWaitExchange { TerminalLauncherManager.waitForCompletion(msg.getRequest()); return Response.builder().build(); } + + @Override + public boolean requiresEnabledApi() { + return false; + } } diff --git a/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java b/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java index d631f22a9..6c883cae9 100644 --- a/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java +++ b/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java @@ -38,6 +38,8 @@ public class AppPrefs { private static AppPrefs INSTANCE; private final List> mapping = new ArrayList<>(); + final BooleanProperty enableHttpApi = + mapVaultSpecific(new SimpleBooleanProperty(false), "enableHttpApi", Boolean.class); final BooleanProperty dontAutomaticallyStartVmSshServer = mapVaultSpecific(new SimpleBooleanProperty(false), "dontAutomaticallyStartVmSshServer", Boolean.class); final BooleanProperty dontAcceptNewHostKeys = @@ -144,6 +146,10 @@ public class AppPrefs { return disableApiAuthentication; } + public ObservableBooleanValue enableHttpApi() { + return enableHttpApi; + } + private final IntegerProperty editorReloadTimeout = map(new SimpleIntegerProperty(1000), "editorReloadTimeout", Integer.class); private final BooleanProperty confirmDeletions = diff --git a/app/src/main/java/io/xpipe/app/prefs/HttpApiCategory.java b/app/src/main/java/io/xpipe/app/prefs/HttpApiCategory.java index 4f763df09..a80cd71c8 100644 --- a/app/src/main/java/io/xpipe/app/prefs/HttpApiCategory.java +++ b/app/src/main/java/io/xpipe/app/prefs/HttpApiCategory.java @@ -16,6 +16,8 @@ public class HttpApiCategory extends AppPrefsCategory { return new OptionsBuilder() .addTitle("httpServerConfiguration") .sub(new OptionsBuilder() + .nameAndDescription("enableHttpApi") + .addToggle(prefs.enableHttpApi) .nameAndDescription("apiKey") .addString(prefs.apiKey) .nameAndDescription("disableApiAuthentication") diff --git a/beacon/src/main/java/io/xpipe/beacon/BeaconInterface.java b/beacon/src/main/java/io/xpipe/beacon/BeaconInterface.java index 91742971c..4ccf3261e 100644 --- a/beacon/src/main/java/io/xpipe/beacon/BeaconInterface.java +++ b/beacon/src/main/java/io/xpipe/beacon/BeaconInterface.java @@ -83,4 +83,8 @@ public abstract class BeaconInterface { public boolean readRawRequestBody() { return false; } + + public boolean requiresEnabledApi() { + return true; + } }