RM: Policy refactor

* moved policy implementations out of RMEntryVoter and into separate classes
 * rather than being a hard coded list, policies are now registered via spring allowing others to be easily added
 * re-arrange some of the support implementation
 * RMEntryVoter is now significantly smaller and most of the logic that was once encapsulated in here is spread over supporting classes and services
 * TODO .. need to review policies and determine which are appropraite .. much easier to do now!



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@48815 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2013-04-04 00:09:06 +00:00
parent 13d4f3f576
commit 05a40e014d
23 changed files with 1146 additions and 757 deletions

View File

@@ -78,6 +78,7 @@
<!-- Import fixed permission definitions for RM -->
<import resource="classpath:alfresco/module/org_alfresco_module_rm/rm-public-services-security-context.xml"/>
<import resource="classpath:alfresco/module/org_alfresco_module_rm/security/rm-method-security-context.xml"/>
<import resource="classpath:alfresco/module/org_alfresco_module_rm/security/rm-policy-context.xml"/>
<!-- Import the RM service's -->
<import resource="classpath:alfresco/module/org_alfresco_module_rm/rm-service-context.xml"/>

View File

@@ -14,7 +14,6 @@
abstract="true"
parent="RMSecurityCommon"
init-method="init">
<property name="voter" ref="rmEntryVoter"/>
<property name="capabilityService" ref="CapabilityService"/>
</bean>

View File

@@ -93,10 +93,7 @@
lazy-init="false"
parent="RMSecurityCommon"
depends-on="CapabilityService">
<!-- Services -->
<property name="namespacePrefixResolver" ref="namespaceService"/>
<property name="dictionaryService" ref="dictionaryService"/>
<property name="dispositionService" ref="dispositionService"/>
<property name="capabilityService" ref="capabilityService"/>
</bean>

View File

@@ -15,6 +15,6 @@
<bean id="rm-method-security-post-processor" class="org.alfresco.module.org_alfresco_module_rm.security.RMMethodSecurityPostProcessor">
<property name="properties" ref="rm-method-security-properties"/>
</bean>
</bean>
</beans>

View File

@@ -0,0 +1,55 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<bean id="basePolicy" abstract="true" parent="RMSecurityCommon" init-method="init">
<property name="capabilityService" ref="capabilityService" />
<property name="rmEntryVoter" ref="rmEntryVoter" />
</bean>
<bean id="readPolicy" parent="basePolicy" class="org.alfresco.module.org_alfresco_module_rm.capability.policy.ReadPolicy">
<property name="name" value="Read"/>
</bean>
<bean id="createPolicy" parent="basePolicy" class="org.alfresco.module.org_alfresco_module_rm.capability.policy.CreatePolicy">
<property name="name" value="Create"/>
</bean>
<bean id="movePolicy" parent="basePolicy" class="org.alfresco.module.org_alfresco_module_rm.capability.policy.MovePolicy">
<property name="name" value="Move"/>
</bean>
<bean id="updatePolicy" parent="basePolicy" class="org.alfresco.module.org_alfresco_module_rm.capability.policy.UpdatePolicy">
<property name="name" value="Update"/>
</bean>
<bean id="deletePolicy" parent="basePolicy" class="org.alfresco.module.org_alfresco_module_rm.capability.policy.DeletePolicy">
<property name="name" value="Delete"/>
</bean>
<bean id="updatePropertiesPolicy" parent="basePolicy" class="org.alfresco.module.org_alfresco_module_rm.capability.policy.UpdatePropertiesPolicy">
<property name="name" value="UpdateProperties"/>
</bean>
<bean id="assocPolicy" parent="basePolicy" class="org.alfresco.module.org_alfresco_module_rm.capability.policy.AssocPolicy">
<property name="name" value="Assoc"/>
</bean>
<bean id="writeContentPolicy" parent="basePolicy" class="org.alfresco.module.org_alfresco_module_rm.capability.policy.WriteContentPolicy">
<property name="name" value="WriteContent"/>
</bean>
<bean id="capabilityPolicy" parent="basePolicy" class="org.alfresco.module.org_alfresco_module_rm.capability.policy.CapabilityPolicy">
<property name="name" value="Capability"/>
</bean>
<bean id="declarePolicy" parent="basePolicy" class="org.alfresco.module.org_alfresco_module_rm.capability.policy.DeclarePolicy">
<property name="name" value="Declare"/>
</bean>
<bean id="readPropertyPolicy" parent="basePolicy" class="org.alfresco.module.org_alfresco_module_rm.capability.policy.ReadPropertyPolicy">
<property name="name" value="ReadProperty"/>
</bean>
</beans>

View File

@@ -41,9 +41,6 @@ public abstract class AbstractCapability extends RMSecurityCommon
@SuppressWarnings("unused")
private static Log logger = LogFactory.getLog(AbstractCapability.class);
/** RM entry voter */
protected RMEntryVoter voter;
/** Capability service */
protected CapabilityService capabilityService;
@@ -63,14 +60,6 @@ public abstract class AbstractCapability extends RMSecurityCommon
/** Indicates whether this is a private capability or not */
protected boolean isPrivate = false;
/**
* @param voter RM entry voter
*/
public void setVoter(RMEntryVoter voter)
{
this.voter = voter;
}
/**
* @param capabilityService capability service
*/

View File

