Began vault recovery wizard

This commit is contained in:
Sebastian Stenzel
2020-02-19 17:27:07 +01:00
parent 35207de7cc
commit d7edfd13a7
14 changed files with 130 additions and 253 deletions

View File

@@ -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"), //

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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 {
}

View File

@@ -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 {
}

View File

@@ -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();
}

View File

@@ -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)

View File

@@ -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());
}
}

View File

@@ -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];

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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>

View 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 &quot;%s&quot;:" 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>