From 268c66a108d86fcb04c1b0095b38c5d0d836ee2a Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 21 Feb 2023 23:05:47 +0100 Subject: [PATCH 01/31] add hub specific tab to vault options --- .../keyloading/hub/HubKeyLoadingStrategy.java | 4 ++-- .../ui/vaultoptions/HubOptionsController.java | 20 +++++++++++++++++++ .../vaultoptions/SelectedVaultOptionsTab.java | 5 +++++ .../vaultoptions/VaultOptionsController.java | 10 +++++++++- .../ui/vaultoptions/VaultOptionsModule.java | 5 +++++ src/main/resources/fxml/vault_options.fxml | 8 ++++++++ .../resources/fxml/vault_options_hub.fxml | 17 ++++++++++++++++ 7 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/cryptomator/ui/vaultoptions/HubOptionsController.java create mode 100644 src/main/resources/fxml/vault_options_hub.fxml diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingStrategy.java b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingStrategy.java index d1a3742ae..cc5edfcb4 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingStrategy.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingStrategy.java @@ -29,8 +29,8 @@ import java.util.concurrent.ExecutionException; public class HubKeyLoadingStrategy implements KeyLoadingStrategy { private static final String SCHEME_PREFIX = "hub+"; - static final String SCHEME_HUB_HTTP = SCHEME_PREFIX + "http"; - static final String SCHEME_HUB_HTTPS = SCHEME_PREFIX + "https"; + public static final String SCHEME_HUB_HTTP = SCHEME_PREFIX + "http"; + public static final String SCHEME_HUB_HTTPS = SCHEME_PREFIX + "https"; private final Stage window; private final KeychainManager keychainManager; diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/HubOptionsController.java b/src/main/java/org/cryptomator/ui/vaultoptions/HubOptionsController.java new file mode 100644 index 000000000..04863bfb5 --- /dev/null +++ b/src/main/java/org/cryptomator/ui/vaultoptions/HubOptionsController.java @@ -0,0 +1,20 @@ +package org.cryptomator.ui.vaultoptions; + +import org.cryptomator.common.vaults.Vault; +import org.cryptomator.ui.common.FxController; + +import javax.inject.Inject; +import javafx.stage.Stage; + +public class HubOptionsController implements FxController { + + private final Vault vault; + private final Stage window; + + + @Inject + public HubOptionsController(@VaultOptionsWindow Vault vault, @VaultOptionsWindow Stage window) { + this.vault = vault; + this.window = window; + } +} diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/SelectedVaultOptionsTab.java b/src/main/java/org/cryptomator/ui/vaultoptions/SelectedVaultOptionsTab.java index 3fc738fb0..f9470af96 100644 --- a/src/main/java/org/cryptomator/ui/vaultoptions/SelectedVaultOptionsTab.java +++ b/src/main/java/org/cryptomator/ui/vaultoptions/SelectedVaultOptionsTab.java @@ -21,4 +21,9 @@ public enum SelectedVaultOptionsTab { */ KEY, + /** + * Show hub tab + */ + HUB + } diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java index c0023acb8..3abc23e9e 100644 --- a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java +++ b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java @@ -2,6 +2,8 @@ package org.cryptomator.ui.vaultoptions; import org.cryptomator.common.vaults.Vault; import org.cryptomator.ui.common.FxController; +import org.cryptomator.ui.keyloading.hub.HubKeyLoadingStrategy; +import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,6 +27,7 @@ public class VaultOptionsController implements FxController { public Tab generalTab; public Tab mountTab; public Tab keyTab; + public Tab hubTab; @Inject VaultOptionsController(@VaultOptionsWindow Stage window, @VaultOptionsWindow Vault vault, ObjectProperty selectedTabProperty) { @@ -38,9 +41,13 @@ public class VaultOptionsController implements FxController { window.setOnShowing(this::windowWillAppear); selectedTabProperty.addListener(observable -> this.selectChosenTab()); tabPane.getSelectionModel().selectedItemProperty().addListener(observable -> this.selectedTabChanged()); - if(!vault.getVaultConfigCache().getUnchecked().getKeyId().getScheme().equals("masterkeyfile")){ + var vaultScheme = vault.getVaultConfigCache().getUnchecked().getKeyId().getScheme(); + if(!vaultScheme.equals(MasterkeyFileLoadingStrategy.SCHEME)){ tabPane.getTabs().remove(keyTab); } + if(!(vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS))){ + tabPane.getTabs().remove(hubTab); + } } private void selectChosenTab() { @@ -53,6 +60,7 @@ public class VaultOptionsController implements FxController { case ANY, GENERAL -> generalTab; case MOUNT -> mountTab; case KEY -> keyTab; + case HUB -> hubTab; }; } diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java index a9014cc54..50df38e71 100644 --- a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java +++ b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java @@ -84,4 +84,9 @@ abstract class VaultOptionsModule { @IntoMap @FxControllerKey(MasterkeyOptionsController.class) abstract FxController bindMasterkeyOptionsController(MasterkeyOptionsController controller); + + @Binds + @IntoMap + @FxControllerKey(HubOptionsController.class) + abstract FxController bindHubOptionsController(HubOptionsController controller); } diff --git a/src/main/resources/fxml/vault_options.fxml b/src/main/resources/fxml/vault_options.fxml index 6ecc2af9b..46babe41c 100644 --- a/src/main/resources/fxml/vault_options.fxml +++ b/src/main/resources/fxml/vault_options.fxml @@ -36,5 +36,13 @@ + + + + + + + + diff --git a/src/main/resources/fxml/vault_options_hub.fxml b/src/main/resources/fxml/vault_options_hub.fxml new file mode 100644 index 000000000..c5ff8e53c --- /dev/null +++ b/src/main/resources/fxml/vault_options_hub.fxml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + From 5db5346c88dd25173cad96a5a280540c0a1161bf Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 23 Feb 2023 12:53:29 +0100 Subject: [PATCH 02/31] refactor error component to own package --- .../cryptomator/ui/{common => error}/ErrorComponent.java | 4 +++- .../cryptomator/ui/{common => error}/ErrorController.java | 3 ++- .../org/cryptomator/ui/{common => error}/ErrorModule.java | 8 +++++++- .../org/cryptomator/ui/fxapp/FxApplicationModule.java | 8 +------- .../org/cryptomator/ui/fxapp/FxApplicationWindows.java | 2 +- .../org/cryptomator/ui/mainwindow/MainWindowModule.java | 2 +- src/main/resources/fxml/error.fxml | 2 +- 7 files changed, 16 insertions(+), 13 deletions(-) rename src/main/java/org/cryptomator/ui/{common => error}/ErrorComponent.java (83%) rename src/main/java/org/cryptomator/ui/{common => error}/ErrorController.java (98%) rename src/main/java/org/cryptomator/ui/{common => error}/ErrorModule.java (81%) diff --git a/src/main/java/org/cryptomator/ui/common/ErrorComponent.java b/src/main/java/org/cryptomator/ui/error/ErrorComponent.java similarity index 83% rename from src/main/java/org/cryptomator/ui/common/ErrorComponent.java rename to src/main/java/org/cryptomator/ui/error/ErrorComponent.java index 8cb430584..554aa65f1 100644 --- a/src/main/java/org/cryptomator/ui/common/ErrorComponent.java +++ b/src/main/java/org/cryptomator/ui/error/ErrorComponent.java @@ -1,8 +1,10 @@ -package org.cryptomator.ui.common; +package org.cryptomator.ui.error; import dagger.BindsInstance; import dagger.Subcomponent; import org.cryptomator.common.Nullable; +import org.cryptomator.ui.common.FxmlFile; +import org.cryptomator.ui.common.FxmlScene; import javafx.scene.Scene; import javafx.stage.Stage; diff --git a/src/main/java/org/cryptomator/ui/common/ErrorController.java b/src/main/java/org/cryptomator/ui/error/ErrorController.java similarity index 98% rename from src/main/java/org/cryptomator/ui/common/ErrorController.java rename to src/main/java/org/cryptomator/ui/error/ErrorController.java index 15d2ee41f..422a44157 100644 --- a/src/main/java/org/cryptomator/ui/common/ErrorController.java +++ b/src/main/java/org/cryptomator/ui/error/ErrorController.java @@ -1,8 +1,9 @@ -package org.cryptomator.ui.common; +package org.cryptomator.ui.error; import org.cryptomator.common.Environment; import org.cryptomator.common.ErrorCode; import org.cryptomator.common.Nullable; +import org.cryptomator.ui.common.FxController; import javax.inject.Inject; import javax.inject.Named; diff --git a/src/main/java/org/cryptomator/ui/common/ErrorModule.java b/src/main/java/org/cryptomator/ui/error/ErrorModule.java similarity index 81% rename from src/main/java/org/cryptomator/ui/common/ErrorModule.java rename to src/main/java/org/cryptomator/ui/error/ErrorModule.java index 01b8790c1..d9ac6eab9 100644 --- a/src/main/java/org/cryptomator/ui/common/ErrorModule.java +++ b/src/main/java/org/cryptomator/ui/error/ErrorModule.java @@ -1,10 +1,16 @@ -package org.cryptomator.ui.common; +package org.cryptomator.ui.error; import dagger.Binds; import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoMap; import org.cryptomator.common.ErrorCode; +import org.cryptomator.ui.common.DefaultSceneFactory; +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 javax.inject.Named; import javax.inject.Provider; diff --git a/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java b/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java index cdeb764be..877675b9c 100644 --- a/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java +++ b/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java @@ -7,9 +7,7 @@ package org.cryptomator.ui.fxapp; import dagger.Module; import dagger.Provides; -import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.ui.common.ErrorComponent; -import org.cryptomator.ui.common.StageFactory; +import org.cryptomator.ui.error.ErrorComponent; import org.cryptomator.ui.lock.LockComponent; import org.cryptomator.ui.mainwindow.MainWindowComponent; import org.cryptomator.ui.preferences.PreferencesComponent; @@ -18,13 +16,9 @@ import org.cryptomator.ui.quit.QuitComponent; import org.cryptomator.ui.traymenu.TrayMenuComponent; import org.cryptomator.ui.unlock.UnlockComponent; -import javax.inject.Named; import javafx.scene.image.Image; import java.io.IOException; import java.io.InputStream; -import java.io.UncheckedIOException; -import java.util.Collections; -import java.util.List; @Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, MainWindowComponent.class, PreferencesComponent.class, UnlockComponent.class, LockComponent.class, QuitComponent.class, ErrorComponent.class}) abstract class FxApplicationModule { diff --git a/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java b/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java index 5d38a9017..2b4f8e7bc 100644 --- a/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java +++ b/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java @@ -5,7 +5,7 @@ import dagger.Lazy; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultState; import org.cryptomator.integrations.tray.TrayIntegrationProvider; -import org.cryptomator.ui.common.ErrorComponent; +import org.cryptomator.ui.error.ErrorComponent; import org.cryptomator.ui.lock.LockComponent; import org.cryptomator.ui.mainwindow.MainWindowComponent; import org.cryptomator.ui.preferences.PreferencesComponent; diff --git a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java index 94acba3cc..6fbb8e16e 100644 --- a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java +++ b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java @@ -6,7 +6,7 @@ import dagger.Provides; import dagger.multibindings.IntoMap; import org.cryptomator.common.vaults.Vault; import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent; -import org.cryptomator.ui.common.ErrorComponent; +import org.cryptomator.ui.error.ErrorComponent; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxControllerKey; import org.cryptomator.ui.common.FxmlFile; diff --git a/src/main/resources/fxml/error.fxml b/src/main/resources/fxml/error.fxml index 1bb8a5ae2..ca0966a0a 100644 --- a/src/main/resources/fxml/error.fxml +++ b/src/main/resources/fxml/error.fxml @@ -15,7 +15,7 @@ Date: Thu, 23 Feb 2023 12:55:30 +0100 Subject: [PATCH 03/31] rename forgetPassword package --- .../ForgetPasswordComponent.java | 2 +- .../ForgetPasswordController.java | 2 +- .../ForgetPasswordModule.java | 2 +- .../ForgetPasswordScoped.java | 2 +- .../ForgetPasswordWindow.java | 2 +- .../ui/keyloading/masterkeyfile/MasterkeyFileLoadingModule.java | 2 +- .../ui/keyloading/masterkeyfile/PassphraseEntryController.java | 2 +- .../cryptomator/ui/vaultoptions/MasterkeyOptionsController.java | 2 +- .../org/cryptomator/ui/vaultoptions/VaultOptionsModule.java | 2 +- src/main/resources/fxml/forget_password.fxml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) rename src/main/java/org/cryptomator/ui/{forgetPassword => forgetpassword}/ForgetPasswordComponent.java (96%) rename src/main/java/org/cryptomator/ui/{forgetPassword => forgetpassword}/ForgetPasswordController.java (97%) rename src/main/java/org/cryptomator/ui/{forgetPassword => forgetpassword}/ForgetPasswordModule.java (98%) rename src/main/java/org/cryptomator/ui/{forgetPassword => forgetpassword}/ForgetPasswordScoped.java (85%) rename src/main/java/org/cryptomator/ui/{forgetPassword => forgetpassword}/ForgetPasswordWindow.java (85%) diff --git a/src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordComponent.java b/src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordComponent.java similarity index 96% rename from src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordComponent.java rename to src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordComponent.java index e7300bb79..347065b85 100644 --- a/src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordComponent.java +++ b/src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordComponent.java @@ -1,4 +1,4 @@ -package org.cryptomator.ui.forgetPassword; +package org.cryptomator.ui.forgetpassword; import dagger.BindsInstance; import dagger.Lazy; diff --git a/src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordController.java b/src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordController.java similarity index 97% rename from src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordController.java rename to src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordController.java index 8cd43ae22..f8a4fc4dd 100644 --- a/src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordController.java +++ b/src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordController.java @@ -1,4 +1,4 @@ -package org.cryptomator.ui.forgetPassword; +package org.cryptomator.ui.forgetpassword; import org.cryptomator.common.keychain.KeychainManager; import org.cryptomator.common.vaults.Vault; diff --git a/src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordModule.java b/src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordModule.java similarity index 98% rename from src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordModule.java rename to src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordModule.java index b0c34e9f5..1a06678cb 100644 --- a/src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordModule.java +++ b/src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordModule.java @@ -1,4 +1,4 @@ -package org.cryptomator.ui.forgetPassword; +package org.cryptomator.ui.forgetpassword; import dagger.Binds; import dagger.Module; diff --git a/src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordScoped.java b/src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordScoped.java similarity index 85% rename from src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordScoped.java rename to src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordScoped.java index 5be483753..bc0bd738e 100644 --- a/src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordScoped.java +++ b/src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordScoped.java @@ -1,4 +1,4 @@ -package org.cryptomator.ui.forgetPassword; +package org.cryptomator.ui.forgetpassword; import javax.inject.Scope; import java.lang.annotation.Documented; diff --git a/src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordWindow.java b/src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordWindow.java similarity index 85% rename from src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordWindow.java rename to src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordWindow.java index 285119e0a..e9162f45d 100644 --- a/src/main/java/org/cryptomator/ui/forgetPassword/ForgetPasswordWindow.java +++ b/src/main/java/org/cryptomator/ui/forgetpassword/ForgetPasswordWindow.java @@ -1,4 +1,4 @@ -package org.cryptomator.ui.forgetPassword; +package org.cryptomator.ui.forgetpassword; import javax.inject.Qualifier; import java.lang.annotation.Documented; diff --git a/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingModule.java b/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingModule.java index 9375b0cff..5e4d148cb 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingModule.java +++ b/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingModule.java @@ -8,7 +8,7 @@ import dagger.multibindings.StringKey; import org.cryptomator.common.keychain.KeychainManager; import org.cryptomator.common.vaults.Vault; import org.cryptomator.integrations.keychain.KeychainAccessException; -import org.cryptomator.ui.forgetPassword.ForgetPasswordComponent; +import org.cryptomator.ui.forgetpassword.ForgetPasswordComponent; import org.cryptomator.ui.keyloading.KeyLoading; import org.cryptomator.ui.keyloading.KeyLoadingScoped; import org.cryptomator.ui.keyloading.KeyLoadingStrategy; diff --git a/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/PassphraseEntryController.java b/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/PassphraseEntryController.java index baadb9a12..6d52362b3 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/PassphraseEntryController.java +++ b/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/PassphraseEntryController.java @@ -7,7 +7,7 @@ import org.cryptomator.common.vaults.Vault; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.WeakBindings; import org.cryptomator.ui.controls.NiceSecurePasswordField; -import org.cryptomator.ui.forgetPassword.ForgetPasswordComponent; +import org.cryptomator.ui.forgetpassword.ForgetPasswordComponent; import org.cryptomator.ui.keyloading.KeyLoading; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/MasterkeyOptionsController.java b/src/main/java/org/cryptomator/ui/vaultoptions/MasterkeyOptionsController.java index 4978335c7..85566ed1f 100644 --- a/src/main/java/org/cryptomator/ui/vaultoptions/MasterkeyOptionsController.java +++ b/src/main/java/org/cryptomator/ui/vaultoptions/MasterkeyOptionsController.java @@ -4,7 +4,7 @@ import org.cryptomator.common.keychain.KeychainManager; import org.cryptomator.common.vaults.Vault; import org.cryptomator.ui.changepassword.ChangePasswordComponent; import org.cryptomator.ui.common.FxController; -import org.cryptomator.ui.forgetPassword.ForgetPasswordComponent; +import org.cryptomator.ui.forgetpassword.ForgetPasswordComponent; import org.cryptomator.ui.recoverykey.RecoveryKeyComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java index a9014cc54..e22635dd3 100644 --- a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java +++ b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java @@ -13,7 +13,7 @@ import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlLoaderFactory; import org.cryptomator.ui.common.FxmlScene; import org.cryptomator.ui.common.StageFactory; -import org.cryptomator.ui.forgetPassword.ForgetPasswordComponent; +import org.cryptomator.ui.forgetpassword.ForgetPasswordComponent; import org.cryptomator.ui.fxapp.PrimaryStage; import org.cryptomator.ui.recoverykey.RecoveryKeyComponent; diff --git a/src/main/resources/fxml/forget_password.fxml b/src/main/resources/fxml/forget_password.fxml index b040754c1..213731a30 100644 --- a/src/main/resources/fxml/forget_password.fxml +++ b/src/main/resources/fxml/forget_password.fxml @@ -13,7 +13,7 @@ Date: Thu, 23 Feb 2023 13:00:51 +0100 Subject: [PATCH 04/31] move new password files to changepassword package --- .../cryptomator/ui/addvaultwizard/AddVaultModule.java | 4 ++-- .../addvaultwizard/CreateNewVaultPasswordController.java | 2 +- .../ui/changepassword/ChangePasswordController.java | 1 - .../ui/changepassword/ChangePasswordModule.java | 2 -- .../NewPasswordController.java | 3 ++- .../{common => changepassword}/PasswordStrengthUtil.java | 2 +- .../ui/keyloading/hub/HubKeyLoadingModule.java | 9 --------- .../cryptomator/ui/recoverykey/RecoveryKeyModule.java | 4 ++-- .../recoverykey/RecoveryKeyResetPasswordController.java | 2 +- src/main/resources/fxml/new_password.fxml | 2 +- .../PasswordStrengthUtilTest.java | 4 ++-- 11 files changed, 12 insertions(+), 23 deletions(-) rename src/main/java/org/cryptomator/ui/{common => changepassword}/NewPasswordController.java (97%) rename src/main/java/org/cryptomator/ui/{common => changepassword}/PasswordStrengthUtil.java (98%) rename src/test/java/org/cryptomator/ui/{common => changepassword}/PasswordStrengthUtilTest.java (91%) diff --git a/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java b/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java index c6acbadf6..02327aaf4 100644 --- a/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java +++ b/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java @@ -11,8 +11,8 @@ 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; +import org.cryptomator.ui.changepassword.NewPasswordController; +import org.cryptomator.ui.changepassword.PasswordStrengthUtil; import org.cryptomator.ui.common.StageFactory; import org.cryptomator.ui.fxapp.PrimaryStage; import org.cryptomator.ui.recoverykey.RecoveryKeyDisplayController; diff --git a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java index 0148686f3..0cd1814d4 100644 --- a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java +++ b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java @@ -13,7 +13,7 @@ import org.cryptomator.cryptolib.common.MasterkeyFileAccess; 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.changepassword.NewPasswordController; import org.cryptomator.ui.common.Tasks; import org.cryptomator.ui.fxapp.FxApplicationWindows; import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy; diff --git a/src/main/java/org/cryptomator/ui/changepassword/ChangePasswordController.java b/src/main/java/org/cryptomator/ui/changepassword/ChangePasswordController.java index 200a70328..4d9666785 100644 --- a/src/main/java/org/cryptomator/ui/changepassword/ChangePasswordController.java +++ b/src/main/java/org/cryptomator/ui/changepassword/ChangePasswordController.java @@ -9,7 +9,6 @@ import org.cryptomator.cryptolib.common.MasterkeyFileAccess; import org.cryptomator.integrations.keychain.KeychainAccessException; import org.cryptomator.ui.common.Animations; import org.cryptomator.ui.common.FxController; -import org.cryptomator.ui.common.NewPasswordController; import org.cryptomator.ui.controls.NiceSecurePasswordField; import org.cryptomator.ui.fxapp.FxApplicationWindows; import org.slf4j.Logger; diff --git a/src/main/java/org/cryptomator/ui/changepassword/ChangePasswordModule.java b/src/main/java/org/cryptomator/ui/changepassword/ChangePasswordModule.java index d95b19410..947f87aeb 100644 --- a/src/main/java/org/cryptomator/ui/changepassword/ChangePasswordModule.java +++ b/src/main/java/org/cryptomator/ui/changepassword/ChangePasswordModule.java @@ -10,8 +10,6 @@ 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; import org.cryptomator.ui.common.StageFactory; import javax.inject.Named; diff --git a/src/main/java/org/cryptomator/ui/common/NewPasswordController.java b/src/main/java/org/cryptomator/ui/changepassword/NewPasswordController.java similarity index 97% rename from src/main/java/org/cryptomator/ui/common/NewPasswordController.java rename to src/main/java/org/cryptomator/ui/changepassword/NewPasswordController.java index 6f029efe1..36b469f49 100644 --- a/src/main/java/org/cryptomator/ui/common/NewPasswordController.java +++ b/src/main/java/org/cryptomator/ui/changepassword/NewPasswordController.java @@ -1,5 +1,6 @@ -package org.cryptomator.ui.common; +package org.cryptomator.ui.changepassword; +import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.controls.FontAwesome5IconView; import org.cryptomator.ui.controls.NiceSecurePasswordField; diff --git a/src/main/java/org/cryptomator/ui/common/PasswordStrengthUtil.java b/src/main/java/org/cryptomator/ui/changepassword/PasswordStrengthUtil.java similarity index 98% rename from src/main/java/org/cryptomator/ui/common/PasswordStrengthUtil.java rename to src/main/java/org/cryptomator/ui/changepassword/PasswordStrengthUtil.java index 0224118cd..202e2f9cb 100644 --- a/src/main/java/org/cryptomator/ui/common/PasswordStrengthUtil.java +++ b/src/main/java/org/cryptomator/ui/changepassword/PasswordStrengthUtil.java @@ -6,7 +6,7 @@ * Contributors: * Jean-Noël Charon - initial API and implementation *******************************************************************************/ -package org.cryptomator.ui.common; +package org.cryptomator.ui.changepassword; import com.nulabinc.zxcvbn.Zxcvbn; import org.cryptomator.common.Environment; diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java index 6f63ee98e..7b8aae875 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java @@ -15,8 +15,6 @@ 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; import org.cryptomator.ui.keyloading.KeyLoading; import org.cryptomator.ui.keyloading.KeyLoadingScoped; import org.cryptomator.ui.keyloading.KeyLoadingStrategy; @@ -153,13 +151,6 @@ public abstract class HubKeyLoadingModule { @FxControllerKey(AuthFlowController.class) abstract FxController bindAuthFlowController(AuthFlowController controller); - @Provides - @IntoMap - @FxControllerKey(NewPasswordController.class) - static FxController provideNewPasswordController(ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater) { - return new NewPasswordController(resourceBundle, strengthRater); - } - @Binds @IntoMap @FxControllerKey(InvalidLicenseController.class) diff --git a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyModule.java b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyModule.java index a5a0b7ec8..397a80f54 100644 --- a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyModule.java +++ b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyModule.java @@ -13,8 +13,8 @@ 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; +import org.cryptomator.ui.changepassword.NewPasswordController; +import org.cryptomator.ui.changepassword.PasswordStrengthUtil; import org.cryptomator.ui.common.StageFactory; import javax.inject.Named; diff --git a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyResetPasswordController.java b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyResetPasswordController.java index 69e1373e1..147893426 100644 --- a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyResetPasswordController.java +++ b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyResetPasswordController.java @@ -5,7 +5,7 @@ import org.cryptomator.common.vaults.Vault; 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.changepassword.NewPasswordController; import org.cryptomator.ui.fxapp.FxApplicationWindows; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/resources/fxml/new_password.fxml b/src/main/resources/fxml/new_password.fxml index 942fea0d0..0d8e36cd6 100644 --- a/src/main/resources/fxml/new_password.fxml +++ b/src/main/resources/fxml/new_password.fxml @@ -8,7 +8,7 @@ diff --git a/src/test/java/org/cryptomator/ui/common/PasswordStrengthUtilTest.java b/src/test/java/org/cryptomator/ui/changepassword/PasswordStrengthUtilTest.java similarity index 91% rename from src/test/java/org/cryptomator/ui/common/PasswordStrengthUtilTest.java rename to src/test/java/org/cryptomator/ui/changepassword/PasswordStrengthUtilTest.java index fe3ba8846..3996bfab2 100644 --- a/src/test/java/org/cryptomator/ui/common/PasswordStrengthUtilTest.java +++ b/src/test/java/org/cryptomator/ui/changepassword/PasswordStrengthUtilTest.java @@ -1,9 +1,9 @@ -package org.cryptomator.ui.common; +package org.cryptomator.ui.changepassword; import com.google.common.base.Strings; import org.cryptomator.common.Environment; +import org.cryptomator.ui.changepassword.PasswordStrengthUtil; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.mockito.Mockito; From 3cf1b829b8ac262d02e5ec11a545ac5d714a5fc6 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 20 Mar 2023 21:40:16 +0100 Subject: [PATCH 05/31] make recovery key ui validation reusable --- .../ui/recoverykey/RecoveryKeyModule.java | 7 + .../RecoveryKeyRecoverController.java | 154 +-------------- .../RecoveryKeyValidateController.java | 180 ++++++++++++++++++ .../resources/fxml/recoverykey_recover.fxml | 34 +--- .../resources/fxml/recoverykey_validate.fxml | 49 +++++ src/main/resources/i18n/strings.properties | 2 +- 6 files changed, 245 insertions(+), 181 deletions(-) create mode 100644 src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyValidateController.java create mode 100644 src/main/resources/fxml/recoverykey_validate.fxml diff --git a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyModule.java b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyModule.java index 397a80f54..06095eebc 100644 --- a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyModule.java +++ b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyModule.java @@ -140,6 +140,13 @@ abstract class RecoveryKeyModule { @FxControllerKey(RecoveryKeyResetPasswordSuccessController.class) abstract FxController bindRecoveryKeyResetPasswordSuccessController(RecoveryKeyResetPasswordSuccessController controller); + @Provides + @IntoMap + @FxControllerKey(RecoveryKeyValidateController.class) + static FxController bindRecoveryKeyValidateController(@RecoveryKeyWindow Vault vault, @RecoveryKeyWindow @Nullable VaultConfig.UnverifiedVaultConfig vaultConfig, @RecoveryKeyWindow StringProperty recoveryKey, RecoveryKeyFactory recoveryKeyFactory) { + return new RecoveryKeyValidateController(vault, vaultConfig, recoveryKey, recoveryKeyFactory); + } + @Provides @IntoMap @FxControllerKey(NewPasswordController.class) diff --git a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyRecoverController.java b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyRecoverController.java index 9082d7311..944c52043 100644 --- a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyRecoverController.java +++ b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyRecoverController.java @@ -1,14 +1,9 @@ package org.cryptomator.ui.recoverykey; -import com.google.common.base.CharMatcher; -import com.google.common.base.Strings; import dagger.Lazy; import org.cryptomator.common.Nullable; -import org.cryptomator.common.ObservableUtil; import org.cryptomator.common.vaults.Vault; import org.cryptomator.cryptofs.VaultConfig; -import org.cryptomator.cryptofs.VaultConfigLoadException; -import org.cryptomator.cryptofs.VaultKeyInvalidException; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; @@ -16,96 +11,34 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.Observable; import javafx.beans.property.StringProperty; import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; import javafx.scene.Scene; -import javafx.scene.control.TextArea; -import javafx.scene.control.TextFormatter; -import javafx.scene.input.KeyCode; -import javafx.scene.input.KeyEvent; import javafx.stage.Stage; -import java.util.Optional; import java.util.ResourceBundle; @RecoveryKeyScoped public class RecoveryKeyRecoverController implements FxController { private static final Logger LOG = LoggerFactory.getLogger(RecoveryKeyCreationController.class); - private static final CharMatcher ALLOWED_CHARS = CharMatcher.inRange('a', 'z').or(CharMatcher.is(' ')); private final Stage window; - private final Vault vault; - private final VaultConfig.UnverifiedVaultConfig unverifiedVaultConfig; - private final StringProperty recoveryKey; - private final ObservableValue recoveryKeyCorrect; - private final ObservableValue recoveryKeyWrong; - private final ObservableValue recoveryKeyInvalid; - private final RecoveryKeyFactory recoveryKeyFactory; - private final ObjectProperty recoveryKeyState; private final Lazy resetPasswordScene; - private final AutoCompleter autoCompleter; - private volatile boolean isWrongKey; - - public TextArea textarea; + @FXML + RecoveryKeyValidateController recoveryKeyValidateController; @Inject - public RecoveryKeyRecoverController(@RecoveryKeyWindow Stage window, @RecoveryKeyWindow Vault vault, @RecoveryKeyWindow @Nullable VaultConfig.UnverifiedVaultConfig unverifiedVaultConfig, @RecoveryKeyWindow StringProperty recoveryKey, RecoveryKeyFactory recoveryKeyFactory, @FxmlScene(FxmlFile.RECOVERYKEY_RESET_PASSWORD) Lazy resetPasswordScene, ResourceBundle resourceBundle) { + public RecoveryKeyRecoverController(@RecoveryKeyWindow Stage window, @RecoveryKeyWindow Vault vault, @RecoveryKeyWindow StringProperty recoveryKey, @FxmlScene(FxmlFile.RECOVERYKEY_RESET_PASSWORD) Lazy resetPasswordScene, ResourceBundle resourceBundle) { this.window = window; window.setTitle(resourceBundle.getString("recoveryKey.recover.title")); - this.vault = vault; - this.unverifiedVaultConfig = unverifiedVaultConfig; - this.recoveryKey = recoveryKey; - this.recoveryKeyFactory = recoveryKeyFactory; this.resetPasswordScene = resetPasswordScene; - this.autoCompleter = new AutoCompleter(recoveryKeyFactory.getDictionary()); - this.recoveryKeyState = new SimpleObjectProperty<>(); - this.recoveryKeyCorrect = ObservableUtil.mapWithDefault(recoveryKeyState, RecoveryKeyState.CORRECT::equals, false); - this.recoveryKeyWrong = ObservableUtil.mapWithDefault(recoveryKeyState, RecoveryKeyState.WRONG::equals, false); - this.recoveryKeyInvalid = ObservableUtil.mapWithDefault(recoveryKeyState, RecoveryKeyState.INVALID::equals, false); } @FXML public void initialize() { - recoveryKey.bind(textarea.textProperty()); - textarea.textProperty().addListener(((observable, oldValue, newValue) -> validateRecoveryKey())); - } - - private TextFormatter.Change filterTextChange(TextFormatter.Change change) { - if (Strings.isNullOrEmpty(change.getText())) { - // pass-through caret/selection changes that don't affect the text - return change; - } - if (!ALLOWED_CHARS.matchesAllOf(change.getText())) { - return null; // reject change - } - - String text = change.getControlNewText(); - int caretPos = change.getCaretPosition(); - if (caretPos == text.length() || text.charAt(caretPos) == ' ') { // are we at the end of a word? - int beginOfWord = Math.max(text.substring(0, caretPos).lastIndexOf(' ') + 1, 0); - String currentWord = text.substring(beginOfWord, caretPos); - Optional suggestion = autoCompleter.autocomplete(currentWord); - if (suggestion.isPresent()) { - String completion = suggestion.get().substring(currentWord.length()); - change.setText(change.getText() + completion); - change.setAnchor(caretPos + completion.length()); - } - } - return change; - } - - @FXML - public void onKeyPressed(KeyEvent keyEvent) { - if (keyEvent.getCode() == KeyCode.TAB && textarea.getAnchor() > textarea.getCaretPosition()) { - // apply autocompletion: - int pos = textarea.getAnchor(); - textarea.insertText(pos, " "); - textarea.positionCaret(pos + 1); - } } @FXML @@ -118,85 +51,10 @@ public class RecoveryKeyRecoverController implements FxController { window.setScene(resetPasswordScene.get()); } - /** - * Checks, if vault config is signed with the given key. - * - * @param key byte array of possible signing key - * @return true, if vault config is signed with this key - */ - private boolean checkKeyAgainstVaultConfig(byte[] key) { - try { - var config = unverifiedVaultConfig.verify(key, unverifiedVaultConfig.allegedVaultVersion()); - LOG.info("Provided recovery key matches vault config signature for vault {}", config.getId()); - return true; - } catch (VaultKeyInvalidException e) { - LOG.debug("Provided recovery key does not match vault config signature."); - isWrongKey = true; - return false; - } catch (VaultConfigLoadException e) { - LOG.error("Failed to parse vault config", e); - return false; - } - } - - private void validateRecoveryKey() { - isWrongKey = false; - var valid = recoveryKeyFactory.validateRecoveryKey(recoveryKey.get(), unverifiedVaultConfig != null ? this::checkKeyAgainstVaultConfig : null); - if (valid) { - recoveryKeyState.set(RecoveryKeyState.CORRECT); - } else if (isWrongKey) { //set via side effect in checkKeyAgainstVaultConfig() - recoveryKeyState.set(RecoveryKeyState.WRONG); - } else { - recoveryKeyState.set(RecoveryKeyState.INVALID); - } - } - /* Getter/Setter */ - public Vault getVault() { - return vault; + public RecoveryKeyValidateController getValidateController() { + return recoveryKeyValidateController; } - public TextFormatter getRecoveryKeyTextFormatter() { - return new TextFormatter<>(this::filterTextChange); - } - - public ObservableValue recoveryKeyInvalidProperty() { - return recoveryKeyInvalid; - } - - public boolean isRecoveryKeyInvalid() { - return recoveryKeyInvalid.getValue(); - } - - public ObservableValue recoveryKeyCorrectProperty() { - return recoveryKeyCorrect; - } - - public boolean isRecoveryKeyCorrect() { - return recoveryKeyCorrect.getValue(); - } - - public ObservableValue recoveryKeyWrongProperty() { - return recoveryKeyWrong; - } - - public boolean isRecoveryKeyWrong() { - return recoveryKeyWrong.getValue(); - } - - private enum RecoveryKeyState { - /** - * Recovery key is a valid key and belongs to this vault - */ - CORRECT, - /** - * Recovery key is a valid key, but does not belong to this vault - */ - WRONG, - /** - * Recovery key is not a valid key. - */ - INVALID; - } } diff --git a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyValidateController.java b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyValidateController.java new file mode 100644 index 000000000..4a8224ffe --- /dev/null +++ b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyValidateController.java @@ -0,0 +1,180 @@ +package org.cryptomator.ui.recoverykey; + + +import com.google.common.base.CharMatcher; +import com.google.common.base.Strings; +import org.cryptomator.common.Nullable; +import org.cryptomator.common.ObservableUtil; +import org.cryptomator.common.vaults.Vault; +import org.cryptomator.cryptofs.VaultConfig; +import org.cryptomator.cryptofs.VaultConfigLoadException; +import org.cryptomator.cryptofs.VaultKeyInvalidException; +import org.cryptomator.ui.common.FxController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.StringProperty; +import javafx.beans.value.ObservableValue; +import javafx.fxml.FXML; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextFormatter; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; + +public class RecoveryKeyValidateController implements FxController { + + private static final Logger LOG = LoggerFactory.getLogger(RecoveryKeyCreationController.class); + private static final CharMatcher ALLOWED_CHARS = CharMatcher.inRange('a', 'z').or(CharMatcher.is(' ')); + + private final Vault vault; + private final VaultConfig.UnverifiedVaultConfig unverifiedVaultConfig; + private final StringProperty recoveryKey; + private final ObservableValue recoveryKeyCorrect; + private final ObservableValue recoveryKeyWrong; + private final ObservableValue recoveryKeyInvalid; + private final RecoveryKeyFactory recoveryKeyFactory; + private final ObjectProperty recoveryKeyState; + private final AutoCompleter autoCompleter; + + private volatile boolean isWrongKey; + + public TextArea textarea; + + public RecoveryKeyValidateController(Vault vault, @Nullable VaultConfig.UnverifiedVaultConfig vaultConfig, StringProperty recoveryKey, RecoveryKeyFactory recoveryKeyFactory) { + this.vault = vault; + this.unverifiedVaultConfig = vaultConfig; + this.recoveryKey = recoveryKey; + this.recoveryKeyFactory = recoveryKeyFactory; + this.autoCompleter = new AutoCompleter(recoveryKeyFactory.getDictionary()); + this.recoveryKeyState = new SimpleObjectProperty<>(); + this.recoveryKeyCorrect = ObservableUtil.mapWithDefault(recoveryKeyState, RecoveryKeyState.CORRECT::equals, false); + this.recoveryKeyWrong = ObservableUtil.mapWithDefault(recoveryKeyState, RecoveryKeyState.WRONG::equals, false); + this.recoveryKeyInvalid = ObservableUtil.mapWithDefault(recoveryKeyState, RecoveryKeyState.INVALID::equals, false); + } + + @FXML + public void initialize() { + recoveryKey.bind(textarea.textProperty()); + textarea.textProperty().addListener(((observable, oldValue, newValue) -> validateRecoveryKey())); + } + + private TextFormatter.Change filterTextChange(TextFormatter.Change change) { + if (Strings.isNullOrEmpty(change.getText())) { + // pass-through caret/selection changes that don't affect the text + return change; + } + if (!ALLOWED_CHARS.matchesAllOf(change.getText())) { + return null; // reject change + } + + String text = change.getControlNewText(); + int caretPos = change.getCaretPosition(); + if (caretPos == text.length() || text.charAt(caretPos) == ' ') { // are we at the end of a word? + int beginOfWord = Math.max(text.substring(0, caretPos).lastIndexOf(' ') + 1, 0); + String currentWord = text.substring(beginOfWord, caretPos); + var suggestion = autoCompleter.autocomplete(currentWord); + if (suggestion.isPresent()) { + String completion = suggestion.get().substring(currentWord.length()); + change.setText(change.getText() + completion); + change.setAnchor(caretPos + completion.length()); + } + } + return change; + } + + @FXML + public void onKeyPressed(KeyEvent keyEvent) { + if (keyEvent.getCode() == KeyCode.TAB && textarea.getAnchor() > textarea.getCaretPosition()) { + // apply autocompletion: + int pos = textarea.getAnchor(); + textarea.insertText(pos, " "); + textarea.positionCaret(pos + 1); + } + } + + /** + * Checks, if vault config is signed with the given key. + * + * @param key byte array of possible signing key + * @return true, if vault config is signed with this key + */ + private boolean checkKeyAgainstVaultConfig(byte[] key) { + assert unverifiedVaultConfig != null; + try { + var config = unverifiedVaultConfig.verify(key, unverifiedVaultConfig.allegedVaultVersion()); + LOG.info("Provided recovery key matches vault config signature for vault {}", config.getId()); + return true; + } catch (VaultKeyInvalidException e) { + LOG.debug("Provided recovery key does not match vault config signature."); + isWrongKey = true; + return false; + } catch (VaultConfigLoadException e) { + LOG.error("Failed to parse vault config", e); + return false; + } + } + + private void validateRecoveryKey() { + isWrongKey = false; + var valid = recoveryKeyFactory.validateRecoveryKey(recoveryKey.get(), unverifiedVaultConfig != null ? this::checkKeyAgainstVaultConfig : null); + if (valid) { + recoveryKeyState.set(RecoveryKeyState.CORRECT); + } else if (isWrongKey) { //set via side effect in checkKeyAgainstVaultConfig() + recoveryKeyState.set(RecoveryKeyState.WRONG); + } else { + recoveryKeyState.set(RecoveryKeyState.INVALID); + } + } + + /* Getter/Setter */ + + public Vault getVault() { + return vault; + } + + public TextFormatter getRecoveryKeyTextFormatter() { + return new TextFormatter<>(this::filterTextChange); + } + + public ObservableValue recoveryKeyInvalidProperty() { + return recoveryKeyInvalid; + } + + public boolean isRecoveryKeyInvalid() { + return recoveryKeyInvalid.getValue(); + } + + public ObservableValue recoveryKeyCorrectProperty() { + return recoveryKeyCorrect; + } + + public boolean isRecoveryKeyCorrect() { + return recoveryKeyCorrect.getValue(); + } + + public ObservableValue recoveryKeyWrongProperty() { + return recoveryKeyWrong; + } + + public boolean isRecoveryKeyWrong() { + return recoveryKeyWrong.getValue(); + } + + private enum RecoveryKeyState { + /** + * Recovery key is a valid key and belongs to this vault + */ + CORRECT, + /** + * Recovery key is a valid key, but does not belong to this vault + */ + WRONG, + /** + * Recovery key is not a valid key. + */ + INVALID; + } + +} diff --git a/src/main/resources/fxml/recoverykey_recover.fxml b/src/main/resources/fxml/recoverykey_recover.fxml index e35905825..4c85f9356 100644 --- a/src/main/resources/fxml/recoverykey_recover.fxml +++ b/src/main/resources/fxml/recoverykey_recover.fxml @@ -1,16 +1,10 @@ - - - - - - - -