William Whittle
2013-06-07 e8b8eec715a41fc0b5e4c397f27c54997f505cb7
Added support for authenticating against a Salesforce org.
1 files added
4 files modified
184 ■■■■■ changed files
.classpath 3 ●●●●● patch | view | raw | blame | history
build.moxie 1 ●●●● patch | view | raw | blame | history
gitblit.iml 33 ●●●●● patch | view | raw | blame | history
src/main/distrib/data/gitblit.properties 15 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/SalesforceUserService.java 132 ●●●●● patch | view | raw | blame | history
.classpath
@@ -37,6 +37,9 @@
    <classpathentry kind="lib" path="ext/jcalendar-1.3.2.jar" />
    <classpathentry kind="lib" path="ext/commons-compress-1.4.1.jar" sourcepath="ext/src/commons-compress-1.4.1.jar" />
    <classpathentry kind="lib" path="ext/xz-1.0.jar" sourcepath="ext/src/xz-1.0.jar" />
    <classpathentry kind="lib" path="ext/force-partner-api-24.0.0.jar" sourcepath="ext/src/force-partner-api-24.0.0.jar" />
    <classpathentry kind="lib" path="ext/force-wsc-24.0.0.jar" sourcepath="ext/src/force-wsc-24.0.0.jar" />
    <classpathentry kind="lib" path="ext/js-1.7R2.jar" sourcepath="ext/src/js-1.7R2.jar" />
    <classpathentry kind="lib" path="ext/junit-4.11.jar" sourcepath="ext/src/junit-4.11.jar" />
    <classpathentry kind="lib" path="ext/hamcrest-core-1.3.jar" sourcepath="ext/src/hamcrest-core-1.3.jar" />
    <classpathentry kind="lib" path="ext/selenium-java-2.28.0.jar" sourcepath="ext/src/selenium-java-2.28.0.jar" />
build.moxie
@@ -147,6 +147,7 @@
- compile 'org.apache.ivy:ivy:2.2.0' :war
- compile 'com.toedter:jcalendar:1.3.2' :authority
- compile 'org.apache.commons:commons-compress:1.4.1' :war
- compile 'com.force.api:force-partner-api:24.0.0' :war
- test 'junit'
# Dependencies for Selenium web page testing
- test 'org.seleniumhq.selenium:selenium-java:${selenium.version}' @jar
gitblit.iml
@@ -380,6 +380,39 @@
        </SOURCES>
      </library>
    </orderEntry>
    <orderEntry type="module-library">
      <library name="force-partner-api-24.0.0.jar">
        <CLASSES>
          <root url="jar://$MODULE_DIR$/ext/force-partner-api-24.0.0.jar!/" />
        </CLASSES>
        <JAVADOC />
        <SOURCES>
          <root url="jar://$MODULE_DIR$/ext/src/force-partner-api-24.0.0.jar!/" />
        </SOURCES>
      </library>
    </orderEntry>
    <orderEntry type="module-library">
      <library name="force-wsc-24.0.0.jar">
        <CLASSES>
          <root url="jar://$MODULE_DIR$/ext/force-wsc-24.0.0.jar!/" />
        </CLASSES>
        <JAVADOC />
        <SOURCES>
          <root url="jar://$MODULE_DIR$/ext/src/force-wsc-24.0.0.jar!/" />
        </SOURCES>
      </library>
    </orderEntry>
    <orderEntry type="module-library">
      <library name="js-1.7R2.jar">
        <CLASSES>
          <root url="jar://$MODULE_DIR$/ext/js-1.7R2.jar!/" />
        </CLASSES>
        <JAVADOC />
        <SOURCES>
          <root url="jar://$MODULE_DIR$/ext/src/js-1.7R2.jar!/" />
        </SOURCES>
      </library>
    </orderEntry>
    <orderEntry type="module-library" scope="TEST">
      <library name="junit-4.11.jar">
        <CLASSES>
