JBoss Identity SVN: r801 - in idm/trunk: idm-testsuite/src/test/resources and 2 other directories.
by jboss-identity-commits@lists.jboss.org
Author: bdaw
Date: 2009-09-21 10:11:12 -0400 (Mon, 21 Sep 2009)
New Revision: 801
Added:
idm/trunk/idm-testsuite/src/test/resources/opends/config/schema/05-inetUser.ldif
Modified:
idm/trunk/idm-ldap/src/main/java/org/jboss/identity/idm/impl/store/ldap/LDAPIdentityObjectTypeConfiguration.java
idm/trunk/idm-ldap/src/main/java/org/jboss/identity/idm/impl/store/ldap/LDAPIdentityStoreImpl.java
idm/trunk/idm-ldap/src/main/java/org/jboss/identity/idm/impl/store/ldap/SimpleLDAPIdentityObjectTypeConfiguration.java
idm/trunk/idm-testsuite/src/test/resources/ldap/initial-empty-openldapds.ldif
idm/trunk/idm-testsuite/src/test/resources/test-identity-config-msad-local.xml
idm/trunk/idm-testsuite/src/test/resources/test-identity-config-openldapds.xml
Log:
some LDAP test fixes
Modified: idm/trunk/idm-ldap/src/main/java/org/jboss/identity/idm/impl/store/ldap/LDAPIdentityObjectTypeConfiguration.java
===================================================================
--- idm/trunk/idm-ldap/src/main/java/org/jboss/identity/idm/impl/store/ldap/LDAPIdentityObjectTypeConfiguration.java 2009-09-18 22:05:48 UTC (rev 800)
+++ idm/trunk/idm-ldap/src/main/java/org/jboss/identity/idm/impl/store/ldap/LDAPIdentityObjectTypeConfiguration.java 2009-09-21 14:11:12 UTC (rev 801)
@@ -51,6 +51,8 @@
String getParentMembershipAttributeName();
+ String getParentMembershipAttributePlaceholder();
+
boolean isParentMembershipAttributeDN();
boolean isAllowEmptyMemberships();
@@ -63,6 +65,8 @@
boolean isChildMembershipAttributeDN();
+ boolean isChildMembershipAttributeVirtual();
+
boolean isAllowEmptyPassword();
String getEnclosePasswordWith();
Modified: idm/trunk/idm-ldap/src/main/java/org/jboss/identity/idm/impl/store/ldap/LDAPIdentityStoreImpl.java
===================================================================
--- idm/trunk/idm-ldap/src/main/java/org/jboss/identity/idm/impl/store/ldap/LDAPIdentityStoreImpl.java 2009-09-18 22:05:48 UTC (rev 800)
+++ idm/trunk/idm-ldap/src/main/java/org/jboss/identity/idm/impl/store/ldap/LDAPIdentityStoreImpl.java 2009-09-21 14:11:12 UTC (rev 801)
@@ -97,6 +97,8 @@
private final String id;
+ public static final String MEMBERSHIP_TYPE = "JBOSS_IDENTITY_MEMBERSHIP";
+
private FeaturesMetaData supportedFeatures;
LDAPIdentityStoreConfiguration configuration;
@@ -705,12 +707,13 @@
IdentityObjectSearchCriteria criteria) throws IdentityException
{
- //TODO: relationshipType is ignored - maybe check and allow only MEMBERSHIP?
+ if (relationshipType != null && !relationshipType.getName().equals(MEMBERSHIP_TYPE))
+ {
+ throw new IdentityException("This store implementation supports only '" + MEMBERSHIP_TYPE +"' relationship type");
+ }
+ LDAPIdentityObjectImpl ldapIO = getSafeLDAPIO(ctx, identity);
-
- LDAPIdentityObjectImpl ldapFromIO = getSafeLDAPIO(ctx, identity);
-
LDAPIdentityObjectTypeConfiguration typeConfig = getTypeConfiguration(ctx, identity.getIdentityType());
LdapContext ldapContext = getLDAPContext(ctx);
@@ -723,157 +726,121 @@
// If parent simply look for all its members
if (parent)
{
- if (typeConfig.getParentMembershipAttributeName() == null)
+ if (typeConfig.getParentMembershipAttributeName() != null)
{
- throw new IdentityException("Membership attribute name not configured. Given IdentityObjectType cannot have" +
- "members: " + identity.getIdentityType().getName());
- }
- Attributes attrs = ldapContext.getAttributes(ldapFromIO.getDn());
- Attribute member = attrs.get(typeConfig.getParentMembershipAttributeName());
- if (member != null)
- {
- NamingEnumeration memberValues = member.getAll();
- while (memberValues.hasMoreElements())
+ Attributes attrs = ldapContext.getAttributes(ldapIO.getDn());
+ Attribute member = attrs.get(typeConfig.getParentMembershipAttributeName());
+
+ if (member != null)
{
- String memberRef = memberValues.nextElement().toString();
-
- if (typeConfig.isParentMembershipAttributeDN())
+ NamingEnumeration memberValues = member.getAll();
+ while (memberValues.hasMoreElements())
{
- //TODO: use direct LDAP query instaed of other find method and add attributesFilter
+ String memberRef = memberValues.nextElement().toString();
- if (criteria != null && criteria.getFilter() != null)
+ // Ignore placeholder value in memberships
+ String placeholder = typeConfig.getParentMembershipAttributePlaceholder();
+ if (placeholder != null && memberRef.equalsIgnoreCase(placeholder))
{
- String name = Tools.stripDnToName(memberRef);
- String regex = Tools.wildcardToRegex(criteria.getFilter());
+ continue;
+ }
- if (Pattern.matches(regex, name))
+ if (typeConfig.isParentMembershipAttributeDN())
+ {
+ //TODO: use direct LDAP query instead of other find method and add attributesFilter
+
+ if (criteria != null && criteria.getFilter() != null)
{
+ String name = Tools.stripDnToName(memberRef);
+ String regex = Tools.wildcardToRegex(criteria.getFilter());
+
+ if (Pattern.matches(regex, name))
+ {
+ objects.add(findIdentityObject(ctx, memberRef));
+ }
+ }
+ else
+ {
objects.add(findIdentityObject(ctx, memberRef));
}
}
else
{
- objects.add(findIdentityObject(ctx, memberRef));
+ //TODO: if relationships are not refered with DNs and only names its not possible to map
+ //TODO: them to proper IdentityType and keep name uniqnes per type. Workaround needed
+ throw new NotYetImplementedException("LDAP limitation. If relationship targets are not refered with FQDNs " +
+ "and only names, it's not possible to map them to proper IdentityType and keep name uniqnes per type. " +
+ "Workaround needed");
}
+ //break;
}
- else
- {
- //TODO: if relationships are not refered with DNs and only names its not possible to map
- //TODO: them to proper IdentityType and keep name uniqnes per type. Workaround needed
- throw new NotYetImplementedException("LDAP limitation. If relationship targets are not refered with FQDNs " +
- "and only names, it's not possible to map them to proper IdentityType and keep name uniqnes per type. " +
- "Workaround needed");
- }
- //break;
}
}
+ else
+ {
+
+ objects.addAll(findRelatedIdentityObjects(ctx, identity, ldapIO, criteria, false));
+
+ }
+
+
}
-
// if not parent then all parent entries need to be found
else
{
- // Search in all other type contexts
- for (IdentityObjectType parentType : configuration.getConfiguredTypes())
+ if (typeConfig.getChildMembershipAttributeName() == null)
{
- checkIOType(parentType);
+ objects.addAll(findRelatedIdentityObjects(ctx, identity, ldapIO, criteria, true));
+ }
+ else
+ {
+ Attributes attrs = ldapContext.getAttributes(ldapIO.getDn());
+ Attribute member = attrs.get(typeConfig.getChildMembershipAttributeName());
- LDAPIdentityObjectTypeConfiguration parentTypeConfiguration = getTypeConfiguration(ctx, parentType);
-
- List<String> allowedTypes = Arrays.asList(parentTypeConfiguration.getAllowedMembershipTypes());
-
- // Check if given identity type can be parent
- if (!allowedTypes.contains(identity.getIdentityType().getName()))
+ if (member != null)
{
- continue;
- }
+ NamingEnumeration memberValues = member.getAll();
+ while (memberValues.hasMoreElements())
+ {
+ String memberRef = memberValues.nextElement().toString();
- String nameFilter = "*";
+ if (typeConfig.isChildMembershipAttributeDN())
+ {
+ //TODO: use direct LDAP query instead of other find method and add attributesFilter
- //Filter by name
- if (criteria != null && criteria.getFilter() != null)
- {
- nameFilter = criteria.getFilter();
- }
+ if (criteria != null && criteria.getFilter() != null)
+ {
+ String name = Tools.stripDnToName(memberRef);
+ String regex = Tools.wildcardToRegex(criteria.getFilter());
- Control[] requestControls = null;
-
- StringBuilder af = new StringBuilder();
-
- // Filter by attribute values
- if (criteria != null && criteria.isFiltered())
- {
- af.append("(&");
-
- for (Map.Entry<String, String[]> stringEntry : criteria.getValues().entrySet())
- {
- for (String value : stringEntry.getValue())
+ if (Pattern.matches(regex, name))
+ {
+ objects.add(findIdentityObject(ctx, memberRef));
+ }
+ }
+ else
+ {
+ objects.add(findIdentityObject(ctx, memberRef));
+ }
+ }
+ else
{
- af.append("(")
- .append(stringEntry.getKey())
- .append("=")
- .append(value)
- .append(")");
+ //TODO: if relationships are not refered with DNs and only names its not possible to map
+ //TODO: them to proper IdentityType and keep name uniqnes per type. Workaround needed
+ throw new NotYetImplementedException("LDAP limitation. If relationship targets are not refered with FQDNs " +
+ "and only names, it's not possible to map them to proper IdentityType and keep name uniqnes per type. " +
+ "Workaround needed");
}
+ //break;
}
-
- af.append(")");
}
+ }
- // Add filter to search only parents of the given entry
- af.append("(")
- .append(parentTypeConfiguration.getParentMembershipAttributeName())
- .append("=");
- if (parentTypeConfiguration.isParentMembershipAttributeDN())
- {
- af.append(ldapFromIO.getDn());
- }
- else
- {
- //TODO: this doesn't make much sense unless parent/child are same identity types and resides in the same LDAP context
- af.append(ldapFromIO.getName());
- }
- af.append(")");
- String filter = parentTypeConfiguration.getEntrySearchFilter();
- List<SearchResult> sr = null;
- String[] entryCtxs = parentTypeConfiguration.getCtxDNs();
-
- if (filter != null && filter.length() > 0)
- {
-
- Object[] filterArgs = {nameFilter};
- sr = searchIdentityObjects(ctx,
- entryCtxs,
- "(&(" + filter + ")" + af.toString() + ")",
- filterArgs,
- new String[]{parentTypeConfiguration.getIdAttributeName()},
- requestControls);
- }
- else
- {
- filter = "(".concat(parentTypeConfiguration.getIdAttributeName()).concat("=").concat(nameFilter).concat(")");
- sr = searchIdentityObjects(ctx,
- entryCtxs,
- "(&(" + filter + ")" + af.toString() + ")",
- null,
- new String[]{parentTypeConfiguration.getIdAttributeName()},
- requestControls);
- }
-
- for (SearchResult res : sr)
- {
- LdapContext ldapCtx = (LdapContext)res.getObject();
- String dn = ldapCtx.getNameInNamespace();
-
- objects.add(createIdentityObjectInstance(ctx, parentType, res.getAttributes(), dn));
- }
- }
-
-
}
}
@@ -906,6 +873,177 @@
return objects;
}
+ public List<IdentityObject> findRelatedIdentityObjects(IdentityStoreInvocationContext ctx,
+ IdentityObject identity,
+ LDAPIdentityObjectImpl ldapIO,
+ IdentityObjectSearchCriteria criteria,
+ boolean parents)
+ throws IdentityException, NamingException
+ {
+
+ List<IdentityObject> objects = new LinkedList<IdentityObject>();
+
+ LDAPIdentityObjectTypeConfiguration typeConfiguration = getTypeConfiguration(ctx, identity.getIdentityType());
+
+ List<String> allowedTypes = Arrays.asList(typeConfiguration.getAllowedMembershipTypes());
+
+
+ // Search in all other type contexts
+ for (IdentityObjectType checkedIOType : configuration.getConfiguredTypes())
+ {
+ checkIOType(checkedIOType);
+
+ LDAPIdentityObjectTypeConfiguration checkedTypeConfiguration = getTypeConfiguration(ctx, checkedIOType);
+
+ List<String> checkedAllowedTypes = Arrays.asList(checkedTypeConfiguration.getAllowedMembershipTypes());
+
+ if (parents)
+ {
+ // Check if given identity type can be parent
+ if (!checkedAllowedTypes.contains(identity.getIdentityType().getName()))
+ {
+ continue;
+ }
+
+ }
+ else
+ {
+ //Check if given identity type can be child
+ if (!allowedTypes.contains(checkedIOType.getName()))
+ {
+ continue;
+ }
+ }
+
+ // Check if this type is capable to keep needed reference
+ if (parents && checkedTypeConfiguration.getParentMembershipAttributeName() == null)
+ {
+ continue;
+ }
+
+ if (!parents && checkedTypeConfiguration.getChildMembershipAttributeName() == null)
+ {
+ continue;
+ }
+
+ String nameFilter = "*";
+
+ //Filter by name
+ if (criteria != null && criteria.getFilter() != null)
+ {
+ nameFilter = criteria.getFilter();
+ }
+
+ Control[] requestControls = null;
+
+ StringBuilder af = new StringBuilder();
+
+ // Filter by attribute values
+ if (criteria != null && criteria.isFiltered())
+ {
+ af.append("(&");
+
+ for (Map.Entry<String, String[]> stringEntry : criteria.getValues().entrySet())
+ {
+ for (String value : stringEntry.getValue())
+ {
+ af.append("(")
+ .append(stringEntry.getKey())
+ .append("=")
+ .append(value)
+ .append(")");
+ }
+ }
+
+ af.append(")");
+ }
+
+
+ if(parents)
+ {
+ // Add filter to search only parents of the given entry
+ af.append("(")
+ .append(checkedTypeConfiguration.getParentMembershipAttributeName())
+ .append("=");
+ if (checkedTypeConfiguration.isParentMembershipAttributeDN())
+ {
+ af.append(ldapIO.getDn());
+ }
+ else
+ {
+ //TODO: this doesn't make much sense unless parent/child are same identity types and resides in the same LDAP context
+ af.append(ldapIO.getName());
+ }
+ af.append(")");
+ }
+ else
+ {
+ // Add filter to search only childs of the given entry
+ af.append("(")
+ .append(checkedTypeConfiguration.getChildMembershipAttributeName())
+ .append("=");
+ if (checkedTypeConfiguration.isChildMembershipAttributeDN())
+ {
+ af.append(ldapIO.getDn());
+ }
+ else
+ {
+ //TODO: this doesn't make much sense unless parent/child are same identity types and resides in the same LDAP context
+ af.append(ldapIO.getName());
+ }
+ af.append(")");
+ }
+
+
+ String filter = checkedTypeConfiguration.getEntrySearchFilter();
+ List<SearchResult> sr = null;
+
+ String[] entryCtxs = checkedTypeConfiguration.getCtxDNs();
+
+ if (filter != null && filter.length() > 0)
+ {
+
+ Object[] filterArgs = {nameFilter};
+ sr = searchIdentityObjects(ctx,
+ entryCtxs,
+ "(&(" + filter + ")" + af.toString() + ")",
+ filterArgs,
+ new String[]{checkedTypeConfiguration.getIdAttributeName()},
+ requestControls);
+ }
+ else
+ {
+ filter = "(".concat(checkedTypeConfiguration.getIdAttributeName()).concat("=").concat(nameFilter).concat(")");
+ sr = searchIdentityObjects(ctx,
+ entryCtxs,
+ "(&(" + filter + ")" + af.toString() + ")",
+ null,
+ new String[]{checkedTypeConfiguration.getIdAttributeName()},
+ requestControls);
+ }
+
+ for (SearchResult res : sr)
+ {
+ LdapContext ldapCtx = (LdapContext)res.getObject();
+ String dn = ldapCtx.getNameInNamespace();
+
+ if (parents)
+ {
+ // Ignore placeholder value in memberships
+ String placeholder = checkedTypeConfiguration.getParentMembershipAttributePlaceholder();
+ if (placeholder != null && dn.equalsIgnoreCase(placeholder))
+ {
+ continue;
+ }
+ }
+
+ objects.add(createIdentityObjectInstance(ctx, checkedIOType, res.getAttributes(), dn));
+ }
+ }
+
+ return objects;
+ }
+
public Set<IdentityObjectRelationship> resolveRelationships(IdentityStoreInvocationContext ctx,
IdentityObject identity,
IdentityObjectRelationshipType type,
@@ -913,10 +1051,12 @@
boolean named,
String name) throws IdentityException
{
- //TODO: relationshipType is ignored - maybe check and allow only MEMBERSHIP?
+ if (type == null || !type.getName().equals(MEMBERSHIP_TYPE))
+ {
+ throw new IdentityException("This store implementation supports only '" + MEMBERSHIP_TYPE +"' relationship type");
+ }
-
LDAPIdentityObjectImpl ldapIO = getSafeLDAPIO(ctx, identity);
LDAPIdentityObjectTypeConfiguration typeConfig = getTypeConfiguration(ctx, identity.getIdentityType());
@@ -932,115 +1072,95 @@
if (parent)
{
Attributes attrs = ldapContext.getAttributes(ldapIO.getDn());
- Attribute member = attrs.get(typeConfig.getParentMembershipAttributeName());
- if (member != null)
+ if (typeConfig.getParentMembershipAttributeName() != null )
{
- NamingEnumeration memberValues = member.getAll();
- while (memberValues.hasMoreElements())
+ Attribute member = attrs.get(typeConfig.getParentMembershipAttributeName());
+
+
+ if (member != null)
{
- String memberRef = memberValues.nextElement().toString();
-
- if (typeConfig.isParentMembershipAttributeDN())
+ NamingEnumeration memberValues = member.getAll();
+ while (memberValues.hasMoreElements())
{
- //TODO: use direct LDAP query instaed of other find method and add attributesFilter
+ String memberRef = memberValues.nextElement().toString();
+ // Ignore placeholder value in memberships
+ String placeholder = typeConfig.getParentMembershipAttributePlaceholder();
+ if (placeholder != null && memberRef.equalsIgnoreCase(placeholder))
+ {
+ continue;
+ }
- relationships.add(new LDAPIdentityObjectRelationshipImpl(null, ldapIO, findIdentityObject(ctx, memberRef)));
+ if (typeConfig.isParentMembershipAttributeDN())
+ {
+ //TODO: use direct LDAP query instaed of other find method and add attributesFilter
+ relationships.add(new LDAPIdentityObjectRelationshipImpl(MEMBERSHIP_TYPE, ldapIO, findIdentityObject(ctx, memberRef)));
+
+ }
+ else
+ {
+ //TODO: if relationships are not refered with DNs and only names its not possible to map
+ //TODO: them to proper IdentityType and keep name uniqnes per type. Workaround needed
+ throw new NotYetImplementedException("LDAP limitation. If relationship targets are not refered with FQDNs " +
+ "and only names, it's not possible to map them to proper IdentityType and keep name uniqnes per type. " +
+ "Workaround needed");
+ }
+ //break;
}
- else
- {
- //TODO: if relationships are not refered with DNs and only names its not possible to map
- //TODO: them to proper IdentityType and keep name uniqnes per type. Workaround needed
- throw new NotYetImplementedException("LDAP limitation. If relationship targets are not refered with FQDNs " +
- "and only names, it's not possible to map them to proper IdentityType and keep name uniqnes per type. " +
- "Workaround needed");
- }
- //break;
}
}
+ else
+ {
+
+ relationships.addAll(findRelationships(ctx, identity, ldapIO, false));
+ }
+
}
// if not parent then all parent entries need to be found
else
{
- // Search in all other type contexts
- for (IdentityObjectType parentType : configuration.getConfiguredTypes())
+ Attributes attrs = ldapContext.getAttributes(ldapIO.getDn());
+
+ if (typeConfig.getChildMembershipAttributeName() != null)
{
- checkIOType(parentType);
+ Attribute member = attrs.get(typeConfig.getChildMembershipAttributeName());
- LDAPIdentityObjectTypeConfiguration parentTypeConfiguration = getTypeConfiguration(ctx, parentType);
-
- List<String> allowedTypes = Arrays.asList(parentTypeConfiguration.getAllowedMembershipTypes());
-
- // Check if given identity type can be parent
- if (!allowedTypes.contains(identity.getIdentityType().getName()))
+ if (member != null)
{
- continue;
- }
+ NamingEnumeration memberValues = member.getAll();
+ while (memberValues.hasMoreElements())
+ {
+ String memberRef = memberValues.nextElement().toString();
- String nameFilter = "*";
+ // Ignore placeholder value in memberships
- //Filter by name
- Control[] requestControls = null;
+ if (typeConfig.isChildMembershipAttributeDN())
+ {
+ //TODO: use direct LDAP query instaed of other find method and add attributesFilter
- StringBuilder af = new StringBuilder();
+ relationships.add(new LDAPIdentityObjectRelationshipImpl(MEMBERSHIP_TYPE, findIdentityObject(ctx, memberRef), ldapIO));
-
- // Add filter to search only parents of the given entry
- af.append("(")
- .append(parentTypeConfiguration.getParentMembershipAttributeName())
- .append("=");
- if (parentTypeConfiguration.isParentMembershipAttributeDN())
- {
- af.append(ldapIO.getDn());
+ }
+ else
+ {
+ //TODO: if relationships are not refered with DNs and only names its not possible to map
+ //TODO: them to proper IdentityType and keep name uniqnes per type. Workaround needed
+ throw new NotYetImplementedException("LDAP limitation. If relationship targets are not refered with FQDNs " +
+ "and only names, it's not possible to map them to proper IdentityType and keep name uniqnes per type. " +
+ "Workaround needed");
+ }
+ //break;
+ }
}
- else
- {
- //TODO: this doesn't make much sense unless parent/child are same identity types and resides in the same LDAP context
- af.append(ldapIO.getName());
- }
- af.append(")");
-
- String filter = parentTypeConfiguration.getEntrySearchFilter();
- List<SearchResult> sr = null;
-
- String[] entryCtxs = parentTypeConfiguration.getCtxDNs();
-
- if (filter != null && filter.length() > 0)
- {
-
- Object[] filterArgs = {nameFilter};
- sr = searchIdentityObjects(ctx,
- entryCtxs,
- "(&(" + filter + ")" + af.toString() + ")",
- filterArgs,
- new String[]{parentTypeConfiguration.getIdAttributeName()},
- requestControls);
- }
- else
- {
- filter = "(".concat(parentTypeConfiguration.getIdAttributeName()).concat("=").concat(nameFilter).concat(")");
- sr = searchIdentityObjects(ctx,
- entryCtxs,
- "(&(" + filter + ")" + af.toString() + ")",
- null,
- new String[]{parentTypeConfiguration.getIdAttributeName()},
- requestControls);
- }
-
- for (SearchResult res : sr)
- {
- LdapContext ldapCtx = (LdapContext)res.getObject();
- String dn = ldapCtx.getNameInNamespace();
-
- relationships.add(new LDAPIdentityObjectRelationshipImpl(null, createIdentityObjectInstance(ctx, parentType, res.getAttributes(), dn), ldapIO));
- }
}
-
-
+ else
+ {
+ relationships.addAll(findRelationships(ctx, identity, ldapIO, true));
+ }
}
}
@@ -1064,6 +1184,157 @@
return relationships;
}
+ /**
+ * Search all configured LDAP contexts for possible Identity Object Types and lookup for parent/child references
+ * to form relationships
+ *
+ * @param ctx
+ * @param identity
+ * @param ldapIO
+ * @param parents if true will lookup parents to reference child, if false will look children to reference parent
+ * @return
+ * @throws IdentityException
+ * @throws NamingException
+ */
+ private Collection<LDAPIdentityObjectRelationshipImpl> findRelationships(IdentityStoreInvocationContext ctx,
+ IdentityObject identity,
+ LDAPIdentityObjectImpl ldapIO,
+ boolean parents)
+ throws IdentityException, NamingException
+ {
+
+ Set<LDAPIdentityObjectRelationshipImpl> relationships = new HashSet<LDAPIdentityObjectRelationshipImpl>();
+
+ LDAPIdentityObjectTypeConfiguration typeConfiguration = getTypeConfiguration(ctx, identity.getIdentityType());
+
+ List<String> allowedTypes = Arrays.asList(typeConfiguration.getAllowedMembershipTypes());
+//
+ // Search in all other type contexts
+ for (IdentityObjectType checkedIOType : configuration.getConfiguredTypes())
+ {
+ checkIOType(checkedIOType);
+
+ LDAPIdentityObjectTypeConfiguration checkedTypeConfiguration = getTypeConfiguration(ctx, checkedIOType);
+
+ List<String> checkedAllowedTypes = Arrays.asList(checkedTypeConfiguration.getAllowedMembershipTypes());
+
+ if (parents)
+ {
+ // Check if given identity type can be parent
+ if (!checkedAllowedTypes.contains(identity.getIdentityType().getName()))
+ {
+ continue;
+ }
+
+ }
+ else
+ {
+ //Check if given identity type can be child
+ if (!allowedTypes.contains(checkedIOType.getName()))
+ {
+ continue;
+ }
+ }
+
+ String nameFilter = "*";
+
+ //Filter by name
+ Control[] requestControls = null;
+
+ StringBuilder af = new StringBuilder();
+
+
+ if(parents)
+ {
+ // Add filter to search only parents of the given entry
+ af.append("(")
+ .append(checkedTypeConfiguration.getParentMembershipAttributeName())
+ .append("=");
+ if (checkedTypeConfiguration.isParentMembershipAttributeDN())
+ {
+ af.append(ldapIO.getDn());
+ }
+ else
+ {
+ //TODO: this doesn't make much sense unless parent/child are same identity types and resides in the same LDAP context
+ af.append(ldapIO.getName());
+ }
+ af.append(")");
+ }
+ else
+ {
+ // Add filter to search only childs of the given entry
+ af.append("(")
+ .append(checkedTypeConfiguration.getChildMembershipAttributeName())
+ .append("=");
+ if (checkedTypeConfiguration.isChildMembershipAttributeDN())
+ {
+ af.append(ldapIO.getDn());
+ }
+ else
+ {
+ //TODO: this doesn't make much sense unless parent/child are same identity types and resides in the same LDAP context
+ af.append(ldapIO.getName());
+ }
+ af.append(")");
+ }
+
+ String filter = checkedTypeConfiguration.getEntrySearchFilter();
+ List<SearchResult> sr = null;
+
+ String[] entryCtxs = checkedTypeConfiguration.getCtxDNs();
+
+ if (filter != null && filter.length() > 0)
+ {
+
+ Object[] filterArgs = {nameFilter};
+ sr = searchIdentityObjects(ctx,
+ entryCtxs,
+ "(&(" + filter + ")" + af.toString() + ")",
+ filterArgs,
+ new String[]{checkedTypeConfiguration.getIdAttributeName()},
+ requestControls);
+ }
+ else
+ {
+ filter = "(".concat(checkedTypeConfiguration.getIdAttributeName()).concat("=").concat(nameFilter).concat(")");
+ sr = searchIdentityObjects(ctx,
+ entryCtxs,
+ "(&(" + filter + ")" + af.toString() + ")",
+ null,
+ new String[]{checkedTypeConfiguration.getIdAttributeName()},
+ requestControls);
+ }
+
+ for (SearchResult res : sr)
+ {
+ LdapContext ldapCtx = (LdapContext)res.getObject();
+ String dn = ldapCtx.getNameInNamespace();
+
+
+
+ if (parents)
+ {
+ // Ignore placeholder values
+ String placeholder = checkedTypeConfiguration.getParentMembershipAttributePlaceholder();
+ if (placeholder != null && dn.equalsIgnoreCase(placeholder))
+ {
+ continue;
+ }
+
+
+ relationships.add(new LDAPIdentityObjectRelationshipImpl(MEMBERSHIP_TYPE, createIdentityObjectInstance(ctx, checkedIOType, res.getAttributes(), dn), ldapIO));
+ }
+ else
+ {
+ relationships.add(new LDAPIdentityObjectRelationshipImpl(MEMBERSHIP_TYPE, ldapIO, createIdentityObjectInstance(ctx, checkedIOType, res.getAttributes(), dn)));
+ }
+ }
+ }
+
+ return relationships;
+ }
+
public Collection<IdentityObject> findIdentityObject(IdentityStoreInvocationContext ctx,
IdentityObject identity,
IdentityObjectRelationshipType relationshipType,
@@ -1088,6 +1359,11 @@
);
}
+ if (relationshipType == null || !relationshipType.getName().equals(MEMBERSHIP_TYPE))
+ {
+ throw new IdentityException("This store implementation supports only '" + MEMBERSHIP_TYPE +"' relationship type");
+ }
+
LDAPIdentityObjectRelationshipImpl relationship = null;
LDAPIdentityObjectImpl ldapFromIO = getSafeLDAPIO(ctx, fromIdentity);
@@ -1095,6 +1371,7 @@
LDAPIdentityObjectImpl ldapToIO = getSafeLDAPIO(ctx, toIdentity);
LDAPIdentityObjectTypeConfiguration fromTypeConfig = getTypeConfiguration(ctx, fromIdentity.getIdentityType());
+ LDAPIdentityObjectTypeConfiguration toTypeConfig = getTypeConfiguration(ctx, toIdentity.getIdentityType());
LdapContext ldapContext = getLDAPContext(ctx);
@@ -1110,21 +1387,44 @@
// Construct new member attribute values
Attributes attrs = new BasicAttributes(true);
- Attribute member = new BasicAttribute(fromTypeConfig.getParentMembershipAttributeName());
+ if (fromTypeConfig.getParentMembershipAttributeName() != null)
+ {
- if (fromTypeConfig.isParentMembershipAttributeDN())
- {
- member.add(ldapToIO.getDn());
+ Attribute member = new BasicAttribute(fromTypeConfig.getParentMembershipAttributeName());
+
+ if (fromTypeConfig.isParentMembershipAttributeDN())
+ {
+ member.add(ldapToIO.getDn());
+ }
+ else
+ {
+ member.add(toIdentity.getName());
+ }
+
+ attrs.put(member);
+
+ ldapContext.modifyAttributes(ldapFromIO.getDn(), DirContext.ADD_ATTRIBUTE, attrs);
}
- else
+
+ if (toTypeConfig.getChildMembershipAttributeName() != null && !toTypeConfig.isChildMembershipAttributeVirtual())
{
- member.add(toIdentity.getName());
- }
- attrs.put(member);
+ Attribute member = new BasicAttribute(toTypeConfig.getChildMembershipAttributeName());
- ldapContext.modifyAttributes(ldapFromIO.getDn(), DirContext.ADD_ATTRIBUTE, attrs);
+ if (toTypeConfig.isChildMembershipAttributeDN())
+ {
+ member.add(ldapFromIO.getDn());
+ }
+ else
+ {
+ member.add(fromIdentity.getName());
+ }
+ attrs.put(member);
+
+ ldapContext.modifyAttributes(ldapToIO.getDn(), DirContext.ADD_ATTRIBUTE, attrs);
+ }
+
relationship = new LDAPIdentityObjectRelationshipImpl(name, ldapFromIO, ldapToIO);
}
@@ -1165,6 +1465,7 @@
LDAPIdentityObjectImpl ldapToIO = getSafeLDAPIO(ctx, toIdentity);
LDAPIdentityObjectTypeConfiguration fromTypeConfig = getTypeConfiguration(ctx, fromIdentity.getIdentityType());
+ LDAPIdentityObjectTypeConfiguration toTypeConfig = getTypeConfiguration(ctx, toIdentity.getIdentityType());
// If relationship is not allowed simply return
//TODO: use features description instead
@@ -1189,21 +1490,43 @@
//construct new member attribute values
Attributes attrs = new BasicAttributes(true);
- Attribute member = new BasicAttribute(fromTypeConfig.getParentMembershipAttributeName());
+ if (fromTypeConfig.getParentMembershipAttributeName() != null)
+ {
- if (fromTypeConfig.isParentMembershipAttributeDN())
- {
- member.add(ldapToIO.getDn());
+ Attribute member = new BasicAttribute(fromTypeConfig.getParentMembershipAttributeName());
+
+ if (fromTypeConfig.isParentMembershipAttributeDN())
+ {
+ member.add(ldapToIO.getDn());
+ }
+ else
+ {
+ member.add(toIdentity.getName());
+ }
+
+ attrs.put(member);
+
+ ldapContext.modifyAttributes(ldapFromIO.getDn(), DirContext.REMOVE_ATTRIBUTE, attrs);
}
- else
+
+ if (toTypeConfig.getChildMembershipAttributeName() != null && !toTypeConfig.isChildMembershipAttributeVirtual())
{
- member.add(toIdentity.getName());
- }
+ Attribute member = new BasicAttribute(toTypeConfig.getChildMembershipAttributeName());
- attrs.put(member);
+ if (toTypeConfig.isChildMembershipAttributeDN())
+ {
+ member.add(ldapFromIO.getDn());
+ }
+ else
+ {
+ member.add(fromIdentity.getName());
+ }
- ldapContext.modifyAttributes(ldapFromIO.getDn(), DirContext.REMOVE_ATTRIBUTE, attrs);
+ attrs.put(member);
+ ldapContext.modifyAttributes(ldapToIO.getDn(), DirContext.REMOVE_ATTRIBUTE, attrs);
+ }
+
}
catch (NamingException e)
{
@@ -1232,13 +1555,17 @@
);
}
+
// as relationship type is ignored in this impl for now...
removeRelationship(ctx, identity1, identity2, null, null);
removeRelationship(ctx, identity2, identity1, null, null);
}
- public Set<IdentityObjectRelationship> resolveRelationships(IdentityStoreInvocationContext ctx, IdentityObject fromIdentity, IdentityObject toIdentity, IdentityObjectRelationshipType relationshipType) throws IdentityException
+ public Set<IdentityObjectRelationship> resolveRelationships(IdentityStoreInvocationContext ctx,
+ IdentityObject fromIdentity,
+ IdentityObject toIdentity,
+ IdentityObjectRelationshipType relationshipType) throws IdentityException
{
// relationshipType is ignored for now
@@ -1251,12 +1578,20 @@
);
}
+ if (relationshipType != null && !relationshipType.getName().equals(MEMBERSHIP_TYPE))
+ {
+ throw new IdentityException("This store implementation supports only '" + MEMBERSHIP_TYPE +"' relationship type");
+ }
+
Set<IdentityObjectRelationship> relationships = new HashSet<IdentityObjectRelationship>();
+
+
LDAPIdentityObjectImpl ldapFromIO = getSafeLDAPIO(ctx, fromIdentity);
LDAPIdentityObjectImpl ldapToIO = getSafeLDAPIO(ctx, toIdentity);
LDAPIdentityObjectTypeConfiguration fromTypeConfig = getTypeConfiguration(ctx, fromIdentity.getIdentityType());
+ LDAPIdentityObjectTypeConfiguration toTypeConfig = getTypeConfiguration(ctx, toIdentity.getIdentityType());
// If relationship is not allowed return empty set
//TODO: use features description instead
@@ -1271,24 +1606,49 @@
try
{
Attributes attrs = ldapContext.getAttributes(ldapFromIO.getDn());
- Attribute member = attrs.get(fromTypeConfig.getParentMembershipAttributeName());
- if (member != null)
+ if (fromTypeConfig.getParentMembershipAttributeName() != null)
{
- NamingEnumeration memberValues = member.getAll();
- while (memberValues.hasMoreElements())
+ Attribute member = attrs.get(fromTypeConfig.getParentMembershipAttributeName());
+
+ if (member != null)
{
- String memberRef = memberValues.nextElement().toString();
+ NamingEnumeration memberValues = member.getAll();
+ while (memberValues.hasMoreElements())
+ {
+ String memberRef = memberValues.nextElement().toString();
- if ((fromTypeConfig.isParentMembershipAttributeDN() && memberRef.equals(ldapToIO.getDn())) ||
- (!fromTypeConfig.isParentMembershipAttributeDN() && memberRef.equals(ldapToIO.getName())))
+ if ((fromTypeConfig.isParentMembershipAttributeDN() && memberRef.equals(ldapToIO.getDn())) ||
+ (!fromTypeConfig.isParentMembershipAttributeDN() && memberRef.equals(ldapToIO.getName())))
+ {
+ //TODO: impl lacks support for rel type
+ relationships.add(new LDAPIdentityObjectRelationshipImpl(MEMBERSHIP_TYPE, ldapFromIO, ldapToIO));
+ }
+ }
+ }
+ }
+ else if (toTypeConfig.getChildMembershipAttributeName() != null)
+ {
+ Attribute member = attrs.get(toTypeConfig.getChildMembershipAttributeName());
+
+ if (member != null)
+ {
+ NamingEnumeration memberValues = member.getAll();
+ while (memberValues.hasMoreElements())
{
- //TODO: impl lacks support for rel type
- relationships.add(new LDAPIdentityObjectRelationshipImpl(null, ldapFromIO, ldapToIO));
+ String memberRef = memberValues.nextElement().toString();
+
+ if ((fromTypeConfig.isChildMembershipAttributeDN() && memberRef.equals(ldapFromIO.getDn())) ||
+ (!fromTypeConfig.isChildMembershipAttributeDN() && memberRef.equals(ldapFromIO.getName())))
+ {
+ //TODO: impl lacks support for rel type
+ relationships.add(new LDAPIdentityObjectRelationshipImpl(MEMBERSHIP_TYPE, ldapFromIO, ldapToIO));
+ }
}
}
}
+
}
catch (NamingException e)
{
Modified: idm/trunk/idm-ldap/src/main/java/org/jboss/identity/idm/impl/store/ldap/SimpleLDAPIdentityObjectTypeConfiguration.java
===================================================================
--- idm/trunk/idm-ldap/src/main/java/org/jboss/identity/idm/impl/store/ldap/SimpleLDAPIdentityObjectTypeConfiguration.java 2009-09-18 22:05:48 UTC (rev 800)
+++ idm/trunk/idm-ldap/src/main/java/org/jboss/identity/idm/impl/store/ldap/SimpleLDAPIdentityObjectTypeConfiguration.java 2009-09-21 14:11:12 UTC (rev 801)
@@ -57,6 +57,8 @@
private final String parentMembershipAttributeName;
+ private final String parentMembershipAttributePlaceholder;
+
private final boolean isParentMembershipAttributeDN;
private final boolean allowEmptyMemberships;
@@ -67,6 +69,8 @@
private final boolean isChildMembershipAttributeDN;
+ private final boolean isChildMembershipAttributeVirtual;
+
private final boolean allowEmptyPassword;
private final String enclosePasswordWith;
@@ -94,6 +98,8 @@
public static final String PARENT_MEMBERSHIP_ATTRIBUTE_NAME = "parentMembershipAttributeName";
+ public static final String PARENT_MEMBERSHIP_ATTRIBUTE_PLACEHOLDER = "parentMembershipAttributePlaceholder";
+
public static final String IS_PARENT_MEMBERSHIP_ATTRIBUTE_DN = "isParentMembershipAttributeDN";
public static final String ALLOW_EMPTY_MEMBERSHIPS = "isAllowEmptyMemberships";
@@ -104,6 +110,8 @@
public static final String CHILD_MEMBERSHIP_ATTRIBUTE_DN = "childMembershipAttributeDN";
+ public static final String CHILD_MEMBERSHIP_ATTRIBUTE_VIRTUAL = "childMembershipAttributeVirtual";
+
public static final String ALLOW_EMPTY_PASSWORD = "allowEmptyPassword";
public static final String ENCLOSE_PASSWORD_WITH = "enclosePasswordWith";
@@ -122,6 +130,7 @@
this.entrySearchFilter = objectTypeMD.getOptionSingleValue(ENTRY_SEARCH_FILTER);
this.entrySearchScope = objectTypeMD.getOptionSingleValue(ENTRY_SEARCH_SCOPE);
this.parentMembershipAttributeName = objectTypeMD.getOptionSingleValue(PARENT_MEMBERSHIP_ATTRIBUTE_NAME);
+ this.parentMembershipAttributePlaceholder = objectTypeMD.getOptionSingleValue(PARENT_MEMBERSHIP_ATTRIBUTE_PLACEHOLDER);
this.childMembershipAttributeName = objectTypeMD.getOptionSingleValue(CHILD_MEMBERSHIP_ATTRIBUTE_NAME);
this.enclosePasswordWith = objectTypeMD.getOptionSingleValue(ENCLOSE_PASSWORD_WITH);
this.passwordEncoding = objectTypeMD.getOptionSingleValue(PASSWORD_ENCODIGN);
@@ -167,6 +176,16 @@
this.isChildMembershipAttributeDN = false;
}
+ String isChildMembershipAttributeVirtual = objectTypeMD.getOptionSingleValue(CHILD_MEMBERSHIP_ATTRIBUTE_DN);
+ if (isChildMembershipAttributeVirtual != null && isChildMembershipAttributeVirtual.equalsIgnoreCase("false"))
+ {
+ this.isChildMembershipAttributeVirtual = false;
+ }
+ else
+ {
+ this.isChildMembershipAttributeVirtual = true;
+ }
+
String allowEmptyPassword = objectTypeMD.getOptionSingleValue(ALLOW_EMPTY_PASSWORD);
if (allowEmptyPassword != null && allowEmptyPassword.equalsIgnoreCase("true"))
{
@@ -349,6 +368,11 @@
return parentMembershipAttributeName;
}
+ public String getParentMembershipAttributePlaceholder()
+ {
+ return parentMembershipAttributePlaceholder;
+ }
+
public boolean isParentMembershipAttributeDN()
{
return isParentMembershipAttributeDN;
@@ -395,6 +419,11 @@
return isChildMembershipAttributeDN;
}
+ public boolean isChildMembershipAttributeVirtual()
+ {
+ return isChildMembershipAttributeVirtual;
+ }
+
public boolean isAllowEmptyPassword()
{
return allowEmptyPassword;
Modified: idm/trunk/idm-testsuite/src/test/resources/ldap/initial-empty-openldapds.ldif
===================================================================
--- idm/trunk/idm-testsuite/src/test/resources/ldap/initial-empty-openldapds.ldif 2009-09-18 22:05:48 UTC (rev 800)
+++ idm/trunk/idm-testsuite/src/test/resources/ldap/initial-empty-openldapds.ldif 2009-09-21 14:11:12 UTC (rev 801)
@@ -18,6 +18,11 @@
objectclass: organization
o: test
+dn: ou=placeholder,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com
+objectclass: top
+objectclass: organizationalUnit
+ou: placeholder
+
dn: ou=People,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com
objectclass: top
objectclass: organizationalUnit
Added: idm/trunk/idm-testsuite/src/test/resources/opends/config/schema/05-inetUser.ldif
===================================================================
--- idm/trunk/idm-testsuite/src/test/resources/opends/config/schema/05-inetUser.ldif (rev 0)
+++ idm/trunk/idm-testsuite/src/test/resources/opends/config/schema/05-inetUser.ldif 2009-09-21 14:11:12 UTC (rev 801)
@@ -0,0 +1,21 @@
+# Some schema parts that were missing in standard set
+#
+#
+#
+dn: cn=schema
+objectClass: top
+objectClass: ldapSubentry
+objectClass: subschema
+attributeTypes: ( 2.16.840.1.113730.3.1.692 NAME 'inetUserStatus'
+ DESC '"active", "inactive", or "deleted" status of a user' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ SINGLE-VALUE X-ORIGIN 'Nortel subscriber interoperability' )
+attributeTypes: ( 2.16.840.1.113730.3.1.693 NAME 'inetUserHttpURL'
+ DESC 'A users Web addresses' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ X-ORIGIN 'Nortel subscriber interoperability' )
+attributeTypes: ( 1.2.840.113556.1.2.102 NAME 'memberOf'
+ DESC 'Group that theentry belongs to' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ X-ORIGIN 'iPlanet Delegated Administrator' )
+objectClasses: ( 2.16.840.1.113730.3.2.130 NAME 'inetUser'
+ DESC 'Auxiliary class which must be present in an entry for delivery of subscriber services'
+ SUP top AUXILIARY MAY ( uid $ inetUserStatus $ inetUserHttpURL $ userPassword $ memberOf )
+ X-ORIGIN 'Nortel subscriber interoperability' )
Modified: idm/trunk/idm-testsuite/src/test/resources/test-identity-config-msad-local.xml
===================================================================
--- idm/trunk/idm-testsuite/src/test/resources/test-identity-config-msad-local.xml 2009-09-18 22:05:48 UTC (rev 800)
+++ idm/trunk/idm-testsuite/src/test/resources/test-identity-config-msad-local.xml 2009-09-21 14:11:12 UTC (rev 801)
@@ -910,7 +910,7 @@
</option>
<option>
<name>adminPassword</name>
- <value>!Q2w3e4r</value>
+ <value>1q@W3e4r</value>
</option>
<option>
<name>authenticationMethod</name>
Modified: idm/trunk/idm-testsuite/src/test/resources/test-identity-config-openldapds.xml
===================================================================
--- idm/trunk/idm-testsuite/src/test/resources/test-identity-config-openldapds.xml 2009-09-18 22:05:48 UTC (rev 800)
+++ idm/trunk/idm-testsuite/src/test/resources/test-identity-config-openldapds.xml 2009-09-21 14:11:12 UTC (rev 801)
@@ -621,6 +621,10 @@
<value>member</value>
</option>
<option>
+ <name>parentMembershipAttributePlaceholder</name>
+ <value>ou=placeholder,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com</value>
+ </option>
+ <option>
<name>isParentMembershipAttributeDN</name>
<value>true</value>
</option>
@@ -632,6 +636,7 @@
<name>createEntryAttributeValues</name>
<value>objectClass=top</value>
<value>objectClass=groupOfNames</value>
+ <value>member=ou=placeholder,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com</value>
</option>
</options>
</identity-object-type>
@@ -683,6 +688,10 @@
<value>true</value>
</option>
<option>
+ <name>parentMembershipAttributePlaceholder</name>
+ <value>ou=placeholder,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com</value>
+ </option>
+ <option>
<name>allowEmptyMemberships</name>
<value>true</value>
</option>
@@ -690,6 +699,7 @@
<name>createEntryAttributeValues</name>
<value>objectClass=top</value>
<value>objectClass=groupOfNames</value>
+ <value>member=ou=placeholder,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com</value>
</option>
</options>
</identity-object-type>
@@ -733,6 +743,10 @@
<value>member</value>
</option>
<option>
+ <name>parentMembershipAttributePlaceholder</name>
+ <value>ou=placeholder,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com</value>
+ </option>
+ <option>
<name>isParentMembershipAttributeDN</name>
<value>true</value>
</option>
@@ -744,6 +758,7 @@
<name>createEntryAttributeValues</name>
<value>objectClass=top</value>
<value>objectClass=groupOfNames</value>
+ <value>member=ou=placeholder,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com</value>
</option>
</options>
</identity-object-type>
@@ -779,6 +794,10 @@
<value>member</value>
</option>
<option>
+ <name>parentMembershipAttributePlaceholder</name>
+ <value>ou=placeholder,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com</value>
+ </option>
+ <option>
<name>isParentMembershipAttributeDN</name>
<value>true</value>
</option>
@@ -790,6 +809,7 @@
<name>createEntryAttributeValues</name>
<value>objectClass=top</value>
<value>objectClass=groupOfNames</value>
+ <value>member=ou=placeholder,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com</value>
</option>
</options>
</identity-object-type>
@@ -825,6 +845,10 @@
<value>member</value>
</option>
<option>
+ <name>parentMembershipAttributePlaceholder</name>
+ <value>ou=placeholder,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com</value>
+ </option>
+ <option>
<name>isParentMembershipAttributeDN</name>
<value>true</value>
</option>
@@ -836,6 +860,7 @@
<name>createEntryAttributeValues</name>
<value>objectClass=top</value>
<value>objectClass=groupOfNames</value>
+ <value>member=ou=placeholder,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com</value>
</option>
</options>
</identity-object-type>
@@ -871,6 +896,10 @@
<value>member</value>
</option>
<option>
+ <name>parentMembershipAttributePlaceholder</name>
+ <value>ou=placeholder,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com</value>
+ </option>
+ <option>
<name>isParentMembershipAttributeDN</name>
<value>true</value>
</option>
@@ -882,6 +911,7 @@
<name>createEntryAttributeValues</name>
<value>objectClass=top</value>
<value>objectClass=groupOfNames</value>
+ <value>member=ou=placeholder,o=test,o=trunk,o=idm,o=jbid,dc=my-domain,dc=com</value>
</option>
</options>
</identity-object-type>