Skip to content

Commit

Permalink
JBIDE-21162 - allow credentials to have no password and be prompted e…
Browse files Browse the repository at this point in the history
…very time

Edit credential has incorrect initialization of password text enablement

Cleanup as per review
  • Loading branch information
robstryker committed Dec 10, 2015
1 parent 83af3da commit 3fd35c6
Show file tree
Hide file tree
Showing 17 changed files with 637 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<?eclipse version="3.5"?>
<plugin>
<extension-point id="org.jboss.tools.foundation.core.propertiesProviders" name="propertiesProviders" schema="schema/org.jboss.tools.foundation.core.propertiesProviders.exsd"/>
<extension-point id="org.jboss.tools.foundation.core.credentialPrompter" name="credentialPrompter" schema="schema/org.jboss.tools.foundation.core.credentialPrompter.exsd"/>

<extension
point="org.jboss.tools.foundation.core.propertiesProviders">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.jboss.tools.foundation.core" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appinfo>
<meta.schema plugin="org.jboss.tools.foundation.core" id="org.jboss.tools.foundation.core.credentialPrompter" name="credentialPrompter"/>
</appinfo>
<documentation>
[Enter description of this extension point.]
</documentation>
</annotation>

<element name="extension">
<annotation>
<appinfo>
<meta.element />
</appinfo>
</annotation>
<complexType>
<sequence>
<element ref="prompter"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>

</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>

</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>

</documentation>
<appinfo>
<meta.attribute translatable="true"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>

<element name="prompter">
<complexType>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>

</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.jboss.tools.foundation.core.credentials.ICredentialsPrompter"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>

<annotation>
<appinfo>
<meta.section type="since"/>
</appinfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>

<annotation>
<appinfo>
<meta.section type="examples"/>
</appinfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>

<annotation>
<appinfo>
<meta.section type="apiinfo"/>
</appinfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>

<annotation>
<appinfo>
<meta.section type="implementation"/>
</appinfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>


