|
@@ -5,6 +5,7 @@
|
|
*
|
|
*
|
|
* Contributors:
|
|
* Contributors:
|
|
* Sebastian Stenzel - initial API and implementation
|
|
* Sebastian Stenzel - initial API and implementation
|
|
|
|
+ * Jean-Noël Charon - password strength meter
|
|
*******************************************************************************/
|
|
*******************************************************************************/
|
|
package org.cryptomator.ui.controllers;
|
|
package org.cryptomator.ui.controllers;
|
|
|
|
|
|
@@ -20,6 +21,8 @@ import javax.inject.Singleton;
|
|
|
|
|
|
import com.nulabinc.zxcvbn.Strength;
|
|
import com.nulabinc.zxcvbn.Strength;
|
|
import com.nulabinc.zxcvbn.Zxcvbn;
|
|
import com.nulabinc.zxcvbn.Zxcvbn;
|
|
|
|
+import javafx.beans.property.IntegerProperty;
|
|
|
|
+import javafx.beans.property.SimpleIntegerProperty;
|
|
import javafx.scene.control.Label;
|
|
import javafx.scene.control.Label;
|
|
import javafx.scene.paint.Color;
|
|
import javafx.scene.paint.Color;
|
|
import javafx.scene.shape.Rectangle;
|
|
import javafx.scene.shape.Rectangle;
|
|
@@ -29,6 +32,8 @@ import org.cryptomator.crypto.engine.UnsupportedVaultFormatException;
|
|
import org.cryptomator.ui.controls.SecPasswordField;
|
|
import org.cryptomator.ui.controls.SecPasswordField;
|
|
import org.cryptomator.ui.model.Vault;
|
|
import org.cryptomator.ui.model.Vault;
|
|
import org.cryptomator.ui.settings.Localization;
|
|
import org.cryptomator.ui.settings.Localization;
|
|
|
|
+import org.cryptomator.ui.util.PasswordStrengthUtil;
|
|
|
|
+import org.fxmisc.easybind.EasyBind;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
@@ -51,8 +56,7 @@ public class ChangePasswordController extends LocalizedFXMLViewController {
|
|
private final Application app;
|
|
private final Application app;
|
|
final ObjectProperty<Vault> vault = new SimpleObjectProperty<>();
|
|
final ObjectProperty<Vault> vault = new SimpleObjectProperty<>();
|
|
private Optional<ChangePasswordListener> listener = Optional.empty();
|
|
private Optional<ChangePasswordListener> listener = Optional.empty();
|
|
- private Zxcvbn zxcvbn = new Zxcvbn();
|
|
|
|
- private List<String> sanitizedInputs = new ArrayList();
|
|
|
|
|
|
+ final IntegerProperty passwordStrength = new SimpleIntegerProperty(); // 0-4
|
|
|
|
|
|
@Inject
|
|
@Inject
|
|
public ChangePasswordController(Application app, Localization localization) {
|
|
public ChangePasswordController(Application app, Localization localization) {
|
|
@@ -60,6 +64,9 @@ public class ChangePasswordController extends LocalizedFXMLViewController {
|
|
this.app = app;
|
|
this.app = app;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Inject
|
|
|
|
+ PasswordStrengthUtil strengthRater;
|
|
|
|
+
|
|
@FXML
|
|
@FXML
|
|
private SecPasswordField oldPasswordField;
|
|
private SecPasswordField oldPasswordField;
|
|
|
|
|
|
@@ -90,17 +97,14 @@ public class ChangePasswordController extends LocalizedFXMLViewController {
|
|
BooleanBinding newPasswordIsEmpty = newPasswordField.textProperty().isEmpty();
|
|
BooleanBinding newPasswordIsEmpty = newPasswordField.textProperty().isEmpty();
|
|
BooleanBinding passwordsDiffer = newPasswordField.textProperty().isNotEqualTo(retypePasswordField.textProperty());
|
|
BooleanBinding passwordsDiffer = newPasswordField.textProperty().isNotEqualTo(retypePasswordField.textProperty());
|
|
changePasswordButton.disableProperty().bind(oldPasswordIsEmpty.or(newPasswordIsEmpty.or(passwordsDiffer)));
|
|
changePasswordButton.disableProperty().bind(oldPasswordIsEmpty.or(newPasswordIsEmpty.or(passwordsDiffer)));
|
|
- newPasswordField.textProperty().addListener((observable, oldValue, newValue) -> {
|
|
|
|
- checkPasswordStrength(newValue);
|
|
|
|
- });
|
|
|
|
|
|
+ EasyBind.subscribe(newPasswordField.textProperty(), this::checkPasswordStrength);
|
|
|
|
|
|
- // default password strength bar visual properties
|
|
|
|
- passwordStrengthShape.setStroke(Color.GRAY);
|
|
|
|
- changeProgressBarAspect(0f, 0f, Color.web("#FF0000"));
|
|
|
|
- passwordStrengthLabel.setText(localization.getString("initialize.messageLabel.passwordStrength") + " : 0%");
|
|
|
|
|
|
+ strengthRater.setLocalization(localization);
|
|
|
|
|
|
- // preparing inputs for the password strength checker
|
|
|
|
- sanitizedInputs.add("cryptomator");
|
|
|
|
|
|
+ passwordStrengthShape.widthProperty().bind(EasyBind.map(passwordStrength, strengthRater::getWidth));
|
|
|
|
+ passwordStrengthShape.fillProperty().bind(EasyBind.map(passwordStrength, strengthRater::getStrengthColor));
|
|
|
|
+ passwordStrengthShape.strokeWidthProperty().bind(EasyBind.map(passwordStrength, strengthRater::getStrokeWidth));
|
|
|
|
+ passwordStrengthLabel.textProperty().bind(EasyBind.map(passwordStrength, strengthRater::getStrengthDescription));
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@@ -154,46 +158,8 @@ public class ChangePasswordController extends LocalizedFXMLViewController {
|
|
// ****************************************
|
|
// ****************************************
|
|
|
|
|
|
private void checkPasswordStrength(String password) {
|
|
private void checkPasswordStrength(String password) {
|
|
- int strengthPercentage = 0;
|
|
|
|
- if (StringUtils.isEmpty(password)) {
|
|
|
|
- changeProgressBarAspect(0f, 0f, Color.web("#FF0000"));
|
|
|
|
- passwordStrengthLabel.setText(localization.getString("initialize.messageLabel.passwordStrength") + " : " + strengthPercentage + "%");
|
|
|
|
- } else {
|
|
|
|
- Color color = Color.web("#FF0000");
|
|
|
|
- Strength strength = zxcvbn.measure(password, sanitizedInputs);
|
|
|
|
- switch (strength.getScore()) {
|
|
|
|
- case 0:
|
|
|
|
- strengthPercentage = 20;
|
|
|
|
- break;
|
|
|
|
- case 1:
|
|
|
|
- strengthPercentage = 40;
|
|
|
|
- color = Color.web("#FF8000");
|
|
|
|
- break;
|
|
|
|
- case 2:
|
|
|
|
- strengthPercentage = 60;
|
|
|
|
- color = Color.web("#FFBF00");
|
|
|
|
- break;
|
|
|
|
- case 3:
|
|
|
|
- strengthPercentage = 80;
|
|
|
|
- color = Color.web("#FFFF00");
|
|
|
|
- break;
|
|
|
|
- case 4:
|
|
|
|
- strengthPercentage = 100;
|
|
|
|
- color = Color.web("#BFFF00");
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- passwordStrengthLabel.setText(localization.getString("initialize.messageLabel.passwordStrength") + " : " + strengthPercentage + "%");
|
|
|
|
- changeProgressBarAspect(0.5f, strengthPercentage * 2.23f, color); // 2.23f is the factor used to get the width to fit the window
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private void changeProgressBarAspect(float strokeWidth, float length, Color color) {
|
|
|
|
- passwordStrengthShape.setFill(color);
|
|
|
|
- passwordStrengthShape.setStrokeWidth(strokeWidth);
|
|
|
|
- passwordStrengthShape.setWidth(length);
|
|
|
|
|
|
+ passwordStrength.set(strengthRater.computeRate(password));
|
|
}
|
|
}
|
|
-
|
|
|
|
/* Getter/Setter */
|
|
/* Getter/Setter */
|
|
|
|
|
|
public ChangePasswordListener getListener() {
|
|
public ChangePasswordListener getListener() {
|