From c82e5577a125f85ac6d5c239227d6cbc46ccffe1 Mon Sep 17 00:00:00 2001 From: Martin Beyer Date: Wed, 24 Feb 2021 15:17:23 +0100 Subject: [PATCH 01/15] New Tab AutoLock in VaultOptions --- .../cryptomator/ui/controls/FontAwesome5Icon.java | 1 + .../ui/vaultoptions/SelectedVaultOptionsTab.java | 6 ++++++ .../ui/vaultoptions/VaultOptionsController.java | 2 ++ .../ui/vaultoptions/VaultOptionsModule.java | 5 +++++ main/ui/src/main/resources/fxml/vault_options.fxml | 8 ++++++++ .../main/resources/fxml/vault_options_autolock.fxml | 12 ++++++++++++ main/ui/src/main/resources/i18n/strings.properties | 2 ++ 7 files changed, 36 insertions(+) create mode 100644 main/ui/src/main/resources/fxml/vault_options_autolock.fxml diff --git a/main/ui/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java b/main/ui/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java index f4d0d058a..1c799d56d 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java @@ -41,6 +41,7 @@ public enum FontAwesome5Icon { TIMES("\uF00D"), // TRASH("\uF1F8"), // UNLINK("\uf127"), // + USER_LOCK("\uF502"), // WRENCH("\uF0AD"), // WINDOW_MINIMIZE("\uF2D1"), // ; diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/SelectedVaultOptionsTab.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/SelectedVaultOptionsTab.java index 86945374a..03a4922d4 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/SelectedVaultOptionsTab.java +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/SelectedVaultOptionsTab.java @@ -20,4 +20,10 @@ public enum SelectedVaultOptionsTab { * Show password tab */ KEY, + + /** + * Show Auto-Lock tab + * + */ + AUTOLOCK, } diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java index 15879e316..20dac7594 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java @@ -23,6 +23,7 @@ public class VaultOptionsController implements FxController { public Tab generalTab; public Tab mountTab; public Tab keyTab; + public Tab autoLockTab; @Inject VaultOptionsController(@VaultOptionsWindow Stage window, ObjectProperty selectedTabProperty) { @@ -47,6 +48,7 @@ public class VaultOptionsController implements FxController { case ANY, GENERAL -> generalTab; case MOUNT -> mountTab; case KEY -> keyTab; + case AUTOLOCK -> autoLockTab; }; } diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java index fb248f38e..89cef234b 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java @@ -84,4 +84,9 @@ abstract class VaultOptionsModule { @FxControllerKey(MasterkeyOptionsController.class) abstract FxController bindMasterkeyOptionsController(MasterkeyOptionsController controller); + @Binds + @IntoMap + @FxControllerKey(AutoLockVaultOptionsController.class) + abstract FxController bindAutoLockVaultOptionsController(AutoLockVaultOptionsController controller); + } diff --git a/main/ui/src/main/resources/fxml/vault_options.fxml b/main/ui/src/main/resources/fxml/vault_options.fxml index 2229f5709..090988c7b 100644 --- a/main/ui/src/main/resources/fxml/vault_options.fxml +++ b/main/ui/src/main/resources/fxml/vault_options.fxml @@ -36,5 +36,13 @@ + + + + + + + + diff --git a/main/ui/src/main/resources/fxml/vault_options_autolock.fxml b/main/ui/src/main/resources/fxml/vault_options_autolock.fxml new file mode 100644 index 000000000..3586def6b --- /dev/null +++ b/main/ui/src/main/resources/fxml/vault_options_autolock.fxml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/main/ui/src/main/resources/i18n/strings.properties b/main/ui/src/main/resources/i18n/strings.properties index 20aa17a14..86972b92c 100644 --- a/main/ui/src/main/resources/i18n/strings.properties +++ b/main/ui/src/main/resources/i18n/strings.properties @@ -292,6 +292,8 @@ vaultOptions.masterkey.forgetSavedPasswordBtn=Forget Saved Password vaultOptions.masterkey.recoveryKeyExpanation=A recovery key is your only means to restore access to a vault if you lose your password. vaultOptions.masterkey.showRecoveryKeyBtn=Display Recovery Key vaultOptions.masterkey.recoverPasswordBtn=Recover Password +## Auto Lock +vaultOptions.autoLock=Auto-Lock # Recovery Key recoveryKey.title=Recovery Key From 8fccb1b8f03748537e392a9436659f99417b5844 Mon Sep 17 00:00:00 2001 From: Martin Beyer Date: Wed, 24 Feb 2021 16:20:34 +0100 Subject: [PATCH 02/15] Added some Settings --- .../common/settings/VaultSettings.java | 25 +++++++++++++++---- .../settings/VaultSettingsJsonAdapter.java | 12 +++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java index 7de22753a..79d9629ba 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java @@ -8,7 +8,6 @@ package org.cryptomator.common.settings; import com.google.common.base.CharMatcher; import com.google.common.base.Strings; import com.google.common.io.BaseEncoding; - import javafx.beans.Observable; import javafx.beans.binding.Bindings; import javafx.beans.binding.StringBinding; @@ -20,12 +19,11 @@ import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; + import java.nio.file.Path; import java.util.Objects; import java.util.Optional; import java.util.Random; -import java.util.Set; -import java.util.stream.Collectors; /** * The settings specific to a single vault. @@ -39,6 +37,9 @@ public class VaultSettings { public static final String DEFAULT_MOUNT_FLAGS = ""; public static final int DEFAULT_FILENAME_LENGTH_LIMIT = -1; public static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK; + public static final boolean DEFAULT_LOCK_ON_SLEEP = false; + public static final boolean DEFAULT_LOCK_AFTER_IDLETIME = false; + public static final String DEFAULT_LOCK_IDLETIME_IN_MINUTES = "30"; private static final Random RNG = new Random(); @@ -54,7 +55,9 @@ public class VaultSettings { private final StringProperty mountFlags = new SimpleStringProperty(DEFAULT_MOUNT_FLAGS); private final IntegerProperty filenameLengthLimit = new SimpleIntegerProperty(DEFAULT_FILENAME_LENGTH_LIMIT); private final ObjectProperty actionAfterUnlock = new SimpleObjectProperty<>(DEFAULT_ACTION_AFTER_UNLOCK); - + private final BooleanProperty lockOnSleep = new SimpleBooleanProperty(DEFAULT_LOCK_ON_SLEEP); + private final BooleanProperty lockAfterIdleTime = new SimpleBooleanProperty(DEFAULT_LOCK_AFTER_IDLETIME); + private final StringProperty lockIdleTimeInMinutes = new SimpleStringProperty(DEFAULT_LOCK_IDLETIME_IN_MINUTES); private final StringBinding mountName; public VaultSettings(String id) { @@ -63,7 +66,7 @@ public class VaultSettings { } Observable[] observables() { - return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, filenameLengthLimit, actionAfterUnlock}; + return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, filenameLengthLimit, actionAfterUnlock, lockOnSleep, lockAfterIdleTime, lockIdleTimeInMinutes}; } public static VaultSettings withRandomId() { @@ -164,6 +167,18 @@ public class VaultSettings { return actionAfterUnlock.get(); } + public BooleanProperty lockOnSleep() { + return lockOnSleep; + } + + public BooleanProperty lockAfterIdleTime() { + return lockAfterIdleTime; + } + + public StringProperty lockIdleTimeInMinutes() { + return lockIdleTimeInMinutes; + } + /* Hashcode/Equals */ @Override diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java index 04a352a49..42d0e3b39 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java @@ -31,6 +31,9 @@ class VaultSettingsJsonAdapter { out.name("mountFlags").value(value.mountFlags().get()); out.name("filenameLengthLimit").value(value.filenameLengthLimit().get()); out.name("actionAfterUnlock").value(value.actionAfterUnlock().get().name()); + out.name("lockOnSleep").value(value.lockOnSleep().get()); + out.name("lockAfterIdleTime").value(value.lockAfterIdleTime().get()); + out.name("lockIdleTimeInMinutes").value(value.lockIdleTimeInMinutes().get()); out.endObject(); } @@ -48,6 +51,9 @@ class VaultSettingsJsonAdapter { String mountFlags = VaultSettings.DEFAULT_MOUNT_FLAGS; int filenameLengthLimit = VaultSettings.DEFAULT_FILENAME_LENGTH_LIMIT; WhenUnlocked actionAfterUnlock = VaultSettings.DEFAULT_ACTION_AFTER_UNLOCK; + boolean lockOnSleep = VaultSettings.DEFAULT_LOCK_ON_SLEEP; + boolean lockAfterIdleTime = VaultSettings.DEFAULT_LOCK_AFTER_IDLETIME; + String lockIdleTimeInMinutes = VaultSettings.DEFAULT_LOCK_IDLETIME_IN_MINUTES; in.beginObject(); while (in.hasNext()) { @@ -66,6 +72,9 @@ class VaultSettingsJsonAdapter { case "mountFlags" -> mountFlags = in.nextString(); case "filenameLengthLimit" -> filenameLengthLimit = in.nextInt(); case "actionAfterUnlock" -> actionAfterUnlock = parseActionAfterUnlock(in.nextString()); + case "lockOnSleep" -> lockOnSleep = in.nextBoolean(); + case "lockAfterIdleTime" -> lockAfterIdleTime = in.nextBoolean(); + case "lockIdleTimeInMinutes" -> lockIdleTimeInMinutes = in.nextString(); default -> { LOG.warn("Unsupported vault setting found in JSON: " + name); in.skipValue(); @@ -90,6 +99,9 @@ class VaultSettingsJsonAdapter { vaultSettings.mountFlags().set(mountFlags); vaultSettings.filenameLengthLimit().set(filenameLengthLimit); vaultSettings.actionAfterUnlock().set(actionAfterUnlock); + vaultSettings.lockOnSleep().set(lockOnSleep); + vaultSettings.lockAfterIdleTime().set(lockAfterIdleTime); + vaultSettings.lockIdleTimeInMinutes().set(lockIdleTimeInMinutes); return vaultSettings; } From d13dfe3526f83c5d89d81bd62c0c4afe364b50c1 Mon Sep 17 00:00:00 2001 From: Martin Beyer Date: Wed, 24 Feb 2021 16:23:49 +0100 Subject: [PATCH 03/15] First take at UI implementation of a Auto-Lock Tab --- .../AutoLockVaultOptionsController.java | 37 +++++++++++++++++++ .../fxml/vault_options_autolock.fxml | 14 ++++++- .../main/resources/i18n/strings.properties | 3 ++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java new file mode 100644 index 000000000..24de5c8c1 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java @@ -0,0 +1,37 @@ +package org.cryptomator.ui.vaultoptions; + +import org.cryptomator.common.vaults.Vault; +import org.cryptomator.ui.common.FxController; + +import javax.inject.Inject; + +import javafx.fxml.FXML; +import javafx.scene.control.CheckBox; +import javafx.scene.control.TextField; +import javafx.stage.Stage; + +import java.util.ResourceBundle; + +@VaultOptionsScoped +public class AutoLockVaultOptionsController implements FxController { + + private final Vault vault; + private final Stage window; + public CheckBox lockOnSleepCheckbox; + public CheckBox lockAfterIdleTimeCheckbox; + public TextField lockIdleTimeInMinutesTextField; + + @Inject + AutoLockVaultOptionsController(@VaultOptionsWindow Stage window, @VaultOptionsWindow Vault vault, ResourceBundle resourceBundle) { + this.window = window; + this.vault = vault; + //this.resourceBundle = resourceBundle; + } + + @FXML + public void initialize() { + lockOnSleepCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().lockOnSleep()); + lockAfterIdleTimeCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().lockAfterIdleTime()); + lockIdleTimeInMinutesTextField.textProperty().bindBidirectional(vault.getVaultSettings().lockIdleTimeInMinutes()); + } +} diff --git a/main/ui/src/main/resources/fxml/vault_options_autolock.fxml b/main/ui/src/main/resources/fxml/vault_options_autolock.fxml index 3586def6b..18a91f38d 100644 --- a/main/ui/src/main/resources/fxml/vault_options_autolock.fxml +++ b/main/ui/src/main/resources/fxml/vault_options_autolock.fxml @@ -1,7 +1,11 @@ - + + + + + + + + + + + + + diff --git a/main/ui/src/main/resources/i18n/strings.properties b/main/ui/src/main/resources/i18n/strings.properties index 86972b92c..2ef5d89cc 100644 --- a/main/ui/src/main/resources/i18n/strings.properties +++ b/main/ui/src/main/resources/i18n/strings.properties @@ -294,6 +294,9 @@ vaultOptions.masterkey.showRecoveryKeyBtn=Display Recovery Key vaultOptions.masterkey.recoverPasswordBtn=Recover Password ## Auto Lock vaultOptions.autoLock=Auto-Lock +vaultOptions.autoLock.lockOnSleep=Lock on sleep +vaultOptions.autoLock.lockAfterIdleTime=Lock after computer is idle for x minutes +vaultOptions.autoLock.lockAfterAmountOfIdleTime=Following minutes are set: # Recovery Key recoveryKey.title=Recovery Key From 5a11d02fa80f3c5125809a50820ef81ae24c4a1b Mon Sep 17 00:00:00 2001 From: Martin Beyer Date: Tue, 9 Mar 2021 18:52:53 +0100 Subject: [PATCH 04/15] Splitting the "Lock after X minutes" Checkbox in to two string resources. --- .../resources/fxml/vault_options_autolock.fxml | 16 ++++++++++------ .../src/main/resources/i18n/strings.properties | 3 ++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/main/ui/src/main/resources/fxml/vault_options_autolock.fxml b/main/ui/src/main/resources/fxml/vault_options_autolock.fxml index 18a91f38d..a2f14453f 100644 --- a/main/ui/src/main/resources/fxml/vault_options_autolock.fxml +++ b/main/ui/src/main/resources/fxml/vault_options_autolock.fxml @@ -4,8 +4,9 @@ - + + - - - - - + + + + + + + + diff --git a/main/ui/src/main/resources/i18n/strings.properties b/main/ui/src/main/resources/i18n/strings.properties index 2ef5d89cc..fc66d90ea 100644 --- a/main/ui/src/main/resources/i18n/strings.properties +++ b/main/ui/src/main/resources/i18n/strings.properties @@ -295,7 +295,8 @@ vaultOptions.masterkey.recoverPasswordBtn=Recover Password ## Auto Lock vaultOptions.autoLock=Auto-Lock vaultOptions.autoLock.lockOnSleep=Lock on sleep -vaultOptions.autoLock.lockAfterIdleTime=Lock after computer is idle for x minutes +vaultOptions.autoLock.lockAfterIdleTimePart1=Lock after computer is idle for +vaultOptions.autoLock.lockAfterIdleTimePart2=minutes. vaultOptions.autoLock.lockAfterAmountOfIdleTime=Following minutes are set: # Recovery Key From 8592e3667bff5d59d56d28e386c0ff627ff91a1d Mon Sep 17 00:00:00 2001 From: Martin Beyer Date: Tue, 9 Mar 2021 18:55:35 +0100 Subject: [PATCH 05/15] Applying a SystemListener when the notify gets called with SLEEP --- .../cryptomator/ui/fxapp/FxApplication.java | 56 ++++++++++++++++--- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java index 73c04fe5f..7b1adb47a 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java +++ b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java @@ -1,10 +1,23 @@ package org.cryptomator.ui.fxapp; import dagger.Lazy; +import javafx.application.Application; +import javafx.application.Platform; +import javafx.beans.binding.Bindings; +import javafx.beans.binding.BooleanBinding; +import javafx.beans.value.ObservableValue; +import javafx.collections.ObservableList; +import javafx.stage.Stage; +import javafx.stage.Window; import org.cryptomator.common.LicenseHolder; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.UiTheme; import org.cryptomator.common.vaults.Vault; +import org.cryptomator.common.vaults.VaultListManager; +import org.cryptomator.common.vaults.Volume; +import org.cryptomator.integrations.autolock.AutoLockException; +import org.cryptomator.integrations.autolock.AutoLockProvider; +import org.cryptomator.integrations.autolock.SystemState; import org.cryptomator.integrations.tray.TrayIntegrationProvider; import org.cryptomator.integrations.uiappearance.Theme; import org.cryptomator.integrations.uiappearance.UiAppearanceException; @@ -22,15 +35,9 @@ import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.inject.Provider; -import javafx.application.Application; -import javafx.application.Platform; -import javafx.beans.binding.Bindings; -import javafx.beans.binding.BooleanBinding; -import javafx.beans.value.ObservableValue; -import javafx.collections.ObservableList; -import javafx.stage.Stage; -import javafx.stage.Window; import java.awt.desktop.QuitResponse; +import java.awt.desktop.SystemSleepEvent; +import java.awt.desktop.SystemSleepListener; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -53,9 +60,11 @@ public class FxApplication extends Application { private final ObservableList visibleWindows; private final BooleanBinding hasVisibleWindows; private final UiAppearanceListener systemInterfaceThemeListener = this::systemInterfaceThemeChanged; + private final VaultListManager vaultListManager; + private final Optional autoLockProvider; @Inject - FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, Provider unlockWindowBuilderProvider, Provider lockWindowBuilderProvider, Lazy quitWindow, Optional trayIntegration, Optional appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder) { + FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, Provider unlockWindowBuilderProvider, Provider lockWindowBuilderProvider, Lazy quitWindow, Optional trayIntegration, Optional appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder, VaultListManager vaultListManager, Optional autoLockProvider) { this.settings = settings; this.mainWindow = mainWindow; this.preferencesWindow = preferencesWindow; @@ -68,6 +77,8 @@ public class FxApplication extends Application { this.licenseHolder = licenseHolder; this.visibleWindows = Stage.getWindows().filtered(Window::isShowing); this.hasVisibleWindows = Bindings.isNotEmpty(visibleWindows); + this.vaultListManager = vaultListManager; + this.autoLockProvider = autoLockProvider; } public void start() { @@ -78,6 +89,7 @@ public class FxApplication extends Application { settings.theme().addListener(this::appThemeChanged); loadSelectedStyleSheet(settings.theme().get()); + applySystemListener(); } @Override @@ -192,4 +204,30 @@ public class FxApplication extends Application { }); } + private void applySystemListener() { + autoLockProvider.ifPresent(autoLockProvider -> { + try { + autoLockProvider.addListener(this::systemInterfaceStateChanged); + } catch (AutoLockException e) { + LOG.error("Failed to listen to changing System Power and Lock states."); + } + }); + } + + private void systemInterfaceStateChanged(SystemState systemState) { + vaultListManager.getVaultList().forEach(vault -> { + switch (systemState) { + case SLEEP -> { + if (vault.getVaultSettings().lockOnSleep().get()) { + try { + vault.lock(true); + } catch (Volume.VolumeException e) { + e.printStackTrace(); + } + } + } + } + }); + } + } From 1292548042ea465f534affd8a4d293d42e80df72 Mon Sep 17 00:00:00 2001 From: Martin Beyer Date: Mon, 29 Mar 2021 10:44:39 +0200 Subject: [PATCH 06/15] Implementing new settings and locking after a certain amount of minutes --- .../common/settings/VaultSettings.java | 14 ++++++- .../settings/VaultSettingsJsonAdapter.java | 8 ++++ .../cryptomator/ui/fxapp/FxApplication.java | 38 ++++++++++++++----- .../AutoLockVaultOptionsController.java | 5 ++- .../fxml/vault_options_autolock.fxml | 10 ++++- .../main/resources/i18n/strings.properties | 3 +- 6 files changed, 64 insertions(+), 14 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java index 79d9629ba..c73190f38 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java @@ -40,6 +40,8 @@ public class VaultSettings { public static final boolean DEFAULT_LOCK_ON_SLEEP = false; public static final boolean DEFAULT_LOCK_AFTER_IDLETIME = false; public static final String DEFAULT_LOCK_IDLETIME_IN_MINUTES = "30"; + public static final boolean DEFAULT_LOCK_AFTER_TIME = false; + public static final String DEFAULT_LOCK_TIME_IN_MINUTES = "30"; private static final Random RNG = new Random(); @@ -58,6 +60,8 @@ public class VaultSettings { private final BooleanProperty lockOnSleep = new SimpleBooleanProperty(DEFAULT_LOCK_ON_SLEEP); private final BooleanProperty lockAfterIdleTime = new SimpleBooleanProperty(DEFAULT_LOCK_AFTER_IDLETIME); private final StringProperty lockIdleTimeInMinutes = new SimpleStringProperty(DEFAULT_LOCK_IDLETIME_IN_MINUTES); + private final BooleanProperty lockAfterTime = new SimpleBooleanProperty(DEFAULT_LOCK_AFTER_TIME); + private final StringProperty lockTimeInMinutes = new SimpleStringProperty(DEFAULT_LOCK_TIME_IN_MINUTES); private final StringBinding mountName; public VaultSettings(String id) { @@ -66,7 +70,7 @@ public class VaultSettings { } Observable[] observables() { - return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, filenameLengthLimit, actionAfterUnlock, lockOnSleep, lockAfterIdleTime, lockIdleTimeInMinutes}; + return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, filenameLengthLimit, actionAfterUnlock, lockOnSleep, lockAfterIdleTime, lockIdleTimeInMinutes, lockAfterTime, lockTimeInMinutes}; } public static VaultSettings withRandomId() { @@ -179,6 +183,14 @@ public class VaultSettings { return lockIdleTimeInMinutes; } + public BooleanProperty lockAfterTime() { + return lockAfterTime; + } + + public StringProperty lockTimeInMinutes() { + return lockTimeInMinutes; + } + /* Hashcode/Equals */ @Override diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java index 42d0e3b39..717f2474d 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java @@ -34,6 +34,8 @@ class VaultSettingsJsonAdapter { out.name("lockOnSleep").value(value.lockOnSleep().get()); out.name("lockAfterIdleTime").value(value.lockAfterIdleTime().get()); out.name("lockIdleTimeInMinutes").value(value.lockIdleTimeInMinutes().get()); + out.name("lockAfterTime").value(value.lockAfterTime().get()); + out.name("lockTimeInMinutes").value(value.lockTimeInMinutes().get()); out.endObject(); } @@ -54,6 +56,8 @@ class VaultSettingsJsonAdapter { boolean lockOnSleep = VaultSettings.DEFAULT_LOCK_ON_SLEEP; boolean lockAfterIdleTime = VaultSettings.DEFAULT_LOCK_AFTER_IDLETIME; String lockIdleTimeInMinutes = VaultSettings.DEFAULT_LOCK_IDLETIME_IN_MINUTES; + boolean lockAfterTime = VaultSettings.DEFAULT_LOCK_AFTER_TIME; + String lockTimeInMinutes = VaultSettings.DEFAULT_LOCK_TIME_IN_MINUTES; in.beginObject(); while (in.hasNext()) { @@ -75,6 +79,8 @@ class VaultSettingsJsonAdapter { case "lockOnSleep" -> lockOnSleep = in.nextBoolean(); case "lockAfterIdleTime" -> lockAfterIdleTime = in.nextBoolean(); case "lockIdleTimeInMinutes" -> lockIdleTimeInMinutes = in.nextString(); + case "lockAfterTime" -> lockAfterTime = in.nextBoolean(); + case "lockTimeInMinutes" -> lockTimeInMinutes = in.nextString(); default -> { LOG.warn("Unsupported vault setting found in JSON: " + name); in.skipValue(); @@ -102,6 +108,8 @@ class VaultSettingsJsonAdapter { vaultSettings.lockOnSleep().set(lockOnSleep); vaultSettings.lockAfterIdleTime().set(lockAfterIdleTime); vaultSettings.lockIdleTimeInMinutes().set(lockIdleTimeInMinutes); + vaultSettings.lockAfterTime().set(lockAfterTime); + vaultSettings.lockTimeInMinutes().set(lockTimeInMinutes); return vaultSettings; } diff --git a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java index 7b1adb47a..d49ef2c7e 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java +++ b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java @@ -15,9 +15,9 @@ import org.cryptomator.common.settings.UiTheme; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultListManager; import org.cryptomator.common.vaults.Volume; -import org.cryptomator.integrations.autolock.AutoLockException; -import org.cryptomator.integrations.autolock.AutoLockProvider; -import org.cryptomator.integrations.autolock.SystemState; +//import org.cryptomator.integrations.autolock.AutoLockException; +//import org.cryptomator.integrations.autolock.AutoLockProvider; +//import org.cryptomator.integrations.autolock.SystemState; import org.cryptomator.integrations.tray.TrayIntegrationProvider; import org.cryptomator.integrations.uiappearance.Theme; import org.cryptomator.integrations.uiappearance.UiAppearanceException; @@ -36,8 +36,7 @@ import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.inject.Provider; import java.awt.desktop.QuitResponse; -import java.awt.desktop.SystemSleepEvent; -import java.awt.desktop.SystemSleepListener; +import java.util.Date; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -61,10 +60,12 @@ public class FxApplication extends Application { private final BooleanBinding hasVisibleWindows; private final UiAppearanceListener systemInterfaceThemeListener = this::systemInterfaceThemeChanged; private final VaultListManager vaultListManager; - private final Optional autoLockProvider; + //private final Optional autoLockProvider; @Inject - FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, Provider unlockWindowBuilderProvider, Provider lockWindowBuilderProvider, Lazy quitWindow, Optional trayIntegration, Optional appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder, VaultListManager vaultListManager, Optional autoLockProvider) { + //FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, Provider unlockWindowBuilderProvider, Provider lockWindowBuilderProvider, Lazy quitWindow, Optional trayIntegration, Optional appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder, VaultListManager vaultListManager, Optional autoLockProvider) { + FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, Provider unlockWindowBuilderProvider, Provider lockWindowBuilderProvider, Lazy quitWindow, Optional trayIntegration, Optional appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder, VaultListManager vaultListManager) { + this.settings = settings; this.mainWindow = mainWindow; this.preferencesWindow = preferencesWindow; @@ -78,7 +79,7 @@ public class FxApplication extends Application { this.visibleWindows = Stage.getWindows().filtered(Window::isShowing); this.hasVisibleWindows = Bindings.isNotEmpty(visibleWindows); this.vaultListManager = vaultListManager; - this.autoLockProvider = autoLockProvider; + //this.autoLockProvider = autoLockProvider; } public void start() { @@ -89,7 +90,7 @@ public class FxApplication extends Application { settings.theme().addListener(this::appThemeChanged); loadSelectedStyleSheet(settings.theme().get()); - applySystemListener(); + //applySystemListener(); } @Override @@ -128,6 +129,7 @@ public class FxApplication extends Application { unlockWindowBuilderProvider.get().vault(vault).owner(owner).build().startUnlockWorkflow(); LOG.debug("Showing UnlockWindow for {}", vault.getDisplayName()); }); + checkAutolock(vault, owner); } public void startLockWorkflow(Vault vault, Optional owner) { @@ -204,7 +206,7 @@ public class FxApplication extends Application { }); } - private void applySystemListener() { + /*private void applySystemListener() { autoLockProvider.ifPresent(autoLockProvider -> { try { autoLockProvider.addListener(this::systemInterfaceStateChanged); @@ -229,5 +231,21 @@ public class FxApplication extends Application { } }); } + */ + + public void checkAutolock(Vault vault, Optional owner){ + if (vault.getVaultSettings().lockAfterTime().get()){ //TODO: this is lock after a fixed amount of minutes + LOG.info("Locking after {} minutes", vault.getVaultSettings().lockTimeInMinutes().get()); + new java.util.Timer().schedule( + new java.util.TimerTask() { + @Override + public void run() { + startLockWorkflow(vault, owner); + } + }, + new Date(System.currentTimeMillis() + Integer.parseInt(vault.getVaultSettings().lockTimeInMinutes().get()) * 60 * 1000) + ); + } + } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java index 24de5c8c1..722dcab97 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java @@ -19,13 +19,14 @@ public class AutoLockVaultOptionsController implements FxController { private final Stage window; public CheckBox lockOnSleepCheckbox; public CheckBox lockAfterIdleTimeCheckbox; + public CheckBox lockAfterTimeCheckbox; public TextField lockIdleTimeInMinutesTextField; + public TextField lockTimeInMinutesTextField; @Inject AutoLockVaultOptionsController(@VaultOptionsWindow Stage window, @VaultOptionsWindow Vault vault, ResourceBundle resourceBundle) { this.window = window; this.vault = vault; - //this.resourceBundle = resourceBundle; } @FXML @@ -33,5 +34,7 @@ public class AutoLockVaultOptionsController implements FxController { lockOnSleepCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().lockOnSleep()); lockAfterIdleTimeCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().lockAfterIdleTime()); lockIdleTimeInMinutesTextField.textProperty().bindBidirectional(vault.getVaultSettings().lockIdleTimeInMinutes()); + lockAfterTimeCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().lockAfterTime()); + lockTimeInMinutesTextField.textProperty().bindBidirectional(vault.getVaultSettings().lockTimeInMinutes()); } } diff --git a/main/ui/src/main/resources/fxml/vault_options_autolock.fxml b/main/ui/src/main/resources/fxml/vault_options_autolock.fxml index a2f14453f..466d4d21b 100644 --- a/main/ui/src/main/resources/fxml/vault_options_autolock.fxml +++ b/main/ui/src/main/resources/fxml/vault_options_autolock.fxml @@ -15,11 +15,19 @@ + + + + + + + + - + diff --git a/main/ui/src/main/resources/i18n/strings.properties b/main/ui/src/main/resources/i18n/strings.properties index fc66d90ea..31311fc2a 100644 --- a/main/ui/src/main/resources/i18n/strings.properties +++ b/main/ui/src/main/resources/i18n/strings.properties @@ -297,7 +297,8 @@ vaultOptions.autoLock=Auto-Lock vaultOptions.autoLock.lockOnSleep=Lock on sleep vaultOptions.autoLock.lockAfterIdleTimePart1=Lock after computer is idle for vaultOptions.autoLock.lockAfterIdleTimePart2=minutes. -vaultOptions.autoLock.lockAfterAmountOfIdleTime=Following minutes are set: +vaultOptions.autoLock.lockAfterTimePart1=Lock after +vaultOptions.autoLock.lockAfterTimePart2=minutes. # Recovery Key recoveryKey.title=Recovery Key From 1c35780d9ec99714edd43efcf15b3214ec20d686 Mon Sep 17 00:00:00 2001 From: Martin Beyer Date: Mon, 29 Mar 2021 19:10:05 +0200 Subject: [PATCH 07/15] Cleaned up integrations implementation and added Regex for input --- .../common/settings/VaultSettings.java | 20 +-------- .../settings/VaultSettingsJsonAdapter.java | 12 ------ .../cryptomator/ui/fxapp/FxApplication.java | 41 ++----------------- .../AutoLockVaultOptionsController.java | 17 +++++--- 4 files changed, 16 insertions(+), 74 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java index faca30b94..5b828380d 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java @@ -37,9 +37,6 @@ public class VaultSettings { public static final String DEFAULT_MOUNT_FLAGS = ""; public static final int DEFAULT_FILENAME_LENGTH_LIMIT = -1; public static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK; - public static final boolean DEFAULT_LOCK_ON_SLEEP = false; - public static final boolean DEFAULT_LOCK_AFTER_IDLETIME = false; - public static final String DEFAULT_LOCK_IDLETIME_IN_MINUTES = "30"; public static final boolean DEFAULT_LOCK_AFTER_TIME = false; public static final String DEFAULT_LOCK_TIME_IN_MINUTES = "30"; @@ -57,9 +54,6 @@ public class VaultSettings { private final StringProperty mountFlags = new SimpleStringProperty(DEFAULT_MOUNT_FLAGS); private final IntegerProperty filenameLengthLimit = new SimpleIntegerProperty(DEFAULT_FILENAME_LENGTH_LIMIT); private final ObjectProperty actionAfterUnlock = new SimpleObjectProperty<>(DEFAULT_ACTION_AFTER_UNLOCK); - private final BooleanProperty lockOnSleep = new SimpleBooleanProperty(DEFAULT_LOCK_ON_SLEEP); - private final BooleanProperty lockAfterIdleTime = new SimpleBooleanProperty(DEFAULT_LOCK_AFTER_IDLETIME); - private final StringProperty lockIdleTimeInMinutes = new SimpleStringProperty(DEFAULT_LOCK_IDLETIME_IN_MINUTES); private final BooleanProperty lockAfterTime = new SimpleBooleanProperty(DEFAULT_LOCK_AFTER_TIME); private final StringProperty lockTimeInMinutes = new SimpleStringProperty(DEFAULT_LOCK_TIME_IN_MINUTES); private final StringBinding mountName; @@ -70,7 +64,7 @@ public class VaultSettings { } Observable[] observables() { - return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, filenameLengthLimit, actionAfterUnlock, lockOnSleep, lockAfterIdleTime, lockIdleTimeInMinutes, lockAfterTime, lockTimeInMinutes}; + return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, filenameLengthLimit, actionAfterUnlock, lockAfterTime, lockTimeInMinutes}; } public static VaultSettings withRandomId() { @@ -171,18 +165,6 @@ public class VaultSettings { return actionAfterUnlock.get(); } - public BooleanProperty lockOnSleep() { - return lockOnSleep; - } - - public BooleanProperty lockAfterIdleTime() { - return lockAfterIdleTime; - } - - public StringProperty lockIdleTimeInMinutes() { - return lockIdleTimeInMinutes; - } - public BooleanProperty lockAfterTime() { return lockAfterTime; } diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java index 717f2474d..a32956411 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java @@ -31,9 +31,6 @@ class VaultSettingsJsonAdapter { out.name("mountFlags").value(value.mountFlags().get()); out.name("filenameLengthLimit").value(value.filenameLengthLimit().get()); out.name("actionAfterUnlock").value(value.actionAfterUnlock().get().name()); - out.name("lockOnSleep").value(value.lockOnSleep().get()); - out.name("lockAfterIdleTime").value(value.lockAfterIdleTime().get()); - out.name("lockIdleTimeInMinutes").value(value.lockIdleTimeInMinutes().get()); out.name("lockAfterTime").value(value.lockAfterTime().get()); out.name("lockTimeInMinutes").value(value.lockTimeInMinutes().get()); out.endObject(); @@ -53,9 +50,6 @@ class VaultSettingsJsonAdapter { String mountFlags = VaultSettings.DEFAULT_MOUNT_FLAGS; int filenameLengthLimit = VaultSettings.DEFAULT_FILENAME_LENGTH_LIMIT; WhenUnlocked actionAfterUnlock = VaultSettings.DEFAULT_ACTION_AFTER_UNLOCK; - boolean lockOnSleep = VaultSettings.DEFAULT_LOCK_ON_SLEEP; - boolean lockAfterIdleTime = VaultSettings.DEFAULT_LOCK_AFTER_IDLETIME; - String lockIdleTimeInMinutes = VaultSettings.DEFAULT_LOCK_IDLETIME_IN_MINUTES; boolean lockAfterTime = VaultSettings.DEFAULT_LOCK_AFTER_TIME; String lockTimeInMinutes = VaultSettings.DEFAULT_LOCK_TIME_IN_MINUTES; @@ -76,9 +70,6 @@ class VaultSettingsJsonAdapter { case "mountFlags" -> mountFlags = in.nextString(); case "filenameLengthLimit" -> filenameLengthLimit = in.nextInt(); case "actionAfterUnlock" -> actionAfterUnlock = parseActionAfterUnlock(in.nextString()); - case "lockOnSleep" -> lockOnSleep = in.nextBoolean(); - case "lockAfterIdleTime" -> lockAfterIdleTime = in.nextBoolean(); - case "lockIdleTimeInMinutes" -> lockIdleTimeInMinutes = in.nextString(); case "lockAfterTime" -> lockAfterTime = in.nextBoolean(); case "lockTimeInMinutes" -> lockTimeInMinutes = in.nextString(); default -> { @@ -105,9 +96,6 @@ class VaultSettingsJsonAdapter { vaultSettings.mountFlags().set(mountFlags); vaultSettings.filenameLengthLimit().set(filenameLengthLimit); vaultSettings.actionAfterUnlock().set(actionAfterUnlock); - vaultSettings.lockOnSleep().set(lockOnSleep); - vaultSettings.lockAfterIdleTime().set(lockAfterIdleTime); - vaultSettings.lockIdleTimeInMinutes().set(lockIdleTimeInMinutes); vaultSettings.lockAfterTime().set(lockAfterTime); vaultSettings.lockTimeInMinutes().set(lockTimeInMinutes); return vaultSettings; diff --git a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java index d49ef2c7e..400760e2d 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java +++ b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java @@ -15,9 +15,6 @@ import org.cryptomator.common.settings.UiTheme; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultListManager; import org.cryptomator.common.vaults.Volume; -//import org.cryptomator.integrations.autolock.AutoLockException; -//import org.cryptomator.integrations.autolock.AutoLockProvider; -//import org.cryptomator.integrations.autolock.SystemState; import org.cryptomator.integrations.tray.TrayIntegrationProvider; import org.cryptomator.integrations.uiappearance.Theme; import org.cryptomator.integrations.uiappearance.UiAppearanceException; @@ -60,12 +57,9 @@ public class FxApplication extends Application { private final BooleanBinding hasVisibleWindows; private final UiAppearanceListener systemInterfaceThemeListener = this::systemInterfaceThemeChanged; private final VaultListManager vaultListManager; - //private final Optional autoLockProvider; @Inject - //FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, Provider unlockWindowBuilderProvider, Provider lockWindowBuilderProvider, Lazy quitWindow, Optional trayIntegration, Optional appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder, VaultListManager vaultListManager, Optional autoLockProvider) { FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, Provider unlockWindowBuilderProvider, Provider lockWindowBuilderProvider, Lazy quitWindow, Optional trayIntegration, Optional appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder, VaultListManager vaultListManager) { - this.settings = settings; this.mainWindow = mainWindow; this.preferencesWindow = preferencesWindow; @@ -79,7 +73,6 @@ public class FxApplication extends Application { this.visibleWindows = Stage.getWindows().filtered(Window::isShowing); this.hasVisibleWindows = Bindings.isNotEmpty(visibleWindows); this.vaultListManager = vaultListManager; - //this.autoLockProvider = autoLockProvider; } public void start() { @@ -90,7 +83,6 @@ public class FxApplication extends Application { settings.theme().addListener(this::appThemeChanged); loadSelectedStyleSheet(settings.theme().get()); - //applySystemListener(); } @Override @@ -206,36 +198,11 @@ public class FxApplication extends Application { }); } - /*private void applySystemListener() { - autoLockProvider.ifPresent(autoLockProvider -> { - try { - autoLockProvider.addListener(this::systemInterfaceStateChanged); - } catch (AutoLockException e) { - LOG.error("Failed to listen to changing System Power and Lock states."); - } - }); - } - private void systemInterfaceStateChanged(SystemState systemState) { - vaultListManager.getVaultList().forEach(vault -> { - switch (systemState) { - case SLEEP -> { - if (vault.getVaultSettings().lockOnSleep().get()) { - try { - vault.lock(true); - } catch (Volume.VolumeException e) { - e.printStackTrace(); - } - } - } - } - }); - } - */ - public void checkAutolock(Vault vault, Optional owner){ - if (vault.getVaultSettings().lockAfterTime().get()){ //TODO: this is lock after a fixed amount of minutes - LOG.info("Locking after {} minutes", vault.getVaultSettings().lockTimeInMinutes().get()); + private void checkAutolock(Vault vault, Optional owner){ + if (vault.getVaultSettings().lockAfterTime().get()){ + LOG.info("Locking after {} minutes.", vault.getVaultSettings().lockTimeInMinutes().get()); new java.util.Timer().schedule( new java.util.TimerTask() { @Override @@ -243,7 +210,7 @@ public class FxApplication extends Application { startLockWorkflow(vault, owner); } }, - new Date(System.currentTimeMillis() + Integer.parseInt(vault.getVaultSettings().lockTimeInMinutes().get()) * 60 * 1000) + new Date(System.currentTimeMillis() + (int)(Double.parseDouble(vault.getVaultSettings().lockTimeInMinutes().get()) * 60 * 1000)) ); } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java index 722dcab97..21af0c3d9 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java @@ -5,6 +5,8 @@ import org.cryptomator.ui.common.FxController; import javax.inject.Inject; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; import javafx.scene.control.TextField; @@ -17,10 +19,7 @@ public class AutoLockVaultOptionsController implements FxController { private final Vault vault; private final Stage window; - public CheckBox lockOnSleepCheckbox; - public CheckBox lockAfterIdleTimeCheckbox; public CheckBox lockAfterTimeCheckbox; - public TextField lockIdleTimeInMinutesTextField; public TextField lockTimeInMinutesTextField; @Inject @@ -31,10 +30,16 @@ public class AutoLockVaultOptionsController implements FxController { @FXML public void initialize() { - lockOnSleepCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().lockOnSleep()); - lockAfterIdleTimeCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().lockAfterIdleTime()); - lockIdleTimeInMinutesTextField.textProperty().bindBidirectional(vault.getVaultSettings().lockIdleTimeInMinutes()); lockAfterTimeCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().lockAfterTime()); lockTimeInMinutesTextField.textProperty().bindBidirectional(vault.getVaultSettings().lockTimeInMinutes()); + //force the field to be a double with the correct decimal point + lockTimeInMinutesTextField.textProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, String oldValue, String newValue) { + if (!newValue.matches("\\d{0,9}([\\.]\\d{0,9})?")) { + lockTimeInMinutesTextField.setText(newValue.replaceAll("[^\\d]", "")); + } + } + }); } } From 1c012287787ea1b2c4641f7734dd5b0ffd37741b Mon Sep 17 00:00:00 2001 From: Martin Beyer Date: Mon, 29 Mar 2021 19:29:17 +0200 Subject: [PATCH 08/15] Removing LockOnSleep UI elements (not implemented yet) --- .../main/resources/fxml/vault_options_autolock.fxml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/main/ui/src/main/resources/fxml/vault_options_autolock.fxml b/main/ui/src/main/resources/fxml/vault_options_autolock.fxml index 466d4d21b..e7c120fb9 100644 --- a/main/ui/src/main/resources/fxml/vault_options_autolock.fxml +++ b/main/ui/src/main/resources/fxml/vault_options_autolock.fxml @@ -22,15 +22,5 @@ - - - - - - - - - - From 92de05b3db77a3ace436edca66ef6276c4cca9a1 Mon Sep 17 00:00:00 2001 From: Martin Beyer Date: Thu, 1 Apr 2021 11:42:41 +0200 Subject: [PATCH 09/15] Changed textfield to only accept Integers, Using scheduled Executor as Timer --- .../common/settings/VaultSettings.java | 15 +++-------- .../settings/VaultSettingsJsonAdapter.java | 4 +-- .../cryptomator/ui/fxapp/FxApplication.java | 25 ++++++++----------- .../AutoLockVaultOptionsController.java | 7 +++--- .../main/resources/i18n/strings.properties | 3 --- 5 files changed, 20 insertions(+), 34 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java index 5b828380d..1b93d0901 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java @@ -11,14 +11,7 @@ import com.google.common.io.BaseEncoding; import javafx.beans.Observable; import javafx.beans.binding.Bindings; import javafx.beans.binding.StringBinding; -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.IntegerProperty; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleBooleanProperty; -import javafx.beans.property.SimpleIntegerProperty; -import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.property.StringProperty; +import javafx.beans.property.*; import java.nio.file.Path; import java.util.Objects; @@ -38,7 +31,7 @@ public class VaultSettings { public static final int DEFAULT_FILENAME_LENGTH_LIMIT = -1; public static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK; public static final boolean DEFAULT_LOCK_AFTER_TIME = false; - public static final String DEFAULT_LOCK_TIME_IN_MINUTES = "30"; + public static final int DEFAULT_LOCK_TIME_IN_MINUTES = 30; private static final Random RNG = new Random(); @@ -55,7 +48,7 @@ public class VaultSettings { private final IntegerProperty filenameLengthLimit = new SimpleIntegerProperty(DEFAULT_FILENAME_LENGTH_LIMIT); private final ObjectProperty actionAfterUnlock = new SimpleObjectProperty<>(DEFAULT_ACTION_AFTER_UNLOCK); private final BooleanProperty lockAfterTime = new SimpleBooleanProperty(DEFAULT_LOCK_AFTER_TIME); - private final StringProperty lockTimeInMinutes = new SimpleStringProperty(DEFAULT_LOCK_TIME_IN_MINUTES); + private final IntegerProperty lockTimeInMinutes = new SimpleIntegerProperty(DEFAULT_LOCK_TIME_IN_MINUTES); private final StringBinding mountName; public VaultSettings(String id) { @@ -169,7 +162,7 @@ public class VaultSettings { return lockAfterTime; } - public StringProperty lockTimeInMinutes() { + public IntegerProperty lockTimeInMinutes() { return lockTimeInMinutes; } diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java index a32956411..ffff021e2 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java @@ -51,7 +51,7 @@ class VaultSettingsJsonAdapter { int filenameLengthLimit = VaultSettings.DEFAULT_FILENAME_LENGTH_LIMIT; WhenUnlocked actionAfterUnlock = VaultSettings.DEFAULT_ACTION_AFTER_UNLOCK; boolean lockAfterTime = VaultSettings.DEFAULT_LOCK_AFTER_TIME; - String lockTimeInMinutes = VaultSettings.DEFAULT_LOCK_TIME_IN_MINUTES; + int lockTimeInMinutes = VaultSettings.DEFAULT_LOCK_TIME_IN_MINUTES; in.beginObject(); while (in.hasNext()) { @@ -71,7 +71,7 @@ class VaultSettingsJsonAdapter { case "filenameLengthLimit" -> filenameLengthLimit = in.nextInt(); case "actionAfterUnlock" -> actionAfterUnlock = parseActionAfterUnlock(in.nextString()); case "lockAfterTime" -> lockAfterTime = in.nextBoolean(); - case "lockTimeInMinutes" -> lockTimeInMinutes = in.nextString(); + case "lockTimeInMinutes" -> lockTimeInMinutes = in.nextInt(); default -> { LOG.warn("Unsupported vault setting found in JSON: " + name); in.skipValue(); diff --git a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java index 400760e2d..cc6e97d72 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java +++ b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java @@ -14,7 +14,6 @@ import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.UiTheme; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultListManager; -import org.cryptomator.common.vaults.Volume; import org.cryptomator.integrations.tray.TrayIntegrationProvider; import org.cryptomator.integrations.uiappearance.Theme; import org.cryptomator.integrations.uiappearance.UiAppearanceException; @@ -33,10 +32,11 @@ import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.inject.Provider; import java.awt.desktop.QuitResponse; -import java.util.Date; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; @FxApplicationScoped public class FxApplication extends Application { @@ -57,9 +57,10 @@ public class FxApplication extends Application { private final BooleanBinding hasVisibleWindows; private final UiAppearanceListener systemInterfaceThemeListener = this::systemInterfaceThemeChanged; private final VaultListManager vaultListManager; + private final ScheduledExecutorService scheduledExecutorService; @Inject - FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, Provider unlockWindowBuilderProvider, Provider lockWindowBuilderProvider, Lazy quitWindow, Optional trayIntegration, Optional appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder, VaultListManager vaultListManager) { + FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, Provider unlockWindowBuilderProvider, Provider lockWindowBuilderProvider, Lazy quitWindow, Optional trayIntegration, Optional appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder, VaultListManager vaultListManager, ScheduledExecutorService scheduledExecutorService) { this.settings = settings; this.mainWindow = mainWindow; this.preferencesWindow = preferencesWindow; @@ -73,6 +74,7 @@ public class FxApplication extends Application { this.visibleWindows = Stage.getWindows().filtered(Window::isShowing); this.hasVisibleWindows = Bindings.isNotEmpty(visibleWindows); this.vaultListManager = vaultListManager; + this.scheduledExecutorService = scheduledExecutorService; } public void start() { @@ -199,19 +201,12 @@ public class FxApplication extends Application { } - - private void checkAutolock(Vault vault, Optional owner){ - if (vault.getVaultSettings().lockAfterTime().get()){ + private void checkAutolock(Vault vault, Optional owner) { + if (vault.getVaultSettings().lockAfterTime().get()) { LOG.info("Locking after {} minutes.", vault.getVaultSettings().lockTimeInMinutes().get()); - new java.util.Timer().schedule( - new java.util.TimerTask() { - @Override - public void run() { - startLockWorkflow(vault, owner); - } - }, - new Date(System.currentTimeMillis() + (int)(Double.parseDouble(vault.getVaultSettings().lockTimeInMinutes().get()) * 60 * 1000)) - ); + scheduledExecutorService.schedule(() -> { + startLockWorkflow(vault, owner); + }, (long) (vault.getVaultSettings().lockTimeInMinutes().get()), TimeUnit.MINUTES); } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java index 21af0c3d9..906a40ba3 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java @@ -5,12 +5,14 @@ import org.cryptomator.ui.common.FxController; import javax.inject.Inject; +import javafx.beans.binding.Bindings; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; import javafx.scene.control.TextField; import javafx.stage.Stage; +import javafx.util.converter.NumberStringConverter; import java.util.ResourceBundle; @@ -31,12 +33,11 @@ public class AutoLockVaultOptionsController implements FxController { @FXML public void initialize() { lockAfterTimeCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().lockAfterTime()); - lockTimeInMinutesTextField.textProperty().bindBidirectional(vault.getVaultSettings().lockTimeInMinutes()); - //force the field to be a double with the correct decimal point + Bindings.bindBidirectional(lockTimeInMinutesTextField.textProperty(), vault.getVaultSettings().lockTimeInMinutes(), new NumberStringConverter()); lockTimeInMinutesTextField.textProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, String oldValue, String newValue) { - if (!newValue.matches("\\d{0,9}([\\.]\\d{0,9})?")) { + if (!newValue.matches("\\d{0,9}")) { lockTimeInMinutesTextField.setText(newValue.replaceAll("[^\\d]", "")); } } diff --git a/main/ui/src/main/resources/i18n/strings.properties b/main/ui/src/main/resources/i18n/strings.properties index 31311fc2a..d429d29b5 100644 --- a/main/ui/src/main/resources/i18n/strings.properties +++ b/main/ui/src/main/resources/i18n/strings.properties @@ -294,9 +294,6 @@ vaultOptions.masterkey.showRecoveryKeyBtn=Display Recovery Key vaultOptions.masterkey.recoverPasswordBtn=Recover Password ## Auto Lock vaultOptions.autoLock=Auto-Lock -vaultOptions.autoLock.lockOnSleep=Lock on sleep -vaultOptions.autoLock.lockAfterIdleTimePart1=Lock after computer is idle for -vaultOptions.autoLock.lockAfterIdleTimePart2=minutes. vaultOptions.autoLock.lockAfterTimePart1=Lock after vaultOptions.autoLock.lockAfterTimePart2=minutes. From cd7acea54e9dc6b95ae02839ff96f9bf35f83d2a Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 2 Jun 2021 14:52:27 +0200 Subject: [PATCH 10/15] Use of NumericTextField --- .../AutoLockVaultOptionsController.java | 23 ++++--------------- .../fxml/vault_options_autolock.fxml | 4 ++-- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java index 906a40ba3..e8e5ca5fb 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java @@ -2,31 +2,23 @@ package org.cryptomator.ui.vaultoptions; import org.cryptomator.common.vaults.Vault; import org.cryptomator.ui.common.FxController; +import org.cryptomator.ui.controls.NumericTextField; import javax.inject.Inject; - import javafx.beans.binding.Bindings; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; -import javafx.scene.control.TextField; -import javafx.stage.Stage; import javafx.util.converter.NumberStringConverter; -import java.util.ResourceBundle; - @VaultOptionsScoped public class AutoLockVaultOptionsController implements FxController { private final Vault vault; - private final Stage window; public CheckBox lockAfterTimeCheckbox; - public TextField lockTimeInMinutesTextField; + public NumericTextField lockTimeInMinutesTextField; @Inject - AutoLockVaultOptionsController(@VaultOptionsWindow Stage window, @VaultOptionsWindow Vault vault, ResourceBundle resourceBundle) { - this.window = window; + AutoLockVaultOptionsController(@VaultOptionsWindow Vault vault) { this.vault = vault; } @@ -34,13 +26,6 @@ public class AutoLockVaultOptionsController implements FxController { public void initialize() { lockAfterTimeCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().lockAfterTime()); Bindings.bindBidirectional(lockTimeInMinutesTextField.textProperty(), vault.getVaultSettings().lockTimeInMinutes(), new NumberStringConverter()); - lockTimeInMinutesTextField.textProperty().addListener(new ChangeListener() { - @Override - public void changed(ObservableValue observable, String oldValue, String newValue) { - if (!newValue.matches("\\d{0,9}")) { - lockTimeInMinutesTextField.setText(newValue.replaceAll("[^\\d]", "")); - } - } - }); } + } diff --git a/main/ui/src/main/resources/fxml/vault_options_autolock.fxml b/main/ui/src/main/resources/fxml/vault_options_autolock.fxml index e7c120fb9..8d63b792d 100644 --- a/main/ui/src/main/resources/fxml/vault_options_autolock.fxml +++ b/main/ui/src/main/resources/fxml/vault_options_autolock.fxml @@ -1,9 +1,9 @@ + - @@ -18,7 +18,7 @@ - + From 8f8fa0248ccb035a644d98261adb5e5266048aa8 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 2 Jun 2021 15:53:57 +0200 Subject: [PATCH 11/15] converted lock after "time" to "idle time" --- .../org/cryptomator/common/CommonsModule.java | 9 +-- .../cryptomator/common/vaults/AutoLocker.java | 62 +++++++++++++++++++ .../common/vaults/VaultListManager.java | 11 ++-- .../common/vaults/VaultListModule.java | 19 ++++++ .../cryptomator/common/vaults/VaultStats.java | 18 ++++++ .../cryptomator/ui/fxapp/FxApplication.java | 17 +---- .../main/resources/i18n/strings.properties | 4 +- 7 files changed, 109 insertions(+), 31 deletions(-) create mode 100644 main/commons/src/main/java/org/cryptomator/common/vaults/AutoLocker.java create mode 100644 main/commons/src/main/java/org/cryptomator/common/vaults/VaultListModule.java diff --git a/main/commons/src/main/java/org/cryptomator/common/CommonsModule.java b/main/commons/src/main/java/org/cryptomator/common/CommonsModule.java index f8e0e8078..705f98b8f 100644 --- a/main/commons/src/main/java/org/cryptomator/common/CommonsModule.java +++ b/main/commons/src/main/java/org/cryptomator/common/CommonsModule.java @@ -15,6 +15,7 @@ import org.cryptomator.common.settings.SettingsProvider; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultComponent; import org.cryptomator.common.vaults.VaultListManager; +import org.cryptomator.common.vaults.VaultListModule; import org.cryptomator.cryptolib.common.MasterkeyFileAccess; import org.cryptomator.frontend.webdav.WebDavServer; import org.slf4j.Logger; @@ -37,7 +38,7 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -@Module(subcomponents = {VaultComponent.class}, includes = {KeychainModule.class}) +@Module(subcomponents = {VaultComponent.class}, includes = {VaultListModule.class, KeychainModule.class}) public abstract class CommonsModule { private static final Logger LOG = LoggerFactory.getLogger(CommonsModule.class); @@ -87,12 +88,6 @@ public abstract class CommonsModule { return settingsProvider.get(); } - @Provides - @Singleton - static ObservableList provideVaultList(VaultListManager vaultListManager) { - return vaultListManager.getVaultList(); - } - @Provides @Singleton static ScheduledExecutorService provideScheduledExecutorService(ShutdownHook shutdownHook) { diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/AutoLocker.java b/main/commons/src/main/java/org/cryptomator/common/vaults/AutoLocker.java new file mode 100644 index 000000000..dcaafdb13 --- /dev/null +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/AutoLocker.java @@ -0,0 +1,62 @@ +package org.cryptomator.common.vaults; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import javax.inject.Singleton; +import javafx.collections.ObservableList; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +@Singleton +public class AutoLocker { + + private static final Logger LOG = LoggerFactory.getLogger(AutoLocker.class); + + private final ScheduledExecutorService scheduler; + private final ObservableList vaultList; + + @Inject + public AutoLocker(ScheduledExecutorService scheduler, ObservableList vaultList) { + this.scheduler = scheduler; + this.vaultList = vaultList; + } + + public void init() { + scheduler.scheduleAtFixedRate(this::tick, 0, 1, TimeUnit.MINUTES); + } + + private void tick() { + vaultList.stream() // all vaults + .filter(Vault::isUnlocked) // unlocked vaults + .filter(this::exceedsIdleTime) // idle vaults + .forEach(this::autolock); + } + + private void autolock(Vault vault) { + try { + vault.lock(false); + LOG.info("Autolocked {} after idle timeout", vault.getDisplayName()); + } catch (Volume.VolumeException | LockNotCompletedException e) { + LOG.error("Autolocking failed.", e); + } + } + + private boolean exceedsIdleTime(Vault vault) { + assert vault.isUnlocked(); + // TODO: shouldn't we read these properties from within FX Application Thread? + if (vault.getVaultSettings().lockAfterTime().get()) { + int maxIdleMinutes = vault.getVaultSettings().lockTimeInMinutes().get(); + var idleSince = vault.getStats().getLastActivity(); + var threshold = idleSince.plus(maxIdleMinutes, ChronoUnit.MINUTES); + return threshold.isBefore(Instant.now()); + } else { + return false; + } + } + + +} diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/VaultListManager.java b/main/commons/src/main/java/org/cryptomator/common/vaults/VaultListManager.java index d5038630a..05ea8ce07 100644 --- a/main/commons/src/main/java/org/cryptomator/common/vaults/VaultListManager.java +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/VaultListManager.java @@ -37,22 +37,21 @@ public class VaultListManager { private static final Logger LOG = LoggerFactory.getLogger(VaultListManager.class); + private final AutoLocker autoLocker; private final VaultComponent.Builder vaultComponentBuilder; private final ObservableList vaultList; private final String defaultVaultName; @Inject - public VaultListManager(VaultComponent.Builder vaultComponentBuilder, ResourceBundle resourceBundle, Settings settings) { + public VaultListManager(ObservableList vaultList, AutoLocker autoLocker, VaultComponent.Builder vaultComponentBuilder, ResourceBundle resourceBundle, Settings settings) { + this.vaultList = vaultList; + this.autoLocker = autoLocker; this.vaultComponentBuilder = vaultComponentBuilder; this.defaultVaultName = resourceBundle.getString("defaults.vault.vaultName"); - this.vaultList = FXCollections.observableArrayList(Vault::observables); addAll(settings.getDirectories()); vaultList.addListener(new VaultListChangeListener(settings.getDirectories())); - } - - public ObservableList getVaultList() { - return vaultList; + autoLocker.init(); } public Vault add(Path pathToVault) throws IOException { diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/VaultListModule.java b/main/commons/src/main/java/org/cryptomator/common/vaults/VaultListModule.java new file mode 100644 index 000000000..644d05335 --- /dev/null +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/VaultListModule.java @@ -0,0 +1,19 @@ +package org.cryptomator.common.vaults; + +import dagger.Module; +import dagger.Provides; + +import javax.inject.Singleton; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +@Module +public class VaultListModule { + + @Provides + @Singleton + public ObservableList provideVaultList() { + return FXCollections.observableArrayList(Vault::observables); + } + +} diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/VaultStats.java b/main/commons/src/main/java/org/cryptomator/common/vaults/VaultStats.java index 6dc86e8be..64205a0f2 100644 --- a/main/commons/src/main/java/org/cryptomator/common/vaults/VaultStats.java +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/VaultStats.java @@ -13,9 +13,11 @@ import javafx.beans.property.LongProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.SimpleLongProperty; +import javafx.beans.property.SimpleObjectProperty; import javafx.concurrent.ScheduledService; import javafx.concurrent.Task; import javafx.util.Duration; +import java.time.Instant; import java.util.Optional; import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicReference; @@ -39,6 +41,7 @@ public class VaultStats { private final LongProperty totalBytesDecrypted = new SimpleLongProperty(); private final LongProperty filesRead = new SimpleLongProperty(); private final LongProperty filesWritten = new SimpleLongProperty(); + private final ObjectProperty lastActivity = new SimpleObjectProperty<>(); @Inject VaultStats(AtomicReference fs, VaultState state, ExecutorService executor) { @@ -73,9 +76,16 @@ public class VaultStats { toalBytesWritten.set(stats.map(CryptoFileSystemStats::pollTotalBytesWritten).orElse(0L)); totalBytesEncrypted.set(stats.map(CryptoFileSystemStats::pollTotalBytesEncrypted).orElse(0L)); totalBytesDecrypted.set(stats.map(CryptoFileSystemStats::pollTotalBytesDecrypted).orElse(0L)); + var oldAccessCount = filesRead.get() + filesWritten.get(); filesRead.set(stats.map(CryptoFileSystemStats::pollAmountOfAccessesRead).orElse(0L)); filesWritten.set(stats.map(CryptoFileSystemStats::pollAmountOfAccessesWritten).orElse(0L)); + var newAccessCount = filesRead.get() + filesWritten.get(); + // check for any I/O activity + if (newAccessCount > oldAccessCount) { + LOG.info("ACTIVITY!"); + lastActivity.set(Instant.now()); + } } private double getCacheHitRate(CryptoFileSystemStats stats) { @@ -175,4 +185,12 @@ public class VaultStats { public LongProperty filesWritten() {return filesWritten;} public long getFilesWritten() {return filesWritten.get();} + + public ObjectProperty lastActivityProperty() { + return lastActivity; + } + + public Instant getLastActivity() { + return lastActivity.get(); + } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java index a19a13bf1..02a2e5b9e 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java +++ b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java @@ -59,11 +59,9 @@ public class FxApplication extends Application { private final ObservableList visibleWindows; private final BooleanBinding hasVisibleWindows; private final UiAppearanceListener systemInterfaceThemeListener = this::systemInterfaceThemeChanged; - private final VaultListManager vaultListManager; - private final ScheduledExecutorService scheduledExecutorService; @Inject - FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, Provider unlockWorkflowBuilderProvider, Provider lockWorkflowBuilderProvider, Lazy quitWindow, ErrorComponent.Builder errorWindowBuilder, Optional trayIntegration, Optional appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder, VaultListManager vaultListManager, ScheduledExecutorService scheduledExecutorService) { + FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, Provider unlockWorkflowBuilderProvider, Provider lockWorkflowBuilderProvider, Lazy quitWindow, ErrorComponent.Builder errorWindowBuilder, Optional trayIntegration, Optional appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder) { this.settings = settings; this.mainWindow = mainWindow; this.preferencesWindow = preferencesWindow; @@ -77,8 +75,6 @@ public class FxApplication extends Application { this.licenseHolder = licenseHolder; this.visibleWindows = Stage.getWindows().filtered(Window::isShowing); this.hasVisibleWindows = Bindings.isNotEmpty(visibleWindows); - this.vaultListManager = vaultListManager; - this.scheduledExecutorService = scheduledExecutorService; } public void start() { @@ -131,7 +127,6 @@ public class FxApplication extends Application { showMainWindow().thenAccept(mainWindow -> errorWindowBuilder.window(mainWindow).cause(new IllegalStateException("Unable to unlock vault in non-locked state."))); } }); - checkAutolock(vault, owner); } public void startLockWorkflow(Vault vault, Optional owner) { @@ -212,14 +207,4 @@ public class FxApplication extends Application { }); } - - private void checkAutolock(Vault vault, Optional owner) { - if (vault.getVaultSettings().lockAfterTime().get()) { - LOG.info("Locking after {} minutes.", vault.getVaultSettings().lockTimeInMinutes().get()); - scheduledExecutorService.schedule(() -> { - startLockWorkflow(vault, owner); - }, (long) (vault.getVaultSettings().lockTimeInMinutes().get()), TimeUnit.MINUTES); - } - } - } diff --git a/main/ui/src/main/resources/i18n/strings.properties b/main/ui/src/main/resources/i18n/strings.properties index 552131181..8ffc15c4c 100644 --- a/main/ui/src/main/resources/i18n/strings.properties +++ b/main/ui/src/main/resources/i18n/strings.properties @@ -331,8 +331,8 @@ vaultOptions.masterkey.showRecoveryKeyBtn=Display Recovery Key vaultOptions.masterkey.recoverPasswordBtn=Recover Password ## Auto Lock vaultOptions.autoLock=Auto-Lock -vaultOptions.autoLock.lockAfterTimePart1=Lock after -vaultOptions.autoLock.lockAfterTimePart2=minutes. +vaultOptions.autoLock.lockAfterTimePart1=Lock when idle for +vaultOptions.autoLock.lockAfterTimePart2=minutes # Recovery Key recoveryKey.title=Recovery Key From 9be95efd10d0e4c1d6dc9b07b312e32fd79769e3 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 2 Jun 2021 16:08:46 +0200 Subject: [PATCH 12/15] store autolock time in seconds instead of minutes --- .../common/settings/VaultSettings.java | 18 ++++++------- .../settings/VaultSettingsJsonAdapter.java | 16 ++++++------ .../cryptomator/common/vaults/AutoLocker.java | 10 +++---- .../AutoLockVaultOptionsController.java | 26 ++++++++++++++++--- 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java index 1db67d4d5..132df8245 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java @@ -30,8 +30,8 @@ public class VaultSettings { public static final String DEFAULT_MOUNT_FLAGS = ""; public static final int DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH = -1; public static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK; - public static final boolean DEFAULT_LOCK_AFTER_TIME = false; - public static final int DEFAULT_LOCK_TIME_IN_MINUTES = 30; + public static final boolean DEFAULT_AUTOLOCK_WHEN_IDLE = false; + public static final int DEFAULT_AUTOLOCK_IDLE_SECONDS = 30 * 60; private static final Random RNG = new Random(); @@ -47,8 +47,8 @@ public class VaultSettings { private final StringProperty mountFlags = new SimpleStringProperty(DEFAULT_MOUNT_FLAGS); private final IntegerProperty maxCleartextFilenameLength = new SimpleIntegerProperty(DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH); private final ObjectProperty actionAfterUnlock = new SimpleObjectProperty<>(DEFAULT_ACTION_AFTER_UNLOCK); - private final BooleanProperty lockAfterTime = new SimpleBooleanProperty(DEFAULT_LOCK_AFTER_TIME); - private final IntegerProperty lockTimeInMinutes = new SimpleIntegerProperty(DEFAULT_LOCK_TIME_IN_MINUTES); + private final BooleanProperty autoLockWhenIdle = new SimpleBooleanProperty(DEFAULT_AUTOLOCK_WHEN_IDLE); + private final IntegerProperty autoLockIdleSeconds = new SimpleIntegerProperty(DEFAULT_AUTOLOCK_IDLE_SECONDS); private final StringBinding mountName; public VaultSettings(String id) { @@ -57,7 +57,7 @@ public class VaultSettings { } Observable[] observables() { - return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, maxCleartextFilenameLength, actionAfterUnlock, lockAfterTime, lockTimeInMinutes}; + return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, maxCleartextFilenameLength, actionAfterUnlock, autoLockWhenIdle, autoLockIdleSeconds}; } public static VaultSettings withRandomId() { @@ -158,12 +158,12 @@ public class VaultSettings { return actionAfterUnlock.get(); } - public BooleanProperty lockAfterTime() { - return lockAfterTime; + public BooleanProperty autoLockWhenIdle() { + return autoLockWhenIdle; } - public IntegerProperty lockTimeInMinutes() { - return lockTimeInMinutes; + public IntegerProperty autoLockIdleSeconds() { + return autoLockIdleSeconds; } /* Hashcode/Equals */ diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java index 26aa3d51c..0cf92a48b 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java @@ -31,8 +31,8 @@ class VaultSettingsJsonAdapter { out.name("mountFlags").value(value.mountFlags().get()); out.name("maxCleartextFilenameLength").value(value.maxCleartextFilenameLength().get()); out.name("actionAfterUnlock").value(value.actionAfterUnlock().get().name()); - out.name("lockAfterTime").value(value.lockAfterTime().get()); - out.name("lockTimeInMinutes").value(value.lockTimeInMinutes().get()); + out.name("autoLockWhenIdle").value(value.autoLockWhenIdle().get()); + out.name("autoLockIdleSeconds").value(value.autoLockIdleSeconds().get()); out.endObject(); } @@ -50,8 +50,8 @@ class VaultSettingsJsonAdapter { String mountFlags = VaultSettings.DEFAULT_MOUNT_FLAGS; int maxCleartextFilenameLength = VaultSettings.DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH; WhenUnlocked actionAfterUnlock = VaultSettings.DEFAULT_ACTION_AFTER_UNLOCK; - boolean lockAfterTime = VaultSettings.DEFAULT_LOCK_AFTER_TIME; - int lockTimeInMinutes = VaultSettings.DEFAULT_LOCK_TIME_IN_MINUTES; + boolean autoLockWhenIdle = VaultSettings.DEFAULT_AUTOLOCK_WHEN_IDLE; + int autoLockIdleSeconds = VaultSettings.DEFAULT_AUTOLOCK_IDLE_SECONDS; in.beginObject(); while (in.hasNext()) { @@ -70,8 +70,8 @@ class VaultSettingsJsonAdapter { case "mountFlags" -> mountFlags = in.nextString(); case "maxCleartextFilenameLength" -> maxCleartextFilenameLength = in.nextInt(); case "actionAfterUnlock" -> actionAfterUnlock = parseActionAfterUnlock(in.nextString()); - case "lockAfterTime" -> lockAfterTime = in.nextBoolean(); - case "lockTimeInMinutes" -> lockTimeInMinutes = in.nextInt(); + case "autoLockWhenIdle" -> autoLockWhenIdle = in.nextBoolean(); + case "autoLockIdleSeconds" -> autoLockIdleSeconds = in.nextInt(); default -> { LOG.warn("Unsupported vault setting found in JSON: " + name); in.skipValue(); @@ -96,8 +96,8 @@ class VaultSettingsJsonAdapter { vaultSettings.mountFlags().set(mountFlags); vaultSettings.maxCleartextFilenameLength().set(maxCleartextFilenameLength); vaultSettings.actionAfterUnlock().set(actionAfterUnlock); - vaultSettings.lockAfterTime().set(lockAfterTime); - vaultSettings.lockTimeInMinutes().set(lockTimeInMinutes); + vaultSettings.autoLockWhenIdle().set(autoLockWhenIdle); + vaultSettings.autoLockIdleSeconds().set(autoLockIdleSeconds); return vaultSettings; } diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/AutoLocker.java b/main/commons/src/main/java/org/cryptomator/common/vaults/AutoLocker.java index dcaafdb13..da584086d 100644 --- a/main/commons/src/main/java/org/cryptomator/common/vaults/AutoLocker.java +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/AutoLocker.java @@ -7,7 +7,6 @@ import javax.inject.Inject; import javax.inject.Singleton; import javafx.collections.ObservableList; import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -48,11 +47,10 @@ public class AutoLocker { private boolean exceedsIdleTime(Vault vault) { assert vault.isUnlocked(); // TODO: shouldn't we read these properties from within FX Application Thread? - if (vault.getVaultSettings().lockAfterTime().get()) { - int maxIdleMinutes = vault.getVaultSettings().lockTimeInMinutes().get(); - var idleSince = vault.getStats().getLastActivity(); - var threshold = idleSince.plus(maxIdleMinutes, ChronoUnit.MINUTES); - return threshold.isBefore(Instant.now()); + if (vault.getVaultSettings().autoLockWhenIdle().get()) { + int maxIdleSeconds = vault.getVaultSettings().autoLockIdleSeconds().get(); + var deadline = vault.getStats().getLastActivity().plusSeconds(maxIdleSeconds); + return deadline.isBefore(Instant.now()); } else { return false; } diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java index e8e5ca5fb..1bb74690f 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java @@ -8,12 +8,13 @@ import javax.inject.Inject; import javafx.beans.binding.Bindings; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; -import javafx.util.converter.NumberStringConverter; +import javafx.util.StringConverter; @VaultOptionsScoped public class AutoLockVaultOptionsController implements FxController { private final Vault vault; + public CheckBox lockAfterTimeCheckbox; public NumericTextField lockTimeInMinutesTextField; @@ -24,8 +25,27 @@ public class AutoLockVaultOptionsController implements FxController { @FXML public void initialize() { - lockAfterTimeCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().lockAfterTime()); - Bindings.bindBidirectional(lockTimeInMinutesTextField.textProperty(), vault.getVaultSettings().lockTimeInMinutes(), new NumberStringConverter()); + lockAfterTimeCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().autoLockWhenIdle()); + Bindings.bindBidirectional(lockTimeInMinutesTextField.textProperty(), vault.getVaultSettings().autoLockIdleSeconds(), new IdleTimeSecondsConverter()); + } + + private static class IdleTimeSecondsConverter extends StringConverter { + + @Override + public String toString(Number seconds) { + int minutes = seconds.intValue() / 60; // int-truncate + return Integer.toString(minutes); + } + + @Override + public Number fromString(String string) { + try { + int minutes = Integer.valueOf(string); + return minutes * 60; + } catch (NumberFormatException e) { + return 0; + } + } } } From 751a6079c33a5541923931b62a991f1af8effd5e Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 2 Jun 2021 16:09:23 +0200 Subject: [PATCH 13/15] use explicit imports [ci skip] --- .../cryptomator/common/settings/VaultSettings.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java index 132df8245..10a023806 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java @@ -8,11 +8,18 @@ package org.cryptomator.common.settings; import com.google.common.base.CharMatcher; import com.google.common.base.Strings; import com.google.common.io.BaseEncoding; + import javafx.beans.Observable; import javafx.beans.binding.Bindings; import javafx.beans.binding.StringBinding; -import javafx.beans.property.*; - +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; import java.nio.file.Path; import java.util.Objects; import java.util.Optional; From 820f7989d0f03e9e977267a8af4a3885bcf32038 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 2 Jun 2021 16:10:42 +0200 Subject: [PATCH 14/15] remove debug log statement [ci skip] --- .../src/main/java/org/cryptomator/common/vaults/VaultStats.java | 1 - 1 file changed, 1 deletion(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/VaultStats.java b/main/commons/src/main/java/org/cryptomator/common/vaults/VaultStats.java index 64205a0f2..f6744ec6b 100644 --- a/main/commons/src/main/java/org/cryptomator/common/vaults/VaultStats.java +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/VaultStats.java @@ -83,7 +83,6 @@ public class VaultStats { // check for any I/O activity if (newAccessCount > oldAccessCount) { - LOG.info("ACTIVITY!"); lastActivity.set(Instant.now()); } } From 005d2a82fea664dae6613e862b8a88f11eab4268 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 2 Jun 2021 16:22:19 +0200 Subject: [PATCH 15/15] use stopwatch item for autolock tab --- .../main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java | 2 +- main/ui/src/main/resources/fxml/vault_options.fxml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java b/main/ui/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java index 91865c02e..a273447bb 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java @@ -39,11 +39,11 @@ public enum FontAwesome5Icon { REDO("\uF01E"), // SEARCH("\uF002"), // SPINNER("\uF110"), // + STOPWATCH("\uF2F2"), // SYNC("\uF021"), // TIMES("\uF00D"), // TRASH("\uF1F8"), // UNLINK("\uf127"), // - USER_LOCK("\uF502"), // WRENCH("\uF0AD"), // WINDOW_MINIMIZE("\uF2D1"), // ; diff --git a/main/ui/src/main/resources/fxml/vault_options.fxml b/main/ui/src/main/resources/fxml/vault_options.fxml index 090988c7b..4808209b2 100644 --- a/main/ui/src/main/resources/fxml/vault_options.fxml +++ b/main/ui/src/main/resources/fxml/vault_options.fxml @@ -38,7 +38,7 @@ - +