summaryrefslogblamecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LoginWindow.java
blob: 491aed9fcfd223030a85d7fefb8e96b5b2e6863c (plain) (tree)
1
2
3
4
5
                                      
 
                          

                                     












                                           
 
                               











                                                                             
                                                              






                                                          
 

                         
   
   
                                                    
 
                                                                                 
 














                                                          
                         


                                                                          


                                                         
 
                                               





































































                                                                                                                     

                                                                    




















































































































































                                                                                                                                         

                         

























                                                                                                               
         
 













                                                                                                                              
                                                             













                                                                                                          


                                                   
 
package org.openslx.dozmod.gui.window;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JList;

import org.apache.log4j.Logger;
import org.openslx.bwlp.thrift.iface.Organization;
import org.openslx.dozmod.App;
import org.openslx.dozmod.Config;
import org.openslx.dozmod.authentication.Authenticator;
import org.openslx.dozmod.authentication.Authenticator.AuthenticatorCallback;
import org.openslx.dozmod.authentication.EcpAuthenticator;
import org.openslx.dozmod.authentication.ShibbolethEcp;
import org.openslx.dozmod.authentication.ShibbolethEcp.ReturnCode;
import org.openslx.dozmod.authentication.TestAccountAuthenticator;
import org.openslx.dozmod.gui.Gui;
import org.openslx.dozmod.gui.MainWindow;
import org.openslx.dozmod.gui.helper.MessageType;
import org.openslx.dozmod.gui.window.layout.LoginWindowLayout;
import org.openslx.dozmod.thrift.OrganizationCache;
import org.openslx.dozmod.thrift.Session;
import org.openslx.thrifthelper.ThriftManager;
import org.openslx.util.QuickTimer;
import org.openslx.util.QuickTimer.Task;

import edu.kit.scc.dei.ecplean.ECPAuthenticationException;

/**
 * @author Jonathan Bauer
 * 
 */
public class LoginWindow extends LoginWindowLayout {

	private final static Logger LOGGER = Logger.getLogger(LoginWindow.class);

	// TODO This has nothing to to with the layout
	public static enum LOGIN_TYPE {
		ECP(0),
		TEST_ACCOUNT(1),
		DIRECT_CONNECT(2);

		public final int id;

		private LOGIN_TYPE(final int id) {
			this.id = id;
		}
	}

	// authentication method to use for login attempts
	protected LOGIN_TYPE loginType = null;
	// text constants
	private final String NO_USERNAME = "Kein Benutzername angegeben!";
	private final String NO_PASSWORD = "Kein Passwort angegeben!";

