diff --git a/main/pom.xml b/main/pom.xml
index ddd4262ec..02223a389 100644
--- a/main/pom.xml
+++ b/main/pom.xml
@@ -25,7 +25,7 @@
16
- 2.0.0-beta5
+ 2.1.0-beta1
1.0.0-beta2
1.0.0-beta2
1.0.0-beta2
diff --git a/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java b/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java
index 625c95acb..a1773d7af 100644
--- a/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java
+++ b/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java
@@ -12,6 +12,7 @@ public enum FxmlFile {
ERROR("/fxml/error.fxml"), //
FORGET_PASSWORD("/fxml/forget_password.fxml"), //
HEALTH_START("/fxml/health_start.fxml"), //
+ HEALTH_CHECK("/fxml/health_check.fxml"), //
LOCK_FORCED("/fxml/lock_forced.fxml"), //
LOCK_FAILED("/fxml/lock_failed.fxml"), //
MAIN_WINDOW("/fxml/main_window.fxml"), //
diff --git a/main/ui/src/main/java/org/cryptomator/ui/health/CheckController.java b/main/ui/src/main/java/org/cryptomator/ui/health/CheckController.java
new file mode 100644
index 000000000..77b137494
--- /dev/null
+++ b/main/ui/src/main/java/org/cryptomator/ui/health/CheckController.java
@@ -0,0 +1,59 @@
+package org.cryptomator.ui.health;
+
+import org.cryptomator.common.vaults.Vault;
+import org.cryptomator.cryptofs.VaultConfig;
+import org.cryptomator.cryptofs.health.api.DiagnosticResult;
+import org.cryptomator.cryptofs.health.api.HealthCheck;
+import org.cryptomator.cryptolib.api.Masterkey;
+import org.cryptomator.ui.common.FxController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import javafx.fxml.FXML;
+import javafx.stage.Stage;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
+
+@HealthCheckScoped
+public class CheckController implements FxController {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CheckController.class);
+
+ private final Vault vault;
+ private final Stage window;
+ private final Masterkey masterkey;
+ private final VaultConfig vaultConfig;
+ private final SecureRandom csprng;
+
+ @Inject
+ public CheckController(@HealthCheckWindow Vault vault, @HealthCheckWindow Stage window, AtomicReference masterkeyRef, AtomicReference vaultConfigRef, SecureRandom csprng) {
+ this.vault = vault;
+ this.window = window;
+ this.masterkey = Objects.requireNonNull(masterkeyRef.get());
+ this.vaultConfig = Objects.requireNonNull(vaultConfigRef.get());
+ this.csprng = csprng;
+ }
+
+ @FXML
+ public void runCheck() {
+ // TODO run in background task...
+ try (var cryptor = vaultConfig.getCipherCombo().getCryptorProvider(csprng).withKey(masterkey)) {
+ List results = new ArrayList<>();
+ HealthCheck.allChecks().forEach(c -> {
+ LOG.info("Running check {}...", c.identifier());
+ results.addAll(c.check(vault.getPath(), vaultConfig, masterkey, cryptor));
+ });
+ results.forEach(r -> {
+ LOG.info("Result: {}", r);
+ });
+ }
+ }
+
+ public VaultConfig getVaultConfig() {
+ return vaultConfig;
+ }
+}
diff --git a/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckModule.java b/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckModule.java
index c5414ab9a..0a17678fc 100644
--- a/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckModule.java
+++ b/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckModule.java
@@ -5,6 +5,8 @@ import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.common.vaults.Vault;
+import org.cryptomator.cryptofs.VaultConfig;
+import org.cryptomator.cryptolib.api.Masterkey;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
@@ -17,15 +19,32 @@ import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
import org.cryptomator.ui.mainwindow.MainWindow;
import javax.inject.Provider;
+import javafx.beans.Observable;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.util.Map;
+import java.util.Optional;
import java.util.ResourceBundle;
+import java.util.concurrent.atomic.AtomicReference;
@Module(subcomponents = {KeyLoadingComponent.class})
abstract class HealthCheckModule {
+ @Provides
+ @HealthCheckScoped
+ static AtomicReference provideMasterkeyRef() {
+ return new AtomicReference<>();
+ }
+
+ @Provides
+ @HealthCheckScoped
+ static AtomicReference provideVaultConfigRef() {
+ return new AtomicReference<>();
+ }
+
@Provides
@HealthCheckWindow
@HealthCheckScoped
@@ -43,25 +62,48 @@ abstract class HealthCheckModule {
@Provides
@HealthCheckWindow
@HealthCheckScoped
- static Stage provideStage(StageFactory factory, @MainWindow Stage owner, ResourceBundle resourceBundle) {
+ static Stage provideStage(StageFactory factory, @MainWindow Stage owner, ResourceBundle resourceBundle, ChangeListener showingListener) {
Stage stage = factory.create();
stage.setTitle(resourceBundle.getString("health.title"));
stage.setResizable(false);
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(owner);
+ stage.showingProperty().addListener(showingListener);
return stage;
}
+ @Provides
+ @HealthCheckScoped
+ static ChangeListener provideWindowShowingChangeListener(AtomicReference masterkey) {
+ return (observable, wasShowing, isShowing) -> {
+ if (!isShowing) {
+ Optional.ofNullable(masterkey.getAndSet(null)).ifPresent(Masterkey::destroy);
+ }
+ };
+ }
+
@Provides
@FxmlScene(FxmlFile.HEALTH_START)
@HealthCheckScoped
- static Scene provideUnlockSelectMasterkeyFileScene(@HealthCheckWindow FxmlLoaderFactory fxmlLoaders) {
+ static Scene provideHealthStartScene(@HealthCheckWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.HEALTH_START);
}
+ @Provides
+ @FxmlScene(FxmlFile.HEALTH_CHECK)
+ @HealthCheckScoped
+ static Scene provideHealthCheckScene(@HealthCheckWindow FxmlLoaderFactory fxmlLoaders) {
+ return fxmlLoaders.createScene(FxmlFile.HEALTH_CHECK);
+ }
+
@Binds
@IntoMap
@FxControllerKey(StartController.class)
abstract FxController bindStartController(StartController controller);
+ @Binds
+ @IntoMap
+ @FxControllerKey(CheckController.class)
+ abstract FxController bindCheckController(CheckController controller);
+
}
diff --git a/main/ui/src/main/java/org/cryptomator/ui/health/StartController.java b/main/ui/src/main/java/org/cryptomator/ui/health/StartController.java
index 6d9c51b4b..848be8a9d 100644
--- a/main/ui/src/main/java/org/cryptomator/ui/health/StartController.java
+++ b/main/ui/src/main/java/org/cryptomator/ui/health/StartController.java
@@ -1,5 +1,6 @@
package org.cryptomator.ui.health;
+import dagger.Lazy;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.cryptofs.VaultConfig;
import org.cryptomator.cryptofs.VaultConfigLoadException;
@@ -7,6 +8,8 @@ import org.cryptomator.cryptofs.VaultKeyInvalidException;
import org.cryptomator.cryptolib.api.Masterkey;
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
import org.cryptomator.ui.common.FxController;
+import org.cryptomator.ui.common.FxmlFile;
+import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.fxapp.FxApplication;
import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
import org.cryptomator.ui.unlock.UnlockCancelledException;
@@ -16,10 +19,12 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.application.Platform;
import javafx.fxml.FXML;
+import javafx.scene.Scene;
import javafx.stage.Stage;
import java.net.URI;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicReference;
@HealthCheckScoped
public class StartController implements FxController {
@@ -30,13 +35,19 @@ public class StartController implements FxController {
private final Optional unverifiedVaultConfig;
private final KeyLoadingStrategy keyLoadingStrategy;
private final ExecutorService executor;
+ private final AtomicReference masterkeyRef;
+ private final AtomicReference vaultConfigRef;
+ private final Lazy checkScene;
@Inject
- public StartController(@HealthCheckWindow Vault vault, @HealthCheckWindow Stage window, @HealthCheckWindow KeyLoadingStrategy keyLoadingStrategy, ExecutorService executor) {
+ public StartController(@HealthCheckWindow Vault vault, @HealthCheckWindow Stage window, @HealthCheckWindow KeyLoadingStrategy keyLoadingStrategy, ExecutorService executor, AtomicReference masterkeyRef, AtomicReference vaultConfigRef, @FxmlScene(FxmlFile.HEALTH_CHECK) Lazy checkScene) {
this.window = window;
this.unverifiedVaultConfig = vault.getUnverifiedVaultConfig();
this.keyLoadingStrategy = keyLoadingStrategy;
this.executor = executor;
+ this.masterkeyRef = masterkeyRef;
+ this.vaultConfigRef = vaultConfigRef;
+ this.checkScene = checkScene;
}
@FXML
@@ -53,9 +64,16 @@ public class StartController implements FxController {
private void loadKey() {
assert !Platform.isFxApplicationThread();
+ assert unverifiedVaultConfig.isPresent();
try (var masterkey = keyLoadingStrategy.masterkeyLoader().loadKey(unverifiedVaultConfig.orElseThrow().getKeyId())) {
- var clone = masterkey.clone(); // original key will get destroyed
- Platform.runLater(() -> loadedKey(clone));
+ var unverifiedCfg = unverifiedVaultConfig.get();
+ var verifiedCfg = unverifiedCfg.verify(masterkey.getEncoded(), unverifiedCfg.allegedVaultVersion());
+ vaultConfigRef.set(verifiedCfg);
+ var old = masterkeyRef.getAndSet(masterkey.clone());
+ if (old != null) {
+ old.destroy();
+ }
+ Platform.runLater(this::loadedKey);
} catch (MasterkeyLoadingFailedException e) {
if (keyLoadingStrategy.recoverFromException(e)) {
// retry
@@ -63,29 +81,24 @@ public class StartController implements FxController {
} else {
Platform.runLater(() -> loadingKeyFailed(e));
}
- }
- }
-
- private void loadedKey(Masterkey masterkey) {
- assert unverifiedVaultConfig.isPresent();
- var unverifiedCfg = unverifiedVaultConfig.get();
- try {
- var verifiedCfg = unverifiedCfg.verify(masterkey.getEncoded(), unverifiedCfg.allegedVaultVersion());
- LOG.info("Verified vault config with cipher {}", verifiedCfg.getCipherCombo());
} catch (VaultKeyInvalidException e) {
- LOG.error("Invalid key");
- // TODO show error screen
+ Platform.runLater(() -> loadingKeyFailed(e));
} catch (VaultConfigLoadException e) {
- LOG.error("Failed to verify vault config", e);
- // TODO show error screen
- } finally {
- masterkey.destroy();
+ Platform.runLater(() -> loadingKeyFailed(e));
}
}
- private void loadingKeyFailed(MasterkeyLoadingFailedException e) {
+ private void loadedKey() {
+ LOG.debug("Loaded valid key");
+ window.setScene(checkScene.get());
+ }
+
+ private void loadingKeyFailed(Exception e) {
if (e instanceof UnlockCancelledException) {
// ok
+ } else if (e instanceof VaultKeyInvalidException) {
+ LOG.error("Invalid key");
+ // TODO show error screen
} else {
LOG.error("Failed to load key.", e);
// TODO show error screen
diff --git a/main/ui/src/main/resources/fxml/health_check.fxml b/main/ui/src/main/resources/fxml/health_check.fxml
new file mode 100644
index 000000000..42942e01b
--- /dev/null
+++ b/main/ui/src/main/resources/fxml/health_check.fxml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/main/ui/src/main/resources/fxml/health_start.fxml b/main/ui/src/main/resources/fxml/health_start.fxml
index 15d3809a5..351e5885b 100644
--- a/main/ui/src/main/resources/fxml/health_start.fxml
+++ b/main/ui/src/main/resources/fxml/health_start.fxml
@@ -25,7 +25,7 @@
-
+