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 5b33a9765..5c13b66bc 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 @@ -31,6 +31,7 @@ public class VaultSettings { public static final boolean DEFAULT_UNLOCK_AFTER_STARTUP = false; public static final boolean DEFAULT_REAVEAL_AFTER_MOUNT = true; public static final boolean DEFAULT_USES_INDIVIDUAL_MOUNTPATH = false; + public static final boolean DEFAULT_USES_READONLY_MODE = false; private final String id; private final ObjectProperty path = new SimpleObjectProperty<>(); @@ -40,6 +41,7 @@ public class VaultSettings { private final BooleanProperty revealAfterMount = new SimpleBooleanProperty(DEFAULT_REAVEAL_AFTER_MOUNT); private final BooleanProperty usesIndividualMountPath = new SimpleBooleanProperty(DEFAULT_USES_INDIVIDUAL_MOUNTPATH); private final StringProperty individualMountPath = new SimpleStringProperty(); + private final BooleanProperty usesReadOnlyMode = new SimpleBooleanProperty(DEFAULT_USES_READONLY_MODE); public VaultSettings(String id) { this.id = Objects.requireNonNull(id); @@ -48,7 +50,7 @@ public class VaultSettings { } Observable[] observables() { - return new Observable[]{path, mountName, winDriveLetter, unlockAfterStartup, revealAfterMount, usesIndividualMountPath, individualMountPath}; + return new Observable[]{path, mountName, winDriveLetter, unlockAfterStartup, revealAfterMount, usesIndividualMountPath, individualMountPath, usesReadOnlyMode}; } private void deriveMountNameFromPath(Path path) { @@ -131,6 +133,10 @@ public class VaultSettings { return individualMountPath; } + public BooleanProperty usesReadOnlyMode() { + return usesReadOnlyMode; + } + /* 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 866b78bc9..996c9a358 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 @@ -27,6 +27,7 @@ class VaultSettingsJsonAdapter { out.name("revealAfterMount").value(value.revealAfterMount().get()); out.name("usesIndividualMountPath").value(value.usesIndividualMountPath().get()); out.name("individualMountPath").value(value.individualMountPath().get()); //TODO: should this always be written? ( because it could contain metadata, which the user may not want to save!) + out.name("usesReadOnlyMode").value(value.usesReadOnlyMode().get()); out.endObject(); } @@ -39,6 +40,7 @@ class VaultSettingsJsonAdapter { boolean unlockAfterStartup = VaultSettings.DEFAULT_UNLOCK_AFTER_STARTUP; boolean revealAfterMount = VaultSettings.DEFAULT_REAVEAL_AFTER_MOUNT; boolean usesIndividualMountPath = VaultSettings.DEFAULT_USES_INDIVIDUAL_MOUNTPATH; + boolean usesReadOnlyMode = VaultSettings.DEFAULT_USES_READONLY_MODE; in.beginObject(); while (in.hasNext()) { @@ -68,6 +70,9 @@ class VaultSettingsJsonAdapter { case "individualMountPath": individualMountPath = in.nextString(); break; + case "usesReadOnlyMode": + usesReadOnlyMode = in.nextBoolean(); + break; default: LOG.warn("Unsupported vault setting found in JSON: " + name); in.skipValue(); @@ -83,6 +88,7 @@ class VaultSettingsJsonAdapter { vaultSettings.revealAfterMount().set(revealAfterMount); vaultSettings.usesIndividualMountPath().set(usesIndividualMountPath); vaultSettings.individualMountPath().set(individualMountPath); + vaultSettings.usesReadOnlyMode().set(usesReadOnlyMode); return vaultSettings; } diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java index b1851ba15..c2c50bdc5 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java @@ -150,6 +150,9 @@ public class UnlockController implements ViewController { @FXML private CheckBox unlockAfterStartup; + @FXML + private CheckBox useReadOnlyMode; + @Override public void initialize() { advancedOptions.managedProperty().bind(advancedOptions.visibleProperty()); @@ -240,7 +243,7 @@ public class UnlockController implements ViewController { VaultSettings vaultSettings = vault.getVaultSettings(); unlockAfterStartup.setSelected(savePassword.isSelected() && vaultSettings.unlockAfterStartup().get()); revealAfterMount.setSelected(vaultSettings.revealAfterMount().get()); - + useReadOnlyMode.setSelected(vaultSettings.usesReadOnlyMode().get()); if (!settings.preferredVolumeImpl().get().equals(VolumeImpl.WEBDAV)) { useCustomMountPoint.setSelected(vaultSettings.usesIndividualMountPath().get()); customMountPointField.textProperty().setValue(vaultSettings.individualMountPath().getValueSafe()); @@ -249,7 +252,7 @@ public class UnlockController implements ViewController { vaultSubs = vaultSubs.and(EasyBind.subscribe(unlockAfterStartup.selectedProperty(), vaultSettings.unlockAfterStartup()::set)); vaultSubs = vaultSubs.and(EasyBind.subscribe(revealAfterMount.selectedProperty(), vaultSettings.revealAfterMount()::set)); vaultSubs = vaultSubs.and(EasyBind.subscribe(useCustomMountPoint.selectedProperty(), vaultSettings.usesIndividualMountPath()::set)); - + vaultSubs = vaultSubs.and(EasyBind.subscribe(useReadOnlyMode.selectedProperty(), vaultSettings.usesReadOnlyMode()::set)); } // **************************************** diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java index 78a2a51e4..ae45a1191 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java @@ -21,6 +21,7 @@ import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.VaultSettings; import org.cryptomator.cryptofs.CryptoFileSystem; import org.cryptomator.cryptofs.CryptoFileSystemProperties; +import org.cryptomator.cryptofs.CryptoFileSystemProperties.FileSystemFlags; import org.cryptomator.cryptofs.CryptoFileSystemProvider; import org.cryptomator.cryptolib.api.CryptoException; import org.cryptomator.cryptolib.api.InvalidPassphraseException; @@ -38,6 +39,8 @@ import java.nio.file.NoSuchFileException; import java.nio.file.NotDirectoryException; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; @@ -78,9 +81,13 @@ public class Vault { } private CryptoFileSystem unlockCryptoFileSystem(CharSequence passphrase) throws NoSuchFileException, IOException, InvalidPassphraseException, CryptoException { + List flags = new ArrayList<>(); + if (vaultSettings.usesReadOnlyMode().get()) { + flags.add(FileSystemFlags.READONLY); + } CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties() // .withPassphrase(passphrase) // - .withFlags() // + .withFlags(flags) // .withMasterkeyFilename(MASTERKEY_FILENAME) // .build(); return CryptoFileSystemProvider.newFileSystem(getPath(), fsProps); diff --git a/main/ui/src/main/resources/fxml/unlock.fxml b/main/ui/src/main/resources/fxml/unlock.fxml index 7fb73d71a..428a696f6 100644 --- a/main/ui/src/main/resources/fxml/unlock.fxml +++ b/main/ui/src/main/resources/fxml/unlock.fxml @@ -80,14 +80,17 @@ - + - -