diff --git a/config/alfresco/extension/ldap-authentication-context.xml.sample b/config/alfresco/extension/ldap-authentication-context.xml.sample index f50725c1a9..34dbe20833 100644 --- a/config/alfresco/extension/ldap-authentication-context.xml.sample +++ b/config/alfresco/extension/ldap-authentication-context.xml.sample @@ -287,6 +287,10 @@ member + + + + @@ -397,6 +401,13 @@ + + + + + + + @@ -437,6 +448,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/source/java/org/alfresco/repo/importer/ExportSourceImporter.java b/source/java/org/alfresco/repo/importer/ExportSourceImporter.java index 836694320c..cbe486e250 100644 --- a/source/java/org/alfresco/repo/importer/ExportSourceImporter.java +++ b/source/java/org/alfresco/repo/importer/ExportSourceImporter.java @@ -21,14 +21,14 @@ import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; -import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.util.List; +import java.util.Set; import javax.transaction.UserTransaction; -import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.cache.SimpleCache; import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; @@ -52,21 +52,23 @@ public class ExportSourceImporter implements ImporterJobSPI private ExportSource exportSource; private AuthenticationComponent authenticationComponent; - + private StoreRef storeRef; private String path; - + private boolean clearAllChildren; - + private NodeService nodeService; - + private SearchService searchService; - + private NamespacePrefixResolver namespacePrefixResolver; - + private TransactionService transactionService; + private Set caches; + public ExportSourceImporter() { super(); @@ -96,7 +98,7 @@ public class ExportSourceImporter implements ImporterJobSPI { this.storeRef = new StoreRef(storeRef); } - + public void setTransactionService(TransactionService transactionService) { this.transactionService = transactionService; @@ -111,8 +113,11 @@ public class ExportSourceImporter implements ImporterJobSPI { this.nodeService = nodeService; } - - + + public void setCaches(Set caches) + { + this.caches = caches; + } public void setAuthenticationComponent(AuthenticationComponent authenticationComponent) { @@ -124,6 +129,7 @@ public class ExportSourceImporter implements ImporterJobSPI this.searchService = searchService; } + @SuppressWarnings("unchecked") public void doImport() { UserTransaction userTransaction = null; @@ -132,18 +138,28 @@ public class ExportSourceImporter implements ImporterJobSPI userTransaction = transactionService.getUserTransaction(); userTransaction.begin(); authenticationComponent.setSystemUserAsCurrentUser(); - if(clearAllChildren) + if (clearAllChildren) { - List refs = searchService.selectNodes(nodeService.getRootNode(storeRef), path, null, namespacePrefixResolver, false); - for(NodeRef ref: refs) + List refs = searchService.selectNodes(nodeService.getRootNode(storeRef), path, null, + namespacePrefixResolver, false); + for (NodeRef ref : refs) { - for(ChildAssociationRef car: nodeService.getChildAssocs(ref)) + for (ChildAssociationRef car : nodeService.getChildAssocs(ref)) { nodeService.deleteNode(car.getChildRef()); } } } - + + if (caches != null) + { + for (SimpleCache cache : caches) + { + + cache.clear(); + } + } + File tempFile = TempFileProvider.createTempFile("ExportSourceImporter-", ".xml"); Writer writer = new BufferedWriter(new FileWriter(tempFile)); XMLWriter xmlWriter = createXMLExporter(writer); @@ -157,12 +173,36 @@ public class ExportSourceImporter implements ImporterJobSPI importerService.importView(reader, location, REPLACE_BINDING, null); reader.close(); + + if (caches != null) + { + for (SimpleCache cache : caches) + { + cache.clear(); + } + } + userTransaction.commit(); } - catch(Throwable t) + catch (Throwable t) { - try { if (userTransaction != null) {userTransaction.rollback();} } catch (Exception ex) {} - try {authenticationComponent.clearCurrentSecurityContext(); } catch (Exception ex) {} + try + { + if (userTransaction != null) + { + userTransaction.rollback(); + } + } + catch (Exception ex) + { + } + try + { + authenticationComponent.clearCurrentSecurityContext(); + } + catch (Exception ex) + { + } throw new ExportSourceImporterException("Failed to import", t); } finally diff --git a/source/java/org/alfresco/repo/security/authentication/ldap/LDAPGroupExportSource.java b/source/java/org/alfresco/repo/security/authentication/ldap/LDAPGroupExportSource.java index 8e74cce996..013760b20e 100644 --- a/source/java/org/alfresco/repo/security/authentication/ldap/LDAPGroupExportSource.java +++ b/source/java/org/alfresco/repo/security/authentication/ldap/LDAPGroupExportSource.java @@ -32,12 +32,16 @@ import javax.naming.directory.Attributes; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; +import javax.transaction.UserTransaction; import org.alfresco.model.ContentModel; import org.alfresco.repo.importer.ExportSource; import org.alfresco.repo.importer.ExportSourceImporterException; +import org.alfresco.repo.security.authority.AuthorityDAO; +import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.ApplicationContextHelper; import org.alfresco.util.EqualsHelper; import org.alfresco.util.GUID; @@ -86,6 +90,8 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean private QName viewIdRef; + private AuthorityDAO authorityDAO; + public LDAPGroupExportSource() { super(); @@ -141,6 +147,11 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean this.errorOnMissingMembers = errorOnMissingMembers; } + public void setAuthorityDAO(AuthorityDAO authorityDAO) + { + this.authorityDAO = authorityDAO; + } + public void generateExport(XMLWriter writer) { HashSet rootGroups = new HashSet(); @@ -222,7 +233,8 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean String toId = lookup.get(sl.to).guid; AttributesImpl attrs = new AttributesImpl(); - attrs.addAttribute(viewIdRef.getNamespaceURI(), viewIdRef.getLocalName(), viewIdRef.toPrefixString(), null, fromId); + attrs.addAttribute(viewIdRef.getNamespaceURI(), viewIdRef.getLocalName(), viewIdRef.toPrefixString(), null, + fromId); writer.startElement(viewRef.getNamespaceURI(), viewRef.getLocalName(), viewRef.toPrefixString(namespaceService), attrs); @@ -234,7 +246,8 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean ContentModel.ASSOC_MEMBER.toPrefixString(namespaceService), new AttributesImpl()); AttributesImpl attrsRef = new AttributesImpl(); - attrsRef.addAttribute(viewIdRef.getNamespaceURI(), viewIdRef.getLocalName(), viewIdRef.toPrefixString(), null, toId); + attrsRef.addAttribute(viewIdRef.getNamespaceURI(), viewIdRef.getLocalName(), viewIdRef.toPrefixString(), null, + toId); attrsRef.addAttribute(childQName.getNamespaceURI(), childQName.getLocalName(), childQName.toPrefixString(), null, QName.createQName(ContentModel.USER_MODEL_URI, sl.to).toPrefixString(namespaceService)); @@ -255,13 +268,13 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean private void addRootGroup(HashMap lookup, Group group, XMLWriter writer) throws SAXException { + QName nodeUUID = QName.createQName("sys:node-uuid", namespaceService); AttributesImpl attrs = new AttributesImpl(); attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_1_0_URI, childQName.getLocalName(), childQName .toPrefixString(), null, QName.createQName(ContentModel.USER_MODEL_URI, group.gid).toPrefixString( namespaceService)); - attrs.addAttribute(viewId.getNamespaceURI(), viewId.getLocalName(), viewId - .toPrefixString(), null, group.guid); + attrs.addAttribute(viewId.getNamespaceURI(), viewId.getLocalName(), viewId.toPrefixString(), null, group.guid); writer.startElement(ContentModel.TYPE_AUTHORITY_CONTAINER.getNamespaceURI(), ContentModel.TYPE_AUTHORITY_CONTAINER.getLocalName(), ContentModel.TYPE_AUTHORITY_CONTAINER @@ -301,6 +314,23 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean addgroup(lookup, child, writer); } + if ((authorityDAO != null ) && authorityDAO.authorityExists(group.gid)) + { + NodeRef authNodeRef = authorityDAO.getAuthorityNodeRefOrNull(group.gid); + if (authNodeRef != null) + { + String uguid = authorityDAO.getAuthorityNodeRefOrNull(group.gid).getId(); + + writer.startElement(nodeUUID.getNamespaceURI(), nodeUUID.getLocalName(), nodeUUID + .toPrefixString(namespaceService), new AttributesImpl()); + + writer.characters(uguid.toCharArray(), 0, uguid.length()); + + writer.endElement(nodeUUID.getNamespaceURI(), nodeUUID.getLocalName(), nodeUUID + .toPrefixString(namespaceService)); + } + } + writer.endElement(ContentModel.TYPE_AUTHORITY_CONTAINER.getNamespaceURI(), ContentModel.TYPE_AUTHORITY_CONTAINER.getLocalName(), ContentModel.TYPE_AUTHORITY_CONTAINER .toPrefixString(namespaceService)); @@ -337,9 +367,10 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean SearchResult result = (SearchResult) searchResults.next(); Attributes attributes = result.getAttributes(); Attribute gidAttribute = attributes.get(groupIdAttributeName); - if(gidAttribute == null) + if (gidAttribute == null) { - throw new ExportSourceImporterException("Group returned by group search does not have mandatory group id attribute "+attributes); + throw new ExportSourceImporterException( + "Group returned by group search does not have mandatory group id attribute " + attributes); } String gid = (String) gidAttribute.get(0); @@ -421,9 +452,9 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean } Attributes attributes = result.getAttributes(); Attribute objectclass = attributes.get("objectclass"); - if(objectclass == null) + if (objectclass == null) { - throw new ExportSourceImporterException("Failed to find attribute objectclass for DN "+dn); + throw new ExportSourceImporterException("Failed to find attribute objectclass for DN " + dn); } for (int i = 0; i < objectclass.size(); i++) { @@ -447,9 +478,10 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean try { Attribute groupIdAttribute = attributes.get(groupIdAttributeName); - if(groupIdAttribute == null) + if (groupIdAttribute == null) { - throw new ExportSourceImporterException("Group missing group id attribute DN ="+dn + " att = "+groupIdAttributeName); + throw new ExportSourceImporterException("Group missing group id attribute DN =" + + dn + " att = " + groupIdAttributeName); } id = (String) groupIdAttribute.get(0); } @@ -471,9 +503,10 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean try { Attribute userIdAttribute = attributes.get(userIdAttributeName); - if(userIdAttribute == null) + if (userIdAttribute == null) { - throw new ExportSourceImporterException("User missing user id attribute DN ="+dn + " att = "+userIdAttributeName); + throw new ExportSourceImporterException("User missing user id attribute DN =" + + dn + " att = " + userIdAttributeName); } id = (String) userIdAttribute.get(0); } @@ -495,7 +528,7 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean { if (isGroup == null) { - throw new ExportSourceImporterException("Type not recognised for DN"+dn); + throw new ExportSourceImporterException("Type not recognised for DN" + dn); } else if (isGroup) { @@ -580,7 +613,7 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean private Group(String gid) { - this.gid = "GROUP_" + gid; + this.gid = "GROUP_" + gid; } @Override @@ -613,8 +646,8 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean private SecondaryLink(String from, String to) { - this.from = from; - this.to = to; + this.from = from; + this.to = to; } @Override @@ -648,17 +681,22 @@ public class LDAPGroupExportSource implements ExportSource, InitializingBean } } - public static void main(String[] args) throws IOException + public static void main(String[] args) throws Exception { ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(); ExportSource source = (ExportSource) ctx.getBean("ldapGroupExportSource"); + TransactionService txs = (TransactionService) ctx.getBean("transactionComponent"); + UserTransaction tx = txs.getUserTransaction(); + tx.begin(); + File file = new File(args[0]); Writer writer = new BufferedWriter(new FileWriter(file)); XMLWriter xmlWriter = createXMLExporter(writer); source.generateExport(xmlWriter); xmlWriter.close(); + tx.commit(); } private static XMLWriter createXMLExporter(Writer writer) diff --git a/source/java/org/alfresco/repo/security/authentication/ldap/LDAPPersonExportSource.java b/source/java/org/alfresco/repo/security/authentication/ldap/LDAPPersonExportSource.java index badddbe25f..422871d5ae 100644 --- a/source/java/org/alfresco/repo/security/authentication/ldap/LDAPPersonExportSource.java +++ b/source/java/org/alfresco/repo/security/authentication/ldap/LDAPPersonExportSource.java @@ -19,7 +19,6 @@ package org.alfresco.repo.security.authentication.ldap; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; -import java.io.IOException; import java.io.Writer; import java.util.Collection; import java.util.Map; @@ -31,6 +30,7 @@ import javax.naming.directory.Attributes; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; +import javax.transaction.UserTransaction; import org.alfresco.model.ContentModel; import org.alfresco.repo.importer.ExportSource; @@ -38,6 +38,7 @@ import org.alfresco.repo.importer.ExportSourceImporterException; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.ApplicationContextHelper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -50,7 +51,7 @@ import org.xml.sax.helpers.AttributesImpl; public class LDAPPersonExportSource implements ExportSource { private static Log s_logger = LogFactory.getLog(LDAPPersonExportSource.class); - + private String personQuery = "(objectclass=inetOrgPerson)"; private String searchBase; @@ -149,24 +150,28 @@ public class LDAPPersonExportSource implements ExportSource SearchControls userSearchCtls = new SearchControls(); userSearchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE); - System.out.println("COUNT "+userSearchCtls.getCountLimit()); - System.out.println("TIME "+userSearchCtls.getTimeLimit()); + userSearchCtls.setCountLimit(Integer.MAX_VALUE); - + NamingEnumeration searchResults = ctx.search(searchBase, personQuery, userSearchCtls); while (searchResults.hasMoreElements()) { SearchResult result = (SearchResult) searchResults.next(); Attributes attributes = result.getAttributes(); Attribute uidAttribute = attributes.get(userIdAttributeName); + if (uidAttribute == null) + { + throw new ExportSourceImporterException( + "User returned by user search does not have mandatory user id attribute " + attributes); + } String uid = (String) uidAttribute.get(0); - if(s_logger.isDebugEnabled()) + if (s_logger.isDebugEnabled()) { - s_logger.debug("Adding user for "+uid); + s_logger.debug("Adding user for " + uid); } - System.out.println("User "+uid); - + + writer.startElement(ContentModel.TYPE_PERSON.getNamespaceURI(), ContentModel.TYPE_PERSON .getLocalName(), ContentModel.TYPE_PERSON.toPrefixString(namespaceService), attrs); @@ -199,13 +204,17 @@ public class LDAPPersonExportSource implements ExportSource .toPrefixString(namespaceService), new AttributesImpl()); // cater for null - String attribute = attributeMapping.get(key); - if (attribute != null) + String attributeName = attributeMapping.get(key); + if (attributeName != null) { - String value = (String) attributes.get(attribute).get(0); - if (value != null) + Attribute attribute = attributes.get(attributeName); + if (attribute != null) { - writer.characters(value.toCharArray(), 0, value.length()); + String value = (String) attribute.get(0); + if (value != null) + { + writer.characters(value.toCharArray(), 0, value.length()); + } } } @@ -292,17 +301,21 @@ public class LDAPPersonExportSource implements ExportSource } } - public static void main(String[] args) throws IOException + public static void main(String[] args) throws Exception { ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(); ExportSource source = (ExportSource) ctx.getBean("ldapPeopleExportSource"); - + TransactionService txs = (TransactionService) ctx.getBean("transactionComponent"); + UserTransaction tx = txs.getUserTransaction(); + tx.begin(); + File file = new File(args[0]); Writer writer = new BufferedWriter(new FileWriter(file)); XMLWriter xmlWriter = createXMLExporter(writer); source.generateExport(xmlWriter); xmlWriter.close(); + tx.commit(); } private static XMLWriter createXMLExporter(Writer writer) diff --git a/source/java/org/alfresco/repo/security/authority/AuthorityDAO.java b/source/java/org/alfresco/repo/security/authority/AuthorityDAO.java index ff72501824..4dbf17f4cb 100644 --- a/source/java/org/alfresco/repo/security/authority/AuthorityDAO.java +++ b/source/java/org/alfresco/repo/security/authority/AuthorityDAO.java @@ -18,6 +18,7 @@ package org.alfresco.repo.security.authority; import java.util.Set; +import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.AuthorityType; public interface AuthorityDAO @@ -96,4 +97,12 @@ public interface AuthorityDAO * @return */ boolean authorityExists(String name); + + /** + * Get a node ref for the authority if one exists + * + * @param name + * @return + */ + NodeRef getAuthorityNodeRefOrNull(String name); } diff --git a/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java b/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java index c2dcb80584..0fa7e6ed31 100644 --- a/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java +++ b/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java @@ -50,11 +50,17 @@ public class AuthorityDAOImpl implements AuthorityDAO public static final StoreRef STOREREF_USERS = new StoreRef("user", "alfrescoUserStore"); private NodeService nodeService; + private NamespacePrefixResolver namespacePrefixResolver; + private QName qnameAssocSystem; + private QName qnameAssocAuthorities; + private SearchService searchService; + private DictionaryService dictionaryService; + private SimpleCache> userToAuthorityCache; public AuthorityDAOImpl() @@ -91,11 +97,10 @@ public class AuthorityDAOImpl implements AuthorityDAO public boolean authorityExists(String name) { - NodeRef ref = getAuthorityOrNull(name); + NodeRef ref = getAuthorityOrNull(name); return ref != null; - } - - + } + public void addAuthority(String parentName, String childName) { NodeRef parentRef = getAuthorityOrNull(parentName); @@ -120,11 +125,8 @@ public class AuthorityDAOImpl implements AuthorityDAO { throw new UnknownAuthorityException("An authority was not found for " + childName); } - nodeService.addChild( - parentRef, - childRef, - ContentModel.ASSOC_MEMBER, - QName.createQName("usr", childName, namespacePrefixResolver)); + nodeService.addChild(parentRef, childRef, ContentModel.ASSOC_MEMBER, QName.createQName("usr", childName, + namespacePrefixResolver)); } } @@ -140,22 +142,14 @@ public class AuthorityDAOImpl implements AuthorityDAO { throw new UnknownAuthorityException("An authority was not found for " + parentName); } - nodeService.createNode( - parentRef, - ContentModel.ASSOC_MEMBER, - QName.createQName("usr", name, namespacePrefixResolver), - ContentModel.TYPE_AUTHORITY_CONTAINER, - props); + nodeService.createNode(parentRef, ContentModel.ASSOC_MEMBER, QName.createQName("usr", name, + namespacePrefixResolver), ContentModel.TYPE_AUTHORITY_CONTAINER, props); } else { NodeRef authorityContainerRef = getAuthorityContainer(); - nodeService.createNode( - authorityContainerRef, - ContentModel.ASSOC_CHILDREN, - QName.createQName("usr", name, namespacePrefixResolver), - ContentModel.TYPE_AUTHORITY_CONTAINER, - props); + nodeService.createNode(authorityContainerRef, ContentModel.ASSOC_CHILDREN, QName.createQName("usr", name, + namespacePrefixResolver), ContentModel.TYPE_AUTHORITY_CONTAINER, props); } } @@ -430,9 +424,8 @@ public class AuthorityDAOImpl implements AuthorityDAO { for (ResultSetRow row : rs) { - String test = DefaultTypeConverter.INSTANCE.convert( - String.class, - nodeService.getProperty(row.getNodeRef(), ContentModel.PROP_AUTHORITY_NAME)); + String test = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(row + .getNodeRef(), ContentModel.PROP_AUTHORITY_NAME)); if (test.equals(name)) { return row.getNodeRef(); @@ -457,9 +450,7 @@ public class AuthorityDAOImpl implements AuthorityDAO private NodeRef getAuthorityContainer() { NodeRef rootNodeRef = nodeService.getRootNode(STOREREF_USERS); - List results = nodeService.getChildAssocs( - rootNodeRef, - RegexQNamePattern.MATCH_ALL, + List results = nodeService.getChildAssocs(rootNodeRef, RegexQNamePattern.MATCH_ALL, qnameAssocSystem); NodeRef sysNodeRef = null; if (results.size() == 0) @@ -470,10 +461,7 @@ public class AuthorityDAOImpl implements AuthorityDAO { sysNodeRef = results.get(0).getChildRef(); } - results = nodeService.getChildAssocs( - sysNodeRef, - RegexQNamePattern.MATCH_ALL, - qnameAssocAuthorities); + results = nodeService.getChildAssocs(sysNodeRef, RegexQNamePattern.MATCH_ALL, qnameAssocAuthorities); NodeRef authNodeRef = null; if (results.size() == 0) { @@ -485,4 +473,10 @@ public class AuthorityDAOImpl implements AuthorityDAO } return authNodeRef; } + + public NodeRef getAuthorityNodeRefOrNull(String name) + { + return getAuthorityOrNull(name); + } + }