src/main/distrib/data/gitblit.properties
@@ -499,6 +499,7 @@
# Alternative user services:
#    com.gitblit.LdapUserService
#    com.gitblit.RedmineUserService
#    com.gitblit.SalesforceUserService
#
# Any custom user service implementation must have a public default constructor.
#
@@ -1096,6 +1097,20 @@
# Advanced Realm Settings
#
# The SalesforceUserService must be backed by another user service for standard user
# and team management.
# default: users.conf
#
# RESTART REQUIRED
# BASEFOLDER
realm.salesforce.backingUserService = ${baseFolder}/users.conf
# Restrict the Salesforce user to members of this org.
# default: 0 (i.e. do not check the Org ID)
#
# RESTART REQUIRED
realm.salesforce.orgId = 0
# URL of the LDAP server.
# To use encrypted transport, use either ldaps:// URL for SSL or ldap+tls:// to
# send StartTLS command.
src/main/java/com/gitblit/SalesforceUserService.java
New file
@@ -0,0 +1,132 @@
package com.gitblit;
import java.io.File;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.StringUtils;
import com.sforce.soap.partner.Connector;
import com.sforce.soap.partner.GetUserInfoResult;
import com.sforce.soap.partner.PartnerConnection;
import com.sforce.ws.ConnectionException;
import com.sforce.ws.ConnectorConfig;
public class SalesforceUserService extends GitblitUserService {
    public static final Logger logger = LoggerFactory
            .getLogger(SalesforceUserService.class);
    private IStoredSettings settings;
    @Override
    public void setup(IStoredSettings settings) {
        this.settings = settings;
        String file = settings.getString(
                Keys.realm.salesforce.backingUserService,
                "${baseFolder}/users.conf");
        File realmFile = GitBlit.getFileOrFolder(file);
        serviceImpl = createUserService(realmFile);
        logger.info("Salesforce User Service backed by "
                + serviceImpl.toString());
    }
    @Override
    public UserModel authenticate(String username, char[] password) {
        if (isLocalAccount(username)) {
            // local account, bypass Salesforce authentication
            return super.authenticate(username, password);
        }
        ConnectorConfig config = new ConnectorConfig();
        config.setUsername(username);
        config.setPassword(new String(password));
        try {
            PartnerConnection connection = Connector.newConnection(config);
            GetUserInfoResult info = connection.getUserInfo();
            String org = settings.getString(Keys.realm.salesforce.orgId, "0")
                    .trim();
            if (!org.equals("0")) {
                if (!org.equals(info.getOrganizationId())) {
                    logger.warn("Access attempted by user of an invalid org: "
                            + info.getUserName() + ", org: "
                            + info.getOrganizationName() + "("
                            + info.getOrganizationId() + ")");
                    return null;
                }
            }
            logger.info("Authenticated user " + info.getUserName()
                    + " using org " + info.getOrganizationName() + "("
                    + info.getOrganizationId() + ")");
            String simpleUsername = getSimpleUsername(info);
            UserModel user = null;
            synchronized (this) {
                user = getUserModel(simpleUsername);
                if (user == null)
                    user = new UserModel(simpleUsername);
                if (StringUtils.isEmpty(user.cookie)
                        && !ArrayUtils.isEmpty(password)) {
                    user.cookie = StringUtils.getSHA1(user.username
                            + new String(password));
                }
                setUserAttributes(user, info);
                super.updateUserModel(user);
            }
            return user;
        } catch (ConnectionException e) {
            logger.error("Failed to authenticate", e);
        }
        return null;
    }
    private void setUserAttributes(UserModel user, GetUserInfoResult info) {
        // Don't want visibility into the real password, make up a dummy
        user.password = ExternalAccount;
        user.accountType = getAccountType();
        // Get full name Attribute
        user.displayName = info.getUserFullName();
        // Get email address Attribute
        user.emailAddress = info.getUserEmail();
    }
    /**
     * Simple user name is the first part of the email address.
     */
    private String getSimpleUsername(GetUserInfoResult info) {
        String email = info.getUserEmail();
        return email.split("@")[0];
    }
    @Override
    public boolean supportsCredentialChanges() {
        return false;
    }
    @Override
    public boolean supportsDisplayNameChanges() {
        return false;
    }
    @Override
    public boolean supportsEmailAddressChanges() {
        return false;
    }
}