summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorCarsten Pfeiffer2011-07-04 04:57:53 (EDT)
committer Carsten Pfeiffer2011-07-04 05:00:07 (EDT)
commitd087744b091b88083710563510a1dbe6cebb3f9d (patch)
treec4b45b021ceac6a48ba969438cf69274703a8b9f
parent66d9aa2a1cb94641a51532b2bb52c409a12d7b2c (diff)
downloadegit-d087744b091b88083710563510a1dbe6cebb3f9d.zip
egit-d087744b091b88083710563510a1dbe6cebb3f9d.tar.gz
egit-d087744b091b88083710563510a1dbe6cebb3f9d.tar.bz2
Make use of secure storage for ssh auth againrefs/changes/96/3796/2
Let EGitCredentialsProvider handle all currently known credential types instead of just username and password. Both pubkey and password auth work. Reverts http://egit.eclipse.org/r/#change,3574 so that the EGitCredentialsProvider is not silently overwritten. Additionally removes the need for http://egit.eclipse.org/r/#change,3594 Change-Id: Idaabeba86467573108f7ab7307f11f4ad57d9378
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseSshSessionFactory.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java12
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/credentials/EGitCredentialsProvider.java130
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CustomPromptDialog.java194
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties4
5 files changed, 327 insertions, 16 deletions
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseSshSessionFactory.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseSshSessionFactory.java
index cdc3c46..d2d8cc3 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseSshSessionFactory.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseSshSessionFactory.java
@@ -59,8 +59,7 @@ class EclipseSshSessionFactory extends JschConfigSessionFactory {
@Override
protected void configure(final OpenSshConfig.Host hc, final Session session) {
UserInfo userInfo = session.getUserInfo();
- if (!hc.isBatchMode()
- && (userInfo == null || userInfo.getPassword() == null))
+ if (!hc.isBatchMode() && userInfo == null)
new UserInfoPrompter(session);
}
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java
index 7f74df9..a566634 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java
@@ -3838,6 +3838,18 @@ public class UIText extends NLS {
/** */
public static String SynchronizeFetchJob_FetchFailedMessage;
+ /** */
+ public static String EGitCredentialsProvider_question;
+
+ /** */
+ public static String EGitCredentialsProvider_information;
+
+ /** */
+ public static String CustomPromptDialog_provide_information_for;
+
+ /** */
+ public static String CustomPromptDialog_information_about;
+
static {
initializeMessages(BUNDLE_NAME, UIText.class);
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/credentials/EGitCredentialsProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/credentials/EGitCredentialsProvider.java
index 6c3a55f..c85c342 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/credentials/EGitCredentialsProvider.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/credentials/EGitCredentialsProvider.java
@@ -14,7 +14,11 @@ import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.egit.core.Activator;
import org.eclipse.egit.core.securestorage.UserPasswordCredentials;
import org.eclipse.egit.ui.UIText;
+import org.eclipse.egit.ui.internal.dialogs.CustomPromptDialog;
import org.eclipse.equinox.security.storage.StorageException;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.window.Window;
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
import org.eclipse.jgit.transport.CredentialItem;
import org.eclipse.jgit.transport.CredentialsProvider;
@@ -37,9 +41,13 @@ public class EGitCredentialsProvider extends CredentialsProvider {
@Override
public boolean supports(CredentialItem... items) {
for (CredentialItem i : items) {
- if (i instanceof CredentialItem.Username)
+ if (i instanceof CredentialItem.StringType)
continue;
- else if (i instanceof CredentialItem.Password)
+ else if (i instanceof CredentialItem.CharArrayType)
+ continue;
+ else if (i instanceof CredentialItem.YesNoType)
+ continue;
+ else if (i instanceof CredentialItem.InformationalMessage)
continue;
else
return false;
@@ -48,10 +56,16 @@ public class EGitCredentialsProvider extends CredentialsProvider {
}
@Override
- public boolean get(final URIish uri, CredentialItem... items)
+ public boolean get(final URIish uri, final CredentialItem... items)
throws UnsupportedCredentialItem {
+
+ if (items.length == 0) {
+ return true;
+ }
+
CredentialItem.Username userItem = null;
CredentialItem.Password passwordItem = null;
+ boolean isSpecial = false;
for (CredentialItem item : items) {
if (item instanceof CredentialItem.Username)
@@ -59,21 +73,110 @@ public class EGitCredentialsProvider extends CredentialsProvider {
else if (item instanceof CredentialItem.Password)
passwordItem = (CredentialItem.Password) item;
else
- throw new UnsupportedCredentialItem(uri, item.getPromptText());
+ isSpecial = true;
+ }
+
+ if (!isSpecial && (userItem != null || passwordItem != null)) {
+ UserPasswordCredentials credentials = getCredentialsFromSecureStore(uri);
+
+ if (credentials == null) {
+ credentials = getCredentialsFromUser(uri);
+ if (credentials == null)
+ return false;
+ }
+ if (userItem != null)
+ userItem.setValue(credentials.getUser());
+ if (passwordItem != null)
+ passwordItem.setValue(credentials.getPassword().toCharArray());
+ return true;
}
- UserPasswordCredentials credentials = getCredentialsFromSecureStore(uri);
+ // special handling for non-user,non-password type items
+ final boolean[] result = new boolean[1];
+
+ PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
+ public void run() {
+ Shell shell = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow().getShell();
- if (credentials == null) {
- credentials = getCredentialsFromUser(uri);
- if (credentials == null)
+ if (items.length == 1) {
+ CredentialItem item = items[0];
+ result[0] = getSingleSpecial(shell, uri, item);
+ } else {
+ result[0] = getMultiSpecial(shell, uri, items);
+ }
+ }
+ });
+
+ return result[0];
+ }
+
+ /**
+ * Opens a dialog for a single non-user, non-password type item.
+ * @param shell the shell to use
+ * @param uri the uri of the get request
+ * @param item the item to handle
+ * @return <code>true</code> if the request was successful and values were supplied;
+ * <code>false</code> if the user canceled the request and did not supply all requested values.
+ */
+ private boolean getSingleSpecial(Shell shell, URIish uri, CredentialItem item) {
+ if (item instanceof CredentialItem.InformationalMessage) {
+ MessageDialog.openInformation(shell, UIText.EGitCredentialsProvider_information, item.getPromptText());
+ return true;
+ } else if (item instanceof CredentialItem.YesNoType) {
+ CredentialItem.YesNoType v = (CredentialItem.YesNoType) item;
+ String[] labels = new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL };
+ int[] resultIDs = new int[] { IDialogConstants.YES_ID, IDialogConstants.NO_ID, IDialogConstants.CANCEL_ID };
+
+ MessageDialog dialog = new MessageDialog(
+ shell,
+ UIText.EGitCredentialsProvider_question,
+ null,
+ item.getPromptText(),
+ MessageDialog.QUESTION_WITH_CANCEL,
+ labels,
+ 0);
+ dialog.setBlockOnOpen(true);
+ int r = dialog.open();
+ if (r < 0) {
return false;
+ }
+
+ switch (resultIDs[r]) {
+ case IDialogConstants.YES_ID: {
+ v.setValue(true);
+ return true;
+ }
+ case IDialogConstants.NO_ID: {
+ v.setValue(false);
+ return true;
+ }
+ default:
+ // abort
+ return false;
+ }
+ } else {
+ // generically handles all other types of items
+ return getMultiSpecial(shell, uri, item);
}
- if (userItem != null)
- userItem.setValue(credentials.getUser());
- if (passwordItem != null)
- passwordItem.setValue(credentials.getPassword().toCharArray());
- return true;
+ }
+
+ /**
+ * Opens a generic dialog presenting all CredentialItems to the user.
+ * @param shell the shell to use
+ * @param uri the uri of the get request
+ * @param items the items to handle
+ * @return <code>true</code> if the request was successful and values were supplied;
+ * <code>false</code> if the user canceled the request and did not supply all requested values.
+ */
+ private boolean getMultiSpecial(Shell shell, URIish uri, CredentialItem... items) {
+ CustomPromptDialog dialog = new CustomPromptDialog(shell, uri, UIText.EGitCredentialsProvider_information, items);
+ dialog.setBlockOnOpen(true);
+ int r = dialog.open();
+ if (r == Window.OK) {
+ return true;
+ }
+ return false;
}
private UserPasswordCredentials getCredentialsFromUser(final URIish uri) {
@@ -100,5 +203,4 @@ public class EGitCredentialsProvider extends CredentialsProvider {
}
return credentials;
}
-
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CustomPromptDialog.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CustomPromptDialog.java
new file mode 100644
index 0000000..5f0b9e0
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CustomPromptDialog.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2011 GEBIT Solutions.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Carsten Pfeiffer(GEBIT Solutions) - initial implementation
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.dialogs;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.egit.ui.UIText;
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jgit.transport.CredentialItem;
+import org.eclipse.jgit.transport.CredentialItem.CharArrayType;
+import org.eclipse.jgit.transport.CredentialItem.StringType;
+import org.eclipse.jgit.transport.CredentialItem.YesNoType;
+import org.eclipse.jgit.transport.URIish;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+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.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * This dialog is used in order to display information about
+ * authentication problems, and/or request authentication input
+ * from the user.
+ *
+ * The {@link CredentialItem CredentialItems} passed in the constructor
+ * are updated to reflect the user-specified values as soon as the dialog
+ * is confirmed.
+ */
+public class CustomPromptDialog extends TrayDialog {
+ private CredentialItem[] credentialItems;
+ private List<Control> editingControls;
+ private URIish uri;
+ private String title;
+ private static final String KEY_ITEM = "item"; //$NON-NLS-1$
+
+ /**
+ * Creates an instance of the dialog that will present the given
+ * CredentialItems and let the user supply values for them
+ * @param shell the shell for this dialog
+ * @param uri the uri for which the information shall be displayed
+ * @param title an optional title for this dialog
+ * @param items the items to display and edit
+ */
+ public CustomPromptDialog(Shell shell, URIish uri, String title, CredentialItem... items) {
+ super(shell);
+ this.uri = uri;
+ this.title = title;
+ setShellStyle(getShellStyle() | SWT.SHELL_TRIM);
+ credentialItems = items;
+ }
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ if (title != null) {
+ newShell.setText(title);
+ }
+ }
+
+ /**
+ * Returns the credential items that were passed into the constructor.
+ * @return the credential items
+ */
+ public CredentialItem[] getCredentialItems() {
+ return credentialItems;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ editingControls = new ArrayList<Control>(credentialItems.length);
+
+ Composite main = (Composite) super.createDialogArea(parent);
+ GridLayout mainLayout = (GridLayout) main.getLayout();
+ mainLayout.numColumns = 2;
+
+ Label infoLabel = new Label(main, SWT.NONE);
+ GridDataFactory.defaultsFor(infoLabel).span(2, 1).applyTo(infoLabel);
+ String tempInfoText = hasEditingItems()
+ ? UIText.CustomPromptDialog_provide_information_for
+ : UIText.CustomPromptDialog_information_about;
+ infoLabel.setText(NLS.bind(tempInfoText, uri.toString()));
+
+ for (CredentialItem item : credentialItems) {
+ Label label = new Label(main, SWT.NONE);
+ label.setText(item.getPromptText());
+ GridDataFactory.defaultsFor(label).applyTo(label);
+
+ if (item instanceof CharArrayType || item instanceof StringType) {
+ Text text = new Text(main, SWT.BORDER | (item.isValueSecure() ? SWT.PASSWORD : SWT.NONE));
+ GridDataFactory.defaultsFor(text).applyTo(text);
+ text.setData(KEY_ITEM, item);
+ editingControls.add(text);
+ } else if (item instanceof YesNoType) {
+ Button checkBox = new Button(main, SWT.CHECK);
+ GridDataFactory.defaultsFor(checkBox).applyTo(checkBox);
+ editingControls.add(checkBox);
+ } else {
+ // unknown type, not editable
+ Label dummy = new Label(main, SWT.NONE);
+ GridDataFactory.fillDefaults().applyTo(dummy);
+ }
+ }
+
+ return main;
+ }
+
+ /**
+ * Returns <code>true</code> if there's anything to edit for the user
+ * @return <code>true</code> if the user needs to supply some data
+ */
+ private boolean hasEditingItems() {
+ for (CredentialItem item : credentialItems) {
+ if (item instanceof StringType) {
+ return true;
+ }
+ if (item instanceof CharArrayType) {
+ return true;
+ }
+ if (item instanceof YesNoType) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected void okPressed() {
+ updateValues();
+
+ super.okPressed();
+ }
+
+ /**
+ * Updates all {@link CredentialItem CredentialItems} with the
+ * user-supplied values.
+ */
+ private void updateValues() {
+ for (Control control : editingControls) {
+ if (control instanceof Text) {
+ Text textControl = (Text) control;
+ CredentialItem itemToUpdate = (CredentialItem) textControl.getData(KEY_ITEM);
+ String value = textControl.getText();
+ updateValue(itemToUpdate, value);
+ } else if (control instanceof Button) {
+ Button checkBoxControl = (Button) control;
+ CredentialItem itemToUpdate = (CredentialItem) checkBoxControl.getData(KEY_ITEM);
+ boolean value = checkBoxControl.getSelection();
+ updateValue(itemToUpdate, value);
+ }
+ }
+ }
+
+ /**
+ * Updates the value of the given {@link CredentialItem}.
+ * @param itemToUpdate the item to update
+ * @param value the new value
+ */
+ protected void updateValue(CredentialItem itemToUpdate, String value) {
+ if (itemToUpdate instanceof CharArrayType) {
+ ((CharArrayType) itemToUpdate).setValueNoCopy(value.toCharArray());
+ } else if (itemToUpdate instanceof StringType) {
+ ((StringType) itemToUpdate).setValue(value);
+ } else {
+ throw new IllegalArgumentException("Cannot handle item of type " + itemToUpdate.getClass()); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Updates the value of the given {@link CredentialItem}.
+ * @param itemToUpdate the item to update
+ * @param value the new value
+ */
+ protected void updateValue(CredentialItem itemToUpdate, boolean value) {
+ if (itemToUpdate instanceof YesNoType) {
+ ((YesNoType) itemToUpdate).setValue(value);
+ } else {
+ throw new IllegalArgumentException("Cannot handle item of type " + itemToUpdate.getClass()); //$NON-NLS-1$
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties
index c0e544d..946e877 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties
@@ -69,6 +69,10 @@ GerritConfigurationPage_pushUri=Push URI
GerritConfigurationPage_title=Gerrit Configuration
EGitCredentialsProvider_errorReadingCredentials=Failed reading credentials from secure store
+EGitCredentialsProvider_question=Question
+EGitCredentialsProvider_information=Information
+CustomPromptDialog_provide_information_for=Provide information for {0}
+CustomPromptDialog_information_about=Information about {0}
EgitUiUtils_CouldNotOpenEditorMessage=Could not open editor of type {0}
ExistingOrNewPage_BrowseRepositoryButton=Browse...
ExistingOrNewPage_CreateButton=&Create Repository