From 8ba2540b35b1e981f2f231a468564565b4b02693 Mon Sep 17 00:00:00 2001 From: Jan-Peter Klein Date: Mon, 11 Sep 2023 14:23:31 +0200 Subject: [PATCH 001/131] implemented volume type selection in 'vault options mount' --- .../vaultoptions/MountOptionsController.java | 126 ++++++++++++++++-- .../resources/fxml/vault_options_mount.fxml | 29 +++- 2 files changed, 140 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java b/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java index 5eeab43e0..4e97e7fd5 100644 --- a/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java +++ b/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java @@ -1,18 +1,26 @@ package org.cryptomator.ui.vaultoptions; import com.google.common.base.Strings; +import dagger.Lazy; +import org.cryptomator.common.ObservableUtil; import org.cryptomator.common.mount.ActualMountService; +import org.cryptomator.common.mount.MountModule; import org.cryptomator.common.mount.WindowsDriveLetters; +import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.VaultSettings; import org.cryptomator.common.vaults.Vault; import org.cryptomator.integrations.mount.MountCapability; +import org.cryptomator.integrations.mount.MountService; import org.cryptomator.ui.common.FxController; -import org.cryptomator.ui.fxapp.FxApplicationWindows; -import org.cryptomator.ui.preferences.SelectedPreferencesTab; import javax.inject.Inject; +import javax.inject.Named; +import javafx.application.Application; +import javafx.beans.binding.Bindings; +import javafx.beans.binding.BooleanExpression; import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; +import javafx.scene.control.Button; import javafx.scene.control.CheckBox; import javafx.scene.control.ChoiceBox; import javafx.scene.control.RadioButton; @@ -26,16 +34,25 @@ import java.io.File; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; +import java.util.List; +import java.util.Optional; import java.util.ResourceBundle; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; @VaultOptionsScoped public class MountOptionsController implements FxController { + private static final String DOCS_MOUNTING_URL = "https://docs.cryptomator.org/en/1.7/desktop/volume-type/"; + private static final int MIN_PORT = 1024; + private static final int MAX_PORT = 65535; + private final Stage window; private final VaultSettings vaultSettings; private final WindowsDriveLetters windowsDriveLetters; private final ResourceBundle resourceBundle; + private final Lazy application; + private final Settings settings; private final ObservableValue defaultMountFlags; private final ObservableValue mountpointDirSupported; @@ -43,7 +60,10 @@ public class MountOptionsController implements FxController { private final ObservableValue readOnlySupported; private final ObservableValue mountFlagsSupported; private final ObservableValue directoryPath; - private final FxApplicationWindows applicationWindows; + private final List mountProviders; + private final ObservableValue selectedMountService; + private final ObservableValue fuseRestartRequired; + private final BooleanExpression loopbackPortSupported; //-- FXML objects -- @@ -56,9 +76,21 @@ public class MountOptionsController implements FxController { public RadioButton mountPointDirBtn; public TextField directoryPathField; public ChoiceBox driveLetterSelection; + public ChoiceBox volumeTypeChoiceBox; + public TextField loopbackPortField; + public Button loopbackPortApplyButton; + @Inject - MountOptionsController(@VaultOptionsWindow Stage window, @VaultOptionsWindow Vault vault, ObservableValue mountService, WindowsDriveLetters windowsDriveLetters, ResourceBundle resourceBundle, FxApplicationWindows applicationWindows) { + MountOptionsController(@VaultOptionsWindow Stage window, // + @VaultOptionsWindow Vault vault, // + ObservableValue mountService, // + WindowsDriveLetters windowsDriveLetters, // + ResourceBundle resourceBundle, // + Lazy application, + Settings settings, // + List mountProviders, // + @Named("FUPFMS") AtomicReference firstUsedProblematicFuseMountService) { this.window = window; this.vaultSettings = vault.getVaultSettings(); this.windowsDriveLetters = windowsDriveLetters; @@ -75,7 +107,17 @@ public class MountOptionsController implements FxController { this.mountFlagsSupported = mountService.map(as -> as.service().hasCapability(MountCapability.MOUNT_FLAGS)); this.readOnlySupported = mountService.map(as -> as.service().hasCapability(MountCapability.READ_ONLY)); this.directoryPath = vault.getVaultSettings().mountPoint.map(p -> isDriveLetter(p) ? null : p.toString()); - this.applicationWindows = applicationWindows; + this.application = application; + this.settings = settings; + this.mountProviders = mountProviders; + var fallbackProvider = mountProviders.stream().findFirst().orElse(null); + this.selectedMountService = ObservableUtil.mapWithDefault(settings.mountService, serviceName -> mountProviders.stream().filter(s -> s.getClass().getName().equals(serviceName)).findFirst().orElse(fallbackProvider), fallbackProvider); + this.fuseRestartRequired = selectedMountService.map(s -> {// + return firstUsedProblematicFuseMountService.get() != null // + && MountModule.isProblematicFuseService(s) // + && !firstUsedProblematicFuseMountService.get().equals(s); + }); + this.loopbackPortSupported = BooleanExpression.booleanExpression(selectedMountService.map(s -> s.hasCapability(MountCapability.LOOPBACK_PORT))); } @FXML @@ -106,11 +148,21 @@ public class MountOptionsController implements FxController { mountPointToggleGroup.selectToggle(mountPointDirBtn); } mountPointToggleGroup.selectedToggleProperty().addListener(this::selectedToggleChanged); - } - @FXML - public void openVolumePreferences() { - applicationWindows.showPreferencesWindow(SelectedPreferencesTab.VOLUME); + volumeTypeChoiceBox.getItems().add(null); + volumeTypeChoiceBox.getItems().addAll(mountProviders); + volumeTypeChoiceBox.setConverter(new MountServiceConverter()); + boolean autoSelected = settings.mountService.get() == null; + volumeTypeChoiceBox.getSelectionModel().select(autoSelected ? null : selectedMountService.getValue()); + volumeTypeChoiceBox.valueProperty().addListener((observableValue, oldProvider, newProvider) -> { + var toSet = Optional.ofNullable(newProvider).map(nP -> nP.getClass().getName()).orElse(null); + settings.mountService.set(toSet); + }); + + loopbackPortField.setText(String.valueOf(settings.port.get())); + loopbackPortApplyButton.visibleProperty().bind(settings.port.asString().isNotEqualTo(loopbackPortField.textProperty())); + loopbackPortApplyButton.disableProperty().bind(Bindings.createBooleanBinding(this::validateLoopbackPort, loopbackPortField.textProperty()).not()); + } @FXML @@ -229,6 +281,26 @@ public class MountOptionsController implements FxController { } + public void openDocs() { + application.get().getHostServices().showDocument(DOCS_MOUNTING_URL); + } + + private boolean validateLoopbackPort() { + try { + int port = Integer.parseInt(loopbackPortField.getText()); + return port == 0 // choose port automatically + || port >= MIN_PORT && port <= MAX_PORT; // port within range + } catch (NumberFormatException e) { + return false; + } + } + + public void doChangeLoopbackPort() { + if (validateLoopbackPort()) { + settings.port.set(Integer.parseInt(loopbackPortField.getText())); + } + } + //@formatter:off private static class NoDirSelectedException extends Exception {} //@formatter:on @@ -274,4 +346,40 @@ public class MountOptionsController implements FxController { public String getDirectoryPath() { return directoryPath.getValue(); } + + public ObservableValue fuseRestartRequiredProperty() { + return fuseRestartRequired; + } + + public boolean getFuseRestartRequired() { + return fuseRestartRequired.getValue(); + } + + public BooleanExpression loopbackPortSupportedProperty() { + return loopbackPortSupported; + } + + public boolean isLoopbackPortSupported() { + return loopbackPortSupported.get(); + } + + //Helpers + /* Helpers */ + + private class MountServiceConverter extends StringConverter { + + @Override + public String toString(MountService provider) { + if (provider == null) { + return resourceBundle.getString("preferences.volume.type.automatic"); + } else { + return provider.displayName(); + } + } + + @Override + public MountService fromString(String string) { + throw new UnsupportedOperationException(); + } + } } diff --git a/src/main/resources/fxml/vault_options_mount.fxml b/src/main/resources/fxml/vault_options_mount.fxml index 762d36d27..921747132 100644 --- a/src/main/resources/fxml/vault_options_mount.fxml +++ b/src/main/resources/fxml/vault_options_mount.fxml @@ -1,6 +1,7 @@ + @@ -12,7 +13,7 @@ - + - - + + + + From 41c22b7840c9261b29e3fe26207ae96854f3262b Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Fri, 17 Nov 2023 13:30:40 +0100 Subject: [PATCH 021/131] Rename leftovers --- src/main/java/org/cryptomator/ui/common/FxmlFile.java | 2 +- .../cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java | 4 ++-- .../cryptomator/ui/keyloading/hub/ReceiveKeyController.java | 4 +--- .../fxml/{hub_setup_device.fxml => hub_register_device.fxml} | 0 4 files changed, 4 insertions(+), 6 deletions(-) rename src/main/resources/fxml/{hub_setup_device.fxml => hub_register_device.fxml} (100%) diff --git a/src/main/java/org/cryptomator/ui/common/FxmlFile.java b/src/main/java/org/cryptomator/ui/common/FxmlFile.java index 46542ccb9..d5308b5c0 100644 --- a/src/main/java/org/cryptomator/ui/common/FxmlFile.java +++ b/src/main/java/org/cryptomator/ui/common/FxmlFile.java @@ -23,7 +23,7 @@ public enum FxmlFile { HUB_LEGACY_REGISTER_DEVICE("/fxml/hub_legacy_register_device.fxml"), // HUB_REGISTER_SUCCESS("/fxml/hub_register_success.fxml"), // HUB_REGISTER_FAILED("/fxml/hub_register_failed.fxml"), // - HUB_SETUP_DEVICE("/fxml/hub_setup_device.fxml"), // + HUB_REGISTER_DEVICE("/fxml/hub_register_device.fxml"), // HUB_UNAUTHORIZED_DEVICE("/fxml/hub_unauthorized_device.fxml"), // HUB_REQUIRE_ACCOUNT_INIT("/fxml/hub_require_account_init.fxml"), // LOCK_FORCED("/fxml/lock_forced.fxml"), // 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 235fbf639..9f62a0c90 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java @@ -135,10 +135,10 @@ public abstract class HubKeyLoadingModule { } @Provides - @FxmlScene(FxmlFile.HUB_SETUP_DEVICE) + @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) @KeyLoadingScoped static Scene provideHubRegisterDeviceScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) { - return fxmlLoaders.createScene(FxmlFile.HUB_SETUP_DEVICE); + return fxmlLoaders.createScene(FxmlFile.HUB_REGISTER_DEVICE); } @Provides diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java b/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java index c0681d4bb..d00041640 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java @@ -11,7 +11,6 @@ import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; import org.cryptomator.ui.keyloading.KeyLoading; import org.cryptomator.ui.keyloading.KeyLoadingScoped; -import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,7 +31,6 @@ import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.time.Duration; -import java.time.Instant; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; @@ -60,7 +58,7 @@ public class ReceiveKeyController implements FxController { private final HttpClient httpClient; @Inject - public ReceiveKeyController(@KeyLoading Vault vault, ExecutorService executor, @KeyLoading Stage window, HubConfig hubConfig, @Named("deviceId") String deviceId, @Named("bearerToken") AtomicReference tokenRef, CompletableFuture result, @FxmlScene(FxmlFile.HUB_SETUP_DEVICE) Lazy setupDeviceScene, @FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_DEVICE) Lazy legacyRegisterDeviceScene, @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy unauthorizedScene, @FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT) Lazy accountInitializationScene, @FxmlScene(FxmlFile.HUB_INVALID_LICENSE) Lazy invalidLicenseScene) { + public ReceiveKeyController(@KeyLoading Vault vault, ExecutorService executor, @KeyLoading Stage window, HubConfig hubConfig, @Named("deviceId") String deviceId, @Named("bearerToken") AtomicReference tokenRef, CompletableFuture result, @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy setupDeviceScene, @FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_DEVICE) Lazy legacyRegisterDeviceScene, @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy unauthorizedScene, @FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT) Lazy accountInitializationScene, @FxmlScene(FxmlFile.HUB_INVALID_LICENSE) Lazy invalidLicenseScene) { this.window = window; this.hubConfig = hubConfig; this.deviceId = deviceId; diff --git a/src/main/resources/fxml/hub_setup_device.fxml b/src/main/resources/fxml/hub_register_device.fxml similarity index 100% rename from src/main/resources/fxml/hub_setup_device.fxml rename to src/main/resources/fxml/hub_register_device.fxml From e7e88f13e3d096c7e61b6fbf87afde8ebcf10377 Mon Sep 17 00:00:00 2001 From: Jan-Peter Klein Date: Fri, 17 Nov 2023 14:51:13 +0100 Subject: [PATCH 022/131] improved code quality --- .../java/org/cryptomator/common/CommonsModule.java | 13 ------------- .../cryptomator/common/vaults/VaultListManager.java | 2 -- .../ui/preferences/VolumePreferencesController.java | 6 +----- .../unlock/UnlockFuseRestartRequiredController.java | 9 +++++++++ .../org/cryptomator/ui/unlock/UnlockWorkflow.java | 5 ----- .../cryptomator/common/settings/SettingsTest.java | 8 ++++++-- 6 files changed, 16 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/cryptomator/common/CommonsModule.java b/src/main/java/org/cryptomator/common/CommonsModule.java index 9cba60131..5ea69da6d 100644 --- a/src/main/java/org/cryptomator/common/CommonsModule.java +++ b/src/main/java/org/cryptomator/common/CommonsModule.java @@ -7,12 +7,10 @@ package org.cryptomator.common; import dagger.Module; import dagger.Provides; -import org.apache.commons.lang3.SystemUtils; import org.cryptomator.common.keychain.KeychainModule; import org.cryptomator.common.mount.MountModule; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.SettingsProvider; -import org.cryptomator.common.settings.VaultSettings; import org.cryptomator.common.vaults.VaultComponent; import org.cryptomator.common.vaults.VaultListModule; import org.cryptomator.cryptolib.common.MasterkeyFileAccess; @@ -23,8 +21,6 @@ import org.slf4j.LoggerFactory; import javax.inject.Named; import javax.inject.Singleton; -import javafx.beans.value.ObservableValue; -import java.net.InetSocketAddress; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Comparator; @@ -138,15 +134,6 @@ public abstract class CommonsModule { LOG.error("Uncaught exception in " + thread.getName(), throwable); } - @Provides - @Singleton - static ObservableValue provideServerSocketAddressBinding(VaultSettings vaultSettings) { - return vaultSettings.port.map(port -> { - String host = SystemUtils.IS_OS_WINDOWS ? "127.0.0.1" : "localhost"; - return InetSocketAddress.createUnresolved(host, vaultSettings.port.intValue()); - }); - } - @Provides @Singleton @Named("FUPFMS") diff --git a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java index 0351981a0..cbcc281ac 100644 --- a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java +++ b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java @@ -73,8 +73,6 @@ public class VaultListManager { private VaultSettings newVaultSettings(Path path) { VaultSettings vaultSettings = VaultSettings.withRandomId(); vaultSettings.path.set(path); - vaultSettings.mountService.set(vaultSettings.mountService.getValue()); - vaultSettings.port.set(vaultSettings.port.getValue()); if (path.getFileName() != null) { vaultSettings.displayName.set(path.getFileName().toString()); } else { diff --git a/src/main/java/org/cryptomator/ui/preferences/VolumePreferencesController.java b/src/main/java/org/cryptomator/ui/preferences/VolumePreferencesController.java index fbd5d11ec..c06a4596b 100644 --- a/src/main/java/org/cryptomator/ui/preferences/VolumePreferencesController.java +++ b/src/main/java/org/cryptomator/ui/preferences/VolumePreferencesController.java @@ -3,13 +3,11 @@ package org.cryptomator.ui.preferences; import dagger.Lazy; import org.cryptomator.common.ObservableUtil; import org.cryptomator.common.settings.Settings; -import org.cryptomator.common.vaults.VaultModule; import org.cryptomator.integrations.mount.MountCapability; import org.cryptomator.integrations.mount.MountService; import org.cryptomator.ui.common.FxController; import javax.inject.Inject; -import javax.inject.Named; import javafx.application.Application; import javafx.beans.value.ObservableValue; import javafx.scene.control.ChoiceBox; @@ -17,7 +15,6 @@ import javafx.util.StringConverter; import java.util.List; import java.util.Optional; import java.util.ResourceBundle; -import java.util.concurrent.atomic.AtomicReference; @PreferencesScoped public class VolumePreferencesController implements FxController { @@ -39,7 +36,6 @@ public class VolumePreferencesController implements FxController { VolumePreferencesController(Settings settings, Lazy application, List mountProviders, - @Named("FUPFMS") AtomicReference firstUsedProblematicFuseMountService, ResourceBundle resourceBundle) { this.settings = settings; this.application = application; @@ -101,7 +97,7 @@ public class VolumePreferencesController implements FxController { /* Helpers */ - public class MountServiceConverter extends StringConverter { + private class MountServiceConverter extends StringConverter { @Override public String toString(MountService provider) { diff --git a/src/main/java/org/cryptomator/ui/unlock/UnlockFuseRestartRequiredController.java b/src/main/java/org/cryptomator/ui/unlock/UnlockFuseRestartRequiredController.java index 26ef4c7de..4f9e5649b 100644 --- a/src/main/java/org/cryptomator/ui/unlock/UnlockFuseRestartRequiredController.java +++ b/src/main/java/org/cryptomator/ui/unlock/UnlockFuseRestartRequiredController.java @@ -8,22 +8,31 @@ import org.cryptomator.ui.vaultoptions.SelectedVaultOptionsTab; import javax.inject.Inject; import javafx.fxml.FXML; import javafx.stage.Stage; +import java.util.ResourceBundle; @UnlockScoped public class UnlockFuseRestartRequiredController implements FxController { private final Stage window; + private final ResourceBundle resourceBundle; private final FxApplicationWindows appWindows; private final Vault vault; + @Inject UnlockFuseRestartRequiredController(@UnlockWindow Stage window, + ResourceBundle resourceBundle, FxApplicationWindows appWindows, @UnlockWindow Vault vault) { this.window = window; + this.resourceBundle = resourceBundle; this.appWindows = appWindows; this.vault = vault; } + public void initialize() { + window.setTitle(String.format(resourceBundle.getString("unlock.error.fuseRestartRequired.title"), vault.getDisplayName())); + } + @FXML public void close() { window.close(); diff --git a/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java b/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java index 7c776ad14..98385f1d6 100644 --- a/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java +++ b/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java @@ -23,7 +23,6 @@ import javafx.concurrent.Task; import javafx.scene.Scene; import javafx.stage.Stage; import java.io.IOException; -import java.util.ResourceBundle; /** * A multi-step task that consists of background activities as well as user interaction. @@ -36,7 +35,6 @@ public class UnlockWorkflow extends Task { private static final Logger LOG = LoggerFactory.getLogger(UnlockWorkflow.class); private final Stage window; - private final ResourceBundle resourceBundle; private final Vault vault; private final VaultService vaultService; private final Lazy successScene; @@ -48,7 +46,6 @@ public class UnlockWorkflow extends Task { @Inject UnlockWorkflow(@UnlockWindow Stage window, // - ResourceBundle resourceBundle, @UnlockWindow Vault vault, // VaultService vaultService, // @FxmlScene(FxmlFile.UNLOCK_SUCCESS) Lazy successScene, // @@ -58,7 +55,6 @@ public class UnlockWorkflow extends Task { @UnlockWindow KeyLoadingStrategy keyLoadingStrategy, // @UnlockWindow ObjectProperty illegalMountPointException) { this.window = window; - this.resourceBundle = resourceBundle; this.vault = vault; this.vaultService = vaultService; this.successScene = successScene; @@ -103,7 +99,6 @@ public class UnlockWorkflow extends Task { private void handleFuseRestartRequiredError(FuseRestartRequiredException fRRE) { Platform.runLater(() -> { window.setScene(fuseRestartRequiredScene.get()); - window.setTitle(String.format(resourceBundle.getString("unlock.error.fuseRestartRequired.title"), vault.getDisplayName())); window.show(); }); } diff --git a/src/test/java/org/cryptomator/common/settings/SettingsTest.java b/src/test/java/org/cryptomator/common/settings/SettingsTest.java index ee18b50c1..114b7f980 100644 --- a/src/test/java/org/cryptomator/common/settings/SettingsTest.java +++ b/src/test/java/org/cryptomator/common/settings/SettingsTest.java @@ -24,12 +24,16 @@ public class SettingsTest { Mockito.verify(changeListener, Mockito.times(0)).accept(settings); // first change (to property): - settings.directories.add(vaultSettings); + settings.windowXPosition.set(100); Mockito.verify(changeListener, Mockito.times(1)).accept(settings); // second change (to list): - vaultSettings.displayName.set("asd"); + settings.directories.add(vaultSettings); Mockito.verify(changeListener, Mockito.times(2)).accept(settings); + + // third change (to property of list item): + vaultSettings.displayName.set("asd"); + Mockito.verify(changeListener, Mockito.times(3)).accept(settings); } } From 1199ef40ddcfa33305708caf74f81b554d392aec Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Fri, 17 Nov 2023 15:27:46 +0100 Subject: [PATCH 023/131] on 409 repsonse of registerDevice-request, show setupFailed with adjusted message --- .../hub/DeviceAlreadyExistsException.java | 6 ++++ .../keyloading/hub/HubKeyLoadingModule.java | 8 +++++ .../hub/RegisterDeviceController.java | 29 +++++++++---------- .../hub/RegisterFailedController.java | 21 ++++++++++---- .../resources/fxml/hub_register_device.fxml | 9 ------ .../resources/fxml/hub_register_failed.fxml | 3 +- src/main/resources/i18n/strings.properties | 5 ++-- 7 files changed, 48 insertions(+), 33 deletions(-) create mode 100644 src/main/java/org/cryptomator/ui/keyloading/hub/DeviceAlreadyExistsException.java diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/DeviceAlreadyExistsException.java b/src/main/java/org/cryptomator/ui/keyloading/hub/DeviceAlreadyExistsException.java new file mode 100644 index 000000000..fd7cb4f5d --- /dev/null +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/DeviceAlreadyExistsException.java @@ -0,0 +1,6 @@ +package org.cryptomator.ui.keyloading.hub; + +/** + * Thrown, when Hub registerDevice-Request returns with 409 + */ +public class DeviceAlreadyExistsException extends RuntimeException {} 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 9f62a0c90..92e9af6f0 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java @@ -72,6 +72,14 @@ public abstract class HubKeyLoadingModule { return new CompletableFuture<>(); } + @Provides + @KeyLoadingScoped + @Named("registerException") + static AtomicReference provideRegisterException() { + return new AtomicReference<>(); + } + + @Binds @IntoMap @KeyLoadingScoped diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/RegisterDeviceController.java b/src/main/java/org/cryptomator/ui/keyloading/hub/RegisterDeviceController.java index 837dc5032..c51c7a8ab 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/RegisterDeviceController.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/RegisterDeviceController.java @@ -40,6 +40,7 @@ import java.text.ParseException; import java.time.Duration; import java.time.Instant; import java.util.Objects; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutorService; @@ -55,6 +56,7 @@ public class RegisterDeviceController implements FxController { private final Stage window; private final HubConfig hubConfig; private final String bearerToken; + private final AtomicReference registerException; private final Lazy registerSuccessScene; private final Lazy registerFailedScene; private final String deviceId; @@ -62,7 +64,6 @@ public class RegisterDeviceController implements FxController { private final CompletableFuture result; private final HttpClient httpClient; - private final BooleanProperty deviceNameAlreadyExists = new SimpleBooleanProperty(false); private final BooleanProperty invalidSetupCode = new SimpleBooleanProperty(false); private final BooleanProperty workInProgress = new SimpleBooleanProperty(false); public TextField setupCodeField; @@ -70,13 +71,14 @@ public class RegisterDeviceController implements FxController { public Button registerBtn; @Inject - public RegisterDeviceController(@KeyLoading Stage window, ExecutorService executor, HubConfig hubConfig, @Named("deviceId") String deviceId, DeviceKey deviceKey, CompletableFuture result, @Named("bearerToken") AtomicReference bearerToken, @FxmlScene(FxmlFile.HUB_REGISTER_SUCCESS) Lazy registerSuccessScene, @FxmlScene(FxmlFile.HUB_REGISTER_FAILED) Lazy registerFailedScene) { + public RegisterDeviceController(@KeyLoading Stage window, ExecutorService executor, HubConfig hubConfig, @Named("deviceId") String deviceId, DeviceKey deviceKey, CompletableFuture result, @Named("bearerToken") AtomicReference bearerToken, @Named("registerException") AtomicReference registerException, @FxmlScene(FxmlFile.HUB_REGISTER_SUCCESS) Lazy registerSuccessScene, @FxmlScene(FxmlFile.HUB_REGISTER_FAILED) Lazy registerFailedScene) { this.window = window; this.hubConfig = hubConfig; this.deviceId = deviceId; this.deviceKeyPair = Objects.requireNonNull(deviceKey.get()); this.result = result; this.bearerToken = Objects.requireNonNull(bearerToken.get()); + this.registerException = registerException; this.registerSuccessScene = registerSuccessScene; this.registerFailedScene = registerFailedScene; this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed); @@ -85,7 +87,6 @@ public class RegisterDeviceController implements FxController { public void initialize() { deviceNameField.setText(determineHostname()); - deviceNameField.textProperty().addListener(observable -> deviceNameAlreadyExists.set(false)); deviceNameField.disableProperty().bind(workInProgress); setupCodeField.textProperty().addListener(observable -> invalidSetupCode.set(false)); setupCodeField.disableProperty().bind(workInProgress); @@ -146,7 +147,7 @@ public class RegisterDeviceController implements FxController { return httpClient.sendAsync(putDeviceReq, HttpResponse.BodyHandlers.discarding()); }).whenCompleteAsync((response, throwable) -> { if (response != null) { - this.handleResponse(response); + this.handleRegisterDeviceResponse(response); } else { this.setupFailed(throwable); } @@ -170,12 +171,12 @@ public class RegisterDeviceController implements FxController { } } - private void handleResponse(HttpResponse response) { + private void handleRegisterDeviceResponse(HttpResponse response) { if (response.statusCode() == 201) { LOG.debug("Device registration for hub instance {} successful.", hubConfig.authSuccessUrl); window.setScene(registerSuccessScene.get()); } else if (response.statusCode() == 409) { - deviceNameAlreadyExists.set(true); + setupFailed(new DeviceAlreadyExistsException()); } else { setupFailed(new IllegalStateException("Unexpected http status code " + response.statusCode())); } @@ -185,7 +186,12 @@ public class RegisterDeviceController implements FxController { switch (cause) { case CompletionException e when e.getCause() instanceof JWEHelper.InvalidJweKeyException -> invalidSetupCode.set(true); default -> { - LOG.warn("Device setup failed.", cause); + if(cause instanceof DeviceAlreadyExistsException) { + LOG.debug("Device already registered in hub instance {} for different user", hubConfig.authSuccessUrl); + } else { + LOG.warn("Device setup failed.", cause); + } + registerException.set(cause); window.setScene(registerFailedScene.get()); result.completeExceptionally(cause); } @@ -202,15 +208,6 @@ public class RegisterDeviceController implements FxController { } //--- Getters & Setters - - public BooleanProperty deviceNameAlreadyExistsProperty() { - return deviceNameAlreadyExists; - } - - public boolean getDeviceNameAlreadyExists() { - return deviceNameAlreadyExists.get(); - } - public BooleanProperty invalidSetupCodeProperty() { return invalidSetupCode; } diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/RegisterFailedController.java b/src/main/java/org/cryptomator/ui/keyloading/hub/RegisterFailedController.java index 57150390c..495fda7dd 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/RegisterFailedController.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/RegisterFailedController.java @@ -1,23 +1,27 @@ package org.cryptomator.ui.keyloading.hub; -import com.nimbusds.jose.JWEObject; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.keyloading.KeyLoading; import javax.inject.Inject; +import javax.inject.Named; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; import javafx.fxml.FXML; import javafx.stage.Stage; -import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicReference; public class RegisterFailedController implements FxController { private final Stage window; - private final CompletableFuture result; + private final Throwable registerException; + private final SimpleBooleanProperty deviceAlreadyExisting; @Inject - public RegisterFailedController(@KeyLoading Stage window, CompletableFuture result) { + public RegisterFailedController(@KeyLoading Stage window, @Named("registerException") AtomicReference registerExceptionRef) { this.window = window; - this.result = result; + this.registerException = registerExceptionRef.get(); + this.deviceAlreadyExisting = new SimpleBooleanProperty(registerException instanceof DeviceAlreadyExistsException); } @FXML @@ -25,5 +29,12 @@ public class RegisterFailedController implements FxController { window.close(); } + public boolean isDeviceAlreadyExisting() { + return deviceAlreadyExisting.get(); + } + + public boolean isGenericError() { + return !deviceAlreadyExisting.get(); + } } diff --git a/src/main/resources/fxml/hub_register_device.fxml b/src/main/resources/fxml/hub_register_device.fxml index f83ad6a97..e1a1e39ff 100644 --- a/src/main/resources/fxml/hub_register_device.fxml +++ b/src/main/resources/fxml/hub_register_device.fxml @@ -57,15 +57,6 @@ - - - + From 1343099be6fccb3d9fac31fd3364f9f195e64f84 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 30 Nov 2023 09:26:11 +0100 Subject: [PATCH 034/131] [ci skip] correct dependabot config --- .github/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0e12bbba9..3d2f42f8d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,7 +6,7 @@ updates: interval: "weekly" day: "monday" time: "06:00" - timezone: "UTC" + timezone: "Etc/UTC" groups: java-test-dependencies: patterns: From 43ad1c05c0125f763bf87693ce00f8c96581d6fa Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 30 Nov 2023 11:18:33 +0100 Subject: [PATCH 035/131] cancel background task, if window is closed --- .../CreateNewVaultLocationController.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java index 939077401..988592e09 100644 --- a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java +++ b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java @@ -131,7 +131,16 @@ public class CreateNewVaultLocationController implements FxController { @FXML public void initialize() { - backgroundExecutor.submit(this::loadLocationPresets); + var task = backgroundExecutor.submit(this::loadLocationPresets); + var onHiddenAction = window.getOnHidden(); + if(onHiddenAction != null) { + window.setOnHidden(evt -> { + task.cancel(true); + onHiddenAction.handle(evt); + }); + } else { + window.setOnHidden(_ -> task.cancel(true)); + } locationPresetsToggler.selectedToggleProperty().addListener(this::togglePredefinedLocation); usePresetPath.bind(locationPresetsToggler.selectedToggleProperty().isNotEqualTo(customRadioButton)); } From 89b8bc414805eef99722214384a9aa88227523cd Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 30 Nov 2023 11:44:41 +0100 Subject: [PATCH 036/131] adjust ui and add localization --- src/main/resources/fxml/addvault_new_location.fxml | 4 +++- src/main/resources/i18n/strings.properties | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/resources/fxml/addvault_new_location.fxml b/src/main/resources/fxml/addvault_new_location.fxml index 2da0f4c5a..8310ef1fd 100644 --- a/src/main/resources/fxml/addvault_new_location.fxml +++ b/src/main/resources/fxml/addvault_new_location.fxml @@ -12,6 +12,7 @@ + - +