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





                               
                           
                                         
                                       



                                                  
                              
                                 


                                                                             
                                                       

                                                                  
                                  
                                         
                                                 
                                                              
                                                   
                                         
                                              

                                        
 
                                                          
 

                         
   
   
                                                    
 
                                                                                 
 
                         


                                                                          
           

                                                                   
                                                                  
           

                           
                                                   


                                                         




                                                                              
                                              
                                                    
                                                       
 

                                            
                                     

                                                                     






                                                                                                
                                                 
                                                           

                                                                 
                                                                       
                                                                             


                                         
                   
 

                                                                          



                                                                             
                                                                                         
                                                        
                 




                                                                            
 







                                                                        




                                                                         

                                               















                                                                               
                                                          
                                                          
                                                           








                                                                               
                                                                    









                                                                                 
                                                                      

                         
 

                                                                            
                                                              

                                                             
                                                                                        

                                                       

                                 
                   

         







                                                                       
 
                                        


















                                                                                          










                                                                                                                           
                                       



                                                  
           
                                                         
                                                                  





                                                                               

                                                             
                         

                                               

                                                                                              




                                                                               
                 
         
 
           

                                                                                   

                                             
           


                                             

                                                                                                                      

                               
                                                    

                                                         
                                                            
                                         
                                                                                                        

                               
                                         
                                                                                                        

                               

                                                                         
                                                  
                                                                     
 



                                                                                           
                                                                                   

                                                     
                                                              

                                                             
                                                                                                                      



                                                                                                      
                                                                                                                     
                                                                                      

                                                        





                                                                                                                                         
                                                                                      
                                              
                                                   
                                        
                                                                                                                            
                                              



                                 
                                                   
                                            
                                    
                         
                                                                                      
                              
                                  
                                                                       
                              
                                    
                                                                                                                  
                               
                        
                                                                                                                      





                                                                                       


                                                                                                                        
                               
                 
         
 

                                                                      

                                         

                                            
                                                                  
 
                                 

                                                                                 













                                                                                                                              
         
 
           

                                                                                   








                                                                                                                           

         
package org.openslx.dozmod.gui.window;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.log4j.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Shell;
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);

	// text constants
	private final String NO_USERNAME = "Kein Benutzername angegeben!";
	private final String NO_PASSWORD = "Kein Passwort angegeben!";

	/**
	 * Constructor doing the setup of the logical GUI functions
	 * Fetches the organization list for BWIDM logins and
	 * adds mouse/keyboard event listeners to various widgets.
	 * 
	 * @param mainShell
	 */
	public LoginWindow(final Shell mainShell) {
		// call the constructor of the superclass
		super(mainShell);

		// fetch the list of the identity providers as an async Thread
		// else the GUI is blocked until this is done.
		idpCombo.add("Initialisiere...");
		idpCombo.select(0);
		idpCombo.setEnabled(false);
		loginButton.setEnabled(false);
		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);
				}
				// now send the organisations back to the LoginWindow
				// through populateIdpCombo()
				Gui.display.asyncExec(new Runnable() {
					@Override
					public void run() {
						if (isDisposed())
							return;
						populateIdpCombo(orgs);
						loginButton.setEnabled(true);
					}
				});
			}
		});

		// 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;
		}
		authButtons[savedLoginType.id].setSelection(true);
		loginType = savedLoginType;
		// enable the IDP combo only if we actually have items in it
		idpText.setVisible(savedLoginType == LOGIN_TYPE.ECP);
		idpCombo.setVisible(savedLoginType == LOGIN_TYPE.ECP);

		// finally check if we had a saved username
		String savedUsername = Config.getUsername();
		if (savedUsername != null && !savedUsername.isEmpty()) {
			usernameText.setText(savedUsername);
			saveUsernameCheck.setSelection(true);
			passwordText.setFocus();
		} else
			usernameText.setFocus();

		// actions of the login button
		loginButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				doSaveConfig();
				doLogin();
			}
		});

		// for save username checkbox.
		saveUsernameCheck.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				// clickedSaveUsernameCheck();
			}
		});

		// selecting the "Authentifizierung über bwIDM" radio button
		authButtons[0].addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				idpText.setVisible(true);
				idpCombo.setEnabled(true);
				idpCombo.setVisible(true);
				loginType = LOGIN_TYPE.ECP;
			}
		});

		// selecting the "Test-Zugang mit festem Benutzer" radio button
		authButtons[1].addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				idpText.setVisible(false);
				idpCombo.setVisible(false);
				loginType = LOGIN_TYPE.TEST_ACCOUNT;
			}
		});

		authButtons[2].setEnabled(false);
		// selecting the "Direkte Verbindung zum Satteliten" radio button
		authButtons[2].addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				idpText.setVisible(false);
				idpCombo.setVisible(false);
				loginType = LOGIN_TYPE.DIRECT_CONNECT;
			}
		});

		// add a key listener to the password field to trigger login
		// when the user presses the ENTER key.
		passwordText.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {
					doSaveConfig();
					doLogin();
				}
			}
		});
	}

	public void populateIdpCombo(List<Organization> orgs) {

		// safety check to see if the login window still exists
		// when this function gets called by the other thread
		if (this.isDisposed())
			return;
		// always clearup the list first
		idpCombo.removeAll();

		// sanity checks on orgs
		if (orgs == null) {
			LOGGER.error("No organizations received from the cache.");
			idpCombo.add("No entries");
			return;
		}

		// 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 check if we had a saved identity provider
		String savedOrganizationId = Config.getIdentityProvider();
		// add only organizations which have an ECP URL to the combobox
		for (Organization o : orgs) {
			if (o.getEcpUrl() == null | o.getEcpUrl().isEmpty())
				continue;
			idpCombo.add(o.displayName);
			idpCombo.setData(o.displayName, o);
			if (savedOrganizationId != null && !savedOrganizationId.isEmpty()
					&& savedOrganizationId.equals(o.getOrganizationId()))
				// select the organization we just added, this seems kinda bad - is there a better way?
				idpCombo.select(idpCombo.getItemCount() - 1);
			//idpCombo.select(idpCombo.indexOf(savedOrganizationId)); this is probably not optimal... but safer
		}
		// if no organization was saved, none is selected, so select the first one in the combobox
		if (idpCombo.getSelectionIndex() == -1)
			idpCombo.select(0);
		// finally re-enable it
		if (idpCombo.isVisible())
			idpCombo.setEnabled(true);
	}

	/**
	 * 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.isEnabled()) {
			// save username
			String username = usernameText.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 = getSelectedOrganization();
		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.getShell(), "No login type set, a default should be set! Ignoring...",
					MessageType.ERROR, LOGGER, null);
			return;
		}
		// here we only check for the fields
		String username = usernameText.getText();
		String password = passwordText.getText();
		// login clicked, lets first read the fields
		if (username.isEmpty()) {
			Gui.showMessageBox(this.getShell(), NO_USERNAME, MessageType.ERROR, null, null);
			return;
		}
		if (password.isEmpty()) {
			Gui.showMessageBox(this.getShell(), NO_PASSWORD, MessageType.ERROR, null, null);
			return;
		}

		// determine which organization was selected by the user.
		// TODO: Needed for test accounts?
		Organization selectedOrg = getSelectedOrganization();

		// 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.getShell(), "IdP Error", MessageType.ERROR, null, 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.getShell(), "Invalid token from the service provider!",
							MessageType.ERROR, LOGGER, t);
					break;
				case UNREGISTERED_ERROR:
					Gui.showMessageBox(me.getShell(), "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.getShell(), "ECP Authenticator says: Invalid URL.",
							MessageType.ERROR, LOGGER, t);
					break;
				case GENERIC_ERROR:
				default:
					Gui.showMessageBox(me.getShell(), "Internal error!", MessageType.ERROR, null, 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.getShell(), "Not yet implemented", MessageType.ERROR, null, null);
			return;
		default:
			Gui.showMessageBox(this.getShell(), "No login type selected!", MessageType.ERROR, null, null);
			return;
		}

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

	/**
	 * Functions called by doLogin is the login process succeeded.
	 * 
	 * @param user user who logged in
	 */
	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())
				MainWindow.openPopup(DisclaimerWindow.class, true, true);
			getShell().dispose();
			return;
		} catch (Exception ex) {
			e = ex;
		}
		Gui.showMessageBox(this.getShell(), "Login succeeded, but Satellite rejected the session token. :-(",
				MessageType.ERROR, LOGGER, e);
	}

	/**
	 * @return the organization currently selected in the combobox for identity
	 *         providers
	 */
	private final Organization getSelectedOrganization() {
		// get the index of the selected item in the combobox
		int selectionIndex = idpCombo.getSelectionIndex();
		if (selectionIndex == -1) {
			LOGGER.error("No identity provider is selected in the combobox. There should be a default value!");
			return null;
		}
		return (Organization) idpCombo.getData(idpCombo.getItem(selectionIndex));
	}
}