mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-17 10:11:27 +00:00
read vault config async
This commit is contained in:
@@ -18,11 +18,15 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@@ -31,38 +35,40 @@ public class StartController implements FxController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(StartController.class);
|
||||
|
||||
private final Vault vault;
|
||||
private final Stage window;
|
||||
private final Optional<VaultConfig.UnverifiedVaultConfig> unverifiedVaultConfig;
|
||||
private final CompletableFuture<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;
|
||||
private final Lazy<ErrorComponent.Builder> errorComponent;
|
||||
private final ObjectProperty<State> state = new SimpleObjectProperty<>(State.LOADING);
|
||||
private final BooleanBinding loading = state.isEqualTo(State.LOADING);
|
||||
private final BooleanBinding failed = state.isEqualTo(State.FAILED);
|
||||
private final BooleanBinding loaded = state.isEqualTo(State.LOADED);
|
||||
|
||||
public enum State {
|
||||
LOADING,
|
||||
FAILED,
|
||||
LOADED
|
||||
}
|
||||
|
||||
/* FXML */
|
||||
|
||||
@Inject
|
||||
public StartController(@HealthCheckWindow Vault vault, @HealthCheckWindow Stage window, @HealthCheckWindow KeyLoadingStrategy keyLoadingStrategy, ExecutorService executor, AtomicReference<Masterkey> masterkeyRef, AtomicReference<VaultConfig> vaultConfigRef, @FxmlScene(FxmlFile.HEALTH_CHECK_LIST) Lazy<Scene> checkScene, Lazy<ErrorComponent.Builder> errorComponent) {
|
||||
this.vault = vault;
|
||||
this.window = window;
|
||||
this.unverifiedVaultConfig = CompletableFuture.supplyAsync(this::loadConfig, executor);
|
||||
this.keyLoadingStrategy = keyLoadingStrategy;
|
||||
this.executor = executor;
|
||||
this.masterkeyRef = masterkeyRef;
|
||||
this.vaultConfigRef = vaultConfigRef;
|
||||
this.checkScene = checkScene;
|
||||
this.errorComponent = errorComponent;
|
||||
|
||||
//TODO: this is ugly
|
||||
//idea: delay the loading of the vault config and show a spinner (something like "check/load config") and react to the result of the loading
|
||||
//or: load vault config in a previous step to see if it is loadable.
|
||||
VaultConfig.UnverifiedVaultConfig tmp;
|
||||
try {
|
||||
tmp = vault.getUnverifiedVaultConfig();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
tmp = null;
|
||||
}
|
||||
this.unverifiedVaultConfig = Optional.ofNullable(tmp);
|
||||
this.unverifiedVaultConfig.whenCompleteAsync(this::loadedConfig, Platform::runLater);
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -77,11 +83,29 @@ public class StartController implements FxController {
|
||||
executor.submit(this::loadKey);
|
||||
}
|
||||
|
||||
private VaultConfig.UnverifiedVaultConfig loadConfig() {
|
||||
try {
|
||||
return this.vault.getUnverifiedVaultConfig();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadedConfig(VaultConfig.UnverifiedVaultConfig cfg, Throwable exception) {
|
||||
assert Platform.isFxApplicationThread();
|
||||
if (exception != null) {
|
||||
state.set(State.FAILED);
|
||||
} else {
|
||||
assert cfg != null;
|
||||
state.set(State.LOADED);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadKey() {
|
||||
assert !Platform.isFxApplicationThread();
|
||||
assert unverifiedVaultConfig.isPresent();
|
||||
try (var masterkey = keyLoadingStrategy.loadKey(unverifiedVaultConfig.orElseThrow().getKeyId())) {
|
||||
var unverifiedCfg = unverifiedVaultConfig.get();
|
||||
assert unverifiedVaultConfig.isDone();
|
||||
var unverifiedCfg = unverifiedVaultConfig.join();
|
||||
try (var masterkey = keyLoadingStrategy.loadKey(unverifiedCfg.getKeyId())) {
|
||||
var verifiedCfg = unverifiedCfg.verify(masterkey.getEncoded(), unverifiedCfg.allegedVaultVersion());
|
||||
vaultConfigRef.set(verifiedCfg);
|
||||
var old = masterkeyRef.getAndSet(masterkey.clone());
|
||||
@@ -96,8 +120,6 @@ public class StartController implements FxController {
|
||||
} else {
|
||||
Platform.runLater(() -> loadingKeyFailed(e));
|
||||
}
|
||||
} catch (VaultKeyInvalidException e) {
|
||||
Platform.runLater(() -> loadingKeyFailed(e));
|
||||
} catch (VaultConfigLoadException e) {
|
||||
Platform.runLater(() -> loadingKeyFailed(e));
|
||||
}
|
||||
@@ -120,8 +142,29 @@ public class StartController implements FxController {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInvalidConfig() {
|
||||
return unverifiedVaultConfig.isEmpty();
|
||||
/* Getter */
|
||||
|
||||
public BooleanBinding loadingProperty() {
|
||||
return loading;
|
||||
}
|
||||
|
||||
public boolean isLoading() {
|
||||
return loading.get();
|
||||
}
|
||||
|
||||
public BooleanBinding failedProperty() {
|
||||
return failed;
|
||||
}
|
||||
|
||||
public boolean isFailed() {
|
||||
return failed.get();
|
||||
}
|
||||
|
||||
public BooleanBinding loadedProperty() {
|
||||
return loaded;
|
||||
}
|
||||
|
||||
public boolean isLoaded() {
|
||||
return loaded.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,22 +17,25 @@
|
||||
<Insets topRightBottomLeft="12"/>
|
||||
</padding>
|
||||
<children>
|
||||
|
||||
<!-- TODO: combine the two below labels to one and bind the properties accordingly or, preferably think about a new flow -->
|
||||
<Label text="%health.start.configInvalid" visible="${controller.invalidConfig}" managed="${controller.invalidConfig}" wrapText="true" contentDisplay="LEFT">
|
||||
<Label text="TODO loading config..." visible="${controller.loading}" managed="${controller.loading}" wrapText="true" contentDisplay="LEFT">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="TIMES" styleClass="glyph-icon-red" />
|
||||
<FontAwesome5IconView glyph="SPINNER"/>
|
||||
</graphic>
|
||||
</Label>
|
||||
<Label text="%health.start.configValid" visible="${!controller.invalidConfig}" managed="${!controller.invalidConfig}" wrapText="true" contentDisplay="LEFT">
|
||||
<Label text="%health.start.configInvalid" visible="${controller.failed}" managed="${controller.failed}" wrapText="true" contentDisplay="LEFT">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="CHECK" styleClass="glyph-icon-primary" />
|
||||
<FontAwesome5IconView glyph="TIMES" styleClass="glyph-icon-red"/>
|
||||
</graphic>
|
||||
</Label>
|
||||
<Label text="%health.start.configValid" visible="${controller.loaded}" managed="${controller.loaded}" wrapText="true" contentDisplay="LEFT">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="CHECK" styleClass="glyph-icon-primary"/>
|
||||
</graphic>
|
||||
</Label>
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
|
||||
<buttons>
|
||||
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
|
||||
<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" disable="${controller.invalidConfig}" defaultButton="true" onAction="#next"/>
|
||||
<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" disable="${!controller.loaded}" defaultButton="true" onAction="#next"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</children>
|
||||
|
||||
Reference in New Issue
Block a user