summaryrefslogblamecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LoginWindow.java
blob: 56a0607c9a54982d7f13d479e4f4ef6bfa61f8ba (plain) (tree)
1
2
3
4
5
6
7
8
9
                                      
 
                      

                                     



                                   

                                    





                                        
                          
 
                               
                                                  



                                                             


                                                       
                                                                          




                                                                             
                                                   
                                  
                                         
                                                 
                                                              






                                                          
 

                         
   
   
                           
                                                    
 
                                                                                 
 
                                                      
                                      





                                    
                                                 




                                                          
                                             
                         


                                                                          
                                               
                                                         
                                   






                                                                     
                                               
                                                                 




                                                                                       
                                                                                                                                 
                                                                 
                                         


                                 
 

                                                                          
                                         
                     
                                                                            

                                                                                         
                                                       
                 
 
                                                      


                                                                        



                                                                          













                                                                          
                                                                                    
























                                                                                                                     
 
                                                                    

                                                                    




                                                                            
                                                            





                                                                          
                         


                                                               














                                                                             
                                                                    

                                                               
 




                                                                                  

                                                                                                                       


                                                                                      
                                                                                                      




























































                                                                                                           
                                                                                                            

                                                     
                                                                  






                                                                                                             

                                                                                                                             






                                                                                                                                         

                                                                                                                                 





                                                                                                                   

                         





















                                                                                                             
                                                                                                                           

                               
         
 

                                                                      

                      
           

                                                                                               
 

                                                                                
                                                                       

                                                                                                                               





                                                                                                        

                                   

















                                                                                                                                                              

                                                                                                                            
                                                                                                  

                                                                                       

                                                              

                                                                                                                     
                         

                                  
                 

                                                                                                                       


                                                              









                                                     


                                 
                                                    
 
                                                               
                                     
         
 
package org.openslx.dozmod.gui.window;

import java.awt.Frame;
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.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JFrame;

import org.apache.log4j.Logger;
import org.openslx.bwlp.thrift.iface.Organization;
import org.openslx.bwlp.thrift.iface.SatelliteServer.Client;
import org.openslx.bwlp.thrift.iface.TAuthorizationException;
import org.openslx.bwlp.thrift.iface.TInternalServerError;
import org.openslx.bwlp.thrift.iface.WhoamiInfo;
import org.openslx.dozmod.App;
import org.openslx.dozmod.Config;
import org.openslx.dozmod.authentication.Authenticator;
import org.openslx.dozmod.authentication.Authenticator.AuthenticationData;
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.GraphicalCertHandler;
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
 * 
 */
