Performing handshake and online init in LoginDialog
This commit is contained in:
parent
9498bf216d
commit
b3101e2418
@ -51,7 +51,7 @@ public class Receiver implements Runnable {
|
||||
|
||||
try (ObjectInputStream oin = new ObjectInputStream(new ByteArrayInputStream(objBytes))) {
|
||||
Object obj = oin.readObject();
|
||||
logger.finest("Received object " + obj);
|
||||
logger.info("Received object " + obj);
|
||||
|
||||
// Get appropriate processor
|
||||
@SuppressWarnings("rawtypes")
|
||||
|
@ -2,17 +2,25 @@ package envoy.client.ui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.naming.TimeLimitExceededException;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import envoy.client.data.Settings;
|
||||
import envoy.client.data.*;
|
||||
import envoy.client.event.HandshakeSuccessfulEvent;
|
||||
import envoy.client.net.Client;
|
||||
import envoy.client.util.EnvoyLog;
|
||||
import envoy.data.LoginCredentials;
|
||||
import envoy.data.Message;
|
||||
import envoy.data.User;
|
||||
import envoy.event.EventBus;
|
||||
import envoy.event.HandshakeRejectionEvent;
|
||||
import envoy.exception.EnvoyException;
|
||||
|
||||
/**
|
||||
* Project: <strong>envoy-client</strong><br>
|
||||
@ -25,7 +33,7 @@ import envoy.event.HandshakeRejectionEvent;
|
||||
*/
|
||||
public class LoginDialog extends JDialog {
|
||||
|
||||
private final JPanel contentPanel;
|
||||
private JPanel contentPanel;
|
||||
private JTextField textField;
|
||||
private JPasswordField passwordField;
|
||||
private JPasswordField repeatPasswordField;
|
||||
@ -47,14 +55,111 @@ public class LoginDialog extends JDialog {
|
||||
|
||||
private LoginCredentials credentials;
|
||||
|
||||
private static final long serialVersionUID = 352021600833907468L;
|
||||
private final Client client;
|
||||
private final LocalDb localDb;
|
||||
private final Cache<Message> receivedMessageCache;
|
||||
|
||||
private static final Config config = Config.getInstance();
|
||||
private static final Logger logger = EnvoyLog.getLogger(LoginDialog.class.getSimpleName());
|
||||
private static final long serialVersionUID = 352021600833907468L;
|
||||
|
||||
/**
|
||||
* Displays a dialog enabling the user to enter their user name and password.
|
||||
*
|
||||
* @param client the client used to perform the handshake
|
||||
* @param localDb the local database in which data is persisted
|
||||
* @param receivedMessageCache the cache that stored messages received during
|
||||
* the handshake
|
||||
* @since Envoy v0.3-alpha
|
||||
*/
|
||||
public LoginDialog() {
|
||||
public LoginDialog(Client client, LocalDb localDb, Cache<Message> receivedMessageCache) {
|
||||
this.client = client;
|
||||
this.localDb = localDb;
|
||||
this.receivedMessageCache = receivedMessageCache;
|
||||
|
||||
// Prepare handshake
|
||||
localDb.loadIdGenerator();
|
||||
|
||||
initUi();
|
||||
|
||||
okButton.addActionListener((evt) -> {
|
||||
try {
|
||||
if (registerCheckBox.isSelected()) {
|
||||
// Check password equality
|
||||
if (Arrays.equals(passwordField.getPassword(), repeatPasswordField.getPassword()))
|
||||
credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), true);
|
||||
else {
|
||||
JOptionPane.showMessageDialog(this, "The repeated password is not the origional password!");
|
||||
clearPasswordFields();
|
||||
}
|
||||
} else credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), false);
|
||||
performHandshake();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
// Listen to handshake rejections
|
||||
EventBus.getInstance().register(HandshakeRejectionEvent.class, evt -> {
|
||||
for (Component c : contentPanel.getComponents())
|
||||
if (c == errorMessage) contentPanel.remove(errorMessage);
|
||||
clearPasswordFields();
|
||||
errorMessage = new JLabel(evt.get());
|
||||
gbc_errorMessage = new GridBagConstraints();
|
||||
gbc_errorMessage.gridx = 2;
|
||||
gbc_errorMessage.gridy = 0;
|
||||
gbc_errorMessage.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_errorMessage.insets = new Insets(5, 5, 5, 5);
|
||||
contentPanel.add(errorMessage, gbc_errorMessage);
|
||||
contentPanel.revalidate();
|
||||
contentPanel.repaint();
|
||||
});
|
||||
|
||||
// Exit the application when the dialog is cancelled
|
||||
cancelButton.addActionListener(evt -> { logger.info("The login process has been cancelled. Exiting..."); System.exit(0); });
|
||||
|
||||
// Log in directly if configured
|
||||
if (config.hasLoginCredentials()) {
|
||||
credentials = config.getLoginCredentials();
|
||||
performHandshake();
|
||||
return;
|
||||
}
|
||||
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
private void performHandshake() {
|
||||
try {
|
||||
client.performHandshake(credentials, receivedMessageCache);
|
||||
if (client.isOnline()) {
|
||||
client.initReceiver(localDb, receivedMessageCache);
|
||||
dispose();
|
||||
}
|
||||
} catch (IOException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (TimeLimitExceededException e) {
|
||||
logger.warning("Could not connect to server. Trying offline mode...");
|
||||
e.printStackTrace();
|
||||
try {
|
||||
// Try entering offline mode
|
||||
localDb.loadUsers();
|
||||
User clientUser = localDb.getUsers().get(credentials.getIdentifier());
|
||||
if (clientUser == null) throw new EnvoyException("Could not enter offline mode: user name unknown");
|
||||
client.setSender(clientUser);
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"A connection to the server could not be established. Starting in offline mode.\n" + e,
|
||||
"Connection error",
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
dispose();
|
||||
} catch (Exception e1) {
|
||||
JOptionPane.showMessageDialog(null, e1, "Client error", JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initUi() {
|
||||
setSize(338, 123);
|
||||
setLocationRelativeTo(null);
|
||||
getContentPane().setLayout(new BorderLayout());
|
||||
@ -67,150 +172,109 @@ public class LoginDialog extends JDialog {
|
||||
gbl_contentPanel.columnWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE };
|
||||
gbl_contentPanel.rowWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE };
|
||||
contentPanel.setLayout(gbl_contentPanel);
|
||||
{
|
||||
lblUserName = new JLabel("Username:");
|
||||
GridBagConstraints gbc_lblUserName = new GridBagConstraints();
|
||||
gbc_lblUserName.anchor = GridBagConstraints.EAST;
|
||||
gbc_lblUserName.insets = new Insets(0, 0, 5, 5);
|
||||
gbc_lblUserName.gridx = 0;
|
||||
gbc_lblUserName.gridy = 0;
|
||||
contentPanel.add(lblUserName, gbc_lblUserName);
|
||||
}
|
||||
{
|
||||
textField = new JTextField();
|
||||
textField.setBorder(null);
|
||||
GridBagConstraints gbc_textField = new GridBagConstraints();
|
||||
gbc_textField.insets = new Insets(0, 0, 5, 0);
|
||||
gbc_textField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_textField.gridx = 1;
|
||||
gbc_textField.gridy = 0;
|
||||
contentPanel.add(textField, gbc_textField);
|
||||
textField.setColumns(10);
|
||||
}
|
||||
{
|
||||
lblPassword = new JLabel("Password:");
|
||||
GridBagConstraints gbc_lblPassword = new GridBagConstraints();
|
||||
gbc_lblPassword.anchor = GridBagConstraints.EAST;
|
||||
gbc_lblPassword.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_lblPassword.gridx = 0;
|
||||
gbc_lblPassword.gridy = 1;
|
||||
contentPanel.add(lblPassword, gbc_lblPassword);
|
||||
}
|
||||
{
|
||||
passwordField = new JPasswordField();
|
||||
passwordField.setBorder(null);
|
||||
GridBagConstraints gbc_passwordField = new GridBagConstraints();
|
||||
gbc_passwordField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_passwordField.gridx = 1;
|
||||
gbc_passwordField.gridy = 1;
|
||||
contentPanel.add(passwordField, gbc_passwordField);
|
||||
}
|
||||
{
|
||||
lblRepeatPassword = new JLabel("Repeat Password:");
|
||||
gbc_lblRepeatPassword = new GridBagConstraints();
|
||||
gbc_lblRepeatPassword.anchor = GridBagConstraints.EAST;
|
||||
gbc_lblRepeatPassword.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_lblRepeatPassword.gridx = 0;
|
||||
gbc_lblRepeatPassword.gridy = 2;
|
||||
}
|
||||
{
|
||||
repeatPasswordField = new JPasswordField();
|
||||
gbc_repeatPasswordField = new GridBagConstraints();
|
||||
gbc_repeatPasswordField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_repeatPasswordField.gridx = 1;
|
||||
gbc_repeatPasswordField.gridy = 2;
|
||||
}
|
||||
{
|
||||
EventBus.getInstance().register(HandshakeRejectionEvent.class, evt -> {
|
||||
contentPanel.remove(errorMessage);
|
||||
clearPasswordFields();
|
||||
// TODO delete - only for testing purposes
|
||||
System.out.println("Caught HandshakeRejectionEvent with reason" + evt.get());
|
||||
errorMessage = new JLabel(evt.get());
|
||||
gbc_errorMessage = new GridBagConstraints();
|
||||
gbc_errorMessage.gridx = 2;
|
||||
gbc_errorMessage.gridy = 0;
|
||||
gbc_errorMessage.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_errorMessage.insets = new Insets(5, 5, 5, 5);
|
||||
contentPanel.add(errorMessage, gbc_errorMessage);
|
||||
});
|
||||
}
|
||||
{
|
||||
buttonPane = new JPanel();
|
||||
|
||||
registerText = new JTextPane();
|
||||
registerText.setEditable(false);
|
||||
registerText.setText("Register?");
|
||||
registerText.setFont(new Font("Arial", Font.BOLD, 12));
|
||||
registerText.setAlignmentX(LEFT_ALIGNMENT);
|
||||
buttonPane.add(registerText);
|
||||
lblUserName = new JLabel("Username:");
|
||||
GridBagConstraints gbc_lblUserName = new GridBagConstraints();
|
||||
gbc_lblUserName.anchor = GridBagConstraints.EAST;
|
||||
gbc_lblUserName.insets = new Insets(0, 0, 5, 5);
|
||||
gbc_lblUserName.gridx = 0;
|
||||
gbc_lblUserName.gridy = 0;
|
||||
contentPanel.add(lblUserName, gbc_lblUserName);
|
||||
|
||||
registerCheckBox = new JCheckBox();
|
||||
registerCheckBox.setAlignmentX(LEFT_ALIGNMENT);
|
||||
registerCheckBox.addItemListener(e -> {
|
||||
switch (e.getStateChange()) {
|
||||
case ItemEvent.SELECTED:
|
||||
contentPanel.add(lblRepeatPassword, gbc_lblRepeatPassword);
|
||||
contentPanel.add(repeatPasswordField, gbc_repeatPasswordField);
|
||||
setSize(338, 148);
|
||||
break;
|
||||
textField = new JTextField();
|
||||
textField.setBorder(null);
|
||||
GridBagConstraints gbc_textField = new GridBagConstraints();
|
||||
gbc_textField.insets = new Insets(0, 0, 5, 0);
|
||||
gbc_textField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_textField.gridx = 1;
|
||||
gbc_textField.gridy = 0;
|
||||
contentPanel.add(textField, gbc_textField);
|
||||
textField.setColumns(10);
|
||||
|
||||
case ItemEvent.DESELECTED:
|
||||
if (repeatPasswordField.getParent() == contentPanel) {
|
||||
contentPanel.remove(lblRepeatPassword);
|
||||
contentPanel.remove(repeatPasswordField);
|
||||
setSize(338, 123);
|
||||
}
|
||||
break;
|
||||
}
|
||||
contentPanel.revalidate();
|
||||
contentPanel.repaint();
|
||||
});
|
||||
buttonPane.add(registerCheckBox);
|
||||
lblPassword = new JLabel("Password:");
|
||||
GridBagConstraints gbc_lblPassword = new GridBagConstraints();
|
||||
gbc_lblPassword.anchor = GridBagConstraints.EAST;
|
||||
gbc_lblPassword.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_lblPassword.gridx = 0;
|
||||
gbc_lblPassword.gridy = 1;
|
||||
contentPanel.add(lblPassword, gbc_lblPassword);
|
||||
|
||||
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
|
||||
getContentPane().add(buttonPane, BorderLayout.SOUTH);
|
||||
{
|
||||
okButton = new PrimaryButton("OK");
|
||||
okButton.addActionListener((evt) -> {
|
||||
try {
|
||||
if (registerCheckBox.isSelected()) {
|
||||
// password checking
|
||||
if (Arrays.equals(passwordField.getPassword(), repeatPasswordField.getPassword()))
|
||||
credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), true);
|
||||
else {
|
||||
JOptionPane.showMessageDialog(this, "The repeated password is not the origional password!");
|
||||
clearPasswordFields();
|
||||
}
|
||||
} else credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), false);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
passwordField = new JPasswordField();
|
||||
passwordField.setBorder(null);
|
||||
GridBagConstraints gbc_passwordField = new GridBagConstraints();
|
||||
gbc_passwordField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_passwordField.gridx = 1;
|
||||
gbc_passwordField.gridy = 1;
|
||||
contentPanel.add(passwordField, gbc_passwordField);
|
||||
|
||||
lblRepeatPassword = new JLabel("Repeat Password:");
|
||||
gbc_lblRepeatPassword = new GridBagConstraints();
|
||||
gbc_lblRepeatPassword.anchor = GridBagConstraints.EAST;
|
||||
gbc_lblRepeatPassword.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_lblRepeatPassword.gridx = 0;
|
||||
gbc_lblRepeatPassword.gridy = 2;
|
||||
|
||||
repeatPasswordField = new JPasswordField();
|
||||
gbc_repeatPasswordField = new GridBagConstraints();
|
||||
gbc_repeatPasswordField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_repeatPasswordField.gridx = 1;
|
||||
gbc_repeatPasswordField.gridy = 2;
|
||||
|
||||
buttonPane = new JPanel();
|
||||
|
||||
registerText = new JTextPane();
|
||||
registerText.setEditable(false);
|
||||
registerText.setText("Register?");
|
||||
registerText.setFont(new Font("Arial", Font.BOLD, 12));
|
||||
registerText.setAlignmentX(LEFT_ALIGNMENT);
|
||||
buttonPane.add(registerText);
|
||||
|
||||
registerCheckBox = new JCheckBox();
|
||||
registerCheckBox.setAlignmentX(LEFT_ALIGNMENT);
|
||||
registerCheckBox.addItemListener(e -> {
|
||||
switch (e.getStateChange()) {
|
||||
case ItemEvent.SELECTED:
|
||||
contentPanel.add(lblRepeatPassword, gbc_lblRepeatPassword);
|
||||
contentPanel.add(repeatPasswordField, gbc_repeatPasswordField);
|
||||
setSize(338, 148);
|
||||
break;
|
||||
|
||||
case ItemEvent.DESELECTED:
|
||||
if (repeatPasswordField.getParent() == contentPanel) {
|
||||
contentPanel.remove(lblRepeatPassword);
|
||||
contentPanel.remove(repeatPasswordField);
|
||||
setSize(338, 123);
|
||||
}
|
||||
});
|
||||
okButton.setActionCommand("OK");
|
||||
buttonPane.add(okButton);
|
||||
getRootPane().setDefaultButton(okButton);
|
||||
break;
|
||||
}
|
||||
{
|
||||
cancelButton = new PrimaryButton("Cancel");
|
||||
cancelButton.addActionListener((evt) -> dispose());
|
||||
cancelButton.setActionCommand("Cancel");
|
||||
buttonPane.add(cancelButton);
|
||||
}
|
||||
}
|
||||
contentPanel.revalidate();
|
||||
contentPanel.repaint();
|
||||
});
|
||||
buttonPane.add(registerCheckBox);
|
||||
|
||||
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
|
||||
getContentPane().add(buttonPane, BorderLayout.SOUTH);
|
||||
okButton = new PrimaryButton("OK");
|
||||
okButton.setActionCommand("OK");
|
||||
buttonPane.add(okButton);
|
||||
getRootPane().setDefaultButton(okButton);
|
||||
|
||||
cancelButton = new PrimaryButton("Cancel");
|
||||
cancelButton.setActionCommand("Cancel");
|
||||
buttonPane.add(cancelButton);
|
||||
setTheme();
|
||||
|
||||
setModal(true);
|
||||
setVisible(true);
|
||||
setModalityType(Dialog.DEFAULT_MODALITY_TYPE);
|
||||
|
||||
EventBus.getInstance().register(HandshakeSuccessfulEvent.class, evt -> dispose());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the text stored in the passwort fields.
|
||||
* Resets the text stored in the password fields.
|
||||
*
|
||||
* @since Envoy v0.3-alpha
|
||||
*/
|
||||
public void clearPasswordFields() {
|
||||
private void clearPasswordFields() {
|
||||
passwordField.setText(null);
|
||||
repeatPasswordField.setText(null);
|
||||
}
|
||||
@ -258,11 +322,4 @@ public class LoginDialog extends JDialog {
|
||||
cancelButton.setBackground(theme.getInteractableBackgroundColor());
|
||||
cancelButton.setForeground(theme.getInteractableForegroundColor());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link LoginCredentials} entered by the user, or {@code null} if
|
||||
* the dialog has been cancelled
|
||||
* @since Envoy v0.3-alpha
|
||||
*/
|
||||
public LoginCredentials getCredentials() { return credentials; }
|
||||
}
|
@ -15,9 +15,7 @@ import envoy.client.data.*;
|
||||
import envoy.client.net.Client;
|
||||
import envoy.client.net.WriteProxy;
|
||||
import envoy.client.util.EnvoyLog;
|
||||
import envoy.data.LoginCredentials;
|
||||
import envoy.data.Message;
|
||||
import envoy.data.User;
|
||||
import envoy.exception.EnvoyException;
|
||||
|
||||
/**
|
||||
@ -74,14 +72,6 @@ public class Startup {
|
||||
EnvoyLog.setFileLevelBarrier(config.getFileLevelBarrier());
|
||||
EnvoyLog.setConsoleLevelBarrier(config.getConsoleLevelBarrier());
|
||||
|
||||
// Acquire login credentials
|
||||
LoginCredentials credentials = config.hasLoginCredentials() ? config.getLoginCredentials() : new LoginDialog().getCredentials();
|
||||
|
||||
if (credentials == null) {
|
||||
logger.info("The login process has been cancelled. Exiting...");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
// Initialize the local database
|
||||
LocalDb localDb;
|
||||
if (config.isIgnoreLocalDB()) {
|
||||
@ -95,45 +85,23 @@ public class Startup {
|
||||
} catch (IOException e3) {
|
||||
logger.log(Level.SEVERE, "Could not initialize local database", e3);
|
||||
JOptionPane
|
||||
.showMessageDialog(null, "Could not initialize local database!\n" + e3.toString(), "Local database error", JOptionPane.ERROR_MESSAGE);
|
||||
.showMessageDialog(null, "Could not initialize local database!\n" + e3, "Local database error", JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(() -> chatWindow.setVisible(true));
|
||||
|
||||
// Acquire the client user (with ID) either from the server or from the local
|
||||
// database, which triggers offline mode
|
||||
// Initialize client and unread message cache
|
||||
Client client = new Client();
|
||||
Cache<Message> cache = new Cache<>();
|
||||
try {
|
||||
// Try entering online mode first
|
||||
localDb.loadIdGenerator();
|
||||
client.performHandshake(credentials, cache);
|
||||
client.initReceiver(localDb, cache);
|
||||
} catch (Exception e1) {
|
||||
logger.warning("Could not connect to server. Trying offline mode...");
|
||||
e1.printStackTrace();
|
||||
try {
|
||||
// Try entering offline mode
|
||||
localDb.loadUsers();
|
||||
User clientUser = localDb.getUsers().get(credentials.getIdentifier());
|
||||
if (clientUser == null) throw new EnvoyException("Could not enter offline mode: user name unknown");
|
||||
client.setSender(clientUser);
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"A connection to the server could not be established. Starting in offline mode.\n" + e1,
|
||||
"Connection error",
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
} catch (Exception e2) {
|
||||
JOptionPane.showMessageDialog(null, e2.toString(), "Client error", JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to connect to the server
|
||||
new LoginDialog(client, localDb, cache);
|
||||
SwingUtilities.invokeLater(() -> chatWindow.setVisible(true));
|
||||
|
||||
// Set client user in local database
|
||||
localDb.setUser(client.getSender());
|
||||
|
||||
|
||||
// Initialize chats in local database
|
||||
try {
|
||||
localDb.initializeUserStorage();
|
||||
|
Reference in New Issue
Block a user