diff --git a/src/main/java/org/cryptomator/ui/common/FxmlFile.java b/src/main/java/org/cryptomator/ui/common/FxmlFile.java index 7298d3487..9af0578cf 100644 --- a/src/main/java/org/cryptomator/ui/common/FxmlFile.java +++ b/src/main/java/org/cryptomator/ui/common/FxmlFile.java @@ -22,8 +22,9 @@ public enum FxmlFile { HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), // HUB_LEGACY_REGISTER_DEVICE("/fxml/hub_legacy_register_device.fxml"), // HUB_REGISTER_SUCCESS("/fxml/hub_register_success.fxml"), // + HUB_REGISTER_DEVICE_ALREADY_EXISTS("/fxml/hub_register_device_already_exists.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/DeviceAlreadyExistsException.java b/src/main/java/org/cryptomator/ui/keyloading/hub/DeviceAlreadyExistsException.java new file mode 100644 index 000000000..0c942e67b --- /dev/null +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/DeviceAlreadyExistsException.java @@ -0,0 +1,12 @@ +package org.cryptomator.ui.keyloading.hub; + +import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException; + +/** + * Thrown, when Hub registerDevice-Request returns with 409 + */ +class DeviceAlreadyExistsException extends MasterkeyLoadingFailedException { + public DeviceAlreadyExistsException() { + super("Device already registered on this Hub instance"); + } +} 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..2076db9eb 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,17 @@ 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 + @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE_ALREADY_EXISTS) + @KeyLoadingScoped + static Scene provideHubRegisterDeviceAlreadyExistsScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) { + return fxmlLoaders.createScene(FxmlFile.HUB_REGISTER_DEVICE_ALREADY_EXISTS); } @Provides 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 9ea5e7735..40f845a63 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingStrategy.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingStrategy.java @@ -1,7 +1,6 @@ package org.cryptomator.ui.keyloading.hub; import com.google.common.base.Preconditions; -import com.nimbusds.jose.JWEObject; import dagger.Lazy; import org.cryptomator.common.keychain.KeychainManager; import org.cryptomator.common.keychain.NoKeychainAccessProviderException; @@ -44,6 +43,7 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy { this.window = window; this.keychainManager = keychainManager; window.setTitle(windowTitle); + window.setOnCloseRequest(_ -> result.cancel(true)); this.authFlowScene = authFlowScene; this.noKeychainScene = noKeychainScene; this.result = result; 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..e0f305fd2 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; @@ -51,7 +49,7 @@ public class ReceiveKeyController implements FxController { private final String deviceId; private final String bearerToken; private final CompletableFuture result; - private final Lazy setupDeviceScene; + private final Lazy registerDeviceScene; private final Lazy legacyRegisterDeviceScene; private final Lazy unauthorizedScene; private final Lazy accountInitializationScene; @@ -60,13 +58,13 @@ 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 registerDeviceScene, @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; this.bearerToken = Objects.requireNonNull(tokenRef.get()); this.result = result; - this.setupDeviceScene = setupDeviceScene; + this.registerDeviceScene = registerDeviceScene; this.legacyRegisterDeviceScene = legacyRegisterDeviceScene; this.unauthorizedScene = unauthorizedScene; this.accountInitializationScene = accountInitializationScene; @@ -141,7 +139,7 @@ public class ReceiveKeyController implements FxController { var device = JSON.reader().readValue(response.body(), DeviceDto.class); receivedBothEncryptedKeys(encryptedVaultKey, device.userPrivateKey); } - case 404 -> needsDeviceSetup(); // TODO: using the setup code, we can theoretically immediately unlock + case 404 -> needsDeviceRegistration(); // TODO: using the setup code, we can theoretically immediately unlock default -> throw new IllegalStateException("Unexpected response " + response.statusCode()); } } catch (IOException e) { @@ -149,8 +147,8 @@ public class ReceiveKeyController implements FxController { } } - private void needsDeviceSetup() { - window.setScene(setupDeviceScene.get()); + private void needsDeviceRegistration() { + window.setScene(registerDeviceScene.get()); } private void receivedBothEncryptedKeys(String encryptedVaultKey, String encryptedUserKey) throws IOException { 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..08af2492a 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/RegisterDeviceController.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/RegisterDeviceController.java @@ -57,12 +57,12 @@ public class RegisterDeviceController implements FxController { private final String bearerToken; private final Lazy registerSuccessScene; private final Lazy registerFailedScene; + private final Lazy deviceAlreadyExistsScene; private final String deviceId; private final P384KeyPair deviceKeyPair; 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,7 +70,7 @@ 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, @FxmlScene(FxmlFile.HUB_REGISTER_SUCCESS) Lazy registerSuccessScene, @FxmlScene(FxmlFile.HUB_REGISTER_FAILED) Lazy registerFailedScene, @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE_ALREADY_EXISTS) Lazy deviceAlreadyExistsScene) { this.window = window; this.hubConfig = hubConfig; this.deviceId = deviceId; @@ -79,13 +79,13 @@ public class RegisterDeviceController implements FxController { this.bearerToken = Objects.requireNonNull(bearerToken.get()); this.registerSuccessScene = registerSuccessScene; this.registerFailedScene = registerFailedScene; + this.deviceAlreadyExistsScene = deviceAlreadyExistsScene; this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed); this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).executor(executor).build(); } 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 +146,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 +170,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())); } @@ -184,10 +184,13 @@ public class RegisterDeviceController implements FxController { private void setupFailed(Throwable cause) { switch (cause) { case CompletionException e when e.getCause() instanceof JWEHelper.InvalidJweKeyException -> invalidSetupCode.set(true); + case DeviceAlreadyExistsException e -> { + LOG.debug("Device already registered in hub instance {} for different user", hubConfig.authSuccessUrl); + window.setScene(deviceAlreadyExistsScene.get()); + } default -> { LOG.warn("Device setup failed.", cause); window.setScene(registerFailedScene.get()); - result.completeExceptionally(cause); } } } @@ -202,15 +205,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..7df27b06a 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/RegisterFailedController.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/RegisterFailedController.java @@ -1,6 +1,5 @@ package org.cryptomator.ui.keyloading.hub; -import com.nimbusds.jose.JWEObject; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.keyloading.KeyLoading; @@ -22,8 +21,8 @@ public class RegisterFailedController implements FxController { @FXML public void close() { + result.cancel(true); window.close(); } - } diff --git a/src/main/resources/fxml/hub_setup_device.fxml b/src/main/resources/fxml/hub_register_device.fxml similarity index 88% rename from src/main/resources/fxml/hub_setup_device.fxml rename to src/main/resources/fxml/hub_register_device.fxml index f83ad6a97..e1a1e39ff 100644 --- a/src/main/resources/fxml/hub_setup_device.fxml +++ b/src/main/resources/fxml/hub_register_device.fxml @@ -57,15 +57,6 @@ - -