aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarsten Pfeiffer2011-07-04 04:57:53 -0400
committerCarsten Pfeiffer2011-07-04 05:00:07 -0400
commitd087744b091b88083710563510a1dbe6cebb3f9d (patch)
treec4b45b021ceac6a48ba969438cf69274703a8b9f
parent66d9aa2a1cb94641a51532b2bb52c409a12d7b2c (diff)
downloadegit-d087744b091b88083710563510a1dbe6cebb3f9d.zip
egit-d087744b091b88083710563510a1dbe6cebb3f9d.tar.gz
egit-d087744b091b88083710563510a1dbe6cebb3f9d.tar.xz
Make use of secure storage for ssh auth again
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