From aa746dd474cd84c41c4f37caf16ba194066a0ec7 Mon Sep 17 00:00:00 2001 From: Tuna Aksoy Date: Thu, 11 Jun 2015 09:37:24 +0000 Subject: [PATCH] RM-2130 (Check classification after method execution, filtering results where appropriate) * Initial (early) commit to get feedback from the review * The "check" method will be changed later +review RM @rwetherall git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/DEV/ENFORCE@105923 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../classified-content-context.xml | 40 ++++- .../ClassificationMethodInterceptor.java | 45 ++++- ...ationRefPostMethodInvocationProcessor.java | 61 +++++++ .../BasePostMethodInvocationProcessor.java | 157 ++++++++++++++++++ ...ationRefPostMethodInvocationProcessor.java | 61 +++++++ .../NodeRefPostMethodInvocationProcessor.java | 54 ++++++ 6 files changed, 402 insertions(+), 16 deletions(-) create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/AssociationRefPostMethodInvocationProcessor.java create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/BasePostMethodInvocationProcessor.java create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ChildAssociationRefPostMethodInvocationProcessor.java create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/NodeRefPostMethodInvocationProcessor.java diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/classified-content-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/classified-content-context.xml index 0e94fc654b..4b804025ee 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/classified-content-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/classified-content-context.xml @@ -1,11 +1,11 @@ @@ -32,16 +32,40 @@ - + - - - + + + + + + + + + + + + + + + + diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/ClassificationMethodInterceptor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/ClassificationMethodInterceptor.java index fbd3943177..338c5ea278 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/ClassificationMethodInterceptor.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/ClassificationMethodInterceptor.java @@ -18,13 +18,16 @@ */ package org.alfresco.module.org_alfresco_module_rm.classification.interceptor; +import static org.alfresco.model.ContentModel.TYPE_CONTENT; import static org.codehaus.plexus.util.StringUtils.isNotBlank; import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; -import org.alfresco.model.ContentModel; 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.classification.interceptor.processor.BasePostMethodInvocationProcessor; import org.alfresco.module.org_alfresco_module_rm.util.AlfrescoTransactionSupport; import org.alfresco.module.org_alfresco_module_rm.util.AuthenticationUtil; import org.alfresco.repo.security.permissions.AccessDeniedException; @@ -37,6 +40,7 @@ import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.GUID; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; +import org.apache.log4j.Logger; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -49,6 +53,12 @@ import org.springframework.context.ApplicationContextAware; */ public class ClassificationMethodInterceptor implements MethodInterceptor, ApplicationContextAware { + /** Logger */ + private static Logger LOG = Logger.getLogger(ClassificationMethodInterceptor.class); + + /** Post method invocation processors */ + private Map, BasePostMethodInvocationProcessor> processors = new HashMap, BasePostMethodInvocationProcessor>(); + private static final String KEY_PROCESSING = GUID.generate(); /** application context */ @@ -72,7 +82,7 @@ public class ClassificationMethodInterceptor implements MethodInterceptor, Appli /** * @return {@link ContentClassificationService} content classification service */ - protected ContentClassificationService getContentClassificaitonService() + protected ContentClassificationService getContentClassificationService() { return (ContentClassificationService)applicationContext.getBean("contentClassificationService"); } @@ -102,6 +112,16 @@ public class ClassificationMethodInterceptor implements MethodInterceptor, Appli return (DictionaryService)applicationContext.getBean("dictionaryService"); } + /** + * Registers the post method invocation processors + * + * @param object The object to register + */ + public void register(BasePostMethodInvocationProcessor object) + { + processors.put(object.getClassName(), object); + } + /** * Check that the current user is cleared to see the items passed as parameters to the current * method invocation. @@ -176,8 +196,8 @@ public class ClassificationMethodInterceptor implements MethodInterceptor, Appli private void checkNode(NodeRef testNodeRef) { if (getNodeService().exists(testNodeRef) && - getDictionaryService().isSubClass(getNodeService().getType(testNodeRef), ContentModel.TYPE_CONTENT) && - !getContentClassificaitonService().hasClearance(testNodeRef)) + getDictionaryService().isSubClass(getNodeService().getType(testNodeRef), TYPE_CONTENT) && + !getContentClassificationService().hasClearance(testNodeRef)) { // throw exception throw new AccessDeniedException("You do not have clearance!"); @@ -192,19 +212,28 @@ public class ClassificationMethodInterceptor implements MethodInterceptor, Appli { boolean isValidUser = validUser(); + // pre method invocation check if (isValidUser) { - // pre method invocation check checkClassification(invocation); } // method proceed Object result = invocation.proceed(); - if (isValidUser) + // post method invocation processing + if (isValidUser && result != null) { - // post method invocation processing - // TODO + Class clazz = result.getClass(); + BasePostMethodInvocationProcessor processor = processors.get(clazz); + if (processor != null) + { + processor.process(result); + } + else + { + LOG.warn("No post method invocation processor found for '" + clazz + "'."); + } } return result; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/AssociationRefPostMethodInvocationProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/AssociationRefPostMethodInvocationProcessor.java new file mode 100644 index 0000000000..85b5243636 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/AssociationRefPostMethodInvocationProcessor.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2005-2015 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 . + */ +package org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor; + +import static org.alfresco.util.ParameterCheck.mandatory; + +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * AssociationRef Post Method Invocation Processor + * + * @author Tuna Aksoy + * @since 3.0 + */ +public class AssociationRefPostMethodInvocationProcessor extends BasePostMethodInvocationProcessor +{ + /** + * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#getClassName() + */ + @Override + public Class getClassName() + { + return AssociationRef.class; + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#process(java.lang.Object) + */ + @Override + public T process(T object) + { + mandatory("object", object); + + AssociationRef associationRef = ((AssociationRef) object); + + NodeRef sourceRef = associationRef.getSourceRef(); + check(sourceRef); + + NodeRef targetRef = associationRef.getTargetRef(); + check(targetRef); + + return object; + } +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/BasePostMethodInvocationProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/BasePostMethodInvocationProcessor.java new file mode 100644 index 0000000000..f66d0d0b94 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/BasePostMethodInvocationProcessor.java @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2005-2015 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 . + */ +package org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor; + +import org.alfresco.model.ContentModel; +import org.alfresco.module.org_alfresco_module_rm.classification.ContentClassificationService; +import org.alfresco.module.org_alfresco_module_rm.classification.interceptor.ClassificationMethodInterceptor; +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; + +/** + * Base class for post method invocation processors + * + * @author Tuna Aksoy + * @since 3.0 + */ +public abstract class BasePostMethodInvocationProcessor +{ + /** Classification method interceptor */ + private ClassificationMethodInterceptor classificationMethodInterceptor; + + /** Node service */ + private NodeService nodeService; + + /** Dictionary service */ + private DictionaryService dictionaryService; + + /** Content classification service */ + private ContentClassificationService contentClassificationService; + + /** + * @return the classificationMethodInterceptor + */ + protected ClassificationMethodInterceptor getClassificationMethodInterceptor() + { + return this.classificationMethodInterceptor; + } + + /** + * @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 classificationMethodInterceptor the classificationMethodInterceptor to set + */ + public void setClassificationMethodInterceptor(ClassificationMethodInterceptor classificationMethodInterceptor) + { + this.classificationMethodInterceptor = classificationMethodInterceptor; + } + + /** + * @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; + } + + /** + * Performs checks on the given object and throws exception if not all checks pass + * + * @param object The object to check + * @return The given object + */ + public abstract T process(T object); + + /** + * Gets the class name + * + * @return The class name + */ + public abstract Class getClassName(); + + /** + * Registers the post method invocation processors + */ + public void register() + { + getClassificationMethodInterceptor().register(this); + } + + /** + * Performs checks on the given node: + * + *
    + *
  • Does the node exist
  • + *
  • Is it a content
  • + *
  • Is the logged in user cleared to see the it.
  • + *
+ * + * @param nodeRef Node reference + */ + protected void check(NodeRef nodeRef) + { + if (getNodeService().exists(nodeRef) && + getDictionaryService().isSubClass(getNodeService().getType(nodeRef), ContentModel.TYPE_CONTENT) && + !getContentClassificationService().hasClearance(nodeRef)) + { + // throw exception + throw new AccessDeniedException("You do not have clearance!"); + } + } +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ChildAssociationRefPostMethodInvocationProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ChildAssociationRefPostMethodInvocationProcessor.java new file mode 100644 index 0000000000..c868c34ea2 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ChildAssociationRefPostMethodInvocationProcessor.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2005-2015 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 . + */ +package org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor; + +import static org.alfresco.util.ParameterCheck.mandatory; + +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * ChildAssociationRef Post Method Invocation Processor + * + * @author Tuna Aksoy + * @since 3.0 + */ +public class ChildAssociationRefPostMethodInvocationProcessor extends BasePostMethodInvocationProcessor +{ + /** + * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#getClassName() + */ + @Override + public Class getClassName() + { + return ChildAssociationRef.class; + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#process(java.lang.Object) + */ + @Override + public T process(T object) + { + mandatory("object", object); + + ChildAssociationRef childAssociationRef = ((ChildAssociationRef) object); + + NodeRef childRef = childAssociationRef.getChildRef(); + check(childRef); + + NodeRef parentRef = childAssociationRef.getParentRef(); + check(parentRef); + + return object; + } +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/NodeRefPostMethodInvocationProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/NodeRefPostMethodInvocationProcessor.java new file mode 100644 index 0000000000..8d78d7e4c6 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/NodeRefPostMethodInvocationProcessor.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2005-2015 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 . + */ +package org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor; + +import static org.alfresco.util.ParameterCheck.mandatory; + +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * NodeRef Post Method Invocation Processor + * + * @author Tuna Aksoy + * @since 3.0 + */ +public class NodeRefPostMethodInvocationProcessor extends BasePostMethodInvocationProcessor +{ + /** + * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#getClassName() + */ + @Override + public Class getClassName() + { + return NodeRef.class; + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#process(java.lang.Object) + */ + @Override + public T process(T object) + { + mandatory("object", object); + + check(((NodeRef) object)); + + return object; + } +}