mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-08-12 04:21:01 +00:00
Rework
This commit is contained in:
@@ -76,9 +76,13 @@ public class AppShellCheck {
|
||||
|
||||
@Override
|
||||
protected boolean fallBackInstantly() {
|
||||
var complex = ShellDialects.CMD.requiresScript(System.getenv("USERPROFILE")) ||
|
||||
ShellDialects.CMD.requiresScript(System.getenv("TEMP"));
|
||||
return complex;
|
||||
// In theory, this prevents cmd issues with unsupported characters
|
||||
// However, due to workarounds, this should still work
|
||||
// Falling back to powershell would make it slower and introduce other potential issues
|
||||
// var complex = ShellDialects.CMD.requiresScript(System.getenv("USERPROFILE")) ||
|
||||
// ShellDialects.CMD.requiresScript(System.getenv("TEMP"));
|
||||
// return complex;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.xpipe.app.password;
|
||||
|
||||
import io.xpipe.app.ext.ProcessControlProvider;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.util.CommandSupport;
|
||||
import io.xpipe.core.process.CommandBuilder;
|
||||
import io.xpipe.core.process.ShellControl;
|
||||
|
||||
@@ -22,6 +23,16 @@ public class OnePasswordManager implements PasswordManager {
|
||||
|
||||
@Override
|
||||
public String retrievePassword(String key) {
|
||||
try {
|
||||
CommandSupport.isInLocalPathOrThrow("1Password CLI", "op");
|
||||
} catch (Exception e) {
|
||||
ErrorEvent.fromThrowable(e)
|
||||
.expected()
|
||||
.link("https://developer.1password.com/docs/cli/get-started/")
|
||||
.handle();
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
var r = getOrStartShell()
|
||||
.command(CommandBuilder.of()
|
||||
|
||||
@@ -23,6 +23,7 @@ public interface PasswordManager {
|
||||
l.add(EnpassPasswordManager.class);
|
||||
}
|
||||
l.add(KeeperPasswordManager.class);
|
||||
l.add(PsonoPasswordManager.class);
|
||||
if (OsType.getLocal() == OsType.WINDOWS) {
|
||||
l.add(WindowsCredentialManager.class);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
package io.xpipe.app.password;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import io.xpipe.app.comp.base.ButtonComp;
|
||||
import io.xpipe.app.comp.base.SecretFieldComp;
|
||||
import io.xpipe.app.comp.base.TextFieldComp;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.ext.ProcessControlProvider;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.util.*;
|
||||
import io.xpipe.core.process.CommandBuilder;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.process.ShellControl;
|
||||
import io.xpipe.core.util.InPlaceSecretValue;
|
||||
import io.xpipe.core.util.SecretValue;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@ToString
|
||||
@Jacksonized
|
||||
@JsonTypeName("psono")
|
||||
public class PsonoPasswordManager implements PasswordManager {
|
||||
|
||||
private final InPlaceSecretValue apiKey;
|
||||
private final InPlaceSecretValue apiSecretKey;
|
||||
private final String serverUrl;
|
||||
|
||||
public static OptionsBuilder createOptions(Property<PsonoPasswordManager> p) {
|
||||
var apiKey = new SimpleObjectProperty<>(p.getValue().getApiKey());
|
||||
var apiSecretKey = new SimpleObjectProperty<>(p.getValue().getApiSecretKey());
|
||||
var serverUrl = new SimpleStringProperty(p.getValue().getServerUrl());
|
||||
return new OptionsBuilder()
|
||||
.nameAndDescription("psonoServerUrl")
|
||||
.addComp(new TextFieldComp(serverUrl).apply(struc -> {
|
||||
struc.get().setPromptText("https://www.psono.pw/server");
|
||||
}).maxWidth(600), serverUrl)
|
||||
.nameAndDescription("psonoApiKey")
|
||||
.addComp(new SecretFieldComp(apiKey, false).maxWidth(600), apiKey)
|
||||
.nameAndDescription("psonoApiSecretKey")
|
||||
.addComp(new SecretFieldComp(apiSecretKey, false).maxWidth(600), apiSecretKey)
|
||||
.bind(
|
||||
() -> {
|
||||
return PsonoPasswordManager.builder().apiKey(apiKey.get()).apiSecretKey(apiSecretKey.get()).serverUrl(serverUrl.get()).build();
|
||||
},
|
||||
p);
|
||||
}
|
||||
|
||||
private static ShellControl SHELL;
|
||||
|
||||
private static synchronized ShellControl getOrStartShell() throws Exception {
|
||||
if (SHELL == null) {
|
||||
SHELL = ProcessControlProvider.get().createLocalProcessControl(true);
|
||||
}
|
||||
SHELL.start();
|
||||
return SHELL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String retrievePassword(String key) {
|
||||
try {
|
||||
CommandSupport.isInLocalPathOrThrow("Psono CLI", "psonoci");
|
||||
} catch (Exception e) {
|
||||
ErrorEvent.fromThrowable(e)
|
||||
.expected()
|
||||
.link("https://doc.psono.com/user/psonoci/install.html")
|
||||
.handle();
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
var cmd = getOrStartShell()
|
||||
.command(CommandBuilder.of()
|
||||
.add("psonoci", "--api-key-id")
|
||||
.addLiteral(apiKey.getSecretValue())
|
||||
.add("--api-secret-key-hex")
|
||||
.addLiteral(apiSecretKey.getSecretValue())
|
||||
.add("--server-url")
|
||||
.addLiteral(serverUrl)
|
||||
.add("secret", "get")
|
||||
.addLiteral(key)
|
||||
.add("password"));
|
||||
cmd.setSensitive();;
|
||||
var r = cmd.readStdoutOrThrow();
|
||||
return r;
|
||||
} catch (Exception e) {
|
||||
ErrorEvent.fromThrowable(e).handle();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyPlaceholder() {
|
||||
return AppI18n.get("psonoPlaceholder");
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ import io.xpipe.app.terminal.TerminalLauncher;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
import io.xpipe.app.util.LocalShell;
|
||||
import io.xpipe.core.process.CommandBuilder;
|
||||
import io.xpipe.core.process.ShellDialect;
|
||||
import io.xpipe.core.process.ShellDialects;
|
||||
import io.xpipe.core.process.ShellScript;
|
||||
import io.xpipe.core.util.XPipeInstallation;
|
||||
|
||||
@@ -113,11 +115,17 @@ public class ChocoUpdater extends UpdateHandler {
|
||||
var performedUpdate = new PerformedUpdate(p.getVersion(), p.getBody(), p.getVersion());
|
||||
AppCache.update("performedUpdate", performedUpdate);
|
||||
OperationMode.executeAfterShutdown(() -> {
|
||||
var systemWide =
|
||||
Files.exists(XPipeInstallation.getCurrentInstallationBasePath().resolve("system"));
|
||||
var propertiesArguments = systemWide ? ", --install-arguments=\"'ALLUSERS=1'\"" : "";
|
||||
TerminalLauncher.openDirectFallback("XPipe Updater", sc -> {
|
||||
var pkg = "xpipe";
|
||||
var commandToRun = "Start-Process -Wait -Verb runAs -FilePath choco -ArgumentList upgrade, " + pkg
|
||||
+ ", -y" + propertiesArguments;
|
||||
var powershell = ShellDialects.isPowershell(sc);
|
||||
var powershellCommand = powershell ? "powershell -Command " + sc.getShellDialect().quoteArgument(commandToRun) : "powershell -Command " + commandToRun;
|
||||
return ShellScript.lines(
|
||||
"powershell -Command \"Start-Process -Verb runAs -FilePath choco -ArgumentList upgrade, " + pkg
|
||||
+ "\"",
|
||||
powershellCommand,
|
||||
AppRestart.getTerminalRestartCommand());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package io.xpipe.app.util;
|
||||
|
||||
import io.xpipe.app.comp.Comp;
|
||||
import io.xpipe.app.comp.CompStructure;
|
||||
import io.xpipe.app.comp.augment.Augment;
|
||||
import io.xpipe.app.comp.base.*;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.ext.GuiDialog;
|
||||
@@ -16,6 +18,8 @@ import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import javafx.scene.layout.VBox;
|
||||
import net.synedra.validatorfx.Check;
|
||||
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
@@ -35,6 +39,7 @@ public class OptionsBuilder {
|
||||
private final List<Check> allChecks = new ArrayList<>();
|
||||
private final List<OptionsComp.Entry> entries = new ArrayList<>();
|
||||
private final List<Property<?>> props = new ArrayList<>();
|
||||
private final List<Augment<CompStructure<VBox>>> augments = new ArrayList<>();
|
||||
|
||||
private ObservableValue<String> name;
|
||||
private ObservableValue<String> description;
|
||||
@@ -53,6 +58,11 @@ public class OptionsBuilder {
|
||||
this.allValidators.add(ownValidator);
|
||||
}
|
||||
|
||||
public OptionsBuilder augment(Augment<CompStructure<VBox>> augment) {
|
||||
this.augments.add(augment);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Validator buildEffectiveValidator() {
|
||||
return new ChainedValidator(allValidators);
|
||||
}
|
||||
@@ -459,7 +469,11 @@ public class OptionsBuilder {
|
||||
|
||||
public OptionsComp buildComp() {
|
||||
finishCurrent();
|
||||
return new OptionsComp(allChecks, entries);
|
||||
var comp = new OptionsComp(allChecks, entries);
|
||||
for (Augment<CompStructure<VBox>> augment : augments) {
|
||||
comp.apply(augment);
|
||||
}
|
||||
return comp;
|
||||
}
|
||||
|
||||
public Region build() {
|
||||
|
||||
Reference in New Issue
Block a user