use of org.alfresco.repo.security.sync.NodeDescription in project alfresco-repository by Alfresco.
the class LDAPUserRegistry method getGroups.
/*
* (non-Javadoc)
* @see org.alfresco.repo.security.sync.UserRegistry#getGroups(java.util.Date)
*/
public Collection<NodeDescription> getGroups(Date modifiedSince) {
// Work out whether the user and group trees are disjoint. This may allow us to optimize reverse DN
// resolution.
final LdapName groupDistinguishedNamePrefix;
try {
groupDistinguishedNamePrefix = fixedLdapName(this.groupSearchBase.toLowerCase());
} catch (InvalidNameException e) {
Object[] params = { this.groupSearchBase.toLowerCase(), e.getLocalizedMessage() };
throw new AlfrescoRuntimeException("synchronization.err.ldap.search.base.invalid", params, e);
}
final LdapName userDistinguishedNamePrefix;
try {
userDistinguishedNamePrefix = fixedLdapName(this.userSearchBase.toLowerCase());
} catch (InvalidNameException e) {
Object[] params = { this.userSearchBase.toLowerCase(), e.getLocalizedMessage() };
throw new AlfrescoRuntimeException("synchronization.err.ldap.search.base.invalid", params, e);
}
final boolean disjoint = !groupDistinguishedNamePrefix.startsWith(userDistinguishedNamePrefix) && !userDistinguishedNamePrefix.startsWith(groupDistinguishedNamePrefix);
// Choose / generate the query
String query;
if (modifiedSince == null) {
query = this.groupQuery;
} else {
query = MessageFormat.format(this.groupDifferentialQuery, this.timestampFormat.format(modifiedSince));
}
// Run the query and process the results
final Map<String, NodeDescription> lookup = new TreeMap<String, NodeDescription>();
processQuery(new AbstractSearchCallback() {
// We get a whole new context to avoid interference with cookies from paged results
private DirContext ctx = LDAPUserRegistry.this.ldapInitialContextFactory.getDefaultIntialDirContext();
protected void doProcess(SearchResult result) throws NamingException, ParseException {
Attributes attributes = result.getAttributes();
Attribute gidAttribute = attributes.get(LDAPUserRegistry.this.groupIdAttributeName);
if (gidAttribute == null) {
if (LDAPUserRegistry.this.errorOnMissingGID) {
Object[] params = { result.getNameInNamespace(), LDAPUserRegistry.this.groupIdAttributeName };
throw new AlfrescoRuntimeException("synchronization.err.ldap.get.group.id.missing", params);
} else {
LDAPUserRegistry.logger.warn("Missing GID on " + attributes);
return;
}
}
String groupShortName = gidAttribute.get(0).toString();
String gid = "GROUP_" + groupShortName;
NodeDescription group = lookup.get(gid);
if (group == null) {
// Apply the mapped properties to the node description
group = mapToNode(LDAPUserRegistry.this.groupAttributeMapping, LDAPUserRegistry.this.groupAttributeDefaults, result);
// Make sure the "GROUP_" prefix is applied
group.getProperties().put(ContentModel.PROP_AUTHORITY_NAME, gid);
lookup.put(gid, group);
} else if (LDAPUserRegistry.this.errorOnDuplicateGID) {
throw new AlfrescoRuntimeException("Duplicate group id found for " + gid);
} else {
LDAPUserRegistry.logger.warn("Duplicate gid found for " + gid + " -> merging definitions");
}
Set<String> childAssocs = group.getChildAssociations();
// Get the repeating (and possibly range restricted) member attribute
Attribute memAttribute = getRangeRestrictedAttribute(attributes, LDAPUserRegistry.this.memberAttributeName);
int nextStart = LDAPUserRegistry.this.attributeBatchSize;
if (LDAPUserRegistry.logger.isDebugEnabled()) {
LDAPUserRegistry.logger.debug("Processing group: " + gid + ", from source: " + group.getSourceId());
}
// Loop until we get to the end of the range
while (memAttribute != null) {
for (int i = 0; i < memAttribute.size(); i++) {
String attribute = (String) memAttribute.get(i);
if (attribute != null && attribute.length() > 0) {
try {
// Attempt to parse the member attribute as a DN. If this fails we have a fallback
// in the catch block
LdapName distinguishedNameForComparison = fixedLdapName(attribute.toLowerCase());
Attribute nameAttribute;
// and group DNs without a secondary lookup
if (disjoint) {
LdapName distinguishedName = fixedLdapName(attribute);
Attributes nameAttributes = distinguishedName.getRdn(distinguishedName.size() - 1).toAttributes();
// Recognize user DNs
if (distinguishedNameForComparison.startsWith(userDistinguishedNamePrefix) && (nameAttribute = nameAttributes.get(LDAPUserRegistry.this.userIdAttributeName)) != null) {
if (LDAPUserRegistry.logger.isDebugEnabled()) {
LDAPUserRegistry.logger.debug("User DN recognized: " + nameAttribute.get());
}
childAssocs.add((String) nameAttribute.get());
continue;
}
// Recognize group DNs
if (distinguishedNameForComparison.startsWith(groupDistinguishedNamePrefix) && (nameAttribute = nameAttributes.get(LDAPUserRegistry.this.groupIdAttributeName)) != null) {
if (LDAPUserRegistry.logger.isDebugEnabled()) {
LDAPUserRegistry.logger.debug("Group DN recognized: " + "GROUP_" + nameAttribute.get());
}
childAssocs.add("GROUP_" + nameAttribute.get());
continue;
}
}
// If we can't determine the name and type from the DN alone, try a directory lookup
if (distinguishedNameForComparison.startsWith(userDistinguishedNamePrefix) || distinguishedNameForComparison.startsWith(groupDistinguishedNamePrefix)) {
try {
Attributes childAttributes = this.ctx.getAttributes(jndiName(attribute), new String[] { "objectclass", LDAPUserRegistry.this.groupIdAttributeName, LDAPUserRegistry.this.userIdAttributeName });
Attribute objectClass = childAttributes.get("objectclass");
if (hasAttributeValue(objectClass, LDAPUserRegistry.this.personType)) {
nameAttribute = childAttributes.get(LDAPUserRegistry.this.userIdAttributeName);
if (nameAttribute == null) {
if (LDAPUserRegistry.this.errorOnMissingUID) {
throw new AlfrescoRuntimeException("User missing user id attribute DN =" + attribute + " att = " + LDAPUserRegistry.this.userIdAttributeName);
} else {
LDAPUserRegistry.logger.warn("User missing user id attribute DN =" + attribute + " att = " + LDAPUserRegistry.this.userIdAttributeName);
continue;
}
}
if (LDAPUserRegistry.logger.isDebugEnabled()) {
LDAPUserRegistry.logger.debug("User DN recognized by directory lookup: " + nameAttribute.get());
}
childAssocs.add((String) nameAttribute.get());
continue;
} else if (hasAttributeValue(objectClass, LDAPUserRegistry.this.groupType)) {
nameAttribute = childAttributes.get(LDAPUserRegistry.this.groupIdAttributeName);
if (nameAttribute == null) {
if (LDAPUserRegistry.this.errorOnMissingGID) {
Object[] params = { result.getNameInNamespace(), LDAPUserRegistry.this.groupIdAttributeName };
throw new AlfrescoRuntimeException("synchronization.err.ldap.get.group.id.missing", params);
} else {
LDAPUserRegistry.logger.warn("Missing GID on " + childAttributes);
continue;
}
}
if (LDAPUserRegistry.logger.isDebugEnabled()) {
LDAPUserRegistry.logger.debug("Group DN recognized by directory lookup: " + "GROUP_" + nameAttribute.get());
}
childAssocs.add("GROUP_" + nameAttribute.get());
continue;
}
} catch (ServiceUnavailableException | CommunicationException e) {
// MNT-21614: Check & fail if communication breaks due to ServiceUnavailableException or CommunicationException
if (e.getMessage() != null) {
Object[] params = { e.getLocalizedMessage() };
throw new AlfrescoRuntimeException("synchronization.err.ldap.search", params, e);
}
continue;
} catch (NamingException e) {
// MNT-17966
if (e.getMessage() != null && e.getMessage().startsWith(NAMING_TIMEOUT_EXCEPTION_MESSAGE)) {
Object[] params = { e.getLocalizedMessage() };
throw new AlfrescoRuntimeException("synchronization.err.ldap.search", params, e);
}
// Unresolvable name
if (LDAPUserRegistry.this.errorOnMissingMembers) {
Object[] params = { groupShortName, attribute, e.getLocalizedMessage() };
throw new AlfrescoRuntimeException("synchronization.err.ldap.group.member.missing.exception", params, e);
}
LDAPUserRegistry.logger.warn("Failed to resolve member of group '" + groupShortName + "' with distinguished name: " + attribute, e);
continue;
}
}
if (LDAPUserRegistry.this.errorOnMissingMembers) {
Object[] params = { groupShortName, attribute };
throw new AlfrescoRuntimeException("synchronization.err.ldap.group.member.missing", params);
}
LDAPUserRegistry.logger.warn("Failed to resolve member of group '" + groupShortName + "' with distinguished name: " + attribute);
} catch (InvalidNameException e) {
// posixGroup (FDS) that directly lists user names
if (LDAPUserRegistry.logger.isDebugEnabled()) {
LDAPUserRegistry.logger.debug("Member DN recognized as posixGroup: " + attribute);
}
childAssocs.add(attribute);
}
}
}
// fetch the next batch
if (nextStart > 0 && !LDAPUserRegistry.PATTERN_RANGE_END.matcher(memAttribute.getID().toLowerCase()).find()) {
Attributes childAttributes = this.ctx.getAttributes(jndiName(result.getNameInNamespace()), new String[] { LDAPUserRegistry.this.memberAttributeName + ";range=" + nextStart + '-' + (nextStart + LDAPUserRegistry.this.attributeBatchSize - 1) });
memAttribute = getRangeRestrictedAttribute(childAttributes, LDAPUserRegistry.this.memberAttributeName);
nextStart += LDAPUserRegistry.this.attributeBatchSize;
} else {
memAttribute = null;
}
}
}
public void close() throws NamingException {
this.ctx.close();
}
}, this.groupSearchBase, query, this.groupKeys.getFirst());
if (LDAPUserRegistry.logger.isDebugEnabled()) {
LDAPUserRegistry.logger.debug("Found " + lookup.size());
}
return lookup.values();
}
use of org.alfresco.repo.security.sync.NodeDescription in project alfresco-repository by Alfresco.
the class LDAPUserRegistry method mapToNode.
private NodeDescription mapToNode(Map<String, String> attributeMapping, Map<String, String> attributeDefaults, SearchResult result) throws NamingException {
NodeDescription nodeDescription = new NodeDescription(result.getNameInNamespace());
Attributes ldapAttributes = result.getAttributes();
// Parse the timestamp
Attribute modifyTimestamp = ldapAttributes.get(this.modifyTimestampAttributeName);
if (modifyTimestamp != null) {
try {
nodeDescription.setLastModified(this.timestampFormat.parse(modifyTimestamp.get().toString()));
} catch (ParseException e) {
throw new AlfrescoRuntimeException("Failed to parse timestamp.", e);
}
}
// Apply the mapped attributes
PropertyMap properties = nodeDescription.getProperties();
for (String key : attributeMapping.keySet()) {
QName keyQName = QName.createQName(key, this.namespaceService);
// cater for null
String attributeName = attributeMapping.get(key);
if (attributeName != null) {
Attribute attribute = ldapAttributes.get(attributeName);
String defaultAttribute = attributeDefaults.get(key);
if (attribute != null) {
String value = (String) attribute.get(0);
if (value != null) {
properties.put(keyQName, value);
}
} else if (defaultAttribute != null) {
properties.put(keyQName, defaultAttribute);
} else {
// Make sure that a 2nd sync, updates deleted ldap attributes(MNT-14026)
properties.put(keyQName, null);
}
} else {
String defaultValue = attributeDefaults.get(key);
if (defaultValue != null) {
properties.put(keyQName, defaultValue);
}
}
}
return nodeDescription;
}
Aggregations