diff --git a/config/alfresco/authentication-services-context.xml b/config/alfresco/authentication-services-context.xml
index c1a83469b7..0504dfc5e4 100644
--- a/config/alfresco/authentication-services-context.xml
+++ b/config/alfresco/authentication-services-context.xml
@@ -74,7 +74,6 @@
-
@@ -118,7 +117,6 @@
-
diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml
index 5bebbe3f9c..ed29ca3e85 100644
--- a/config/alfresco/core-services-context.xml
+++ b/config/alfresco/core-services-context.xml
@@ -519,7 +519,7 @@
-
+
diff --git a/config/alfresco/extension/chaining-authentication-context.xml.sample b/config/alfresco/extension/chaining-authentication-context.xml.sample
index f73a4a09b1..8abcbfd99b 100644
--- a/config/alfresco/extension/chaining-authentication-context.xml.sample
+++ b/config/alfresco/extension/chaining-authentication-context.xml.sample
@@ -5,9 +5,9 @@
-
+
-
+
@@ -18,6 +18,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config/alfresco/extension/ldap-authentication-context.xml.sample b/config/alfresco/extension/ldap-authentication-context.xml.sample
index 08d68177ad..9830dba432 100644
--- a/config/alfresco/extension/ldap-authentication-context.xml.sample
+++ b/config/alfresco/extension/ldap-authentication-context.xml.sample
@@ -3,6 +3,17 @@
+
+
+
+
+ true
+
+
+ classpath:alfresco/extension/ldap-authentication.properties
+
+
+
@@ -34,11 +45,11 @@
"%s" - the user id is passed through without modification.
Used for LDAP authentication such as DIGEST-MD5, anything that is not "simple".
- "cn=%s,ou=London,dc=company,dc=com" - If the user types in "Joe Bloggs" the authentricate as "cn=Joe Bloggs,ou=London,dc=company,dc=com"
- Usually for simple authentication.
+ "cn=%s,ou=London,dc=company,dc=com" - If the user types in "Joe Bloggs" the authenticate as "cn=Joe Bloggs,ou=London,dc=company,dc=com"
+ Usually for simple authentication. Simple authentication always uses the DN for the user.
-->
- %s
+ ${ldap.authentication.userNameFormat}
@@ -54,14 +65,14 @@
-
-
-
-
-
-
-
-
-
-
- (objectclass=inetOrgPerson)
-
-
-
-
- dc=alfresco,dc=org
-
-
-
-
- uid
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- (objectclass=groupOfNames)
-
-
-
-
- dc=alfresco,dc=org
-
-
-
-
- uid
-
-
-
-
- cn
-
-
-
-
- groupOfNames
-
-
-
-
- inetOrgPerson
-
-
-
-
-
-
-
-
-
-
- member
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- org.alfresco.repo.importer.ImporterJob
-
-
-
-
-
-
-
-
- 300000
-
-
-
- 3600000
-
-
-
-
-
-
-
-
- org.alfresco.repo.importer.ImporterJob
-
-
-
-
-
-
-
-
- 300000
-
-
-
- 3600000
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${spaces.store}
-
-
-
-
- /${system.system_container.childname}/${system.people_container.childname}
-
-
-
-
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${alfresco_user_store.store}
-
-
-
-
- /${alfresco_user_store.system_container.childname}/${alfresco_user_store.authorities_container.childname}
-
-
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/config/alfresco/extension/ldap-authentication.properties b/config/alfresco/extension/ldap-authentication.properties
new file mode 100644
index 0000000000..7b5a8bab83
--- /dev/null
+++ b/config/alfresco/extension/ldap-authentication.properties
@@ -0,0 +1,27 @@
+#
+# This properties file brings together the common options for LDAP authentication rather than editing the bean definitions
+#
+
+# How to map the user id entered by the user to taht passed through to LDAP
+# - simple
+# - this must be a DN and would be something like
+# CN=%s,DC=company,DC=com
+# - digest
+# - usually pass through what is entered
+# %s
+ldap.authentication.userNameFormat=%s
+
+# The LDAP context factory to use
+ldap.authentication.java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
+
+# The URL to connect to the LDAP server
+ldap.authentication.java.naming.provider.url=ldap://openldap.domain.com:389
+
+# The authentication mechanism to use
+ldap.authentication.java.naming.security.authentication=DIGEST-MD5
+
+# The default principal to use (only used for LDAP sync)
+ldap.authentication.java.naming.security.principal=reader
+
+# The password for the default principal (only used for LDAP sync)
+ldap.authentication.java.naming.security.credentials=secret
\ No newline at end of file
diff --git a/config/alfresco/extension/ldap-synchronisation-context.xml.sample b/config/alfresco/extension/ldap-synchronisation-context.xml.sample
new file mode 100644
index 0000000000..d61cb0b408
--- /dev/null
+++ b/config/alfresco/extension/ldap-synchronisation-context.xml.sample
@@ -0,0 +1,377 @@
+
+
+
+
+
+
+
+ true
+
+
+ classpath:alfresco/extension/ldap-synchronisation.properties
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${ldap.synchronisation.personQuery}
+
+
+
+
+ ${ldap.synchronisation.personSearchBase}
+
+
+
+
+ ${ldap.synchronisation.userIdAttributeName]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${ldap.synchronisation.groupQuery}
+
+
+
+
+ ${ldap.synchronisation.groupSearchBase}
+
+
+
+
+ ${ldap.synchronisation.userIdAttributeName}
+
+
+
+
+ ${ldap.synchronisation.groupIdAttributeName}
+
+
+
+
+ ${ldap.synchronisation.groupType}
+
+
+
+
+ ${ldap.synchronisation.personType}
+
+
+
+
+
+
+
+
+
+
+ ${ldap.synchronisation.groupMemberAttributeName}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.alfresco.repo.importer.ImporterJob
+
+
+
+
+
+
+
+ ${ldap.synchronisation.import.person.cron}
+
+
+
+
+
+
+
+
+
+
+ org.alfresco.repo.importer.ImporterJob
+
+
+
+
+
+
+
+ ${ldap.synchronisation.import.group.cron}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${spaces.store}
+
+
+
+
+ /${system.system_container.childname}/${system.people_container.childname}
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${alfresco_user_store.store}
+
+
+
+
+ /${alfresco_user_store.system_container.childname}/${alfresco_user_store.authorities_container.childname}
+
+
+
+
+ ${ldap.synchronisation.import.group.clearAllChildren}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config/alfresco/extension/ldap-synchronisation.properties b/config/alfresco/extension/ldap-synchronisation.properties
new file mode 100644
index 0000000000..ffd1392f9d
--- /dev/null
+++ b/config/alfresco/extension/ldap-synchronisation.properties
@@ -0,0 +1,59 @@
+#
+# This properties file is used to configure LDAP syncronisation
+#
+
+# The query to find the people to import
+ldap.synchronisation.personQuery=(objectclass=inetOrgPerson)
+
+# The search base of the query to find people to import
+ldap.synchronisation.personSearchBase=dc=company,dc=com
+
+# The attribute name on people objects found in LDAP to use as the uid in Alfresco
+ldap.synchronisation.userIdAttributeName=uid
+
+# The attribute on person objects in LDAP to map to the first name property in Alfresco
+ldap.synchronisation.userFirstNameAttributeName=givenName
+
+# The attribute on person objects in LDAP to map to the last name property in Alfresco
+ldap.synchronisation.userLastNameAttributeName=sn
+
+# The attribute on person objects in LDAP to map to the email property in Alfresco
+ldap.synchronisation.userEmailAttributeName=mail
+
+# The attribute on person objects in LDAP to map to the organizational id property in Alfresco
+ldap.synchronisation.userOrganizationalIdAttributeName=o
+
+# The default home folder provider to use for people created via LDAP import
+ldap.synchronisation.defaultHomeFolderProvider=personalHomeFolderProvider
+
+# The query to find group objects
+ldap.synchronisation.groupQuery=(objectclass=groupOfNames)
+
+# The search base to use to find group objects
+ldap.synchronisation.groupSearchBase=dc=company,dc=com
+
+# The attribute on LDAP group objects to map to the gid property in Alfrecso
+ldap.synchronisation.groupIdAttributeName=cn
+
+# The group type in LDAP
+ldap.synchronisation.groupType=groupOfNames
+
+# The person type in LDAP
+ldap.synchronisation.personType=inetOrgPerson
+
+# The attribute in LDAP on group objects that defines the DN for its members
+ldap.synchronisation.groupMemberAttributeName=member
+
+# The cron expression defining when people imports should take place
+ldap.synchronisation.import.person.cron=0 0 * * * ?
+
+# The cron expression defining when group imports should take place
+ldap.synchronisation.import.group.cron=0 30 * * * ?
+
+# Should all groups be cleared out at import time?
+# - this is safe as groups are not used in Alfresco for other things (unlike person objects which you should never clear out during an import)
+# - setting this to true means old group definitions will be tidied up.
+ldap.synchronisation.import.group.clearAllChildren=true
+
+
+
diff --git a/config/alfresco/model/contentModel.xml b/config/alfresco/model/contentModel.xml
index 91b7857084..7024f83836 100644
--- a/config/alfresco/model/contentModel.xml
+++ b/config/alfresco/model/contentModel.xml
@@ -219,6 +219,7 @@
false
true
+ false
diff --git a/config/alfresco/ownable-services-context.xml b/config/alfresco/ownable-services-context.xml
index a2bbab152b..9e2848e0c2 100644
--- a/config/alfresco/ownable-services-context.xml
+++ b/config/alfresco/ownable-services-context.xml
@@ -7,10 +7,13 @@
-
+
+
+
+
\ No newline at end of file
diff --git a/config/alfresco/public-services-security-context.xml b/config/alfresco/public-services-security-context.xml
index e09f634d42..6e0b4cc6d3 100644
--- a/config/alfresco/public-services-security-context.xml
+++ b/config/alfresco/public-services-security-context.xml
@@ -204,7 +204,7 @@
-
+
${system.acl.maxPermissionCheckTimeMillis}
diff --git a/config/alfresco/rule-services-context.xml b/config/alfresco/rule-services-context.xml
index b8e669c6c5..e8deb83ebe 100644
--- a/config/alfresco/rule-services-context.xml
+++ b/config/alfresco/rule-services-context.xml
@@ -101,6 +101,9 @@
+
+
+
@@ -166,7 +169,7 @@
-
+
false
diff --git a/source/java/org/alfresco/jcr/test/TestData.java b/source/java/org/alfresco/jcr/test/TestData.java
index c0b329f47e..ed0075cfb7 100644
--- a/source/java/org/alfresco/jcr/test/TestData.java
+++ b/source/java/org/alfresco/jcr/test/TestData.java
@@ -76,7 +76,7 @@ public class TestData
public Object execute() throws Exception
{
// Bootstrap Users
- MutableAuthenticationDao authDAO = (MutableAuthenticationDao) applicationContext.getBean("alfDaoImpl");
+ MutableAuthenticationDao authDAO = (MutableAuthenticationDao) applicationContext.getBean("authenticationDao");
if (authDAO.userExists("superuser") == false)
{
authDAO.createUser("superuser", "".toCharArray());
diff --git a/source/java/org/alfresco/repo/audit/AuditServiceTest.java b/source/java/org/alfresco/repo/audit/AuditServiceTest.java
index 05643eaa3e..1bfe1938e0 100644
--- a/source/java/org/alfresco/repo/audit/AuditServiceTest.java
+++ b/source/java/org/alfresco/repo/audit/AuditServiceTest.java
@@ -120,7 +120,7 @@ public class AuditServiceTest extends BaseSpringTest
authorityService = (AuthorityService) applicationContext.getBean("authorityService");
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
- authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("alfDaoImpl");
+ authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("authenticationDao");
auditService = (AuditService) applicationContext.getBean("AuditService");
auditEntry = (AuditEntry) applicationContext.getBean("auditModel");
diff --git a/source/java/org/alfresco/repo/avm/wf/AVMSubmitPackageHandler.java b/source/java/org/alfresco/repo/avm/wf/AVMSubmitPackageHandler.java
index 813fd26b91..622d9ce896 100644
--- a/source/java/org/alfresco/repo/avm/wf/AVMSubmitPackageHandler.java
+++ b/source/java/org/alfresco/repo/avm/wf/AVMSubmitPackageHandler.java
@@ -177,7 +177,7 @@ public class AVMSubmitPackageHandler
Map list = fAVMService.getDirectoryListing(desc, true);
for (AVMNodeDescriptor child : list.values())
{
- recursivelyRemoveLocks(webProject, child.getVersionID(), child.getPath());
+ recursivelyRemoveLocks(webProject, version, child.getPath());
}
}
}
diff --git a/source/java/org/alfresco/repo/content/metadata/xml/XPathMetadataExtracter.java b/source/java/org/alfresco/repo/content/metadata/xml/XPathMetadataExtracter.java
index f657bc76a4..bb59db11a9 100644
--- a/source/java/org/alfresco/repo/content/metadata/xml/XPathMetadataExtracter.java
+++ b/source/java/org/alfresco/repo/content/metadata/xml/XPathMetadataExtracter.java
@@ -57,6 +57,8 @@ import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
/**
* An extracter that pulls values from XML documents using configurable XPath
@@ -248,7 +250,30 @@ public class XPathMetadataExtracter extends AbstractMappingMetadataExtracter imp
String documentProperty = element.getKey();
XPathExpression xpathExpression = element.getValue();
// Execute it
- String value = (String) xpathExpression.evaluate(document, XPathConstants.STRING);
+ NodeList nodeList = (NodeList) xpathExpression.evaluate(document, XPathConstants.NODESET);
+ // Convert the value
+ Serializable value = null;
+ int nodeCount = nodeList.getLength();
+ if (nodeCount == 0)
+ {
+ // No result
+ }
+ else if (nodeCount == 1)
+ {
+ Node node = nodeList.item(0);
+ // Get the string value
+ value = node.getTextContent();
+ }
+ else
+ {
+ // Make a collection of the values
+ ArrayList stringValues = new ArrayList(5);
+ for (int i = 0; i < nodeCount; i++)
+ {
+ stringValues.add(nodeList.item(i).getTextContent());
+ }
+ value = stringValues;
+ }
// Put the value
rawProperties.put(documentProperty, value);
}
@@ -305,7 +330,7 @@ public class XPathMetadataExtracter extends AbstractMappingMetadataExtracter imp
xpathExpressionMapping.put(documentProperty, xpathExpression);
if (logger.isDebugEnabled())
{
- logger.debug("Added mapping from " + documentProperty + " to " + xpathExpression);
+ logger.debug("Added mapping from " + documentProperty + " to " + xpathStr);
}
}
// Done
diff --git a/source/java/org/alfresco/repo/ownable/impl/OwnableServiceImpl.java b/source/java/org/alfresco/repo/ownable/impl/OwnableServiceImpl.java
index 8ed945a724..81868d6a4c 100644
--- a/source/java/org/alfresco/repo/ownable/impl/OwnableServiceImpl.java
+++ b/source/java/org/alfresco/repo/ownable/impl/OwnableServiceImpl.java
@@ -26,49 +26,65 @@ package org.alfresco.repo.ownable.impl;
import java.io.Serializable;
import java.util.HashMap;
+import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.cache.SimpleCache;
+import org.alfresco.repo.node.NodeServicePolicies;
+import org.alfresco.repo.policy.JavaBehaviour;
+import org.alfresco.repo.policy.PolicyComponent;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.OwnableService;
+import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
+import org.alfresco.util.EqualsHelper;
import org.springframework.beans.factory.InitializingBean;
/**
- * Ownership service support. Use in permissions framework as dynamic authority.
+ * Ownership service support. Use in permissions framework as dynamic authority.
*
* @author Andy Hind
*/
-public class OwnableServiceImpl implements OwnableService, InitializingBean
+public class OwnableServiceImpl implements OwnableService, InitializingBean, NodeServicePolicies.OnAddAspectPolicy, NodeServicePolicies.OnUpdatePropertiesPolicy,
+ NodeServicePolicies.OnRemoveAspectPolicy, NodeServicePolicies.OnDeleteNodePolicy
{
private NodeService nodeService;
-
+
private AuthenticationService authenticationService;
-
+
private SimpleCache nodeOwnerCache;
+ private PolicyComponent policyComponent;
+
public OwnableServiceImpl()
{
super();
}
// IOC
-
+
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
-
+
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
-
+
+ public void setPolicyComponent(PolicyComponent policyComponent)
+ {
+ this.policyComponent = policyComponent;
+ }
+
/**
- * @param ownerCache a transactionally-safe cache of node owners
+ * @param ownerCache
+ * a transactionally-safe cache of node owners
*/
public void setNodeOwnerCache(SimpleCache ownerCache)
{
@@ -89,14 +105,31 @@ public class OwnableServiceImpl implements OwnableService, InitializingBean
{
throw new IllegalArgumentException("Property 'nodeOwnerCache' has not been set");
}
+ if (policyComponent == null)
+ {
+ throw new IllegalArgumentException("Property 'policyComponent' has not been set");
+ }
+
+ policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onAddAspect"), ContentModel.ASPECT_OWNABLE, new JavaBehaviour(this, "onAddAspect"));
+ policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"), ContentModel.ASPECT_OWNABLE, new JavaBehaviour(this, "onUpdateProperties"));
+ policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onRemoveAspect"), ContentModel.ASPECT_OWNABLE, new JavaBehaviour(this,
+ "onRemoveAspect"));
+ policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onDeleteNode"), ContentModel.ASPECT_OWNABLE, new JavaBehaviour(this, "onDeleteNode"));
+
+ policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onAddAspect"), ContentModel.ASPECT_AUDITABLE, new JavaBehaviour(this, "onAddAspect"));
+ policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"), ContentModel.ASPECT_AUDITABLE, new JavaBehaviour(this, "onUpdateProperties"));
+ policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onRemoveAspect"), ContentModel.ASPECT_AUDITABLE, new JavaBehaviour(this,
+ "onRemoveAspect"));
+ policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onDeleteNode"), ContentModel.ASPECT_AUDITABLE, new JavaBehaviour(this, "onDeleteNode"));
+
}
-
+
// OwnableService implmentation
-
+
public String getOwner(NodeRef nodeRef)
{
String userName = nodeOwnerCache.get(nodeRef);
-
+
if (userName == null)
{
// If ownership is not explicitly set then we fall back to the creator
@@ -104,13 +137,13 @@ public class OwnableServiceImpl implements OwnableService, InitializingBean
{
userName = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(nodeRef, ContentModel.PROP_OWNER));
}
- else if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_AUDITABLE))
+ else if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_AUDITABLE))
{
userName = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(nodeRef, ContentModel.PROP_CREATOR));
}
nodeOwnerCache.put(nodeRef, userName);
}
-
+
return userName;
}
@@ -138,4 +171,41 @@ public class OwnableServiceImpl implements OwnableService, InitializingBean
{
return getOwner(nodeRef) != null;
}
+
+ public void onAddAspect(NodeRef nodeRef, QName aspectTypeQName)
+ {
+ nodeOwnerCache.remove(nodeRef);
+ }
+
+ public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
+ {
+ nodeOwnerCache.remove(nodeRef);
+ }
+
+ public void onDeleteNode(ChildAssociationRef childAssocRef, boolean isNodeArchived)
+ {
+ nodeOwnerCache.remove(childAssocRef.getChildRef());
+ }
+
+ public void onUpdateProperties(NodeRef nodeRef, Map before, Map after)
+ {
+ Serializable pb = before.get(ContentModel.PROP_OWNER);
+ Serializable pa = after.get(ContentModel.PROP_OWNER);
+
+ if (!EqualsHelper.nullSafeEquals(pb, pa))
+ {
+ nodeOwnerCache.remove(nodeRef);
+ return;
+ }
+
+ pb = before.get(ContentModel.PROP_CREATOR);
+ pa = after.get(ContentModel.PROP_CREATOR);
+
+ if (!EqualsHelper.nullSafeEquals(pb, pa))
+ {
+ nodeOwnerCache.remove(nodeRef);
+ return;
+ }
+
+ }
}
diff --git a/source/java/org/alfresco/repo/ownable/impl/OwnableServiceTest.java b/source/java/org/alfresco/repo/ownable/impl/OwnableServiceTest.java
index c888393f2f..137340d3a3 100644
--- a/source/java/org/alfresco/repo/ownable/impl/OwnableServiceTest.java
+++ b/source/java/org/alfresco/repo/ownable/impl/OwnableServiceTest.java
@@ -24,6 +24,9 @@
*/
package org.alfresco.repo.ownable.impl;
+import java.io.Serializable;
+import java.util.HashMap;
+
import javax.transaction.UserTransaction;
import junit.framework.TestCase;
@@ -40,6 +43,7 @@ import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.OwnableService;
import org.alfresco.service.cmr.security.PermissionService;
+import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.springframework.context.ApplicationContext;
@@ -85,7 +89,7 @@ public class OwnableServiceTest extends TestCase
permissionService = (PermissionService) ctx.getBean("permissionService");
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
- authenticationDAO = (MutableAuthenticationDao) ctx.getBean("alfDaoImpl");
+ authenticationDAO = (MutableAuthenticationDao) ctx.getBean("authenticationDao");
TransactionService transactionService = (TransactionService) ctx.getBean(ServiceRegistry.TRANSACTION_SERVICE.getLocalName());
@@ -147,6 +151,14 @@ public class OwnableServiceTest extends TestCase
assertFalse(nodeService.hasAspect(testNode, ContentModel.ASPECT_OWNABLE));
assertTrue(dynamicAuthority.hasAuthority(testNode, "andy"));
+ assertEquals("andy", ownableService.getOwner(testNode));
+
+ nodeService.setProperty(testNode, ContentModel.PROP_CREATOR, "woof");
+ assertEquals("woof", ownableService.getOwner(testNode));
+
+ nodeService.setProperty(testNode, ContentModel.PROP_CREATOR, "andy");
+ assertEquals("andy", ownableService.getOwner(testNode));
+
permissionService.setInheritParentPermissions(testNode, false);
@@ -189,6 +201,16 @@ public class OwnableServiceTest extends TestCase
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(testNode, PermissionService.TAKE_OWNERSHIP));
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(testNode, PermissionService.SET_OWNER));
+ nodeService.setProperty(testNode, ContentModel.PROP_OWNER, "muppet");
+ assertEquals("muppet", ownableService.getOwner(testNode));
+ nodeService.removeAspect(testNode, ContentModel.ASPECT_OWNABLE);
+ assertEquals("andy", ownableService.getOwner(testNode));
+
+ HashMap aspectProperties = new HashMap();
+ aspectProperties.put(ContentModel.PROP_OWNER, "muppet");
+ nodeService.addAspect(testNode, ContentModel.ASPECT_OWNABLE, aspectProperties);
+ assertEquals("muppet", ownableService.getOwner(testNode));
+
}
diff --git a/source/java/org/alfresco/repo/rule/ruletrigger/OnContentUpdateRuleTrigger.java b/source/java/org/alfresco/repo/rule/ruletrigger/OnContentUpdateRuleTrigger.java
index f4a57af465..94ee0688db 100644
--- a/source/java/org/alfresco/repo/rule/ruletrigger/OnContentUpdateRuleTrigger.java
+++ b/source/java/org/alfresco/repo/rule/ruletrigger/OnContentUpdateRuleTrigger.java
@@ -26,9 +26,12 @@ package org.alfresco.repo.rule.ruletrigger;
import java.util.List;
+import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.ContentServicePolicies;
+import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.NodeRef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -87,9 +90,24 @@ public class OnContentUpdateRuleTrigger extends RuleTriggerAbstractBase
*/
public void onContentUpdate(NodeRef nodeRef, boolean newContent)
{
- if (newContent == this.onNewContent)
+
+ // Check the new content and make sure that we do indeed want to trigger the rule
+ boolean fail = false;
+ if (newContent == true)
+ {
+ ContentReader contentReader = this.contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
+ if (contentReader == null ||
+ contentReader.exists() == false ||
+ isZeroLengthOfficeDoc(contentReader) == true)
+ {
+ fail = true;
+ }
+ }
+
+ // Trigger the rules in the appropriate way
+ if (fail == false && newContent == this.onNewContent)
{
- if (triggerParentRules == true)
+ if (triggerParentRules == true)
{
if (logger.isDebugEnabled() == true)
{
@@ -108,5 +126,24 @@ public class OnContentUpdateRuleTrigger extends RuleTriggerAbstractBase
}
}
}
+
+ /**
+ * Indicates whether we are dealing with a zero length office document or not
+ *
+ * @param contentReader the content reader
+ * @return boolean true if zero length office document, false otherwise
+ */
+ private boolean isZeroLengthOfficeDoc(ContentReader contentReader)
+ {
+ boolean result = false;
+ if (contentReader.getSize() == 0 &&
+ (MimetypeMap.MIMETYPE_WORD.equals(contentReader.getMimetype()) == true ||
+ MimetypeMap.MIMETYPE_EXCEL.equals(contentReader.getMimetype()) == true ||
+ MimetypeMap.MIMETYPE_PPT.equals(contentReader.getMimetype()) == true))
+ {
+ result = true;
+ }
+ return result;
+ }
}
diff --git a/source/java/org/alfresco/repo/rule/ruletrigger/RuleTriggerAbstractBase.java b/source/java/org/alfresco/repo/rule/ruletrigger/RuleTriggerAbstractBase.java
index 3f905590da..9affdee83b 100644
--- a/source/java/org/alfresco/repo/rule/ruletrigger/RuleTriggerAbstractBase.java
+++ b/source/java/org/alfresco/repo/rule/ruletrigger/RuleTriggerAbstractBase.java
@@ -30,12 +30,13 @@ import java.util.Set;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.rule.RuleType;
/**
- * Rule trigger abstract base
+ * Rule trigger abstract base
*
* @author Roy Wetherall
*/
@@ -55,6 +56,11 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
* The node service
*/
protected NodeService nodeService;
+
+ /**
+ * The content service
+ */
+ protected ContentService contentService;
/**
* The authentication Component
@@ -91,6 +97,16 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
{
this.nodeService = nodeService;
}
+
+ /**
+ * Set the content service
+ *
+ * @param contentService the content service
+ */
+ public void setContentService(ContentService contentService)
+ {
+ this.contentService = contentService;
+ }
/**
* Set the authenticationComponent
@@ -123,6 +139,7 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
/**
* Registration of an interested rule type
+ *
*/
public void registerRuleType(RuleType ruleType)
{
@@ -131,7 +148,7 @@ public abstract class RuleTriggerAbstractBase implements RuleTrigger
/**
* Trigger the rules that relate to any interested rule types for the node
- * references passed.
+ * references passed.
*
* @param nodeRef
* the node reference who rules are to be triggered
diff --git a/source/java/org/alfresco/repo/search/SearchServiceTest.java b/source/java/org/alfresco/repo/search/SearchServiceTest.java
index 1a2cb079b9..6e30d0c463 100644
--- a/source/java/org/alfresco/repo/search/SearchServiceTest.java
+++ b/source/java/org/alfresco/repo/search/SearchServiceTest.java
@@ -98,7 +98,7 @@ public class SearchServiceTest extends TestCase
nodeService = (NodeService) ctx.getBean("dbNodeService");
authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
authenticationService = (AuthenticationService) ctx.getBean("authenticationService");
- authenticationDAO = (MutableAuthenticationDao) ctx.getBean("alfDaoImpl");
+ authenticationDAO = (MutableAuthenticationDao) ctx.getBean("authenticationDao");
pubSearchService = (SearchService) ctx.getBean("SearchService");
pubPermissionService = (PermissionService) ctx.getBean("PermissionService");
diff --git a/source/java/org/alfresco/repo/security/authentication/AbstractAuthenticationComponent.java b/source/java/org/alfresco/repo/security/authentication/AbstractAuthenticationComponent.java
index baa5b6b4e9..b7e31a3803 100644
--- a/source/java/org/alfresco/repo/security/authentication/AbstractAuthenticationComponent.java
+++ b/source/java/org/alfresco/repo/security/authentication/AbstractAuthenticationComponent.java
@@ -28,10 +28,6 @@ import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.UserDetails;
-import net.sf.acegisecurity.context.Context;
-import net.sf.acegisecurity.context.ContextHolder;
-import net.sf.acegisecurity.context.security.SecureContext;
-import net.sf.acegisecurity.context.security.SecureContextImpl;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import net.sf.acegisecurity.providers.dao.User;
@@ -46,11 +42,9 @@ import org.alfresco.service.cmr.security.PermissionService;
*/
public abstract class AbstractAuthenticationComponent implements AuthenticationComponent
{
-
- // Name of the system user
-
- static final String SYSTEM_USER_NAME = "System";
-
+ /**
+ * The abstract class keeps track of support for guest login
+ */
private Boolean allowGuestLogin = null;
public AbstractAuthenticationComponent()
@@ -58,6 +52,11 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
super();
}
+ /**
+ * Set if guest login is supported.
+ *
+ * @param allowGuestLogin
+ */
public void setAllowGuestLogin(Boolean allowGuestLogin)
{
this.allowGuestLogin = allowGuestLogin;
@@ -65,6 +64,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
public void authenticate(String userName, char[] password) throws AuthenticationException
{
+ // Support guest login from the login screen
if ((userName != null) && (userName.equalsIgnoreCase(PermissionService.GUEST_AUTHORITY)))
{
setGuestUserAsCurrentUser();
@@ -75,6 +75,14 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
}
}
+ /**
+ * Default unsupported authentication implementation
+ * - as of 2.1 this is the best way to implement your own authentication component as it will support guest login
+ * - prior to this direct over ride for authenticate(String , char[]) was used. This will still work.
+ *
+ * @param userName
+ * @param password
+ */
protected void authenticateImpl(String userName, char[] password)
{
throw new UnsupportedOperationException();
@@ -97,11 +105,11 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
try
{
UserDetails ud = null;
- if (userName.equals(SYSTEM_USER_NAME))
+ if (userName.equals(AuthenticationUtil.SYSTEM_USER_NAME))
{
GrantedAuthority[] gas = new GrantedAuthority[1];
gas[0] = new GrantedAuthorityImpl("ROLE_SYSTEM");
- ud = new User(SYSTEM_USER_NAME, "", true, true, true, true, gas);
+ ud = new User(AuthenticationUtil.SYSTEM_USER_NAME, "", true, true, true, true, gas);
}
else if (userName.equalsIgnoreCase(PermissionService.GUEST_AUTHORITY))
{
@@ -173,28 +181,6 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
return AuthenticationUtil.getCurrentUserName();
}
- /**
- * Get the current user name
- *
- * @param authentication
- * Authentication
- * @return String
- */
- private String getUserName(Authentication authentication)
- {
- String username;
- if (authentication.getPrincipal() instanceof UserDetails)
- {
- username = ((UserDetails) authentication.getPrincipal()).getUsername();
- }
- else
- {
- username = authentication.getPrincipal().toString();
- }
-
- return username;
- }
-
/**
* Set the system user as the current user.
*
@@ -202,7 +188,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
*/
public Authentication setSystemUserAsCurrentUser()
{
- return setCurrentUser(SYSTEM_USER_NAME);
+ return setCurrentUser(AuthenticationUtil.SYSTEM_USER_NAME);
}
/**
@@ -212,7 +198,7 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
*/
public String getSystemUserName()
{
- return SYSTEM_USER_NAME;
+ return AuthenticationUtil.SYSTEM_USER_NAME;
}
/**
diff --git a/source/java/org/alfresco/repo/security/authentication/AuthenticationTest.java b/source/java/org/alfresco/repo/security/authentication/AuthenticationTest.java
index 23f345cdd5..7e28fa99aa 100644
--- a/source/java/org/alfresco/repo/security/authentication/AuthenticationTest.java
+++ b/source/java/org/alfresco/repo/security/authentication/AuthenticationTest.java
@@ -135,7 +135,7 @@ public class AuthenticationTest extends TestCase
// ctx.getBean("permissionService");
ticketsCache = (SimpleCache) ctx.getBean("ticketsCache");
- dao = (MutableAuthenticationDao) ctx.getBean("alfDaoImpl");
+ dao = (MutableAuthenticationDao) ctx.getBean("authenticationDao");
authenticationManager = (AuthenticationManager) ctx.getBean("authenticationManager");
saltSource = (SaltSource) ctx.getBean("saltSource");
diff --git a/source/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java b/source/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java
index a83ef0a637..65fef412a8 100644
--- a/source/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java
+++ b/source/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java
@@ -231,7 +231,6 @@ public abstract class AuthenticationUtil
private static String getUserName(Authentication authentication)
{
String username;
-
if (authentication.getPrincipal() instanceof UserDetails)
{
username = ((UserDetails) authentication.getPrincipal()).getUsername();
diff --git a/source/java/org/alfresco/repo/security/authentication/ChainingAuthenticationComponentImpl.java b/source/java/org/alfresco/repo/security/authentication/ChainingAuthenticationComponentImpl.java
new file mode 100644
index 0000000000..74cf50fdce
--- /dev/null
+++ b/source/java/org/alfresco/repo/security/authentication/ChainingAuthenticationComponentImpl.java
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.security.authentication;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sf.acegisecurity.Authentication;
+
+import org.alfresco.service.cmr.security.PermissionService;
+
+/**
+ * A chaining authentication component is required for all the beans that qire up an authentication component and not an
+ * authentication service. It supports chaining in much the same way and wires up components in the same way asthe
+ * chaining authentication service wires up services.
+ *
+ * @author andyh
+ */
+public class ChainingAuthenticationComponentImpl implements AuthenticationComponent
+{
+ /**
+ * NLTM authentication mode - if unset - finds the first component that supports NTLM - if set - finds the first
+ * component that supports the specified mode.
+ */
+ private NTLMMode ntlmMode = null;
+
+ /**
+ * The authentication components
+ */
+ private List authenticationComponents;
+
+ /**
+ * An authentication service that supports change (as wired in to the authentication service). It is never used for
+ * change it is to ensure it is at the top of the list (as required by the chaining authentication service)
+ */
+ private AuthenticationComponent mutableAuthenticationComponent;
+
+ /**
+ * Get the authentication components
+ *
+ * @return - a list of authentication components
+ */
+ public List getAuthenticationComponents()
+ {
+ return authenticationComponents;
+ }
+
+ /**
+ * Set a list of authentication components
+ *
+ * @param authenticationComponents
+ */
+ public void setAuthenticationComponents(List authenticationComponents)
+ {
+ this.authenticationComponents = authenticationComponents;
+ }
+
+ /**
+ * Get the authentication service thta must be at the top of the list (this may be null)
+ *
+ * @return
+ */
+ public AuthenticationComponent getMutableAuthenticationComponent()
+ {
+ return mutableAuthenticationComponent;
+ }
+
+ /**
+ * Set the authentication component at the top of the list.
+ *
+ * @param mutableAuthenticationComponent
+ */
+ public void setMutableAuthenticationComponent(AuthenticationComponent mutableAuthenticationComponent)
+ {
+ this.mutableAuthenticationComponent = mutableAuthenticationComponent;
+ }
+
+
+
+ public void setNtlmMode(NTLMMode ntlmMode)
+ {
+ this.ntlmMode = ntlmMode;
+ }
+
+ /**
+ * Chain authentication with user name and password - tries all in order until one works, or fails.
+ */
+ public void authenticate(String userName, char[] password) throws AuthenticationException
+ {
+ for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
+ {
+ try
+ {
+ authComponent.authenticate(userName, password);
+ return;
+ }
+ catch (AuthenticationException e)
+ {
+ // Ignore and chain
+ }
+ }
+ throw new AuthenticationException("Failed to authenticate");
+ }
+
+ /**
+ * NTLM passthrough authentication - if a mode is defined - the first PASS_THROUGH provider is used - if not, the
+ * first component that supports NTLM is used if it supports PASS_THROUGH
+ */
+ public Authentication authenticate(Authentication token) throws AuthenticationException
+ {
+ if (ntlmMode != null)
+ {
+ switch (ntlmMode)
+ {
+ case NONE:
+ throw new AuthenticationException("NTLM is not supported");
+ case MD4_PROVIDER:
+ throw new AuthenticationException("NTLM passthrough is not supported then configured for MD4 hashing");
+ case PASS_THROUGH:
+ for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
+ {
+ if (authComponent.getNTLMMode() == NTLMMode.PASS_THROUGH)
+ {
+ return authComponent.authenticate(token);
+ }
+ }
+ throw new AuthenticationException("No NTLM passthrough authentication to use");
+ default:
+ throw new AuthenticationException("No NTLM passthrough authentication to use");
+ }
+ }
+ else
+ {
+ for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
+ {
+ if (authComponent.getNTLMMode() != NTLMMode.NONE)
+ {
+ if (authComponent.getNTLMMode() == NTLMMode.PASS_THROUGH)
+ {
+ return authComponent.authenticate(token);
+ }
+ else
+ {
+ throw new AuthenticationException("The first authentication component to support NTLM supports MD4 hashing");
+ }
+ }
+ }
+ throw new AuthenticationException("No NTLM passthrough authentication to use");
+ }
+
+ }
+
+ /**
+ * Clear the security context
+ */
+ public void clearCurrentSecurityContext()
+ {
+ AuthenticationUtil.clearCurrentSecurityContext();
+ }
+
+ /**
+ * Get the current authentication
+ */
+ public Authentication getCurrentAuthentication() throws AuthenticationException
+ {
+ return AuthenticationUtil.getCurrentAuthentication();
+ }
+
+ /**
+ * Get the current user name
+ */
+ public String getCurrentUserName() throws AuthenticationException
+ {
+ return AuthenticationUtil.getCurrentUserName();
+ }
+
+ /**
+ * Get the guest user name
+ */
+ public String getGuestUserName()
+ {
+ return PermissionService.GUEST_AUTHORITY.toLowerCase();
+ }
+
+ /**
+ * Get the MD4 password hash
+ */
+ public String getMD4HashedPassword(String userName)
+ {
+ if (ntlmMode != null)
+ {
+ switch (ntlmMode)
+ {
+ case NONE:
+ throw new AuthenticationException("NTLM is not supported");
+ case PASS_THROUGH:
+ throw new AuthenticationException("NTLM passthrough is not supported then configured for MD4 hashing");
+ case MD4_PROVIDER:
+ for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
+ {
+ if (authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
+ {
+ return authComponent.getMD4HashedPassword(userName);
+ }
+ }
+ throw new AuthenticationException("No MD4 provider available");
+ default:
+ throw new AuthenticationException("No MD4 provider available");
+ }
+ }
+ else
+ {
+ for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
+ {
+ if (authComponent.getNTLMMode() != NTLMMode.NONE)
+ {
+ if (authComponent.getNTLMMode() == NTLMMode.PASS_THROUGH)
+ {
+ throw new AuthenticationException("The first authentication component to support NTLM supports passthrough");
+ }
+ else
+ {
+ return authComponent.getMD4HashedPassword(userName);
+ }
+ }
+ }
+ throw new AuthenticationException("No MD4 provider available");
+ }
+
+ }
+
+ /**
+ * Get the NTLM mode - this is only what is set if one of the implementations provides support for that mode.
+ */
+ public NTLMMode getNTLMMode()
+ {
+ if (ntlmMode != null)
+ {
+ switch (ntlmMode)
+ {
+ case NONE:
+ return NTLMMode.NONE;
+ case PASS_THROUGH:
+ for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
+ {
+ if (authComponent.getNTLMMode() == NTLMMode.PASS_THROUGH)
+ {
+ return NTLMMode.PASS_THROUGH;
+ }
+ }
+ return NTLMMode.NONE;
+ case MD4_PROVIDER:
+ for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
+ {
+ if (authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
+ {
+ return NTLMMode.MD4_PROVIDER;
+ }
+ }
+ return NTLMMode.NONE;
+ default:
+ return NTLMMode.NONE;
+ }
+ }
+ else
+ {
+ for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
+ {
+ if (authComponent.getNTLMMode() != NTLMMode.NONE)
+ {
+ return authComponent.getNTLMMode();
+ }
+ }
+ return NTLMMode.NONE;
+ }
+ }
+
+ /**
+ * Get the system user name
+ */
+ public String getSystemUserName()
+ {
+ return AuthenticationUtil.SYSTEM_USER_NAME;
+ }
+
+ /**
+ * If any implementation supoprts guest then huest is allowed
+ */
+ public boolean guestUserAuthenticationAllowed()
+ {
+ for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
+ {
+ if (authComponent.guestUserAuthenticationAllowed())
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Ste the current authentication
+ */
+ public Authentication setCurrentAuthentication(Authentication authentication)
+ {
+ return AuthenticationUtil.setCurrentAuthentication(authentication);
+ }
+
+ /**
+ * Set the current user - try all implementations - as some may check the user exists
+ */
+ public Authentication setCurrentUser(String userName)
+ {
+ for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
+ {
+ try
+ {
+ return authComponent.setCurrentUser(userName);
+ }
+ catch (AuthenticationException e)
+ {
+ // Ignore and chain
+ }
+ }
+ throw new AuthenticationException("Failed to set current user " + userName);
+ }
+
+ /**
+ * Authenticate as guest - try all in the cahin
+ */
+ public Authentication setGuestUserAsCurrentUser()
+ {
+ for (AuthenticationComponent authComponent : getUsableAuthenticationComponents())
+ {
+ try
+ {
+ return authComponent.setGuestUserAsCurrentUser();
+ }
+ catch (AuthenticationException e)
+ {
+ // Ignore and chain
+ }
+ }
+ throw new AuthenticationException("Guest authentication is not allowed");
+ }
+
+ /**
+ * Set the system user
+ */
+ public Authentication setSystemUserAsCurrentUser()
+ {
+ return setCurrentUser(getSystemUserName());
+ }
+
+ /**
+ * Helper to get authentication components
+ *
+ * @return
+ */
+ private List getUsableAuthenticationComponents()
+ {
+ if (mutableAuthenticationComponent == null)
+ {
+ return authenticationComponents;
+ }
+ else
+ {
+ ArrayList services = new ArrayList(authenticationComponents == null ? 1 : (authenticationComponents.size() + 1));
+ services.add(mutableAuthenticationComponent);
+ if (authenticationComponents != null)
+ {
+ services.addAll(authenticationComponents);
+ }
+ return services;
+ }
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/security/authority/SimpleAuthorityServiceTest.java b/source/java/org/alfresco/repo/security/authority/SimpleAuthorityServiceTest.java
index a5663cd9cf..a7dcb1e0f7 100644
--- a/source/java/org/alfresco/repo/security/authority/SimpleAuthorityServiceTest.java
+++ b/source/java/org/alfresco/repo/security/authority/SimpleAuthorityServiceTest.java
@@ -72,7 +72,7 @@ public class SimpleAuthorityServiceTest extends TestCase
authorityService = (AuthorityService) ctx.getBean("authorityService");
pubAuthorityService = (AuthorityService) ctx.getBean("AuthorityService");
personService = (PersonService) ctx.getBean("personService");
- authenticationDAO = (MutableAuthenticationDao) ctx.getBean("alfDaoImpl");
+ authenticationDAO = (MutableAuthenticationDao) ctx.getBean("authenticationDao");
this.authenticationComponent.setSystemUserAsCurrentUser();
diff --git a/source/java/org/alfresco/repo/security/permissions/dynamic/LockOwnerDynamicAuthorityTest.java b/source/java/org/alfresco/repo/security/permissions/dynamic/LockOwnerDynamicAuthorityTest.java
index 06fbc55505..d6f48fe8b7 100644
--- a/source/java/org/alfresco/repo/security/permissions/dynamic/LockOwnerDynamicAuthorityTest.java
+++ b/source/java/org/alfresco/repo/security/permissions/dynamic/LockOwnerDynamicAuthorityTest.java
@@ -90,7 +90,7 @@ public class LockOwnerDynamicAuthorityTest extends TestCase
authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
lockService = (LockService) ctx.getBean("lockService");
permissionService = (PermissionService) ctx.getBean("permissionService");
- authenticationDAO = (MutableAuthenticationDao) ctx.getBean("alfDaoImpl");
+ authenticationDAO = (MutableAuthenticationDao) ctx.getBean("authenticationDao");
checkOutCheckInService = (CheckOutCheckInService) ctx.getBean("checkOutCheckInService");
ownableService = (OwnableService) ctx.getBean("ownableService");
diff --git a/source/java/org/alfresco/repo/security/permissions/impl/AbstractPermissionTest.java b/source/java/org/alfresco/repo/security/permissions/impl/AbstractPermissionTest.java
index c4a9065ae4..07bf39195a 100644
--- a/source/java/org/alfresco/repo/security/permissions/impl/AbstractPermissionTest.java
+++ b/source/java/org/alfresco/repo/security/permissions/impl/AbstractPermissionTest.java
@@ -102,7 +102,7 @@ public class AbstractPermissionTest extends BaseSpringTest
authorityService = (AuthorityService) applicationContext.getBean("authorityService");
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
- authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("alfDaoImpl");
+ authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("authenticationDao");
StoreRef storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.nanoTime());
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 5bd47bead8..2034d2c51f 100644
--- a/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceImpl.java
+++ b/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceImpl.java
@@ -70,8 +70,8 @@ import org.springframework.beans.factory.InitializingBean;
public class PermissionServiceImpl implements PermissionServiceSPI, InitializingBean
{
- static SimplePermissionReference OLD_ALL_PERMISSIONS_REFERENCE = new SimplePermissionReference(QName.createQName(
- "", PermissionService.ALL_PERMISSIONS), PermissionService.ALL_PERMISSIONS);
+ static SimplePermissionReference OLD_ALL_PERMISSIONS_REFERENCE = new SimplePermissionReference(QName.createQName("", PermissionService.ALL_PERMISSIONS),
+ PermissionService.ALL_PERMISSIONS);
private static Log log = LogFactory.getLog(PermissionServiceImpl.class);
@@ -228,8 +228,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
throw new IllegalArgumentException("Property 'policyComponent' has not been set");
}
- policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onMoveNode"),
- ContentModel.TYPE_BASE, new JavaBehaviour(this, "onMoveNode"));
+ policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onMoveNode"), ContentModel.TYPE_BASE, new JavaBehaviour(this, "onMoveNode"));
}
@@ -263,8 +262,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
NodePermissionEntry nodePremissionEntry = getSetPermissions(nodeRef);
for (PermissionEntry pe : nodePremissionEntry.getPermissionEntries())
{
- accessPermissions.add(new AccessPermissionImpl(getPermission(pe.getPermissionReference()), pe
- .getAccessStatus(), pe.getAuthority()));
+ accessPermissions.add(new AccessPermissionImpl(getPermission(pe.getPermissionReference()), pe.getAccessStatus(), pe.getAuthority()));
}
return accessPermissions;
}
@@ -390,8 +388,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
if (log.isDebugEnabled())
{
log.debug("Permission <"
- + perm + "> is " + (result ? "allowed" : "denied") + " for "
- + authenticationComponent.getCurrentUserName() + " on node " + nodeService.getPath(nodeRef));
+ + perm + "> is " + (result ? "allowed" : "denied") + " for " + authenticationComponent.getCurrentUserName() + " on node " + nodeService.getPath(nodeRef));
}
status = result ? AccessStatus.ALLOWED : AccessStatus.DENIED;
@@ -649,21 +646,16 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
// Set the required node permissions
if (required.equals(getPermissionReference(ALL_PERMISSIONS)))
{
- nodeRequirements = modelDAO.getRequiredPermissions(
- getPermissionReference(PermissionService.FULL_CONTROL), typeQName, aspectQNames,
- RequiredPermission.On.NODE);
+ nodeRequirements = modelDAO.getRequiredPermissions(getPermissionReference(PermissionService.FULL_CONTROL), typeQName, aspectQNames, RequiredPermission.On.NODE);
}
else
{
- nodeRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames,
- RequiredPermission.On.NODE);
+ nodeRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames, RequiredPermission.On.NODE);
}
- parentRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames,
- RequiredPermission.On.PARENT);
+ parentRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames, RequiredPermission.On.PARENT);
- childrenRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames,
- RequiredPermission.On.CHILDREN);
+ childrenRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames, RequiredPermission.On.CHILDREN);
// Find all the permissions that grant the allowed permission
// All permissions are treated specially.
@@ -695,8 +687,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
* @param recursiveIn
* @return
*/
- boolean evaluate(Set authorisations, NodeRef nodeRef, Set> denied,
- MutableBoolean recursiveIn)
+ boolean evaluate(Set authorisations, NodeRef nodeRef, Set> denied, MutableBoolean recursiveIn)
{
// Do we defer our required test to a parent (yes if not null)
MutableBoolean recursiveOut = null;
@@ -771,8 +762,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
if (pr.equals(required))
{
// Recursive permission
- success &= this.evaluate(authorisations, car.getParentRef(), locallyDenied,
- recursiveOut);
+ success &= this.evaluate(authorisations, car.getParentRef(), locallyDenied, recursiveOut);
if ((recursiveOut != null) && recursiveOut.getValue())
{
if (recursiveIn != null)
@@ -848,8 +838,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
}
- public boolean hasSinglePermission(Set authorisations, NodeRef nodeRef,
- Set> denied)
+ public boolean hasSinglePermission(Set authorisations, NodeRef nodeRef, Set> denied)
{
nodeRef = tenantService.getName(nodeRef);
@@ -974,8 +963,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
// All the sets that grant this permission must be
// denied
// Note that granters includes the orginal permission
- Set granters = modelDAO
- .getGrantingPermissions(pe.getPermissionReference());
+ Set granters = modelDAO.getGrantingPermissions(pe.getPermissionReference());
for (PermissionReference granter : granters)
{
deniedSet.add(new Pair(pe.getAuthority(), granter));
@@ -991,8 +979,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
// All permission excludes all permissions available for
// the node.
- if (pe.getPermissionReference().equals(getAllPermissionReference())
- || pe.getPermissionReference().equals(OLD_ALL_PERMISSIONS_REFERENCE))
+ if (pe.getPermissionReference().equals(getAllPermissionReference()) || pe.getPermissionReference().equals(OLD_ALL_PERMISSIONS_REFERENCE))
{
for (PermissionReference deny : modelDAO.getAllPermissions(nodeRef))
{
@@ -1048,8 +1035,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
* the set of denied permissions/authority pais
* @return
*/
- private boolean isGranted(PermissionEntry pe, Set authorisations,
- Set> denied)
+ private boolean isGranted(PermissionEntry pe, Set authorisations, Set> denied)
{
// If the permission entry denies then we just deny
if (pe.isDenied())
@@ -1059,16 +1045,41 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
// The permission is allowed but we deny it as it is in the denied
// set
+
if (denied != null)
{
- Pair specific = new Pair(pe.getAuthority(),
- required);
+ Pair specific = new Pair(pe.getAuthority(), required);
if (denied.contains(specific))
{
return false;
}
}
+ // any deny denies
+
+ if (false)
+ {
+ if (denied != null)
+ {
+ for (String auth : authorisations)
+ {
+ Pair specific = new Pair(auth, required);
+ if (denied.contains(specific))
+ {
+ return false;
+ }
+ for (PermissionReference perm : granters)
+ {
+ specific = new Pair(auth, perm);
+ if (denied.contains(specific))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
// If the permission has a match in both the authorities and
// granters list it is allowed
// It applies to the current user and it is granted
@@ -1124,8 +1135,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
return false;
}
Pair other = (Pair) o;
- return EqualsHelper.nullSafeEquals(this.getA(), other.getA())
- && EqualsHelper.nullSafeEquals(this.getB(), other.getB());
+ return EqualsHelper.nullSafeEquals(this.getA(), other.getA()) && EqualsHelper.nullSafeEquals(this.getB(), other.getB());
}
@Override
@@ -1167,15 +1177,13 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
return permissionsDaoComponent.getAllSetPermissions(authority);
}
- public Set findNodesByAssignedPermissionForCurrentUser(String permission, boolean allow, boolean includeContainingAuthorities,
- boolean exactPermissionMatch)
+ public Set findNodesByAssignedPermissionForCurrentUser(String permission, boolean allow, boolean includeContainingAuthorities, boolean exactPermissionMatch)
{
String currentUser = authenticationComponent.getCurrentUserName();
return findNodesByAssignedPermission(currentUser, permission, allow, includeContainingAuthorities, exactPermissionMatch);
}
- public Set findNodesByAssignedPermission(String authority, String permission, boolean allow,
- boolean includeContainingAuthorities, boolean includeContainingPermissions)
+ public Set findNodesByAssignedPermission(String authority, String permission, boolean allow, boolean includeContainingAuthorities, boolean includeContainingPermissions)
{
// TODO: owned nodes and add owner rights ??
// Does not include dynamic permissions (they would have to be done by query - e.g. owership and OWNER rights)
diff --git a/source/java/org/alfresco/repo/version/BaseVersionStoreTest.java b/source/java/org/alfresco/repo/version/BaseVersionStoreTest.java
index a6cfb5e9ca..7d92be6f87 100644
--- a/source/java/org/alfresco/repo/version/BaseVersionStoreTest.java
+++ b/source/java/org/alfresco/repo/version/BaseVersionStoreTest.java
@@ -149,7 +149,7 @@ public abstract class BaseVersionStoreTest extends BaseSpringTest
this.authenticationService = (AuthenticationService)applicationContext.getBean("authenticationService");
this.transactionService = (TransactionService)this.applicationContext.getBean("transactionComponent");
this.txnHelper = (RetryingTransactionHelper) applicationContext.getBean("retryingTransactionHelper");
- this.authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("alfDaoImpl");
+ this.authenticationDAO = (MutableAuthenticationDao) applicationContext.getBean("authenticationDao");
this.nodeArchiveService = (NodeArchiveService) applicationContext.getBean("nodeArchiveService");
this.nodeService = (NodeService)applicationContext.getBean("nodeService");
diff --git a/source/test-resources/xml-metadata/eclipse-project-mappings.properties b/source/test-resources/xml-metadata/eclipse-project-mappings.properties
index c68df82456..23ca69a138 100644
--- a/source/test-resources/xml-metadata/eclipse-project-mappings.properties
+++ b/source/test-resources/xml-metadata/eclipse-project-mappings.properties
@@ -5,7 +5,11 @@
# Namespaces
namespace.prefix.cm=http://www.alfresco.org/model/content/1.0
+namespace.prefix.test=http://www.alfresco.org/model/test/1.0
# Mappings
name=cm:title
description=cm:description
+multi-value-text=test:multi-value-text
+multi-value-node=test:multi-value-node
+complex-node=test:complex-node
diff --git a/source/test-resources/xml-metadata/eclipse-project-xpath-mappings.properties b/source/test-resources/xml-metadata/eclipse-project-xpath-mappings.properties
index 3299d1ffea..15f384d335 100644
--- a/source/test-resources/xml-metadata/eclipse-project-xpath-mappings.properties
+++ b/source/test-resources/xml-metadata/eclipse-project-xpath-mappings.properties
@@ -8,3 +8,6 @@
# Mappings
name=/projectDescription/name/text()
description=/projectDescription/comment/text()
+multi-value-text=/projectDescription/natures/nature/text()
+multi-value-node=/projectDescription/natures/nature
+complex-node=/projectDescription/natures
\ No newline at end of file