summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.classpath3
-rw-r--r--build.moxie1
-rw-r--r--gitblit.iml33
-rw-r--r--src/main/distrib/data/gitblit.properties15
-rw-r--r--src/main/java/com/gitblit/SalesforceUserService.java132
5 files changed, 184 insertions, 0 deletions
diff --git a/.classpath b/.classpath
index ffb673d8..e25f68c5 100644
--- a/.classpath
+++ b/.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" />
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;
+ }
+}