diff options
-rw-r--r-- | .classpath | 3 | ||||
-rw-r--r-- | build.moxie | 1 | ||||
-rw-r--r-- | gitblit.iml | 33 | ||||
-rw-r--r-- | src/main/distrib/data/gitblit.properties | 15 | ||||
-rw-r--r-- | src/main/java/com/gitblit/SalesforceUserService.java | 132 |
5 files changed, 184 insertions, 0 deletions
@@ -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" /> diff --git a/build.moxie b/build.moxie index d27e08a6..be9a21cf 100644 --- a/build.moxie +++ b/build.moxie @@ -147,6 +147,7 @@ dependencies: - 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 diff --git a/gitblit.iml b/gitblit.iml index fe245be2..b90adbd0 100644 --- a/gitblit.iml +++ b/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> diff --git a/src/main/distrib/data/gitblit.properties b/src/main/distrib/data/gitblit.properties index 36d78035..82e77f35 100644 --- a/src/main/distrib/data/gitblit.properties +++ b/src/main/distrib/data/gitblit.properties @@ -499,6 +499,7 @@ web.projectsFile = ${baseFolder}/projects.conf # 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 @@ federation.sets = # 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.
diff --git a/src/main/java/com/gitblit/SalesforceUserService.java b/src/main/java/com/gitblit/SalesforceUserService.java new file mode 100644 index 00000000..4a6a1bae --- /dev/null +++ b/src/main/java/com/gitblit/SalesforceUserService.java @@ -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; + } +} |