diff --git a/config/alfresco/public-services-security-context.xml b/config/alfresco/public-services-security-context.xml index 27268967be..28d8a48802 100644 --- a/config/alfresco/public-services-security-context.xml +++ b/config/alfresco/public-services-security-context.xml @@ -64,6 +64,9 @@ + + + diff --git a/source/java/org/alfresco/filesys/server/auth/AlfrescoAuthenticator.java b/source/java/org/alfresco/filesys/server/auth/AlfrescoAuthenticator.java index ec20bd579e..817e7b361b 100644 --- a/source/java/org/alfresco/filesys/server/auth/AlfrescoAuthenticator.java +++ b/source/java/org/alfresco/filesys/server/auth/AlfrescoAuthenticator.java @@ -91,7 +91,7 @@ public class AlfrescoAuthenticator extends CifsAuthenticator if ( client.isGuest()) m_authComponent.setGuestUserAsCurrentUser(); else - m_authComponent.setCurrentUser(client.getUserName()); + m_authComponent.setCurrentUser(mapUserNameToPerson(client.getUserName())); // Debug @@ -229,7 +229,7 @@ public class AlfrescoAuthenticator extends CifsAuthenticator // Set the current user to be authenticated, save the authentication token - client.setAuthenticationToken( m_authComponent.setCurrentUser(client.getUserName())); + client.setAuthenticationToken( m_authComponent.setCurrentUser(mapUserNameToPerson(client.getUserName()))); // Get the users home folder node, if available diff --git a/source/java/org/alfresco/filesys/server/auth/CifsAuthenticator.java b/source/java/org/alfresco/filesys/server/auth/CifsAuthenticator.java index d21b62e627..7815a7cf8f 100644 --- a/source/java/org/alfresco/filesys/server/auth/CifsAuthenticator.java +++ b/source/java/org/alfresco/filesys/server/auth/CifsAuthenticator.java @@ -890,4 +890,50 @@ public abstract class CifsAuthenticator } } + /** + * Map the case insensitive logon name to the internal person object user name + * + * @param userName String + * @return String + */ + protected final String mapUserNameToPerson(String userName) + { + // Get the home folder for the user + + UserTransaction tx = m_transactionService.getUserTransaction(); + String personName = null; + + try + { + tx.begin(); + personName = m_personService.getUserIdentifier( userName); + tx.commit(); + } + catch (Throwable ex) + { + try + { + tx.rollback(); + } + catch (Throwable ex2) + { + logger.error("Failed to rollback transaction", ex2); + } + + // Re-throw the exception + + if (ex instanceof RuntimeException) + { + throw (RuntimeException) ex; + } + else + { + throw new RuntimeException("Error during execution of transaction.", ex); + } + } + + // Return the person name + + return personName; + } } \ No newline at end of file diff --git a/source/java/org/alfresco/filesys/server/auth/EnterpriseCifsAuthenticator.java b/source/java/org/alfresco/filesys/server/auth/EnterpriseCifsAuthenticator.java index 3bf487c3ff..0b973efc20 100644 --- a/source/java/org/alfresco/filesys/server/auth/EnterpriseCifsAuthenticator.java +++ b/source/java/org/alfresco/filesys/server/auth/EnterpriseCifsAuthenticator.java @@ -1106,7 +1106,7 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticator implements Ca // Setup the Acegi authenticated user - m_authComponent.setCurrentUser( krbDetails.getUserName()); + m_authComponent.setCurrentUser( mapUserNameToPerson(krbDetails.getUserName())); // Store the full user name in the client information, indicate that this is not a guest logon @@ -1236,7 +1236,7 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticator implements Ca // Setup the Acegi authenticated user - m_authComponent.setCurrentUser( userName); + m_authComponent.setCurrentUser( mapUserNameToPerson(userName)); // Store the full user name in the client information, indicate that this is not a guest logon @@ -1368,7 +1368,7 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticator implements Ca // Setup the Acegi authenticated user - m_authComponent.setCurrentUser( client.getUserName()); + m_authComponent.setCurrentUser( mapUserNameToPerson( client.getUserName())); // Store the full user name in the client information, indicate that this is not a guest logon @@ -1479,7 +1479,7 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticator implements Ca // Setup the Acegi authenticated user - m_authComponent.setCurrentUser( userName); + m_authComponent.setCurrentUser( mapUserNameToPerson( userName)); // Store the full user name in the client information, indicate that this is not a guest logon @@ -1602,7 +1602,7 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticator implements Ca // Setup the Acegi authenticated user - m_authComponent.setCurrentUser( client.getUserName()); + m_authComponent.setCurrentUser( mapUserNameToPerson( client.getUserName())); // Store the full user name in the client information, indicate that this is not a guest logon @@ -1765,7 +1765,7 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticator implements Ca // Setup the Acegi authenticated user - m_authComponent.setCurrentUser( userName); + m_authComponent.setCurrentUser( mapUserNameToPerson( userName)); // Store the full user name in the client information, indicate that this is not a guest logon diff --git a/source/java/org/alfresco/filesys/server/auth/passthru/PassthruAuthenticator.java b/source/java/org/alfresco/filesys/server/auth/passthru/PassthruAuthenticator.java index b2a83d1454..7d539310e9 100644 --- a/source/java/org/alfresco/filesys/server/auth/passthru/PassthruAuthenticator.java +++ b/source/java/org/alfresco/filesys/server/auth/passthru/PassthruAuthenticator.java @@ -125,7 +125,7 @@ public class PassthruAuthenticator extends CifsAuthenticator implements SessionL { // Use the existing authentication token - m_authComponent.setCurrentUser(client.getUserName()); + m_authComponent.setCurrentUser( mapUserNameToPerson( client.getUserName())); // Debug @@ -220,40 +220,28 @@ public class PassthruAuthenticator extends CifsAuthenticator implements SessionL // Map the passthru username to an Alfresco person String username = client.getUserName(); - NodeRef userNode = m_personService.getPerson( username); + String personName = m_personService.getUserIdentifier( username); - if ( userNode != null) + if ( personName != null) { - // Get the person name and use that as the current user to line up with permission checks - - String personName = (String) m_nodeService.getProperty(userNode, ContentModel.PROP_USERNAME); + // Use the person name as the current user + m_authComponent.setCurrentUser(personName); // DEBUG if ( logger.isDebugEnabled()) logger.debug("Setting current user using person " + personName + " (username " + username + ")"); + + // Allow the user full access to the server + + authSts = CifsAuthenticator.AUTH_ALLOW; + + // Debug + + if (logger.isDebugEnabled()) + logger.debug("Passthru authenticate user=" + client.getUserName() + ", FULL"); } - else - { - // Set using the user name - - m_authComponent.setCurrentUser( username); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("Setting current user using username " + username); - } - - // Allow the user full access to the server - - authSts = CifsAuthenticator.AUTH_ALLOW; - - // Debug - - if (logger.isDebugEnabled()) - logger.debug("Passthru authenticate user=" + client.getUserName() + ", FULL"); } finally { diff --git a/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java b/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java index 19262467a3..2d4c4e618d 100644 --- a/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java +++ b/source/java/org/alfresco/repo/security/authority/AuthorityDAOImpl.java @@ -61,7 +61,7 @@ public class AuthorityDAOImpl implements AuthorityDAO private DictionaryService dictionaryService; - private SimpleCache> userToAuthorityCache; + private SimpleCache> userToAuthorityCache; public AuthorityDAOImpl() { @@ -90,7 +90,7 @@ public class AuthorityDAOImpl implements AuthorityDAO this.searchService = searchService; } - public void setUserToAuthorityCache(SimpleCache> userToAuthorityCache) + public void setUserToAuthorityCache(SimpleCache> userToAuthorityCache) { this.userToAuthorityCache = userToAuthorityCache; } @@ -127,6 +127,7 @@ public class AuthorityDAOImpl implements AuthorityDAO } nodeService.addChild(parentRef, childRef, ContentModel.ASSOC_MEMBER, QName.createQName("usr", childName, namespacePrefixResolver)); + userToAuthorityCache.clear(); } else { @@ -165,7 +166,7 @@ public class AuthorityDAOImpl implements AuthorityDAO throw new UnknownAuthorityException("An authority was not found for " + name); } nodeService.deleteNode(nodeRef); - + userToAuthorityCache.clear(); } public Set getAllRootAuthorities(AuthorityType type) @@ -234,15 +235,31 @@ public class AuthorityDAOImpl implements AuthorityDAO throw new UnknownAuthorityException("An authority was not found for " + childName); } nodeService.removeChild(parentRef, childRef); + userToAuthorityCache.clear(); } } public Set getContainingAuthorities(AuthorityType type, String name, boolean immediate) { - HashSet authorities = new HashSet(); - findAuthorities(type, name, authorities, true, !immediate); - return authorities; + if (AuthorityType.getAuthorityType(name).equals(AuthorityType.USER) && ! immediate && (type == null)) + { + // Cache user to authority look ups + HashSet authorities = userToAuthorityCache.get(name); + if(authorities == null) + { + authorities = new HashSet(); + findAuthorities(type, name, authorities, true, !immediate); + userToAuthorityCache.put(name, authorities); + } + return authorities; + } + else + { + HashSet authorities = new HashSet(); + findAuthorities(type, name, authorities, true, !immediate); + return authorities; + } } private void findAuthorities(AuthorityType type, String name, Set authorities, boolean parents, @@ -276,12 +293,7 @@ public class AuthorityDAOImpl implements AuthorityDAO private ArrayList getUserContainers(String name) { - ArrayList containers = userToAuthorityCache.get(name); - if (containers == null) - { - containers = findUserContainers(name); - userToAuthorityCache.put(name, containers); - } + ArrayList containers = findUserContainers(name); return containers; } diff --git a/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceImpl.java b/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceImpl.java index 70b7d714fd..e09c09310a 100644 --- a/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceImpl.java +++ b/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceImpl.java @@ -26,7 +26,10 @@ import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.GrantedAuthority; import net.sf.acegisecurity.providers.dao.User; +import org.alfresco.model.ContentModel; import org.alfresco.repo.cache.SimpleCache; +import org.alfresco.repo.policy.JavaBehaviour; +import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.security.permissions.DynamicAuthority; import org.alfresco.repo.security.permissions.NodePermissionEntry; @@ -43,6 +46,7 @@ import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.util.EqualsHelper; import org.apache.commons.logging.Log; @@ -102,6 +106,8 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing */ private List dynamicAuthorities; + private PolicyComponent policyComponent; + /* * Standard spring construction. */ @@ -152,13 +158,24 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing /** * Set the permissions access cache. * - * @param accessCache a transactionally safe cache + * @param accessCache + * a transactionally safe cache */ public void setAccessCache(SimpleCache accessCache) { this.accessCache = accessCache; } + public void setPolicyComponent(PolicyComponent policyComponent) + { + this.policyComponent = policyComponent; + } + + public void onMoveNode(ChildAssociationRef oldChildAssocRef, ChildAssociationRef newChildAssocRef) + { + accessCache.clear(); + } + public void afterPropertiesSet() throws Exception { if (dictionaryService == null) @@ -189,6 +206,13 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing { throw new IllegalArgumentException("Property 'accessCache' has not been set"); } + if (policyComponent == null) + { + throw new IllegalArgumentException("Property 'policyComponent' has not been set"); + } + + policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onMoveNode"), ContentModel.ASPECT_AUDITABLE, new JavaBehaviour(this, "onMoveNode")); + } // @@ -372,7 +396,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing Set authorisations = getAuthorisations(auth, nodeRef); Serializable key = generateKey( authorisations, - nodeService.getPath(nodeRef), + nodeRef, perm); AccessStatus status = accessCache.get(key); if (status != null) @@ -423,16 +447,17 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing } /** - * Key for a cache object is built from all the known Authorities (which can change - * dynamically so they must all be used) the NodeRef ID and the permission reference itself. - * This gives a unique key for each permission test. + * Key for a cache object is built from all the known Authorities (which can + * change dynamically so they must all be used) the NodeRef ID and the + * permission reference itself. This gives a unique key for each permission + * test. */ - static Serializable generateKey(Set auths, Path path, PermissionReference perm) + static Serializable generateKey(Set auths, NodeRef nodeRef, PermissionReference perm) { LinkedHashSet key = new LinkedHashSet(); key.add(perm.toString()); key.addAll(auths); - key.add(path); + key.add(nodeRef); return key; }