From f6d7de15b1471b1c101362dbaf598de8031e6540 Mon Sep 17 00:00:00 2001
From: Alfred Schmid <A.Schmid@ff-muenchen.de>
Date: Wed, 19 Feb 2014 11:04:16 -0500
Subject: [PATCH] Load empty groups as empty teams from ldap, when ldap user synchronization is enabled.

---
 src/main/java/com/gitblit/auth/LdapAuthProvider.java        |   24 ++++++++++++
 src/test/resources/ldap/addgroup.ldif                       |    5 ++
 src/main/distrib/data/gitblit.properties                    |    9 ++++
 src/test/java/com/gitblit/tests/LdapAuthenticationTest.java |   28 ++++++++++++++
 4 files changed, 66 insertions(+), 0 deletions(-)

diff --git a/src/main/distrib/data/gitblit.properties b/src/main/distrib/data/gitblit.properties
index bd0efd9..3297d25 100644
--- a/src/main/distrib/data/gitblit.properties
+++ b/src/main/distrib/data/gitblit.properties
@@ -1460,6 +1460,14 @@
 # SINCE 1.0.0
 realm.ldap.groupMemberPattern = (&(objectClass=group)(member=${dn}))
 
+# Filter criteria for empty LDAP groups
+#
+# Query pattern to use when searching for an empty team. This may be any valid 
+# LDAP query expression, including the standard (&) and (|) operators.
+#
+# SINCE 1.4.0
+realm.ldap.groupEmptyMemberPattern = (&(objectClass=group)(!(member=*)))
+
 # LDAP users or groups that should be given administrator privileges.
 #
 # Teams are specified with a leading '@' character.  Groups with spaces in the
@@ -1516,6 +1524,7 @@
 # default: 5 MINUTES
 #
 # RESTART REQUIRED
+# SINCE 1.4.0
 realm.ldap.synchronizeUsers.ldapSyncPeriod = 5 MINUTES
 
 # Defines whether to delete non-existent LDAP users from the backing user service
diff --git a/src/main/java/com/gitblit/auth/LdapAuthProvider.java b/src/main/java/com/gitblit/auth/LdapAuthProvider.java
index 1ec273a..b208459 100644
--- a/src/main/java/com/gitblit/auth/LdapAuthProvider.java
+++ b/src/main/java/com/gitblit/auth/LdapAuthProvider.java
@@ -152,6 +152,9 @@
                                 userManager.updateTeamModels(userTeams.values());
                             }
                         }
+                        if (!supportsTeamMembershipChanges()) {
+                        	getEmptyTeamsFromLdap(ldapConnection);
+                        }
                         lastLdapUserSync.set(System.currentTimeMillis());
                     } finally {
                         ldapConnection.close();
@@ -435,6 +438,27 @@
 		}
 	}
 
+	private void getEmptyTeamsFromLdap(LDAPConnection ldapConnection) {
+		String groupBase = settings.getString(Keys.realm.ldap.groupBase, "");
+		String groupMemberPattern = settings.getString(Keys.realm.ldap.groupEmptyMemberPattern, "(&(objectClass=group)(!(member=*)))");
+
+		SearchResult teamMembershipResult = doSearch(ldapConnection, groupBase, true, groupMemberPattern, null);
+		if (teamMembershipResult != null && teamMembershipResult.getEntryCount() > 0) {
+			for (int i = 0; i < teamMembershipResult.getEntryCount(); i++) {
+				SearchResultEntry teamEntry = teamMembershipResult.getSearchEntries().get(i);
+				if (!teamEntry.hasAttribute("member")) {
+					String teamName = teamEntry.getAttribute("cn").getValue();
+	
+					TeamModel teamModel = userManager.getTeamModel(teamName);
+					if (teamModel == null) {
+						teamModel = createTeamFromLdap(teamEntry);
+						userManager.updateTeamModel(teamModel);
+					}
+				}
+			}
+		}
+	}
+
 	private TeamModel createTeamFromLdap(SearchResultEntry teamEntry) {
 		TeamModel answer = new TeamModel(teamEntry.getAttributeValue("cn"));
 		answer.accountType = getAccountType();
diff --git a/src/test/java/com/gitblit/tests/LdapAuthenticationTest.java b/src/test/java/com/gitblit/tests/LdapAuthenticationTest.java
index ce3615e..670dde0 100644
--- a/src/test/java/com/gitblit/tests/LdapAuthenticationTest.java
+++ b/src/test/java/com/gitblit/tests/LdapAuthenticationTest.java
@@ -34,6 +34,7 @@
 import com.gitblit.manager.IUserManager;
 import com.gitblit.manager.RuntimeManager;
 import com.gitblit.manager.UserManager;
+import com.gitblit.models.TeamModel;
 import com.gitblit.models.UserModel;
 import com.gitblit.tests.mock.MemorySettings;
 import com.unboundid.ldap.listener.InMemoryDirectoryServer;
@@ -208,6 +209,23 @@
 		assertEquals("Number of ldap users in gitblit user model", 6, countLdapUsersInUserManager());
 	}
 
+	@Test
+	public void addingGroupsInLdapShouldNotUpdateGitBlitUsersAndGroups() throws Exception {
+		settings.put("realm.ldap.ldapCachePeriod", "0 MINUTES");
+		ds.addEntries(LDIFReader.readEntries(RESOURCE_DIR + "addgroup.ldif"));
+		ldap.synchronizeWithLdapService();
+		assertEquals("Number of ldap groups in gitblit team model", 0, countLdapTeamsInUserManager());
+	}
+
+	@Test
+	public void addingGroupsInLdapShouldUpdateGitBlitUsersAndGroups() throws Exception {
+		settings.put("realm.ldap.synchronizeUsers.enable", "true");
+		settings.put("realm.ldap.ldapCachePeriod", "0 MINUTES");
+		ds.addEntries(LDIFReader.readEntries(RESOURCE_DIR + "addgroup.ldif"));
+		ldap.synchronizeWithLdapService();
+		assertEquals("Number of ldap groups in gitblit team model", 1, countLdapTeamsInUserManager());
+	}
+
 	private int countLdapUsersInUserManager() {
 		int ldapAccountCount = 0;
 		for (UserModel userModel : userManager.getAllUsers()) {
@@ -218,4 +236,14 @@
 		return ldapAccountCount;
 	}
 
+	private int countLdapTeamsInUserManager() {
+		int ldapAccountCount = 0;
+		for (TeamModel teamModel : userManager.getAllTeams()) {
+			if (AccountType.LDAP.equals(teamModel.accountType)) {
+				ldapAccountCount++;
+			}
+		}
+		return ldapAccountCount;
+	}
+
 }
diff --git a/src/test/resources/ldap/addgroup.ldif b/src/test/resources/ldap/addgroup.ldif
new file mode 100644
index 0000000..665df31
--- /dev/null
+++ b/src/test/resources/ldap/addgroup.ldif
@@ -0,0 +1,5 @@
+dn: CN=Git_Group_Without_Members,OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain
+objectClass: top
+objectClass: group
+cn: Git_Group_Without_Members
+sAMAccountName: Git_Group_Without_Members

--
Gitblit v1.9.1