mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-22 04:31:27 +00:00
cleanup
removed MASTERKEY_MISSING new recoveryActionType RESTORE_ALL
This commit is contained in:
@@ -7,21 +7,17 @@ import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.cryptomator.common.vaults.VaultState.Value;
|
||||
import static org.cryptomator.common.Constants.MASTERKEY_BACKUP_SUFFIX;
|
||||
|
||||
public final class BackupRestorer {
|
||||
|
||||
private BackupRestorer() {}
|
||||
|
||||
public static boolean restoreIfPresent(Path vaultPath, Value vaultState) {
|
||||
Path targetFile = switch (vaultState) {
|
||||
case VAULT_CONFIG_MISSING -> vaultPath.resolve("vault.cryptomator");
|
||||
case MASTERKEY_MISSING -> vaultPath.resolve("masterkey.cryptomator");
|
||||
default -> throw new IllegalArgumentException("Unexpected vault state: " + vaultState);
|
||||
};
|
||||
public static boolean restoreIfPresent(Path vaultPath, String fileName) {
|
||||
Path targetFile = vaultPath.resolve(fileName);
|
||||
|
||||
try (Stream<Path> files = Files.list(vaultPath)) {
|
||||
return files.filter(file -> isValidBackupFileForState(file.getFileName().toString(), vaultState))
|
||||
return files.filter(file -> isValidBackupFileForState(file.getFileName().toString(), fileName))
|
||||
.max((f1, f2) -> {
|
||||
try {
|
||||
FileTime time1 = Files.getLastModifiedTime(f1);
|
||||
@@ -38,12 +34,8 @@ public final class BackupRestorer {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isValidBackupFileForState(String fileName, Value vaultState) {
|
||||
return switch (vaultState) {
|
||||
case VAULT_CONFIG_MISSING -> fileName.startsWith("vault.cryptomator") && fileName.endsWith(".bkup");
|
||||
case MASTERKEY_MISSING -> fileName.startsWith("masterkey.cryptomator") && fileName.endsWith(".bkup");
|
||||
default -> false;
|
||||
};
|
||||
private static boolean isValidBackupFileForState(String fileName, String vaultState) {
|
||||
return fileName.startsWith(vaultState) && fileName.endsWith(MASTERKEY_BACKUP_SUFFIX);
|
||||
}
|
||||
|
||||
private static boolean copyBackupFile(Path backupFile, Path configPath) {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package org.cryptomator.common.recovery;
|
||||
|
||||
public enum RecoveryActionType {
|
||||
RESTORE_VAULT_CONFIG,
|
||||
RESTORE_ALL,
|
||||
RESTORE_MASTERKEY,
|
||||
RESTORE_VAULT_CONFIG,
|
||||
RESET_PASSWORD,
|
||||
SHOW_KEY,
|
||||
CONVERT_VAULT
|
||||
|
||||
@@ -11,9 +11,6 @@ import java.util.Comparator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
||||
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
|
||||
|
||||
public final class RecoveryDirectory implements AutoCloseable {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(RecoveryDirectory.class);
|
||||
@@ -34,9 +31,8 @@ public final class RecoveryDirectory implements AutoCloseable {
|
||||
return new RecoveryDirectory(vaultPath, tempDir);
|
||||
}
|
||||
|
||||
public void moveRecoveredFiles() throws IOException {
|
||||
Files.move(recoveryPath.resolve(MASTERKEY_FILENAME), vaultPath.resolve(MASTERKEY_FILENAME), StandardCopyOption.REPLACE_EXISTING);
|
||||
Files.move(recoveryPath.resolve(VAULTCONFIG_FILENAME), vaultPath.resolve(VAULTCONFIG_FILENAME), StandardCopyOption.REPLACE_EXISTING);
|
||||
public void moveRecoveredFile(String file) throws IOException {
|
||||
Files.move(recoveryPath.resolve(file), vaultPath.resolve(file), StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
private void deleteRecoveryDirectory() {
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.cryptomator.cryptofs.event.FilesystemEvent;
|
||||
import org.cryptomator.cryptolib.api.CryptoException;
|
||||
import org.cryptomator.cryptolib.api.MasterkeyLoader;
|
||||
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
|
||||
import org.cryptomator.event.VaultEvent;
|
||||
import org.cryptomator.integrations.mount.MountFailedException;
|
||||
import org.cryptomator.integrations.mount.Mountpoint;
|
||||
import org.cryptomator.integrations.mount.UnmountFailedException;
|
||||
@@ -35,7 +34,6 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
@@ -75,7 +73,6 @@ public class Vault {
|
||||
private final BooleanBinding missing;
|
||||
private final BooleanBinding needsMigration;
|
||||
private final BooleanBinding unknownError;
|
||||
private final BooleanBinding missingMasterkey;
|
||||
private final BooleanBinding missingVaultConfig;
|
||||
private final ObjectBinding<Mountpoint> mountPoint;
|
||||
private final Mounter mounter;
|
||||
@@ -105,7 +102,6 @@ public class Vault {
|
||||
this.processing = Bindings.createBooleanBinding(this::isProcessing, state);
|
||||
this.unlocked = Bindings.createBooleanBinding(this::isUnlocked, state);
|
||||
this.missing = Bindings.createBooleanBinding(this::isMissing, state);
|
||||
this.missingMasterkey = Bindings.createBooleanBinding(this::isMissingMasterkey, state);
|
||||
this.missingVaultConfig = Bindings.createBooleanBinding(this::isMissingVaultConfig, state);
|
||||
this.needsMigration = Bindings.createBooleanBinding(this::isNeedsMigration, state);
|
||||
this.unknownError = Bindings.createBooleanBinding(this::isUnknownError, state);
|
||||
@@ -340,20 +336,12 @@ public class Vault {
|
||||
return state.get() == VaultState.Value.ERROR;
|
||||
}
|
||||
|
||||
public BooleanBinding missingMasterkeyProperty() {
|
||||
return missingMasterkey;
|
||||
}
|
||||
|
||||
public boolean isMissingMasterkey() {
|
||||
return state.get() == VaultState.Value.MASTERKEY_MISSING;
|
||||
}
|
||||
|
||||
public BooleanBinding missingVaultConfigProperty() {
|
||||
return missingVaultConfig;
|
||||
}
|
||||
|
||||
public boolean isMissingVaultConfig() {
|
||||
return state.get() == VaultState.Value.VAULT_CONFIG_MISSING;
|
||||
return state.get() == VaultState.Value.VAULT_CONFIG_MISSING || state.get() == VaultState.Value.ALL_MISSING;
|
||||
}
|
||||
|
||||
public ReadOnlyStringProperty displayNameProperty() {
|
||||
|
||||
@@ -25,10 +25,11 @@ import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
||||
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.ERROR;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.MASTERKEY_MISSING;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.ALL_MISSING;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.NEEDS_MIGRATION;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.PROCESSING;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.UNLOCKED;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.VAULT_CONFIG_MISSING;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.Constants;
|
||||
@@ -39,7 +40,6 @@ import org.cryptomator.cryptofs.CryptoFileSystemProvider;
|
||||
import org.cryptomator.cryptofs.DirStructure;
|
||||
import org.cryptomator.cryptofs.migration.Migrators;
|
||||
import org.cryptomator.integrations.mount.MountService;
|
||||
import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -146,7 +146,7 @@ public class VaultListManager {
|
||||
vaultSettings.lastKnownKeyLoader.set(Constants.DEFAULT_KEY_ID.toString());
|
||||
}
|
||||
|
||||
if (vaultState != VaultState.Value.VAULT_CONFIG_MISSING) {
|
||||
if (vaultState != VAULT_CONFIG_MISSING) {
|
||||
initializeLastKnownKeyLoaderIfPossible(vaultSettings, wrapper);
|
||||
}
|
||||
|
||||
@@ -179,10 +179,6 @@ public class VaultListManager {
|
||||
try {
|
||||
VaultState.Value determined = determineVaultState(vault.getPath(), vault.getVaultSettings());
|
||||
|
||||
if (determined == MASTERKEY_MISSING && KeyLoadingStrategy.isHubVault(vault.getVaultConfigCache().getUnchecked().getKeyId().getScheme())) {
|
||||
determined = LOCKED;
|
||||
}
|
||||
|
||||
if (determined == LOCKED) {
|
||||
vault.getVaultConfigCache().reloadConfig();
|
||||
}
|
||||
@@ -205,24 +201,18 @@ public class VaultListManager {
|
||||
return VaultState.Value.MISSING;
|
||||
}
|
||||
|
||||
boolean vaultConfigRestored = Files.notExists(pathToVaultConfig)
|
||||
&& BackupRestorer.restoreIfPresent(pathToVaultConfig.getParent(), VaultState.Value.VAULT_CONFIG_MISSING);
|
||||
BackupRestorer.restoreIfPresent(pathToVaultConfig.getParent(), VAULTCONFIG_FILENAME);
|
||||
|
||||
boolean masterkeyRestored = Files.notExists(pathToMasterkey)
|
||||
&& KeyLoadingStrategy.isMasterkeyFileVault(vaultSettings.lastKnownKeyLoader.get())
|
||||
&& BackupRestorer.restoreIfPresent(pathToMasterkey.getParent(), VaultState.Value.MASTERKEY_MISSING);
|
||||
BackupRestorer.restoreIfPresent(pathToMasterkey.getParent(), MASTERKEY_FILENAME);
|
||||
|
||||
if (vaultConfigRestored || masterkeyRestored) {
|
||||
return LOCKED;
|
||||
if (!Files.exists(pathToVaultConfig) && !Files.exists(pathToMasterkey)) {
|
||||
return ALL_MISSING;
|
||||
}
|
||||
|
||||
if (Files.notExists(pathToVaultConfig)) {
|
||||
return VaultState.Value.VAULT_CONFIG_MISSING;
|
||||
if (!Files.exists(pathToVaultConfig)) {
|
||||
return VAULT_CONFIG_MISSING;
|
||||
}
|
||||
|
||||
if (Files.notExists(pathToMasterkey) && KeyLoadingStrategy.isMasterkeyFileVault(vaultSettings.lastKnownKeyLoader.get())) {
|
||||
return VaultState.Value.MASTERKEY_MISSING;
|
||||
}
|
||||
|
||||
return checkDirStructure(pathToVault);
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ public class VaultState extends ObservableValueBase<VaultState.Value> implements
|
||||
VAULT_CONFIG_MISSING,
|
||||
|
||||
/**
|
||||
* No masterkey found at the provided path
|
||||
* No vault config and masterkey found at the provided path
|
||||
*/
|
||||
MASTERKEY_MISSING,
|
||||
ALL_MISSING,
|
||||
|
||||
/**
|
||||
* Vault requires migration to a newer vault format
|
||||
|
||||
@@ -18,13 +18,10 @@ import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import static org.cryptomator.common.Constants.CRYPTOMATOR_FILENAME_GLOB;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.MASTERKEY_MISSING;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.VAULT_CONFIG_MISSING;
|
||||
|
||||
import dagger.Lazy;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
@@ -36,7 +33,6 @@ import org.cryptomator.common.vaults.VaultConfigCache;
|
||||
import org.cryptomator.common.vaults.VaultListManager;
|
||||
import org.cryptomator.common.vaults.VaultState;
|
||||
import org.cryptomator.integrations.mount.MountService;
|
||||
import org.cryptomator.integrations.mount.Mountpoint;
|
||||
import org.cryptomator.integrations.uiappearance.Theme;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
@@ -151,10 +147,11 @@ public class ChooseExistingVaultController implements FxController {
|
||||
}
|
||||
|
||||
Vault preparedVault = prepareVault(selectedDirectory, vaultComponentFactory, mountServices);
|
||||
VaultListManager.redetermineVaultState(preparedVault);
|
||||
VaultState.Value state = preparedVault.getState();
|
||||
switch (state) {
|
||||
case VAULT_CONFIG_MISSING -> recoveryKeyWindow.create(preparedVault, window, RecoveryActionType.RESTORE_VAULT_CONFIG).showOnboardingDialogWindow();
|
||||
case MASTERKEY_MISSING -> recoveryKeyWindow.create(preparedVault, window, RecoveryActionType.RESTORE_MASTERKEY).showOnboardingDialogWindow();
|
||||
case VAULT_CONFIG_MISSING -> recoveryKeyWindow.create(preparedVault, window, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_VAULT_CONFIG)).showOnboardingDialogWindow();
|
||||
case ALL_MISSING -> recoveryKeyWindow.create(preparedVault, window, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_ALL)).showOnboardingDialogWindow();
|
||||
default -> {
|
||||
vaultListManager.addVault(preparedVault);
|
||||
vault.set(preparedVault);
|
||||
@@ -174,7 +171,7 @@ public class ChooseExistingVaultController implements FxController {
|
||||
}
|
||||
|
||||
var wrapper = new VaultConfigCache(vaultSettings);
|
||||
Vault vault = vaultComponentFactory.create(vaultSettings, wrapper, VAULT_CONFIG_MISSING, null).vault();
|
||||
Vault vault = vaultComponentFactory.create(vaultSettings, wrapper, LOCKED, null).vault();
|
||||
try {
|
||||
VaultListManager.determineVaultState(vault.getPath(), vaultSettings);
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -122,7 +122,7 @@ abstract class ConvertVaultModule {
|
||||
@IntoMap
|
||||
@FxControllerKey(RecoveryKeyValidateController.class)
|
||||
static FxController bindRecoveryKeyValidateController(@ConvertVaultWindow Vault vault, @ConvertVaultWindow VaultConfig.UnverifiedVaultConfig vaultConfig, @ConvertVaultWindow StringProperty recoveryKey, RecoveryKeyFactory recoveryKeyFactory) {
|
||||
return new RecoveryKeyValidateController(vault, vaultConfig, recoveryKey, recoveryKeyFactory, RecoveryActionType.CONVERT_VAULT, null, null);
|
||||
return new RecoveryKeyValidateController(vault, vaultConfig, recoveryKey, recoveryKeyFactory, new SimpleObjectProperty<>(RecoveryActionType.CONVERT_VAULT), null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,15 +15,13 @@ import org.cryptomator.ui.lock.LockComponent;
|
||||
import org.cryptomator.ui.mainwindow.MainWindowComponent;
|
||||
import org.cryptomator.ui.preferences.PreferencesComponent;
|
||||
import org.cryptomator.ui.quit.QuitComponent;
|
||||
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
|
||||
import org.cryptomator.ui.sharevault.ShareVaultComponent;
|
||||
import org.cryptomator.ui.traymenu.TrayMenuComponent;
|
||||
import org.cryptomator.ui.unlock.UnlockComponent;
|
||||
import org.cryptomator.ui.updatereminder.UpdateReminderComponent;
|
||||
import org.cryptomator.ui.vaultoptions.VaultOptionsComponent;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.scene.image.Image;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -40,7 +38,8 @@ import java.io.InputStream;
|
||||
HealthCheckComponent.class, //
|
||||
UpdateReminderComponent.class, //
|
||||
ShareVaultComponent.class, //
|
||||
EventViewComponent.class})
|
||||
EventViewComponent.class, //
|
||||
RecoveryKeyComponent.class})
|
||||
abstract class FxApplicationModule {
|
||||
|
||||
private static Image createImageFromResource(String resourceName) throws IOException {
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package org.cryptomator.ui.keyloading.masterkeyfile;
|
||||
|
||||
import org.cryptomator.common.recovery.RecoveryActionType;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.keyloading.KeyLoading;
|
||||
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.beans.binding.StringBinding;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
@@ -27,17 +31,39 @@ public class ChooseMasterkeyFileController implements FxController {
|
||||
private final Stage window;
|
||||
private final Vault vault;
|
||||
private final CompletableFuture<Path> result;
|
||||
private final RecoveryKeyComponent.Factory recoveryKeyWindow;
|
||||
private final ResourceBundle resourceBundle;
|
||||
|
||||
@FXML private CheckBox restoreInsteadCheckBox;
|
||||
@FXML private Button chooseButton;
|
||||
|
||||
@Inject
|
||||
public ChooseMasterkeyFileController(@KeyLoading Stage window, @KeyLoading Vault vault, CompletableFuture<Path> result, ResourceBundle resourceBundle) {
|
||||
public ChooseMasterkeyFileController(@KeyLoading Stage window, //
|
||||
@KeyLoading Vault vault, //
|
||||
CompletableFuture<Path> result, //
|
||||
RecoveryKeyComponent.Factory recoveryKeyWindow, //
|
||||
ResourceBundle resourceBundle) {
|
||||
this.window = window;
|
||||
this.vault = vault;
|
||||
this.result = result;
|
||||
this.recoveryKeyWindow = recoveryKeyWindow;
|
||||
this.resourceBundle = resourceBundle;
|
||||
this.window.setOnHiding(this::windowClosed);
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void initialize() {
|
||||
restoreInsteadCheckBox.selectedProperty().addListener((_, _, newVal) -> {
|
||||
if (newVal) {
|
||||
chooseButton.setText(resourceBundle.getString("addvaultwizard.existing.restore"));
|
||||
chooseButton.setOnAction(e -> restoreMasterkey());
|
||||
} else {
|
||||
chooseButton.setText(resourceBundle.getString("generic.button.choose"));
|
||||
chooseButton.setOnAction(e -> proceed());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void cancel() {
|
||||
window.close();
|
||||
@@ -47,6 +73,12 @@ public class ChooseMasterkeyFileController implements FxController {
|
||||
result.cancel(true);
|
||||
}
|
||||
|
||||
@FXML
|
||||
void restoreMasterkey() {
|
||||
window.close();
|
||||
recoveryKeyWindow.create(vault, window, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_MASTERKEY)).showOnboardingDialogWindow();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void proceed() {
|
||||
LOG.trace("proceed()");
|
||||
|
||||
@@ -52,7 +52,7 @@ public class VaultDetailController implements FxController {
|
||||
case LOCKED -> FontAwesome5Icon.LOCK;
|
||||
case PROCESSING -> FontAwesome5Icon.SPINNER;
|
||||
case UNLOCKED -> FontAwesome5Icon.LOCK_OPEN;
|
||||
case NEEDS_MIGRATION, MISSING, VAULT_CONFIG_MISSING, MASTERKEY_MISSING, ERROR -> FontAwesome5Icon.EXCLAMATION_TRIANGLE;
|
||||
case NEEDS_MIGRATION, MISSING, VAULT_CONFIG_MISSING, ALL_MISSING, ERROR -> FontAwesome5Icon.EXCLAMATION_TRIANGLE;
|
||||
};
|
||||
} else {
|
||||
return FontAwesome5Icon.EXCLAMATION_TRIANGLE;
|
||||
|
||||
@@ -3,8 +3,10 @@ package org.cryptomator.ui.mainwindow;
|
||||
import org.cryptomator.common.recovery.RecoveryActionType;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.common.vaults.VaultListManager;
|
||||
import org.cryptomator.common.vaults.VaultState;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.dialogs.Dialogs;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationWindows;
|
||||
import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
|
||||
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
|
||||
|
||||
@@ -16,13 +18,17 @@ import javafx.fxml.FXML;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import static org.cryptomator.common.Constants.CRYPTOMATOR_FILENAME_GLOB;
|
||||
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
||||
|
||||
@MainWindowScoped
|
||||
public class VaultDetailMissingVaultController implements FxController {
|
||||
|
||||
private final FxApplicationWindows appWindows;
|
||||
private final Stage mainWindow;
|
||||
private final ObjectProperty<Vault> vault;
|
||||
private final ObservableList<Vault> vaults;
|
||||
private final ResourceBundle resourceBundle;
|
||||
@@ -31,12 +37,17 @@ public class VaultDetailMissingVaultController implements FxController {
|
||||
private final Dialogs dialogs;
|
||||
|
||||
@Inject
|
||||
public VaultDetailMissingVaultController(ObjectProperty<Vault> vault, //
|
||||
public VaultDetailMissingVaultController(FxApplicationWindows appWindows, //
|
||||
@MainWindow Stage mainWindow, //
|
||||
ObjectProperty<Vault> vault, //
|
||||
ObservableList<Vault> vaults, //
|
||||
ResourceBundle resourceBundle, //
|
||||
@MainWindow Stage window, //
|
||||
Dialogs dialogs, //
|
||||
RecoveryKeyComponent.Factory recoveryKeyWindow) {
|
||||
|
||||
this.appWindows = appWindows;
|
||||
this.mainWindow = mainWindow;
|
||||
this.vault = vault;
|
||||
this.vaults = vaults;
|
||||
this.resourceBundle = resourceBundle;
|
||||
@@ -60,14 +71,23 @@ public class VaultDetailMissingVaultController implements FxController {
|
||||
if(KeyLoadingStrategy.isHubVault(vault.get().getVaultSettings().lastKnownKeyLoader.get())){
|
||||
dialogs.prepareContactHubAdmin(window).build().showAndWait();
|
||||
}
|
||||
else if(Files.exists(vault.get().getPath().resolve(MASTERKEY_FILENAME))){
|
||||
recoveryKeyWindow.create(vault.get(), window, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_VAULT_CONFIG)).showOnboardingDialogWindow();
|
||||
}
|
||||
else {
|
||||
recoveryKeyWindow.create(vault.get(), window, RecoveryActionType.RESTORE_VAULT_CONFIG).showOnboardingDialogWindow();
|
||||
recoveryKeyWindow.create(vault.get(), window, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_ALL)).showOnboardingDialogWindow();
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
void restoreMasterkey() {
|
||||
recoveryKeyWindow.create(vault.get(), window, RecoveryActionType.RESTORE_MASTERKEY).showRecoveryKeyRecoverWindow();
|
||||
recoveryKeyWindow.create(vault.get(), window, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_MASTERKEY)).showRecoveryKeyRecoverWindow();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void unlock() {
|
||||
vault.get().stateProperty().set(VaultState.Value.LOCKED);
|
||||
appWindows.startUnlockWorkflow(vault.get(), mainWindow);
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
||||
@@ -55,7 +55,7 @@ public class VaultListCellController implements FxController {
|
||||
case LOCKED -> FontAwesome5Icon.LOCK;
|
||||
case PROCESSING -> FontAwesome5Icon.SPINNER;
|
||||
case UNLOCKED -> FontAwesome5Icon.LOCK_OPEN;
|
||||
case NEEDS_MIGRATION, MISSING, VAULT_CONFIG_MISSING, MASTERKEY_MISSING, ERROR -> FontAwesome5Icon.EXCLAMATION_TRIANGLE;
|
||||
case NEEDS_MIGRATION, MISSING, VAULT_CONFIG_MISSING, ALL_MISSING, ERROR -> FontAwesome5Icon.EXCLAMATION_TRIANGLE;
|
||||
};
|
||||
} else {
|
||||
return FontAwesome5Icon.EXCLAMATION_TRIANGLE;
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.Objects;
|
||||
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.ERROR;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.MASTERKEY_MISSING;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.ALL_MISSING;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.MISSING;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.NEEDS_MIGRATION;
|
||||
import static org.cryptomator.common.vaults.VaultState.Value.UNLOCKED;
|
||||
@@ -65,7 +65,7 @@ public class VaultListContextMenuController implements FxController {
|
||||
|
||||
this.selectedVaultState = selectedVault.flatMap(Vault::stateProperty).orElse(null);
|
||||
this.selectedVaultPassphraseStored = selectedVault.map(this::isPasswordStored).orElse(false);
|
||||
this.selectedVaultRemovable = selectedVaultState.map(EnumSet.of(LOCKED, MISSING, ERROR, NEEDS_MIGRATION, MASTERKEY_MISSING, VAULT_CONFIG_MISSING)::contains).orElse(false);
|
||||
this.selectedVaultRemovable = selectedVaultState.map(EnumSet.of(LOCKED, MISSING, ERROR, NEEDS_MIGRATION, ALL_MISSING, VAULT_CONFIG_MISSING)::contains).orElse(false);
|
||||
this.selectedVaultUnlockable = selectedVaultState.map(LOCKED::equals).orElse(false);
|
||||
this.selectedVaultLockable = selectedVaultState.map(UNLOCKED::equals).orElse(false);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
@@ -54,7 +55,7 @@ public interface RecoveryKeyComponent {
|
||||
|
||||
RecoveryKeyComponent create(@BindsInstance @RecoveryKeyWindow Vault vault, //
|
||||
@BindsInstance @Named("keyRecoveryOwner") Stage owner, //
|
||||
@BindsInstance @Named("recoverType") RecoveryActionType recoverType);
|
||||
@BindsInstance @Named("recoverType") ObjectProperty<RecoveryActionType> recoverType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,28 +1,45 @@
|
||||
package org.cryptomator.ui.recoverykey;
|
||||
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.common.recovery.CryptoFsInitializer;
|
||||
import org.cryptomator.common.recovery.MasterkeyService;
|
||||
import org.cryptomator.common.recovery.RecoveryActionType;
|
||||
import org.cryptomator.common.recovery.RecoveryDirectory;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.common.vaults.VaultListManager;
|
||||
import org.cryptomator.cryptolib.api.CryptoException;
|
||||
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
|
||||
import org.cryptomator.cryptolib.api.Masterkey;
|
||||
import org.cryptomator.cryptolib.common.MasterkeyFileAccess;
|
||||
import org.cryptomator.ui.common.Animations;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.controls.FormattedLabel;
|
||||
import org.cryptomator.ui.controls.NiceSecurePasswordField;
|
||||
import org.cryptomator.ui.dialogs.Dialogs;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationWindows;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.stage.Stage;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
||||
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
|
||||
|
||||
@RecoveryKeyScoped
|
||||
public class RecoveryKeyCreationController implements FxController {
|
||||
|
||||
@@ -30,23 +47,74 @@ public class RecoveryKeyCreationController implements FxController {
|
||||
|
||||
private final Stage window;
|
||||
private final Lazy<Scene> successScene;
|
||||
private final Lazy<Scene> recoverykeyExpertSettingsScene;
|
||||
private final MasterkeyFileAccess masterkeyFileAccess;
|
||||
private final Vault vault;
|
||||
private final ExecutorService executor;
|
||||
private final RecoveryKeyFactory recoveryKeyFactory;
|
||||
private final StringProperty recoveryKeyProperty;
|
||||
private final FxApplicationWindows appWindows;
|
||||
public NiceSecurePasswordField passwordField;
|
||||
private final IntegerProperty shorteningThreshold;
|
||||
private final ObjectProperty<RecoveryActionType> recoverType;
|
||||
private final ResourceBundle resourceBundle;
|
||||
public FormattedLabel descriptionLabel;
|
||||
public Button cancelButton;
|
||||
public Button nextButton;
|
||||
private final VaultListManager vaultListManager;
|
||||
private final Dialogs dialogs;
|
||||
private final Stage owner;
|
||||
|
||||
@Inject
|
||||
public RecoveryKeyCreationController(@RecoveryKeyWindow Stage window, @FxmlScene(FxmlFile.RECOVERYKEY_SUCCESS) Lazy<Scene> successScene, @RecoveryKeyWindow Vault vault, RecoveryKeyFactory recoveryKeyFactory, ExecutorService executor, @RecoveryKeyWindow StringProperty recoveryKey, FxApplicationWindows appWindows, ResourceBundle resourceBundle) {
|
||||
public RecoveryKeyCreationController(FxApplicationWindows appWindows, //
|
||||
@RecoveryKeyWindow Stage window, //
|
||||
@Named("keyRecoveryOwner") Stage owner, //
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_SUCCESS) Lazy<Scene> successScene, //
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_EXPERT_SETTINGS) Lazy<Scene> recoverykeyExpertSettingsScene, //
|
||||
@RecoveryKeyWindow Vault vault, //
|
||||
RecoveryKeyFactory recoveryKeyFactory, //
|
||||
MasterkeyFileAccess masterkeyFileAccess, //
|
||||
ExecutorService executor, //
|
||||
@RecoveryKeyWindow StringProperty recoveryKey, //
|
||||
@Named("shorteningThreshold") IntegerProperty shorteningThreshold, //
|
||||
@Named("recoverType") ObjectProperty<RecoveryActionType> recoverType, //
|
||||
VaultListManager vaultListManager, //
|
||||
ResourceBundle resourceBundle, //
|
||||
Dialogs dialogs) {
|
||||
this.window = window;
|
||||
window.setTitle(resourceBundle.getString("recoveryKey.display.title"));
|
||||
this.successScene = successScene;
|
||||
this.recoverykeyExpertSettingsScene = recoverykeyExpertSettingsScene;
|
||||
this.vault = vault;
|
||||
this.executor = executor;
|
||||
this.recoveryKeyFactory = recoveryKeyFactory;
|
||||
this.recoveryKeyProperty = recoveryKey;
|
||||
this.appWindows = appWindows;
|
||||
this.recoverType = recoverType;
|
||||
this.resourceBundle = resourceBundle;
|
||||
this.masterkeyFileAccess = masterkeyFileAccess;
|
||||
this.shorteningThreshold = shorteningThreshold;
|
||||
this.vaultListManager = vaultListManager;
|
||||
this.owner = owner;
|
||||
this.dialogs = dialogs;
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
if (recoverType.get().equals(RecoveryActionType.SHOW_KEY)) {
|
||||
window.setTitle(resourceBundle.getString("recoveryKey.display.title"));
|
||||
} else if (recoverType.get().equals(RecoveryActionType.RESTORE_VAULT_CONFIG)) {
|
||||
window.setTitle(resourceBundle.getString("recoveryKey.recoverVaultConfig.title"));
|
||||
descriptionLabel.formatProperty().set(resourceBundle.getString("recoveryKey.recover.description"));
|
||||
cancelButton.setOnAction((_) -> back());
|
||||
cancelButton.setText(resourceBundle.getString("generic.button.back"));
|
||||
nextButton.setOnAction((_) -> restoreWithPassword());
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void back() {
|
||||
window.setScene(recoverykeyExpertSettingsScene.get());
|
||||
window.centerOnScreen();
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -71,6 +139,40 @@ public class RecoveryKeyCreationController implements FxController {
|
||||
executor.submit(task);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void restoreWithPassword() {
|
||||
|
||||
try (RecoveryDirectory recoveryDirectory = RecoveryDirectory.create(vault.getPath())) {
|
||||
Path recoveryPath = recoveryDirectory.getRecoveryPath();
|
||||
|
||||
Path masterkeyFilePath = vault.getPath().resolve(MASTERKEY_FILENAME);
|
||||
|
||||
try (Masterkey masterkey = MasterkeyService.load(masterkeyFileAccess, masterkeyFilePath, passwordField.getCharacters())) {
|
||||
var combo = MasterkeyService.detect(masterkey.getEncoded(), vault.getPath());
|
||||
CryptoFsInitializer.init(recoveryPath, masterkey, shorteningThreshold.get(), combo.get());
|
||||
}
|
||||
|
||||
recoveryDirectory.moveRecoveredFile(VAULTCONFIG_FILENAME);
|
||||
|
||||
if (!vaultListManager.containsVault(vault.getPath())) {
|
||||
vaultListManager.add(vault.getPath());
|
||||
}
|
||||
window.close();
|
||||
dialogs.prepareRecoverPasswordSuccess(window, owner, resourceBundle) //
|
||||
.setTitleKey("recoveryKey.recoverVaultConfig.title") //
|
||||
.setMessageKey("recoveryKey.recover.resetVaultConfigSuccess.message") //
|
||||
.build().showAndWait();
|
||||
|
||||
} catch (InvalidPassphraseException e) {
|
||||
LOG.info("Password invalid", e);
|
||||
Animations.createShakeWindowAnimation(window).play();
|
||||
} catch (IOException | CryptoException e) {
|
||||
LOG.error("Recovery process failed", e);
|
||||
appWindows.showErrorWindow(e, window, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@FXML
|
||||
public void close() {
|
||||
window.close();
|
||||
|
||||
@@ -6,17 +6,23 @@ import javafx.application.Application;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.common.recovery.RecoveryActionType;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.common.vaults.VaultState;
|
||||
import org.cryptomator.ui.addvaultwizard.CreateNewVaultExpertSettingsController;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.controls.NumericTextField;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@RecoveryKeyScoped
|
||||
public class RecoveryKeyExpertSettingsController implements FxController {
|
||||
@@ -27,28 +33,40 @@ public class RecoveryKeyExpertSettingsController implements FxController {
|
||||
|
||||
private final Stage window;
|
||||
private final Lazy<Application> application;
|
||||
private final Lazy<Scene> resetPasswordScene;
|
||||
private final Lazy<Scene> recoverScene;
|
||||
|
||||
public CheckBox expertSettingsCheckBox;
|
||||
public NumericTextField shorteningThresholdTextField;
|
||||
private final Vault vault;
|
||||
private final ObjectProperty<RecoveryActionType> recoverType;
|
||||
private final IntegerProperty shorteningThreshold;
|
||||
private final Lazy<Scene> resetPasswordScene;
|
||||
private final Lazy<Scene> createScene;
|
||||
private final Lazy<Scene> onBoardingScene;
|
||||
private final Lazy<Scene> recoverScene;
|
||||
private final BooleanBinding validShorteningThreshold;
|
||||
|
||||
@FXML public CheckBox expertSettingsCheckBox;
|
||||
@FXML public NumericTextField shorteningThresholdTextField;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(RecoveryKeyExpertSettingsController.class);
|
||||
|
||||
@Inject
|
||||
public RecoveryKeyExpertSettingsController(@RecoveryKeyWindow Stage window, //
|
||||
Lazy<Application> application, //
|
||||
@RecoveryKeyWindow Vault vault, //
|
||||
@Named("recoverType") ObjectProperty<RecoveryActionType> recoverType, //
|
||||
@Named("shorteningThreshold") IntegerProperty shorteningThreshold, //
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_RESET_PASSWORD) Lazy<Scene> resetPasswordScene, //
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_CREATE) Lazy<Scene> createScene, //
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_ONBOARDING) Lazy<Scene> onBoardingScene, //
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_RECOVER) Lazy<Scene> recoverScene) {
|
||||
this.window = window;
|
||||
this.application = application;
|
||||
this.resetPasswordScene = resetPasswordScene;
|
||||
this.recoverScene = recoverScene;
|
||||
this.vault = vault;
|
||||
this.recoverType = recoverType;
|
||||
this.shorteningThreshold = shorteningThreshold;
|
||||
this.resetPasswordScene = resetPasswordScene;
|
||||
this.createScene = createScene;
|
||||
this.onBoardingScene = onBoardingScene;
|
||||
this.recoverScene = recoverScene;
|
||||
this.validShorteningThreshold = Bindings.createBooleanBinding(this::isValidShorteningThreshold, shorteningThreshold);
|
||||
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -87,11 +105,19 @@ public class RecoveryKeyExpertSettingsController implements FxController {
|
||||
|
||||
@FXML
|
||||
public void back() {
|
||||
window.setScene(recoverScene.get());
|
||||
if(recoverType.get().equals(RecoveryActionType.RESTORE_ALL) && vault.getState().equals(VaultState.Value.VAULT_CONFIG_MISSING))
|
||||
window.setScene(recoverScene.get());
|
||||
else if(recoverType.get().equals(RecoveryActionType.RESTORE_ALL) && vault.getState().equals(VaultState.Value.ALL_MISSING))
|
||||
window.setScene(recoverScene.get());
|
||||
else if(recoverType.get().equals(RecoveryActionType.RESTORE_VAULT_CONFIG))
|
||||
window.setScene(onBoardingScene.get());
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void next() {
|
||||
window.setScene(resetPasswordScene.get());
|
||||
if(recoverType.get().equals(RecoveryActionType.RESTORE_VAULT_CONFIG))
|
||||
window.setScene(createScene.get());
|
||||
else
|
||||
window.setScene(resetPasswordScene.get());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ abstract class RecoveryKeyModule {
|
||||
@Provides
|
||||
@IntoMap
|
||||
@FxControllerKey(RecoveryKeyValidateController.class)
|
||||
static FxController bindRecoveryKeyValidateController(@RecoveryKeyWindow Vault vault, @RecoveryKeyWindow @Nullable VaultConfig.UnverifiedVaultConfig vaultConfig, @RecoveryKeyWindow StringProperty recoveryKey, RecoveryKeyFactory recoveryKeyFactory, @Named("recoverType") RecoveryActionType recoverType, @Named("cipherCombo") ObjectProperty<CryptorProvider.Scheme> cipherCombo, @Nullable MasterkeyFileAccess masterkeyFileAccess) {
|
||||
static FxController bindRecoveryKeyValidateController(@RecoveryKeyWindow Vault vault, @RecoveryKeyWindow @Nullable VaultConfig.UnverifiedVaultConfig vaultConfig, @RecoveryKeyWindow StringProperty recoveryKey, RecoveryKeyFactory recoveryKeyFactory, @Named("recoverType") ObjectProperty<RecoveryActionType> recoverType, @Named("cipherCombo") ObjectProperty<CryptorProvider.Scheme> cipherCombo, @Nullable MasterkeyFileAccess masterkeyFileAccess) {
|
||||
return new RecoveryKeyValidateController(vault, vaultConfig, recoveryKey, recoveryKeyFactory, recoverType, cipherCombo, masterkeyFileAccess);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,38 +1,119 @@
|
||||
package org.cryptomator.ui.recoverykey;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.common.recovery.RecoveryActionType;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.RadioButton;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.Stage;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import static org.cryptomator.common.recovery.RecoveryActionType.RESTORE_ALL;
|
||||
import static org.cryptomator.common.recovery.RecoveryActionType.RESTORE_VAULT_CONFIG;
|
||||
|
||||
@RecoveryKeyScoped
|
||||
public class RecoveryKeyOnboardingController implements FxController {
|
||||
|
||||
private final Stage window;
|
||||
private final Lazy<Scene> recoverykeyRecoverScene;
|
||||
private RecoveryActionType recoverType;
|
||||
private final Lazy<Scene> recoverykeyExpertSettingsScene;
|
||||
private ObjectProperty<RecoveryActionType> recoverType;
|
||||
|
||||
public Label titleLabel;
|
||||
public Label messageLabel;
|
||||
public Label secondTextDesc;
|
||||
public Label thirdTextIndex;
|
||||
public Label thirdTextDesc;
|
||||
|
||||
@FXML
|
||||
private CheckBox affirmationBox;
|
||||
@FXML
|
||||
private RadioButton recoveryKeyRadio;
|
||||
@FXML
|
||||
private RadioButton passwordRadio;
|
||||
@FXML
|
||||
private Button nextButton;
|
||||
@FXML
|
||||
private VBox chooseMethodeBox;
|
||||
private final ToggleGroup methodToggleGroup = new ToggleGroup();
|
||||
|
||||
|
||||
@Inject
|
||||
public RecoveryKeyOnboardingController(@RecoveryKeyWindow Stage window, //
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_RECOVER) Lazy<Scene> recoverykeyRecoverScene, //
|
||||
@Named("recoverType") RecoveryActionType recoverType, //
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_EXPERT_SETTINGS) Lazy<Scene> recoverykeyExpertSettingsScene, //
|
||||
@Named("recoverType") ObjectProperty<RecoveryActionType> recoverType, //
|
||||
ResourceBundle resourceBundle) {
|
||||
this.window = window;
|
||||
window.setTitle(resourceBundle.getString("recoveryKey.recoverVaultConfig.title"));
|
||||
|
||||
this.recoverykeyRecoverScene = recoverykeyRecoverScene;
|
||||
this.recoverykeyExpertSettingsScene = recoverykeyExpertSettingsScene;
|
||||
this.recoverType = recoverType;
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
|
||||
recoveryKeyRadio.setToggleGroup(methodToggleGroup);
|
||||
passwordRadio.setToggleGroup(methodToggleGroup);
|
||||
|
||||
boolean showMethodSelection = (recoverType.get() == RecoveryActionType.RESTORE_VAULT_CONFIG);
|
||||
chooseMethodeBox.setVisible(showMethodSelection);
|
||||
chooseMethodeBox.setManaged(showMethodSelection);
|
||||
|
||||
nextButton.disableProperty().bind( //
|
||||
affirmationBox.selectedProperty().not() //
|
||||
.or(methodToggleGroup.selectedToggleProperty().isNull() //
|
||||
.and(showMethodSelectionProperty())));
|
||||
|
||||
switch (recoverType.get()) {
|
||||
case RESTORE_VAULT_CONFIG -> {
|
||||
window.setTitle("Recover Vault Config");
|
||||
messageLabel.setText("Read this:");
|
||||
secondTextDesc.setText("You will need the vault password or recovery key, a new password and possible some expert settings.");
|
||||
thirdTextIndex.setVisible(false);
|
||||
thirdTextIndex.setManaged(false);
|
||||
thirdTextDesc.setVisible(false);
|
||||
thirdTextDesc.setManaged(false);
|
||||
}
|
||||
case RESTORE_MASTERKEY -> {
|
||||
window.setTitle("Recover Masterkey");
|
||||
messageLabel.setText("Read this:");
|
||||
titleLabel.setText("Recover Masterkey");
|
||||
secondTextDesc.setText("You will need the vault recovery key.");
|
||||
thirdTextIndex.setVisible(false);
|
||||
thirdTextIndex.setManaged(false);
|
||||
thirdTextDesc.setVisible(false);
|
||||
thirdTextDesc.setManaged(false);
|
||||
}
|
||||
default -> {
|
||||
thirdTextIndex.setVisible(true);
|
||||
thirdTextIndex.setManaged(true);
|
||||
thirdTextDesc.setVisible(true);
|
||||
thirdTextDesc.setManaged(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BooleanProperty showMethodSelectionProperty() {
|
||||
return new SimpleBooleanProperty(recoverType.get() == RecoveryActionType.RESTORE_VAULT_CONFIG);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void close() {
|
||||
window.close();
|
||||
@@ -40,7 +121,21 @@ public class RecoveryKeyOnboardingController implements FxController {
|
||||
|
||||
@FXML
|
||||
public void next() {
|
||||
recoverType = RecoveryActionType.RESTORE_VAULT_CONFIG;
|
||||
window.setScene(recoverykeyRecoverScene.get());
|
||||
switch (recoverType.get()) {
|
||||
case RESTORE_VAULT_CONFIG, RESTORE_ALL -> {
|
||||
Object selectedToggle = methodToggleGroup.getSelectedToggle();
|
||||
if (selectedToggle == recoveryKeyRadio) {
|
||||
recoverType.set(RESTORE_ALL);
|
||||
window.setScene(recoverykeyRecoverScene.get());
|
||||
} else if (selectedToggle == passwordRadio) {
|
||||
recoverType.set(RESTORE_VAULT_CONFIG);
|
||||
window.setScene(recoverykeyExpertSettingsScene.get());
|
||||
} else {
|
||||
window.setScene(recoverykeyRecoverScene.get());
|
||||
window.centerOnScreen();
|
||||
}
|
||||
}
|
||||
case RESTORE_MASTERKEY -> window.setScene(recoverykeyRecoverScene.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import javax.inject.Named;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.stage.Stage;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@@ -19,6 +20,12 @@ public class RecoveryKeyRecoverController implements FxController {
|
||||
|
||||
private final Stage window;
|
||||
private final Lazy<Scene> nextScene;
|
||||
private final Lazy<Scene> onBoardingScene;
|
||||
private final ResourceBundle resourceBundle;
|
||||
public ObjectProperty<RecoveryActionType> recoverType;
|
||||
|
||||
@FXML
|
||||
private Button cancelButton;
|
||||
|
||||
@FXML
|
||||
RecoveryKeyValidateController recoveryKeyValidateController;
|
||||
@@ -27,11 +34,15 @@ public class RecoveryKeyRecoverController implements FxController {
|
||||
public RecoveryKeyRecoverController(@RecoveryKeyWindow Stage window, //
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_RESET_PASSWORD) Lazy<Scene> resetPasswordScene, //
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_EXPERT_SETTINGS) Lazy<Scene> expertSettingsScene, //
|
||||
ResourceBundle resourceBundle, @Named("recoverType") RecoveryActionType recoverType) {
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_ONBOARDING) Lazy<Scene> onBoardingScene, //
|
||||
ResourceBundle resourceBundle, //
|
||||
@Named("recoverType") ObjectProperty<RecoveryActionType> recoverType) {
|
||||
this.window = window;
|
||||
|
||||
this.nextScene = switch (recoverType) {
|
||||
case RESTORE_VAULT_CONFIG -> {
|
||||
this.recoverType = recoverType;
|
||||
this.onBoardingScene = onBoardingScene;
|
||||
this.resourceBundle = resourceBundle;
|
||||
this.nextScene = switch (recoverType.get()) {
|
||||
case RESTORE_ALL, RESTORE_VAULT_CONFIG -> {
|
||||
window.setTitle(resourceBundle.getString("recoveryKey.recoverVaultConfig.title"));
|
||||
yield expertSettingsScene;
|
||||
}
|
||||
@@ -56,11 +67,18 @@ public class RecoveryKeyRecoverController implements FxController {
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
switch (recoverType.get()) {
|
||||
case RESTORE_ALL, RESTORE_VAULT_CONFIG -> cancelButton.setText(resourceBundle.getString("generic.button.back"));
|
||||
case RESET_PASSWORD -> cancelButton.setText(resourceBundle.getString("generic.button.cancel"));
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void close() {
|
||||
window.close();
|
||||
switch (recoverType.get()) {
|
||||
case RESTORE_ALL, RESTORE_VAULT_CONFIG -> window.setScene(onBoardingScene.get());
|
||||
case RESET_PASSWORD -> window.close();
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
||||
@@ -1,24 +1,5 @@
|
||||
package org.cryptomator.ui.recoverykey;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyBooleanWrapper;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
||||
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.common.recovery.CryptoFsInitializer;
|
||||
import org.cryptomator.common.recovery.MasterkeyService;
|
||||
@@ -39,6 +20,27 @@ import org.cryptomator.ui.fxapp.FxApplicationWindows;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyBooleanWrapper;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.stage.Stage;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
||||
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
|
||||
|
||||
@RecoveryKeyScoped
|
||||
public class RecoveryKeyResetPasswordController implements FxController {
|
||||
|
||||
@@ -50,11 +52,12 @@ public class RecoveryKeyResetPasswordController implements FxController {
|
||||
private final ExecutorService executor;
|
||||
private final StringProperty recoveryKey;
|
||||
private final Lazy<Scene> recoverExpertSettingsScene;
|
||||
private final Lazy<Scene> recoverykeyRecoverScene;
|
||||
private final FxApplicationWindows appWindows;
|
||||
private final MasterkeyFileAccess masterkeyFileAccess;
|
||||
private final VaultListManager vaultListManager;
|
||||
private final IntegerProperty shorteningThreshold;
|
||||
private final RecoveryActionType recoverType;
|
||||
private final ObjectProperty<RecoveryActionType> recoverType;
|
||||
private final ObjectProperty<CryptorProvider.Scheme> cipherCombo;
|
||||
private final ResourceBundle resourceBundle;
|
||||
private final StringProperty buttonText = new SimpleStringProperty();
|
||||
@@ -62,6 +65,8 @@ public class RecoveryKeyResetPasswordController implements FxController {
|
||||
private final Stage owner;
|
||||
|
||||
public NewPasswordController newPasswordController;
|
||||
public Button backButton;
|
||||
public Button nextButton;
|
||||
|
||||
@Inject
|
||||
public RecoveryKeyResetPasswordController(@RecoveryKeyWindow Stage window, //
|
||||
@@ -70,11 +75,12 @@ public class RecoveryKeyResetPasswordController implements FxController {
|
||||
ExecutorService executor, //
|
||||
@Named("keyRecoveryOwner") Stage owner, @RecoveryKeyWindow StringProperty recoveryKey, //
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_EXPERT_SETTINGS) Lazy<Scene> recoverExpertSettingsScene, //
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_RECOVER) Lazy<Scene> recoverykeyRecoverScene, //
|
||||
FxApplicationWindows appWindows, //
|
||||
MasterkeyFileAccess masterkeyFileAccess, //
|
||||
VaultListManager vaultListManager, //
|
||||
@Named("shorteningThreshold") IntegerProperty shorteningThreshold, //
|
||||
@Named("recoverType") RecoveryActionType recoverType, //
|
||||
@Named("recoverType") ObjectProperty<RecoveryActionType> recoverType, //
|
||||
@Named("cipherCombo") ObjectProperty<CryptorProvider.Scheme> cipherCombo,//
|
||||
ResourceBundle resourceBundle, Dialogs dialogs) {
|
||||
this.window = window;
|
||||
@@ -83,6 +89,7 @@ public class RecoveryKeyResetPasswordController implements FxController {
|
||||
this.executor = executor;
|
||||
this.recoveryKey = recoveryKey;
|
||||
this.recoverExpertSettingsScene = recoverExpertSettingsScene;
|
||||
this.recoverykeyRecoverScene = recoverykeyRecoverScene;
|
||||
this.appWindows = appWindows;
|
||||
this.masterkeyFileAccess = masterkeyFileAccess;
|
||||
this.vaultListManager = vaultListManager;
|
||||
@@ -92,25 +99,35 @@ public class RecoveryKeyResetPasswordController implements FxController {
|
||||
this.resourceBundle = resourceBundle;
|
||||
this.dialogs = dialogs;
|
||||
this.owner = owner;
|
||||
initButtonText(recoverType);
|
||||
}
|
||||
|
||||
private void initButtonText(RecoveryActionType type) {
|
||||
if (type == RecoveryActionType.RESTORE_MASTERKEY) {
|
||||
buttonText.set(resourceBundle.getString("generic.button.close"));
|
||||
} else {
|
||||
buttonText.set(resourceBundle.getString("generic.button.back"));
|
||||
@FXML
|
||||
public void initialize() {
|
||||
switch (recoverType.get()) {
|
||||
case RESTORE_MASTERKEY -> {
|
||||
nextButton.setText(resourceBundle.getString("recoveryKey.recover.recoverBtn"));
|
||||
nextButton.setOnAction((_) -> resetPassword());
|
||||
}
|
||||
case RESTORE_ALL -> {
|
||||
nextButton.setText(resourceBundle.getString("recoveryKey.recover.recoverBtn"));
|
||||
nextButton.setOnAction((_) -> restorePassword());
|
||||
}
|
||||
case RESET_PASSWORD -> {
|
||||
nextButton.setText(resourceBundle.getString("recoveryKey.recover.resetBtn"));
|
||||
nextButton.setOnAction((_) -> resetPassword());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void close() {
|
||||
if (recoverType.equals(RecoveryActionType.RESTORE_MASTERKEY)) {
|
||||
window.close();
|
||||
} else {
|
||||
window.setScene(recoverExpertSettingsScene.get());
|
||||
switch (recoverType.get()) {
|
||||
case RESTORE_ALL -> window.setScene(recoverExpertSettingsScene.get());
|
||||
case RESTORE_MASTERKEY, RESET_PASSWORD -> window.setScene(recoverykeyRecoverScene.get());
|
||||
default -> window.close();
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void restorePassword() {
|
||||
try (RecoveryDirectory recoveryDirectory = RecoveryDirectory.create(vault.getPath())) {
|
||||
@@ -123,16 +140,14 @@ public class RecoveryKeyResetPasswordController implements FxController {
|
||||
CryptoFsInitializer.init(recoveryPath, masterkey, shorteningThreshold.get(), cipherCombo.get());
|
||||
}
|
||||
|
||||
recoveryDirectory.moveRecoveredFiles();
|
||||
recoveryDirectory.moveRecoveredFile(MASTERKEY_FILENAME);
|
||||
recoveryDirectory.moveRecoveredFile(VAULTCONFIG_FILENAME);
|
||||
|
||||
if (!vaultListManager.containsVault(vault.getPath())) {
|
||||
vaultListManager.add(vault.getPath());
|
||||
}
|
||||
window.close();
|
||||
dialogs.prepareRecoverPasswordSuccess(window, owner, resourceBundle)
|
||||
.setTitleKey("recoveryKey.recoverVaultConfig.title")
|
||||
.setMessageKey("recoveryKey.recover.resetVaultConfigSuccess.message")
|
||||
.build().showAndWait();
|
||||
dialogs.prepareRecoverPasswordSuccess(window, owner, resourceBundle).setTitleKey("recoveryKey.recoverVaultConfig.title").setMessageKey("recoveryKey.recover.resetVaultConfigSuccess.message").build().showAndWait();
|
||||
|
||||
} catch (IOException | CryptoException e) {
|
||||
LOG.error("Recovery process failed", e);
|
||||
@@ -148,14 +163,12 @@ public class RecoveryKeyResetPasswordController implements FxController {
|
||||
|
||||
task.setOnSucceeded(_ -> {
|
||||
LOG.info("Used recovery key to reset password for {}.", vault.getDisplayablePath());
|
||||
if (vault.getState().equals(org.cryptomator.common.vaults.VaultState.Value.MASTERKEY_MISSING)) {
|
||||
dialogs.prepareRecoverPasswordSuccess(window, owner, resourceBundle)
|
||||
.setTitleKey("recoveryKey.recoverMasterkey.title")
|
||||
.setMessageKey("recoveryKey.recover.resetMasterkeyFileSuccess.message")
|
||||
.build().showAndWait();
|
||||
if (recoverType.get().equals(RecoveryActionType.RESET_PASSWORD)) {
|
||||
window.close();
|
||||
dialogs.prepareRecoverPasswordSuccess(window, owner, resourceBundle).build().showAndWait();
|
||||
} else {
|
||||
dialogs.prepareRecoverPasswordSuccess(window, owner, resourceBundle)
|
||||
.build().showAndWait();
|
||||
window.close();
|
||||
dialogs.prepareRecoverPasswordSuccess(window, owner, resourceBundle).setTitleKey("recoveryKey.recoverMasterkey.title").setMessageKey("recoveryKey.recover.resetMasterkeyFileSuccess.message").build().showAndWait();
|
||||
}
|
||||
window.close();
|
||||
});
|
||||
@@ -185,6 +198,7 @@ public class RecoveryKeyResetPasswordController implements FxController {
|
||||
public boolean isPasswordSufficientAndMatching() {
|
||||
return newPasswordController.isGoodPassword();
|
||||
}
|
||||
|
||||
private final ReadOnlyBooleanWrapper vaultConfigMissing = new ReadOnlyBooleanWrapper();
|
||||
|
||||
public ReadOnlyBooleanProperty vaultConfigMissingProperty() {
|
||||
|
||||
@@ -44,7 +44,7 @@ public class RecoveryKeyValidateController implements FxController {
|
||||
private final ObjectProperty<RecoveryKeyState> recoveryKeyState;
|
||||
private final ObjectProperty<CryptorProvider.Scheme> cipherCombo;
|
||||
private final AutoCompleter autoCompleter;
|
||||
private final RecoveryActionType recoverType;
|
||||
private final ObjectProperty<RecoveryActionType> recoverType;
|
||||
private final MasterkeyFileAccess masterkeyFileAccess;
|
||||
|
||||
private volatile boolean isWrongKey;
|
||||
@@ -55,7 +55,7 @@ public class RecoveryKeyValidateController implements FxController {
|
||||
@Nullable VaultConfig.UnverifiedVaultConfig vaultConfig, //
|
||||
StringProperty recoveryKey, //
|
||||
RecoveryKeyFactory recoveryKeyFactory, //
|
||||
@Named("recoverType") RecoveryActionType recoverType, //
|
||||
@Named("recoverType") ObjectProperty<RecoveryActionType> recoverType, //
|
||||
@Named("cipherCombo") ObjectProperty<CryptorProvider.Scheme> cipherCombo,//
|
||||
MasterkeyFileAccess masterkeyFileAccess) {
|
||||
this.vault = vault;
|
||||
@@ -135,8 +135,8 @@ public class RecoveryKeyValidateController implements FxController {
|
||||
}
|
||||
|
||||
private void validateRecoveryKey() {
|
||||
switch (recoverType) {
|
||||
case RESTORE_VAULT_CONFIG -> {
|
||||
switch (recoverType.get()) {
|
||||
case RESTORE_ALL, RESTORE_VAULT_CONFIG -> {
|
||||
try{
|
||||
var combo = MasterkeyService.validateRecoveryKeyAndDetectCombo(recoveryKeyFactory, vault, recoveryKey.get(), masterkeyFileAccess);
|
||||
combo.ifPresent(cipherCombo::set);
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.common.StageFactory;
|
||||
import org.cryptomator.ui.keyloading.KeyLoadingComponent;
|
||||
import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
|
||||
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.inject.Named;
|
||||
@@ -27,7 +28,7 @@ import javafx.stage.Stage;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@Module(subcomponents = {KeyLoadingComponent.class})
|
||||
@Module(subcomponents = {KeyLoadingComponent.class, RecoveryKeyComponent.class})
|
||||
abstract class UnlockModule {
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.cryptomator.ui.forgetpassword.ForgetPasswordComponent;
|
||||
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
@@ -50,12 +49,12 @@ public class MasterkeyOptionsController implements FxController {
|
||||
|
||||
@FXML
|
||||
public void showRecoveryKey() {
|
||||
recoveryKeyWindow.create(vault, window, RecoveryActionType.SHOW_KEY).showRecoveryKeyCreationWindow();
|
||||
recoveryKeyWindow.create(vault, window, new SimpleObjectProperty<>(RecoveryActionType.SHOW_KEY)).showRecoveryKeyCreationWindow();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void showRecoverVaultDialog() {
|
||||
recoveryKeyWindow.create(vault, window, RecoveryActionType.RESET_PASSWORD).showRecoveryKeyRecoverWindow();
|
||||
recoveryKeyWindow.create(vault, window, new SimpleObjectProperty<>(RecoveryActionType.RESET_PASSWORD)).showRecoveryKeyRecoverWindow();
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<Insets bottom="6" top="6"/>
|
||||
</padding>
|
||||
</Label>
|
||||
<FormattedLabel format="%recoveryKey.create.description" arg1="${controller.vault.displayName}" wrapText="true">
|
||||
<FormattedLabel fx:id="descriptionLabel" format="%recoveryKey.create.description" arg1="${controller.vault.displayName}" wrapText="true">
|
||||
<padding>
|
||||
<Insets bottom="6"/>
|
||||
</padding>
|
||||
@@ -49,8 +49,8 @@
|
||||
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
|
||||
<buttons>
|
||||
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
|
||||
<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" defaultButton="true" onAction="#createRecoveryKey" disable="${passwordField.text.empty}"/>
|
||||
<Button fx:id="cancelButton" text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
|
||||
<Button fx:id="nextButton" text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" defaultButton="true" onAction="#createRecoveryKey" disable="${passwordField.text.empty}"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</VBox>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<?import javafx.scene.control.CheckBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.image.Image?>
|
||||
<?import javafx.scene.control.ToggleGroup?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
@@ -13,6 +14,7 @@
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.control.RadioButton?>
|
||||
<VBox xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.recoverykey.RecoveryKeyOnboardingController"
|
||||
@@ -33,10 +35,10 @@
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="12"/>
|
||||
</padding>
|
||||
<Label text="%recoveryKey.recoverVaultConfig.title" styleClass="label-extra-large"/>
|
||||
<Label fx:id="titleLabel" text="%recoveryKey.recoverVaultConfig.title" styleClass="label-extra-large"/>
|
||||
<Region minHeight="15"/>
|
||||
<VBox>
|
||||
<Label text="%recoveryKey.recover.onBoarding.message" wrapText="true"/>
|
||||
<Label fx:id="messageLabel" text="%recoveryKey.recover.onBoarding.message" wrapText="true"/>
|
||||
<GridPane alignment="CENTER_LEFT" >
|
||||
<padding>
|
||||
<Insets left="6"/>
|
||||
@@ -53,19 +55,28 @@
|
||||
<Label text="1." GridPane.rowIndex="0" GridPane.columnIndex="0" />
|
||||
<Label text="%recoveryKey.recover.onBoarding.intro1" wrapText="true" GridPane.rowIndex="0" GridPane.columnIndex="1" />
|
||||
<Label text="2." GridPane.rowIndex="1" GridPane.columnIndex="0" />
|
||||
<Label text="%recoveryKey.recover.onBoarding.intro2" wrapText="true" GridPane.rowIndex="1" GridPane.columnIndex="1" />
|
||||
<Label text="3." GridPane.rowIndex="2" GridPane.columnIndex="0" />
|
||||
<Label text="%recoveryKey.recover.onBoarding.intro3" wrapText="true" GridPane.rowIndex="2" GridPane.columnIndex="1" />
|
||||
<Label fx:id="secondTextDesc" text="%recoveryKey.recover.onBoarding.intro2" wrapText="true" GridPane.rowIndex="1" GridPane.columnIndex="1" />
|
||||
<Label fx:id="thirdTextIndex" text="3." GridPane.rowIndex="2" GridPane.columnIndex="0" />
|
||||
<Label fx:id="thirdTextDesc" text="%recoveryKey.recover.onBoarding.intro3" wrapText="true" GridPane.rowIndex="2" GridPane.columnIndex="1" />
|
||||
</GridPane>
|
||||
<Region minHeight="15"/>
|
||||
<CheckBox text="%recoveryKey.recover.onBoarding.affirmation" fx:id="affirmationBox"/>
|
||||
<VBox fx:id="chooseMethodeBox">
|
||||
<Label text="%recoveryKey.recover.onBoarding.chooseMethod"/>
|
||||
<RadioButton fx:id="recoveryKeyRadio" text="%recoveryKey.recover.onBoarding.useRecoveryKey">
|
||||
<toggleGroup>
|
||||
<ToggleGroup fx:id="methodToggleGroup"/>
|
||||
</toggleGroup>
|
||||
</RadioButton>
|
||||
<RadioButton fx:id="passwordRadio" text="%recoveryKey.recover.onBoarding.usePassword"/>
|
||||
</VBox>
|
||||
<CheckBox fx:id="affirmationBox" text="%recoveryKey.recover.onBoarding.affirmation"/>
|
||||
</VBox>
|
||||
</VBox>
|
||||
</HBox>
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
|
||||
<buttons>
|
||||
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
|
||||
<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" disable="${!affirmationBox.selected}" defaultButton="true" onAction="#next"/>
|
||||
<Button fx:id="nextButton" text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" disable="${!affirmationBox.selected}" defaultButton="true" onAction="#next"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</children>
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
<Region VBox.vgrow="ALWAYS"/>
|
||||
|
||||
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+BX">
|
||||
<buttons>
|
||||
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
|
||||
<Button fx:id="cancelButton" text="%generic.button.back" ButtonBar.buttonData="BACK_PREVIOUS" cancelButton="true" onAction="#close"/>
|
||||
<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" defaultButton="true" onAction="#recover" disable="${!controller.validateController.recoveryKeyCorrect}"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
|
||||
@@ -24,9 +24,8 @@
|
||||
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+CI">
|
||||
<buttons>
|
||||
<Button text="${controller.buttonText}" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
|
||||
<Button text="%recoveryKey.recover.resetBtn" ButtonBar.buttonData="FINISH" defaultButton="true" onAction="#resetPassword" managed="${!controller.vaultConfigMissing}" disable="${!controller.passwordSufficientAndMatching}"/>
|
||||
<Button text="%recoveryKey.recover.recoverBtn" ButtonBar.buttonData="FINISH" defaultButton="true" onAction="#restorePassword" managed="${controller.vaultConfigMissing}" disable="${!controller.passwordSufficientAndMatching}"/>
|
||||
<Button fx:id="backButton" text="%generic.button.back" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
|
||||
<Button fx:id="nextButton" text="%recoveryKey.recover.recoverBtn" ButtonBar.buttonData="FINISH" defaultButton="true" disable="${!controller.passwordSufficientAndMatching}"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</VBox>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<?import javafx.scene.Group?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import org.cryptomator.ui.controls.FormattedLabel?>
|
||||
<?import javafx.scene.control.CheckBox?>
|
||||
<HBox xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.keyloading.masterkeyfile.ChooseMasterkeyFileController"
|
||||
@@ -40,12 +41,13 @@
|
||||
</padding>
|
||||
</Label>
|
||||
<FormattedLabel format="%unlock.chooseMasterkey.description" arg1="${controller.displayName}" wrapText="true"/>
|
||||
<CheckBox fx:id="restoreInsteadCheckBox" text="%unlock.chooseMasterkey.restoreInstead" wrapText="true"/>
|
||||
|
||||
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
|
||||
<buttons>
|
||||
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#cancel"/>
|
||||
<Button text="%generic.button.choose" ButtonBar.buttonData="NEXT_FORWARD" defaultButton="true" onAction="#proceed"/>
|
||||
<Button fx:id="chooseButton" text="%generic.button.choose" ButtonBar.buttonData="NEXT_FORWARD" defaultButton="true" onAction="#proceed"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</VBox>
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
<fx:include VBox.vgrow="ALWAYS" source="vault_detail_missing.fxml" visible="${controller.vault.missing}" managed="${controller.vault.missing}"/>
|
||||
<fx:include VBox.vgrow="ALWAYS" source="vault_detail_needsmigration.fxml" visible="${controller.vault.needsMigration}" managed="${controller.vault.needsMigration}"/>
|
||||
<fx:include VBox.vgrow="ALWAYS" source="vault_detail_unknownerror.fxml" visible="${controller.vault.unknownError}" managed="${controller.vault.unknownError}"/>
|
||||
<fx:include VBox.vgrow="ALWAYS" source="vault_detail_missing_masterkey.fxml" visible="${controller.vault.missingMasterkey}" managed="${controller.vault.missingMasterkey}"/>
|
||||
<fx:include VBox.vgrow="ALWAYS" source="vault_detail_missing_vault_config.fxml" visible="${controller.vault.missingVaultConfig}" managed="${controller.vault.missingVaultConfig}"/>
|
||||
</children>
|
||||
</VBox>
|
||||
|
||||
@@ -29,6 +29,11 @@
|
||||
<FontAwesome5IconView glyph="REDO"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Button text="Select Masterkey" minWidth="120" onAction="#unlock">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="MAGIC"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Button text="%main.vaultDetail.missingMasterkey.restore" minWidth="120" onAction="#restoreMasterkey">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="MAGIC"/>
|
||||
|
||||
@@ -135,6 +135,7 @@ unlock.unlockBtn=Unlock
|
||||
## Select
|
||||
unlock.chooseMasterkey.message=Masterkey file not found
|
||||
unlock.chooseMasterkey.description=Cryptomator could not find the masterkey file for vault "%s". Please choose the key file manually.
|
||||
unlock.chooseMasterkey.restoreInstead=Restore instead... blablabla
|
||||
unlock.chooseMasterkey.filePickerTitle=Select Masterkey File
|
||||
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator Masterkey
|
||||
## Success
|
||||
@@ -511,6 +512,7 @@ vaultOptions.hub.convertBtn=Convert to Password-Based Vault
|
||||
recoveryKey.display.title=Show Recovery Key
|
||||
recoveryKey.create.message=Password required
|
||||
recoveryKey.create.description=Enter the password for "%s" to show its recovery key.
|
||||
recoveryKey.recover.description=Enter the password for "%s" to recover the vault config.
|
||||
recoveryKey.display.description=The following recovery key can be used to restore access to "%s":
|
||||
recoveryKey.display.StorageHints=Keep it somewhere very secure, e.g.:\n • Store it using a password manager\n • Save it on a USB flash drive\n • Print it on paper
|
||||
## Reset Password
|
||||
@@ -547,6 +549,9 @@ recoveryKey.recover.onBoarding.confirm=Use RecoveryKey
|
||||
recoveryKey.recover.onBoarding.intro1=Ensure all files are completely synced.
|
||||
recoveryKey.recover.onBoarding.intro2=You will need the Recovery Key of the vault.
|
||||
recoveryKey.recover.onBoarding.intro3=A new vault password and possible some expert settings.
|
||||
recoveryKey.recover.onBoarding.chooseMethod=Choose recovery method:
|
||||
recoveryKey.recover.onBoarding.useRecoveryKey=Use Recovery Key
|
||||
recoveryKey.recover.onBoarding.usePassword=Use Password
|
||||
recoveryKey.recover.onBoarding.affirmation=I have read and understood the above information
|
||||
|
||||
|
||||
@@ -568,6 +573,7 @@ passwordStrength.messageLabel.1=Weak
|
||||
passwordStrength.messageLabel.2=Fair
|
||||
passwordStrength.messageLabel.3=Strong
|
||||
passwordStrength.messageLabel.4=Very strong
|
||||
password.promptText=Enter password
|
||||
|
||||
# Quit
|
||||
quit.title=Quit Application
|
||||
|
||||
Reference in New Issue
Block a user