Simplify password creation (#1646)

* Remove the password properties and directly access password fields from included fxml files
* wipe the password fields when closing a window
This commit is contained in:
Armin Schrenk
2021-05-17 10:18:10 +02:00
committed by GitHub
parent 189699d359
commit a2ad7d69ab
11 changed files with 64 additions and 91 deletions

View File

@@ -6,10 +6,10 @@ import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.common.NewPasswordController;
import org.cryptomator.ui.common.PasswordStrengthUtil;
@@ -33,13 +33,6 @@ import java.util.ResourceBundle;
@Module
public abstract class AddVaultModule {
@Provides
@AddVaultWizardScoped
@Named("newPassword")
static ObjectProperty<CharSequence> provideNewPasswordProperty() {
return new SimpleObjectProperty<>("");
}
@Provides
@AddVaultWizardWindow
@AddVaultWizardScoped
@@ -167,8 +160,8 @@ public abstract class AddVaultModule {
@Provides
@IntoMap
@FxControllerKey(NewPasswordController.class)
static FxController provideNewPasswordController(ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater, @Named("newPassword") ObjectProperty<CharSequence> password) {
return new NewPasswordController(resourceBundle, strengthRater, password);
static FxController provideNewPasswordController(ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater) {
return new NewPasswordController(resourceBundle, strengthRater);
}
@Binds

View File

@@ -14,6 +14,7 @@ import org.cryptomator.ui.common.ErrorComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.common.NewPasswordController;
import org.cryptomator.ui.common.Tasks;
import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy;
import org.cryptomator.ui.recoverykey.RecoveryKeyFactory;
@@ -23,7 +24,6 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
@@ -41,7 +41,6 @@ import java.net.URI;
import java.nio.channels.WritableByteChannel;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.security.SecureRandom;
@@ -70,7 +69,6 @@ public class CreateNewVaultPasswordController implements FxController {
private final StringProperty recoveryKeyProperty;
private final VaultListManager vaultListManager;
private final ResourceBundle resourceBundle;
private final ObjectProperty<CharSequence> password;
private final ReadmeGenerator readmeGenerator;
private final SecureRandom csprng;
private final MasterkeyFileAccess masterkeyFileAccess;
@@ -81,9 +79,10 @@ public class CreateNewVaultPasswordController implements FxController {
public ToggleGroup recoveryKeyChoice;
public Toggle showRecoveryKey;
public Toggle skipRecoveryKey;
public NewPasswordController newPasswordSceneController;
@Inject
CreateNewVaultPasswordController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_RECOVERYKEY) Lazy<Scene> recoveryKeyScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, ErrorComponent.Builder errorComponent, ExecutorService executor, RecoveryKeyFactory recoveryKeyFactory, @Named("vaultName") StringProperty vaultName, ObjectProperty<Path> vaultPath, @AddVaultWizardWindow ObjectProperty<Vault> vault, @Named("recoveryKey") StringProperty recoveryKey, VaultListManager vaultListManager, ResourceBundle resourceBundle, @Named("newPassword") ObjectProperty<CharSequence> password, ReadmeGenerator readmeGenerator, SecureRandom csprng, MasterkeyFileAccess masterkeyFileAccess) {
CreateNewVaultPasswordController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_RECOVERYKEY) Lazy<Scene> recoveryKeyScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, ErrorComponent.Builder errorComponent, ExecutorService executor, RecoveryKeyFactory recoveryKeyFactory, @Named("vaultName") StringProperty vaultName, ObjectProperty<Path> vaultPath, @AddVaultWizardWindow ObjectProperty<Vault> vault, @Named("recoveryKey") StringProperty recoveryKey, VaultListManager vaultListManager, ResourceBundle resourceBundle, ReadmeGenerator readmeGenerator, SecureRandom csprng, MasterkeyFileAccess masterkeyFileAccess) {
this.window = window;
this.chooseLocationScene = chooseLocationScene;
this.recoveryKeyScene = recoveryKeyScene;
@@ -97,7 +96,6 @@ public class CreateNewVaultPasswordController implements FxController {
this.recoveryKeyProperty = recoveryKey;
this.vaultListManager = vaultListManager;
this.resourceBundle = resourceBundle;
this.password = password;
this.readmeGenerator = readmeGenerator;
this.csprng = csprng;
this.masterkeyFileAccess = masterkeyFileAccess;
@@ -108,8 +106,11 @@ public class CreateNewVaultPasswordController implements FxController {
@FXML
public void initialize() {
BooleanBinding isValidNewPassword = Bindings.createBooleanBinding(() -> password.get() != null && password.get().length() > 0, password);
readyToCreateVault.bind(isValidNewPassword.and(recoveryKeyChoice.selectedToggleProperty().isNotNull()).and(processing.not()));
readyToCreateVault.bind(newPasswordSceneController.passwordsMatchAndSufficientProperty().and(recoveryKeyChoice.selectedToggleProperty().isNotNull()).and(processing.not()));
window.setOnHiding(event -> {
newPasswordSceneController.passwordField.wipe();
newPasswordSceneController.reenterField.wipe();
});
}
@FXML
@@ -142,8 +143,8 @@ public class CreateNewVaultPasswordController implements FxController {
Path pathToVault = vaultPathProperty.get();
processing.set(true);
Tasks.create(() -> {
initializeVault(pathToVault, password.get());
return recoveryKeyFactory.createRecoveryKey(pathToVault, password.get());
initializeVault(pathToVault);
return recoveryKeyFactory.createRecoveryKey(pathToVault, newPasswordSceneController.passwordField.getCharacters());
}).onSuccess(recoveryKey -> {
initializationSucceeded(pathToVault);
recoveryKeyProperty.set(recoveryKey);
@@ -160,7 +161,7 @@ public class CreateNewVaultPasswordController implements FxController {
Path pathToVault = vaultPathProperty.get();
processing.set(true);
Tasks.create(() -> {
initializeVault(pathToVault, password.get());
initializeVault(pathToVault);
}).onSuccess(() -> {
initializationSucceeded(pathToVault);
window.setScene(successScene.get());
@@ -172,11 +173,11 @@ public class CreateNewVaultPasswordController implements FxController {
}).runOnce(executor);
}
private void initializeVault(Path path, CharSequence passphrase) throws IOException {
private void initializeVault(Path path) throws IOException {
// 1. write masterkey:
Path masterkeyFilePath = path.resolve(MASTERKEY_FILENAME);
try (Masterkey masterkey = Masterkey.generate(csprng)) {
masterkeyFileAccess.persist(masterkey, masterkeyFilePath, passphrase);
masterkeyFileAccess.persist(masterkey, masterkeyFilePath, newPasswordSceneController.passwordField.getCharacters());
// 2. initialize vault:
try {

View File

@@ -10,21 +10,18 @@ import org.cryptomator.integrations.keychain.KeychainAccessException;
import org.cryptomator.ui.common.Animations;
import org.cryptomator.ui.common.ErrorComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.NewPasswordController;
import org.cryptomator.ui.controls.NiceSecurePasswordField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.ObjectProperty;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.stage.Stage;
import java.io.IOException;
import java.nio.CharBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
@@ -41,7 +38,6 @@ public class ChangePasswordController implements FxController {
private final Stage window;
private final Vault vault;
private final ObjectProperty<CharSequence> newPassword;
private final ErrorComponent.Builder errorComponent;
private final KeychainManager keychain;
private final SecureRandom csprng;
@@ -50,12 +46,12 @@ public class ChangePasswordController implements FxController {
public NiceSecurePasswordField oldPasswordField;
public CheckBox finalConfirmationCheckbox;
public Button finishButton;
public NewPasswordController newPasswordController;
@Inject
public ChangePasswordController(@ChangePasswordWindow Stage window, @ChangePasswordWindow Vault vault, @Named("newPassword") ObjectProperty<CharSequence> newPassword, ErrorComponent.Builder errorComponent, KeychainManager keychain, SecureRandom csprng, MasterkeyFileAccess masterkeyFileAccess) {
public ChangePasswordController(@ChangePasswordWindow Stage window, @ChangePasswordWindow Vault vault, ErrorComponent.Builder errorComponent, KeychainManager keychain, SecureRandom csprng, MasterkeyFileAccess masterkeyFileAccess) {
this.window = window;
this.vault = vault;
this.newPassword = newPassword;
this.errorComponent = errorComponent;
this.keychain = keychain;
this.csprng = csprng;
@@ -66,8 +62,12 @@ public class ChangePasswordController implements FxController {
public void initialize() {
BooleanBinding checkboxNotConfirmed = finalConfirmationCheckbox.selectedProperty().not();
BooleanBinding oldPasswordFieldEmpty = oldPasswordField.textProperty().isEmpty();
BooleanBinding newPasswordInvalid = Bindings.createBooleanBinding(() -> newPassword.get() == null || newPassword.get().length() == 0, newPassword);
finishButton.disableProperty().bind(checkboxNotConfirmed.or(oldPasswordFieldEmpty).or(newPasswordInvalid));
finishButton.disableProperty().bind(checkboxNotConfirmed.or(oldPasswordFieldEmpty).or(newPasswordController.passwordsMatchAndSufficientProperty().not()));
window.setOnHiding(event -> {
oldPasswordField.wipe();
newPasswordController.passwordField.wipe();
newPasswordController.reenterField.wipe();
});
}
@FXML
@@ -78,10 +78,8 @@ public class ChangePasswordController implements FxController {
@FXML
public void finish() {
try {
//String normalizedOldPassphrase = Normalizer.normalize(oldPasswordField.getCharacters(), Normalizer.Form.NFC);
//String normalizedNewPassphrase = Normalizer.normalize(newPassword.get(), Normalizer.Form.NFC);
CharSequence oldPassphrase = oldPasswordField.getCharacters(); // TODO verify: is this already NFC-normalized?
CharSequence newPassphrase = newPassword.get(); // TODO verify: is this already NFC-normalized?
CharSequence oldPassphrase = oldPasswordField.getCharacters();
CharSequence newPassphrase = newPasswordController.passwordField.getCharacters();
Path masterkeyPath = vault.getPath().resolve(MASTERKEY_FILENAME);
byte[] oldMasterkeyBytes = Files.readAllBytes(masterkeyPath);
byte[] newMasterkeyBytes = masterkeyFileAccess.changePassphrase(oldMasterkeyBytes, oldPassphrase, newPassphrase);
@@ -89,8 +87,8 @@ public class ChangePasswordController implements FxController {
Files.move(masterkeyPath, backupKeyPath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
Files.write(masterkeyPath, newMasterkeyBytes, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
LOG.info("Successfully changed password for {}", vault.getDisplayName());
window.close();
updatePasswordInSystemkeychain();
window.close();
} catch (InvalidPassphraseException e) {
Animations.createShakeWindowAnimation(window).play();
oldPasswordField.selectAll();
@@ -104,7 +102,7 @@ public class ChangePasswordController implements FxController {
private void updatePasswordInSystemkeychain() {
if (keychain.isSupported()) {
try {
keychain.changePassphrase(vault.getId(), CharBuffer.wrap(newPassword.get()));
keychain.changePassphrase(vault.getId(), newPasswordController.passwordField.getCharacters());
LOG.info("Successfully updated password in system keychain for {}", vault.getDisplayName());
} catch (KeychainAccessException e) {
LOG.error("Failed to update password in system keychain.", e);

View File

@@ -5,10 +5,10 @@ import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.common.NewPasswordController;
import org.cryptomator.ui.common.PasswordStrengthUtil;
@@ -16,8 +16,6 @@ import org.cryptomator.ui.common.StageFactory;
import javax.inject.Named;
import javax.inject.Provider;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
@@ -27,13 +25,6 @@ import java.util.ResourceBundle;
@Module
abstract class ChangePasswordModule {
@Provides
@ChangePasswordScoped
@Named("newPassword")
static ObjectProperty<CharSequence> provideNewPasswordProperty() {
return new SimpleObjectProperty<>("");
}
@Provides
@ChangePasswordWindow
@ChangePasswordScoped
@@ -71,8 +62,8 @@ abstract class ChangePasswordModule {
@Provides
@IntoMap
@FxControllerKey(NewPasswordController.class)
static FxController provideNewPasswordController(ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater, @Named("newPassword") ObjectProperty<CharSequence> password) {
return new NewPasswordController(resourceBundle, strengthRater, password);
static FxController provideNewPasswordController(ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater) {
return new NewPasswordController(resourceBundle, strengthRater);
}
}

View File

@@ -8,7 +8,8 @@ import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
@@ -18,8 +19,8 @@ public class NewPasswordController implements FxController {
private final ResourceBundle resourceBundle;
private final PasswordStrengthUtil strengthRater;
private final ObjectProperty<CharSequence> password;
private final IntegerProperty passwordStrength = new SimpleIntegerProperty(-1);
private final ReadOnlyBooleanWrapper passwordsMatchAndSufficient = new ReadOnlyBooleanWrapper();
public NiceSecurePasswordField passwordField;
public NiceSecurePasswordField reenterField;
@@ -31,10 +32,9 @@ public class NewPasswordController implements FxController {
public FontAwesome5IconView passwordMatchCheckmark;
public FontAwesome5IconView passwordMatchCross;
public NewPasswordController(ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater, ObjectProperty<CharSequence> password) {
public NewPasswordController(ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater) {
this.resourceBundle = resourceBundle;
this.strengthRater = strengthRater;
this.password = password;
}
@FXML
@@ -44,7 +44,7 @@ public class NewPasswordController implements FxController {
passwordStrengthLabel.graphicProperty().bind(Bindings.createObjectBinding(this::getIconViewForPasswordStrengthLabel, passwordField.textProperty(), passwordStrength));
passwordStrengthLabel.textProperty().bind(EasyBind.map(passwordStrength, strengthRater::getStrengthDescription));
BooleanBinding passwordsMatch = Bindings.createBooleanBinding(this::hasSamePasswordInBothFields, passwordField.textProperty(), reenterField.textProperty());
BooleanBinding passwordsMatch = Bindings.createBooleanBinding(this::passwordFieldsMatch, passwordField.textProperty(), reenterField.textProperty());
BooleanBinding reenterFieldNotEmpty = reenterField.textProperty().isNotEmpty();
passwordMatchLabel.visibleProperty().bind(reenterFieldNotEmpty);
passwordMatchLabel.graphicProperty().bind(Bindings.when(passwordsMatch.and(reenterFieldNotEmpty)).then(passwordMatchCheckmark).otherwise(passwordMatchCross));
@@ -54,6 +54,7 @@ public class NewPasswordController implements FxController {
reenterField.textProperty().addListener(this::passwordsDidChange);
}
private FontAwesome5IconView getIconViewForPasswordStrengthLabel() {
if (passwordField.getCharacters().length() == 0) {
return null;
@@ -67,17 +68,19 @@ public class NewPasswordController implements FxController {
}
private void passwordsDidChange(@SuppressWarnings("unused") Observable observable) {
if (hasSamePasswordInBothFields() && strengthRater.fulfillsMinimumRequirements(passwordField.getCharacters())) {
password.set(passwordField.getCharacters());
} else {
password.set("");
if (passwordFieldsMatch() && strengthRater.fulfillsMinimumRequirements(passwordField.getCharacters())) {
passwordsMatchAndSufficient.setValue(true);
}
}
private boolean hasSamePasswordInBothFields() {
private boolean passwordFieldsMatch() {
return CharSequence.compare(passwordField.getCharacters(), reenterField.getCharacters()) == 0;
}
public ReadOnlyBooleanProperty passwordsMatchAndSufficientProperty() {
return passwordsMatchAndSufficient.getReadOnlyProperty();
}
/* Getter/Setter */
public IntegerProperty passwordStrengthProperty() {

View File

@@ -123,7 +123,7 @@ public class SecurePasswordField extends TextField {
}
private void updateCapsLocked() {
// AWT code needed until https://bugs.openjdk.java.net/browse/JDK-8090882 is closed:
//TODO: fixed in JavaFX 17. AWT code needed until update (see https://bugs.openjdk.java.net/browse/JDK-8259680)
capsLocked.set(isFocused() && Toolkit.getDefaultToolkit().getLockingKeyState(java.awt.event.KeyEvent.VK_CAPS_LOCK));
}

View File

@@ -6,10 +6,10 @@ import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.common.NewPasswordController;
import org.cryptomator.ui.common.PasswordStrengthUtil;
@@ -17,8 +17,6 @@ import org.cryptomator.ui.common.StageFactory;
import javax.inject.Named;
import javax.inject.Provider;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
@@ -56,14 +54,6 @@ abstract class RecoveryKeyModule {
return new SimpleStringProperty();
}
@Provides
@RecoveryKeyScoped
@Named("newPassword")
static ObjectProperty<CharSequence> provideNewPasswordProperty() {
return new SimpleObjectProperty<>("");
}
// ------------------
@Provides
@@ -126,8 +116,8 @@ abstract class RecoveryKeyModule {
@Provides
@IntoMap
@FxControllerKey(NewPasswordController.class)
static FxController provideNewPasswordController(ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater, @Named("newPassword") ObjectProperty<CharSequence> password) {
return new NewPasswordController(resourceBundle, strengthRater, password);
static FxController provideNewPasswordController(ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater) {
return new NewPasswordController(resourceBundle, strengthRater);
}
}

View File

@@ -6,14 +6,12 @@ import org.cryptomator.ui.common.ErrorComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.common.NewPasswordController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.StringProperty;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
@@ -32,21 +30,19 @@ public class RecoveryKeyResetPasswordController implements FxController {
private final RecoveryKeyFactory recoveryKeyFactory;
private final ExecutorService executor;
private final StringProperty recoveryKey;
private final ObjectProperty<CharSequence> newPassword;
private final Lazy<Scene> recoverScene;
private final BooleanBinding invalidNewPassword;
private final ErrorComponent.Builder errorComponent;
public NewPasswordController newPasswordController;
@Inject
public RecoveryKeyResetPasswordController(@RecoveryKeyWindow Stage window, @RecoveryKeyWindow Vault vault, RecoveryKeyFactory recoveryKeyFactory, ExecutorService executor, @RecoveryKeyWindow StringProperty recoveryKey, @Named("newPassword") ObjectProperty<CharSequence> newPassword, @FxmlScene(FxmlFile.RECOVERYKEY_RECOVER) Lazy<Scene> recoverScene, ErrorComponent.Builder errorComponent) {
public RecoveryKeyResetPasswordController(@RecoveryKeyWindow Stage window, @RecoveryKeyWindow Vault vault, RecoveryKeyFactory recoveryKeyFactory, ExecutorService executor, @RecoveryKeyWindow StringProperty recoveryKey, @FxmlScene(FxmlFile.RECOVERYKEY_RECOVER) Lazy<Scene> recoverScene, ErrorComponent.Builder errorComponent) {
this.window = window;
this.vault = vault;
this.recoveryKeyFactory = recoveryKeyFactory;
this.executor = executor;
this.recoveryKey = recoveryKey;
this.newPassword = newPassword;
this.recoverScene = recoverScene;
this.invalidNewPassword = Bindings.createBooleanBinding(this::isInvalidNewPassword, newPassword);
this.errorComponent = errorComponent;
}
@@ -81,7 +77,7 @@ public class RecoveryKeyResetPasswordController implements FxController {
@Override
protected Void call() throws IOException, IllegalArgumentException {
recoveryKeyFactory.resetPasswordWithRecoveryKey(vault.getPath(), recoveryKey.get(), newPassword.get());
recoveryKeyFactory.resetPasswordWithRecoveryKey(vault.getPath(), recoveryKey.get(), newPasswordController.passwordField.getCharacters());
return null;
}
@@ -89,11 +85,12 @@ public class RecoveryKeyResetPasswordController implements FxController {
/* Getter/Setter */
public BooleanBinding invalidNewPasswordProperty() {
return invalidNewPassword;
public ReadOnlyBooleanProperty validPasswordProperty() {
return newPasswordController.passwordsMatchAndSufficientProperty();
}
public boolean isInvalidNewPassword() {
return newPassword.get() == null || newPassword.get().length() == 0;
public boolean isValidPassword() {
return newPasswordController.passwordsMatchAndSufficientProperty().get();
}
}

View File

@@ -23,7 +23,7 @@
<Insets topRightBottomLeft="24"/>
</padding>
<children>
<fx:include source="/fxml/new_password.fxml"/>
<fx:include fx:id="newPasswordScene" source="/fxml/new_password.fxml"/>
<Region VBox.vgrow="ALWAYS"/>

View File

@@ -25,7 +25,7 @@
<Region prefHeight="12" VBox.vgrow="NEVER"/>
<fx:include source="/fxml/new_password.fxml"/>
<fx:include fx:id="newPassword" source="/fxml/new_password.fxml"/>
<CheckBox fx:id="finalConfirmationCheckbox" text="%changepassword.finalConfirmation" wrapText="true"/>

View File

@@ -17,7 +17,7 @@
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<fx:include source="/fxml/new_password.fxml"/>
<fx:include fx:id="newPassword" source="/fxml/new_password.fxml"/>
<Region VBox.vgrow="ALWAYS"/>
@@ -25,7 +25,7 @@
<ButtonBar buttonMinWidth="120" buttonOrder="B+I">
<buttons>
<Button text="%generic.button.back" ButtonBar.buttonData="BACK_PREVIOUS" cancelButton="true" onAction="#back"/>
<Button text="%generic.button.done" ButtonBar.buttonData="FINISH" defaultButton="true" onAction="#done" disable="${controller.invalidNewPassword}"/>
<Button text="%generic.button.done" ButtonBar.buttonData="FINISH" defaultButton="true" onAction="#done" disable="${!controller.validPassword}"/>
</buttons>
</ButtonBar>
</VBox>