/*******************************************************************************
* Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.com>
* This file is part of Gluster Management Console.
*
* Gluster Management Console is free software; you can redistribute
* it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* Gluster Management Console is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*******************************************************************************/
package org.gluster.storage.management.console.dialogs;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.PojoProperties;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.gluster.storage.management.client.ClustersClient;
import org.gluster.storage.management.client.UsersClient;
import org.gluster.storage.management.console.Activator;
import org.gluster.storage.management.console.ConsoleConstants;
import org.gluster.storage.management.console.GlusterDataModelManager;
import org.gluster.storage.management.console.IImageKeys;
import org.gluster.storage.management.console.dialogs.ClusterSelectionDialog.CLUSTER_MODE;
import org.gluster.storage.management.console.preferences.PreferenceConstants;
import org.gluster.storage.management.console.utils.GUIHelper;
import org.gluster.storage.management.console.validators.StringRequiredValidator;
import org.gluster.storage.management.core.constants.CoreConstants;
import org.gluster.storage.management.core.model.ConnectionDetails;
/**
* Login dialog, which prompts for the user's account info, and has Login and Cancel buttons.
*/
public class LoginDialog extends Dialog {
public static final int RETURN_CODE_ERROR = 2;
private Text userIdText = null;
private Text passwordText = null;
private Button okButton;
private final ConnectionDetails connectionDetails = new ConnectionDetails("gluster", "");
private final GUIHelper guiHelper = GUIHelper.getInstance();
private Composite composite;
public LoginDialog(Shell parentShell) {
super(parentShell);
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText("Gluster Management Console");
addEscapeListener(newShell);
}
private void addEscapeListener(Shell shell) {
shell.addTraverseListener(new TraverseListener() {
@Override
public void keyTraversed(TraverseEvent e) {
if (e.keyCode == SWT.ESC) {
cancelPressed();
}
}
});
}
private void createUserIdLabel(Composite composite) {
Label userIdLabel = new Label(composite, SWT.NONE);
userIdLabel.setText("&User ID:");
userIdLabel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false));
}
private void createUserIdText(Composite composite) {
userIdText = new Text(composite, SWT.BORDER);
userIdText.setText("gluster");
userIdText.setEnabled(false);
GridData layoutData = new GridData(convertWidthInCharsToPixels(32), 15);
userIdText.setLayoutData(layoutData);
}
private void createPasswordLabel(Composite composite) {
Label passwordLabel = new Label(composite, SWT.NONE);
passwordLabel.setText("&Password:");
passwordLabel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false));
}
private void createPasswordText(Composite composite) {
passwordText = new Text(composite, SWT.BORDER | SWT.PASSWORD);
GridData layoutData = new GridData(convertWidthInCharsToPixels(32), 15);
passwordText.setLayoutData(layoutData);
}
private void configureDialogLayout(Composite composite) {
GridLayout layout = (GridLayout) composite.getLayout();
layout.numColumns = 2;
layout.marginLeft = 10;
layout.marginRight = 10;
layout.marginTop = 30;
layout.marginBottom = 0;
layout.horizontalSpacing = 20;
layout.verticalSpacing = 10;
}
private void configureButtonCompositeLayout(Composite composite) {
GridLayout layout = (GridLayout) composite.getLayout();
layout.marginLeft = 20;
layout.marginRight = 20;
layout.marginTop = 0;
layout.horizontalSpacing = 10;
layout.verticalSpacing = 10;
}
/**
* Overriding to make sure that the dialog is centered in screen
*/
@Override
protected void initializeBounds() {
super.initializeBounds();
getShell().setSize(390, 240);
guiHelper.centerShellInScreen(getShell());
}
@Override
protected Control createDialogArea(Composite parent) {
parent.setBackgroundImage(guiHelper.getImage(IImageKeys.DIALOG_SPLASH_IMAGE));
// Makes sure that child composites inherit the same background
parent.setBackgroundMode(SWT.INHERIT_FORCE);
composite = (Composite) super.createDialogArea(parent);
configureDialogLayout(composite);
GridData layoutData = new GridData(390, 110);
composite.setLayoutData(layoutData);
createUserIdLabel(composite);
createUserIdText(composite);
createPasswordLabel(composite);
createPasswordText(composite);
setupAutoLoginIfRequired();
return composite;
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
configureButtonCompositeLayout(parent);
GridData layoutData = new GridData(390, 130);
layoutData.horizontalAlignment = SWT.CENTER;
layoutData.verticalAlignment = SWT.TOP;
layoutData.grabExcessHorizontalSpace = true;
parent.setLayoutData(layoutData);
layoutData = new GridData();
layoutData.widthHint = 70;
layoutData.horizontalAlignment = SWT.RIGHT;
layoutData.grabExcessHorizontalSpace = true;
Button cancelButton = createButton(parent, IDialogConstants.CANCEL_ID, "&Cancel", false);
cancelButton.setLayoutData(layoutData);
layoutData = new GridData();
layoutData.widthHint = 70;
layoutData.horizontalAlignment = SWT.LEFT;
layoutData.grabExcessHorizontalSpace = true;
okButton = createButton(parent, IDialogConstants.OK_ID, "&Login", true);
okButton.setLayoutData(layoutData);
setupDataBinding();
}
private void setupAutoLoginIfRequired() {
final String password = System.getProperty(ConsoleConstants.PROPERTY_AUTO_LOGIN_PASSWORD, null);
if (password == null) {
return;
}
getShell().addShellListener(new ShellAdapter() {
@Override
public void shellActivated(ShellEvent e) {
super.shellActivated(e);
if (passwordText.getText().isEmpty()) {
// Check whether the password has been passed as system parameter. This can be used for avoiding
// human intervention on login dialog while running SWTBot automated tests.
passwordText.setText(password);
okPressed();
}
}
});
}
/**
* Sets up data binding between the text fields and the connection details object. Also attaches a "string required"
* validator to the "password" text field. This validator is configured to do the following on validation failure<br>
* <li>show an ERROR decorator</li><li>disable the "Login" button
*/
private void setupDataBinding() {
DataBindingContext dataBindingContext = new DataBindingContext(SWTObservables.getRealm(Display.getCurrent()));
UpdateValueStrategy passwordBindingStrategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE);
// The Validator shows error decoration and disables OK button on
// validation failure
passwordBindingStrategy.setBeforeSetValidator(new StringRequiredValidator("Please enter password!", guiHelper
.createErrorDecoration(passwordText), okButton));
dataBindingContext.bindValue(WidgetProperties.text(SWT.Modify).observe(passwordText),
PojoProperties.value("password").observe(connectionDetails), passwordBindingStrategy,
passwordBindingStrategy);
UpdateValueStrategy userIdBindingStrategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE);
dataBindingContext
.bindValue(WidgetProperties.text(SWT.Modify).observe(userIdText), PojoProperties.value("userId")
.observe(connectionDetails), userIdBindingStrategy, userIdBindingStrategy);
}
protected void okPressed() {
String user = connectionDetails.getUserId();
String password = connectionDetails.getPassword();
UsersClient usersClient = new UsersClient();
try {
usersClient.authenticate(user, password);
} catch(Exception e) {
MessageDialog.openError(getShell(), "Authentication Failed", e.getMessage());
setReturnCode(RETURN_CODE_ERROR);
return;
}
// authentication successful. close the login dialog and open the next one.
close();
IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore();
boolean showClusterSelectionDialog = preferenceStore.getBoolean(PreferenceConstants.P_SHOW_CLUSTER_SELECTION_DIALOG);
// If the password is default, Let user to change the password
if (password.equalsIgnoreCase(CoreConstants.DEFAULT_PASSWORD)) {
ChangePasswordDialog dialog = new ChangePasswordDialog(getShell());
if (dialog.open() == Dialog.CANCEL) {
MessageDialog.openError(getShell(), "Change password Cancelled",
"Password must be changed on first login!" + CoreConstants.NEWLINE + "Application will close.");
cancelPressed();
return;
}
// after first login, cluster selection dialog must be shown.
showClusterSelectionDialog = true;
}
ClustersClient clustersClient = new ClustersClient();
CLUSTER_MODE mode;
String clusterName = null;
if (!showClusterSelectionDialog) {
clusterName = preferenceStore.getString(PreferenceConstants.P_DEFAULT_CLUSTER_NAME);
if (clusterName == null || clusterName.isEmpty()) {
// Cluster name not available in preferences. Hence we must show the cluster selection dialog.
showClusterSelectionDialog = true;
} else {
mode = CLUSTER_MODE.SELECT;
}
}
String serverName = null;
if (showClusterSelectionDialog) {
ClusterSelectionDialog clusterDialog = new ClusterSelectionDialog(getParentShell(),
clustersClient.getClusterNames());
int userAction = clusterDialog.open();
if (userAction == Window.CANCEL) {
MessageDialog.openError(getShell(), "Login Cancelled",
"User cancelled login at cluster selection. Application will close!");
cancelPressed();
return;
}
mode = clusterDialog.getClusterMode();
clusterName = clusterDialog.getClusterName();
serverName = clusterDialog.getServerName();
} else {
mode = CLUSTER_MODE.SELECT;
}
try {
createOrRegisterCluster(clustersClient, clusterName, serverName, mode);
final String clusterName1 = clusterName;
new ProgressMonitorDialog(getShell()).run(true, false, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
GlusterDataModelManager.getInstance().initializeModel(clusterName1, monitor);
}
});
super.okPressed();
} catch (Exception e) {
String errMsg;
if(e instanceof InvocationTargetException) {
errMsg = ((InvocationTargetException) e).getTargetException().getMessage();
} else {
errMsg = e.getMessage();
}
setReturnCode(RETURN_CODE_ERROR);
MessageDialog.openError(getShell(), "Gluster Management Console", errMsg);
}
}
public void createOrRegisterCluster(ClustersClient clustersClient, String clusterName, String serverName,
CLUSTER_MODE mode) {
switch (mode) {
case SELECT:
return;
case CREATE:
clustersClient.createCluster(clusterName);
break;
case REGISTER:
clustersClient.registerCluster(clusterName, serverName);
break;
}
}
}