</schema>
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,22 @@ public interface ICredentialsModel {
*/
public void addCredentials(ICredentialDomain domain, String user, String pass);

/**
* Add credentials that require a prompt on every occasion
* @param domain
* @param user
*/
public void addPromptedCredentials(ICredentialDomain domain, String user);


/**
* Return whether this credential requires a prompt on every occasion
* @param domain
* @param user
* @return
*/
public boolean credentialRequiresPrompt(ICredentialDomain domain, String user);

/**
* Remove a credential from the given credential domain
* @param domain
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*******************************************************************************
* Copyright (c) 2015 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.foundation.core.credentials;

/**
* Provide a password for the given domain / user combination
*/
public interface ICredentialsPrompter {
/**
* Get the password
* @param domain
* @param user
* @return
*/
public String getPassword(ICredentialDomain domain, String user);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@
******************************************************************************/
package org.jboss.tools.foundation.core.credentials.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import org.eclipse.equinox.security.storage.ISecurePreferences;
import org.eclipse.equinox.security.storage.SecurePreferencesFactory;
Expand All @@ -29,6 +33,7 @@ public class CredentialDomain implements ICredentialDomain {
static final String PROPERTY_PASS = "pass";
static final String PROPERTY_DEFAULT_USER = "default.user";
static final String PROPERTY_USER_LIST = "user.list";
static final String PROPERTY_PROMPTED_USER_LIST = "user.list.prompted";

static final String NOT_LOADED_PASSWORD = "********";

Expand All @@ -37,20 +42,22 @@ public class CredentialDomain implements ICredentialDomain {
private String id, defaultUsername;
private boolean removable;
private HashMap<String, String> credentials;
private ArrayList<String> promptedCredentials;
public CredentialDomain(String id, String name, boolean removable) {
this.id = id;
this.userVisibleName = name;
this.removable = removable;
this.defaultUsername = null;
credentials = new HashMap<String, String>();
this.credentials = new HashMap<String, String>();
this.promptedCredentials = new ArrayList<String>();
}

public CredentialDomain(Preferences pref) throws BackingStoreException {
this.id = pref.get(PROPERTY_ID, (String)null);
this.userVisibleName = pref.get(PROPERTY_NAME, (String)null);;
this.removable = pref.getBoolean(PROPERTY_REMOVABLE, true);
this.defaultUsername = pref.get(PROPERTY_DEFAULT_USER, (String)null);

credentials = new HashMap<String, String>();
String usersList = pref.get(PROPERTY_USER_LIST, (String)null);
if( !usersList.isEmpty()) {
Expand All @@ -59,8 +66,20 @@ public CredentialDomain(Preferences pref) throws BackingStoreException {
credentials.put(users[i], NOT_LOADED_PASSWORD);
}
}
if( defaultUsername == null && credentials.size() > 0 ) {
defaultUsername = credentials.keySet().iterator().next();

String promptedUserList = pref.get(PROPERTY_PROMPTED_USER_LIST, (String)null);
promptedCredentials = new ArrayList<String>();
if( !promptedUserList.isEmpty()) {
String[] users = (usersList == null ? new String[0] : promptedUserList.split("\n"));
promptedCredentials.addAll(Arrays.asList(users));
}

if( defaultUsername == null || !userExists(defaultUsername)) {
// The default name doesn't exist, so we need another.
String[] users = getUsernames();
if( users.length > 0) {
defaultUsername = users[0];
}
}
}
public String getId() {
Expand All @@ -74,44 +93,62 @@ public String getName() {
}

public boolean userExists(String user) {
return credentials.containsKey(user);
return credentials.containsKey(user) || promptedCredentials.contains(user);
}

public boolean userRequiresPrompt(String user) {
return promptedCredentials.contains(user);
}

public String[] getUsernames() {
Set<String> keys = credentials.keySet();
return (String[]) keys.toArray(new String[keys.size()]);
SortedSet<String> ret = new TreeSet<String>();
ret.addAll(credentials.keySet());
ret.addAll(promptedCredentials);
return (String[]) ret.toArray(new String[ret.size()]);
}

protected void addCredentials(String user, String pass) {
if( defaultUsername == null )
defaultUsername = user;
promptedCredentials.remove(user);
credentials.put(user, pass);
}


protected void addPromptedCredentials(String user) {
if( defaultUsername == null )
defaultUsername = user;
credentials.remove(user);
promptedCredentials.add(user);
}

protected void removeCredential(String user) {
credentials.remove(user);
promptedCredentials.remove(user);
if( user.equals(defaultUsername)) {
// We've removed our default, find a new one
if( credentials.size() == 0 ) {
String[] usernames = getUsernames();
if( usernames.length == 0 ) {
defaultUsername = null;
} else {
// Take the first from the list
defaultUsername = credentials.keySet().iterator().next();
defaultUsername = usernames[0];
}
}
}

public String getCredentials(String user) throws StorageException {
String ret = credentials.get(user);
if( NOT_LOADED_PASSWORD.equals(ret)) {
ISecurePreferences secureRoot = SecurePreferencesFactory.getDefault();
ISecurePreferences secureCredentialRoot = secureRoot.node(CredentialsModel.CREDENTIAL_BASE_KEY);
ISecurePreferences secureDomain = secureCredentialRoot.node(getId());
ISecurePreferences secureUser = secureDomain.node(user);
ret = secureUser.get(PROPERTY_PASS, (String)null);
credentials.put(user, ret);
if( !userRequiresPrompt(user)) {
String ret = credentials.get(user);
if( NOT_LOADED_PASSWORD.equals(ret)) {
ISecurePreferences secureRoot = SecurePreferencesFactory.getDefault();
ISecurePreferences secureCredentialRoot = secureRoot.node(CredentialsModel.CREDENTIAL_BASE_KEY);
ISecurePreferences secureDomain = secureCredentialRoot.node(getId());
ISecurePreferences secureUser = secureDomain.node(user);
ret = secureUser.get(PROPERTY_PASS, (String)null);
credentials.put(user, ret);
}
return ret;
} else {
return CredentialsModel.getDefault().promptForPassword(this, user);
}
return ret;
}

void saveToPreferences(Preferences prefs, ISecurePreferences securePrefs) throws StorageException {
Expand All @@ -131,14 +168,17 @@ void saveToPreferences(Preferences prefs, ISecurePreferences securePrefs) throws
ISecurePreferences userNode = securePrefs.node(user);
userNode.put(PROPERTY_PASS, getCredentials(user), true);
}

String[] promptedUsers = (String[]) promptedCredentials.toArray(new String[promptedCredentials.size()]);
prefs.put(PROPERTY_PROMPTED_USER_LIST, String.join("\n", promptedUsers));
}
@Override

public String getDefaultUsername() {
return defaultUsername;
}

public void setDefaultUsername(String user) throws IllegalArgumentException {
if( !credentials.containsKey(user)) {
if( !userExists(user)) {
throw new IllegalArgumentException("User " + user + " does not exist for this domain.");
}
defaultUsername = user;
Expand Down
Loading

0 comments on commit 3fd35c6

Please sign in to comment.