mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
RM-2129 (Check classification before method execution)
+review RM @rwetherall git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@107649 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -69,8 +69,6 @@ public class ClassificationServiceBootstrap extends AbstractLifecycleBean implem
|
||||
private ExemptionCategoryFieldsValidator exemptionCategoryFieldsValidator = new ExemptionCategoryFieldsValidator();
|
||||
private ClassificationSchemeEntityValidator<ExemptionCategory> exemptionCategoryValidator = new ClassificationSchemeEntityValidator<>(exemptionCategoryFieldsValidator);
|
||||
|
||||
private boolean isInitialised = false;
|
||||
|
||||
public ClassificationServiceBootstrap(AuthenticationUtil authUtil,
|
||||
TransactionService txService,
|
||||
AttributeService attributeService,
|
||||
@@ -95,11 +93,6 @@ public class ClassificationServiceBootstrap extends AbstractLifecycleBean implem
|
||||
public ExemptionCategoryManager getExemptionCategoryManager() { return exemptionCategoryManager; }
|
||||
public ClearanceLevelManager getClearanceLevelManager() { return clearanceLevelManager; }
|
||||
|
||||
public boolean isInitialised()
|
||||
{
|
||||
return isInitialised;
|
||||
}
|
||||
|
||||
@Override public void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
authenticationUtil.runAsSystem(new org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork<Void>()
|
||||
@@ -123,7 +116,6 @@ public class ClassificationServiceBootstrap extends AbstractLifecycleBean implem
|
||||
exemptionCategoryManager.setExemptionCategories(exemptionCategories);
|
||||
|
||||
initConfiguredClearanceLevels(classificationLevelManager.getClassificationLevels());
|
||||
isInitialised = true;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
@@ -83,28 +83,21 @@ public class ClassificationMethodInterceptor implements MethodInterceptor
|
||||
{
|
||||
mandatory("invocation", invocation);
|
||||
|
||||
Object result = null;
|
||||
|
||||
boolean canProceed = true;
|
||||
boolean isUserValid = isUserValid();
|
||||
|
||||
// Pre method invocation processing
|
||||
if (isUserValid)
|
||||
{
|
||||
//FIXME!!!
|
||||
// Pre method invocation processing
|
||||
//canProceed = getPreMethodInvocationProcessor().process(invocation);
|
||||
getPreMethodInvocationProcessor().process(invocation);
|
||||
}
|
||||
|
||||
if (canProceed)
|
||||
{
|
||||
// Method invocation
|
||||
result = invocation.proceed();
|
||||
// Method invocation
|
||||
Object result = invocation.proceed();
|
||||
|
||||
// Post method invocation processing
|
||||
if (isUserValid && result != null)
|
||||
{
|
||||
result = getPostMethodInvocationProcessor().process(result);
|
||||
}
|
||||
// Post method invocation processing
|
||||
if (isUserValid && result != null)
|
||||
{
|
||||
result = getPostMethodInvocationProcessor().process(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@@ -26,8 +26,6 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Registry for post method invocation processors
|
||||
*
|
||||
@@ -36,11 +34,8 @@ import org.apache.log4j.Logger;
|
||||
*/
|
||||
public class PostMethodInvocationProcessor
|
||||
{
|
||||
/** Logger */
|
||||
private static Logger LOG = Logger.getLogger(PostMethodInvocationProcessor.class);
|
||||
|
||||
/** Post method invocation processors */
|
||||
private Map<Class<?>, BasePostMethodInvocationProcessor> processors = new HashMap<Class<?>, BasePostMethodInvocationProcessor>();
|
||||
private Map<Class<?>, BasePostMethodInvocationProcessor> processors = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Registers a post method invocation processor
|
||||
@@ -51,7 +46,7 @@ public class PostMethodInvocationProcessor
|
||||
{
|
||||
mandatory("object", object);
|
||||
|
||||
processors.put(object.getClassName(), object);
|
||||
getProcessors().put(object.getClassName(), object);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,25 +67,27 @@ public class PostMethodInvocationProcessor
|
||||
*/
|
||||
protected BasePostMethodInvocationProcessor getProcessor(Object object)
|
||||
{
|
||||
mandatory("object", object);
|
||||
|
||||
BasePostMethodInvocationProcessor result = null;
|
||||
Class<? extends Object> clazz = object.getClass();
|
||||
|
||||
if (clazz.isArray())
|
||||
if (object != null)
|
||||
{
|
||||
result = getProcessors().get(Array.class);
|
||||
}
|
||||
Class<? extends Object> clazz = object.getClass();
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
Set<Entry<Class<?>, BasePostMethodInvocationProcessor>> processorsEntrySet = getProcessors().entrySet();
|
||||
for (Map.Entry<Class<?>, BasePostMethodInvocationProcessor> processorEntry : processorsEntrySet)
|
||||
if (clazz.isArray())
|
||||
{
|
||||
if (processorEntry.getKey().isAssignableFrom(clazz))
|
||||
result = getProcessors().get(Array.class);
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
Set<Entry<Class<?>, BasePostMethodInvocationProcessor>> processorsEntrySet = getProcessors().entrySet();
|
||||
for (Map.Entry<Class<?>, BasePostMethodInvocationProcessor> processorEntry : processorsEntrySet)
|
||||
{
|
||||
result = processorEntry.getValue();
|
||||
break;
|
||||
if (processorEntry.getKey().isAssignableFrom(clazz))
|
||||
{
|
||||
result = processorEntry.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,10 +112,6 @@ public class PostMethodInvocationProcessor
|
||||
{
|
||||
result = processor.process(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.debug("No processor found for '" + result + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@@ -18,22 +18,18 @@
|
||||
*/
|
||||
package org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor;
|
||||
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import static org.alfresco.model.ContentModel.TYPE_CONTENT;
|
||||
import static org.alfresco.util.GUID.generate;
|
||||
import static org.alfresco.util.ParameterCheck.mandatory;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationServiceBootstrap;
|
||||
import org.alfresco.module.org_alfresco_module_rm.classification.ContentClassificationService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.util.AlfrescoTransactionSupport;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -48,221 +44,88 @@ import org.springframework.context.ApplicationContextAware;
|
||||
*/
|
||||
public class PreMethodInvocationProcessor implements ApplicationContextAware
|
||||
{
|
||||
/** Key to mark the transaction as processing */
|
||||
private static final String KEY_PROCESSING = generate();
|
||||
|
||||
/** Application context */
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
/**
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||
{
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content classification service
|
||||
*
|
||||
* @return The content classification service
|
||||
*/
|
||||
protected ContentClassificationService getContentClassificationService()
|
||||
{
|
||||
return (ContentClassificationService)applicationContext.getBean("contentClassificationService");
|
||||
}
|
||||
|
||||
protected AlfrescoTransactionSupport getAlfrescoTransactionSupport()
|
||||
{
|
||||
return (AlfrescoTransactionSupport)applicationContext.getBean("rm.alfrescoTransactionSupport");
|
||||
}
|
||||
|
||||
protected RetryingTransactionHelper getRetryingTransactionHelper()
|
||||
{
|
||||
return ((TransactionService)applicationContext.getBean("transactionService")).getRetryingTransactionHelper();
|
||||
}
|
||||
|
||||
protected ClassificationServiceBootstrap getClassificationServiceBootstrap()
|
||||
{
|
||||
return (ClassificationServiceBootstrap)applicationContext.getBean("classificationServiceBootstrap");
|
||||
return (ContentClassificationService) applicationContext.getBean("contentClassificationService");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node service
|
||||
*
|
||||
* @return The node service
|
||||
*/
|
||||
protected NodeService getNodeService()
|
||||
{
|
||||
return (NodeService)applicationContext.getBean("dbNodeService");
|
||||
return (NodeService) applicationContext.getBean("dbNodeService");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the dictionary service
|
||||
*
|
||||
* @return The dictionary service
|
||||
*/
|
||||
protected DictionaryService getDictionaryService()
|
||||
{
|
||||
return (DictionaryService)applicationContext.getBean("dictionaryService");
|
||||
return (DictionaryService) applicationContext.getBean("dictionaryService");
|
||||
}
|
||||
|
||||
// /** Transaction service */
|
||||
// private TransactionService transactionService;
|
||||
//
|
||||
// /** Classification service bootstrap */
|
||||
// private ClassificationServiceBootstrap classificationServiceBootstrap;
|
||||
//
|
||||
// /** Alfresco transaction support */
|
||||
// private AlfrescoTransactionSupport alfrescoTransactionSupport;
|
||||
//
|
||||
// /** Node service */
|
||||
// private NodeService nodeService;
|
||||
//
|
||||
// /** Dictionary service */
|
||||
// private DictionaryService dictionaryService;
|
||||
//
|
||||
// /** Content classification service */
|
||||
// private ContentClassificationService contentClassificationService;
|
||||
//
|
||||
// /**
|
||||
// * @return the transactionService
|
||||
// */
|
||||
// protected TransactionService getTransactionService()
|
||||
// {
|
||||
// return this.transactionService;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @return the classificationServiceBootstrap
|
||||
// */
|
||||
// protected ClassificationServiceBootstrap getClassificationServiceBootstrap()
|
||||
// {
|
||||
// return this.classificationServiceBootstrap;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @return the alfrescoTransactionSupport
|
||||
// */
|
||||
// protected AlfrescoTransactionSupport getAlfrescoTransactionSupport()
|
||||
// {
|
||||
// return this.alfrescoTransactionSupport;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @return the nodeService
|
||||
// */
|
||||
// protected NodeService getNodeService()
|
||||
// {
|
||||
// return this.nodeService;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @return the dictionaryService
|
||||
// */
|
||||
// protected DictionaryService getDictionaryService()
|
||||
// {
|
||||
// return this.dictionaryService;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @return the contentClassificationService
|
||||
// */
|
||||
// protected ContentClassificationService getContentClassificationService()
|
||||
// {
|
||||
// return this.contentClassificationService;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @param transactionService the transactionService to set
|
||||
// */
|
||||
// public void setTransactionService(TransactionService transactionService)
|
||||
// {
|
||||
// this.transactionService = transactionService;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @param classificationServiceBootstrap the classificationServiceBootstrap to set
|
||||
// */
|
||||
// public void setClassificationServiceBootstrap(ClassificationServiceBootstrap classificationServiceBootstrap)
|
||||
// {
|
||||
// this.classificationServiceBootstrap = classificationServiceBootstrap;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @param alfrescoTransactionSupport the alfrescoTransactionSupport to set
|
||||
// */
|
||||
// public void setAlfrescoTransactionSupport(AlfrescoTransactionSupport alfrescoTransactionSupport)
|
||||
// {
|
||||
// this.alfrescoTransactionSupport = alfrescoTransactionSupport;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @param nodeService the nodeService to set
|
||||
// */
|
||||
// public void setNodeService(NodeService nodeService)
|
||||
// {
|
||||
// this.nodeService = nodeService;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @param dictionaryService the dictionaryService to set
|
||||
// */
|
||||
// public void setDictionaryService(DictionaryService dictionaryService)
|
||||
// {
|
||||
// this.dictionaryService = dictionaryService;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @param contentClassificationService the contentClassificationService to set
|
||||
// */
|
||||
// public void setContentClassificationService(ContentClassificationService contentClassificationService)
|
||||
// {
|
||||
// this.contentClassificationService = contentClassificationService;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Checks if the current user is cleared to see the items
|
||||
* passed as parameters to the current method invocation.
|
||||
*
|
||||
* @param invocation The current method invocation
|
||||
* @return <code>true</code> if the user is cleared to see the items, <code>false</code> otherwise
|
||||
*/
|
||||
public boolean process(final MethodInvocation invocation)
|
||||
public void process(MethodInvocation invocation)
|
||||
{
|
||||
mandatory("invocation", invocation);
|
||||
|
||||
// do in transaction
|
||||
return /*getTransactionService().*/getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Boolean>()
|
||||
Method method = invocation.getMethod();
|
||||
String className = method.getDeclaringClass().getSimpleName();
|
||||
String methodName = method.getName();
|
||||
String name = className + "." + methodName;
|
||||
Object[] args = invocation.getArguments();
|
||||
|
||||
if (getMethodNames().contains(name))
|
||||
{
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Boolean execute() throws Throwable
|
||||
for (Object arg : args)
|
||||
{
|
||||
Boolean result = true;
|
||||
|
||||
// ensure classification service has been bootstrapped
|
||||
if (getClassificationServiceBootstrap().isInitialised())
|
||||
if (arg != null && NodeRef.class.isAssignableFrom(arg.getClass()))
|
||||
{
|
||||
// check that we are not already processing a classification check
|
||||
Object value = getAlfrescoTransactionSupport().getResource(KEY_PROCESSING);
|
||||
if (value == null)
|
||||
{
|
||||
Method method = invocation.getMethod();
|
||||
Class[] params = method.getParameterTypes();
|
||||
|
||||
int position = 0;
|
||||
for (Class param : params)
|
||||
{
|
||||
// if the param is a node reference
|
||||
if (NodeRef.class.isAssignableFrom(param))
|
||||
{
|
||||
// mark the transaction as processing a classification check
|
||||
getAlfrescoTransactionSupport().bindResource(KEY_PROCESSING, TRUE);
|
||||
try
|
||||
{
|
||||
// get the value of the parameter
|
||||
NodeRef testNodeRef = (NodeRef) invocation.getArguments()[position];
|
||||
|
||||
// if node exists then see if the current user has clearance
|
||||
result = isNodeCleared(testNodeRef);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// clear the transaction as processed a classification check
|
||||
getAlfrescoTransactionSupport().unbindResource(KEY_PROCESSING);
|
||||
}
|
||||
}
|
||||
|
||||
position++;
|
||||
}
|
||||
}
|
||||
isNodeCleared(((NodeRef) arg), name);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of method names to check before invocation
|
||||
*
|
||||
* @return List of method names to check before invocation
|
||||
*/
|
||||
private List<String> getMethodNames()
|
||||
{
|
||||
return newArrayList(
|
||||
"NodeService.setProperty",
|
||||
//"NodeService.getProperty",
|
||||
"FileFolderService.copy"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,19 +133,15 @@ public class PreMethodInvocationProcessor implements ApplicationContextAware
|
||||
* the currently logged in user is cleared to see it.
|
||||
*
|
||||
* @param nodeRef Node reference to check
|
||||
* @return <code>true</code> if the node passes the checks, <code>false</code> otherwise
|
||||
* @param name The name of the invoked method
|
||||
*/
|
||||
private boolean isNodeCleared(NodeRef nodeRef)
|
||||
private void isNodeCleared(NodeRef nodeRef, String name)
|
||||
{
|
||||
boolean result = true;
|
||||
|
||||
if (getNodeService().exists(nodeRef) &&
|
||||
getDictionaryService().isSubClass(getNodeService().getType(nodeRef), TYPE_CONTENT) &&
|
||||
!getContentClassificationService().hasClearance(nodeRef))
|
||||
{
|
||||
result = false;
|
||||
throw new AccessDeniedException("The method '" + name + "' was called, but you are not cleared for the node.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user