@@ -18,41 +18,23 @@
*/
package org.alfresco.module.org_alfresco_module_rm.capability;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.ConfigAttribute;
import net.sf.acegisecurity.ConfigAttributeDefinition;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService;
import org.alfresco.module.org_alfresco_module_rm.capability.impl.CreateCapability;
import org.alfresco.module.org_alfresco_module_rm.capability.impl.UpdateCapability;
import org.alfresco.module.org_alfresco_module_rm.capability.impl.UpdatePropertiesCapability;
import org.alfresco.module.org_alfresco_module_rm.caveat.RMCaveatConfigComponent;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.capability.policy.ConfigAttributeDefinition;
import org.alfresco.module.org_alfresco_module_rm.capability.policy.Policy;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
import org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterException;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.AssociationRef;
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.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.OwnableService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -66,60 +48,34 @@ public class RMEntryVoter extends RMSecurityCommon
{
private static Log logger = LogFactory.getLog(RMEntryVoter.class);
private static final String RM = "RM";
private static final String RM_ALLOW = "RM_ALLOW";
private static final String RM_DENY = "RM_DENY";
private static final String RM_CAP = "RM_CAP";
private static final String RM_ABSTAIN = "RM_ABSTAIN";
private static final String RM_QUERY = "RM_QUERY";
private NamespacePrefixResolver nspr;
private NodeService nodeService;
private PermissionService permissionService;
private RMCaveatConfigComponent caveatConfigComponent;
private DictionaryService dictionaryService;
private RecordsManagementService recordsManagementService;
private DispositionService dispositionService;
private NamespacePrefixResolver nspr;
private SearchService searchService;
private OwnableService ownableService;
private CapabilityService capabilityService;
private static HashMap<String, Policy> policies = new HashMap<String, Policy>();
private HashMap<String, Policy> policies = new HashMap<String, Policy>();
static
// static
// {
// policies.put("Read", new ReadPolicy());
// policies.put("Create", new CreatePolicy());
// policies.put("Move", new MovePolicy());
// policies.put("Update", new UpdatePolicy());
// policies.put("Delete", new DeletePolicy());
// policies.put("UpdateProperties", new UpdatePropertiesPolicy());
// policies.put("Assoc", new AssocPolicy());
// policies.put("WriteContent", new WriteContentPolicy());
// policies.put("Capability", new CapabilityPolicy());
// policies.put("Declare", new DeclarePolicy());
// policies.put("ReadProperty", new ReadPropertyPolicy());
// }
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
policies.put("Read", new ReadPolicy());
policies.put("Create", new CreatePolicy());
policies.put("Move", new MovePolicy());
policies.put("Update", new UpdatePolicy());
policies.put("Delete", new DeletePolicy());
policies.put("UpdateProperties", new UpdatePropertiesPolicy());
policies.put("Assoc", new AssocPolicy());
policies.put("WriteContent", new WriteContentPolicy());
policies.put("Capability", new CapabilityPolicy());
policies.put("Declare", new DeclarePolicy());
policies.put("ReadProperty", new ReadPropertyPolicy());
}
/**
* Set the permission service
*
* @param permissionService
*/
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
/**
* Set the node service
*
* @param nodeService
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
this.applicationContext = applicationContext;
}
/**
@@ -144,6 +100,7 @@ public class RMEntryVoter extends RMSecurityCommon
}
/**
*
* @return
*/
public OwnableService getOwnableService()
@@ -164,23 +121,27 @@ public class RMEntryVoter extends RMSecurityCommon
{
this.nspr = nspr;
}
public void setCaveatConfigComponent(RMCaveatConfigComponent caveatConfigComponent)
/**
* Register a policy the voter
*
* @param policy policy
*/
public void registerPolicy(Policy policy)
{
this.caveatConfigComponent = caveatConfigComponent;
}
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
policies.put(policy.getName(), policy);
}
/**
* @see net.sf.acegisecurity.vote.AccessDecisionVoter#supports(net.sf.acegisecurity.ConfigAttribute)
*/
@Override
public boolean supports(ConfigAttribute attribute)
{
if ((attribute.getAttribute() != null)
&& (attribute.getAttribute().equals(RM_ABSTAIN)
|| attribute.getAttribute().equals(RM_QUERY) || attribute.getAttribute().equals(RM_ALLOW) || attribute.getAttribute().equals(RM_DENY)
|| attribute.getAttribute().startsWith(RM_CAP) || attribute.getAttribute().startsWith(RM)))
&& (attribute.getAttribute().equals(ConfigAttributeDefinition.RM_ABSTAIN)
|| attribute.getAttribute().equals(ConfigAttributeDefinition.RM_QUERY) || attribute.getAttribute().equals(ConfigAttributeDefinition.RM_ALLOW) || attribute.getAttribute().equals(ConfigAttributeDefinition.RM_DENY)
|| attribute.getAttribute().startsWith(ConfigAttributeDefinition.RM_CAP) || attribute.getAttribute().startsWith(ConfigAttributeDefinition.RM)))
{
return true;
}
@@ -197,7 +158,7 @@ public class RMEntryVoter extends RMSecurityCommon
}
@SuppressWarnings("unchecked")
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config)
public int vote(Authentication authentication, Object object, net.sf.acegisecurity.ConfigAttributeDefinition config)
{
if (logger.isDebugEnabled())
{
@@ -214,7 +175,7 @@ public class RMEntryVoter extends RMSecurityCommon
return AccessDecisionVoter.ACCESS_GRANTED;
}
List<ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config);
List<ConfigAttributeDefinition> supportedDefinitions = extractSupportedDefinitions(config);
// No RM definitions so we do not vote
if (supportedDefinitions.size() == 0)
@@ -231,36 +192,36 @@ public class RMEntryVoter extends RMSecurityCommon
// If any abstain we deny
// All present must vote to allow unless an explicit direction comes first (e.g. RM_ALLOW)
for (ConfigAttributeDefintion cad : supportedDefinitions)
for (ConfigAttributeDefinition cad : supportedDefinitions)
{
// Whatever is found first takes precedence
if (cad.typeString.equals(RM_DENY))
if (cad.getTypeString().equals(ConfigAttributeDefinition.RM_DENY))
{
return AccessDecisionVoter.ACCESS_DENIED;
}
else if (cad.typeString.equals(RM_ABSTAIN))
else if (cad.getTypeString().equals(ConfigAttributeDefinition.RM_ABSTAIN))
{
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
else if (cad.typeString.equals(RM_ALLOW))
else if (cad.getTypeString().equals(ConfigAttributeDefinition.RM_ALLOW))
{
return AccessDecisionVoter.ACCESS_GRANTED;
}
// RM_QUERY is a special case - the entry is allowed and filtering sorts out the results
// It is distinguished from RM_ALLOW so query may have additional behaviour in the future
else if (cad.typeString.equals(RM_QUERY))
else if (cad.getTypeString().equals(ConfigAttributeDefinition.RM_QUERY))
{
return AccessDecisionVoter.ACCESS_GRANTED;
}
// Ignore config that references method arguments that do not exist
// Arguably we should deny here but that requires a full impact analysis
// These entries effectively abstain
else if (((cad.parameters.get(0) != null) && (cad.parameters.get(0) >= invocation.getArguments().length))
|| ((cad.parameters.get(1) != null) && (cad.parameters.get(1) >= invocation.getArguments().length)))
else if (((cad.getParameters().get(0) != null) && (cad.getParameters().get(0) >= invocation.getArguments().length)) ||
((cad.getParameters().get(1) != null) && (cad.getParameters().get(1) >= invocation.getArguments().length)))
{
continue;
}
else if (cad.typeString.equals(RM_CAP))
else if (cad.getTypeString().equals(ConfigAttributeDefinition.RM_CAP))
{
switch(checkCapability(invocation, params, cad))
{
@@ -271,11 +232,11 @@ public class RMEntryVoter extends RMSecurityCommon
{
if(logger.isTraceEnabled())
{
logger.trace("Capability " + cad.required + " abstained for " + invocation.getMethod(), new IllegalStateException());
logger.trace("Capability " + cad.getRequired() + " abstained for " + invocation.getMethod(), new IllegalStateException());
}
else
{
logger.debug("Capability " + cad.required + " abstained for " + invocation.getMethod());
logger.debug("Capability " + cad.getRequired() + " abstained for " + invocation.getMethod());
}
}
// abstain denies
@@ -284,7 +245,7 @@ public class RMEntryVoter extends RMSecurityCommon
break;
}
}
else if (cad.typeString.equals(RM))
else if (cad.getTypeString().equals(ConfigAttributeDefinition.RM))
{
switch(checkPolicy(invocation, params, cad))
{
@@ -295,11 +256,11 @@ public class RMEntryVoter extends RMSecurityCommon
{
if(logger.isTraceEnabled())
{
logger.trace("Policy " + cad.policyName + " abstained for " + invocation.getMethod(), new IllegalStateException());
logger.trace("Policy " + cad.getPolicyName() + " abstained for " + invocation.getMethod(), new IllegalStateException());
}
else
{
logger.debug("Policy " + cad.policyName + " abstained for " + invocation.getMethod());
logger.debug("Policy " + cad.getPolicyName() + " abstained for " + invocation.getMethod());
}
}
// abstain denies
@@ -317,14 +278,14 @@ public class RMEntryVoter extends RMSecurityCommon
}
@SuppressWarnings("unchecked")
private int checkCapability(MethodInvocation invocation, Class[] params, ConfigAttributeDefintion cad)
private int checkCapability(MethodInvocation invocation, Class[] params, ConfigAttributeDefinition cad)
{
NodeRef testNodeRef = getTestNode(getNodeService(), getRecordsManagementService(), invocation, params, cad.parameters.get(0), cad.parent);
NodeRef testNodeRef = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
if (testNodeRef == null)
{
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
Capability capability = capabilityService.getCapability(cad.required.getName());
Capability capability = capabilityService.getCapability(cad.getRequired().getName());
if (capability == null)
{
return AccessDecisionVoter.ACCESS_DENIED;
@@ -334,210 +295,16 @@ public class RMEntryVoter extends RMSecurityCommon
}
@SuppressWarnings("unchecked")
private static QName getType(NodeService nodeService, MethodInvocation invocation, Class[] params, int position, boolean parent)
private int checkPolicy(MethodInvocation invocation, Class[] params, ConfigAttributeDefinition cad)
{
if (QName.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
QName qname = (QName) invocation.getArguments()[position];
return qname;
}
}
else if (NodeRef.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
NodeRef nodeRef = (NodeRef) invocation.getArguments()[position];
return nodeService.getType(nodeRef);
}
}
return null;
}
@SuppressWarnings("unchecked")
private static QName getQName(MethodInvocation invocation, Class[] params, int position)
{
if (QName.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
QName qname = (QName) invocation.getArguments()[position];
return qname;
}
}
throw new ACLEntryVoterException("Unknown type");
}
@SuppressWarnings("unchecked")
private static Serializable getProperty(MethodInvocation invocation, Class[] params, int position)
{
if (invocation.getArguments()[position] == null)
{
return null;
}
if (Serializable.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
Serializable property = (Serializable) invocation.getArguments()[position];
return property;
}
}
throw new ACLEntryVoterException("Unknown type");
}
@SuppressWarnings("unchecked")
private static Map<QName, Serializable> getProperties(MethodInvocation invocation, Class[] params, int position)
{
if (invocation.getArguments()[position] == null)
{
return null;
}
if (Map.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
Map<QName, Serializable> properties = (Map<QName, Serializable>) invocation.getArguments()[position];
return properties;
}
}
throw new ACLEntryVoterException("Unknown type");
}
@SuppressWarnings("unchecked")
private static NodeRef getTestNode(NodeService nodeService, RecordsManagementService rmService, MethodInvocation invocation, Class[] params, int position, boolean parent)
{
NodeRef testNodeRef = null;
if (position < 0)
{
// Test against the fileplan root node
List<NodeRef> rmRoots = rmService.getFilePlans();
if (rmRoots.size() != 0)
{
// TODO for now we can take the first one as we only support a single rm site
testNodeRef = rmRoots.get(0);
if (logger.isDebugEnabled())
{
logger.debug("\tPermission test against the rm root node " + nodeService.getPath(testNodeRef));
}
}
}
else if (StoreRef.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
if (logger.isDebugEnabled())
{
logger.debug("\tPermission test against the store - using permissions on the root node");
}
StoreRef storeRef = (StoreRef) invocation.getArguments()[position];
if (nodeService.exists(storeRef))
{
testNodeRef = nodeService.getRootNode(storeRef);
}
}
}
else if (NodeRef.class.isAssignableFrom(params[position]))
{
testNodeRef = (NodeRef) invocation.getArguments()[position];
if (parent)
{
testNodeRef = nodeService.getPrimaryParent(testNodeRef).getParentRef();
if (logger.isDebugEnabled())
{
if (nodeService.exists(testNodeRef))
{
logger.debug("\tPermission test for parent on node " + nodeService.getPath(testNodeRef));
}
else
{
logger.debug("\tPermission test for parent on non-existing node " + testNodeRef);
}
logger.debug("\tPermission test for parent on node " + nodeService.getPath(testNodeRef));
}
}
else
{
if (logger.isDebugEnabled())
{
if (nodeService.exists(testNodeRef))
{
logger.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
}
else
{
logger.debug("\tPermission test on non-existing node " + testNodeRef);
}
}
}
}
else if (ChildAssociationRef.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
if (parent)
{
testNodeRef = ((ChildAssociationRef) invocation.getArguments()[position]).getParentRef();
}
else
{
testNodeRef = ((ChildAssociationRef) invocation.getArguments()[position]).getChildRef();
}
if (logger.isDebugEnabled())
{
if (nodeService.exists(testNodeRef))
{
logger.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
}
else
{
logger.debug("\tPermission test on non-existing node " + testNodeRef);
}
}
}
}
else if (AssociationRef.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
if (parent)
{
testNodeRef = ((AssociationRef) invocation.getArguments()[position]).getSourceRef();
}
else
{
testNodeRef = ((AssociationRef) invocation.getArguments()[position]).getTargetRef();
}
if (logger.isDebugEnabled())
{
if (nodeService.exists(testNodeRef))
{
logger.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
}
else
{
logger.debug("\tPermission test on non-existing node " + testNodeRef);
}
}
}
}
return testNodeRef;
}
@SuppressWarnings("unchecked")
private int checkPolicy(MethodInvocation invocation, Class[] params, ConfigAttributeDefintion cad)
{
Policy policy = policies.get(cad.policyName);
Policy policy = policies.get(cad.getPolicyName());
if (policy == null)
{
return AccessDecisionVoter.ACCESS_GRANTED;
}
else
{
return policy.evaluate(this.nodeService, this.recordsManagementService, this.capabilityService, invocation, params, cad);
return policy.evaluate(invocation, params, cad);
}
}
@@ -548,9 +315,9 @@ public class RMEntryVoter extends RMSecurityCommon
}
@SuppressWarnings("unchecked")
private List<ConfigAttributeDefintion> extractSupportedDefinitions(ConfigAttributeDefinition config)
private List<ConfigAttributeDefinition> extractSupportedDefinitions(net.sf.acegisecurity.ConfigAttributeDefinition config)
{
List<ConfigAttributeDefintion> definitions = new ArrayList<ConfigAttributeDefintion>(2);
List<ConfigAttributeDefinition> definitions = new ArrayList<ConfigAttributeDefinition>(2);
Iterator iter = config.getConfigAttributes();
while (iter.hasNext())
@@ -559,454 +326,11 @@ public class RMEntryVoter extends RMSecurityCommon
if (this.supports(attr))
{
definitions.add(new ConfigAttributeDefintion(attr));
definitions.add(new ConfigAttributeDefinition(attr, nspr));
}
}
return definitions;
}
/**
* @return the nodeService
*/
public NodeService getNodeService()
{
return nodeService;
}
/**
* @return the permissionService
*/
public PermissionService getPermissionService()
{
return permissionService;
}
/**
* @return the caveatConfigService
*/
public RMCaveatConfigComponent getCaveatConfigComponent()
{
return caveatConfigComponent;
}
/**
* @param recordsManagementService
* the recordsManagementService to set
*/
public void setRecordsManagementService(RecordsManagementService recordsManagementService)
{
this.recordsManagementService = recordsManagementService;
}
/**
* @return the recordsManagementService
*/
public RecordsManagementService getRecordsManagementService()
{
return recordsManagementService;
}
public void setDispositionService(DispositionService dispositionService)
{
this.dispositionService = dispositionService;
}
public DispositionService getDispositionService()
{
return dispositionService;
}
/**
* @return the dictionaryService
*/
public DictionaryService getDictionaryService()
{
return dictionaryService;
}
private class ConfigAttributeDefintion
{
String typeString;
String policyName;
SimplePermissionReference required;
HashMap<Integer, Integer> parameters = new HashMap<Integer, Integer>(2, 1.0f);
boolean parent = false;
ConfigAttributeDefintion(ConfigAttribute attr)
{
StringTokenizer st = new StringTokenizer(attr.getAttribute(), ".", false);
if (st.countTokens() < 1)
{
throw new ACLEntryVoterException("There must be at least one token in a config attribute");
}
typeString = st.nextToken();
if (!(typeString.equals(RM) || typeString.equals(RM_ALLOW) || typeString.equals(RM_CAP) || typeString.equals(RM_DENY) || typeString.equals(RM_QUERY) || typeString
.equals(RM_ABSTAIN)))
{
throw new ACLEntryVoterException("Invalid type: must be ACL_NODE, ACL_PARENT or ACL_ALLOW");
}
if (typeString.equals(RM))
{
policyName = st.nextToken();
int position = 0;
while (st.hasMoreElements())
{
String numberString = st.nextToken();
Integer value = Integer.parseInt(numberString);
parameters.put(position, value);
position++;
}
}
else if (typeString.equals(RM_CAP))
{
String numberString = st.nextToken();
String qNameString = st.nextToken();
String permissionString = st.nextToken();
Integer value = Integer.parseInt(numberString);
parameters.put(0, value);
QName qName = QName.createQName(qNameString, nspr);
required = SimplePermissionReference.getPermissionReference(qName, permissionString);
if (st.hasMoreElements())
{
parent = true;
}
}
}
}
interface Policy
{
/**
*
* @param nodeService
* @param rmService
* @param capabilitiesService
* @param invocation
* @param params
* @param cad
* @return
*/
@SuppressWarnings("unchecked")
int evaluate(
NodeService nodeService,
RecordsManagementService rmService,
CapabilityService capabilitiesService,
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefintion cad);
}
private static class ReadPolicy implements Policy
{
@SuppressWarnings("unchecked")
public int evaluate(
NodeService nodeService,
RecordsManagementService rmService,
CapabilityService capabilityService,
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefintion cad)
{
NodeRef testNodeRef = getTestNode(nodeService, rmService, invocation, params, cad.parameters.get(0), cad.parent);
return capabilityService.getCapability(RMPermissionModel.VIEW_RECORDS).evaluate(testNodeRef);
}
}
private static class CreatePolicy implements Policy
{
@SuppressWarnings("unchecked")
public int evaluate(
NodeService nodeService,
RecordsManagementService rmService,
CapabilityService capabilityService,
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefintion cad)
{
NodeRef destination = getTestNode(nodeService, rmService, invocation, params, cad.parameters.get(0), cad.parent);
QName type = getType(nodeService, invocation, params, cad.parameters.get(1), cad.parent);
// linkee is not null for creating secondary child assocs
NodeRef linkee = getTestNode(nodeService, rmService, invocation, params, cad.parameters.get(1), cad.parent);
QName assocType = null;
if(cad.parameters.size() > 2)
{
assocType = getType(nodeService, invocation, params, cad.parameters.get(2), cad.parent);
}
return ((CreateCapability)capabilityService.getCapability("Create")).evaluate(destination, linkee, type, assocType);
}
}
private static class MovePolicy implements Policy
{
@SuppressWarnings("unchecked")
public int evaluate(
NodeService nodeService,
RecordsManagementService rmService,
CapabilityService capabilityService,
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefintion cad)
{
NodeRef movee = null;
if (cad.parameters.get(0) > -1)
{
movee = getTestNode(nodeService, rmService, invocation, params, cad.parameters.get(0), cad.parent);
}
NodeRef destination = null;
if (cad.parameters.get(1) > -1)
{
destination = getTestNode(nodeService, rmService, invocation, params, cad.parameters.get(1), cad.parent);
}
if ((movee != null) && (destination != null))
{
return capabilityService.getCapability("Move").evaluate(movee, destination);
}
else
{
return AccessDecisionVoter.ACCESS_DENIED;
}
}
}
private static class UpdatePolicy implements Policy
{
@SuppressWarnings("unchecked")
public int evaluate(
NodeService nodeService,
RecordsManagementService rmService,
CapabilityService capabilityService,
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefintion cad)
{
NodeRef updatee = getTestNode(nodeService, rmService, invocation, params, cad.parameters.get(0), cad.parent);
QName aspectQName = null;
if (cad.parameters.size() > 1)
{
if (cad.parameters.get(1) > -1)
{
aspectQName = getQName(invocation, params, cad.parameters.get(1));
}
}
Map<QName, Serializable> properties = null;
if (cad.parameters.size() > 2)
{
if (cad.parameters.get(2) > -1)
{
properties = getProperties(invocation, params, cad.parameters.get(2));
}
}
UpdateCapability updateCapability = (UpdateCapability)capabilityService.getCapability("Update");
return updateCapability.evaluate(updatee, aspectQName, properties);
}
}
private static class DeletePolicy implements Policy
{
@SuppressWarnings("unchecked")
public int evaluate(
NodeService nodeService,
RecordsManagementService rmService,
CapabilityService capabilityService,
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefintion cad)
{
NodeRef deletee = null;
if (cad.parameters.get(0) > -1)
{
deletee = getTestNode(nodeService, rmService, invocation, params, cad.parameters.get(0), cad.parent);
}
if (deletee != null)
{
return capabilityService.getCapability("Delete").evaluate(deletee);
}
else
{
return AccessDecisionVoter.ACCESS_DENIED;
}
}
}
private static class UpdatePropertiesPolicy implements Policy
{
@SuppressWarnings("unchecked")
public int evaluate(
NodeService nodeService,
RecordsManagementService rmService,
CapabilityService capabilityService,
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefintion cad)
{
NodeRef updatee = getTestNode(nodeService, rmService, invocation, params, cad.parameters.get(0), cad.parent);
Map<QName, Serializable> properties;
if (QName.class.isAssignableFrom(params[cad.parameters.get(1)]))
{
// single update/delete
// We have a specific property
QName propertyQName = getQName(invocation, params, cad.parameters.get(1));
properties = new HashMap<QName, Serializable>(1, 1.0f);
if (cad.parameters.size() > 2)
{
properties.put(propertyQName, getProperty(invocation, params, cad.parameters.get(2)));
}
else
{
properties.put(propertyQName, null);
}
}
else
{
properties = getProperties(invocation, params, cad.parameters.get(1));
}
return ((UpdatePropertiesCapability)capabilityService.getCapability("UpdateProperties")).evaluate(updatee, properties);
}
}
private static class AssocPolicy implements Policy
{
@SuppressWarnings("unchecked")
public int evaluate(
NodeService nodeService,
RecordsManagementService rmService,
CapabilityService capabilityService,
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefintion cad)
{
Policy policy = policies.get("Read");
if (policy == null)
{
return AccessDecisionVoter.ACCESS_DENIED;
}
else
{
return policy.evaluate(nodeService, rmService, capabilityService, invocation, params, cad);
}
}
}
private static class WriteContentPolicy implements Policy
{
@SuppressWarnings("unchecked")
public int evaluate(
NodeService nodeService,
RecordsManagementService rmService,
CapabilityService capabilityService,
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefintion cad)
{
NodeRef updatee = getTestNode(nodeService, rmService, invocation, params, cad.parameters.get(0), cad.parent);
return capabilityService.getCapability("WriteContent").evaluate(updatee);
}
}
private static class CapabilityPolicy implements Policy
{
@SuppressWarnings("unchecked")
public int evaluate(
NodeService nodeService,
RecordsManagementService rmService,
CapabilityService capabilityService,
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefintion cad)
{
NodeRef assignee = getTestNode(nodeService, rmService, invocation, params, cad.parameters.get(0), cad.parent);
return capabilityService.getCapability(RMPermissionModel.MANAGE_ACCESS_CONTROLS).evaluate(assignee);
}
}
private static class DeclarePolicy implements Policy
{
@SuppressWarnings("unchecked")
public int evaluate(
NodeService nodeService,
RecordsManagementService rmService,
CapabilityService capabilityService,
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefintion cad)
{
NodeRef declaree = getTestNode(nodeService, rmService, invocation, params, cad.parameters.get(0), cad.parent);
return capabilityService.getCapability("Declare").evaluate(declaree);
}
}
private static class ReadPropertyPolicy implements Policy
{
@SuppressWarnings("unchecked")
public int evaluate(
NodeService nodeService,
RecordsManagementService rmService,
CapabilityService capabilityService,
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefintion cad)
{
NodeRef nodeRef = getTestNode(nodeService, rmService, invocation, params, cad.parameters.get(0), cad.parent);
QName propertyQName = getQName(invocation, params, cad.parameters.get(1));
if(propertyQName.equals(RecordsManagementModel.PROP_HOLD_REASON))
{
return capabilityService.getCapability(RMPermissionModel.VIEW_UPDATE_REASONS_FOR_FREEZE).evaluate(nodeRef);
}
else
{
return AccessDecisionVoter.ACCESS_GRANTED;
}
}
}
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException
{
this.applicationContext = applicationContext;
}
}

