From f59baa7abea806ac6d93c8059bfddb60b3acc06d Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Fri, 14 Sep 2007 21:10:37 +0000
Subject: [PATCH] Add support for the groupOfEntries group type as defined in draft-findlay-ldap-groupofentries. Entries with the groupOfEntries object class should be treated in a manner that is virtually identical to entries with the groupOfNames object class (technically, groupOfNames does not allow zero-member groups, but the OpenDS implementation does allow this).
---
opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java | 40 +++++++
opendj-sdk/opends/resource/schema/00-core.ldif | 11 +
opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java | 16 +++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/GroupManagerTestCase.java | 214 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 273 insertions(+), 8 deletions(-)
diff --git a/opendj-sdk/opends/resource/schema/00-core.ldif b/opendj-sdk/opends/resource/schema/00-core.ldif
index 979bedf..0897463 100644
--- a/opendj-sdk/opends/resource/schema/00-core.ldif
+++ b/opendj-sdk/opends/resource/schema/00-core.ldif
@@ -433,10 +433,10 @@
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'RFC 1274' )
attributeTypes: ( 0.9.2342.19200300.100.1.31 NAME 'cNAMERecord'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'RFC 1274' )
-attributeTypes: ( 2.16.840.1.113730.3.1.602 NAME 'entryDN'
- DESC 'DN of the entry' EQUALITY distinguishedNameMatch
- SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE NO-USER-MODIFICATION
- USAGE directoryOperation X-ORIGIN 'draft-zeilenga-ldap-entrydn' )
+attributeTypes: ( 1.3.6.1.1.20 NAME 'entryDN' DESC 'DN of the entry'
+ EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation
+ X-ORIGIN 'RFC 5020' )
attributeTypes: ( 1.3.6.1.4.1.453.16.2.103 NAME 'numSubordinates'
DESC 'Count of immediate subordinates'
EQUALITY integerMatch ORDERING integerOrderingMatch
@@ -622,4 +622,7 @@
objectClasses: ( 0.9.2342.19200300.100.4.22 NAME 'qualityLabelledData' SUP top
MUST dSAQuality MAY ( subtreeMinimumQuality $ subtreeMaximumQuality )
X-ORIGIN 'RFC 1274' )
+objectClasses: ( 1.2.826.0.1.3458854.2.1.1 NAME 'groupOfEntries' SUP top
+ STRUCTURAL MUST cn MAY ( member $ businessCategory $ seeAlso $ owner $ ou $
+ o $ description ) X-ORIGIN 'draft-findlay-ldap-groupofentries' )
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java
index 1008313..2e46e86 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java
@@ -171,11 +171,32 @@
// Determine whether it is a groupOfNames or groupOfUniqueNames entry. If
// neither, then that's a problem.
AttributeType memberAttributeType;
+ ObjectClass groupOfEntriesClass =
+ DirectoryConfig.getObjectClass(OC_GROUP_OF_ENTRIES_LC, true);
ObjectClass groupOfNamesClass =
DirectoryConfig.getObjectClass(OC_GROUP_OF_NAMES_LC, true);
ObjectClass groupOfUniqueNamesClass =
DirectoryConfig.getObjectClass(OC_GROUP_OF_UNIQUE_NAMES_LC, true);
- if (groupEntry.hasObjectClass(groupOfNamesClass))
+ if (groupEntry.hasObjectClass(groupOfEntriesClass))
+ {
+ if (groupEntry.hasObjectClass(groupOfNamesClass))
+ {
+ Message message = ERR_STATICGROUP_INVALID_OC_COMBINATION.
+ get(String.valueOf(groupEntry.getDN()), OC_GROUP_OF_ENTRIES,
+ OC_GROUP_OF_NAMES);
+ throw new DirectoryException(ResultCode.OBJECTCLASS_VIOLATION, message);
+ }
+ else if (groupEntry.hasObjectClass(groupOfUniqueNamesClass))
+ {
+ Message message = ERR_STATICGROUP_INVALID_OC_COMBINATION.
+ get(String.valueOf(groupEntry.getDN()), OC_GROUP_OF_ENTRIES,
+ OC_GROUP_OF_UNIQUE_NAMES);
+ throw new DirectoryException(ResultCode.OBJECTCLASS_VIOLATION, message);
+ }
+
+ memberAttributeType = DirectoryConfig.getAttributeType(ATTR_MEMBER, true);
+ }
+ else if (groupEntry.hasObjectClass(groupOfNamesClass))
{
if (groupEntry.hasObjectClass(groupOfUniqueNamesClass))
{
@@ -247,7 +268,8 @@
// FIXME -- This needs to exclude enhanced groups once we have support for
// them.
String filterString =
- "(&(|(objectClass=groupOfNames)(objectClass=groupOfUniqueNames))" +
+ "(&(|(objectClass=groupOfNames)(objectClass=groupOfUniqueNames)" +
+ "(objectClass=groupOfEntries))" +
"(!(objectClass=ds-virtual-static-group)))";
return SearchFilter.createFilterFromString(filterString);
}
@@ -271,11 +293,23 @@
return false;
}
+ ObjectClass groupOfEntriesClass =
+ DirectoryConfig.getObjectClass(OC_GROUP_OF_ENTRIES_LC, true);
ObjectClass groupOfNamesClass =
DirectoryConfig.getObjectClass(OC_GROUP_OF_NAMES_LC, true);
ObjectClass groupOfUniqueNamesClass =
DirectoryConfig.getObjectClass(OC_GROUP_OF_UNIQUE_NAMES_LC, true);
- if (entry.hasObjectClass(groupOfNamesClass))
+ if (entry.hasObjectClass(groupOfEntriesClass))
+ {
+ if (entry.hasObjectClass(groupOfNamesClass) ||
+ entry.hasObjectClass(groupOfUniqueNamesClass))
+ {
+ return false;
+ }
+
+ return true;
+ }
+ else if (entry.hasObjectClass(groupOfNamesClass))
{
if (entry.hasObjectClass(groupOfUniqueNamesClass))
{
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java b/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
index 704801e..cb9efc5 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
@@ -655,6 +655,22 @@
/**
+ * The name of the standard "groupOfEntries" object class, formatted in
+ * camelCase.
+ */
+ public static final String OC_GROUP_OF_ENTRIES = "groupOfEntries";
+
+
+
+ /**
+ * The name of the standard "groupOfEntries" object class, formatted in all
+ * lowercase characters.
+ */
+ public static final String OC_GROUP_OF_ENTRIES_LC = "groupofentries";
+
+
+
+ /**
* The name of the standard "groupOfNames" object class, formatted in
* camelCase.
*/
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/GroupManagerTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/GroupManagerTestCase.java
index 01a7716..75630c0 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/GroupManagerTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/GroupManagerTestCase.java
@@ -1002,6 +1002,200 @@
/**
+ * Tests that the server properly handles adding, deleting, and modifying a
+ * static group based on the groupOfEntries object class where that group
+ * contains valid members.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testValidPopulatedGroupOfEntries()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ GroupManager groupManager = DirectoryServer.getGroupManager();
+ groupManager.deregisterAllGroups();
+
+ TestCaseUtils.addEntries(
+ "dn: ou=People,o=test",
+ "objectClass: top",
+ "objectClass: organizationalUnit",
+ "ou: People",
+ "",
+ "dn: ou=Groups,o=test",
+ "objectClass: top",
+ "objectClass: organizationalUnit",
+ "ou: Groups",
+ "",
+ "dn: uid=user.1,ou=People,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: user.1",
+ "givenName: User",
+ "sn: 1",
+ "cn: User 1",
+ "userPassword: password",
+ "",
+ "dn: uid=user.2,ou=People,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: user.2",
+ "givenName: User",
+ "sn: 2",
+ "cn: User 2",
+ "userPassword: password",
+ "",
+ "dn: uid=user.3,ou=People,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: user.3",
+ "givenName: User",
+ "sn: 3",
+ "cn: User 3",
+ "userPassword: password");
+
+
+ // Make sure that there aren't any groups registered with the server.
+ assertFalse(groupManager.getGroupInstances().iterator().hasNext());
+
+
+ // Add a new static group to the server and make sure it gets registered
+ // with the group manager.
+ TestCaseUtils.addEntry(
+ "dn: cn=Test Group of Entries,ou=Groups,o=test",
+ "objectClass: top",
+ "objectClass: groupOfEntries",
+ "cn: Test Group of Entries",
+ "member: uid=user.1,ou=People,o=test",
+ "member: uid=user.2,ou=People,o=test");
+
+
+ // Perform a basic set of validation on the group itself.
+ DN groupDN = DN.decode("cn=Test Group of Entries,ou=Groups,o=test");
+ DN user1DN = DN.decode("uid=user.1,ou=People,o=test");
+ DN user2DN = DN.decode("uid=user.2,ou=People,o=test");
+ DN user3DN = DN.decode("uid=user.3,ou=People,o=test");
+
+ Group groupInstance = groupManager.getGroupInstance(groupDN);
+ assertNotNull(groupInstance);
+ assertEquals(groupInstance.getGroupDN(), groupDN);
+ assertTrue(groupInstance.isMember(user1DN));
+ assertTrue(groupInstance.isMember(user2DN));
+ assertFalse(groupInstance.isMember(user3DN));
+
+ MemberList memberList = groupInstance.getMembers();
+ while (memberList.hasMoreMembers())
+ {
+ DN memberDN = memberList.nextMemberDN();
+ assertTrue(memberDN.equals(user1DN) || memberDN.equals(user2DN));
+ }
+
+ SearchFilter filter = SearchFilter.createFilterFromString("(uid=user.1)");
+ memberList = groupInstance.getMembers(DN.decode("o=test"),
+ SearchScope.WHOLE_SUBTREE, filter);
+ assertTrue(memberList.hasMoreMembers());
+ DN memberDN = memberList.nextMemberDN();
+ assertTrue(memberDN.equals(user1DN));
+ assertFalse(memberList.hasMoreMembers());
+
+ filter = SearchFilter.createFilterFromString("(uid=user.3)");
+ memberList = groupInstance.getMembers(DN.decode("o=test"),
+ SearchScope.WHOLE_SUBTREE, filter);
+ assertFalse(memberList.hasMoreMembers());
+
+
+ // Modify the group and make sure the group manager gets updated
+ // accordingly.
+ LinkedList<Modification> mods = new LinkedList<Modification>();
+ Attribute a2 = new Attribute("member", "uid=user.2,ou=People,o=test");
+ Attribute a3 = new Attribute("member", "uid=user.3,ou=People,o=test");
+ mods.add(new Modification(ModificationType.DELETE, a2));
+ mods.add(new Modification(ModificationType.ADD, a3));
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ ModifyOperation modifyOperation = conn.processModify(groupDN, mods);
+ assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
+
+ groupInstance = groupManager.getGroupInstance(groupDN);
+ assertNotNull(groupInstance);
+ assertEquals(groupInstance.getGroupDN(), groupDN);
+ assertTrue(groupInstance.isMember(user1DN));
+ assertFalse(groupInstance.isMember(user2DN));
+ assertTrue(groupInstance.isMember(user3DN));
+
+
+ // Delete the group and make sure the group manager gets updated
+ // accordingly.
+ DeleteOperation deleteOperation = conn.processDelete(groupDN);
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ assertNull(groupManager.getGroupInstance(groupDN));
+ }
+
+
+
+ /**
+ * Tests that the server properly handles a groupOfEntries object that doesn't
+ * contain any members.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testValidEmptyGroupOfEntries()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ GroupManager groupManager = DirectoryServer.getGroupManager();
+ groupManager.deregisterAllGroups();
+
+ TestCaseUtils.addEntry(
+ "dn: ou=Groups,o=test",
+ "objectClass: top",
+ "objectClass: organizationalUnit",
+ "ou: Groups");
+
+
+ // Make sure that there aren't any groups registered with the server.
+ assertFalse(groupManager.getGroupInstances().iterator().hasNext());
+
+
+ // Add a new static group to the server and make sure it gets registered
+ // with the group manager.
+ TestCaseUtils.addEntry(
+ "dn: cn=Test Group of Entries,ou=Groups,o=test",
+ "objectClass: top",
+ "objectClass: groupOfEntries",
+ "cn: Test Group of Names");
+
+
+ // Make sure that the group exists but doesn't have any members.
+ DN groupDN = DN.decode("cn=Test Group of Entries,ou=Groups,o=test");
+ Group groupInstance = groupManager.getGroupInstance(groupDN);
+ assertNotNull(groupInstance);
+ assertEquals(groupInstance.getGroupDN(), groupDN);
+ assertFalse(groupInstance.getMembers().hasMoreMembers());
+
+
+ // Delete the group and make sure the group manager gets updated
+ // accordingly.
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ DeleteOperation deleteOperation = conn.processDelete(groupDN);
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ assertNull(groupManager.getGroupInstance(groupDN));
+ }
+
+
+
+ /**
* Verifies that the group manager properly handles modify DN operations on
* static group entries.
*
@@ -1170,13 +1364,21 @@
"objectClass: groupOfUniqueNames",
"cn: Group 3",
"uniqueMember: uid=user.1,ou=People,o=test",
- "uniqueMember: uid=user.3,ou=People,o=test");
+ "uniqueMember: uid=user.3,ou=People,o=test",
+ "",
+ "dn: cn=Group 4,ou=Groups,o=test",
+ "objectClass: top",
+ "objectClass: groupOfEntries",
+ "cn: Group 4",
+ "member: uid=user.1,ou=People,o=test",
+ "member: uid=user.2,ou=People,o=test");
// Perform basic validation on the groups.
DN group1DN = DN.decode("cn=Group 1,ou=Groups,o=test");
DN group2DN = DN.decode("cn=Group 2,ou=Groups,o=test");
DN group3DN = DN.decode("cn=Group 3,ou=Groups,o=test");
+ DN group4DN = DN.decode("cn=Group 4,ou=Groups,o=test");
DN user1DN = DN.decode("uid=user.1,ou=People,o=test");
DN user2DN = DN.decode("uid=user.2,ou=People,o=test");
DN user3DN = DN.decode("uid=user.3,ou=People,o=test");
@@ -1184,6 +1386,7 @@
Group group1 = groupManager.getGroupInstance(group1DN);
Group group2 = groupManager.getGroupInstance(group2DN);
Group group3 = groupManager.getGroupInstance(group3DN);
+ Group group4 = groupManager.getGroupInstance(group4DN);
assertNotNull(group1);
assertTrue(group1.isMember(user1DN));
@@ -1200,6 +1403,11 @@
assertFalse(group3.isMember(user2DN));
assertTrue(group3.isMember(user3DN));
+ assertNotNull(group4);
+ assertTrue(group4.isMember(user1DN));
+ assertTrue(group4.isMember(user2DN));
+ assertFalse(group4.isMember(user3DN));
+
// Get a client connection authenticated as user1 and make sure it handles
// group operations correctly.
@@ -1332,6 +1540,10 @@
deleteOperation = conn.processDelete(group3DN);
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
assertNull(groupManager.getGroupInstance(group3DN));
+
+ deleteOperation = conn.processDelete(group4DN);
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ assertNull(groupManager.getGroupInstance(group3DN));
}
--
Gitblit v1.10.0