@SuppressWarnings("serial")
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 LoginType {
		ECP(0),
		TEST_ACCOUNT(1),
		DIRECT_CONNECT(2);

		public final int id;

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

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

	public LoginWindow(Frame modalParent) {
		// call the constructor of the superclass
		super(modalParent);
		setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				Gui.exit(0);
			}
		});
		// first do all listeners stuff
		for (final LoginType type : LoginType.values()) {
			loginTypes[type.id].setActionCommand(type.toString());
			loginTypes[type.id].addItemListener(new ItemListener() {
				@Override
				public void itemStateChanged(ItemEvent e) {
					if (e.getStateChange() == ItemEvent.SELECTED) {
						idpCombo.setEnabled(idpCombo.getModel().getSize() != 0 && type == LoginType.ECP);
						loginType = type;
					}
				}
			});
		}

		// check if we had saved an authentication method
		String savedAuthMethod = Config.getAuthenticationMethod();
		LoginType savedLoginType;
		try {
			savedLoginType = LoginType.valueOf(savedAuthMethod);
		} catch (Exception e) {
			// if no valid LOGIN_TYPE was saved, just enable the BWIDM button
			savedLoginType = LoginType.ECP;
		}

		if (savedLoginType == LoginType.ECP) {
			// disable login button til the idp list is here
			loginButton.setEnabled(false);
		}
		// While filling, disable
		idpCombo.setEnabled(false);
		// Not yet implemented, disable
		loginTypes[LoginType.DIRECT_CONNECT.id].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) {
					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.
		KeyAdapter loginOnEnter = new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				super.keyReleased(e);
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					doLogin();
				}
			}
		};
		passwordField.addKeyListener(loginOnEnter);
		saveUsernameCheck.addKeyListener(loginOnEnter);

		// 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;
		}

		idpCombo.setModel(new DefaultComboBoxModel<Organization>(orgs.toArray(new Organization[orgs.size()])));
		// now check if we had a saved identity provider
		String savedOrganizationId = Config.getIdentityProvider();
		idpCombo.setSelectedItem(OrganizationCache.find(savedOrganizationId));
		idpCombo.setEnabled(idpCombo.getModel().getSize() != 0 && loginType == LoginType.ECP);
	}

	/**
	 * 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, AuthenticationData data, Throwable t) {
				switch (returnCode) {
				case NO_ERROR:
					postSuccessfulLogin(data);
					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.
	 * 
	 * @param data
	 */
	private void postSuccessfulLogin(AuthenticationData data) {
		LOGGER.info(loginType.toString() + " succeeded, token " + data.satelliteToken);

		// TODO: Show satellite selection if > 1
		//String satAddress = data.satellites.get(0).addressList.get(0);
		String satAddress = "132.230.8.113"; // TODO: HACK HACK
		Client client = ThriftManager.getNewSatelliteClient(GraphicalCertHandler.getSslContext(satAddress), satAddress,
				App.THRIFT_SSL_PORT, App.THRIFT_TIMEOUT_MS);
		if (client == null) {
			Gui.showMessageBox(this, "Login erfolgreich, aber der Satellit antwortet nicht",
					MessageType.ERROR, LOGGER, null);
			return;
		}
		WhoamiInfo whoami = null;
		Exception e = null;
		try {
			whoami = client.whoami(data.satelliteToken);
		} catch (TAuthorizationException e1) {
			Gui.showMessageBox(this,
					"Authentifizierung erfolgreich, der Satellit verweigert jedoch die Verbindung.\n\n"
							+ "Grund: " + e1.number.toString() + " (" + e1.message + ")", MessageType.ERROR,
					null, null);
			return;
		} catch (TInternalServerError e1) {
			Gui.showMessageBox(
					this,
					"Authentifizierung erfolgreich, bei der Kommunikation mit dem Satelliten trat jedoch ein interner Server-Fehler auf.",
					MessageType.ERROR, LOGGER, e);
			return;
		} catch (Exception ex) {
			e = ex;
		}
		if (whoami != null) {
			Session.initialize(whoami, satAddress, data.satelliteToken, data.masterToken);
			ThriftManager.setSatelliteAddress(GraphicalCertHandler.getSslContext(Session.getSatelliteAddress()),
					Session.getSatelliteAddress(), App.THRIFT_SSL_PORT, App.THRIFT_TIMEOUT_MS);
			// now read the config to see if the user already agreed to the disclaimer
			//			if (DisclaimerWindow.shouldBeShown())
			//				VirtualizerNoticeWindow.open();
			// Save session (TODO: Extra checkbox)
			if (saveUsernameCheck.isSelected()) {
				Config.saveCurrentSession(Session.getSatelliteAddress(), Session.getSatelliteToken(),
						Session.getMasterToken());
			}
			dispose();
			return;
		}
		Gui.showMessageBox(this,
				"Authentifizierung erfolgreich, aber der Satellit akzeptiert das Sitzungstoken nicht.",
				MessageType.ERROR, LOGGER, e);
	}

	@SuppressWarnings("deprecation")
	@Override
	public void show() {
		if (!isVisible()) {
			pack();
			MainWindow.centerShell(this);
		}
		super.show();
	}

	/**
	 * Opens the login window
	 */
	public static void open(Frame modalParent) {

		LoginWindow win = new LoginWindow(modalParent);
		win.setVisible(true);
	}
}