Add a scheduled service to auto unlock vaults that were missing at startup

This commit is contained in:
Rexbas
2023-02-19 16:29:06 +01:00
parent aa03bd119a
commit ba627d0d60
2 changed files with 62 additions and 9 deletions

View File

@@ -1,30 +1,83 @@
package org.cryptomator.ui.fxapp;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.collections.ObservableList;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
@FxApplicationScoped
public class AutoUnlocker {
private static final Logger LOG = LoggerFactory.getLogger(AutoUnlocker.class);
private final ObservableList<Vault> vaults;
private final FxApplicationWindows appWindows;
private final ScheduledExecutorService scheduler;
private ScheduledFuture<?> future;
private boolean isPeriodicCheckActive = false;
@Inject
public AutoUnlocker(ObservableList<Vault> vaults, FxApplicationWindows appWindows) {
public AutoUnlocker(ObservableList<Vault> vaults, FxApplicationWindows appWindows, ScheduledExecutorService scheduler) {
this.vaults = vaults;
this.appWindows = appWindows;
this.scheduler = scheduler;
}
public void unlock() {
vaults.stream().filter(Vault::isLocked) //
.filter(v -> v.getVaultSettings().unlockAfterStartup().get()) //
.<CompletionStage<Void>>reduce(CompletableFuture.completedFuture(null), //
(unlockFlow, v) -> unlockFlow.handle((voit, ex) -> appWindows.startUnlockWorkflow(v, null)).thenCompose(stage -> stage), //we don't care here about the exception, logged elsewhere
(unlockChain1, unlockChain2) -> unlockChain1.handle((voit, ex) -> unlockChain2).thenCompose(stage -> stage));
public void unlockAll() {
unlock(vaults.stream().filter(v -> v.getVaultSettings().unlockAfterStartup().get()));
}
public void unlock(Stream<Vault> vaultStream) {
vaultStream.filter(Vault::isLocked)
.<CompletionStage<Void>>reduce(CompletableFuture.completedFuture(null),
(unlockFlow, v) -> unlockFlow.handle((voit, ex) -> appWindows.startUnlockWorkflow(v, null)).thenCompose(stage -> stage), // we don't care here about the exception, logged elsewhere
(unlockChain1, unlockChain2) -> unlockChain1.handle((voit, ex) -> unlockChain2).thenCompose(stage -> stage));
}
public void startMissingVaultsChecker() {
if (!isPeriodicCheckActive && getMissingAutoUnlockVaults().count() > 0) {
LOG.info("Found MISSING vaults, starting periodic check");
future = scheduler.scheduleWithFixedDelay(this::tick, 0, 1, TimeUnit.SECONDS);
isPeriodicCheckActive = true;
}
}
private void tick() {
// Find the vaults that are missing but have an existing directory
Vault[] vaultArray = getMissingAutoUnlockVaults().filter(v -> v.getPath().toFile().isDirectory()).toArray(Vault[]::new);
if (vaultArray.length > 0) {
// Redetermine vault states
for (Vault v : vaultArray) {
LOG.info("Found vault directory for '{}'", v.getDisplayName());
VaultListManager.redetermineVaultState(v);
}
// Unlock the vaults that were previously missing
unlock(Arrays.stream(vaultArray));
}
// Stop checking if there are no more missing vaults
if (getMissingAutoUnlockVaults().count() == 0) {
LOG.info("No more MISSING vaults, stopping periodic check");
isPeriodicCheckActive = false;
future.cancel(false);
}
}
private Stream<Vault> getMissingAutoUnlockVaults() {
return vaults.stream()
.filter(Vault::isMissing)
.filter(v -> v.getVaultSettings().unlockAfterStartup().get());
}
}

View File

@@ -68,7 +68,7 @@ public class FxApplication {
});
launchEventHandler.startHandlingLaunchEvents();
autoUnlocker.unlock();
autoUnlocker.unlockAll();
autoUnlocker.startMissingVaultsChecker();
}
}