	public LoginWindow() {
		// call the constructor of the superclass
		super();

		// first do all listeners stuff
		for (final LOGIN_TYPE type : LOGIN_TYPE.values()) {
			loginTypes[type.id].setActionCommand(type.toString());
			loginTypes[type.id].addItemListener(new ItemListener() {
				@Override
				public void itemStateChanged(ItemEvent e) {
					if (e.getStateChange() == ItemEvent.SELECTED) {
						idpLabel.setVisible(type == LOGIN_TYPE.ECP);
						idpCombo.setVisible(type == LOGIN_TYPE.ECP);
						loginType = type;
					} 
				}
			});
		}
    	
		// check if we had saved an authentication method
		String savedAuthMethod = Config.getAuthenticationMethod();
		LOGIN_TYPE savedLoginType;
		try {
			savedLoginType = LOGIN_TYPE.valueOf(savedAuthMethod);
		} catch (Exception e) {
			// if no valid LOGIN_TYPE was saved, just enable the BWIDM button
			savedLoginType = LOGIN_TYPE.ECP;
		}
		
		if (savedLoginType == LOGIN_TYPE.ECP) {
			// disable login button til the idp list is here
			loginButton.setEnabled(false);
		}
		// enable the corresponding button
		loginTypes[savedLoginType.id].setSelected(true);
		loginType = savedLoginType;

		QuickTimer.scheduleOnce(new Task() {
			List<Organization> orgs = null;

			@Override
			public void fire() {
				try {
					// Wait for proxy server init
					App.waitForInit();
					orgs = OrganizationCache.getAll();
				} catch (Exception e) {
					LoginWindow.LOGGER.error("Error during execution: ", e);
				}
				// filter out every organisation without ecp
				Iterator<Organization> iterator = orgs.iterator();
				while (iterator.hasNext()) {
					Organization current = iterator.next();
					if (current == null | !current.isSetEcpUrl() | current.getEcpUrl().isEmpty())
						iterator.remove();
				}
				// all fine, lets sort it
				Collections.sort(orgs, new Comparator<Organization>() {
					public int compare(Organization o1, Organization o2) {
						return o1.getDisplayName().compareTo(o2.getDisplayName());
					}
				});
				// now send the organisations back to the LoginWindow
				// through populateIdpCombo()
				Gui.asyncExec(new Runnable() {
					@Override
					public void run() {
						populateIdpCombo(orgs);
						loginButton.setEnabled(true);
					}
				});
			}
		});
		
		loginButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				doLogin();
			}
		});
		// add a key listener to the password field to trigger login
		// when the user presses the ENTER key.
		passwordField.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				super.keyReleased(e);
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					doLogin();
				}
					
			}
		});

		// finally check if we had a saved username
		String savedUsername = Config.getUsername();
		if (savedUsername != null && !savedUsername.isEmpty()) {
			usernameField.setText(savedUsername);
			saveUsernameCheck.setSelected(true);
			passwordField.requestFocus();
		} else {
			usernameField.requestFocus();
		}
	}

	/**
	 * Called by the thread fetching the organization list from the cache
	 * 
	 * @param orgs list of organization to show in the combo box 
	 */
	public void populateIdpCombo(List<Organization> orgs) {
		
		// sanity checks on orgs
		if (orgs == null) {
			LOGGER.error("No organizations received from the cache.");
			return;
		}
		for (Organization org : orgs) { LOGGER.debug(org); }

		idpCombo.setModel(new DefaultComboBoxModel<Organization>(orgs.toArray(new Organization[orgs.size()])));
		idpCombo.setRenderer(new DefaultListCellRenderer() {
			@Override
			public Component getListCellRendererComponent(JList<?> list,
					Object value, int index, boolean isSelected,
					boolean cellHasFocus) {
				super.getListCellRendererComponent(list, value, index,
						isSelected, cellHasFocus);
				if (value instanceof Organization) {
					Organization org = (Organization) value;
					setText(org.getDisplayName());
				}
				return this;
			}
		});
		// now check if we had a saved identity provider
		String savedOrganizationId = Config.getIdentityProvider();
		idpCombo.setSelectedItem(OrganizationCache.find(savedOrganizationId));

	}

	/**
	 * Saves various user choices to the config file.
	 * This gets triggered when the login button is activated.
	 */
	private void doSaveConfig() {
		// first we need to check if the "Remember me" button is active
		if (saveUsernameCheck.isSelected()) {
			// save username
			String username = usernameField.getText();
			if (!username.isEmpty()) {
				Config.setUsername(username);
			}
		} else {
			Config.setUsername("");
		}
		// always save the authentication method and potentially the identity provider
		Config.setAuthenticationMethod(loginType.toString());
		// save the selected identity provider
		Organization selectedOrg = idpCombo.getItemAt(idpCombo.getSelectedIndex());
		if (selectedOrg != null) {
			Config.setIdentityProvider(selectedOrg.organizationId);
		}
	}

	/**
	 * Actually do the login using the username/password in the field using the
	 * authentication mechanism corresponding to the selected authButton
	 * 
	 * @throws ECPAuthenticationException
	 */
	private void doLogin() {
		// sanity check on loginType.
		if (loginType == null) {
			Gui.showMessageBox(this, "No login type set, a default should be set! Ignoring...",
					MessageType.ERROR, LOGGER, null);
			return;
		}
		// we are doing the login soon, first save the config
		doSaveConfig();
		// here we only check for the fields
		String username = usernameField.getText();
		String password = String.copyValueOf(passwordField.getPassword());
		// login clicked, lets first read the fields
		if (username.isEmpty()) {
			Gui.showMessageBox(this, NO_USERNAME, MessageType.ERROR, LOGGER, null);
			return;
		}
		if (password.isEmpty()) {
			Gui.showMessageBox(this, NO_PASSWORD, MessageType.ERROR, LOGGER, null);
			return;
		}

		// determine which organization was selected by the user.
		Organization selectedOrg = idpCombo.getItemAt(idpCombo.getSelectedIndex());

		// Setup login callback
		final LoginWindow me = this;
		AuthenticatorCallback authenticatorCallback = new AuthenticatorCallback() {
			@Override
			public void postLogin(ReturnCode returnCode, Throwable t) {
				switch (returnCode) {
				case NO_ERROR:
					postSuccessfulLogin();
					break;
				case IDENTITY_PROVIDER_ERROR:
					Gui.showMessageBox(me, "IdP Error", MessageType.ERROR, LOGGER, null);
					break;
				case SERVICE_PROVIDER_ERROR:
					// here if we have t != null then we have not received a token
					// if we have t, then the token is invalid.
					Gui.showMessageBox(me, "Invalid token from the service provider!",
							MessageType.ERROR, LOGGER, t);
					break;
				case UNREGISTERED_ERROR:
					Gui.showMessageBox(me, "You are not registered to bwLehrpool. Please visit "
							+ ShibbolethEcp.getRegistrationUrl() + " and register first.", MessageType.ERROR,
							LOGGER, t);
					break;
				case INVALID_URL_ERROR:
					Gui.showMessageBox(me, "ECP Authenticator says: Invalid URL.",
							MessageType.ERROR, LOGGER, t);
					break;
				case GENERIC_ERROR:
				default:
					Gui.showMessageBox(me, "Internal error!", MessageType.ERROR, LOGGER, null);
					break;
				}
			}
		};

		// now switch over the login types.
		Authenticator authenticator;
		switch (loginType) {
		case ECP:
			authenticator = new EcpAuthenticator(selectedOrg.getEcpUrl());
			break;
		case TEST_ACCOUNT:
			authenticator = new TestAccountAuthenticator();
			break;
		case DIRECT_CONNECT:
			Gui.showMessageBox(this, "Not yet implemented", MessageType.ERROR, LOGGER, null);
			return;
		default:
			Gui.showMessageBox(this, "No login type selected!", MessageType.ERROR, LOGGER, null);
			return;
		}

		// Excute login
		try {
			authenticator.login(username, password, authenticatorCallback);
		} catch (Exception e) {
			Gui.showMessageBox(this, "Authentication failed: " + e.getMessage(), MessageType.ERROR,
					LOGGER, e);
			return;
		}
	}

	/**
	 * Functions called by doLogin is the login process succeeded.
	 */
	private void postSuccessfulLogin() {
		LOGGER.info(loginType.toString() + " succeeded.");

		// TODO HACK HACK
		Session.setSatelliteAddress("132.230.8.113");
		ThriftManager.setSatelliteAddress(Session.getSatelliteAddress());
		// Something like ThriftManager.setSatelliteAddress(Session.getSatelliteAddress()); (might need selection box)
		Exception e = null;
		try {
			ThriftManager.getSatClient().isAuthenticated(Session.getSatelliteToken());
			// now read the config to see if the user already agreed to the disclaimer
//			if (DisclaimerWindow.shouldBeShown())
//				VirtualizerNoticeWindow.open();
			LOGGER.debug("Closing...");
			dispose();
			return;
		} catch (Exception ex) {
			e = ex;
		}
		Gui.showMessageBox(this, "Login succeeded, but Satellite rejected the session token. :-(",
				MessageType.ERROR, LOGGER, e);
	}

	/**
	 * Opens the login window
	 */
	public static void open() {
		new LoginWindow().setVisible(true);
	}
}