mschaefers
2012-11-29 27ae9095639bb228a1b7ff86a3ebe4264abf05be
feature: when using LdapUserService one can configure Gitblit to fetch all users from ldap that can possibly login. This allows to see newly generated LDAP users instantly in Gitblit. By now an LDAP user had to log in once to appear in GitBlit.

feature: when LDAP user synchronization is enabled, one can configure GitBlit to delete all LDAP users from the backing user service that are no longer existent in LDAP. By now LDAP users that were deleted still appeared in the GitBlit user list.
2 files modified
112 ■■■■■ changed files
distrib/gitblit.properties 20 ●●●●● patch | view | raw | blame | history
src/com/gitblit/LdapUserService.java 92 ●●●●● patch | view | raw | blame | history
distrib/gitblit.properties
@@ -1044,6 +1044,26 @@
# SINCE 1.0.0
realm.ldap.email = email
# Defines whether to synchronize all LDAP users into the backing user service
#
# Valid values: true, false
# If left blank, false is assumed
realm.ldap.synchronizeUsers.enable = false
# Defines whether to delete non-existent LDAP users from the backing user service
# during synchronization. depends on  realm.ldap.synchronizeUsers.enable = true
#
# Valid values: true, false
# If left blank, true is assumed
realm.ldap.synchronizeUsers.removeDeleted = true
# Attribute on the USER record that indicate their username to be used in gitblit
# when synchronizing users from LDAP
# if blank, Gitblit will use uid
#
#
realm.ldap.uid = uid
# The RedmineUserService must be backed by another user service for standard user
# and team management.
# default: users.conf
src/com/gitblit/LdapUserService.java
@@ -20,10 +20,9 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
@@ -41,6 +40,8 @@
import com.unboundid.ldap.sdk.extensions.StartTLSExtendedRequest;
import com.unboundid.util.ssl.SSLUtil;
import com.unboundid.util.ssl.TrustAllTrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * Implementation of an LDAP user service.
@@ -50,6 +51,7 @@
public class LdapUserService extends GitblitUserService {
    public static final Logger logger = LoggerFactory.getLogger(LdapUserService.class);
    public static final String LDAP_PASSWORD_KEY = "StoredInLDAP";
    
    private IStoredSettings settings;
@@ -65,6 +67,75 @@
        serviceImpl = createUserService(realmFile);
        logger.info("LDAP User Service backed by " + serviceImpl.toString());
        synchronizeLdapUsers();
    }
    protected void synchronizeLdapUsers() {
        final boolean enabled = settings.getBoolean(Keys.realm.ldap.synchronizeUsers.enable, false);
        if (!enabled) {
            return;
        }
        final boolean deleteRemovedLdapUsers = settings.getBoolean(Keys.realm.ldap.synchronizeUsers.removeDeleted, true);
        LDAPConnection ldapConnection = getLdapConnection();
        if (ldapConnection != null) {
            try {
                String accountBase = settings.getString(Keys.realm.ldap.accountBase, "");
                String uidAttribute = settings.getString(Keys.realm.ldap.uid, "uid");
                String accountPattern = settings.getString(Keys.realm.ldap.accountPattern, "(&(objectClass=person)(sAMAccountName=${username}))");
                accountPattern = StringUtils.replace(accountPattern, "${username}", "*");
                SearchResult result = doSearch(ldapConnection, accountBase, accountPattern);
                if (result != null && result.getEntryCount() > 0) {
                    final Map<String, UserModel> ldapUsers = new HashMap<String, UserModel>();
                    for (SearchResultEntry loggingInUser : result.getSearchEntries()) {
                        final String username = loggingInUser.getAttribute(uidAttribute).getValue();
                        logger.debug("LDAP synchronizing: " + username);
                        UserModel user = getUserModel(username);
                        if (user == null) {
                            user = new UserModel(username);
                        }
                        if (!supportsTeamMembershipChanges())
                            getTeamsFromLdap(ldapConnection, username, loggingInUser, user);
                        // Get User Attributes
                        setUserAttributes(user, loggingInUser);
                        // store in map
                        ldapUsers.put(username, user);
                    }
                    if (deleteRemovedLdapUsers) {
                        logger.debug("detecting removed LDAP users...");
                        for (UserModel userModel : super.getAllUsers()) {
                            if (LDAP_PASSWORD_KEY.equals(userModel.password)) {
                                if (! ldapUsers.containsKey(userModel.username)) {
                                    logger.info("deleting removed LDAP user " + userModel.username + " from backing user service");
                                    super.deleteUser(userModel.username);
                                }
                            }
                        }
                    }
                    for (UserModel user : ldapUsers.values()) {
                        // Push the ldap looked up values to backing file
                        super.updateUserModel(user);
                        if (!supportsTeamMembershipChanges()) {
                            for (TeamModel userTeam : user.teams)
                                updateTeamModel(userTeam);
                        }
                    }
                }
            } finally {
                ldapConnection.close();
            }
        }
    }
    
    private LDAPConnection getLdapConnection() {
@@ -226,6 +297,7 @@
                    if (admin.startsWith("@")) { // Team
                        if (user.getTeam(admin.substring(1)) != null)
                            user.canAdmin = true;
                            logger.debug("user "+ user.username+" has administrative rights");
                    } else
                        if (user.getName().equalsIgnoreCase(admin))
                            user.canAdmin = true;
@@ -239,7 +311,7 @@
        setAdminAttribute(user);
        
        // Don't want visibility into the real password, make up a dummy
        user.password = "StoredInLDAP";
        user.password = LDAP_PASSWORD_KEY;
        
        // Get full name Attribute
        String displayName = settings.getString(Keys.realm.ldap.displayName, "");        
@@ -334,6 +406,18 @@
    }
    
    @Override
    public List<String> getAllUsernames() {
        synchronizeLdapUsers();
        return super.getAllUsernames();
    }
    @Override
    public List<UserModel> getAllUsers() {
        synchronizeLdapUsers();
        return super.getAllUsers();
    }
    /**
     * Returns a simple username without any domain prefixes.
     *