/*
*
* Copyright 2014 http://Bither.net
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* /
*/
package net.bither.viewsystem.froms;
import net.bither.BitherSetting;
import net.bither.BitherUI;
import net.bither.bitherj.crypto.PasswordSeed;
import net.bither.bitherj.crypto.SecureCharSequence;
import net.bither.bitherj.runnable.EditPasswordThread;
import net.bither.bitherj.utils.Utils;
import net.bither.fonts.AwesomeIcon;
import net.bither.languages.MessageKey;
import net.bither.preference.UserPreference;
import net.bither.utils.LocaliserUtils;
import net.bither.utils.PasswordStrengthUtil;
import net.bither.viewsystem.TextBoxes;
import net.bither.viewsystem.base.Labels;
import net.bither.viewsystem.base.Panels;
import net.bither.viewsystem.dialogs.DialogConfirmTask;
import net.bither.viewsystem.dialogs.MessageDialog;
import net.bither.viewsystem.themes.Themes;
import net.miginfocom.swing.MigLayout;
import org.spongycastle.util.Arrays;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
public class ChangePasswordPanel extends WizardPanel {
private JPasswordField currentPassword;
private JLabel spinner;
private JPasswordField newPassword;
private JPasswordField repeatNewPassword;
private JLabel verificationStatusLabel;
private JLabel labStrength;
private JProgressBar pb;
public ChangePasswordPanel() {
super(MessageKey.SHOW_CHANGE_PASSWORD_WIZARD, AwesomeIcon.LOCK);
setOkAction(new ChangePasswordSubmitAction());
}
@Override
public void initialiseContent(JPanel panel) {
panel.setLayout(new MigLayout(
Panels.migXYLayout(),
"[]", // Column constraints
"[]10[]" // Row constraints
));
panel.add(Labels.newChangePasswordNote1(), "wrap");
panel.add(getenterPasswordMaV(), "wrap");
panel.add(getProgressPanel(), "align left,shrink,wrap");
panel.add(getNewPasswordPanel(), "wrap");
}
@Override
public void showPanel() {
super.showPanel();
currentPassword.requestFocus();
}
private JPanel getProgressPanel() {
JPanel pbPanel = Panels.newPanel();
pbPanel.setLayout(new MigLayout(
Panels.migXYLayout(),
"[]50[][]", // Column constraints
"[]" // Row constraints
));
pb = new JProgressBar();
Painter p = new Painter() {
@Override
public void paint(Graphics2D g, Object object, int width, int height) {
JProgressBar bar = (JProgressBar) object;
g.setColor(bar.getForeground());
g.fillRect(0, 1, width - 2, height - 2);
}
};
// install custom painter on the bar
UIDefaults properties = new UIDefaults();
properties.put("ProgressBar[Enabled].foregroundPainter", p);
pb.setBorderPainted(false);
pb.putClientProperty("Nimbus.Overrides", properties);
pb.setStringPainted(false);
pb.setMaximum(5);
pb.setVisible(false);
labStrength = Labels.newValueLabel("");
pbPanel.add(Labels.newChangePasswordNote2(), "align left,shrink");
pbPanel.add(pb, "align center,shrink");
pbPanel.add(labStrength, "align center,shrink");
return pbPanel;
}
private JPanel getenterPasswordMaV() {
JPanel panel = Panels.newPanel(
new MigLayout(
Panels.migXLayout(), // Layout
"[][][][]", // Columns
"[]" // Rows
));
// Keep track of the credentials fields
currentPassword = TextBoxes.newPassword();
// Provide an invisible tar pit spinner
spinner = Labels.newSpinner(Themes.currentTheme.fadedText(), BitherUI.NORMAL_PLUS_ICON_SIZE);
spinner.setVisible(false);
// Bind a document listener to allow instant update of UI to matched passwords
currentPassword.getDocument().addDocumentListener(
new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
updateModel();
}
@Override
public void removeUpdate(DocumentEvent e) {
updateModel();
}
@Override
public void changedUpdate(DocumentEvent e) {
updateModel();
}
/**
* Trigger any UI updates
*/
private void updateModel() {
// Reset the credentials background
currentPassword.setBackground(Themes.currentTheme.dataEntryBackground());
}
});
panel.add(currentPassword, "growx,h 32,push");
//panel.add(showButton, "shrink");
// Ensure the icon label is a size suitable for rotation
panel.add(spinner, BitherUI.NORMAL_PLUS_ICON_SIZE_MIG + ",wrap");
return panel;
}
private JPanel getNewPasswordPanel() {
JPanel panel = Panels.newPanel(
new MigLayout(
Panels.migXLayout(), // Layout
"[][][][]", // Columns (require 4 columns for alignment with EnterPasswordView)
"[][][]" // Rows
));
newPassword = TextBoxes.newPassword();
newPassword.setName(MessageKey.ENTER_NEW_PASSWORD.getKey());
repeatNewPassword = TextBoxes.newPassword();
repeatNewPassword.setName(MessageKey.RETYPE_NEW_PASSWORD.getKey());
// Bind a document listener to allow instant update of UI to matched passwords
newPassword.getDocument().addDocumentListener(
new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
updateModel();
}
@Override
public void removeUpdate(DocumentEvent e) {
updateModel();
}
@Override
public void changedUpdate(DocumentEvent e) {
updateModel();
}
private void updateModel() {
if (!pb.isVisible()) {
pb.setVisible(true);
}
SecureCharSequence secureCharSequence = new SecureCharSequence(newPassword.getPassword());
PasswordStrengthUtil.PasswordStrength strength = PasswordStrengthUtil.checkPassword
(secureCharSequence);
pb.setValue(strength.getValue() + 1);
pb.setForeground(strength.getColor());
labStrength.setText(strength.getName());
secureCharSequence.wipe();
}
}
);
// Bind a document listener to allow instant update of UI to matched passwords
repeatNewPassword.getDocument().addDocumentListener(
new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
updateModel();
}
@Override
public void removeUpdate(DocumentEvent e) {
updateModel();
}
@Override
public void changedUpdate(DocumentEvent e) {
updateModel();
}
private void updateModel() {
}
});
verificationStatusLabel = Labels.newVerificationStatus(".credentials", true);
verificationStatusLabel.setVisible(false);
panel.add(Labels.newEnterNewPassword());
panel.add(newPassword, " wrap");
panel.add(Labels.newRetypeNewPassword());
panel.add(repeatNewPassword, "wrap");
panel.add(verificationStatusLabel, "span 4,grow,push");
return panel;
}
public class ChangePasswordSubmitAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
// changePasswordPanel.clearMessages();
if (currentPassword.getPassword() == null || currentPassword.getPassword().length > BitherSetting.PASSWORD_LENGTH_MAX
|| currentPassword.getPassword().length < BitherSetting.PASSWORD_LENGTH_MIN) {
// Notify must enter the current password.
new MessageDialog(LocaliserUtils.getString("edit_password_enter_current_password")).showMsg();
return;
}
// Get the new passwords on the password fields.
if (newPassword.getPassword() == null || newPassword.getPassword().length > BitherSetting.PASSWORD_LENGTH_MAX
|| newPassword.getPassword().length < BitherSetting.PASSWORD_LENGTH_MIN) {
// Notify the user must enter a new password.
new MessageDialog(LocaliserUtils.getString("edit_password_enter_passwords")).showMsg();
return;
} else {
if (!Arrays.areEqual(newPassword.getPassword(), repeatNewPassword.getPassword())) {
// Notify user passwords are different.
new MessageDialog(LocaliserUtils.getString(
"edit_password_passwords_are_different")).showMsg();
return;
} else {
PasswordSeed passwordSeed = PasswordSeed.getPasswordSeed();
final SecureCharSequence currentCharSequence = new SecureCharSequence(currentPassword.getPassword());
if (!passwordSeed.checkPassword(currentCharSequence)) {
new MessageDialog(LocaliserUtils.getString("password_wrong")).showMsg();
return;
}
final SecureCharSequence newSequence = new SecureCharSequence(newPassword.getPassword());
PasswordStrengthUtil.PasswordStrength strength = PasswordStrengthUtil.checkPassword
(newSequence);
if (UserPreference.getInstance().getCheckPasswordStrength()) {
if (strength == PasswordStrengthUtil.PasswordStrength.Weak) {
String msg = Utils.format(LocaliserUtils.getString("password_strength_error"), strength.getName());
new MessageDialog(msg).showMsg();
return;
} else if (strength == PasswordStrengthUtil.PasswordStrength.Normal) {
String msg = Utils.format(LocaliserUtils.getString("password_strength_warning"), strength.getName());
DialogConfirmTask dialogConfirmTask = new DialogConfirmTask(msg, new Runnable() {
@Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
changePassword(currentCharSequence, newSequence);
}
});
}
});
dialogConfirmTask.pack();
dialogConfirmTask.setVisible(true);
return;
}
}
changePassword(currentCharSequence, newSequence);
}
}
}
private void changePassword(SecureCharSequence currentCharSequence, SecureCharSequence newSequence) {
spinner.setVisible(true);
EditPasswordThread editPasswordThread = new EditPasswordThread(currentCharSequence, newSequence, new EditPasswordThread.EditPasswordListener() {
@Override
public void onSuccess() {
// Success.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
spinner.setVisible(false);
closePanel();
new MessageDialog(LocaliserUtils.getString("edit_password_success")).showMsg();
}
});
}
@Override
public void onFailed() {
// Success.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
spinner.setVisible(false);
new MessageDialog(LocaliserUtils.getString("edit_password_fail")).showMsg();
}
});
}
});
editPasswordThread.start();
}
}
}