mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-04-20 01:26:52 -04:00
Began vault recovery wizard
This commit is contained in:
@@ -20,6 +20,7 @@ public enum FxmlFile {
|
||||
PREFERENCES("/fxml/preferences.fxml"), //
|
||||
QUIT("/fxml/quit.fxml"), //
|
||||
RECOVERYKEY_CREATE("/fxml/recoverykey_create.fxml"), //
|
||||
RECOVERYKEY_RECOVER("/fxml/recoverykey_recover.fxml"), //
|
||||
RECOVERYKEY_SUCCESS("/fxml/recoverykey_success.fxml"), //
|
||||
RECOVER_VAULT("/fxml/recovervault.fxml"),// TODO
|
||||
REMOVE_VAULT("/fxml/remove_vault.fxml"), //
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package org.cryptomator.ui.recovervault;
|
||||
|
||||
import dagger.BindsInstance;
|
||||
import dagger.Lazy;
|
||||
import dagger.Subcomponent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
@RecoverVaultScoped
|
||||
@Subcomponent(modules = {RecoverVaultModule.class})
|
||||
public interface RecoverVaultComponent {
|
||||
|
||||
@RecoverVaultWindow
|
||||
Stage window();
|
||||
|
||||
@FxmlScene(FxmlFile.RECOVER_VAULT)
|
||||
Lazy<Scene> scene();
|
||||
|
||||
default void showRecoverVaultWindow() {
|
||||
Stage stage = window();
|
||||
stage.setScene(scene().get());
|
||||
stage.sizeToScene();
|
||||
stage.show();
|
||||
}
|
||||
|
||||
@Subcomponent.Builder
|
||||
interface Builder {
|
||||
|
||||
@BindsInstance
|
||||
Builder vault(@RecoverVaultWindow Vault vault);
|
||||
|
||||
@BindsInstance
|
||||
Builder owner(@Named("recoverVaultOwner") Stage owner);
|
||||
|
||||
RecoverVaultComponent build();
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package org.cryptomator.ui.recovervault;
|
||||
|
||||
import dagger.Lazy;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.stage.Stage;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@RecoverVaultScoped
|
||||
public class RecoverVaultController implements FxController {
|
||||
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(RecoverVaultController.class);
|
||||
|
||||
private final Stage window;
|
||||
private final Lazy<Scene> successScene;
|
||||
private final Vault vault;
|
||||
private StringProperty recoveryKey;
|
||||
|
||||
public TextArea textarea;
|
||||
|
||||
@Inject
|
||||
public RecoverVaultController(@RecoverVaultWindow Stage window, @FxmlScene(FxmlFile.RECOVER_VAULT) Lazy<Scene> successScene, @RecoverVaultWindow Vault vault, @RecoverVaultWindow StringProperty recoveryKey) {
|
||||
this.window = window;
|
||||
this.successScene = successScene;
|
||||
this.vault = vault;
|
||||
this.recoveryKey = recoveryKey;
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
textarea.getParagraphs().addListener(this::updateRecoveryKeyProperty);
|
||||
}
|
||||
|
||||
|
||||
private void updateRecoveryKeyProperty(@SuppressWarnings("unused") Observable observable) {
|
||||
recoveryKey.set(textarea.getText());
|
||||
}
|
||||
|
||||
|
||||
@FXML
|
||||
public void close() {
|
||||
window.close();
|
||||
}
|
||||
|
||||
public void recoverData(ActionEvent actionEvent) {
|
||||
//TODO: CryptoAPI call, show progress bar
|
||||
}
|
||||
|
||||
/* Getter/Setter */
|
||||
|
||||
public Vault getVault() {
|
||||
return vault;
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package org.cryptomator.ui.recovervault;
|
||||
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import dagger.multibindings.IntoMap;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import org.cryptomator.ui.common.DefaultSceneFactory;
|
||||
import org.cryptomator.ui.common.FXMLLoaderFactory;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxControllerKey;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@Module
|
||||
abstract class RecoverVaultModule {
|
||||
|
||||
@Provides
|
||||
@RecoverVaultWindow
|
||||
@RecoverVaultScoped
|
||||
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
|
||||
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@RecoverVaultWindow
|
||||
@RecoverVaultScoped
|
||||
static Stage provideStage(ResourceBundle resourceBundle, @Named("windowIcons") List<Image> windowIcons, @Named("recoverVaultOwner") Stage owner) {
|
||||
Stage stage = new Stage();
|
||||
//TODO stage.setTitle(resourceBundle.getString("recoverVault.title"));
|
||||
stage.setTitle("TODO recover Vault");
|
||||
stage.setResizable(false);
|
||||
stage.initModality(Modality.WINDOW_MODAL);
|
||||
stage.initOwner(owner);
|
||||
stage.getIcons().addAll(windowIcons);
|
||||
return stage;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@RecoverVaultWindow
|
||||
@RecoverVaultScoped
|
||||
static StringProperty provideRecoveryKeyProperty() {
|
||||
return new SimpleStringProperty();
|
||||
}
|
||||
|
||||
// ------------------
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.RECOVER_VAULT)
|
||||
@RecoverVaultScoped
|
||||
static Scene provideRecoverVaultScene(@RecoverVaultWindow FXMLLoaderFactory fxmlLoaders) {
|
||||
return fxmlLoaders.createScene("/fxml/recovervault.fxml");
|
||||
}
|
||||
|
||||
// ------------------
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(RecoverVaultController.class)
|
||||
abstract FxController bindRecoverVaultController(RecoverVaultController controller);
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package org.cryptomator.ui.recovervault;
|
||||
|
||||
import javax.inject.Scope;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Scope
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface RecoverVaultScoped {
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.cryptomator.ui.recovervault;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
@Qualifier
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
public @interface RecoverVaultWindow {
|
||||
|
||||
}
|
||||
@@ -21,11 +21,21 @@ public interface RecoveryKeyComponent {
|
||||
Stage window();
|
||||
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_CREATE)
|
||||
Lazy<Scene> scene();
|
||||
Lazy<Scene> creationScene();
|
||||
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_RECOVER)
|
||||
Lazy<Scene> recoverScene();
|
||||
|
||||
default void showRecoveryKeyCreationWindow() {
|
||||
Stage stage = window();
|
||||
stage.setScene(scene().get());
|
||||
stage.setScene(creationScene().get());
|
||||
stage.sizeToScene();
|
||||
stage.show();
|
||||
}
|
||||
|
||||
default void showRecoveryKeyRecoverWindow() {
|
||||
Stage stage = window();
|
||||
stage.setScene(recoverScene().get());
|
||||
stage.sizeToScene();
|
||||
stage.show();
|
||||
}
|
||||
|
||||
@@ -70,6 +70,13 @@ abstract class RecoveryKeyModule {
|
||||
return fxmlLoaders.createScene("/fxml/recoverykey_success.fxml");
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.RECOVERYKEY_RECOVER)
|
||||
@RecoveryKeyScoped
|
||||
static Scene provideRecoveryKeyRecoverScene(@RecoveryKeyWindow FXMLLoaderFactory fxmlLoaders) {
|
||||
return fxmlLoaders.createScene("/fxml/recoverykey_recover.fxml");
|
||||
}
|
||||
|
||||
// ------------------
|
||||
|
||||
@Binds
|
||||
@@ -84,6 +91,11 @@ abstract class RecoveryKeyModule {
|
||||
return new RecoveryKeyDisplayController(window, vault.getDisplayableName(), recoveryKey.get());
|
||||
}
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(RecoveryKeyRecoverController.class)
|
||||
abstract FxController provideRecoveryKeyRecoverController(RecoveryKeyRecoverController controller);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(RecoveryKeySuccessController.class)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.cryptomator.ui.recoverykey;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.stage.Stage;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@RecoveryKeyScoped
|
||||
public class RecoveryKeyRecoverController implements FxController {
|
||||
|
||||
private final Stage window;
|
||||
private final Vault vault;
|
||||
private final StringProperty recoveryKey;
|
||||
private final RecoveryKeyFactory recoveryKeyFactory;
|
||||
private final BooleanBinding validRecoveryKey;
|
||||
|
||||
public TextArea textarea;
|
||||
|
||||
@Inject
|
||||
public RecoveryKeyRecoverController(@RecoveryKeyWindow Stage window, @RecoveryKeyWindow Vault vault, @RecoveryKeyWindow StringProperty recoveryKey, RecoveryKeyFactory recoveryKeyFactory) {
|
||||
this.window = window;
|
||||
this.vault = vault;
|
||||
this.recoveryKey = recoveryKey;
|
||||
this.recoveryKeyFactory = recoveryKeyFactory;
|
||||
this.validRecoveryKey = Bindings.createBooleanBinding(this::isValidRecoveryKey, recoveryKey);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
textarea.textProperty().bindBidirectional(recoveryKey);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void close() {
|
||||
window.close();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void recover() {
|
||||
recoveryKeyFactory.validateRecoveryKey(textarea.getText());
|
||||
|
||||
}
|
||||
|
||||
/* Getter/Setter */
|
||||
|
||||
public Vault getVault() {
|
||||
return vault;
|
||||
}
|
||||
|
||||
public BooleanBinding validRecoveryKeyProperty() {
|
||||
return validRecoveryKey;
|
||||
}
|
||||
|
||||
public boolean isValidRecoveryKey() {
|
||||
return recoveryKeyFactory.validateRecoveryKey(recoveryKey.get());
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package org.cryptomator.ui.recoverykey;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@@ -78,6 +79,7 @@ class WordEncoder {
|
||||
* @throws IllegalArgumentException If the encoded string doesn't consist of a multiple of two words or one of the words is unknown to this encoder.
|
||||
*/
|
||||
public byte[] decode(String encoded) {
|
||||
Preconditions.checkArgument(!Strings.isNullOrEmpty(encoded));
|
||||
List<String> splitted = Splitter.on(DELIMITER).omitEmptyStrings().splitToList(encoded);
|
||||
Preconditions.checkArgument(splitted.size() % 2 == 0, "%s needs to be a multiple of two words", encoded);
|
||||
byte[] result = new byte[splitted.size() / 2 * 3];
|
||||
|
||||
@@ -6,7 +6,6 @@ import javafx.stage.Stage;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.changepassword.ChangePasswordComponent;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.recovervault.RecoverVaultComponent;
|
||||
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -18,16 +17,14 @@ public class GeneralVaultOptionsController implements FxController {
|
||||
private final Stage window;
|
||||
private final ChangePasswordComponent.Builder changePasswordWindow;
|
||||
private final RecoveryKeyComponent.Builder recoveryKeyWindow;
|
||||
private final RecoverVaultComponent.Builder recoverVaultWindow;
|
||||
public CheckBox unlockOnStartupCheckbox;
|
||||
|
||||
@Inject
|
||||
GeneralVaultOptionsController(@VaultOptionsWindow Vault vault, @VaultOptionsWindow Stage window, ChangePasswordComponent.Builder changePasswordWindow, RecoveryKeyComponent.Builder recoveryKeyWindow, RecoverVaultComponent.Builder recoverVaultWindow) {
|
||||
GeneralVaultOptionsController(@VaultOptionsWindow Vault vault, @VaultOptionsWindow Stage window, ChangePasswordComponent.Builder changePasswordWindow, RecoveryKeyComponent.Builder recoveryKeyWindow) {
|
||||
this.vault = vault;
|
||||
this.window = window;
|
||||
this.changePasswordWindow = changePasswordWindow;
|
||||
this.recoveryKeyWindow = recoveryKeyWindow;
|
||||
this.recoverVaultWindow = recoverVaultWindow;
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -47,6 +44,6 @@ public class GeneralVaultOptionsController implements FxController {
|
||||
|
||||
@FXML
|
||||
public void showRecoverVaultDialogue(){
|
||||
recoverVaultWindow.vault(vault).owner(window).build().showRecoverVaultWindow();
|
||||
recoveryKeyWindow.vault(vault).owner(window).build().showRecoveryKeyRecoverWindow();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.cryptomator.ui.common.FxControllerKey;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.mainwindow.MainWindow;
|
||||
import org.cryptomator.ui.recovervault.RecoverVaultComponent;
|
||||
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
|
||||
|
||||
import javax.inject.Named;
|
||||
@@ -26,7 +25,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@Module(subcomponents = {ChangePasswordComponent.class, RecoveryKeyComponent.class, RecoverVaultComponent.class})
|
||||
@Module(subcomponents = {ChangePasswordComponent.class, RecoveryKeyComponent.class})
|
||||
abstract class VaultOptionsModule {
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ButtonBar?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import org.cryptomator.ui.controls.FormattedLabel?>
|
||||
<?import javafx.scene.control.CheckBox?>
|
||||
<?import javafx.scene.control.TextArea?>
|
||||
<VBox xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="org.cryptomator.ui.recovervault.RecoverVaultController"
|
||||
minWidth="400"
|
||||
maxWidth="400"
|
||||
minHeight="145"
|
||||
spacing="12"
|
||||
alignment="TOP_CENTER">
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="12"/>
|
||||
</padding>
|
||||
<children>
|
||||
<VBox spacing="6">
|
||||
<FormattedLabel format="TODO If you lost/forgot your password for vault %s, you can get access with your backup passphrase" arg1="${controller.vault.displayableName}" wrapText="true"/>
|
||||
<CheckBox fx:id="confirmation" text="TODO I have understood that all data will be decrypted. This cannot be undone."/>
|
||||
<TextArea editable="true" wrapText="true" prefRowCount="4" fx:id="textarea" promptText="TODO Paste here your backup passphrase."/>
|
||||
</VBox>
|
||||
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="C+X">
|
||||
<buttons>
|
||||
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
|
||||
<Button text="TODO Proceed" ButtonBar.buttonData="NEXT_FORWARD" cancelButton="false" onAction="#recoverData" disable="${!confirmation.selected}"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</VBox>
|
||||
</children>
|
||||
</VBox>
|
||||
37
main/ui/src/main/resources/fxml/recoverykey_recover.fxml
Normal file
37
main/ui/src/main/resources/fxml/recoverykey_recover.fxml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ButtonBar?>
|
||||
<?import javafx.scene.control.TextArea?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import org.cryptomator.ui.controls.FormattedLabel?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<VBox xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="org.cryptomator.ui.recoverykey.RecoveryKeyRecoverController"
|
||||
minWidth="400"
|
||||
maxWidth="400"
|
||||
minHeight="145"
|
||||
spacing="12"
|
||||
alignment="TOP_LEFT">
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="12"/>
|
||||
</padding>
|
||||
<children>
|
||||
<FormattedLabel format="TODO Enter your revoery key for "%s":" arg1="${controller.vault.displayableName}" wrapText="true"/>
|
||||
|
||||
<TextArea wrapText="true" prefRowCount="4" fx:id="textarea"/>
|
||||
|
||||
<Region VBox.vgrow="ALWAYS"/>
|
||||
|
||||
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="C+X">
|
||||
<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="#recover" disable="${!controller.validRecoveryKey}" />
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</VBox>
|
||||
</children>
|
||||
</VBox>
|
||||
Reference in New Issue
Block a user