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.KeyEvent;
import org.eclipse.swt.events.KeyListener;
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.bwlp.thrift.iface.TAuthenticationException;
import org.openslx.bwlp.thrift.iface.UserInfo;
import org.openslx.dozmod.Config;
import org.openslx.dozmod.authentication.BWIDMAuthenticator;
import org.openslx.dozmod.authentication.BWLPAuthenticator;
import org.openslx.dozmod.authentication.BaseAuthenticator.AuthenticatorCallback;
import org.openslx.dozmod.authentication.ShibbolethECP.ReturnCode;
import org.openslx.dozmod.gui.helper.GuiManager;
import org.openslx.dozmod.gui.window.layout.LoginWindowLayout;
import org.openslx.dozmod.gui.window.layout.MainWindowLayout;
import org.openslx.dozmod.thrift.OrganizationCache;
import org.openslx.thrifthelper.ThriftManager;
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!";
// user input variables
private String username = null;
private String password = null;
/**
* 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);
// entries in the combo
List<Organization> orgs = OrganizationCache.getAll();
if (orgs == null) {
LOGGER.error("No organizations received from the cache.");
idpCombo.add("No entries");
}
// 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;
LOGGER.debug("Adding: " + o.toString());
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);
// check if we had saved an authentication method
String savedAuthMethod = Config.getAuthenticationMethod();
if (savedAuthMethod != null && !savedAuthMethod.isEmpty()) {
LOGIN_TYPE savedLoginType = LOGIN_TYPE.getEnum(savedAuthMethod);
// if no valid LOGIN_TYPE was saved, just enable the BWIDM button
if (savedLoginType == null) {
authButtons[LOGIN_TYPE.BWIDM.getId()].setSelection(true);
loginType = LOGIN_TYPE.BWIDM;
} else {
authButtons[savedLoginType.getId()].setSelection(true);
loginType = savedLoginType;
idpText.setVisible(savedLoginType == LOGIN_TYPE.BWIDM);
idpCombo.setVisible(savedLoginType == LOGIN_TYPE.BWIDM);
}
} else {
// default value for LOGIN_TYPE is BWIDM
authButtons[LOGIN_TYPE.BWIDM.getId()].setSelection(true);
loginType = LOGIN_TYPE.BWIDM;
}
// 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.setVisible(true);
loginType = LOGIN_TYPE.BWIDM;
}
});
// 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.BWLP;
}
});
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.SAT;
}
});
// add a key listener to the password field to trigger login
// when the user presses the ENTER key.
passwordText.addKeyListener(new KeyListener() {
@Override
public void keyReleased(KeyEvent e) {
if (e.keyCode == SWT.CR) {
doSaveConfig();
doLogin();
}
}
@Override
public void keyPressed(KeyEvent e) {}
});
}
/**
* 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 != null && !username.isEmpty()) {
// all good, save it
if (!Config.setUsername(username))
LOGGER.error("Could not save username '" + username + "' to '" + Config.getPath() + "'.");
}
}
// always save the authentication method and potentially the identity provider
if (!Config.setAuthenticationMethod(loginType.getTag()))
LOGGER.error("Could not save authentication method '" + loginType.getTag() + "' to '" + Config.getPath() + "'.");
// check if we are doing bwIDM authentication
if (loginType == LOGIN_TYPE.BWIDM) {
// save the selected identity provider
Organization selectedOrg = getSelectedOrganization();
if (!Config.setIdentityProvider(selectedOrg.organizationId))
LOGGER.error("Could not save the identity provider '" + selectedOrg.organizationId + "'!");
}
// finalize by actually storing the config file
if (!Config.store())
LOGGER.error("Could not save '" + Config.getPath() + "'!");
}
/**
* 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) {
LOGGER.error("No login type set, a default should be set! Ignoring...");
return;
}
// here we only check for the fields
username = usernameText.getText();
password = passwordText.getText();
// login clicked, lets first read the fields
if (username == null) {
// tell the GUIManager to show an error to the user
// TODO either popup or in the bottom status bar
GuiManager.showMessage(NO_USERNAME, SWT.ICON_ERROR);
return;
}
if (password == null) {
// tell the GUIManager to show an error to the user
// TODO either popup or in the bottom status bar
GuiManager.showMessage(NO_PASSWORD, SWT.ICON_ERROR);
return;
}
// determine which organization was selected by the user.
Organization selectedOrg = getSelectedOrganization();
// now switch over the login types.
switch (loginType) {
case BWIDM:
BWIDMAuthenticator bwidmAuth = new BWIDMAuthenticator(
selectedOrg.getEcpUrl());
try {
bwidmAuth.login(username, password, new AuthenticatorCallback() {
@Override
public void postLogin(ReturnCode returnCode, UserInfo user) {
// TODO finish this
// handle errors first
if (returnCode != ReturnCode.NO_ERROR && user == null) {
switch(returnCode) {
case IDP_ERROR:
GuiManager.showMessage("IdP Error", SWT.ICON_ERROR);
break;
default:
GuiManager.showMessage("Internal error!", SWT.ICON_ERROR);
break;
}
} else
postSuccessfulLogin();
}
});
} catch (TAuthenticationException e) {
//LOGGER.error("Authentication error, see trace: ", e);
GuiManager.showMessage(e.getMessage(), SWT.ICON_ERROR);
return;
}
break;
case BWLP:
LOGGER.info("bwlp");
BWLPAuthenticator bwlpAuth = new BWLPAuthenticator();
try {
bwlpAuth.login(username, password, new AuthenticatorCallback() {
@Override
public void postLogin(ReturnCode returnCode, UserInfo user) {
// handle errors first
if (returnCode != ReturnCode.NO_ERROR && user == null) {
LOGGER.error("BWLP login failed.");
GuiManager.showMessage("Login failed!", SWT.ICON_ERROR);
}
if (returnCode == ReturnCode.NO_ERROR && user != null)
postSuccessfulLogin();
}
});
} catch (TAuthenticationException e) {
GuiManager.showMessage(e.getMessage(), SWT.ICON_ERROR);
}
break;
case SAT:
LOGGER.warn("Direct satellite login is not yet supported.");
break;
default:
LOGGER.error("Unknown login type! Ignoring...");
break;
}
return;
}
/**
* Functions called by doLogin is the login process succeeded.
*/
private void postSuccessfulLogin() {
LOGGER.info(loginType.getTag() + " succeeded.");
// TODO HACK HACK
ThriftManager.setSatelliteAddress( "132.230.8.113" );
// now read the config to see if the user already agreed to the disclaimer
if (!Config.getDisclaimerAgreement())
GuiManager.addContent(new DisclaimerWindow(getShell()));
else if (!Config.getVmwareLicenseAgreement())
GuiManager.addContent(new VirtualizerNoticeWindow(getShell()));
// TODO: See MainWindowLayout comments
}
/**
* @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));
}
}