diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoading.java b/main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoading.java similarity index 72% rename from main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoading.java rename to main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoading.java index 2d7a8a921..51f9302c8 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoading.java +++ b/main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoading.java @@ -1,4 +1,4 @@ -package org.cryptomator.ui.unlock.masterkeyfile; +package org.cryptomator.ui.keyloading; import javax.inject.Qualifier; import java.lang.annotation.Documented; @@ -9,6 +9,6 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; @Qualifier @Documented @Retention(RUNTIME) -@interface MasterkeyFileLoading { +public @interface KeyLoading { } diff --git a/main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingComponent.java b/main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingComponent.java new file mode 100644 index 000000000..fc274d2a7 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingComponent.java @@ -0,0 +1,28 @@ +package org.cryptomator.ui.keyloading; + +import dagger.BindsInstance; +import dagger.Subcomponent; +import org.cryptomator.common.vaults.Vault; + +import javafx.stage.Stage; + +@KeyLoadingScoped +@Subcomponent(modules = {KeyLoadingModule.class}) +public interface KeyLoadingComponent { + + @KeyLoading + KeyLoadingStrategy keyloadingStrategy(); + + @Subcomponent.Builder + interface Builder { + + @BindsInstance + Builder vault(@KeyLoading Vault vault); + + @BindsInstance + Builder window(@KeyLoading Stage window); + + KeyLoadingComponent build(); + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingModule.java b/main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingModule.java new file mode 100644 index 000000000..77f91f0e4 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingModule.java @@ -0,0 +1,59 @@ +package org.cryptomator.ui.keyloading; + +import dagger.Binds; +import dagger.Module; +import dagger.Provides; +import dagger.multibindings.IntoMap; +import dagger.multibindings.StringKey; +import org.cryptomator.common.vaults.Vault; +import org.cryptomator.cryptofs.VaultConfig.UnverifiedVaultConfig; +import org.cryptomator.ui.common.DefaultSceneFactory; +import org.cryptomator.ui.common.FxController; +import org.cryptomator.ui.common.FxControllerKey; +import org.cryptomator.ui.common.FxmlLoaderFactory; +import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingModule; +import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy; +import org.cryptomator.ui.migration.MigrationStartController; + +import javax.inject.Provider; +import java.net.URI; +import java.util.Map; +import java.util.Optional; +import java.util.ResourceBundle; + +@Module(includes = {MasterkeyFileLoadingModule.class}) +abstract class KeyLoadingModule { + + @Provides + @KeyLoading + @KeyLoadingScoped + static FxmlLoaderFactory provideFxmlLoaderFactory(Map, Provider> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) { + return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle); + } + + @Provides + @KeyLoading + @KeyLoadingScoped + static Optional provideKeyId(@KeyLoading Vault vault) { + return vault.getUnverifiedVaultConfig().map(UnverifiedVaultConfig::getKeyId); + } + + @Provides + @KeyLoading + @KeyLoadingScoped + static KeyLoadingStrategy provideKeyLoaderProvider(@KeyLoading Optional keyId, Map strategies) { + if (keyId.isEmpty()) { + return KeyLoadingStrategy.failed(new IllegalArgumentException("No key id provided")); + } else { + String scheme = keyId.get().getScheme(); + var fallback = KeyLoadingStrategy.failed(new IllegalArgumentException("Unsupported key id " + scheme)); + return strategies.getOrDefault(scheme, fallback); + } + } + + @Binds + @IntoMap + @StringKey("masterkeyfile") + abstract KeyLoadingStrategy bindMasterkeyFileLoadingStrategy(MasterkeyFileLoadingStrategy strategy); + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingScoped.java b/main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingScoped.java similarity index 70% rename from main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingScoped.java rename to main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingScoped.java index 1eeac1e84..5f4355f96 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingScoped.java +++ b/main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingScoped.java @@ -1,4 +1,4 @@ -package org.cryptomator.ui.unlock.masterkeyfile; +package org.cryptomator.ui.keyloading; import javax.inject.Scope; import java.lang.annotation.Documented; @@ -8,6 +8,6 @@ import java.lang.annotation.RetentionPolicy; @Scope @Documented @Retention(RetentionPolicy.RUNTIME) -@interface MasterkeyFileLoadingScoped { +public @interface KeyLoadingScoped { } diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/KeyLoadingComponent.java b/main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java similarity index 65% rename from main/ui/src/main/java/org/cryptomator/ui/unlock/KeyLoadingComponent.java rename to main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java index ec7e8d89b..80f65b6bc 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/KeyLoadingComponent.java +++ b/main/ui/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java @@ -1,10 +1,9 @@ -package org.cryptomator.ui.unlock; +package org.cryptomator.ui.keyloading; import org.cryptomator.cryptolib.api.MasterkeyLoader; import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException; -@FunctionalInterface -public interface KeyLoadingComponent { +public interface KeyLoadingStrategy { /** * @return A reusable masterkey loader, preconfigured with the vault of the current unlock process @@ -32,9 +31,19 @@ public interface KeyLoadingComponent { // no-op } - static KeyLoadingComponent exceptional(Exception exception) { + /** + * A key loading strategy that will always fail by throwing a {@link MasterkeyLoadingFailedException}. + * + * @param exception The cause of the failure. If not alreay an {@link MasterkeyLoadingFailedException}, it will get wrapped. + * @return A new KeyLoadingStrategy that will always fail with an {@link MasterkeyLoadingFailedException}. + */ + static KeyLoadingStrategy failed(Exception exception) { return () -> { - throw new MasterkeyLoadingFailedException("Can not load key", exception); + if (exception instanceof MasterkeyLoadingFailedException e) { + throw e; + } else { + throw new MasterkeyLoadingFailedException("Can not load key", exception); + } }; } diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingContext.java b/main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingContext.java similarity index 74% rename from main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingContext.java rename to main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingContext.java index 298ba1d09..d5cd9c47e 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingContext.java +++ b/main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingContext.java @@ -1,4 +1,4 @@ -package org.cryptomator.ui.unlock.masterkeyfile; +package org.cryptomator.ui.keyloading.masterkeyfile; import dagger.Lazy; import org.cryptomator.cryptolib.api.InvalidPassphraseException; @@ -8,9 +8,9 @@ import org.cryptomator.ui.common.Animations; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; import org.cryptomator.ui.common.UserInteractionLock; +import org.cryptomator.ui.keyloading.KeyLoading; +import org.cryptomator.ui.keyloading.KeyLoadingScoped; import org.cryptomator.ui.unlock.UnlockCancelledException; -import org.cryptomator.ui.unlock.masterkeyfile.MasterkeyFileLoadingModule.MasterkeyFileProvision; -import org.cryptomator.ui.unlock.masterkeyfile.MasterkeyFileLoadingModule.PasswordEntry; import javax.inject.Inject; import javafx.application.Platform; @@ -21,21 +21,21 @@ import java.nio.CharBuffer; import java.nio.file.Path; import java.util.concurrent.atomic.AtomicReference; -@MasterkeyFileLoadingScoped +@KeyLoadingScoped public class MasterkeyFileLoadingContext implements MasterkeyFileLoaderContext { private final Stage window; private final Lazy passphraseEntryScene; private final Lazy selectMasterkeyFileScene; - private final UserInteractionLock passwordEntryLock; - private final UserInteractionLock masterkeyFileProvisionLock; + private final UserInteractionLock passwordEntryLock; + private final UserInteractionLock masterkeyFileProvisionLock; private final AtomicReference password; private final AtomicReference filePath; private boolean wrongPassword; @Inject - public MasterkeyFileLoadingContext(@MasterkeyFileLoading Stage window, @FxmlScene(FxmlFile.UNLOCK_ENTER_PASSWORD) Lazy passphraseEntryScene, @FxmlScene(FxmlFile.UNLOCK_SELECT_MASTERKEYFILE) Lazy selectMasterkeyFileScene, UserInteractionLock passwordEntryLock, UserInteractionLock masterkeyFileProvisionLock, AtomicReference password, AtomicReference filePath) { + public MasterkeyFileLoadingContext(@KeyLoading Stage window, @FxmlScene(FxmlFile.UNLOCK_ENTER_PASSWORD) Lazy passphraseEntryScene, @FxmlScene(FxmlFile.UNLOCK_SELECT_MASTERKEYFILE) Lazy selectMasterkeyFileScene, UserInteractionLock passwordEntryLock, UserInteractionLock masterkeyFileProvisionLock, AtomicReference password, AtomicReference filePath) { this.window = window; this.passphraseEntryScene = passphraseEntryScene; this.selectMasterkeyFileScene = selectMasterkeyFileScene; @@ -53,7 +53,7 @@ public class MasterkeyFileLoadingContext implements MasterkeyFileLoaderContext { assert filePath.get() == null; try { - if (askForCorrectMasterkeyFile() == MasterkeyFileProvision.MASTERKEYFILE_PROVIDED) { + if (askForCorrectMasterkeyFile() == MasterkeyFileLoadingModule.MasterkeyFileProvision.MASTERKEYFILE_PROVIDED) { return filePath.get(); } else { throw new UnlockCancelledException("Choosing masterkey file cancelled."); @@ -64,7 +64,7 @@ public class MasterkeyFileLoadingContext implements MasterkeyFileLoaderContext { } } - private MasterkeyFileProvision askForCorrectMasterkeyFile() throws InterruptedException { + private MasterkeyFileLoadingModule.MasterkeyFileProvision askForCorrectMasterkeyFile() throws InterruptedException { Platform.runLater(() -> { window.setScene(selectMasterkeyFileScene.get()); window.show(); @@ -87,7 +87,7 @@ public class MasterkeyFileLoadingContext implements MasterkeyFileLoaderContext { assert password.get() == null; try { - if (askForPassphrase() == PasswordEntry.PASSWORD_ENTERED) { + if (askForPassphrase() == MasterkeyFileLoadingModule.PasswordEntry.PASSWORD_ENTERED) { assert password.get() != null; return CharBuffer.wrap(password.get()); } else { @@ -99,7 +99,7 @@ public class MasterkeyFileLoadingContext implements MasterkeyFileLoaderContext { } } - private PasswordEntry askForPassphrase() throws InterruptedException { + private MasterkeyFileLoadingModule.PasswordEntry askForPassphrase() throws InterruptedException { Platform.runLater(() -> { window.setScene(passphraseEntryScene.get()); window.show(); diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingFinisher.java b/main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingFinisher.java similarity index 80% rename from main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingFinisher.java rename to main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingFinisher.java index 8a16d3a12..726ca8f97 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingFinisher.java +++ b/main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingFinisher.java @@ -1,8 +1,10 @@ -package org.cryptomator.ui.unlock.masterkeyfile; +package org.cryptomator.ui.keyloading.masterkeyfile; import org.cryptomator.common.keychain.KeychainManager; import org.cryptomator.common.vaults.Vault; import org.cryptomator.integrations.keychain.KeychainAccessException; +import org.cryptomator.ui.keyloading.KeyLoading; +import org.cryptomator.ui.keyloading.KeyLoadingScoped; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,7 +16,7 @@ import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -@MasterkeyFileLoadingScoped +@KeyLoadingScoped public class MasterkeyFileLoadingFinisher { private static final Logger LOG = LoggerFactory.getLogger(MasterkeyFileLoadingFinisher.class); @@ -26,7 +28,7 @@ public class MasterkeyFileLoadingFinisher { private final KeychainManager keychain; @Inject - MasterkeyFileLoadingFinisher(@MasterkeyFileLoading Vault vault, @Named("savedPassword") Optional storedPassword, AtomicReference enteredPassword, @Named("savePassword")AtomicBoolean shouldSavePassword, KeychainManager keychain) { + MasterkeyFileLoadingFinisher(@KeyLoading Vault vault, @Named("savedPassword") Optional storedPassword, AtomicReference enteredPassword, @Named("savePassword") AtomicBoolean shouldSavePassword, KeychainManager keychain) { this.vault = vault; this.storedPassword = storedPassword; this.enteredPassword = enteredPassword; diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingModule.java b/main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingModule.java similarity index 76% rename from main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingModule.java rename to main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingModule.java index 9c3530357..87d6a38a3 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingModule.java @@ -1,4 +1,4 @@ -package org.cryptomator.ui.unlock.masterkeyfile; +package org.cryptomator.ui.keyloading.masterkeyfile; import dagger.Binds; import dagger.Module; @@ -17,6 +17,8 @@ import org.cryptomator.ui.common.FxmlLoaderFactory; import org.cryptomator.ui.common.FxmlScene; import org.cryptomator.ui.common.UserInteractionLock; import org.cryptomator.ui.forgetPassword.ForgetPasswordComponent; +import org.cryptomator.ui.keyloading.KeyLoading; +import org.cryptomator.ui.keyloading.KeyLoadingScoped; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,7 +33,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @Module(subcomponents = {ForgetPasswordComponent.class}) -abstract class MasterkeyFileLoadingModule { +public abstract class MasterkeyFileLoadingModule { private static final Logger LOG = LoggerFactory.getLogger(MasterkeyFileLoadingModule.class); @@ -46,27 +48,27 @@ abstract class MasterkeyFileLoadingModule { } @Provides - @MasterkeyFileLoadingScoped - static MasterkeyFileLoader provideMasterkeyFileLoader(MasterkeyFileAccess masterkeyFileAccess, @MasterkeyFileLoading Vault vault, MasterkeyFileLoadingContext context) { + @KeyLoadingScoped + static MasterkeyFileLoader provideMasterkeyFileLoader(MasterkeyFileAccess masterkeyFileAccess, @KeyLoading Vault vault, MasterkeyFileLoadingContext context) { return masterkeyFileAccess.keyLoader(vault.getPath(), context); } @Provides - @MasterkeyFileLoadingScoped + @KeyLoadingScoped static UserInteractionLock providePasswordEntryLock() { return new UserInteractionLock<>(null); } @Provides - @MasterkeyFileLoadingScoped + @KeyLoadingScoped static UserInteractionLock provideMasterkeyFileProvisionLock() { return new UserInteractionLock<>(null); } @Provides @Named("savedPassword") - @MasterkeyFileLoadingScoped - static Optional provideStoredPassword(KeychainManager keychain, @MasterkeyFileLoading Vault vault) { + @KeyLoadingScoped + static Optional provideStoredPassword(KeychainManager keychain, @KeyLoading Vault vault) { if (!keychain.isSupported()) { return Optional.empty(); } else { @@ -80,42 +82,35 @@ abstract class MasterkeyFileLoadingModule { } @Provides - @MasterkeyFileLoadingScoped + @KeyLoadingScoped static AtomicReference provideUserProvidedMasterkeyPath() { return new AtomicReference<>(); } @Provides - @MasterkeyFileLoadingScoped + @KeyLoadingScoped static AtomicReference providePassword(@Named("savedPassword") Optional storedPassword) { return new AtomicReference<>(storedPassword.orElse(null)); } @Provides @Named("savePassword") - @MasterkeyFileLoadingScoped + @KeyLoadingScoped static AtomicBoolean provideSavePasswordFlag(@Named("savedPassword") Optional storedPassword) { return new AtomicBoolean(storedPassword.isPresent()); } - @Provides - @MasterkeyFileLoading - @MasterkeyFileLoadingScoped - static FxmlLoaderFactory provideFxmlLoaderFactory(Map, Provider> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) { - return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle); - } - @Provides @FxmlScene(FxmlFile.UNLOCK_ENTER_PASSWORD) - @MasterkeyFileLoadingScoped - static Scene provideUnlockScene(@MasterkeyFileLoading FxmlLoaderFactory fxmlLoaders) { + @KeyLoadingScoped + static Scene provideUnlockScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) { return fxmlLoaders.createScene(FxmlFile.UNLOCK_ENTER_PASSWORD); } @Provides @FxmlScene(FxmlFile.UNLOCK_SELECT_MASTERKEYFILE) - @MasterkeyFileLoadingScoped - static Scene provideUnlockSelectMasterkeyFileScene(@MasterkeyFileLoading FxmlLoaderFactory fxmlLoaders) { + @KeyLoadingScoped + static Scene provideUnlockSelectMasterkeyFileScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) { return fxmlLoaders.createScene(FxmlFile.UNLOCK_SELECT_MASTERKEYFILE); } @@ -129,5 +124,4 @@ abstract class MasterkeyFileLoadingModule { @FxControllerKey(SelectMasterkeyFileController.class) abstract FxController bindUnlockSelectMasterkeyFileController(SelectMasterkeyFileController controller); - } diff --git a/main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingStrategy.java b/main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingStrategy.java new file mode 100644 index 000000000..9d03d2094 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/MasterkeyFileLoadingStrategy.java @@ -0,0 +1,38 @@ +package org.cryptomator.ui.keyloading.masterkeyfile; + +import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException; +import org.cryptomator.cryptolib.common.MasterkeyFileLoader; +import org.cryptomator.ui.keyloading.KeyLoading; +import org.cryptomator.ui.keyloading.KeyLoadingStrategy; + +import javax.inject.Inject; + +@KeyLoading +public class MasterkeyFileLoadingStrategy implements KeyLoadingStrategy { + + private final MasterkeyFileLoader masterkeyFileLoader; + private final MasterkeyFileLoadingContext context; + private final MasterkeyFileLoadingFinisher finisher; + + @Inject + public MasterkeyFileLoadingStrategy(MasterkeyFileLoader masterkeyFileLoader, MasterkeyFileLoadingContext context, MasterkeyFileLoadingFinisher finisher){ + this.masterkeyFileLoader = masterkeyFileLoader; + this.context = context; + this.finisher = finisher; + } + + @Override + public MasterkeyFileLoader masterkeyLoader() { + return masterkeyFileLoader; + } + + @Override + public boolean recoverFromException(MasterkeyLoadingFailedException exception) { + return context.recoverFromException(exception); + } + + @Override + public void cleanup(boolean unlockedSuccessfully) { + finisher.cleanup(unlockedSuccessfully); + } +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/PassphraseEntryController.java b/main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/PassphraseEntryController.java similarity index 92% rename from main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/PassphraseEntryController.java rename to main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/PassphraseEntryController.java index 914a2a91b..d4356be85 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/PassphraseEntryController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/PassphraseEntryController.java @@ -1,4 +1,4 @@ -package org.cryptomator.ui.unlock.masterkeyfile; +package org.cryptomator.ui.keyloading.masterkeyfile; import org.cryptomator.common.keychain.KeychainManager; import org.cryptomator.common.vaults.Vault; @@ -7,7 +7,9 @@ import org.cryptomator.ui.common.UserInteractionLock; import org.cryptomator.ui.common.WeakBindings; import org.cryptomator.ui.controls.NiceSecurePasswordField; import org.cryptomator.ui.forgetPassword.ForgetPasswordComponent; -import org.cryptomator.ui.unlock.masterkeyfile.MasterkeyFileLoadingModule.PasswordEntry; +import org.cryptomator.ui.keyloading.KeyLoading; +import org.cryptomator.ui.keyloading.KeyLoadingScoped; +import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingModule.PasswordEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,7 +41,7 @@ import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -@MasterkeyFileLoadingScoped +@KeyLoadingScoped public class PassphraseEntryController implements FxController { private static final Logger LOG = LoggerFactory.getLogger(PassphraseEntryController.class); @@ -67,7 +69,7 @@ public class PassphraseEntryController implements FxController { public Animation unlockAnimation; @Inject - public PassphraseEntryController(@MasterkeyFileLoading Stage window, @MasterkeyFileLoading Vault vault, AtomicReference password, @Named("savePassword") AtomicBoolean savePassword, @Named("savedPassword") Optional savedPassword, UserInteractionLock passwordEntryLock, ForgetPasswordComponent.Builder forgetPassword, KeychainManager keychain) { + public PassphraseEntryController(@KeyLoading Stage window, @KeyLoading Vault vault, AtomicReference password, @Named("savePassword") AtomicBoolean savePassword, @Named("savedPassword") Optional savedPassword, UserInteractionLock passwordEntryLock, ForgetPasswordComponent.Builder forgetPassword, KeychainManager keychain) { this.window = window; this.vault = vault; this.password = password; diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/SelectMasterkeyFileController.java b/main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/SelectMasterkeyFileController.java similarity index 80% rename from main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/SelectMasterkeyFileController.java rename to main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/SelectMasterkeyFileController.java index 62ad5764f..39be2b36e 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/SelectMasterkeyFileController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/SelectMasterkeyFileController.java @@ -1,8 +1,10 @@ -package org.cryptomator.ui.unlock.masterkeyfile; +package org.cryptomator.ui.keyloading.masterkeyfile; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.UserInteractionLock; -import org.cryptomator.ui.unlock.masterkeyfile.MasterkeyFileLoadingModule.MasterkeyFileProvision; +import org.cryptomator.ui.keyloading.KeyLoading; +import org.cryptomator.ui.keyloading.KeyLoadingScoped; +import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingModule.MasterkeyFileProvision; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,7 +18,7 @@ import java.nio.file.Path; import java.util.ResourceBundle; import java.util.concurrent.atomic.AtomicReference; -@MasterkeyFileLoadingScoped +@KeyLoadingScoped public class SelectMasterkeyFileController implements FxController { private static final Logger LOG = LoggerFactory.getLogger(SelectMasterkeyFileController.class); @@ -27,7 +29,7 @@ public class SelectMasterkeyFileController implements FxController { private final ResourceBundle resourceBundle; @Inject - public SelectMasterkeyFileController(@MasterkeyFileLoading Stage window, AtomicReference masterkeyPath, UserInteractionLock masterkeyFileProvisionLock, ResourceBundle resourceBundle) { + public SelectMasterkeyFileController(@KeyLoading Stage window, AtomicReference masterkeyPath, UserInteractionLock masterkeyFileProvisionLock, ResourceBundle resourceBundle) { this.window = window; this.masterkeyPath = masterkeyPath; this.masterkeyFileProvisionLock = masterkeyFileProvisionLock; diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/KeyLoadingModule.java b/main/ui/src/main/java/org/cryptomator/ui/unlock/KeyLoadingModule.java deleted file mode 100644 index 98bd478d0..000000000 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/KeyLoadingModule.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.cryptomator.ui.unlock; - -import dagger.Module; -import dagger.Provides; -import dagger.multibindings.IntoMap; -import dagger.multibindings.StringKey; -import org.cryptomator.common.vaults.Vault; -import org.cryptomator.cryptofs.VaultConfig.UnverifiedVaultConfig; -import org.cryptomator.ui.unlock.masterkeyfile.MasterkeyFileLoadingComponent; - -import javafx.stage.Stage; -import java.net.URI; -import java.util.Map; -import java.util.Optional; - -@Module(subcomponents = {MasterkeyFileLoadingComponent.class}) -abstract class KeyLoadingModule { - - @Provides - @UnlockScoped - static Optional provideKeyId(@UnlockWindow Vault vault) { - return vault.getUnverifiedVaultConfig().map(UnverifiedVaultConfig::getKeyId); - } - - @Provides - @UnlockScoped - static KeyLoadingComponent provideKeyLoaderProvider(Optional keyId, Map keyLoaderProviders) { - if (keyId.isEmpty()) { - return KeyLoadingComponent.exceptional(new IllegalArgumentException("No key id provided")); - } else { - String scheme = keyId.get().getScheme(); - return keyLoaderProviders.getOrDefault(scheme, KeyLoadingComponent.exceptional(new IllegalArgumentException("Unsupported key id " + scheme))); - } - } - - @Provides - @IntoMap - @StringKey("masterkeyfile") - static KeyLoadingComponent provideMasterkeyFileLoadingComponet(MasterkeyFileLoadingComponent.Builder compBuilder, @UnlockWindow Stage window, @UnlockWindow Vault vault) { - return compBuilder.unlockWindow(window).vault(vault).build(); - } - -} diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockComponent.java b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockComponent.java index fee0e74a5..9c0338c5b 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockComponent.java +++ b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockComponent.java @@ -16,7 +16,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; @UnlockScoped -@Subcomponent(modules = {UnlockModule.class, KeyLoadingModule.class}) +@Subcomponent(modules = {UnlockModule.class}) public interface UnlockComponent { ExecutorService defaultExecutorService(); diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockModule.java b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockModule.java index f7e25dd4f..3c1267e65 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockModule.java @@ -12,6 +12,8 @@ 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.keyloading.KeyLoadingComponent; +import org.cryptomator.ui.keyloading.KeyLoadingStrategy; import javax.inject.Named; import javax.inject.Provider; @@ -22,7 +24,7 @@ import java.util.Map; import java.util.Optional; import java.util.ResourceBundle; -@Module +@Module(subcomponents = {KeyLoadingComponent.class}) abstract class UnlockModule { @Provides @@ -48,6 +50,13 @@ abstract class UnlockModule { return stage; } + @Provides + @UnlockWindow + @UnlockScoped + static KeyLoadingStrategy provideKeyLoadingStrategy(KeyLoadingComponent.Builder compBuilder, @UnlockWindow Vault vault, @UnlockWindow Stage window) { + return compBuilder.vault(vault).window(window).build().keyloadingStrategy(); + } + @Provides @FxmlScene(FxmlFile.UNLOCK_SUCCESS) @UnlockScoped diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java index aab68b536..06b42155e 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java +++ b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java @@ -12,6 +12,8 @@ import org.cryptomator.ui.common.ErrorComponent; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; import org.cryptomator.ui.common.VaultService; +import org.cryptomator.ui.keyloading.KeyLoadingComponent; +import org.cryptomator.ui.keyloading.KeyLoadingStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,17 +43,17 @@ public class UnlockWorkflow extends Task { private final Lazy successScene; private final Lazy invalidMountPointScene; private final ErrorComponent.Builder errorComponent; - private final KeyLoadingComponent keyLoadingComp; + private final KeyLoadingStrategy keyLoadingStrategy; @Inject - UnlockWorkflow(@UnlockWindow Stage window, @UnlockWindow Vault vault, VaultService vaultService, @FxmlScene(FxmlFile.UNLOCK_SUCCESS) Lazy successScene, @FxmlScene(FxmlFile.UNLOCK_INVALID_MOUNT_POINT) Lazy invalidMountPointScene, ErrorComponent.Builder errorComponent, KeyLoadingComponent keyLoadingComp) { + UnlockWorkflow(@UnlockWindow Stage window, @UnlockWindow Vault vault, VaultService vaultService, @FxmlScene(FxmlFile.UNLOCK_SUCCESS) Lazy successScene, @FxmlScene(FxmlFile.UNLOCK_INVALID_MOUNT_POINT) Lazy invalidMountPointScene, ErrorComponent.Builder errorComponent, @UnlockWindow KeyLoadingStrategy keyLoadingStrategy) { this.window = window; this.vault = vault; this.vaultService = vaultService; this.successScene = successScene; this.invalidMountPointScene = invalidMountPointScene; this.errorComponent = errorComponent; - this.keyLoadingComp = keyLoadingComp; + this.keyLoadingStrategy = keyLoadingStrategy; setOnFailed(event -> { Throwable throwable = event.getSource().getException(); @@ -78,17 +80,17 @@ public class UnlockWorkflow extends Task { private void attemptUnlock() throws IOException, VolumeException, InvalidMountPointException, CryptoException { boolean success = false; try { - vault.unlock(keyLoadingComp.masterkeyLoader()); + vault.unlock(keyLoadingStrategy.masterkeyLoader()); success = true; } catch (MasterkeyLoadingFailedException e) { - if (keyLoadingComp.recoverFromException(e)) { + if (keyLoadingStrategy.recoverFromException(e)) { LOG.info("Unlock attempt threw {}. Reattempting...", e.getClass().getSimpleName()); attemptUnlock(); } else { throw e; } } finally { - keyLoadingComp.cleanup(success); + keyLoadingStrategy.cleanup(success); } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingComponent.java b/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingComponent.java deleted file mode 100644 index ab3252e28..000000000 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/masterkeyfile/MasterkeyFileLoadingComponent.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.cryptomator.ui.unlock.masterkeyfile; - -import dagger.BindsInstance; -import dagger.Subcomponent; -import org.cryptomator.common.vaults.Vault; -import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException; -import org.cryptomator.cryptolib.common.MasterkeyFileLoader; -import org.cryptomator.ui.unlock.KeyLoadingComponent; - -import javafx.stage.Stage; - -@MasterkeyFileLoadingScoped -@Subcomponent(modules = {MasterkeyFileLoadingModule.class}) -public interface MasterkeyFileLoadingComponent extends KeyLoadingComponent { - - MasterkeyFileLoadingFinisher finisher(); - - MasterkeyFileLoadingContext context(); - - @Override - MasterkeyFileLoader masterkeyLoader(); - - @Override - default boolean recoverFromException(MasterkeyLoadingFailedException exception) { - return context().recoverFromException(exception); - } - - @Override - default void cleanup(boolean unlockedSuccessfully) { - finisher().cleanup(unlockedSuccessfully); - } - - @Subcomponent.Builder - interface Builder { - - @BindsInstance - Builder vault(@MasterkeyFileLoading Vault vault); - - @BindsInstance - Builder unlockWindow(@MasterkeyFileLoading Stage unlockWindow); - - MasterkeyFileLoadingComponent build(); - } - -} diff --git a/main/ui/src/main/resources/fxml/unlock_enter_password.fxml b/main/ui/src/main/resources/fxml/unlock_enter_password.fxml index ff9cc675d..5fb55dd01 100644 --- a/main/ui/src/main/resources/fxml/unlock_enter_password.fxml +++ b/main/ui/src/main/resources/fxml/unlock_enter_password.fxml @@ -14,7 +14,7 @@