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 bc7c4e96d..1b5088328 100644 --- a/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java +++ b/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java @@ -76,6 +76,7 @@ public class AppPrefs { mapVaultSpecific(new SimpleBooleanProperty(false), "dontCachePasswords", Boolean.class); public final BooleanProperty denyTempScriptCreation = mapVaultSpecific(new SimpleBooleanProperty(false), "denyTempScriptCreation", Boolean.class); + final Property passwordManager = mapVaultSpecific(new SimpleObjectProperty<>(), "passwordManager", ExternalPasswordManager.class); final StringProperty passwordManagerCommand = map(new SimpleStringProperty(""), "passwordManagerCommand", String.class); final ObjectProperty startupBehaviour = @@ -256,6 +257,10 @@ public class AppPrefs { developerMode()); } + public ObservableValue externalPasswordManager() { + return passwordManager; + } + public ObservableValue language() { return language; } diff --git a/app/src/main/java/io/xpipe/app/prefs/ExternalPasswordManager.java b/app/src/main/java/io/xpipe/app/prefs/ExternalPasswordManager.java index 0f999ea5b..e875b9900 100644 --- a/app/src/main/java/io/xpipe/app/prefs/ExternalPasswordManager.java +++ b/app/src/main/java/io/xpipe/app/prefs/ExternalPasswordManager.java @@ -1,6 +1,9 @@ package io.xpipe.app.prefs; +import io.xpipe.app.ext.LocalStore; import io.xpipe.app.ext.PrefsChoiceValue; +import io.xpipe.app.issue.ErrorEvent; +import io.xpipe.app.util.LocalShell; import io.xpipe.core.process.OsType; import java.util.List; @@ -8,74 +11,114 @@ import java.util.stream.Stream; public interface ExternalPasswordManager extends PrefsChoiceValue { - String getTemplate(); + String retrievePassword(String key); + + ExternalPasswordManager COMMAND = new ExternalPasswordManager() { - ExternalPasswordManager BITWARDEN = new ExternalPasswordManager() { @Override - public String getTemplate() { - return "bw get password $KEY --nointeraction --raw"; + public String retrievePassword(String key) { + var cmd = AppPrefs.get().passwordManagerString(key); + if (cmd == null) { + return null; + } + + try (var cc = new LocalStore().control().command(cmd).start()) { + return cc.readStdoutOrThrow(); + } catch (Exception ex) { + ErrorEvent.fromThrowable("Unable to retrieve password with command " + cmd, ex) + .expected() + .handle(); + return null; + } } @Override public String getId() { - return "bitwarden"; + return "command"; } }; - ExternalPasswordManager ONEPASSWORD = new ExternalPasswordManager() { + ExternalPasswordManager WINDOWS_CREDENTIAL_MANAGER = new ExternalPasswordManager() { + + private boolean loaded = false; + @Override - public String getTemplate() { - return "op read $KEY --force"; + public synchronized String retrievePassword(String key) { + try { + if (!loaded) { + loaded = true; + var cmd = """ + $code = @" + using System.Text; + using System; + using System.Runtime.InteropServices; + + namespace CredManager { + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct CredentialMem + { + public int flags; + public int type; + public string targetName; + public string comment; + public System.Runtime.InteropServices.ComTypes.FILETIME lastWritten; + public int credentialBlobSize; + public IntPtr credentialBlob; + public int persist; + public int attributeCount; + public IntPtr credAttribute; + public string targetAlias; + public string userName; + } + + public class Credential { + [DllImport("advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern bool CredRead(string target, int type, int reservedFlag, out IntPtr credentialPtr); + + public static string GetUserPassword(string target) + { + CredentialMem credMem; + IntPtr credPtr; + + if (CredRead(target, 1, 0, out credPtr)) + { + credMem = Marshal.PtrToStructure(credPtr); + byte[] passwordBytes = new byte[credMem.credentialBlobSize]; + Marshal.Copy(credMem.credentialBlob, passwordBytes, 0, credMem.credentialBlobSize); + return Encoding.Unicode.GetString(passwordBytes); + } else { + throw new Exception("Failed to retrieve credentials for target: " + target); + } + } + } + } + "@ + Add-Type -TypeDefinition $code -Language CSharp + """; + LocalShell.getLocalPowershell().command(cmd).execute(); + } + + return LocalShell.getLocalPowershell().command("[CredManager.Credential]::GetUserPassword(\"" + key.replaceAll("\"", "`\"") + "\")").readStdoutOrThrow(); + } catch (Exception ex) { + ErrorEvent.fromThrowable(ex) + .expected() + .handle(); + return null; + } } @Override public String getId() { - return "1password"; - } - }; - - ExternalPasswordManager DASHLANE = new ExternalPasswordManager() { - @Override - public String getTemplate() { - return "dcli password --output console $KEY"; - } - - @Override - public String getId() { - return "dashlane"; - } - }; - - ExternalPasswordManager LASTPASS = new ExternalPasswordManager() { - @Override - public String getTemplate() { - return "lpass show --password $KEY"; - } - - @Override - public String getId() { - return "lastpass"; - } - }; - - ExternalPasswordManager MACOS_KEYCHAIN = new ExternalPasswordManager() { - @Override - public String getTemplate() { - return "security find-generic-password -w -l $KEY"; - } - - @Override - public String getId() { - return "macosKeychain"; + return "windowsCredentialManager"; } @Override public boolean isSelectable() { - return OsType.getLocal() == OsType.MACOS; + return OsType.getLocal() == OsType.WINDOWS; } }; - List ALL = Stream.of(ONEPASSWORD, BITWARDEN, DASHLANE, LASTPASS, MACOS_KEYCHAIN) + List ALL = Stream.of(COMMAND, WINDOWS_CREDENTIAL_MANAGER) .filter(externalPasswordManager -> externalPasswordManager.isSelectable()) .toList(); } diff --git a/app/src/main/java/io/xpipe/app/prefs/ExternalPasswordManagerTemplate.java b/app/src/main/java/io/xpipe/app/prefs/ExternalPasswordManagerTemplate.java new file mode 100644 index 000000000..7f0a2d7ad --- /dev/null +++ b/app/src/main/java/io/xpipe/app/prefs/ExternalPasswordManagerTemplate.java @@ -0,0 +1,81 @@ +package io.xpipe.app.prefs; + +import io.xpipe.app.ext.PrefsChoiceValue; +import io.xpipe.core.process.OsType; + +import java.util.List; +import java.util.stream.Stream; + +public interface ExternalPasswordManagerTemplate extends PrefsChoiceValue { + + String getTemplate(); + + ExternalPasswordManagerTemplate BITWARDEN = new ExternalPasswordManagerTemplate() { + @Override + public String getTemplate() { + return "bw get password $KEY --nointeraction --raw"; + } + + @Override + public String getId() { + return "bitwarden"; + } + }; + + ExternalPasswordManagerTemplate ONEPASSWORD = new ExternalPasswordManagerTemplate() { + @Override + public String getTemplate() { + return "op read $KEY --force"; + } + + @Override + public String getId() { + return "1password"; + } + }; + + ExternalPasswordManagerTemplate DASHLANE = new ExternalPasswordManagerTemplate() { + @Override + public String getTemplate() { + return "dcli password --output console $KEY"; + } + + @Override + public String getId() { + return "dashlane"; + } + }; + + ExternalPasswordManagerTemplate LASTPASS = new ExternalPasswordManagerTemplate() { + @Override + public String getTemplate() { + return "lpass show --password $KEY"; + } + + @Override + public String getId() { + return "lastpass"; + } + }; + + ExternalPasswordManagerTemplate MACOS_KEYCHAIN = new ExternalPasswordManagerTemplate() { + @Override + public String getTemplate() { + return "security find-generic-password -w -l $KEY"; + } + + @Override + public String getId() { + return "macosKeychain"; + } + + @Override + public boolean isSelectable() { + return OsType.getLocal() == OsType.MACOS; + } + }; + + List ALL = Stream.of(ONEPASSWORD, BITWARDEN, DASHLANE, LASTPASS, MACOS_KEYCHAIN) + .filter(externalPasswordManager -> externalPasswordManager.isSelectable()) + .toList(); +} diff --git a/app/src/main/java/io/xpipe/app/prefs/PasswordManagerCategory.java b/app/src/main/java/io/xpipe/app/prefs/PasswordManagerCategory.java index 4e98b1705..caa2985d4 100644 --- a/app/src/main/java/io/xpipe/app/prefs/PasswordManagerCategory.java +++ b/app/src/main/java/io/xpipe/app/prefs/PasswordManagerCategory.java @@ -1,33 +1,41 @@ package io.xpipe.app.prefs; +import atlantafx.base.theme.Styles; import io.xpipe.app.comp.base.ButtonComp; import io.xpipe.app.comp.base.IntegratedTextAreaComp; import io.xpipe.app.core.AppI18n; +import io.xpipe.app.ext.LocalStore; +import io.xpipe.app.ext.ProcessControlProvider; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.impl.HorizontalComp; import io.xpipe.app.fxcomps.impl.TextFieldComp; import io.xpipe.app.fxcomps.impl.VerticalComp; +import io.xpipe.app.fxcomps.util.BindingsHelper; import io.xpipe.app.util.OptionsBuilder; import io.xpipe.app.util.TerminalLauncher; import io.xpipe.app.util.ThreadHelper; import io.xpipe.core.process.CommandBuilder; import io.xpipe.core.process.CommandControl; -import io.xpipe.app.ext.ProcessControlProvider; -import io.xpipe.app.ext.LocalStore; - import javafx.beans.property.SimpleStringProperty; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.MenuButton; import javafx.scene.control.MenuItem; - -import atlantafx.base.theme.Styles; +import lombok.Value; import org.kordamp.ikonli.javafx.FontIcon; +import java.util.ArrayList; import java.util.List; public class PasswordManagerCategory extends AppPrefsCategory { + @Value + private static class Choice { + String id; + String template; + ExternalPasswordManager passwordManager; + } + @Override protected String getId() { return "passwordManager"; @@ -37,11 +45,11 @@ public class PasswordManagerCategory extends AppPrefsCategory { return Comp.of(() -> { var cb = new MenuButton(); cb.textProperty().bind(AppI18n.observable("templates")); - ExternalPasswordManager.ALL.forEach(externalPasswordManager -> { + ExternalPasswordManagerTemplate.ALL.forEach(e -> { var m = new MenuItem( - externalPasswordManager.toTranslatedString().getValue()); + e.toTranslatedString().getValue()); m.setOnAction(event -> { - AppPrefs.get().passwordManagerCommand.set(externalPasswordManager.getTemplate()); + AppPrefs.get().passwordManagerCommand.set(e.getTemplate()); event.consume(); }); cb.getItems().add(m); @@ -52,6 +60,14 @@ public class PasswordManagerCategory extends AppPrefsCategory { @Override protected Comp create() { + var choices = new ArrayList(); + ExternalPasswordManagerTemplate.ALL.forEach(externalPasswordManagerTemplate -> { + choices.add(new Choice(externalPasswordManagerTemplate.getId(), externalPasswordManagerTemplate.getTemplate(), null)); + }); + ExternalPasswordManager.ALL.stream().filter(externalPasswordManager -> externalPasswordManager != ExternalPasswordManager.COMMAND).forEach(externalPasswordManager -> { + choices.add(new Choice(externalPasswordManager.getId(), null, externalPasswordManager)); + }); + var prefs = AppPrefs.get(); var testPasswordManagerValue = new SimpleStringProperty(); Runnable test = () -> { @@ -72,20 +88,37 @@ public class PasswordManagerCategory extends AppPrefsCategory { }); }; - var c = new IntegratedTextAreaComp( + var command = new IntegratedTextAreaComp( prefs.passwordManagerCommand, - true, - "pw", + false, + "command", new SimpleStringProperty(ProcessControlProvider.get() .getEffectiveLocalDialect() .getScriptFileEnding())) .apply(struc -> { struc.getTextArea().setPromptText("mypassmgr get $KEY"); }) + .disable(prefs.passwordManagerCommand.isNull()) .minWidth(350) .minHeight(120); - var visit = createTemplateChoice(); - var choice = new VerticalComp(List.of(c, visit)).apply(struc -> { + var templates = Comp.of(() -> { + var cb = new MenuButton(); + cb.textProperty().bind(BindingsHelper.flatMap(prefs.passwordManager,externalPasswordManager -> { + return externalPasswordManager != null ? AppI18n.observable(externalPasswordManager.getId()) : AppI18n.observable("templates"); + })); + choices.forEach(e -> { + var m = new MenuItem(); + m.textProperty().bind(AppI18n.observable(e.getId())); + m.setOnAction(event -> { + AppPrefs.get().passwordManagerCommand.set(e.getTemplate()); + AppPrefs.get().passwordManager.setValue(e.getPasswordManager()); + event.consume(); + }); + cb.getItems().add(m); + }); + return cb; + }); + var choice = new VerticalComp(List.of(templates, command)).apply(struc -> { struc.get().setAlignment(Pos.CENTER_LEFT); struc.get().setSpacing(10); }); diff --git a/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategy.java b/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategy.java index 5ba54ca15..a7e5060c6 100644 --- a/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategy.java +++ b/app/src/main/java/io/xpipe/app/util/SecretRetrievalStrategy.java @@ -124,17 +124,13 @@ public interface SecretRetrievalStrategy { return new SecretQuery() { @Override public SecretQueryResult query(String prompt) { - var cmd = AppPrefs.get().passwordManagerString(key); - if (cmd == null) { + var pm = AppPrefs.get().externalPasswordManager().getValue(); + if (pm == null) { return new SecretQueryResult(null, SecretQueryState.RETRIEVAL_FAILURE); } - String r; - try (var cc = new LocalStore().control().command(cmd).start()) { - r = cc.readStdoutOrThrow(); - } catch (Exception ex) { - ErrorEvent.fromThrowable("Unable to retrieve password with command " + cmd, ex) - .handle(); + var r = pm.retrievePassword(key); + if (r == null) { return new SecretQueryResult(null, SecretQueryState.RETRIEVAL_FAILURE); } diff --git a/lang/app/strings/fixed_en.properties b/lang/app/strings/fixed_en.properties index 9278ae786..661f1afd4 100644 --- a/lang/app/strings/fixed_en.properties +++ b/lang/app/strings/fixed_en.properties @@ -68,3 +68,4 @@ termius=Termius devolutions=Devolutions tryPtb=XPipe Public Test Build zed=Zed +windowsCredentialManager=Windows credential manager diff --git a/lang/app/strings/translations_da.properties b/lang/app/strings/translations_da.properties index cb65bbbd7..80f728f02 100644 --- a/lang/app/strings/translations_da.properties +++ b/lang/app/strings/translations_da.properties @@ -375,7 +375,7 @@ developerModeDescription=Når det er aktiveret, har du adgang til en række ekst editor=Editor custom=Brugerdefineret passwordManagerCommand=Kommando til adgangskodehåndtering -passwordManagerCommandDescription=Den kommando, der skal udføres for at hente adgangskoder. Pladsholderstrengen $KEY vil blive erstattet af den citerede adgangskode, når den kaldes. Dette bør kalde din adgangskodeadministrator CLI for at udskrive adgangskoden til stdout, f.eks. mypassmgr get $KEY.\n\nDu kan derefter indstille nøglen til at blive hentet, hver gang du opretter en forbindelse, der kræver et kodeord. +passwordManagerCommandDescription=Implementeringen af adgangskodeadministratoren eller den brugerdefinerede kommando, der skal udføres for at hente adgangskoder. For brugerdefinerede kommandoer vil pladsholderstrengen $KEY blive erstattet af den citerede adgangskodenøgle, når den kaldes. Dette bør kalde din password manager CLI for at udskrive adgangskoden til stdout, f.eks. mypassmgr get $KEY.\n\nDu kan derefter indstille nøglen til at blive hentet, hver gang du opretter en forbindelse, der kræver en adgangskode. passwordManagerCommandTest=Test password manager passwordManagerCommandTestDescription=Her kan du teste, om outputtet ser korrekt ud, hvis du har opsat en password manager-kommando. Kommandoen skal kun sende selve adgangskoden til stdout, ingen anden formatering skal inkluderes i outputtet. preferEditorTabs=Foretrækker at åbne nye faner diff --git a/lang/app/strings/translations_en.properties b/lang/app/strings/translations_en.properties index b0f57b9cb..9cadec767 100644 --- a/lang/app/strings/translations_en.properties +++ b/lang/app/strings/translations_en.properties @@ -373,7 +373,8 @@ developerModeDescription=When enabled, you will have access to a variety of addi editor=Editor custom=Custom passwordManagerCommand=Password manager command -passwordManagerCommandDescription=The command to execute to fetch passwords. The placeholder string $KEY will be replaced by the quoted password key when called. This should call your password manager CLI to print the password to stdout, e.g. mypassmgr get $KEY.\n\nYou can then set the key to be retrieved whenever you set up a connection which requires a password. +#force +passwordManagerCommandDescription=The password manager implementation or custom command to execute to fetch passwords. For custom commands, the placeholder string $KEY will be replaced by the quoted password key when called. This should call your password manager CLI to print the password to stdout, e.g. mypassmgr get $KEY.\n\nYou can then set the key to be retrieved whenever you set up a connection which requires a password. passwordManagerCommandTest=Test password manager passwordManagerCommandTestDescription=You can test here whether the output looks correct if you have set up a password manager command. The command should only output the password itself to stdout, no other formatting should be included in the output. preferEditorTabs=Prefer to open new tabs diff --git a/lang/app/strings/translations_es.properties b/lang/app/strings/translations_es.properties index 1e11b9a9d..6dd8b8403 100644 --- a/lang/app/strings/translations_es.properties +++ b/lang/app/strings/translations_es.properties @@ -359,7 +359,7 @@ developerModeDescription=Cuando esté activado, tendrás acceso a una serie de o editor=Editor custom=Personalizado passwordManagerCommand=Comando del gestor de contraseñas -passwordManagerCommandDescription=El comando a ejecutar para obtener las contraseñas. La cadena de texto $KEY se sustituirá por la clave de contraseña citada cuando se llame. Esto debería llamar a la CLI de tu gestor de contraseñas para que imprima la contraseña en stdout, por ejemplo, mypassmgr get $KEY.\n\nA continuación, puedes configurar la clave para que se recupere siempre que establezcas una conexión que requiera una contraseña. +passwordManagerCommandDescription=La implementación del gestor de contraseñas o el comando personalizado a ejecutar para obtener las contraseñas. En el caso de los comandos personalizados, la cadena $KEY se sustituirá por la clave de contraseña citada cuando se invoque. Esto debería llamar a la CLI de tu gestor de contraseñas para que imprima la contraseña en stdout, por ejemplo, mypassmgr get $KEY.\n\nA continuación, puedes configurar la clave para que se recupere siempre que establezcas una conexión que requiera una contraseña. passwordManagerCommandTest=Gestor de contraseñas de prueba passwordManagerCommandTestDescription=Aquí puedes comprobar si la salida parece correcta si has configurado un comando gestor de contraseñas. El comando sólo debe mostrar la contraseña en la salida estándar, no debe incluir ningún otro formato. preferEditorTabs=Prefiere abrir nuevas pestañas diff --git a/lang/app/strings/translations_fr.properties b/lang/app/strings/translations_fr.properties index 23d0c23f9..7f3ec03fa 100644 --- a/lang/app/strings/translations_fr.properties +++ b/lang/app/strings/translations_fr.properties @@ -359,7 +359,7 @@ developerModeDescription=Lorsque cette option est activée, tu as accès à tout editor=Éditeur custom=Personnalisé passwordManagerCommand=Commande du gestionnaire de mots de passe -passwordManagerCommandDescription=La commande à exécuter pour récupérer les mots de passe. La chaîne de caractères de remplacement $KEY sera remplacée par la clé de mot de passe citée lorsqu'elle sera appelée. Cette commande devrait appeler ton gestionnaire de mots de passe CLI pour imprimer le mot de passe sur stdout, par exemple mypassmgr get $KEY.\n\nTu peux ensuite configurer la clé pour qu'elle soit récupérée chaque fois que tu établis une connexion qui nécessite un mot de passe. +passwordManagerCommandDescription=L'implémentation du gestionnaire de mots de passe ou la commande personnalisée à exécuter pour récupérer les mots de passe. Pour les commandes personnalisées, la chaîne de caractères $KEY sera remplacée par la clé du mot de passe citée lors de l'appel. Ceci devrait appeler ton gestionnaire de mots de passe CLI pour imprimer le mot de passe sur stdout, par exemple mypassmgr get $KEY.\n\nTu peux ensuite configurer la clé pour qu'elle soit récupérée à chaque fois que tu établis une connexion nécessitant un mot de passe. passwordManagerCommandTest=Test du gestionnaire de mot de passe passwordManagerCommandTestDescription=Tu peux tester ici si la sortie semble correcte si tu as mis en place une commande de gestionnaire de mot de passe. La commande ne doit sortir que le mot de passe lui-même sur stdout, aucun autre formatage ne doit être inclus dans la sortie. preferEditorTabs=Préfère ouvrir de nouveaux onglets diff --git a/lang/app/strings/translations_it.properties b/lang/app/strings/translations_it.properties index 018a1660a..d35d00a6a 100644 --- a/lang/app/strings/translations_it.properties +++ b/lang/app/strings/translations_it.properties @@ -359,7 +359,7 @@ developerModeDescription=Se abilitato, avrai accesso a una serie di opzioni aggi editor=Editore custom=Personalizzato passwordManagerCommand=Comando del gestore di password -passwordManagerCommandDescription=Il comando da eseguire per recuperare le password. La stringa segnaposto $KEY sarà sostituita dalla chiave della password citata quando verrà richiamata. Questo comando dovrebbe richiamare la CLI del tuo gestore di password per stampare la password su stdout, ad esempio mypassmgr get $KEY.\n\nPuoi quindi impostare la chiave da recuperare ogni volta che imposti una connessione che richiede una password. +passwordManagerCommandDescription=L'implementazione del gestore di password o il comando personalizzato da eseguire per recuperare le password. Per i comandi personalizzati, la stringa segnaposto $KEY sarà sostituita dalla chiave della password citata al momento della chiamata. Questo dovrebbe richiamare la CLI del tuo gestore di password per stampare la password su stdout, ad esempio mypassmgr get $KEY.\n\nPotrai quindi impostare la chiave in modo che venga recuperata ogni volta che imposti una connessione che richiede una password. passwordManagerCommandTest=Test del gestore di password passwordManagerCommandTestDescription=Puoi verificare se l'output è corretto se hai impostato un comando di gestione delle password. Il comando deve inviare a stdout solo la password stessa e non deve includere nessun'altra formattazione nell'output. preferEditorTabs=Preferisce aprire nuove schede diff --git a/lang/app/strings/translations_ja.properties b/lang/app/strings/translations_ja.properties index c5279e51d..fea971997 100644 --- a/lang/app/strings/translations_ja.properties +++ b/lang/app/strings/translations_ja.properties @@ -359,7 +359,7 @@ developerModeDescription=有効にすると、開発に役立つさまざまな editor=エディター custom=カスタム passwordManagerCommand=パスワードマネージャーコマンド -passwordManagerCommandDescription=パスワードを取得するために実行するコマンド。プレースホルダ文字列$KEYは、呼び出されたときに引用符で囲まれたパスワードキーに置き換えられる。これは、パスワードを標準出力に出力するために、パスワードマネージャCLIを呼び出す必要がある。\n\nパスワードを必要とする接続をセットアップするときはいつでも、このキーを取得するように設定できる。 +passwordManagerCommandDescription=パスワードを取得するために実行するパスワードマネージャ実装またはカスタムコマンド。カスタムコマンドの場合、$KEYというプレースホルダー文字列は、呼び出されたときに引用符で囲まれたパスワードキーに置き換えられる。これは、パスワードを標準出力に出力するパスワード・マネージャCLIを 呼び出す必要がある。\n\nパスワードを必要とする接続をセットアップするときはいつでも、このキーを取得するように設定できる。 passwordManagerCommandTest=テストパスワードマネージャー passwordManagerCommandTestDescription=パスワード・マネージャー・コマンドをセットアップした場合、出力が正しく見えるかどうかをここでテストできる。コマンドはパスワードそのものを標準出力に出力するだけで、他の書式は出力に含まれないはずである。 preferEditorTabs=新しいタブを開きたい diff --git a/lang/app/strings/translations_nl.properties b/lang/app/strings/translations_nl.properties index 64d6a4d5f..9bef8aacd 100644 --- a/lang/app/strings/translations_nl.properties +++ b/lang/app/strings/translations_nl.properties @@ -359,7 +359,7 @@ developerModeDescription=Als deze optie is ingeschakeld, heb je toegang tot een editor=Bewerker custom=Aangepaste passwordManagerCommand=Opdracht voor wachtwoordbeheer -passwordManagerCommandDescription=Het commando dat moet worden uitgevoerd om wachtwoorden op te halen. De tekenreeks $KEY wordt bij het aanroepen vervangen door de geciteerde wachtwoordsleutel. Dit moet je wachtwoordmanager CLI aanroepen om het wachtwoord naar stdout af te drukken, bijvoorbeeld mypassmgr get $KEY.\n\nJe kunt dan instellen dat de sleutel wordt opgehaald wanneer je een verbinding opzet waarvoor een wachtwoord nodig is. +passwordManagerCommandDescription=De implementatie van de wachtwoordmanager of het aangepaste commando dat moet worden uitgevoerd om wachtwoorden op te halen. Voor aangepaste commando's wordt de tekenreeks $KEY vervangen door de wachtwoordsleutel wanneer deze wordt aangeroepen. Dit moet je wachtwoordmanager CLI aanroepen om het wachtwoord naar stdout af te drukken, bijvoorbeeld mypassmgr get $KEY.\n\nJe kunt dan instellen dat de sleutel wordt opgehaald wanneer je een verbinding opzet waarvoor een wachtwoord nodig is. passwordManagerCommandTest=Wachtwoordmanager testen passwordManagerCommandTestDescription=Je kunt hier testen of de uitvoer er correct uitziet als je een wachtwoordmanager-commando hebt ingesteld. Het commando moet alleen het wachtwoord zelf uitvoeren naar stdout, er mag geen andere opmaak in de uitvoer worden opgenomen. preferEditorTabs=Open liever nieuwe tabbladen diff --git a/lang/app/strings/translations_pt.properties b/lang/app/strings/translations_pt.properties index 6d15c332e..6995cee0e 100644 --- a/lang/app/strings/translations_pt.properties +++ b/lang/app/strings/translations_pt.properties @@ -359,7 +359,7 @@ developerModeDescription=Quando ativado, terás acesso a uma variedade de opçõ editor=Editor custom=Personaliza passwordManagerCommand=Comando do gestor de senhas -passwordManagerCommandDescription=O comando a executar para ir buscar as palavras-passe. A string de espaço reservado $KEY será substituída pela chave de senha citada quando chamada. Isto deve chamar o teu gestor de senhas CLI para imprimir a senha para stdout, por exemplo, mypassmgr get $KEY.\n\nPodes então definir a chave para ser recuperada sempre que configurares uma ligação que requeira uma palavra-passe. +passwordManagerCommandDescription=A implementação do gestor de palavras-passe ou o comando personalizado a executar para obter palavras-passe. Para comandos personalizados, a string de espaço reservado $KEY será substituída pela chave de senha citada quando chamada. Isto deve chamar o teu gestor de palavras-passe CLI para imprimir a palavra-passe no stdout, por exemplo, mypassmgr get $KEY.\n\nPodes então definir a chave para ser recuperada sempre que estabeleceres uma ligação que requeira uma palavra-passe. passwordManagerCommandTest=Testa o gestor de palavras-passe passwordManagerCommandTestDescription=Podes testar aqui se a saída parece correcta se tiveres configurado um comando de gestão de palavras-passe. O comando só deve enviar a própria palavra-passe para stdout, não devendo ser incluída qualquer outra formatação na saída. preferEditorTabs=Prefere abrir novos separadores diff --git a/lang/app/strings/translations_ru.properties b/lang/app/strings/translations_ru.properties index d16895c78..3f57db315 100644 --- a/lang/app/strings/translations_ru.properties +++ b/lang/app/strings/translations_ru.properties @@ -359,7 +359,7 @@ developerModeDescription=Если включить эту функцию, то editor=Редактор custom=Пользовательский passwordManagerCommand=Команда менеджера паролей -passwordManagerCommandDescription=Команда, которую нужно выполнить для получения паролей. Строка-заполнитель $KEY при вызове будет заменена на заключенный в кавычки ключ пароля. Это должно вызвать CLI твоего менеджера паролей для печати пароля в stdout, например, mypassmgr get $KEY.\n\nЗатем ты можешь задать, чтобы ключ извлекался всякий раз, когда ты устанавливаешь соединение, требующее ввода пароля. +passwordManagerCommandDescription=Реализация менеджера паролей или пользовательская команда, которую нужно выполнить для получения паролей. Для пользовательских команд строка-заполнитель $KEY при вызове будет заменена на ключ пароля, взятый в кавычки. Это должно вызвать CLI твоего менеджера паролей для печати пароля в stdout, например, mypassmgr get $KEY.\n\nЗатем ты можешь задать, чтобы ключ извлекался всякий раз, когда ты устанавливаешь соединение, требующее ввода пароля. passwordManagerCommandTest=Тестовый менеджер паролей passwordManagerCommandTestDescription=Здесь ты можешь проверить, правильно ли выглядит вывод, если ты настроил команду менеджера паролей. Команда должна выводить в stdout только сам пароль, никакое другое форматирование не должно присутствовать в выводе. preferEditorTabs=Предпочитает открывать новые вкладки diff --git a/lang/app/strings/translations_tr.properties b/lang/app/strings/translations_tr.properties index ef434cd8e..7c402df86 100644 --- a/lang/app/strings/translations_tr.properties +++ b/lang/app/strings/translations_tr.properties @@ -360,7 +360,7 @@ developerModeDescription=Etkinleştirildiğinde, geliştirme için yararlı olan editor=Editör custom=Özel passwordManagerCommand=Parola yöneticisi komutu -passwordManagerCommandDescription=Parolaları almak için çalıştırılacak komut. Yer tutucu dize $KEY, çağrıldığında alıntılanan parola anahtarıyla değiştirilecektir. Bu, parolayı stdout'a yazdırmak için parola yöneticinizin CLI'sini çağırmalıdır, örneğin mypassmgr get $KEY.\n\nDaha sonra anahtarı, parola gerektiren bir bağlantı kurduğunuzda alınacak şekilde ayarlayabilirsiniz. +passwordManagerCommandDescription=Parolaları almak için çalıştırılacak parola yöneticisi uygulaması veya özel komut. Özel komutlar için $KEY yer tutucu dizesi, çağrıldığında alıntılanan parola anahtarıyla değiştirilecektir. Bu, parolayı stdout'a yazdırmak için parola yöneticinizin CLI'sini çağırmalıdır, örneğin mypassmgr get $KEY.\n\nDaha sonra anahtarı, parola gerektiren bir bağlantı kurduğunuzda alınacak şekilde ayarlayabilirsiniz. passwordManagerCommandTest=Parola yöneticisini test edin passwordManagerCommandTestDescription=Bir parola yöneticisi komutu kurduysanız çıktının doğru görünüp görünmediğini burada test edebilirsiniz. Komut yalnızca parolanın kendisini stdout'a çıktılamalıdır, çıktıya başka hiçbir biçimlendirme dahil edilmemelidir. preferEditorTabs=Yeni sekmeler açmayı tercih edin diff --git a/lang/app/strings/translations_zh.properties b/lang/app/strings/translations_zh.properties index d00a6ec90..00dce968d 100644 --- a/lang/app/strings/translations_zh.properties +++ b/lang/app/strings/translations_zh.properties @@ -359,7 +359,7 @@ developerModeDescription=启用后,您可以访问各种对开发有用的附 editor=编辑器 custom=自定义 passwordManagerCommand=密码管理器命令 -passwordManagerCommandDescription=为获取密码而执行的命令。在调用时,占位符字符串 $KEY 将被带引号的密码密钥替换。该命令应调用密码管理器 CLI 将密码打印到 stdout,例如:mypassmgr get $KEY。\n\n然后,您就可以设置在建立需要密码的连接时检索密钥。 +passwordManagerCommandDescription=用于获取密码的密码管理器执行程序或自定义命令。对于自定义命令,在调用时,占位符字符串 $KEY 将被带引号的密码密钥替换。该命令应调用密码管理器 CLI 将密码打印到 stdout,例如:mypassmgr get $KEY。\n\n然后,您就可以设置在建立需要密码的连接时检索密钥。 passwordManagerCommandTest=测试密码管理器 passwordManagerCommandTestDescription=如果您设置了密码管理器命令,可以在此测试输出是否正确。该命令只能将密码本身输出到 stdout,输出中不应包含其他格式。 preferEditorTabs=首选打开新标签页