View File

@@ -18,6 +18,8 @@
*/
package org.alfresco.module.org_alfresco_module_rm.capability;
import java.util.List;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService;
@@ -25,10 +27,14 @@ import org.alfresco.module.org_alfresco_module_rm.caveat.RMCaveatConfigComponent
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.service.cmr.repository.AssociationRef;
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.StoreRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -220,4 +226,125 @@ public class RMSecurityCommon
}
}
@SuppressWarnings("unchecked")
protected NodeRef getTestNode(MethodInvocation invocation, Class[] params, int position, boolean parent)
{
NodeRef testNodeRef = null;
if (position < 0)
{
// Test against the fileplan root node
List<NodeRef> rmRoots = rmService.getFilePlans();
if (rmRoots.size() != 0)
{
// TODO for now we can take the first one as we only support a single rm site
testNodeRef = rmRoots.get(0);
if (logger.isDebugEnabled())
{
logger.debug("\tPermission test against the rm root node " + nodeService.getPath(testNodeRef));
}
}
}
else if (StoreRef.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
if (logger.isDebugEnabled())
{
logger.debug("\tPermission test against the store - using permissions on the root node");
}
StoreRef storeRef = (StoreRef) invocation.getArguments()[position];
if (nodeService.exists(storeRef))
{
testNodeRef = nodeService.getRootNode(storeRef);
}
}
}
else if (NodeRef.class.isAssignableFrom(params[position]))
{
testNodeRef = (NodeRef) invocation.getArguments()[position];
if (parent)
{
testNodeRef = nodeService.getPrimaryParent(testNodeRef).getParentRef();
if (logger.isDebugEnabled())
{
if (nodeService.exists(testNodeRef))
{
logger.debug("\tPermission test for parent on node " + nodeService.getPath(testNodeRef));
}
else
{
logger.debug("\tPermission test for parent on non-existing node " + testNodeRef);
}
logger.debug("\tPermission test for parent on node " + nodeService.getPath(testNodeRef));
}
}
else
{
if (logger.isDebugEnabled())
{
if (nodeService.exists(testNodeRef))
{
logger.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
}
else
{
logger.debug("\tPermission test on non-existing node " + testNodeRef);
}
}
}
}
else if (ChildAssociationRef.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
if (parent)
{
testNodeRef = ((ChildAssociationRef) invocation.getArguments()[position]).getParentRef();
}
else
{
testNodeRef = ((ChildAssociationRef) invocation.getArguments()[position]).getChildRef();
}
if (logger.isDebugEnabled())
{
if (nodeService.exists(testNodeRef))
{
logger.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
}
else
{
logger.debug("\tPermission test on non-existing node " + testNodeRef);
}
}
}
}
else if (AssociationRef.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
if (parent)
{
testNodeRef = ((AssociationRef) invocation.getArguments()[position]).getSourceRef();
}
else
{
testNodeRef = ((AssociationRef) invocation.getArguments()[position]).getTargetRef();
}
if (logger.isDebugEnabled())
{
if (nodeService.exists(testNodeRef))
{
logger.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
}
else
{
logger.debug("\tPermission test on non-existing node " + testNodeRef);
}
}
}
}
return testNodeRef;
}
}

