Merged V3.2 to HEAD

18157: ETHREEOH-3787: Support portal URL rewriting within surf webscripts
      - WebScriptServletResponse extended to use portlet helper to rewrite URLs when running in context of a portlet. (We can't use WebScriptPortletRequest / Response because we need the full servlet runtime for Surf.)
      - CMIS test webscripts corrected to be portlet enabled
   18272: Merged DEV/BELARUS/V3.2-2010_01_11 to V3.2
      18257: ETHREEOH-4002: User/Group sync does not handle LDAP communication failures
         - Merged with corrections
   18276: ETHREEOH-4002: Correction to previous checkin - modification dates are only persisted after successful processing of users and groups, so need to delete them on comms failure
   18326: ETHREEOH-3873: usr:authorityContainer type metadata must be left in place for upgraded repositories
      - Otherwise you get errors when re-indexing the migrated group nodes
   18340: ETHREEOH-4069: LDAP sync cannot resolve DNs containing a slash character
      - Due to JNDI interpreting the slash character as a separator
   18403: ETHREEOH-4008: LDAP sync should preserve case of group members
      - Was incorrectly extracting attributes from lower-cased DN


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18433 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2010-02-03 12:59:34 +00:00
parent 089c5932ee
commit cdb8e6ef43
2 changed files with 66 additions and 11 deletions

View File

@@ -2,8 +2,8 @@
<description>Alfresco User Model</description> <description>Alfresco User Model</description>
<author>Alfresco</author> <author>Alfresco</author>
<published>2009-06-04</published> <published>2010-01-27</published>
<version>0.2</version> <version>0.3</version>
<imports> <imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/> <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
@@ -74,6 +74,41 @@
</properties> </properties>
</type> </type>
<!-- Note this type is not used and was replaced by cm:authorityContainer -->
<!-- Retained here because old authority containers are left in place in upgraded repositories (after migration) -->
<type name="usr:authorityContainer">
<title>Deprecated Alfresco Authority Type - NOT USED</title>
<parent>usr:authority</parent>
<properties>
<!-- The tokenisation set here is ignored - it is fixed for this type -->
<!-- This is so you can not break group lookup -->
<property name="usr:authorityName">
<type>d:text</type>
</property>
<property name="usr:members">
<type>d:text</type>
<multiple>true</multiple>
</property>
<property name="usr:authorityDisplayName">
<type>d:text</type>
</property>
</properties>
<associations>
<child-association name="usr:member">
<source>
<mandatory>false</mandatory>
<many>true</many>
</source>
<target>
<class>usr:authority</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
<duplicate>false</duplicate>
</child-association>
</associations>
</type>
</types> </types>

View File

@@ -41,7 +41,9 @@ import java.util.TreeMap;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.naming.CompositeName;
import javax.naming.InvalidNameException; import javax.naming.InvalidNameException;
import javax.naming.Name;
import javax.naming.NamingEnumeration; import javax.naming.NamingEnumeration;
import javax.naming.NamingException; import javax.naming.NamingException;
import javax.naming.directory.Attribute; import javax.naming.directory.Attribute;
@@ -684,13 +686,14 @@ public class LDAPUserRegistry implements UserRegistry, LDAPNameResolver, Initial
{ {
// Attempt to parse the member attribute as a DN. If this fails we have a fallback // Attempt to parse the member attribute as a DN. If this fails we have a fallback
// in the catch block // in the catch block
LdapName distinguishedName = new LdapName(attribute.toLowerCase()); LdapName distinguishedNameForComparison = new LdapName(attribute.toLowerCase());
Attribute nameAttribute; Attribute nameAttribute;
// If the user and group search bases are different we may be able to recognize user // If the user and group search bases are different we may be able to recognize user
// and group DNs without a secondary lookup // and group DNs without a secondary lookup
if (disjoint) if (disjoint)
{ {
LdapName distinguishedName = new LdapName(attribute);
Attributes nameAttributes = distinguishedName.getRdn(distinguishedName.size() - 1) Attributes nameAttributes = distinguishedName.getRdn(distinguishedName.size() - 1)
.toAttributes(); .toAttributes();
@@ -714,12 +717,12 @@ public class LDAPUserRegistry implements UserRegistry, LDAPNameResolver, Initial
} }
// If we can't determine the name and type from the DN alone, try a directory lookup // If we can't determine the name and type from the DN alone, try a directory lookup
if (distinguishedName.startsWith(userDistinguishedNamePrefix) if (distinguishedNameForComparison.startsWith(userDistinguishedNamePrefix)
|| distinguishedName.startsWith(groupDistinguishedNamePrefix)) || distinguishedNameForComparison.startsWith(groupDistinguishedNamePrefix))
{ {
try try
{ {
Attributes childAttributes = this.ctx.getAttributes(attribute, new String[] Attributes childAttributes = this.ctx.getAttributes(jndiName(attribute), new String[]
{ {
"objectclass", LDAPUserRegistry.this.groupIdAttributeName, "objectclass", LDAPUserRegistry.this.groupIdAttributeName,
LDAPUserRegistry.this.userIdAttributeName LDAPUserRegistry.this.userIdAttributeName
@@ -805,7 +808,7 @@ public class LDAPUserRegistry implements UserRegistry, LDAPNameResolver, Initial
// fetch the next batch // fetch the next batch
if (nextStart > 0 && !PATTERN_RANGE_END.matcher(memAttribute.getID().toLowerCase()).find()) if (nextStart > 0 && !PATTERN_RANGE_END.matcher(memAttribute.getID().toLowerCase()).find())
{ {
Attributes childAttributes = this.ctx.getAttributes(result.getNameInNamespace(), new String[] Attributes childAttributes = this.ctx.getAttributes(jndiName(result.getNameInNamespace()), new String[]
{ {
LDAPUserRegistry.this.memberAttributeName + ";range=" + nextStart + '-' LDAPUserRegistry.this.memberAttributeName + ";range=" + nextStart + '-'
+ (nextStart + LDAPUserRegistry.this.attributeBatchSize - 1) + (nextStart + LDAPUserRegistry.this.attributeBatchSize - 1)
@@ -835,6 +838,23 @@ public class LDAPUserRegistry implements UserRegistry, LDAPNameResolver, Initial
return lookup.values(); return lookup.values();
} }
/**
* Converts a given DN into one suitable for use through JNDI. In particular, escapes special characters such as '/'
* which have special meaning to JNDI.
*
* @param dn
* the dn
* @return the name
* @throws InvalidNameException
* the invalid name exception
*/
private static Name jndiName(String dn) throws InvalidNameException
{
Name n = new CompositeName();
n.add(dn);
return n;
}
/** /**
* Invokes the given callback on each entry returned by the given query. * Invokes the given callback on each entry returned by the given query.
* *
@@ -862,7 +882,7 @@ public class LDAPUserRegistry implements UserRegistry, LDAPNameResolver, Initial
NamingEnumeration<SearchResult> searchResults; NamingEnumeration<SearchResult> searchResults;
searchResults = ctx.search(searchBase, query, searchControls); searchResults = ctx.search(searchBase, query, searchControls);
while (searchResults.hasMoreElements()) while (searchResults.hasMore())
{ {
SearchResult result = searchResults.next(); SearchResult result = searchResults.next();
callback.process(result); callback.process(result);
@@ -919,9 +939,9 @@ public class LDAPUserRegistry implements UserRegistry, LDAPNameResolver, Initial
NamingEnumeration<SearchResult> searchResults = ctx.search(this.userSearchBase, "(&" + this.personQuery NamingEnumeration<SearchResult> searchResults = ctx.search(this.userSearchBase, "(&" + this.personQuery
+ "(" + this.userIdAttributeName + "=" + userId + "))", userSearchCtls); + "(" + this.userIdAttributeName + "=" + userId + "))", userSearchCtls);
if (searchResults.hasMoreElements()) if (searchResults.hasMore())
{ {
return searchResults.next().getNameInNamespace(); return jndiName(searchResults.next().getNameInNamespace()).toString();
} }
throw new AuthenticationException("Failed to resolve user: " + userId); throw new AuthenticationException("Failed to resolve user: " + userId);
} }
@@ -1200,7 +1220,7 @@ public class LDAPUserRegistry implements UserRegistry, LDAPNameResolver, Initial
do do
{ {
readyForNextPage = this.searchResults == null; readyForNextPage = this.searchResults == null;
while (!readyForNextPage && this.searchResults.hasMoreElements()) while (!readyForNextPage && this.searchResults.hasMore())
{ {
SearchResult result = this.searchResults.next(); SearchResult result = this.searchResults.next();
Attributes attributes = result.getAttributes(); Attributes attributes = result.getAttributes();