diff --git a/ext/base/src/main/java/io/xpipe/ext/base/identity/IdentityChoiceBuilder.java b/ext/base/src/main/java/io/xpipe/ext/base/identity/IdentityChoiceBuilder.java index 9235b2a12..9a991bdfb 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/identity/IdentityChoiceBuilder.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/identity/IdentityChoiceBuilder.java @@ -3,6 +3,7 @@ package io.xpipe.ext.base.identity; import io.xpipe.app.comp.Comp; import io.xpipe.app.comp.base.ButtonComp; import io.xpipe.app.comp.base.InputGroupComp; +import io.xpipe.app.core.AppI18n; import io.xpipe.app.ext.ProcessControlProvider; import io.xpipe.app.platform.LabelGraphic; import io.xpipe.app.platform.OptionsBuilder; @@ -14,8 +15,10 @@ import io.xpipe.app.util.*; import io.xpipe.ext.base.identity.ssh.SshIdentityStrategy; import io.xpipe.ext.base.identity.ssh.SshIdentityStrategyChoiceConfig; +import javafx.beans.binding.Bindings; import javafx.beans.property.*; +import javafx.beans.value.ObservableValue; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Value; @@ -32,19 +35,36 @@ public class IdentityChoiceBuilder { boolean requireUserInput; boolean requirePassword; boolean keyInput; + boolean requireKeyInput; boolean allowAgentForward; String userChoiceTranslationKey; - String passwordChoiceTranslationKey; + ObservableValue passwordChoiceTranslationKey; + + public IdentityChoiceBuilder( + ObjectProperty identity, boolean allowCustomUserInput, boolean requireUserInput, boolean requirePassword, boolean keyInput, + boolean requireKeyInput, + boolean allowAgentForward, String userChoiceTranslationKey, String passwordChoiceTranslationKey + ) { + this.identity = identity; + this.allowCustomUserInput = allowCustomUserInput; + this.requireUserInput = requireUserInput; + this.requirePassword = requirePassword; + this.keyInput = keyInput; + this.requireKeyInput = requireKeyInput; + this.allowAgentForward = allowAgentForward; + this.userChoiceTranslationKey = userChoiceTranslationKey; + this.passwordChoiceTranslationKey = new ReadOnlyStringWrapper(passwordChoiceTranslationKey); + } public static OptionsBuilder ssh(ObjectProperty identity, boolean requireUser) { var i = new IdentityChoiceBuilder( - identity, true, requireUser, true, true, true, "identityChoice", "passwordAuthentication"); + identity, true, requireUser, true, true, true, true, "identityChoice", "passwordAuthentication"); return i.build(); } public static OptionsBuilder container(ObjectProperty identity) { var i = new IdentityChoiceBuilder( - identity, true, false, false, false, false, "customUsername", "customUsernamePassword"); + identity, true, false, false, false, false, false, "customUsername", "customUsernamePassword"); return i.build(); } @@ -100,7 +120,12 @@ public class IdentityChoiceBuilder { .nameAndDescription(userChoiceTranslationKey) .addComp(new IdentitySelectComp(ref, user, pass, identityStrategy, allowCustomUserInput), user) .nonNullIf(inPlaceSelected.and(new SimpleBooleanProperty(requireUserInput))) - .nameAndDescription(passwordChoiceTranslationKey) + .name(Bindings.createStringBinding(() -> { + return AppI18n.get(passwordChoiceTranslationKey.getValue()); + }, passwordChoiceTranslationKey, AppI18n.activeLanguage())) + .description(Bindings.createStringBinding(() -> { + return AppI18n.get(passwordChoiceTranslationKey.getValue() + "Description"); + }, passwordChoiceTranslationKey, AppI18n.activeLanguage())) .sub(passwordChoice, pass) .nonNullIf(inPlaceSelected.and(new SimpleBooleanProperty(requirePassword))) .hide(refSelected) @@ -117,8 +142,7 @@ public class IdentityChoiceBuilder { .description("keyAuthenticationDescription") .documentationLink(DocumentationLink.SSH_KEYS) .sub(keyAuthChoice(identityStrategy, sshIdentityChoiceConfig), identityStrategy) - .nonNullIf(inPlaceSelected) - .disable(refSelected) + .nonNullIf(inPlaceSelected.and(new ReadOnlyBooleanWrapper(requireKeyInput))) .hide(refSelected); } options.bind( diff --git a/lang/strings/translations_en.properties b/lang/strings/translations_en.properties index 0977fe49d..7d3833ae5 100644 --- a/lang/strings/translations_en.properties +++ b/lang/strings/translations_en.properties @@ -1339,6 +1339,8 @@ clearUserDataContent=This will delete all local user data for xpipe and restart. undefined=Undefined copyAddress=Copy address netbirdDeviceScan=Netbird connections +netbirdId=Peer public key +netbirdIdDescription=The internal netbird public key id of the peer tailscaleDeviceScan=Tailscale connections tailscaleInstall.displayName=Tailscale installation tailscaleInstall.displayDescription=Connect to devices in your tailnet via SSH @@ -1351,7 +1353,7 @@ tailscaleHostNameDescription=The hostname of the device in the tailnet tailscaleUsername=Username tailscaleUsernameDescription=The user to log in as tailscalePassword=Password -tailscalePasswordDescription=The optional user password that can be used for sudo +tailscalePasswordDescription=The user password that can be used for sudo scriptName=Script name scriptNameDescription=Give this script a custom name scriptGroupName=Script group name @@ -1863,3 +1865,7 @@ chooseConnectionType=Choose connection type batchMode=Batch mode #context: noun, a type of button toggleButton=Toggle button +tailscaleUseSsh=Use tailscale SSH auth +tailscaleUseSshDescription=Log in via the tailscale SSH server itself without any SSH auth +portDescription=The port the SSH server is running on +tailscaleAuthPassword=