Add locking mechanism to change the vault state t

This commit is contained in:
Armin Schrenk
2021-04-06 13:26:58 +02:00
parent fb1078b35b
commit beba6490c3
6 changed files with 78 additions and 25 deletions
@@ -163,6 +163,8 @@ public class VaultService {
private final Vault vault;
private final boolean forced;
private volatile long stamp;
/**
* @param vault The vault to lock
* @param forced Whether to attempt a forced lock
@@ -176,23 +178,32 @@ public class VaultService {
@Override
protected Vault call() throws Volume.VolumeException {
this.stamp = vault.lockVaultState();
vault.lock(forced);
return vault;
}
@Override
protected void scheduled() {
vault.setState(VaultState.PROCESSING);
vault.setState(VaultState.PROCESSING, stamp);
}
@Override
protected void succeeded() {
vault.setState(VaultState.LOCKED);
vault.setState(VaultState.LOCKED, stamp);
vault.unlockVaultState(stamp);
}
@Override
protected void failed() {
vault.setState(VaultState.UNLOCKED);
vault.setState(VaultState.UNLOCKED, stamp);
vault.unlockVaultState(stamp);
}
@Override
protected void cancelled() {
vault.setState(VaultState.UNLOCKED, stamp);
vault.unlockVaultState(stamp);
}
}
@@ -36,6 +36,8 @@ public class LockWorkflow extends Task<Void> {
private final Lazy<Scene> lockForcedScene;
private final Lazy<Scene> lockFailedScene;
private volatile long stamp;
@Inject
public LockWorkflow(@LockWindow Stage lockWindow, @LockWindow Vault vault, UserInteractionLock<LockModule.ForceLockDecision> forceLockDecisionLock, @FxmlScene(FxmlFile.LOCK_FORCED) Lazy<Scene> lockForcedScene, @FxmlScene(FxmlFile.LOCK_FAILED) Lazy<Scene> lockFailedScene) {
this.lockWindow = lockWindow;
@@ -47,6 +49,7 @@ public class LockWorkflow extends Task<Void> {
@Override
protected Void call() throws Volume.VolumeException, InterruptedException {
this.stamp = vault.lockVaultState();
try {
vault.lock(false);
} catch (Volume.VolumeException e) {
@@ -79,19 +82,21 @@ public class LockWorkflow extends Task<Void> {
@Override
protected void scheduled() {
vault.setState(VaultState.PROCESSING);
vault.setState(VaultState.PROCESSING, stamp);
}
@Override
protected void succeeded() {
LOG.info("Lock of {} succeeded.", vault.getDisplayName());
vault.setState(VaultState.LOCKED);
vault.setState(VaultState.LOCKED, stamp);
vault.unlockVaultState(stamp);
}
@Override
protected void failed() {
LOG.warn("Failed to lock {}.", vault.getDisplayName());
vault.setState(VaultState.UNLOCKED);
vault.setState(VaultState.UNLOCKED, stamp);
vault.unlockVaultState(stamp);
lockWindow.setScene(lockFailedScene.get());
lockWindow.show();
}
@@ -99,7 +104,8 @@ public class LockWorkflow extends Task<Void> {
@Override
protected void cancelled() {
LOG.debug("Lock of {} canceled.", vault.getDisplayName());
vault.setState(VaultState.UNLOCKED);
vault.setState(VaultState.UNLOCKED, stamp);
vault.unlockVaultState(stamp);
}
}
@@ -101,7 +101,8 @@ public class MigrationRunController implements FxController {
public void migrate() {
LOG.info("Migrating vault {}", vault.getPath());
CharSequence password = passwordField.getCharacters();
vault.setState(VaultState.PROCESSING);
long stamp = vault.lockVaultState();
vault.setState(VaultState.PROCESSING, stamp);
passwordField.setDisable(true);
ScheduledFuture<?> progressSyncTask = scheduler.scheduleAtFixedRate(() -> {
Platform.runLater(() -> {
@@ -115,10 +116,10 @@ public class MigrationRunController implements FxController {
}).onSuccess(needsAnotherMigration -> {
if (needsAnotherMigration) {
LOG.info("Migration of '{}' succeeded, but another migration is required.", vault.getDisplayName());
vault.setState(VaultState.NEEDS_MIGRATION);
vault.setState(VaultState.NEEDS_MIGRATION, stamp);
} else {
LOG.info("Migration of '{}' succeeded.", vault.getDisplayName());
vault.setState(VaultState.LOCKED);
vault.setState(VaultState.LOCKED, stamp);
passwordField.wipe();
window.setScene(successScene.get());
}
@@ -127,22 +128,23 @@ public class MigrationRunController implements FxController {
passwordField.setDisable(false);
passwordField.selectAll();
passwordField.requestFocus();
vault.setState(VaultState.NEEDS_MIGRATION);
vault.setState(VaultState.NEEDS_MIGRATION, stamp);
}).onError(FileSystemCapabilityChecker.MissingCapabilityException.class, e -> {
LOG.error("Underlying file system not supported.", e);
vault.setState(VaultState.NEEDS_MIGRATION);
vault.setState(VaultState.NEEDS_MIGRATION, stamp);
missingCapability.set(e.getMissingCapability());
window.setScene(capabilityErrorScene.get());
}).onError(FileNameTooLongException.class, e -> {
LOG.error("Migration failed because the underlying file system does not support long filenames.", e);
vault.setState(VaultState.NEEDS_MIGRATION);
vault.setState(VaultState.NEEDS_MIGRATION, stamp);
errorComponent.cause(e).window(window).returnToScene(startScene.get()).build().showErrorScene();
window.setScene(impossibleScene.get());
}).onError(Exception.class, e -> { // including RuntimeExceptions
LOG.error("Migration failed for technical reasons.", e);
vault.setState(VaultState.NEEDS_MIGRATION);
vault.setState(VaultState.NEEDS_MIGRATION, stamp);
errorComponent.cause(e).window(window).returnToScene(startScene.get()).build().showErrorScene();
}).andFinally(() -> {
vault.unlockVaultState(stamp);
passwordField.setDisable(false);
progressSyncTask.cancel(true);
}).runOnce(executor);
@@ -59,6 +59,8 @@ public class UnlockWorkflow extends Task<Boolean> {
private final Lazy<Scene> invalidMountPointScene;
private final ErrorComponent.Builder errorComponent;
private volatile long stamp;
@Inject
UnlockWorkflow(@UnlockWindow Stage window, @UnlockWindow Vault vault, VaultService vaultService, AtomicReference<char[]> password, @Named("savePassword") AtomicBoolean savePassword, @Named("savedPassword") Optional<char[]> savedPassword, UserInteractionLock<PasswordEntry> passwordEntryLock, KeychainManager keychain, @FxmlScene(FxmlFile.UNLOCK) Lazy<Scene> unlockScene, @FxmlScene(FxmlFile.UNLOCK_SUCCESS) Lazy<Scene> successScene, @FxmlScene(FxmlFile.UNLOCK_INVALID_MOUNT_POINT) Lazy<Scene> invalidMountPointScene, ErrorComponent.Builder errorComponent) {
this.window = window;
@@ -87,6 +89,7 @@ public class UnlockWorkflow extends Task<Boolean> {
@Override
protected Boolean call() throws InterruptedException, IOException, VolumeException, InvalidMountPointException {
try {
this.stamp = vault.lockVaultState();
if (attemptUnlock()) {
handleSuccess();
return true;
@@ -207,22 +210,25 @@ public class UnlockWorkflow extends Task<Boolean> {
@Override
protected void scheduled() {
vault.setState(VaultState.PROCESSING);
vault.setState(VaultState.PROCESSING, stamp);
}
@Override
protected void succeeded() {
vault.setState(VaultState.UNLOCKED);
vault.setState(VaultState.UNLOCKED, stamp);
vault.unlockVaultState(stamp);
}
@Override
protected void failed() {
vault.setState(VaultState.LOCKED);
vault.setState(VaultState.LOCKED, stamp);
vault.unlockVaultState(stamp);
}
@Override
protected void cancelled() {
vault.setState(VaultState.LOCKED);
vault.setState(VaultState.LOCKED, stamp);
vault.unlockVaultState(stamp);
}
}