View File

@@ -0,0 +1,197 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.capability.RMEntryVoter;
import org.alfresco.module.org_alfresco_module_rm.capability.RMSecurityCommon;
import org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Abstract base policy implementation
*
* @author Roy Wetherall
* @since 2.1
*/
public abstract class AbstractBasePolicy extends RMSecurityCommon
implements Policy
{
/** Logger */
protected static Log logger = LogFactory.getLog(AbstractBasePolicy.class);
/** Capability service */
protected CapabilityService capabilityService;
/** RM entry */
protected RMEntryVoter rmEntryVoter;
/** Policy name */
protected String name;
/**
* @param name policy name
*/
public void setName(String name)
{
this.name = name;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.capability.policy.Policy#getName()
*/
@Override
public String getName()
{
return name;
}
/**
* @param capabilityService capability service
*/
public void setCapabilityService(CapabilityService capabilityService)
{
this.capabilityService = capabilityService;
}
/**
* @param rmEntryVoter rm entry voter
*/
public void setRmEntryVoter(RMEntryVoter rmEntryVoter)
{
this.rmEntryVoter = rmEntryVoter;
}
/**
* Init method
*/
public void init()
{
rmEntryVoter.registerPolicy(this);
}
/**
*
* @param invocation
* @param params
* @param position
* @param parent
* @return
*/
@SuppressWarnings("unchecked")
protected QName getType(MethodInvocation invocation, Class[] params, int position, boolean parent)
{
if (QName.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
QName qname = (QName) invocation.getArguments()[position];
return qname;
}
}
else if (NodeRef.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
NodeRef nodeRef = (NodeRef) invocation.getArguments()[position];
return nodeService.getType(nodeRef);
}
}
return null;
}
/**
*
* @param invocation
* @param params
* @param position
* @return
*/
@SuppressWarnings("unchecked")
protected QName getQName(MethodInvocation invocation, Class[] params, int position)
{
if (QName.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
QName qname = (QName) invocation.getArguments()[position];
return qname;
}
}
throw new ACLEntryVoterException("Unknown type");
}
/**
*
* @param invocation
* @param params
* @param position
* @return
*/
@SuppressWarnings("unchecked")
protected Serializable getProperty(MethodInvocation invocation, Class[] params, int position)
{
if (invocation.getArguments()[position] == null)
{
return null;
}
if (Serializable.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
Serializable property = (Serializable) invocation.getArguments()[position];
return property;
}
}
throw new ACLEntryVoterException("Unknown type");
}
/**
*
* @param invocation
* @param params
* @param position
* @return
*/
@SuppressWarnings("unchecked")
protected Map<QName, Serializable> getProperties(MethodInvocation invocation, Class[] params, int position)
{
if (invocation.getArguments()[position] == null)
{
return null;
}
if (Map.class.isAssignableFrom(params[position]))
{
if (invocation.getArguments()[position] != null)
{
Map<QName, Serializable> properties = (Map<QName, Serializable>) invocation.getArguments()[position];
return properties;
}
}
throw new ACLEntryVoterException("Unknown type");
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.aopalliance.intercept.MethodInvocation;
public class AssocPolicy extends AbstractBasePolicy
{
@SuppressWarnings("unchecked")
public int evaluate(
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefinition cad)
{
NodeRef testNodeRef = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
return capabilityService.getCapability(RMPermissionModel.VIEW_RECORDS).evaluate(testNodeRef);
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.aopalliance.intercept.MethodInvocation;
/**
*
* @author Roy Wetherall
* @since 2.1
*/
public class CapabilityPolicy extends AbstractBasePolicy
{
/**
* @see org.alfresco.module.org_alfresco_module_rm.capability.policy.Policy#evaluate(org.aopalliance.intercept.MethodInvocation, java.lang.Class[], org.alfresco.module.org_alfresco_module_rm.capability.policy.ConfigAttributeDefinition)
*/
@Override
@SuppressWarnings("unchecked")
public int evaluate(
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefinition cad)
{
NodeRef assignee = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
return capabilityService.getCapability(RMPermissionModel.MANAGE_ACCESS_CONTROLS).evaluate(assignee);
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import java.util.HashMap;
import java.util.StringTokenizer;
import net.sf.acegisecurity.ConfigAttribute;
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
import org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterException;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
/**
* @author Roy Wetherall
* @since 2.1
*/
public class ConfigAttributeDefinition
{
public static final String RM = "RM";
public static final String RM_ALLOW = "RM_ALLOW";
public static final String RM_DENY = "RM_DENY";
public static final String RM_CAP = "RM_CAP";
public static final String RM_ABSTAIN = "RM_ABSTAIN";
public static final String RM_QUERY = "RM_QUERY";
private String typeString;
private String policyName;
private SimplePermissionReference required;
private HashMap<Integer, Integer> parameters = new HashMap<Integer, Integer>(2, 1.0f);
private boolean parent = false;
public ConfigAttributeDefinition(ConfigAttribute attr, NamespacePrefixResolver namespacePrefixResolver)
{
StringTokenizer st = new StringTokenizer(attr.getAttribute(), ".", false);
if (st.countTokens() < 1)
{
throw new ACLEntryVoterException("There must be at least one token in a config attribute");
}
typeString = st.nextToken();
if (!(typeString.equals(RM) || typeString.equals(RM_ALLOW) || typeString.equals(RM_CAP) || typeString.equals(RM_DENY) || typeString.equals(RM_QUERY) || typeString
.equals(RM_ABSTAIN)))
{
throw new ACLEntryVoterException("Invalid type: must be ACL_NODE, ACL_PARENT or ACL_ALLOW");
}
if (typeString.equals(RM))
{
policyName = st.nextToken();
int position = 0;
while (st.hasMoreElements())
{
String numberString = st.nextToken();
Integer value = Integer.parseInt(numberString);
parameters.put(position, value);
position++;
}
}
else if (typeString.equals(RM_CAP))
{
String numberString = st.nextToken();
String qNameString = st.nextToken();
String permissionString = st.nextToken();
Integer value = Integer.parseInt(numberString);
parameters.put(0, value);
QName qName = QName.createQName(qNameString, namespacePrefixResolver);
required = SimplePermissionReference.getPermissionReference(qName, permissionString);
if (st.hasMoreElements())
{
parent = true;
}
}
}
public String getTypeString()
{
return typeString;
}
public String getPolicyName()
{
return policyName;
}
public SimplePermissionReference getRequired()
{
return required;
}
public HashMap<Integer, Integer> getParameters()
{
return parameters;
}
public boolean isParent()
{
return parent;
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import org.alfresco.module.org_alfresco_module_rm.capability.impl.CreateCapability;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.aopalliance.intercept.MethodInvocation;
public class CreatePolicy extends AbstractBasePolicy
{
@SuppressWarnings("unchecked")
public int evaluate(
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefinition cad)
{
NodeRef destination = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
QName type = getType(invocation, params, cad.getParameters().get(1), cad.isParent());
// linkee is not null for creating secondary child assocs
NodeRef linkee = getTestNode(invocation, params, cad.getParameters().get(1), cad.isParent());
QName assocType = null;
if(cad.getParameters().size() > 2)
{
assocType = getType(invocation, params, cad.getParameters().get(2), cad.isParent());
}
return ((CreateCapability)capabilityService.getCapability("Create")).evaluate(destination, linkee, type, assocType);
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import org.alfresco.service.cmr.repository.NodeRef;
import org.aopalliance.intercept.MethodInvocation;
public class DeclarePolicy extends AbstractBasePolicy
{
@SuppressWarnings("unchecked")
public int evaluate(
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefinition cad)
{
NodeRef declaree = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
return capabilityService.getCapability("Declare").evaluate(declaree);
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.aopalliance.intercept.MethodInvocation;
public class DeletePolicy extends AbstractBasePolicy
{
@SuppressWarnings("unchecked")
public int evaluate(
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefinition cad)
{
NodeRef deletee = null;
if (cad.getParameters().get(0) > -1)
{
deletee = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
}
if (deletee != null)
{
return capabilityService.getCapability("Delete").evaluate(deletee);
}
else
{
return AccessDecisionVoter.ACCESS_DENIED;
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.aopalliance.intercept.MethodInvocation;
public class MovePolicy extends AbstractBasePolicy
{
@SuppressWarnings("unchecked")
public int evaluate(
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefinition cad)
{
NodeRef movee = null;
if (cad.getParameters().get(0) > -1)
{
movee = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
}
NodeRef destination = null;
if (cad.getParameters().get(1) > -1)
{
destination = getTestNode(invocation, params, cad.getParameters().get(1), cad.isParent());
}
if ((movee != null) && (destination != null))
{
return capabilityService.getCapability("Move").evaluate(movee, destination);
}
else
{
return AccessDecisionVoter.ACCESS_DENIED;
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import org.aopalliance.intercept.MethodInvocation;
/**
* Policy interface
*
* @author Roy Wetherall
* @since 2.1
*/
public interface Policy
{
/**
* @return policy name
*/
String getName();
/**
* Evaluate the policy
*
* @param invocation
* @param params
* @param cad
* @return
*/
@SuppressWarnings("unchecked")
int evaluate(
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefinition cad);
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.aopalliance.intercept.MethodInvocation;
public class ReadPolicy extends AbstractBasePolicy
{
@SuppressWarnings("unchecked")
public int evaluate(
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefinition cad)
{
NodeRef testNodeRef = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
return capabilityService.getCapability(RMPermissionModel.VIEW_RECORDS).evaluate(testNodeRef);
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.aopalliance.intercept.MethodInvocation;
public class ReadPropertyPolicy extends AbstractBasePolicy
{
@SuppressWarnings("unchecked")
public int evaluate(
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefinition cad)
{
NodeRef nodeRef = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
QName propertyQName = getQName(invocation, params, cad.getParameters().get(1));
if(propertyQName.equals(RecordsManagementModel.PROP_HOLD_REASON))
{
return capabilityService.getCapability(RMPermissionModel.VIEW_UPDATE_REASONS_FOR_FREEZE).evaluate(nodeRef);
}
else
{
return AccessDecisionVoter.ACCESS_GRANTED;
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.module.org_alfresco_module_rm.capability.impl.UpdateCapability;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.aopalliance.intercept.MethodInvocation;
public class UpdatePolicy extends AbstractBasePolicy
{
@SuppressWarnings("unchecked")
public int evaluate(
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefinition cad)
{
NodeRef updatee = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
QName aspectQName = null;
if (cad.getParameters().size() > 1)
{
if (cad.getParameters().get(1) > -1)
{
aspectQName = getQName(invocation, params, cad.getParameters().get(1));
}
}
Map<QName, Serializable> properties = null;
if (cad.getParameters().size() > 2)
{
if (cad.getParameters().get(2) > -1)
{
properties = getProperties(invocation, params, cad.getParameters().get(2));
}
}
UpdateCapability updateCapability = (UpdateCapability)capabilityService.getCapability("Update");
return updateCapability.evaluate(updatee, aspectQName, properties);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.module.org_alfresco_module_rm.capability.impl.UpdatePropertiesCapability;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.aopalliance.intercept.MethodInvocation;
public class UpdatePropertiesPolicy extends AbstractBasePolicy
{
@SuppressWarnings("unchecked")
public int evaluate(
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefinition cad)
{
NodeRef updatee = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
Map<QName, Serializable> properties;
if (QName.class.isAssignableFrom(params[cad.getParameters().get(1)]))
{
// single update/delete
// We have a specific property
QName propertyQName = getQName(invocation, params, cad.getParameters().get(1));
properties = new HashMap<QName, Serializable>(1, 1.0f);
if (cad.getParameters().size() > 2)
{
properties.put(propertyQName, getProperty(invocation, params, cad.getParameters().get(2)));
}
else
{
properties.put(propertyQName, null);
}
}
else
{
properties = getProperties(invocation, params, cad.getParameters().get(1));
}
return ((UpdatePropertiesCapability)capabilityService.getCapability("UpdateProperties")).evaluate(updatee, properties);
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import org.alfresco.service.cmr.repository.NodeRef;
import org.aopalliance.intercept.MethodInvocation;
public class WriteContentPolicy extends AbstractBasePolicy
{
@SuppressWarnings("unchecked")
public int evaluate(
MethodInvocation invocation,
Class[] params,
ConfigAttributeDefinition cad)
{
NodeRef updatee = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
return capabilityService.getCapability("WriteContent").evaluate(updatee);
}
}

View File

@@ -178,7 +178,7 @@ public class CapabilityServiceImplTest extends BaseRMTestCase
assertNotNull(vitalRecordCapabilities);
vitalRecordCapabilitiesSize = vitalRecordCapabilities.size();
assertEquals(1, vitalRecordCapabilitiesSize);
assertTrue(vitalRecordCapabilitiesSize > 0);
return null;
}