mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-11-04 21:36:45 +00:00
add change password button, delete backups option on changing password
This commit is contained in:
parent
03ec0c9da1
commit
3bd2f69157
5 changed files with 82 additions and 19 deletions
|
@ -22,17 +22,24 @@ public class WalletPasswordDialog extends Dialog<SecureString> {
|
||||||
private final CustomPasswordField passwordConfirm;
|
private final CustomPasswordField passwordConfirm;
|
||||||
private final CheckBox backupExisting;
|
private final CheckBox backupExisting;
|
||||||
private final CheckBox changePassword;
|
private final CheckBox changePassword;
|
||||||
|
private final CheckBox deleteBackups;
|
||||||
|
private boolean addingPassword;
|
||||||
|
|
||||||
public WalletPasswordDialog(PasswordRequirement requirement) {
|
public WalletPasswordDialog(PasswordRequirement requirement) {
|
||||||
this(null, requirement);
|
this(null, requirement);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WalletPasswordDialog(String walletName, PasswordRequirement requirement) {
|
public WalletPasswordDialog(String walletName, PasswordRequirement requirement) {
|
||||||
|
this(null, requirement, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WalletPasswordDialog(String walletName, PasswordRequirement requirement, boolean suggestChangePassword) {
|
||||||
this.requirement = requirement;
|
this.requirement = requirement;
|
||||||
this.password = (CustomPasswordField)TextFields.createClearablePasswordField();
|
this.password = (CustomPasswordField)TextFields.createClearablePasswordField();
|
||||||
this.passwordConfirm = (CustomPasswordField)TextFields.createClearablePasswordField();
|
this.passwordConfirm = (CustomPasswordField)TextFields.createClearablePasswordField();
|
||||||
this.backupExisting = new CheckBox("Backup existing wallet first");
|
this.backupExisting = new CheckBox("Backup existing wallet first");
|
||||||
this.changePassword = new CheckBox("Change password");
|
this.changePassword = new CheckBox("Change password");
|
||||||
|
this.deleteBackups = new CheckBox("Delete any backups");
|
||||||
|
|
||||||
final DialogPane dialogPane = getDialogPane();
|
final DialogPane dialogPane = getDialogPane();
|
||||||
setTitle("Wallet Password" + (walletName != null ? " - " + walletName : ""));
|
setTitle("Wallet Password" + (walletName != null ? " - " + walletName : ""));
|
||||||
|
@ -52,13 +59,21 @@ public class WalletPasswordDialog extends Dialog<SecureString> {
|
||||||
content.getChildren().add(password);
|
content.getChildren().add(password);
|
||||||
content.getChildren().add(passwordConfirm);
|
content.getChildren().add(passwordConfirm);
|
||||||
|
|
||||||
if(requirement == PasswordRequirement.UPDATE_EMPTY || requirement == PasswordRequirement.UPDATE_SET) {
|
|
||||||
content.getChildren().add(backupExisting);
|
|
||||||
backupExisting.setSelected(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(requirement == PasswordRequirement.UPDATE_SET) {
|
if(requirement == PasswordRequirement.UPDATE_SET) {
|
||||||
content.getChildren().add(changePassword);
|
content.getChildren().add(changePassword);
|
||||||
|
changePassword.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
backupExisting.setVisible(!newValue);
|
||||||
|
});
|
||||||
|
changePassword.setSelected(suggestChangePassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(requirement == PasswordRequirement.UPDATE_EMPTY || requirement == PasswordRequirement.UPDATE_SET) {
|
||||||
|
backupExisting.managedProperty().bind(backupExisting.visibleProperty());
|
||||||
|
deleteBackups.managedProperty().bind(deleteBackups.visibleProperty());
|
||||||
|
deleteBackups.visibleProperty().bind(backupExisting.visibleProperty().not());
|
||||||
|
content.getChildren().addAll(backupExisting, deleteBackups);
|
||||||
|
backupExisting.setSelected(true);
|
||||||
|
deleteBackups.setSelected(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
dialogPane.setContent(content);
|
dialogPane.setContent(content);
|
||||||
|
@ -87,10 +102,14 @@ public class WalletPasswordDialog extends Dialog<SecureString> {
|
||||||
okButton.setText("No Password");
|
okButton.setText("No Password");
|
||||||
passwordConfirm.setVisible(false);
|
passwordConfirm.setVisible(false);
|
||||||
passwordConfirm.setManaged(false);
|
passwordConfirm.setManaged(false);
|
||||||
|
backupExisting.setVisible(true);
|
||||||
|
addingPassword = false;
|
||||||
} else {
|
} else {
|
||||||
okButton.setText("Set Password");
|
okButton.setText("Set Password");
|
||||||
passwordConfirm.setVisible(true);
|
passwordConfirm.setVisible(true);
|
||||||
passwordConfirm.setManaged(true);
|
passwordConfirm.setManaged(true);
|
||||||
|
backupExisting.setVisible(false);
|
||||||
|
addingPassword = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -103,13 +122,17 @@ public class WalletPasswordDialog extends Dialog<SecureString> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBackupExisting() {
|
public boolean isBackupExisting() {
|
||||||
return backupExisting.isSelected();
|
return !(addingPassword || isChangePassword()) && backupExisting.isSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isChangePassword() {
|
public boolean isChangePassword() {
|
||||||
return changePassword.isSelected();
|
return changePassword.isSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDeleteBackups() {
|
||||||
|
return (addingPassword || isChangePassword()) && deleteBackups.isSelected();
|
||||||
|
}
|
||||||
|
|
||||||
public enum PasswordRequirement {
|
public enum PasswordRequirement {
|
||||||
LOAD("Please enter the wallet password:", "Unlock"),
|
LOAD("Please enter the wallet password:", "Unlock"),
|
||||||
UPDATE_NEW("Add a password to the wallet?\nLeave empty for none:", "No Password"),
|
UPDATE_NEW("Add a password to the wallet?\nLeave empty for none:", "No Password"),
|
||||||
|
|
|
@ -184,6 +184,18 @@ public class Storage {
|
||||||
Files.copy(walletFile, backupFile);
|
Files.copy(walletFile, backupFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteBackups() {
|
||||||
|
File backupDir = getWalletsBackupDir();
|
||||||
|
File[] unencryptedBackups = backupDir.listFiles((dir, name) -> {
|
||||||
|
int dotIndex = name.lastIndexOf('.');
|
||||||
|
return name.startsWith(walletFile.getName() + "-") && name.substring(walletFile.getName().length() + 1, dotIndex > -1 ? dotIndex : name.length()).matches("[0-9]+");
|
||||||
|
});
|
||||||
|
|
||||||
|
for(File unencryptedBackup : unencryptedBackups) {
|
||||||
|
unencryptedBackup.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ECKey getEncryptionPubKey() {
|
public ECKey getEncryptionPubKey() {
|
||||||
return encryptionPubKey;
|
return encryptionPubKey;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.sparrowwallet.sparrow.wallet;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.sparrow.AppServices;
|
import com.sparrowwallet.sparrow.AppServices;
|
||||||
|
import com.sparrowwallet.sparrow.io.Storage;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.control.ButtonBar;
|
import javafx.scene.control.ButtonBar;
|
||||||
import javafx.scene.control.ButtonType;
|
import javafx.scene.control.ButtonType;
|
||||||
|
@ -11,10 +12,11 @@ import org.controlsfx.tools.Borders;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class AdvancedDialog extends Dialog<Void> {
|
public class AdvancedDialog extends Dialog<Boolean> {
|
||||||
public AdvancedDialog(Wallet wallet) {
|
public AdvancedDialog(WalletForm walletForm) {
|
||||||
final DialogPane dialogPane = getDialogPane();
|
final DialogPane dialogPane = getDialogPane();
|
||||||
AppServices.setStageIcon(dialogPane.getScene().getWindow());
|
AppServices.setStageIcon(dialogPane.getScene().getWindow());
|
||||||
|
Wallet wallet = walletForm.getWallet();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FXMLLoader advancedLoader = new FXMLLoader(AppServices.class.getResource("wallet/advanced.fxml"));
|
FXMLLoader advancedLoader = new FXMLLoader(AppServices.class.getResource("wallet/advanced.fxml"));
|
||||||
|
@ -22,11 +24,18 @@ public class AdvancedDialog extends Dialog<Void> {
|
||||||
AdvancedController settingsAdvancedController = advancedLoader.getController();
|
AdvancedController settingsAdvancedController = advancedLoader.getController();
|
||||||
settingsAdvancedController.initializeView(wallet);
|
settingsAdvancedController.initializeView(wallet);
|
||||||
|
|
||||||
|
boolean noPassword = Storage.NO_PASSWORD_KEY.equals(walletForm.getStorage().getEncryptionPubKey());
|
||||||
final ButtonType closeButtonType = new javafx.scene.control.ButtonType("Close", ButtonBar.ButtonData.CANCEL_CLOSE);
|
final ButtonType closeButtonType = new javafx.scene.control.ButtonType("Close", ButtonBar.ButtonData.CANCEL_CLOSE);
|
||||||
dialogPane.getButtonTypes().addAll(closeButtonType);
|
final ButtonType passwordButtonType = new javafx.scene.control.ButtonType(noPassword ? "Add Password..." : "Change Password...", ButtonBar.ButtonData.LEFT);
|
||||||
|
dialogPane.getButtonTypes().add(closeButtonType);
|
||||||
|
if(wallet.isValid()) {
|
||||||
|
dialogPane.getButtonTypes().add(passwordButtonType);
|
||||||
|
}
|
||||||
|
|
||||||
dialogPane.setPrefWidth(400);
|
dialogPane.setPrefWidth(400);
|
||||||
dialogPane.setPrefHeight(300);
|
dialogPane.setPrefHeight(300);
|
||||||
|
|
||||||
|
setResultConverter(dialogButton -> dialogButton == passwordButtonType);
|
||||||
}
|
}
|
||||||
catch(IOException e) {
|
catch(IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
|
|
@ -183,7 +183,7 @@ public class SettingsController extends WalletFormController implements Initiali
|
||||||
apply.setOnAction(event -> {
|
apply.setOnAction(event -> {
|
||||||
revert.setDisable(true);
|
revert.setDisable(true);
|
||||||
apply.setDisable(true);
|
apply.setDisable(true);
|
||||||
saveWallet(false);
|
saveWallet(false, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
setFieldsFromWallet(walletForm.getWallet());
|
setFieldsFromWallet(walletForm.getWallet());
|
||||||
|
@ -303,8 +303,13 @@ public class SettingsController extends WalletFormController implements Initiali
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showAdvanced(ActionEvent event) {
|
public void showAdvanced(ActionEvent event) {
|
||||||
AdvancedDialog advancedDialog = new AdvancedDialog(walletForm.getWallet());
|
AdvancedDialog advancedDialog = new AdvancedDialog(walletForm);
|
||||||
advancedDialog.showAndWait();
|
Optional<Boolean> optApply = advancedDialog.showAndWait();
|
||||||
|
if(optApply.isPresent() && optApply.get() && walletForm.getWallet().isValid()) {
|
||||||
|
revert.setDisable(true);
|
||||||
|
apply.setDisable(true);
|
||||||
|
saveWallet(false, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -355,7 +360,7 @@ public class SettingsController extends WalletFormController implements Initiali
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveWallet(boolean changePassword) {
|
private void saveWallet(boolean changePassword, boolean suggestChangePassword) {
|
||||||
ECKey existingPubKey = walletForm.getStorage().getEncryptionPubKey();
|
ECKey existingPubKey = walletForm.getStorage().getEncryptionPubKey();
|
||||||
|
|
||||||
WalletPasswordDialog.PasswordRequirement requirement;
|
WalletPasswordDialog.PasswordRequirement requirement;
|
||||||
|
@ -380,7 +385,7 @@ public class SettingsController extends WalletFormController implements Initiali
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WalletPasswordDialog dlg = new WalletPasswordDialog(requirement);
|
WalletPasswordDialog dlg = new WalletPasswordDialog(null, requirement, suggestChangePassword);
|
||||||
Optional<SecureString> password = dlg.showAndWait();
|
Optional<SecureString> password = dlg.showAndWait();
|
||||||
if(password.isPresent()) {
|
if(password.isPresent()) {
|
||||||
if(dlg.isBackupExisting()) {
|
if(dlg.isBackupExisting()) {
|
||||||
|
@ -399,7 +404,7 @@ public class SettingsController extends WalletFormController implements Initiali
|
||||||
try {
|
try {
|
||||||
walletForm.getStorage().setEncryptionPubKey(Storage.NO_PASSWORD_KEY);
|
walletForm.getStorage().setEncryptionPubKey(Storage.NO_PASSWORD_KEY);
|
||||||
walletForm.saveAndRefresh();
|
walletForm.saveAndRefresh();
|
||||||
if(requirement == WalletPasswordDialog.PasswordRequirement.UPDATE_NEW) {
|
if(requirement == WalletPasswordDialog.PasswordRequirement.UPDATE_NEW || requirement == WalletPasswordDialog.PasswordRequirement.UPDATE_CHANGE) {
|
||||||
EventManager.get().post(new RequestOpenWalletsEvent());
|
EventManager.get().post(new RequestOpenWalletsEvent());
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -425,18 +430,28 @@ public class SettingsController extends WalletFormController implements Initiali
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
key = new Key(encryptionFullKey.getPrivKeyBytes(), walletForm.getStorage().getKeyDeriver().getSalt(), EncryptionType.Deriver.ARGON2);
|
||||||
|
|
||||||
if(dlg.isChangePassword()) {
|
if(dlg.isChangePassword()) {
|
||||||
|
if(dlg.isDeleteBackups()) {
|
||||||
|
walletForm.deleteBackups();
|
||||||
|
}
|
||||||
|
|
||||||
walletForm.getStorage().setEncryptionPubKey(null);
|
walletForm.getStorage().setEncryptionPubKey(null);
|
||||||
saveWallet(true);
|
walletForm.getWallet().decrypt(key);
|
||||||
|
saveWallet(true, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
key = new Key(encryptionFullKey.getPrivKeyBytes(), walletForm.getStorage().getKeyDeriver().getSalt(), EncryptionType.Deriver.ARGON2);
|
|
||||||
walletForm.getWallet().encrypt(key);
|
walletForm.getWallet().encrypt(key);
|
||||||
|
|
||||||
walletForm.getStorage().setEncryptionPubKey(encryptionPubKey);
|
walletForm.getStorage().setEncryptionPubKey(encryptionPubKey);
|
||||||
walletForm.saveAndRefresh();
|
walletForm.saveAndRefresh();
|
||||||
if(requirement == WalletPasswordDialog.PasswordRequirement.UPDATE_NEW) {
|
|
||||||
|
if(dlg.isDeleteBackups()) {
|
||||||
|
walletForm.deleteBackups();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(requirement == WalletPasswordDialog.PasswordRequirement.UPDATE_NEW || requirement == WalletPasswordDialog.PasswordRequirement.UPDATE_EMPTY) {
|
||||||
EventManager.get().post(new RequestOpenWalletsEvent());
|
EventManager.get().post(new RequestOpenWalletsEvent());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -75,6 +75,10 @@ public class WalletForm {
|
||||||
storage.backupWallet();
|
storage.backupWallet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteBackups() {
|
||||||
|
storage.deleteBackups();
|
||||||
|
}
|
||||||
|
|
||||||
public void refreshHistory(Integer blockHeight, Wallet pastWallet) {
|
public void refreshHistory(Integer blockHeight, Wallet pastWallet) {
|
||||||
refreshHistory(blockHeight, pastWallet, null);
|
refreshHistory(blockHeight, pastWallet, null);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue