mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-21 20:21:27 +00:00
Added save password functionality to UI
This commit is contained in:
@@ -14,7 +14,7 @@ public interface KeychainAccess {
|
||||
* @param key Unique key previously used while {@link #storePassphrase(String, CharSequence) storing a passphrase}.
|
||||
* @return The stored passphrase for the given key or <code>null</code> if no value for the given key could be found.
|
||||
*/
|
||||
CharSequence loadPassphrase(String key);
|
||||
char[] loadPassphrase(String key);
|
||||
|
||||
/**
|
||||
* Deletes a passphrase with a given key.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.cryptomator.keychain;
|
||||
|
||||
import java.nio.CharBuffer;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@@ -29,8 +27,8 @@ class MacSystemKeychainAccess implements KeychainAccessStrategy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence loadPassphrase(String key) {
|
||||
return CharBuffer.wrap(keychain.loadPassword(key));
|
||||
public char[] loadPassphrase(String key) {
|
||||
return keychain.loadPassword(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,7 +32,7 @@ class WindowsSystemKeychainAccess implements KeychainAccessStrategy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence loadPassphrase(String key) {
|
||||
public char[] loadPassphrase(String key) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import dagger.Component;
|
||||
|
||||
@Singleton
|
||||
@Component(modules = KeychainModule.class)
|
||||
public interface KeychainComponent {
|
||||
interface KeychainComponent {
|
||||
|
||||
Optional<KeychainAccess> keychainAccess();
|
||||
|
||||
@@ -5,15 +5,19 @@ import java.util.Map;
|
||||
|
||||
class MapKeychainAccess implements KeychainAccessStrategy {
|
||||
|
||||
private final Map<String, CharSequence> map = new HashMap<>();
|
||||
private final Map<String, char[]> map = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void storePassphrase(String key, CharSequence passphrase) {
|
||||
map.put(key, passphrase);
|
||||
char[] pw = new char[passphrase.length()];
|
||||
for (int i = 0; i < passphrase.length(); i++) {
|
||||
pw[i] = passphrase.charAt(i);
|
||||
}
|
||||
map.put(key, pw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence loadPassphrase(String key) {
|
||||
public char[] loadPassphrase(String key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>filesystem-api</artifactId>
|
||||
@@ -107,7 +106,6 @@
|
||||
<artifactId>filesystem-stats</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>frontend-api</artifactId>
|
||||
@@ -118,7 +116,11 @@
|
||||
<artifactId>frontend-webdav</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>keychain</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>ui</artifactId>
|
||||
|
||||
@@ -58,6 +58,10 @@
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>jni</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>keychain</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- CryptoLib -->
|
||||
<dependency>
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.cryptomator.frontend.webdav.WebDavModule;
|
||||
import org.cryptomator.frontend.webdav.WebDavServer;
|
||||
import org.cryptomator.jni.JniModule;
|
||||
import org.cryptomator.jni.MacFunctions;
|
||||
import org.cryptomator.keychain.KeychainModule;
|
||||
import org.cryptomator.ui.model.Vault;
|
||||
import org.cryptomator.ui.model.VaultObjectMapperProvider;
|
||||
import org.cryptomator.ui.model.Vaults;
|
||||
@@ -42,7 +43,7 @@ import javafx.application.Application;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
@Module(includes = {CryptoEngineModule.class, CommonsModule.class, WebDavModule.class})
|
||||
@Module(includes = {CryptoEngineModule.class, CommonsModule.class, WebDavModule.class, KeychainModule.class})
|
||||
class CryptomatorModule {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CryptomatorModule.class);
|
||||
|
||||
@@ -12,6 +12,7 @@ package org.cryptomator.ui.controllers;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -31,9 +32,7 @@ import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
@@ -49,9 +48,9 @@ public class ChangePasswordController extends LocalizedFXMLViewController {
|
||||
|
||||
private final Application app;
|
||||
private final PasswordStrengthUtil strengthRater;
|
||||
final ObjectProperty<Vault> vault = new SimpleObjectProperty<>();
|
||||
private Optional<ChangePasswordListener> listener = Optional.empty();
|
||||
private final IntegerProperty passwordStrength = new SimpleIntegerProperty(); // 0-4
|
||||
private Optional<ChangePasswordListener> listener = Optional.empty();
|
||||
private Vault vault;
|
||||
|
||||
@Inject
|
||||
public ChangePasswordController(Application app, PasswordStrengthUtil strengthRater, Localization localization) {
|
||||
@@ -101,7 +100,6 @@ public class ChangePasswordController extends LocalizedFXMLViewController {
|
||||
BooleanBinding oldPasswordIsEmpty = oldPasswordField.textProperty().isEmpty();
|
||||
BooleanBinding newPasswordIsEmpty = newPasswordField.textProperty().isEmpty();
|
||||
BooleanBinding passwordsDiffer = newPasswordField.textProperty().isNotEqualTo(retypePasswordField.textProperty());
|
||||
EasyBind.subscribe(vault, this::vaultDidChange);
|
||||
changePasswordButton.disableProperty().bind(oldPasswordIsEmpty.or(newPasswordIsEmpty.or(passwordsDiffer)));
|
||||
passwordStrength.bind(EasyBind.map(newPasswordField.textProperty(), strengthRater::computeRate));
|
||||
|
||||
@@ -118,10 +116,11 @@ public class ChangePasswordController extends LocalizedFXMLViewController {
|
||||
return getClass().getResource("/fxml/change_password.fxml");
|
||||
}
|
||||
|
||||
private void vaultDidChange(Vault newVault) {
|
||||
oldPasswordField.clear();
|
||||
newPasswordField.clear();
|
||||
retypePasswordField.clear();
|
||||
void setVault(Vault vault) {
|
||||
this.vault = Objects.requireNonNull(vault);
|
||||
oldPasswordField.swipe();
|
||||
newPasswordField.swipe();
|
||||
retypePasswordField.swipe();
|
||||
// trigger "default" change to refresh key bindings:
|
||||
changePasswordButton.setDefaultButton(false);
|
||||
changePasswordButton.setDefaultButton(true);
|
||||
@@ -144,7 +143,7 @@ public class ChangePasswordController extends LocalizedFXMLViewController {
|
||||
private void didClickChangePasswordButton(ActionEvent event) {
|
||||
downloadsPageLink.setVisible(false);
|
||||
try {
|
||||
vault.get().changePassphrase(oldPasswordField.getCharacters(), newPasswordField.getCharacters());
|
||||
vault.changePassphrase(oldPasswordField.getCharacters(), newPasswordField.getCharacters());
|
||||
messageText.setText(localization.getString("changePassword.infoMessage.success"));
|
||||
listener.ifPresent(this::invokeListenerLater);
|
||||
} catch (InvalidPassphraseException e) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -29,9 +30,7 @@ import org.slf4j.LoggerFactory;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
@@ -44,9 +43,9 @@ public class InitializeController extends LocalizedFXMLViewController {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(InitializeController.class);
|
||||
|
||||
private final PasswordStrengthUtil strengthRater;
|
||||
final ObjectProperty<Vault> vault = new SimpleObjectProperty<>();
|
||||
private Optional<InitializationListener> listener = Optional.empty();
|
||||
private final IntegerProperty passwordStrength = new SimpleIntegerProperty(); // 0-4
|
||||
private Optional<InitializationListener> listener = Optional.empty();
|
||||
private Vault vault;
|
||||
|
||||
@Inject
|
||||
public InitializeController(Localization localization, PasswordStrengthUtil strengthRater) {
|
||||
@@ -88,7 +87,6 @@ public class InitializeController extends LocalizedFXMLViewController {
|
||||
public void initialize() {
|
||||
BooleanBinding passwordIsEmpty = passwordField.textProperty().isEmpty();
|
||||
BooleanBinding passwordsDiffer = passwordField.textProperty().isNotEqualTo(retypePasswordField.textProperty());
|
||||
EasyBind.subscribe(vault, this::vaultDidChange);
|
||||
okButton.disableProperty().bind(passwordIsEmpty.or(passwordsDiffer));
|
||||
passwordStrength.bind(EasyBind.map(passwordField.textProperty(), strengthRater::computeRate));
|
||||
|
||||
@@ -105,9 +103,10 @@ public class InitializeController extends LocalizedFXMLViewController {
|
||||
return getClass().getResource("/fxml/initialize.fxml");
|
||||
}
|
||||
|
||||
private void vaultDidChange(Vault newVault) {
|
||||
passwordField.clear();
|
||||
retypePasswordField.clear();
|
||||
void setVault(Vault vault) {
|
||||
this.vault = Objects.requireNonNull(vault);
|
||||
passwordField.swipe();
|
||||
retypePasswordField.swipe();
|
||||
// trigger "default" change to refresh key bindings:
|
||||
okButton.setDefaultButton(false);
|
||||
okButton.setDefaultButton(true);
|
||||
@@ -121,7 +120,7 @@ public class InitializeController extends LocalizedFXMLViewController {
|
||||
protected void initializeVault(ActionEvent event) {
|
||||
final CharSequence passphrase = passwordField.getCharacters();
|
||||
try {
|
||||
vault.get().create(passphrase);
|
||||
vault.create(passphrase);
|
||||
listener.ifPresent(this::invokeListenerLater);
|
||||
} catch (FileAlreadyExistsException ex) {
|
||||
messageLabel.setText(localization.getString("initialize.messageLabel.alreadyInitialized"));
|
||||
|
||||
@@ -315,7 +315,8 @@ public class MainController extends LocalizedFXMLViewController {
|
||||
|
||||
private void showInitializeView() {
|
||||
final InitializeController ctrl = initializeController.get();
|
||||
ctrl.vault.bind(selectedVault);
|
||||
ctrl.loadFxml();
|
||||
ctrl.setVault(selectedVault.get());
|
||||
ctrl.setListener(this::didInitialize);
|
||||
activeController.set(ctrl);
|
||||
}
|
||||
@@ -326,7 +327,8 @@ public class MainController extends LocalizedFXMLViewController {
|
||||
|
||||
private void showUpgradeView() {
|
||||
final UpgradeController ctrl = upgradeController.get();
|
||||
ctrl.vault.bind(selectedVault);
|
||||
ctrl.loadFxml();
|
||||
ctrl.setVault(selectedVault.get());
|
||||
ctrl.setListener(this::didUpgrade);
|
||||
activeController.set(ctrl);
|
||||
}
|
||||
@@ -337,7 +339,8 @@ public class MainController extends LocalizedFXMLViewController {
|
||||
|
||||
private void showUnlockView() {
|
||||
final UnlockController ctrl = unlockController.get();
|
||||
ctrl.vault.bind(selectedVault);
|
||||
ctrl.loadFxml();
|
||||
ctrl.setVault(selectedVault.get());
|
||||
ctrl.setListener(this::didUnlock);
|
||||
activeController.set(ctrl);
|
||||
}
|
||||
@@ -353,6 +356,7 @@ public class MainController extends LocalizedFXMLViewController {
|
||||
final UnlockedController ctrl = unlockedVaults.computeIfAbsent(vault, k -> {
|
||||
return unlockedControllerProvider.get();
|
||||
});
|
||||
ctrl.loadFxml();
|
||||
ctrl.setVault(vault);
|
||||
ctrl.setListener(this::didLock);
|
||||
activeController.set(ctrl);
|
||||
@@ -368,7 +372,8 @@ public class MainController extends LocalizedFXMLViewController {
|
||||
|
||||
private void showChangePasswordView() {
|
||||
final ChangePasswordController ctrl = changePasswordController.get();
|
||||
ctrl.vault.bind(selectedVault);
|
||||
ctrl.loadFxml();
|
||||
ctrl.setVault(selectedVault.get());
|
||||
ctrl.setListener(this::didChangePassword);
|
||||
activeController.set(ctrl);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
package org.cryptomator.ui.controllers;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -22,25 +24,24 @@ import org.cryptomator.frontend.CommandFailedException;
|
||||
import org.cryptomator.frontend.FrontendCreationFailedException;
|
||||
import org.cryptomator.frontend.FrontendFactory;
|
||||
import org.cryptomator.frontend.webdav.mount.WindowsDriveLetters;
|
||||
import org.cryptomator.keychain.KeychainAccess;
|
||||
import org.cryptomator.ui.controls.SecPasswordField;
|
||||
import org.cryptomator.ui.model.Vault;
|
||||
import org.cryptomator.ui.settings.Localization;
|
||||
import org.cryptomator.ui.settings.Settings;
|
||||
import org.cryptomator.ui.util.AsyncTaskService;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dagger.Lazy;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.ChoiceBox;
|
||||
import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.control.Label;
|
||||
@@ -61,22 +62,34 @@ public class UnlockController extends LocalizedFXMLViewController {
|
||||
private final Settings settings;
|
||||
private final WindowsDriveLetters driveLetters;
|
||||
private final ChangeListener<Character> driveLetterChangeListener = this::winDriveLetterDidChange;
|
||||
final ObjectProperty<Vault> vault = new SimpleObjectProperty<>();
|
||||
private final Optional<KeychainAccess> keychainAccess;
|
||||
private Vault vault;
|
||||
private Optional<UnlockListener> listener = Optional.empty();
|
||||
|
||||
@Inject
|
||||
public UnlockController(Application app, Localization localization, AsyncTaskService asyncTaskService, Lazy<FrontendFactory> frontendFactory, Settings settings, WindowsDriveLetters driveLetters) {
|
||||
public UnlockController(Application app, Localization localization, AsyncTaskService asyncTaskService, Lazy<FrontendFactory> frontendFactory, Settings settings, WindowsDriveLetters driveLetters,
|
||||
Optional<KeychainAccess> keychainAccess) {
|
||||
super(localization);
|
||||
this.app = app;
|
||||
this.asyncTaskService = asyncTaskService;
|
||||
this.frontendFactory = frontendFactory;
|
||||
this.settings = settings;
|
||||
this.driveLetters = driveLetters;
|
||||
this.keychainAccess = keychainAccess;
|
||||
}
|
||||
|
||||
@FXML
|
||||
private SecPasswordField passwordField;
|
||||
|
||||
@FXML
|
||||
private Button advancedOptionsButton;
|
||||
|
||||
@FXML
|
||||
private Button unlockButton;
|
||||
|
||||
@FXML
|
||||
private CheckBox savePassword;
|
||||
|
||||
@FXML
|
||||
private TextField mountName;
|
||||
|
||||
@@ -86,12 +99,6 @@ public class UnlockController extends LocalizedFXMLViewController {
|
||||
@FXML
|
||||
private ChoiceBox<Character> winDriveLetter;
|
||||
|
||||
@FXML
|
||||
private Button advancedOptionsButton;
|
||||
|
||||
@FXML
|
||||
private Button unlockButton;
|
||||
|
||||
@FXML
|
||||
private ProgressIndicator progressIndicator;
|
||||
|
||||
@@ -107,8 +114,10 @@ public class UnlockController extends LocalizedFXMLViewController {
|
||||
@Override
|
||||
public void initialize() {
|
||||
advancedOptions.managedProperty().bind(advancedOptions.visibleProperty());
|
||||
unlockButton.disableProperty().bind(passwordField.textProperty().isEmpty());
|
||||
mountName.addEventFilter(KeyEvent.KEY_TYPED, this::filterAlphanumericKeyEvents);
|
||||
mountName.textProperty().addListener(this::mountNameDidChange);
|
||||
savePassword.setDisable(!keychainAccess.isPresent());
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
winDriveLetter.setConverter(new WinDriveLetterLabelConverter());
|
||||
} else {
|
||||
@@ -117,9 +126,6 @@ public class UnlockController extends LocalizedFXMLViewController {
|
||||
winDriveLetter.setVisible(false);
|
||||
winDriveLetter.setManaged(false);
|
||||
}
|
||||
unlockButton.disableProperty().bind(passwordField.textProperty().isEmpty());
|
||||
|
||||
EasyBind.subscribe(vault, this::vaultDidChange);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -127,11 +133,15 @@ public class UnlockController extends LocalizedFXMLViewController {
|
||||
return getClass().getResource("/fxml/unlock.fxml");
|
||||
}
|
||||
|
||||
private void vaultDidChange(Vault newVault) {
|
||||
if (newVault == null) {
|
||||
void setVault(Vault vault) {
|
||||
// trigger "default" change to refresh key bindings:
|
||||
unlockButton.setDefaultButton(false);
|
||||
unlockButton.setDefaultButton(true);
|
||||
if (vault.equals(this.vault)) {
|
||||
return;
|
||||
}
|
||||
passwordField.clear();
|
||||
this.vault = Objects.requireNonNull(vault);
|
||||
passwordField.swipe();
|
||||
advancedOptions.setVisible(false);
|
||||
advancedOptionsButton.setText(localization.getString("unlock.button.advancedOptions.show"));
|
||||
progressIndicator.setVisible(false);
|
||||
@@ -145,13 +155,21 @@ public class UnlockController extends LocalizedFXMLViewController {
|
||||
}
|
||||
downloadsPageLink.setVisible(false);
|
||||
messageText.setText(null);
|
||||
mountName.setText(newVault.getMountName());
|
||||
mountName.setText(vault.getMountName());
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
chooseSelectedDriveLetter();
|
||||
}
|
||||
// trigger "default" change to refresh key bindings:
|
||||
unlockButton.setDefaultButton(false);
|
||||
unlockButton.setDefaultButton(true);
|
||||
savePassword.setSelected(false);
|
||||
// auto-fill pw from keychain:
|
||||
if (keychainAccess.isPresent()) {
|
||||
char[] storedPw = keychainAccess.get().loadPassphrase(vault.getId());
|
||||
if (storedPw != null) {
|
||||
savePassword.setSelected(true);
|
||||
passwordField.setText(new String(storedPw));
|
||||
passwordField.selectRange(storedPw.length, storedPw.length);
|
||||
Arrays.fill(storedPw, ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ****************************************
|
||||
@@ -188,14 +206,11 @@ public class UnlockController extends LocalizedFXMLViewController {
|
||||
}
|
||||
|
||||
private void mountNameDidChange(ObservableValue<? extends String> property, String oldValue, String newValue) {
|
||||
if (vault.get() == null) {
|
||||
return;
|
||||
}
|
||||
// newValue is guaranteed to be a-z0-9_, see #filterAlphanumericKeyEvents
|
||||
if (newValue.isEmpty()) {
|
||||
mountName.setText(vault.get().getMountName());
|
||||
mountName.setText(vault.getMountName());
|
||||
} else {
|
||||
vault.get().setMountName(newValue);
|
||||
vault.setMountName(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,20 +257,17 @@ public class UnlockController extends LocalizedFXMLViewController {
|
||||
}
|
||||
|
||||
private void winDriveLetterDidChange(ObservableValue<? extends Character> property, Character oldValue, Character newValue) {
|
||||
if (vault.get() == null) {
|
||||
return;
|
||||
}
|
||||
vault.get().setWinDriveLetter(newValue);
|
||||
vault.setWinDriveLetter(newValue);
|
||||
settings.save();
|
||||
}
|
||||
|
||||
private void chooseSelectedDriveLetter() {
|
||||
assert SystemUtils.IS_OS_WINDOWS;
|
||||
// if the vault prefers a drive letter, that is currently occupied, this is our last chance to reset this:
|
||||
if (driveLetters.getOccupiedDriveLetters().contains(vault.get().getWinDriveLetter())) {
|
||||
vault.get().setWinDriveLetter(null);
|
||||
if (driveLetters.getOccupiedDriveLetters().contains(vault.getWinDriveLetter())) {
|
||||
vault.setWinDriveLetter(null);
|
||||
}
|
||||
final Character letter = vault.get().getWinDriveLetter();
|
||||
final Character letter = vault.getWinDriveLetter();
|
||||
if (letter == null) {
|
||||
// first option is known to be 'auto-assign' due to #WinDriveLetterComparator.
|
||||
this.winDriveLetter.getSelectionModel().selectFirst();
|
||||
@@ -275,10 +287,10 @@ public class UnlockController extends LocalizedFXMLViewController {
|
||||
progressIndicator.setVisible(true);
|
||||
downloadsPageLink.setVisible(false);
|
||||
CharSequence password = passwordField.getCharacters();
|
||||
asyncTaskService.asyncTaskOf(() -> this.unlock(vault.get(), password)).run();
|
||||
asyncTaskService.asyncTaskOf(() -> this.unlock(password)).run();
|
||||
}
|
||||
|
||||
private void unlock(Vault vault, CharSequence password) {
|
||||
private void unlock(CharSequence password) {
|
||||
try {
|
||||
vault.activateFrontend(frontendFactory.get(), settings, password);
|
||||
vault.reveal();
|
||||
@@ -286,9 +298,15 @@ public class UnlockController extends LocalizedFXMLViewController {
|
||||
messageText.setText(null);
|
||||
listener.ifPresent(lstnr -> lstnr.didUnlock(vault));
|
||||
});
|
||||
if (keychainAccess.isPresent() && savePassword.isSelected()) {
|
||||
keychainAccess.get().storePassphrase(vault.getId(), password);
|
||||
} else {
|
||||
passwordField.swipe();
|
||||
}
|
||||
} catch (InvalidPassphraseException e) {
|
||||
Platform.runLater(() -> {
|
||||
messageText.setText(localization.getString("unlock.errorMessage.wrongPassword"));
|
||||
passwordField.selectAll();
|
||||
passwordField.requestFocus();
|
||||
});
|
||||
} catch (UnsupportedVaultFormatException e) {
|
||||
@@ -307,7 +325,6 @@ public class UnlockController extends LocalizedFXMLViewController {
|
||||
});
|
||||
} finally {
|
||||
Platform.runLater(() -> {
|
||||
passwordField.swipe();
|
||||
mountName.setDisable(false);
|
||||
advancedOptionsButton.setDisable(false);
|
||||
progressIndicator.setVisible(false);
|
||||
|
||||
@@ -27,11 +27,11 @@ import javafx.scene.control.ProgressIndicator;
|
||||
|
||||
public class UpgradeController extends LocalizedFXMLViewController {
|
||||
|
||||
final ObjectProperty<Vault> vault = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Optional<UpgradeStrategy>> strategy = new SimpleObjectProperty<>();
|
||||
private final ObjectProperty<Optional<UpgradeStrategy>> strategy = new SimpleObjectProperty<>();
|
||||
private final UpgradeStrategies strategies;
|
||||
private final AsyncTaskService asyncTaskService;
|
||||
private Optional<UpgradeListener> listener = Optional.empty();
|
||||
private Vault vault;
|
||||
|
||||
@Inject
|
||||
public UpgradeController(Localization localization, UpgradeStrategies strategies, AsyncTaskService asyncTaskService) {
|
||||
@@ -67,8 +67,6 @@ public class UpgradeController extends LocalizedFXMLViewController {
|
||||
BooleanExpression passwordProvided = passwordField.textProperty().isNotEmpty().and(passwordField.disabledProperty().not());
|
||||
BooleanExpression syncFinished = confirmationCheckbox.selectedProperty();
|
||||
upgradeButton.disableProperty().bind(passwordProvided.not().or(syncFinished.not()));
|
||||
|
||||
EasyBind.subscribe(vault, this::vaultDidChange);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,9 +74,10 @@ public class UpgradeController extends LocalizedFXMLViewController {
|
||||
return getClass().getResource("/fxml/upgrade.fxml");
|
||||
}
|
||||
|
||||
private void vaultDidChange(Vault newVault) {
|
||||
void setVault(Vault vault) {
|
||||
this.vault = Objects.requireNonNull(vault);
|
||||
errorLabel.setText(null);
|
||||
strategy.set(strategies.getUpgradeStrategy(newVault));
|
||||
strategy.set(strategies.getUpgradeStrategy(vault));
|
||||
// trigger "default" change to refresh key bindings:
|
||||
upgradeButton.setDefaultButton(false);
|
||||
upgradeButton.setDefaultButton(true);
|
||||
@@ -89,7 +88,7 @@ public class UpgradeController extends LocalizedFXMLViewController {
|
||||
// ****************************************
|
||||
|
||||
private String upgradeNotification(UpgradeStrategy instruction) {
|
||||
return instruction.getNotification(vault.get());
|
||||
return instruction.getNotification(vault);
|
||||
}
|
||||
|
||||
// ****************************************
|
||||
@@ -102,15 +101,14 @@ public class UpgradeController extends LocalizedFXMLViewController {
|
||||
}
|
||||
|
||||
private void upgrade(UpgradeStrategy instruction) {
|
||||
Vault v = Objects.requireNonNull(vault.getValue());
|
||||
passwordField.setDisable(true);
|
||||
progressIndicator.setVisible(true);
|
||||
asyncTaskService //
|
||||
.asyncTaskOf(() -> {
|
||||
if (!instruction.isApplicable(v)) {
|
||||
throw new IllegalStateException("No ugprade needed for " + v.path().getValue());
|
||||
if (!instruction.isApplicable(vault)) {
|
||||
throw new IllegalStateException("No ugprade needed for " + vault.path().getValue());
|
||||
}
|
||||
instruction.upgrade(v, passwordField.getCharacters());
|
||||
instruction.upgrade(vault, passwordField.getCharacters());
|
||||
}) //
|
||||
.onSuccess(this::showNextUpgrade) //
|
||||
.onError(UpgradeFailedException.class, e -> {
|
||||
@@ -125,7 +123,7 @@ public class UpgradeController extends LocalizedFXMLViewController {
|
||||
|
||||
private void showNextUpgrade() {
|
||||
errorLabel.setText(null);
|
||||
Optional<UpgradeStrategy> nextStrategy = strategies.getUpgradeStrategy(vault.getValue());
|
||||
Optional<UpgradeStrategy> nextStrategy = strategies.getUpgradeStrategy(vault);
|
||||
if (nextStrategy.isPresent()) {
|
||||
strategy.set(nextStrategy);
|
||||
} else {
|
||||
|
||||
@@ -68,12 +68,16 @@
|
||||
</HBox>
|
||||
|
||||
<!-- Row 3.1 -->
|
||||
<Label text="%unlock.label.mountName" GridPane.rowIndex="1" GridPane.columnIndex="0" cacheShape="true" cache="true" />
|
||||
<TextField fx:id="mountName" GridPane.rowIndex="1" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
|
||||
<Label GridPane.rowIndex="1" GridPane.columnIndex="0" text="%unlock.label.savePassword" cacheShape="true" cache="true" />
|
||||
<CheckBox GridPane.rowIndex="1" GridPane.columnIndex="1" fx:id="savePassword" cacheShape="true" cache="true" />
|
||||
|
||||
<!-- Row 3.2 -->
|
||||
<Label fx:id="winDriveLetterLabel" text="%unlock.label.winDriveLetter" GridPane.rowIndex="2" GridPane.columnIndex="0" cacheShape="true" cache="true" />
|
||||
<ChoiceBox fx:id="winDriveLetter" GridPane.rowIndex="2" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
|
||||
<Label GridPane.rowIndex="2" GridPane.columnIndex="0" text="%unlock.label.mountName" cacheShape="true" cache="true" />
|
||||
<TextField GridPane.rowIndex="2" GridPane.columnIndex="1" fx:id="mountName" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
|
||||
|
||||
<!-- Row 3.3 -->
|
||||
<Label GridPane.rowIndex="3" GridPane.columnIndex="0" fx:id="winDriveLetterLabel" text="%unlock.label.winDriveLetter" cacheShape="true" cache="true" />
|
||||
<ChoiceBox GridPane.rowIndex="3" GridPane.columnIndex="1" fx:id="winDriveLetter" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
|
||||
</GridPane>
|
||||
|
||||
<!-- Row 4 -->
|
||||
|
||||
@@ -49,6 +49,7 @@ upgrade.version3to4.err.io=Migration failed due to an I/O Exception. See log fil
|
||||
|
||||
# unlock.fxml
|
||||
unlock.label.password=Password
|
||||
unlock.label.savePassword=Save password
|
||||
unlock.label.mountName=Drive name
|
||||
unlock.label.winDriveLetter=Drive letter
|
||||
unlock.label.downloadsPageLink=All Cryptomator versions
|
||||
|
||||
Reference in New Issue
Block a user