mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-21 20:21:27 +00:00
Actually run tests from within Sanitizer UI
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
<project.jdk.version>16</project.jdk.version>
|
||||
|
||||
<!-- cryptomator dependencies -->
|
||||
<cryptomator.cryptofs.version>2.0.0-beta5</cryptomator.cryptofs.version>
|
||||
<cryptomator.cryptofs.version>2.1.0-beta1</cryptomator.cryptofs.version>
|
||||
<cryptomator.integrations.version>1.0.0-beta2</cryptomator.integrations.version>
|
||||
<cryptomator.integrations.win.version>1.0.0-beta2</cryptomator.integrations.win.version>
|
||||
<cryptomator.integrations.mac.version>1.0.0-beta2</cryptomator.integrations.mac.version>
|
||||
|
||||
@@ -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"), //
|
||||
|
||||
@@ -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<Masterkey> masterkeyRef, AtomicReference<VaultConfig> 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<DiagnosticResult> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<Masterkey> provideMasterkeyRef() {
|
||||
return new AtomicReference<>();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@HealthCheckScoped
|
||||
static AtomicReference<VaultConfig> 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<Boolean> 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<Boolean> provideWindowShowingChangeListener(AtomicReference<Masterkey> 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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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<VaultConfig.UnverifiedVaultConfig> unverifiedVaultConfig;
|
||||
private final KeyLoadingStrategy keyLoadingStrategy;
|
||||
private final ExecutorService executor;
|
||||
private final AtomicReference<Masterkey> masterkeyRef;
|
||||
private final AtomicReference<VaultConfig> vaultConfigRef;
|
||||
private final Lazy<Scene> 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<Masterkey> masterkeyRef, AtomicReference<VaultConfig> vaultConfigRef, @FxmlScene(FxmlFile.HEALTH_CHECK) Lazy<Scene> 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
|
||||
|
||||
27
main/ui/src/main/resources/fxml/health_check.fxml
Normal file
27
main/ui/src/main/resources/fxml/health_check.fxml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ButtonBar?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<VBox xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.health.CheckController"
|
||||
minWidth="400"
|
||||
maxWidth="400"
|
||||
minHeight="145"
|
||||
spacing="12">
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="12"/>
|
||||
</padding>
|
||||
<children>
|
||||
<Label text="${controller.vaultConfig.cipherCombo}"/>
|
||||
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+X">
|
||||
<buttons>
|
||||
<Button text="TODO run check" ButtonBar.buttonData="NEXT_FORWARD" defaultButton="true" onAction="#runCheck"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</children>
|
||||
</VBox>
|
||||
@@ -25,7 +25,7 @@
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
|
||||
<buttons>
|
||||
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
|
||||
<Button text="%unlock.unlockBtn" ButtonBar.buttonData="NEXT_FORWARD" disable="${controller.invalidConfig}" defaultButton="true" onAction="#next"/>
|
||||
<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" disable="${controller.invalidConfig}" defaultButton="true" onAction="#next"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</children>
|
||||
|
||||
Reference in New Issue
Block a user