Added support for the C CLI's ~/.mpw config file to speed up sign-in to the GUI.
This commit is contained in:
parent
cced75cdfe
commit
6808016ab7
@ -0,0 +1,32 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
|
import com.apple.eawt.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lhunath, 2014-06-10
|
||||||
|
*/
|
||||||
|
public class AppleGUI extends GUI {
|
||||||
|
|
||||||
|
public AppleGUI() {
|
||||||
|
|
||||||
|
Application application = Application.getApplication();
|
||||||
|
application.addAppEventListener( new AppForegroundListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appMovedToBackground(AppEvent.AppForegroundEvent arg0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appRaisedToForeground(AppEvent.AppForegroundEvent arg0) {
|
||||||
|
open();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
application.addAppEventListener( new AppReOpenedListener() {
|
||||||
|
@Override
|
||||||
|
public void appReOpened(AppEvent.AppReOpenedEvent arg0) {
|
||||||
|
open();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
|
import com.google.common.io.Resources;
|
||||||
|
import java.awt.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lhunath, 2014-06-11
|
||||||
|
*/
|
||||||
|
public abstract class AuthenticationPanel extends JPanel {
|
||||||
|
|
||||||
|
protected final UnlockFrame unlockFrame;
|
||||||
|
|
||||||
|
public AuthenticationPanel(final UnlockFrame unlockFrame) {
|
||||||
|
this.unlockFrame = unlockFrame;
|
||||||
|
|
||||||
|
setLayout( new BoxLayout( this, BoxLayout.PAGE_AXIS ) );
|
||||||
|
|
||||||
|
// Avatar
|
||||||
|
add( Box.createVerticalGlue() );
|
||||||
|
add( new JLabel( new ImageIcon( Resources.getResource( "media/Avatars/avatar-0.png" ) ) ) {
|
||||||
|
@Override
|
||||||
|
public Dimension getMaximumSize() {
|
||||||
|
return new Dimension( Integer.MAX_VALUE, Integer.MAX_VALUE );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
add( Box.createVerticalGlue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateUser() {
|
||||||
|
unlockFrame.setUser( getUser() );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract User getUser();
|
||||||
|
|
||||||
|
public Component getFocusComponent() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.io.CharStreams;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lhunath, 2014-06-11
|
||||||
|
*/
|
||||||
|
public class ConfigAuthenticationPanel extends AuthenticationPanel implements ItemListener, ActionListener {
|
||||||
|
|
||||||
|
private final JComboBox userField;
|
||||||
|
|
||||||
|
public ConfigAuthenticationPanel(final UnlockFrame unlockFrame) {
|
||||||
|
|
||||||
|
// User
|
||||||
|
super( unlockFrame );
|
||||||
|
JLabel userLabel = new JLabel( "User:" );
|
||||||
|
userLabel.setAlignmentX( LEFT_ALIGNMENT );
|
||||||
|
userLabel.setHorizontalAlignment( SwingConstants.CENTER );
|
||||||
|
userLabel.setVerticalAlignment( SwingConstants.BOTTOM );
|
||||||
|
add( userLabel );
|
||||||
|
|
||||||
|
userField = new JComboBox<User>( new DefaultComboBoxModel<>( readConfigUsers() ) ) {
|
||||||
|
@Override
|
||||||
|
public Dimension getMaximumSize() {
|
||||||
|
return new Dimension( Integer.MAX_VALUE, getPreferredSize().height );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
userField.setAlignmentX( LEFT_ALIGNMENT );
|
||||||
|
userField.addItemListener( this );
|
||||||
|
userField.addActionListener( this );
|
||||||
|
add( userField );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected User getUser() {
|
||||||
|
return (User) userField.getSelectedItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasConfigUsers() {
|
||||||
|
return new File( System.getProperty( "user.home" ), ".mpw" ).canRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
private User[] readConfigUsers() {
|
||||||
|
ImmutableList.Builder<User> users = ImmutableList.builder();
|
||||||
|
File mpwConfig = new File( System.getProperty( "user.home" ), ".mpw" );
|
||||||
|
try (FileReader mpwReader = new FileReader( mpwConfig )) {
|
||||||
|
for (String line : CharStreams.readLines( mpwReader )) {
|
||||||
|
if (line.startsWith( "#" ) || line.startsWith( "//" ) || line.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<String> fields = Splitter.on( ':' ).limit( 2 ).split( line ).iterator();
|
||||||
|
String userName = fields.next(), masterPassword = fields.next();
|
||||||
|
users.add( new User( userName, masterPassword ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Iterables.toArray( users.build(), User.class );
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void itemStateChanged(final ItemEvent e) {
|
||||||
|
updateUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(final ActionEvent e) {
|
||||||
|
updateUser();
|
||||||
|
unlockFrame.trySignIn( userField );
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.lyndir.lhunath.masterpassword;
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
import com.apple.eawt.*;
|
import com.google.common.base.Optional;
|
||||||
|
import com.lyndir.lhunath.opal.system.util.TypeUtils;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
@ -33,37 +34,18 @@ public class GUI implements UnlockFrame.SignInCallback {
|
|||||||
public static void main(final String[] args)
|
public static void main(final String[] args)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
|
// Apple
|
||||||
|
Optional<? extends GUI> appleGUI = TypeUtils.newInstance( AppleGUI.class );
|
||||||
|
if (appleGUI.isPresent()) {
|
||||||
|
appleGUI.get().open();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All others
|
||||||
new GUI().open();
|
new GUI().open();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GUI() {
|
void open() {
|
||||||
|
|
||||||
try {
|
|
||||||
getClass().getClassLoader().loadClass( "com.apple.eawt.Application" );
|
|
||||||
Application application = Application.getApplication();
|
|
||||||
application.addAppEventListener( new AppForegroundListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void appMovedToBackground(AppEvent.AppForegroundEvent arg0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void appRaisedToForeground(AppEvent.AppForegroundEvent arg0) {
|
|
||||||
open();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
application.addAppEventListener( new AppReOpenedListener() {
|
|
||||||
@Override
|
|
||||||
public void appReOpened(AppEvent.AppReOpenedEvent arg0) {
|
|
||||||
open();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException | NoClassDefFoundError ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void open() {
|
|
||||||
SwingUtilities.invokeLater( new Runnable() {
|
SwingUtilities.invokeLater( new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -77,9 +59,13 @@ public class GUI implements UnlockFrame.SignInCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean signedIn(final String userName, final String masterPassword) {
|
public boolean signedIn(final User user) {
|
||||||
final byte[] key = MasterPassword.keyForPassword( masterPassword, userName );
|
if (!user.hasKey()) {
|
||||||
passwordFrame = new PasswordFrame( new User( userName, key ) );
|
return false;
|
||||||
|
}
|
||||||
|
user.getKey();
|
||||||
|
|
||||||
|
passwordFrame = new PasswordFrame( user );
|
||||||
|
|
||||||
open();
|
open();
|
||||||
return true;
|
return true;
|
||||||
|
@ -40,7 +40,8 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
|||||||
root.setBorder( new EmptyBorder( 20, 20, 20, 20 ) );
|
root.setBorder( new EmptyBorder( 20, 20, 20, 20 ) );
|
||||||
|
|
||||||
// User
|
// User
|
||||||
add( new JLabel( strf( "Generating passwords for: %s", user.getName() ) ), BorderLayout.NORTH );
|
add( label = new JLabel( strf( "Generating passwords for: %s", user.getName() ) ), BorderLayout.NORTH );
|
||||||
|
label.setAlignmentX( LEFT_ALIGNMENT );
|
||||||
|
|
||||||
// Site
|
// Site
|
||||||
JPanel sitePanel = new JPanel();
|
JPanel sitePanel = new JPanel();
|
||||||
@ -49,13 +50,16 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
|||||||
add( sitePanel, BorderLayout.CENTER );
|
add( sitePanel, BorderLayout.CENTER );
|
||||||
|
|
||||||
// Site Name
|
// Site Name
|
||||||
sitePanel.add( new JLabel( "Site Name:", JLabel.LEADING ) );
|
sitePanel.add( label = new JLabel( "Site Name:", JLabel.LEADING ) );
|
||||||
|
label.setAlignmentX( LEFT_ALIGNMENT );
|
||||||
|
|
||||||
sitePanel.add( siteNameField = new JTextField() {
|
sitePanel.add( siteNameField = new JTextField() {
|
||||||
@Override
|
@Override
|
||||||
public Dimension getMaximumSize() {
|
public Dimension getMaximumSize() {
|
||||||
return new Dimension( Integer.MAX_VALUE, getPreferredSize().height );
|
return new Dimension( Integer.MAX_VALUE, getPreferredSize().height );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
siteNameField.setAlignmentX( LEFT_ALIGNMENT );
|
||||||
siteNameField.getDocument().addDocumentListener( this );
|
siteNameField.getDocument().addDocumentListener( this );
|
||||||
siteNameField.addActionListener( new ActionListener() {
|
siteNameField.addActionListener( new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -86,7 +90,9 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
|||||||
return new Dimension( 50, getPreferredSize().height );
|
return new Dimension( 50, getPreferredSize().height );
|
||||||
}
|
}
|
||||||
} ) );
|
} ) );
|
||||||
|
siteTypeField.setAlignmentX( LEFT_ALIGNMENT );
|
||||||
siteTypeField.setSelectedItem( MPElementType.GeneratedLong );
|
siteTypeField.setSelectedItem( MPElementType.GeneratedLong );
|
||||||
|
siteCounterField.setAlignmentX( LEFT_ALIGNMENT );
|
||||||
siteCounterField.addChangeListener( new ChangeListener() {
|
siteCounterField.addChangeListener( new ChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void stateChanged(final ChangeEvent e) {
|
public void stateChanged(final ChangeEvent e) {
|
||||||
@ -96,6 +102,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
|||||||
|
|
||||||
// Password
|
// Password
|
||||||
add( passwordLabel = new JLabel( " ", JLabel.CENTER ), BorderLayout.SOUTH );
|
add( passwordLabel = new JLabel( " ", JLabel.CENTER ), BorderLayout.SOUTH );
|
||||||
|
passwordLabel.setAlignmentX( LEFT_ALIGNMENT );
|
||||||
passwordLabel.setFont( passwordLabel.getFont().deriveFont( 40f ) );
|
passwordLabel.setFont( passwordLabel.getFont().deriveFont( 40f ) );
|
||||||
|
|
||||||
pack();
|
pack();
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.DocumentEvent;
|
||||||
|
import javax.swing.event.DocumentListener;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lhunath, 2014-06-11
|
||||||
|
*/
|
||||||
|
public class TextAuthenticationPanel extends AuthenticationPanel implements DocumentListener, ActionListener {
|
||||||
|
|
||||||
|
private final JTextField userNameField;
|
||||||
|
private final JPasswordField masterPasswordField;
|
||||||
|
|
||||||
|
public TextAuthenticationPanel(final UnlockFrame unlockFrame) {
|
||||||
|
|
||||||
|
// User Name
|
||||||
|
super( unlockFrame );
|
||||||
|
JLabel userNameLabel = new JLabel( "User Name:" );
|
||||||
|
userNameLabel.setAlignmentX( Component.LEFT_ALIGNMENT );
|
||||||
|
userNameLabel.setHorizontalAlignment( SwingConstants.CENTER );
|
||||||
|
userNameLabel.setVerticalAlignment( SwingConstants.BOTTOM );
|
||||||
|
add( userNameLabel );
|
||||||
|
|
||||||
|
userNameField = new JTextField() {
|
||||||
|
@Override
|
||||||
|
public Dimension getMaximumSize() {
|
||||||
|
return new Dimension( Integer.MAX_VALUE, getPreferredSize().height );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
userNameField.setAlignmentX( Component.LEFT_ALIGNMENT );
|
||||||
|
userNameField.getDocument().addDocumentListener( this );
|
||||||
|
userNameField.addActionListener( this );
|
||||||
|
add( userNameField );
|
||||||
|
|
||||||
|
// Master Password
|
||||||
|
JLabel masterPasswordLabel = new JLabel( "Master Password:" );
|
||||||
|
masterPasswordLabel.setAlignmentX( Component.LEFT_ALIGNMENT );
|
||||||
|
masterPasswordLabel.setHorizontalAlignment( SwingConstants.CENTER );
|
||||||
|
masterPasswordLabel.setVerticalAlignment( SwingConstants.BOTTOM );
|
||||||
|
add( masterPasswordLabel );
|
||||||
|
|
||||||
|
masterPasswordField = new JPasswordField() {
|
||||||
|
@Override
|
||||||
|
public Dimension getMaximumSize() {
|
||||||
|
return new Dimension( Integer.MAX_VALUE, getPreferredSize().height );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
masterPasswordField.setAlignmentX( Component.LEFT_ALIGNMENT );
|
||||||
|
masterPasswordField.addActionListener( this );
|
||||||
|
masterPasswordField.getDocument().addDocumentListener( this );
|
||||||
|
add( masterPasswordField );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getFocusComponent() {
|
||||||
|
return userNameField;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected User getUser() {
|
||||||
|
return new User( userNameField.getText(), new String( masterPasswordField.getPassword() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertUpdate(final DocumentEvent e) {
|
||||||
|
updateUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeUpdate(final DocumentEvent e) {
|
||||||
|
updateUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changedUpdate(final DocumentEvent e) {
|
||||||
|
updateUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(final ActionEvent e) {
|
||||||
|
updateUser();
|
||||||
|
unlockFrame.trySignIn(userNameField,masterPasswordField );
|
||||||
|
}
|
||||||
|
}
|
@ -1,96 +1,48 @@
|
|||||||
package com.lyndir.lhunath.masterpassword;
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
import com.google.common.io.Resources;
|
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
|
||||||
|
|
||||||
import com.lyndir.lhunath.masterpassword.util.Components;
|
import com.lyndir.lhunath.masterpassword.util.Components;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.*;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.*;
|
import javax.swing.border.*;
|
||||||
import javax.swing.event.DocumentEvent;
|
|
||||||
import javax.swing.event.DocumentListener;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lhunath, 2014-06-08
|
* @author lhunath, 2014-06-08
|
||||||
*/
|
*/
|
||||||
public class UnlockFrame extends JFrame implements DocumentListener {
|
public class UnlockFrame extends JFrame {
|
||||||
|
|
||||||
private static final ExecutorService executor = Executors.newSingleThreadExecutor();
|
private static final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
private final SignInCallback signInCallback;
|
private final SignInCallback signInCallback;
|
||||||
private final JPanel root;
|
private final JPanel root;
|
||||||
private final JLabel avatarView;
|
private final JButton signInButton;
|
||||||
private final JTextField userNameField;
|
private final JPanel authenticationContainer;
|
||||||
private final JTextField masterPasswordField;
|
private boolean useConfig;
|
||||||
private final JButton signInButton;
|
public User user;
|
||||||
|
|
||||||
public UnlockFrame(final SignInCallback signInCallback)
|
public UnlockFrame(final SignInCallback signInCallback)
|
||||||
throws HeadlessException {
|
throws HeadlessException {
|
||||||
super( "Unlock Master Password" );
|
super( "Unlock Master Password" );
|
||||||
this.signInCallback = signInCallback;
|
this.signInCallback = signInCallback;
|
||||||
|
|
||||||
JLabel label;
|
|
||||||
|
|
||||||
setDefaultCloseOperation( DISPOSE_ON_CLOSE );
|
setDefaultCloseOperation( DISPOSE_ON_CLOSE );
|
||||||
setContentPane( root = new JPanel( new BorderLayout( 20, 20 ) ) );
|
setContentPane( root = new JPanel( new BorderLayout( 20, 20 ) ) );
|
||||||
root.setBorder( new EmptyBorder( 20, 20, 20, 20 ) );
|
root.setBorder( new EmptyBorder( 20, 20, 20, 20 ) );
|
||||||
|
|
||||||
JPanel userAndPassword = new JPanel();
|
authenticationContainer = new JPanel();
|
||||||
userAndPassword.setLayout( new BoxLayout( userAndPassword, BoxLayout.PAGE_AXIS ) );
|
authenticationContainer.setLayout( new BoxLayout( authenticationContainer, BoxLayout.PAGE_AXIS ) );
|
||||||
userAndPassword.setBorder( new CompoundBorder( new EtchedBorder( EtchedBorder.RAISED ), new EmptyBorder( 8, 8, 8, 8 ) ) );
|
authenticationContainer.setBorder( new CompoundBorder( new EtchedBorder( EtchedBorder.RAISED ), new EmptyBorder( 8, 8, 8, 8 ) ) );
|
||||||
add( userAndPassword, BorderLayout.CENTER );
|
add( authenticationContainer );
|
||||||
|
|
||||||
// Avatar
|
|
||||||
userAndPassword.add( Box.createVerticalGlue() );
|
|
||||||
userAndPassword.add( avatarView = new JLabel( new ImageIcon( Resources.getResource( "media/Avatars/avatar-0.png" ) ) ) {
|
|
||||||
@Override
|
|
||||||
public Dimension getMaximumSize() {
|
|
||||||
return new Dimension( Integer.MAX_VALUE, Integer.MAX_VALUE );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
userAndPassword.add( Box.createVerticalGlue() );
|
|
||||||
|
|
||||||
// User Name
|
|
||||||
userAndPassword.add( label = new JLabel( "User Name:" ) );
|
|
||||||
label.setHorizontalAlignment( SwingConstants.CENTER );
|
|
||||||
label.setVerticalAlignment( SwingConstants.BOTTOM );
|
|
||||||
userAndPassword.add( userNameField = new JTextField() {
|
|
||||||
@Override
|
|
||||||
public Dimension getMaximumSize() {
|
|
||||||
return new Dimension( Integer.MAX_VALUE, getPreferredSize().height );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
userNameField.getDocument().addDocumentListener( this );
|
|
||||||
userNameField.addActionListener( new AbstractAction() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(final ActionEvent e) {
|
|
||||||
trySignIn();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
// Master Password
|
|
||||||
userAndPassword.add( label = new JLabel( "Master Password:" ) );
|
|
||||||
label.setHorizontalAlignment( SwingConstants.CENTER );
|
|
||||||
label.setVerticalAlignment( SwingConstants.BOTTOM );
|
|
||||||
userAndPassword.add( masterPasswordField = new JPasswordField() {
|
|
||||||
@Override
|
|
||||||
public Dimension getMaximumSize() {
|
|
||||||
return new Dimension( Integer.MAX_VALUE, getPreferredSize().height );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
masterPasswordField.getDocument().addDocumentListener( this );
|
|
||||||
masterPasswordField.addActionListener( new AbstractAction() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(final ActionEvent e) {
|
|
||||||
trySignIn();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
// Sign In
|
// Sign In
|
||||||
add( Components.boxLayout( BoxLayout.LINE_AXIS, Box.createGlue(), signInButton = new JButton( "Sign In" ), Box.createGlue() ),
|
root.add( Components.boxLayout( BoxLayout.LINE_AXIS, Box.createGlue(), signInButton = new JButton( "Sign In" ), Box.createGlue() ),
|
||||||
BorderLayout.SOUTH );
|
BorderLayout.SOUTH );
|
||||||
|
signInButton.setAlignmentX( LEFT_ALIGNMENT );
|
||||||
signInButton.addActionListener( new AbstractAction() {
|
signInButton.addActionListener( new AbstractAction() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(final ActionEvent e) {
|
public void actionPerformed(final ActionEvent e) {
|
||||||
@ -98,43 +50,91 @@ public class UnlockFrame extends JFrame implements DocumentListener {
|
|||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
checkSignIn();
|
useConfig = ConfigAuthenticationPanel.hasConfigUsers();
|
||||||
|
createAuthenticationPanel();
|
||||||
pack();
|
|
||||||
setMinimumSize( getSize() );
|
|
||||||
setPreferredSize( new Dimension( 300, 300 ) );
|
|
||||||
pack();
|
|
||||||
|
|
||||||
setLocationByPlatform( true );
|
setLocationByPlatform( true );
|
||||||
setLocationRelativeTo( null );
|
setLocationRelativeTo( null );
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkSignIn() {
|
private void repack() {
|
||||||
String userName = userNameField.getText();
|
setPreferredSize( null );
|
||||||
String masterPassword = masterPasswordField.getText();
|
pack();
|
||||||
|
setMinimumSize( getSize() );
|
||||||
|
setPreferredSize( new Dimension( 300, 300 ) );
|
||||||
|
pack();
|
||||||
|
}
|
||||||
|
|
||||||
boolean enabled = !userName.isEmpty() && !masterPassword.isEmpty();
|
private void createAuthenticationPanel() {
|
||||||
|
authenticationContainer.removeAll();
|
||||||
|
|
||||||
|
final AuthenticationPanel authenticationPanel;
|
||||||
|
if (useConfig) {
|
||||||
|
authenticationPanel = new ConfigAuthenticationPanel( this );
|
||||||
|
} else {
|
||||||
|
authenticationPanel = new TextAuthenticationPanel( this );
|
||||||
|
}
|
||||||
|
authenticationPanel.updateUser();
|
||||||
|
authenticationContainer.add( authenticationPanel, BorderLayout.CENTER );
|
||||||
|
|
||||||
|
final JCheckBox configCheckBox = new JCheckBox( "Use Config File" );
|
||||||
|
configCheckBox.setAlignmentX( LEFT_ALIGNMENT );
|
||||||
|
configCheckBox.setSelected( useConfig );
|
||||||
|
configCheckBox.addItemListener( new ItemListener() {
|
||||||
|
@Override
|
||||||
|
public void itemStateChanged(final ItemEvent e) {
|
||||||
|
useConfig = configCheckBox.isSelected();
|
||||||
|
SwingUtilities.invokeLater( new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
createAuthenticationPanel();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
authenticationContainer.add( configCheckBox );
|
||||||
|
checkSignIn();
|
||||||
|
validate();
|
||||||
|
repack();
|
||||||
|
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater( new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
ifNotNullElse( authenticationPanel.getFocusComponent(), signInButton ).requestFocusInWindow();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
checkSignIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean checkSignIn() {
|
||||||
|
boolean enabled = user != null && !user.getName().isEmpty() && user.hasKey();
|
||||||
signInButton.setEnabled( enabled );
|
signInButton.setEnabled( enabled );
|
||||||
|
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trySignIn() {
|
void trySignIn(final JComponent... signInComponents) {
|
||||||
if (!checkSignIn())
|
if (!checkSignIn()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final String userName = userNameField.getText();
|
for (JComponent signInComponent : signInComponents) {
|
||||||
final String masterPassword = masterPasswordField.getText();
|
signInComponent.setEnabled( false );
|
||||||
|
}
|
||||||
|
|
||||||
userNameField.setEnabled( false );
|
|
||||||
masterPasswordField.setEnabled( false );
|
|
||||||
signInButton.setEnabled( false );
|
signInButton.setEnabled( false );
|
||||||
signInButton.setText( "Signing In..." );
|
signInButton.setText( "Signing In..." );
|
||||||
|
|
||||||
executor.submit( new Runnable() {
|
executor.submit( new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
final boolean success = signInCallback.signedIn( userName, masterPassword );
|
final boolean success = signInCallback.signedIn( user );
|
||||||
|
|
||||||
SwingUtilities.invokeLater( new Runnable() {
|
SwingUtilities.invokeLater( new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -143,9 +143,10 @@ public class UnlockFrame extends JFrame implements DocumentListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
userNameField.setEnabled( true );
|
|
||||||
masterPasswordField.setEnabled( true );
|
|
||||||
signInButton.setText( "Sign In" );
|
signInButton.setText( "Sign In" );
|
||||||
|
for (JComponent signInComponent : signInComponents) {
|
||||||
|
signInComponent.setEnabled( true );
|
||||||
|
}
|
||||||
checkSignIn();
|
checkSignIn();
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
@ -153,23 +154,8 @@ public class UnlockFrame extends JFrame implements DocumentListener {
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void insertUpdate(final DocumentEvent e) {
|
|
||||||
checkSignIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeUpdate(final DocumentEvent e) {
|
|
||||||
checkSignIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void changedUpdate(final DocumentEvent e) {
|
|
||||||
checkSignIn();
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SignInCallback {
|
interface SignInCallback {
|
||||||
|
|
||||||
boolean signedIn(String userName, String masterPassword);
|
boolean signedIn(User user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,49 @@
|
|||||||
package com.lyndir.lhunath.masterpassword;
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
|
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lhunath, 2014-06-08
|
* @author lhunath, 2014-06-08
|
||||||
*/
|
*/
|
||||||
public class User {
|
public class User {
|
||||||
private final String name;
|
|
||||||
private final byte[] key;
|
|
||||||
|
|
||||||
public User(final String name, final byte[] key) {
|
private final String name;
|
||||||
|
private final String masterPassword;
|
||||||
|
private byte[] key;
|
||||||
|
|
||||||
|
public User(final String name, final String masterPassword) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.key = key;
|
this.masterPassword = masterPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasKey() {
|
||||||
|
return key != null || (masterPassword != null && !masterPassword.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] getKey() {
|
public byte[] getKey() {
|
||||||
|
if (key == null) {
|
||||||
|
if (!hasKey()) {
|
||||||
|
throw new IllegalStateException( strf( "Master password unknown for user: %s", name ) );
|
||||||
|
} else {
|
||||||
|
key = MasterPassword.keyForPassword( masterPassword, name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return name.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user