From 2292b2a27448643914c43b914c98c9c45df1da63 Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Wed, 12 Aug 2015 00:51:26 +0000 Subject: [PATCH 1/5] Test branch for exploritory work git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/DEV/ROYTEST@109930 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 From a2399356682f698b33e8af76c5db7b6180e05b4d Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Wed, 12 Aug 2015 04:57:37 +0000 Subject: [PATCH 2/5] Classification enforcement refactor * added permission veto registry * extend permission service to check vetos before permission evaluation * register classification veto * unit and integration tests run * UI tests run git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/DEV/ROYTEST@109931 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../classified-content-context.xml | 24 +- .../extended-repository-context.xml | 72 ++---- .../caveat/RMCaveatConfigComponentImpl.java | 3 +- .../ContentClassificationServiceImpl.java | 11 +- .../ClassificationMethodInterceptor.java | 122 --------- ...icationMethodInterceptorPostProcessor.java | 83 ------- .../ArrayPostMethodInvocationProcessor.java | 90 ------- ...ationRefPostMethodInvocationProcessor.java | 69 ----- .../BasePostMethodInvocationProcessor.java | 159 ------------ ...ationRefPostMethodInvocationProcessor.java | 80 ------ ...llectionPostMethodInvocationProcessor.java | 84 ------- .../NodeRefPostMethodInvocationProcessor.java | 61 ----- ...gResultsPostMethodInvocationProcessor.java | 94 ------- ...eckValuePostMethodInvocationProcessor.java | 63 ----- .../PostMethodInvocationProcessor.java | 119 --------- .../PreMethodInvocationProcessor.java | 235 ------------------ ...eResultsPostMethodInvocationProcessor.java | 84 ------- ...esultSetPostMethodInvocationProcessor.java | 118 --------- ...StoreRefPostMethodInvocationProcessor.java | 63 ----- .../veto/ClassificationPermissionVeto.java | 68 +++++ ...ava => ExtendedPermissionServiceImpl.java} | 33 ++- .../permissions/veto/PermissionVeto.java} | 79 +++--- .../veto/PermissionVetoBaseImpl.java | 45 ++++ .../veto/PermissionVetoRegistry.java | 48 ++++ ...ionEnforcementPreMethodInvocationTest.java | 2 +- ...PostMethodInvocationProcessorUnitTest.java | 76 ------ ...PostMethodInvocationProcessorUnitTest.java | 188 -------------- ...PostMethodInvocationProcessorUnitTest.java | 94 ------- ...PostMethodInvocationProcessorUnitTest.java | 91 ------- 29 files changed, 268 insertions(+), 2090 deletions(-) delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/ClassificationMethodInterceptor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/ClassificationMethodInterceptorPostProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ArrayPostMethodInvocationProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/AssociationRefPostMethodInvocationProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/BasePostMethodInvocationProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ChildAssociationRefPostMethodInvocationProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/CollectionPostMethodInvocationProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/NodeRefPostMethodInvocationProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PagingResultsPostMethodInvocationProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PermissionCheckValuePostMethodInvocationProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PostMethodInvocationProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PreMethodInvocationProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/QueryEngineResultsPostMethodInvocationProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ResultSetPostMethodInvocationProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/StoreRefPostMethodInvocationProcessor.java create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/veto/ClassificationPermissionVeto.java rename rm-server/source/java/org/alfresco/repo/security/permissions/impl/{RMPermissionServiceImpl.java => ExtendedPermissionServiceImpl.java} (88%) rename rm-server/source/java/org/alfresco/{module/org_alfresco_module_rm/classification/interceptor/processor/AccessDeniedException.java => repo/security/permissions/veto/PermissionVeto.java} (56%) create mode 100644 rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoBaseImpl.java create mode 100644 rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoRegistry.java delete mode 100644 rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ArrayPostMethodInvocationProcessorUnitTest.java delete mode 100644 rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/CollectionPostMethodInvocationProcessorUnitTest.java delete mode 100644 rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/NodeRefPostMethodInvocationProcessorUnitTest.java delete mode 100644 rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/QueryEngineResultsPostMethodInvocationProcessorUnitTest.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 0c4e6e1714..fcec3ce501 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 @@ -39,26 +39,14 @@ - - - - + + + + + + - - - - - - - - - - diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/extended-repository-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/extended-repository-context.xml index b2d874242c..2e6f353638 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/extended-repository-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/extended-repository-context.xml @@ -26,6 +26,7 @@ + @@ -34,6 +35,7 @@ + org.alfresco.repo.security.permissions.impl.ExtendedPermissionService @@ -51,6 +53,7 @@ + @@ -77,11 +80,11 @@ + - - + @@ -92,48 +95,20 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${security.anyDenyDenies} - + + + + + + + + + + + + + + @@ -142,13 +117,14 @@ - - - + + + + + - diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/RMCaveatConfigComponentImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/RMCaveatConfigComponentImpl.java index 5ce3db65c3..3462c5028c 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/RMCaveatConfigComponentImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/RMCaveatConfigComponentImpl.java @@ -35,10 +35,11 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import net.sf.acegisecurity.AccessDeniedException; + import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.caveat.RMListOfValuesConstraint.MatchLogic; -import org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.AccessDeniedException; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.cache.SimpleCache; import org.alfresco.repo.content.ContentServicePolicies; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImpl.java index d7d04a3ce1..b0bb3043eb 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImpl.java @@ -203,9 +203,14 @@ public class ContentClassificationServiceImpl extends ServiceBaseImpl @Override public boolean hasClearance(NodeRef nodeRef) { - // Get the node's current classification - ClassificationLevel currentClassification = getCurrentClassification(nodeRef); - return securityClearanceService.isCurrentUserClearedForClassification(currentClassification.getId()); + boolean result = true; + if (nodeService.exists(nodeRef)) + { + // Get the node's current classification + ClassificationLevel currentClassification = getCurrentClassification(nodeRef); + result = securityClearanceService.isCurrentUserClearedForClassification(currentClassification.getId()); + } + return result; } /** 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 deleted file mode 100644 index 468174eb57..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/ClassificationMethodInterceptor.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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; - -import static org.alfresco.repo.security.authentication.AuthenticationUtil.getFullyAuthenticatedUser; -import static org.alfresco.repo.security.authentication.AuthenticationUtil.isRunAsUserTheSystemUser; -import static org.alfresco.util.ParameterCheck.mandatory; -import static org.apache.commons.lang3.StringUtils.isNotBlank; - -import org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.PostMethodInvocationProcessor; -import org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.PreMethodInvocationProcessor; -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - -/** - * Classification method interceptor - * - * @author Roy Wetherall - * @author Tuna Aksoy - * @since 3.0.a - */ -public class ClassificationMethodInterceptor implements MethodInterceptor -{ - /** Pre method invocation processor */ - private PreMethodInvocationProcessor preMethodInvocationProcessor; - - /** Post method invocation processor */ - private PostMethodInvocationProcessor postMethodInvocationProcessor; - - /** - * @return the preMethodInvocationProcessor - */ - protected PreMethodInvocationProcessor getPreMethodInvocationProcessor() - { - return this.preMethodInvocationProcessor; - } - - /** - * @return the postMethodInvocationProcessor - */ - protected PostMethodInvocationProcessor getPostMethodInvocationProcessor() - { - return this.postMethodInvocationProcessor; - } - - /** - * @param postMethodInvocationProcessor the postMethodInvocationProcessor to set - */ - public void setPostMethodInvocationProcessor(PostMethodInvocationProcessor postMethodInvocationProcessor) - { - this.postMethodInvocationProcessor = postMethodInvocationProcessor; - } - - /** - * @param preMethodInvocationProcessor the preMethodInvocationProcessor to set - */ - public void setPreMethodInvocationProcessor(PreMethodInvocationProcessor preMethodInvocationProcessor) - { - this.preMethodInvocationProcessor = preMethodInvocationProcessor; - } - - /** - * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation) - */ - @Override - public Object invoke(MethodInvocation invocation) throws Throwable - { - mandatory("invocation", invocation); - - boolean isUserValid = isUserValid(); - - // Pre method invocation processing - if (isUserValid) - { - getPreMethodInvocationProcessor().process(invocation); - } - - // Method invocation - Object result = invocation.proceed(); - - // Post method invocation processing - if (isUserValid && result != null) - { - result = getPostMethodInvocationProcessor().process(result); - } - - return result; - } - - /** - * Checks if we have an authenticated user and that they aren't "System" - * - * @return true if we have an authenticated user and that they aren't "System", false otherwise. - */ - private boolean isUserValid() - { - boolean result = false; - - if (isNotBlank(getFullyAuthenticatedUser()) && !isRunAsUserTheSystemUser()) - { - result = true; - } - - return result; - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/ClassificationMethodInterceptorPostProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/ClassificationMethodInterceptorPostProcessor.java deleted file mode 100644 index dc81660d32..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/ClassificationMethodInterceptorPostProcessor.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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; - -import org.springframework.beans.BeansException; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.PropertyValue; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.config.RuntimeBeanNameReference; -import org.springframework.beans.factory.support.ManagedList; - -/** - * Classification method interceptor bean factory post processor. - *

- * Bean factory post processor that inspects available beans and adds the classification method interceptor - * to all public services. - * - * @author Roy Wetherall - * @since 3.0.a - */ -public class ClassificationMethodInterceptorPostProcessor implements BeanFactoryPostProcessor -{ - private static final String PROP_INTERCEPTOR_NAMES = "interceptorNames"; - private static final String TYPE_PROXY_FACTORY_BEAN = "ProxyFactoryBean"; - private static final String POSTFIX_SERVICE = "Service"; - private static final String BEAN_NAME_CLASSIFICATION_METHOD_INTERCEPTOR = "classificationMethodInterceptor"; - - /** - * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory) - */ - @SuppressWarnings("unchecked") - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException - { - // get all bean definition names - String beans[] = beanFactory.getBeanDefinitionNames(); - for (String bean : beans) - { - // get bean definition - BeanDefinition beanDefinition = beanFactory.getBeanDefinition(bean); - - // only modify proxy factory beans that follow the public service naming postfix convention - if (beanDefinition.getBeanClassName() != null && - beanDefinition.getBeanClassName().endsWith(TYPE_PROXY_FACTORY_BEAN) && - bean.endsWith(POSTFIX_SERVICE) && - Character.isUpperCase(bean.charAt(0))) - { - // get the property values for the bean definition - MutablePropertyValues propertyValues = beanDefinition.getPropertyValues(); - if (propertyValues.contains(PROP_INTERCEPTOR_NAMES)) - { - // get the current list of interceptor names - PropertyValue value = propertyValues.getPropertyValue(PROP_INTERCEPTOR_NAMES); - ManagedList list = (ManagedList)value.getValue(); - if (!list.isEmpty()) - { - // add reference to classification method interceptor - RuntimeBeanNameReference beanReference = new RuntimeBeanNameReference(BEAN_NAME_CLASSIFICATION_METHOD_INTERCEPTOR); - list.add(beanReference); - } - } - } - } - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ArrayPostMethodInvocationProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ArrayPostMethodInvocationProcessor.java deleted file mode 100644 index 5ef3cfaefc..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ArrayPostMethodInvocationProcessor.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 java.lang.reflect.Array.newInstance; - -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.List; - -import org.springframework.stereotype.Component; - -/** - * Array Post Method Invocation Processor - * - * @author Tuna Aksoy - * @since 3.0.a - */ -@Component -public class ArrayPostMethodInvocationProcessor extends BasePostMethodInvocationProcessor -{ - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#getClassName() - */ - @Override - protected Class getClassName() - { - return Array.class; - } - - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#process(java.lang.Object) - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - protected T process(T object) - { - T result = object; - - if (result != null) - { - T[] objects = (T[]) result; - T obj = objects[0]; - - BasePostMethodInvocationProcessor processor = getPostMethodInvocationProcessor().getProcessor(obj); - if (processor != null) - { - int length = objects.length; - List processedObjects = new ArrayList(); - - for (int i = 0; i < length; i++) - { - Object processedObject = processor.process(objects[i]); - if (processedObject != null) - { - processedObjects.add(processedObject); - } - } - - int size = processedObjects.size(); - T[] objs = (T[]) newInstance(obj.getClass(), size); - - for (int i = 0; i < size; i++) - { - objs[i] = (T) processedObjects.get(i); - } - - result = (T) objs; - } - } - - 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 deleted file mode 100644 index 11b768b52f..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/AssociationRefPostMethodInvocationProcessor.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.service.cmr.repository.AssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; -import org.springframework.stereotype.Component; - -/** - * AssociationRef Post Method Invocation Processor - * - * @author Tuna Aksoy - * @since 3.0.a - */ -@Component -public class AssociationRefPostMethodInvocationProcessor extends BasePostMethodInvocationProcessor -{ - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#getClassName() - */ - @Override - protected Class getClassName() - { - return AssociationRef.class; - } - - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#process(java.lang.Object) - */ - @Override - protected T process(T object) - { - T result = object; - - if (result != null) - { - AssociationRef associationRef = getClassName().cast(result); - - NodeRef sourceRef = associationRef.getSourceRef(); - NodeRef filteredSource = filter(sourceRef); - - NodeRef targetRef = associationRef.getTargetRef(); - NodeRef filteredTarget = filter(targetRef); - - if (filteredSource == null || filteredTarget == null) - { - result = null; - } - } - - return result; - } -} 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 deleted file mode 100644 index b2ddcb4906..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/BasePostMethodInvocationProcessor.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * 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.model.ContentModel.TYPE_CONTENT; - -import javax.annotation.PostConstruct; - -import org.alfresco.module.org_alfresco_module_rm.classification.ContentClassificationService; -import org.alfresco.module.org_alfresco_module_rm.classification.SecurityClearanceService; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.springframework.beans.factory.annotation.Autowired; - -/** - * Base class for post method invocation processors - * - * @author Tuna Aksoy - * @since 3.0.a - */ -public abstract class BasePostMethodInvocationProcessor -{ - /** Node service */ - @Autowired - private NodeService nodeService; - - /** Dictionary service */ - @Autowired - private DictionaryService dictionaryService; - - /** Content classification service */ - @Autowired - private ContentClassificationService contentClassificationService; - - /** Security Clearance Service */ - @Autowired - private SecurityClearanceService securityClearanceService; - - /** Post method invocation processor */ - @Autowired - private PostMethodInvocationProcessor postMethodInvocationProcessor; - - /** Pre method invocation processor */ - @Autowired - private PreMethodInvocationProcessor preMethodInvocationProcessor; - - /** - * @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; - } - - /** - * @return the securityClearanceService - */ - protected SecurityClearanceService getSecurityClearanceService() - { - return this.securityClearanceService; - } - - /** - * @return the postMethodInvocationProcessor - */ - protected PostMethodInvocationProcessor getPostMethodInvocationProcessor() - { - return this.postMethodInvocationProcessor; - } - - /** - * Registers the post method invocation processors - */ - @PostConstruct - private void register() - { - getPostMethodInvocationProcessor().register(this); - } - - /** - * Gets the class name - * - * @return The class name - */ - protected abstract Class getClassName(); - - /** - * Performs checks on the given object and throws exception if not all checks pass - * - * @param object The object to check - * @return The given object - */ - protected abstract T process(T object); - - /** - * Filters the node if the give node reference exist and it is a - * content but the logged in user is not cleared to see the it. - * - * @param nodeRef Node reference - * @return null if the give node reference has been - * filtered, the node reference itself otherwise - */ - protected NodeRef filter(NodeRef nodeRef) - { - NodeRef filter = nodeRef; - - // disable pre-method invocation processor - preMethodInvocationProcessor.disable(); - try - { - if (getNodeService().exists(nodeRef) && - getDictionaryService().isSubClass(getNodeService().getType(nodeRef), TYPE_CONTENT) && - !getContentClassificationService().hasClearance(nodeRef)) - { - filter = null; - } - } - finally - { - // re-enable pre-method invocation processor - preMethodInvocationProcessor.enable(); - } - - return filter; - } -} 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 deleted file mode 100644 index a92354a375..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ChildAssociationRefPostMethodInvocationProcessor.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; -import org.springframework.stereotype.Component; - -/** - * ChildAssociationRef Post Method Invocation Processor - * - * @author Tuna Aksoy - * @since 3.0.a - */ -@Component -public class ChildAssociationRefPostMethodInvocationProcessor extends BasePostMethodInvocationProcessor -{ - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#getClassName() - */ - @Override - protected Class getClassName() - { - return ChildAssociationRef.class; - } - - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#process(java.lang.Object) - */ - @Override - protected T process(T object) - { - T result = object; - - if (result != null) - { - ChildAssociationRef childAssociationRef = getClassName().cast(result); - - NodeRef childRef = childAssociationRef.getChildRef(); - NodeRef filteredChildRef = filter(childRef); - - NodeRef parentRef = childAssociationRef.getParentRef(); - NodeRef filteredParentRef; - - if (parentRef == null) - { - if (filteredChildRef == null) - { - result = null; - } - } - else - { - filteredParentRef = filter(parentRef); - if (filteredChildRef == null || filteredParentRef == null) - { - result = null; - } - } - } - - return result; - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/CollectionPostMethodInvocationProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/CollectionPostMethodInvocationProcessor.java deleted file mode 100644 index 07bdc2f642..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/CollectionPostMethodInvocationProcessor.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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 java.util.Collection; -import java.util.Iterator; - -import org.springframework.stereotype.Component; - -/** - * Collection Post Method Invocation Processor. - * - * @author Tuna Aksoy - * @since 3.0.a - */ -@Component -public class CollectionPostMethodInvocationProcessor extends BasePostMethodInvocationProcessor -{ - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#getClassName() - */ - @SuppressWarnings("rawtypes") - @Override - protected Class getClassName() - { - return Collection.class; - } - - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#process(java.lang.Object) - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - protected T process(T object) - { - T result = object; - - if (result != null) - { - BasePostMethodInvocationProcessor processor = null; - Collection collection = getClassName().cast(object); - Iterator iterator = collection.iterator(); - - while (iterator.hasNext()) - { - Object element = iterator.next(); - if (processor == null) - { - processor = getPostMethodInvocationProcessor().getProcessor(element); - if (processor == null) - { - break; - } - } - - Object processedElement = processor.process(element); - if (processedElement == null) - { - iterator.remove(); - } - } - - result = (T) collection; - } - - return result; - } -} 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 deleted file mode 100644 index 262d6a266c..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/NodeRefPostMethodInvocationProcessor.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.service.cmr.repository.NodeRef; -import org.springframework.stereotype.Component; - -/** - * NodeRef Post Method Invocation Processor - * - * @author Tuna Aksoy - * @since 3.0.a - */ -@Component -public class NodeRefPostMethodInvocationProcessor extends BasePostMethodInvocationProcessor -{ - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#getClassName() - */ - @Override - protected Class getClassName() - { - return NodeRef.class; - } - - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#process(java.lang.Object) - */ - @Override - protected T process(T object) - { - T result = object; - - if (result != null) - { - NodeRef nodeRef = getClassName().cast(result); - if (filter(nodeRef) == null) - { - result = null; - } - } - - return result; - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PagingResultsPostMethodInvocationProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PagingResultsPostMethodInvocationProcessor.java deleted file mode 100644 index 35c30de23d..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PagingResultsPostMethodInvocationProcessor.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 java.util.List; - -import org.alfresco.query.PagingResults; -import org.alfresco.util.Pair; -import org.springframework.stereotype.Component; - -/** - * PagingResults Post Method Invocation Processor - * - * @author Tuna Aksoy - * @since 3.0.a - */ -@Component -public class PagingResultsPostMethodInvocationProcessor extends BasePostMethodInvocationProcessor -{ - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#getClassName() - */ - @SuppressWarnings("rawtypes") - @Override - protected Class getClassName() - { - return PagingResults.class; - } - - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#process(java.lang.Object) - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - protected T process(T object) - { - T result = object; - - if (result != null) - { - final PagingResults pagingResults = getClassName().cast(result); - List page = pagingResults.getPage(); - int originalPageSize = page.size(); - final List processedPage = getPostMethodInvocationProcessor().process(page); - - if (processedPage != null && processedPage.size() != originalPageSize) - { - result = (T) new PagingResults() - { - @Override - public String getQueryExecutionId() - { - return pagingResults.getQueryExecutionId(); - } - @Override - public List getPage() - { - return processedPage; - } - @Override - public boolean hasMoreItems() - { - // hasMoreItems might not be correct. Cannot determine the correct value as request details are needed. - return pagingResults.hasMoreItems(); - } - @Override - public Pair getTotalResultCount() - { - int size = processedPage.size(); - return new Pair(size, size); - } - }; - } - } - - return result; - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PermissionCheckValuePostMethodInvocationProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PermissionCheckValuePostMethodInvocationProcessor.java deleted file mode 100644 index 78e13e36bf..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PermissionCheckValuePostMethodInvocationProcessor.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.repo.security.permissions.PermissionCheckValue; -import org.alfresco.service.cmr.repository.NodeRef; -import org.springframework.stereotype.Component; - -/** - * Permission Check Value Post Method Invocation Processor - * - * @author Tuna Aksoy - * @since 3.0.a - */ -@Component -public class PermissionCheckValuePostMethodInvocationProcessor extends BasePostMethodInvocationProcessor -{ - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#getClassName() - */ - @Override - protected Class getClassName() - { - return PermissionCheckValue.class; - } - - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#process(java.lang.Object) - */ - @Override - protected T process(T object) - { - T result = object; - - if (result != null) - { - PermissionCheckValue permissionCheckValue = getClassName().cast(result); - NodeRef nodeRef = permissionCheckValue.getNodeRef(); - if (filter(nodeRef) == null) - { - result = null; - } - } - - return result; - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PostMethodInvocationProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PostMethodInvocationProcessor.java deleted file mode 100644 index f0a82d8ef2..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PostMethodInvocationProcessor.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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 java.lang.reflect.Array; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * Registry for post method invocation processors - * - * @author Tuna Aksoy - * @since 3.0.a - */ -public class PostMethodInvocationProcessor -{ - /** Post method invocation processors */ - private Map, BasePostMethodInvocationProcessor> processors = new HashMap<>(); - - /** - * Registers a post method invocation processor - * - * @param Post method invocation processor object - */ - public void register(BasePostMethodInvocationProcessor object) - { - mandatory("object", object); - - getProcessors().put(object.getClassName(), object); - } - - /** - * Gets all the available processors - * - * @return the processors Available processors - */ - private Map, BasePostMethodInvocationProcessor> getProcessors() - { - return this.processors; - } - - /** - * Gets the processor from the available processors - * - * @param object The post invocation object - * @return The suitable processor for the given class - */ - protected BasePostMethodInvocationProcessor getProcessor(Object object) - { - BasePostMethodInvocationProcessor result = null; - - if (object != null) - { - Class clazz = object.getClass(); - - if (clazz.isArray()) - { - result = getProcessors().get(Array.class); - } - - if (result == null) - { - Set, BasePostMethodInvocationProcessor>> processorsEntrySet = getProcessors().entrySet(); - for (Map.Entry, BasePostMethodInvocationProcessor> processorEntry : processorsEntrySet) - { - if (processorEntry.getKey().isAssignableFrom(clazz)) - { - result = processorEntry.getValue(); - break; - } - } - } - } - - return result; - } - - /** - * Processes the given object - * - * @param object The object to process - * @return The processed object - */ - public T process(T object) - { - T result = object; - - if (result != null) - { - BasePostMethodInvocationProcessor processor = getProcessor(result); - if (processor != null) - { - result = processor.process(result); - } - } - - return result; - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PreMethodInvocationProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PreMethodInvocationProcessor.java deleted file mode 100644 index cf217e50da..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/PreMethodInvocationProcessor.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * 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 java.lang.Boolean.TRUE; -import static org.alfresco.model.ContentModel.TYPE_CONTENT; -import static org.alfresco.repo.security.authentication.AuthenticationUtil.getFullyAuthenticatedUser; -import static org.alfresco.util.GUID.generate; -import static org.alfresco.util.ParameterCheck.mandatory; - -import java.lang.reflect.Method; - -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.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; -import org.springframework.context.ApplicationContextAware; - -/** - * Pre method invocation processor - * - * @author Roy Wetherall - * @author Tuna Aksoy - * @since 3.0.a - */ -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"); - } - - /** - * Gets the node service - * - * @return The node service - */ - protected NodeService getNodeService() - { - return (NodeService) applicationContext.getBean("dbNodeService"); - } - - /** - * Gets the dictionary service - * - * @return The dictionary service - */ - protected DictionaryService getDictionaryService() - { - return (DictionaryService) applicationContext.getBean("dictionaryService"); - } - - /** - * Gets the alfresco transaction support - * - * @return The alfresco transaction support - */ - protected AlfrescoTransactionSupport getAlfrescoTransactionSupport() - { - return (AlfrescoTransactionSupport) applicationContext.getBean("rm.alfrescoTransactionSupport"); - } - - /** - * Gets the retrying transaction helper - * - * @return The retrying transaction helper - */ - protected RetryingTransactionHelper getRetryingTransactionHelper() - { - return ((TransactionService) applicationContext.getBean("transactionService")).getRetryingTransactionHelper(); - } - - /** - * Gets the classification service bootstrap - * - * @return The classification service bootstrap - */ - protected ClassificationServiceBootstrap getClassificationServiceBootstrap() - { - return (ClassificationServiceBootstrap) applicationContext.getBean("classificationServiceBootstrap"); - } - - /** - * is pre-processing enabled? - * - * @return boolean true if enabled, false otherwise - */ - public boolean isEnabled() - { - return (getAlfrescoTransactionSupport().getResource(KEY_PROCESSING) == null); - } - - /** - * disable pre-processing for this transaction - */ - public void disable() - { - // mark the transaction as processing a classification check - getAlfrescoTransactionSupport().bindResource(KEY_PROCESSING, TRUE); - } - - /** - * enable pre-processing for this transaction - */ - public void enable() - { - // clear the transaction as processed a classification check - getAlfrescoTransactionSupport().unbindResource(KEY_PROCESSING); - } - - /** - * 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 - */ - public void process(final MethodInvocation invocation) - { - mandatory("invocation", invocation); - - // do in transaction - getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - @SuppressWarnings("rawtypes") - public Void execute() throws Throwable - { - // ensure classification service has been bootstrapped - if (getClassificationServiceBootstrap().isInitialised()) - { - // if pre-processing is enabled - if (isEnabled()) - { - 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)) - { - // disable pre-processing - disable(); - try - { - // get the value of the parameter - NodeRef testNodeRef = (NodeRef) invocation.getArguments()[position]; - - // if node exists then see if the current user has clearance - isNodeCleared(testNodeRef, method); - } - finally - { - // re-enable pre-processing - enable(); - } - } - - position++; - } - } - } - - return null; - } - }, true); - } - - /** - * Checks if the given node exists, if it is a content and if - * the currently logged in user is cleared to see it. - * - * @param nodeRef Node reference to check - * @param method The invoked method - */ - private void isNodeCleared(NodeRef nodeRef, Method method) - { - if (nodeRef != null && - getNodeService().exists(nodeRef) && - getDictionaryService().isSubClass(getNodeService().getType(nodeRef), TYPE_CONTENT) && - !getContentClassificationService().hasClearance(nodeRef)) - { - String className = method.getDeclaringClass().getSimpleName(); - String methodName = method.getName(); - String name = className + "." + methodName; - - throw new AccessDeniedException("Access is denied for the user '" + getFullyAuthenticatedUser() - + "' to call the method '" + name + "' for the node '" + nodeRef + "'."); - } - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/QueryEngineResultsPostMethodInvocationProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/QueryEngineResultsPostMethodInvocationProcessor.java deleted file mode 100644 index 55b5f1a647..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/QueryEngineResultsPostMethodInvocationProcessor.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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 java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import org.alfresco.repo.search.impl.querymodel.QueryEngineResults; -import org.alfresco.service.cmr.search.ResultSet; -import org.springframework.stereotype.Component; - -/** - * A post method invocation processor for {@link QueryEngineResults}. - * - * @author Tom Page - * @since 3.0.a - */ -@Component -public class QueryEngineResultsPostMethodInvocationProcessor extends BasePostMethodInvocationProcessor -{ - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#getClassName() - */ - @Override - protected Class getClassName() - { - return QueryEngineResults.class; - } - - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#process(java.lang.Object) - */ - @SuppressWarnings("unchecked") - @Override - protected T process(T object) - { - T result = object; - - if (result != null) - { - QueryEngineResults queryEngineResults = getClassName().cast(result); - Map, ResultSet> resultsMap = queryEngineResults.getResults(); - Map, ResultSet> returnMap = new HashMap<>(); - BasePostMethodInvocationProcessor processor = null; - - for (Entry, ResultSet> entry : resultsMap.entrySet()) - { - ResultSet value = entry.getValue(); - if (processor == null) - { - processor = getPostMethodInvocationProcessor().getProcessor(value); - } - - ResultSet newResultSet = processor.process(value); - if (newResultSet != null) - { - returnMap.put(entry.getKey(), newResultSet); - } - } - - result = (T) new QueryEngineResults(returnMap); - } - - return result; - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ResultSetPostMethodInvocationProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ResultSetPostMethodInvocationProcessor.java deleted file mode 100644 index 71d0500410..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ResultSetPostMethodInvocationProcessor.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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.service.cmr.search.PermissionEvaluationMode.EAGER; - -import java.util.BitSet; - -import org.alfresco.repo.search.SimpleResultSetMetaData; -import org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSet; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.search.ResultSet; -import org.alfresco.service.cmr.search.ResultSetMetaData; -import org.alfresco.service.cmr.search.ResultSetRow; -import org.alfresco.service.cmr.search.SearchParameters; -import org.springframework.stereotype.Component; - -/** - * ResultSet Post Method Invocation Processor - * - * @author Tuna Aksoy - * @since 3.0.a - */ -@Component -public class ResultSetPostMethodInvocationProcessor extends BasePostMethodInvocationProcessor -{ - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#getClassName() - */ - @Override - protected Class getClassName() - { - return ResultSet.class; - } - - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.CollectionPostMethodInvocationProcessor#process(java.lang.Object) - */ - @SuppressWarnings({ "unchecked" }) - @Override - protected T process(T object) - { - T result = object; - - if (result != null) - { - ResultSet returnedObject = getClassName().cast(result); - - BitSet inclusionMask = new BitSet(returnedObject.length()); - FilteringResultSet filteringResultSet = new FilteringResultSet(returnedObject, inclusionMask); - - ResultSetMetaData resultSetMetaData = returnedObject.getResultSetMetaData(); - SearchParameters searchParameters = resultSetMetaData.getSearchParameters(); - - BasePostMethodInvocationProcessor nodeRefProcessor = null; - BasePostMethodInvocationProcessor childAssociationRefProcessor = null; - - for (int i = 0; i < returnedObject.length(); i++) - { - ResultSetRow row = returnedObject.getRow(i); - NodeRef nodeRef = row.getNodeRef(); - - if (nodeRefProcessor == null) - { - nodeRefProcessor = getPostMethodInvocationProcessor().getProcessor(nodeRef); - } - - NodeRef processedNodeRef = nodeRefProcessor.process(nodeRef); - if (processedNodeRef == null) - { - inclusionMask.set(i, false); - } - else - { - ChildAssociationRef childAssocRef = row.getChildAssocRef(); - - if (childAssociationRefProcessor == null) - { - childAssociationRefProcessor = getPostMethodInvocationProcessor().getProcessor(childAssocRef); - } - - ChildAssociationRef childAssociationRef = childAssociationRefProcessor.process(childAssocRef); - if (childAssociationRef == null) - { - inclusionMask.set(i, false); - } - else - { - inclusionMask.set(i, true); - } - } - } - - SimpleResultSetMetaData simpleResultSetMetaData = new SimpleResultSetMetaData(resultSetMetaData.getLimitedBy(), EAGER, searchParameters); - filteringResultSet.setResultSetMetaData(simpleResultSetMetaData); - result = (T) filteringResultSet; - } - - return result; - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/StoreRefPostMethodInvocationProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/StoreRefPostMethodInvocationProcessor.java deleted file mode 100644 index 610988fdd5..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/StoreRefPostMethodInvocationProcessor.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.StoreRef; -import org.springframework.stereotype.Component; - -/** - * StoreRef Post Method Invocation Processor - * - * @author Tuna Aksoy - * @since 3.0.a - */ -@Component -public class StoreRefPostMethodInvocationProcessor extends BasePostMethodInvocationProcessor -{ - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#getClassName() - */ - @Override - protected Class getClassName() - { - return StoreRef.class; - } - - /** - * @see org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.BasePostMethodInvocationProcessor#process(java.lang.Object) - */ - @Override - protected T process(T object) - { - T result = object; - - if (result != null) - { - StoreRef storeRef = getClassName().cast(result); - NodeRef nodeRef = getNodeService().getRootNode(storeRef); - if (filter(nodeRef) == null) - { - result = null; - } - } - - return result; - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/veto/ClassificationPermissionVeto.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/veto/ClassificationPermissionVeto.java new file mode 100644 index 0000000000..e3619272f0 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/veto/ClassificationPermissionVeto.java @@ -0,0 +1,68 @@ +/** + * + */ +package org.alfresco.module.org_alfresco_module_rm.classification.veto; + +import java.util.Set; + +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.TransactionalResourceHelper; +import org.alfresco.repo.security.permissions.veto.PermissionVetoBaseImpl; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * @author Roy Wetherall + * @since 3.0.a + */ +public class ClassificationPermissionVeto extends PermissionVetoBaseImpl +{ + private ContentClassificationService contentClassificationService; + + private TransactionalResourceHelper transactionalResourceHelper; + + private ClassificationServiceBootstrap classificationServiceBootstrap; + + public void setContentClassificationService(ContentClassificationService contentClassificationService) + { + this.contentClassificationService = contentClassificationService; + } + + public void setTransactionalResourceHelper(TransactionalResourceHelper transactionalResourceHelper) + { + this.transactionalResourceHelper = transactionalResourceHelper; + } + + public void setClassificationServiceBootstrap(ClassificationServiceBootstrap classificationServiceBootstrap) + { + this.classificationServiceBootstrap = classificationServiceBootstrap; + } + + /** + * @see org.alfresco.repo.security.permissions.veto.PermissionVeto#isVetoed(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) + */ + @Override + public boolean isVetoed(NodeRef nodeRef, String perm) + { + boolean result = false; + + if (classificationServiceBootstrap.isInitialised()) + { + Set processing = transactionalResourceHelper.getSet(ClassificationPermissionVeto.class.getName()); + if (!processing.contains(nodeRef)) + { + processing.add(nodeRef); + try + { + result = !contentClassificationService.hasClearance(nodeRef); + } + finally + { + processing.remove(nodeRef); + } + } + } + + return result; + } +} diff --git a/rm-server/source/java/org/alfresco/repo/security/permissions/impl/RMPermissionServiceImpl.java b/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java similarity index 88% rename from rm-server/source/java/org/alfresco/repo/security/permissions/impl/RMPermissionServiceImpl.java rename to rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java index e01c1be439..dde345990f 100644 --- a/rm-server/source/java/org/alfresco/repo/security/permissions/impl/RMPermissionServiceImpl.java +++ b/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2014 Alfresco Software Limited. + * Copyright (C) 2005-2015 Alfresco Software Limited. * * This file is part of Alfresco * @@ -23,6 +23,7 @@ import static org.apache.commons.lang.StringUtils.isNotBlank; import java.io.Serializable; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; @@ -34,6 +35,8 @@ import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamic import org.alfresco.repo.cache.SimpleCache; import org.alfresco.repo.security.permissions.AccessControlEntry; import org.alfresco.repo.security.permissions.AccessControlList; +import org.alfresco.repo.security.permissions.veto.PermissionVeto; +import org.alfresco.repo.security.permissions.veto.PermissionVetoRegistry; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AuthorityType; @@ -49,7 +52,7 @@ import org.springframework.context.ApplicationEvent; * * @author Roy Wetherall */ -public class RMPermissionServiceImpl extends PermissionServiceImpl +public class ExtendedPermissionServiceImpl extends PermissionServiceImpl implements ExtendedPermissionService { /** Writers simple cache */ @@ -57,6 +60,9 @@ public class RMPermissionServiceImpl extends PermissionServiceImpl /** File plan service */ private FilePlanService filePlanService; + + /** Permission veto registry */ + private PermissionVetoRegistry permissionVetoRegistry; /** * Gets the file plan service @@ -77,6 +83,11 @@ public class RMPermissionServiceImpl extends PermissionServiceImpl { this.filePlanService = filePlanService; } + + public void setPermissionVetoRegistry(PermissionVetoRegistry permissionVetoRegistry) + { + this.permissionVetoRegistry = permissionVetoRegistry; + } /** * @see org.alfresco.repo.security.permissions.impl.PermissionServiceImpl#setAnyDenyDenies(boolean) @@ -85,7 +96,10 @@ public class RMPermissionServiceImpl extends PermissionServiceImpl public void setAnyDenyDenies(boolean anyDenyDenies) { super.setAnyDenyDenies(anyDenyDenies); - writersCache.clear(); + if (writersCache != null) + { + writersCache.clear(); + } } /** @@ -116,6 +130,19 @@ public class RMPermissionServiceImpl extends PermissionServiceImpl @Override public AccessStatus hasPermission(NodeRef nodeRef, String perm) { + // check permission vetos + List permissionVetos = permissionVetoRegistry.getPermissionVetos(); + for (PermissionVeto permissionVeto : permissionVetos) + { + if (permissionVeto.isVetoed(nodeRef, perm)) + { + // TODO add logging so veto cause can be diagnosed + + // veto access to node + return AccessStatus.DENIED; + } + } + AccessStatus acs = super.hasPermission(nodeRef, perm); if (AccessStatus.DENIED.equals(acs) && PermissionService.READ.equals(perm) && diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/AccessDeniedException.java b/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVeto.java similarity index 56% rename from rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/AccessDeniedException.java rename to rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVeto.java index 2d1095fa0f..e180858e58 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/AccessDeniedException.java +++ b/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVeto.java @@ -1,43 +1,36 @@ -/* - * 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.error.AlfrescoRuntimeException; - -/** - * Access denied exception thrown when a user tries to execute a method call on an uncleared node. - * - * @author Tuna Aksoy - * @since 3.0.a - */ -public class AccessDeniedException extends AlfrescoRuntimeException -{ - /** Serial version uid */ - private static final long serialVersionUID = -1546218007029075883L; - - /** - * Constructor - * - * @param key The key of the exception to be localized - */ - public AccessDeniedException(String key) - { - super(key); - } -} +/* + * 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.repo.security.permissions.veto; + +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * @author Roy Wetherall + * @since 3.0.a + */ +public interface PermissionVeto +{ + /** + * + * @param nodeRef + * @param perm + * @return + */ + boolean isVetoed(NodeRef nodeRef, String perm); +} diff --git a/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoBaseImpl.java b/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoBaseImpl.java new file mode 100644 index 0000000000..5ec384e6d7 --- /dev/null +++ b/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoBaseImpl.java @@ -0,0 +1,45 @@ +/* + * 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.repo.security.permissions.veto; + +/** + * @author Roy Wetherall + * @since 3.0.a + */ +public abstract class PermissionVetoBaseImpl implements PermissionVeto +{ + /** permission veto refistry */ + private PermissionVetoRegistry permissionVetoRegistry; + + /** + * @param permissionVetoRegistry permission veto registry + */ + public void setPermissionVetoRegistry(PermissionVetoRegistry permissionVetoRegistry) + { + this.permissionVetoRegistry = permissionVetoRegistry; + } + + /** + * Init method to add this permission veto to the registry + */ + public void init() + { + permissionVetoRegistry.addPermissionVeto(this); + } +} diff --git a/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoRegistry.java b/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoRegistry.java new file mode 100644 index 0000000000..ef117cbb8b --- /dev/null +++ b/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoRegistry.java @@ -0,0 +1,48 @@ +/* + * 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.repo.security.permissions.veto; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Roy Wetherall + * @since 3.0.a + */ +public class PermissionVetoRegistry +{ + /** list of vetos to apply */ + private List permissionVetos = new ArrayList(); + + /** + * @param permissionVeto permission veto + */ + public void addPermissionVeto(PermissionVeto permissionVeto) + { + permissionVetos.add(permissionVeto); + } + + /** + * @return {@link List}<{@link PermissionVeto}> list of permission vetos + */ + public List getPermissionVetos() + { + return permissionVetos; + } +} diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/classification/interceptor/ClassificationEnforcementPreMethodInvocationTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/classification/interceptor/ClassificationEnforcementPreMethodInvocationTest.java index 38aa493450..35172653af 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/classification/interceptor/ClassificationEnforcementPreMethodInvocationTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/classification/interceptor/ClassificationEnforcementPreMethodInvocationTest.java @@ -27,8 +27,8 @@ import java.util.HashMap; import java.util.Map; import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationAspectProperties; -import org.alfresco.module.org_alfresco_module_rm.classification.interceptor.processor.AccessDeniedException; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; +import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ArrayPostMethodInvocationProcessorUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ArrayPostMethodInvocationProcessorUnitTest.java deleted file mode 100644 index c3ba94c6d3..0000000000 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/ArrayPostMethodInvocationProcessorUnitTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE; -import static org.alfresco.util.GUID.generate; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import org.alfresco.service.cmr.repository.NodeRef; -import org.apache.commons.lang3.ArrayUtils; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; - -/** - * Array Post Method Invocation Processor Unit Test - * - * @author Tuna Aksoy - * @since 3.0.a - */ -public class ArrayPostMethodInvocationProcessorUnitTest -{ - private static final NodeRef NODE_REF_1 = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, generate()); - private static final NodeRef NODE_REF_2 = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, generate()); - private static final NodeRef NODE_REF_3 = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, generate()); - private static final NodeRef NODE_REF_4 = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, generate()); - - @InjectMocks private ArrayPostMethodInvocationProcessor arrayPostMethodInvocationProcessor; - @Mock private PostMethodInvocationProcessor mockedPostMethodInvocationProcessor; - @Mock private BasePostMethodInvocationProcessor mockedNodeRefProcessor; - - @Before - public void setUp() - { - initMocks(this); - - when(mockedPostMethodInvocationProcessor.getProcessor(isA(NodeRef.class))).thenReturn(mockedNodeRefProcessor); - - when(mockedNodeRefProcessor.process(NODE_REF_1)).thenReturn(NODE_REF_1); - when(mockedNodeRefProcessor.process(NODE_REF_2)).thenReturn(null); - when(mockedNodeRefProcessor.process(NODE_REF_3)).thenReturn(NODE_REF_3); - when(mockedNodeRefProcessor.process(NODE_REF_4)).thenReturn(null); - } - - @Test - public void testArrayPostMethodInvocationProcessor() - { - NodeRef[] nodes = new NodeRef[] { NODE_REF_1, NODE_REF_2, NODE_REF_3, NODE_REF_4 }; - NodeRef[] processedNodes = arrayPostMethodInvocationProcessor.process(nodes); - - assertEquals(2, processedNodes.length); - assertTrue(ArrayUtils.contains(processedNodes, NODE_REF_1)); - assertTrue(ArrayUtils.contains(processedNodes, NODE_REF_3)); - } -} diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/CollectionPostMethodInvocationProcessorUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/CollectionPostMethodInvocationProcessorUnitTest.java deleted file mode 100644 index 5e481ef93d..0000000000 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/CollectionPostMethodInvocationProcessorUnitTest.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * 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 com.google.common.collect.Lists.newArrayList; -import static java.util.Arrays.asList; -import static org.alfresco.util.GUID.generate; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.SortedSet; -import java.util.TreeSet; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; - -/** - * Unit tests for the {@link CollectionPostMethodInvocationProcessor}. - * - * @author Tom Page - * @since 3.0.a - */ -public class CollectionPostMethodInvocationProcessorUnitTest -{ - private static final String REALLY_LONG_OUTPUT_STRING = generate() + generate(); - private static final String NON_FILTERED = generate(); - private static final String FILTERED = generate(); - - @InjectMocks private CollectionPostMethodInvocationProcessor collectionPostMethodInvocationProcessor; - @Mock private PostMethodInvocationProcessor mockPostMethodInvocationProcessor; - @Mock private BasePostMethodInvocationProcessor mockStringProcessor; - - @Before - public void setUp() - { - initMocks(this); - - when(mockPostMethodInvocationProcessor.getProcessor(isA(List.class))).thenReturn(collectionPostMethodInvocationProcessor); - when(mockPostMethodInvocationProcessor.getProcessor(isA(String.class))).thenReturn(mockStringProcessor); - - when(mockStringProcessor.process(REALLY_LONG_OUTPUT_STRING)).thenReturn(REALLY_LONG_OUTPUT_STRING); - when(mockStringProcessor.process(NON_FILTERED)).thenReturn(NON_FILTERED); - when(mockStringProcessor.process(FILTERED)).thenReturn(null); - } - - @Test - public void testProcess_copesWithNull() - { - Object result = collectionPostMethodInvocationProcessor.process(null); - - assertNull("Expected null collection to be passed through.", result); - } - - @Test - public void testProcess_nullMember() - { - List collection = new ArrayList<>(); - collection.add(null); - - Object result = collectionPostMethodInvocationProcessor.process(collection); - - assertEquals("Expected collection containing null to be passed through.", collection, result); - } - - @Test - public void testProcess_emptyList() - { - List collection = new ArrayList<>(); - - Collection result = collectionPostMethodInvocationProcessor.process(collection); - - assertEquals(collection, result); - } - - @Test - public void testProcess_nonFilteredMember() - { - Object collection = asList(NON_FILTERED); - - Object result = collectionPostMethodInvocationProcessor.process(collection); - - assertEquals("Expected element to still be present in result.", collection, result); - } - - @Test - public void testProcess_filteredMemberInModifiableList() - { - List collection = newArrayList(FILTERED); - - Collection result = collectionPostMethodInvocationProcessor.process(collection); - - assertTrue("Expected an empty list.", result.isEmpty()); - } - - @Test(expected = UnsupportedOperationException.class) - public void testProcess_filteredMemberInUnmodifiableList() - { - List collection = asList(FILTERED, NON_FILTERED); - - collectionPostMethodInvocationProcessor.process(collection); - } - - @Test - public void testProcess_noProcessorDefined() - { - List collection = asList(1, 4, 91); - - Collection result = collectionPostMethodInvocationProcessor.process(collection); - - assertEquals("If no processor is defined for the members then the whole list should be returned.", collection, result); - } - - @SuppressWarnings("unchecked") - @Test - public void testProcess_listOfLists() - { - List innerListA = newArrayList(FILTERED, NON_FILTERED); - List innerListB = newArrayList(FILTERED, NON_FILTERED); - List> collection = newArrayList(innerListA, innerListB); - - Collection> result = collectionPostMethodInvocationProcessor.process(collection); - - List expectedInnerListA = asList(NON_FILTERED); - List expectedInnerListB = asList(NON_FILTERED); - List> expected = asList(expectedInnerListA, expectedInnerListB); - assertEquals(expected, result); - } - - /** - * Given I have a sorted set of input strings - * When I pass it to the collection processor - * Then I expect items above my clearance to be filtered - * And I expect items below my clearance to be passed through - * And I expect the output set to be sorted using the same comparator as the input. - */ - @Test - public void testProcess_sortedSet() - { - // Create a custom comparator that sorts based on the length of the strings. - Comparator comparator = new Comparator() - { - public int compare(String o1, String o2) - { - return o1.length() - o2.length(); - } - }; - - SortedSet collection = new TreeSet<>(comparator); - collection.add(REALLY_LONG_OUTPUT_STRING); - collection.add(NON_FILTERED); - collection.add(FILTERED); - - Collection result = collectionPostMethodInvocationProcessor.process(collection); - - Iterator iterator = result.iterator(); - assertEquals("Expected the first element to be the shortest", NON_FILTERED, iterator.next()); - assertEquals("Expected the second element to be the longest", REALLY_LONG_OUTPUT_STRING, iterator.next()); - assertFalse("Expected two elements in output", iterator.hasNext()); - } -} diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/NodeRefPostMethodInvocationProcessorUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/NodeRefPostMethodInvocationProcessorUnitTest.java deleted file mode 100644 index 9826bfc4f1..0000000000 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/NodeRefPostMethodInvocationProcessorUnitTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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.junit.Assert.assertEquals; -import static org.mockito.Mockito.when; -import static org.springframework.extensions.webscripts.GUID.generate; - -import org.alfresco.module.org_alfresco_module_rm.classification.ContentClassificationService; -import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; -import org.alfresco.service.cmr.repository.NodeRef; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; - -/** - * NodeRef Post Method Invocation Processor Unit Test - * - * @author Tuna Aksoy - * @since 3.0.a - */ -public class NodeRefPostMethodInvocationProcessorUnitTest extends BaseUnitTest -{ - @InjectMocks private NodeRefPostMethodInvocationProcessor nodeRefPostMethodInvocationProcessor; - @Mock private ContentClassificationService mockedContentClassificationService; - @Mock private PreMethodInvocationProcessor mockedPreMethodInvocationProcessor; - - @Test - public void testProcessingNonExistingNode() - { - NodeRef nodeRef = new NodeRef(generate() + "://" + generate() + "/"); - - when(mockedDictionaryService.isSubClass(mockedNodeService.getType(nodeRef), TYPE_CONTENT)).thenReturn(true); - when(mockedContentClassificationService.hasClearance(nodeRef)).thenReturn(true); - - assertEquals(nodeRef, nodeRefPostMethodInvocationProcessor.process(nodeRef)); - } - - @Test - public void testProcessingNonContent() - { - NodeRef nodeRef = generateNodeRef(); - - when(mockedDictionaryService.isSubClass(mockedNodeService.getType(nodeRef), TYPE_CONTENT)).thenReturn(false); - when(mockedContentClassificationService.hasClearance(nodeRef)).thenReturn(true); - - assertEquals(nodeRef, nodeRefPostMethodInvocationProcessor.process(nodeRef)); - } - - @Test - public void testExistingNodeWithUserClearance() - { - NodeRef nodeRef = generateNodeRef(); - - when(mockedDictionaryService.isSubClass(mockedNodeService.getType(nodeRef), TYPE_CONTENT)).thenReturn(true); - when(mockedContentClassificationService.hasClearance(nodeRef)).thenReturn(true); - - assertEquals(nodeRef, nodeRefPostMethodInvocationProcessor.process(nodeRef)); - } - - @Test - public void testExistingNodeWithNoUserClearance() - { - NodeRef nodeRef = generateNodeRef(); - - when(mockedDictionaryService.isSubClass(mockedNodeService.getType(nodeRef), TYPE_CONTENT)).thenReturn(true); - when(mockedContentClassificationService.hasClearance(nodeRef)).thenReturn(false); - - assertEquals(null, nodeRefPostMethodInvocationProcessor.process(nodeRef)); - } - - @Test - public void testProcessingNull() - { - assertEquals("Expected null to be passed through without error.", null, - nodeRefPostMethodInvocationProcessor.process((NodeRef) null)); - } -} diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/QueryEngineResultsPostMethodInvocationProcessorUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/QueryEngineResultsPostMethodInvocationProcessorUnitTest.java deleted file mode 100644 index 4c18056a78..0000000000 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/interceptor/processor/QueryEngineResultsPostMethodInvocationProcessorUnitTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import org.alfresco.repo.search.impl.querymodel.QueryEngineResults; -import org.alfresco.service.cmr.search.ResultSet; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; - -import com.google.common.collect.Sets; - -/** - * Unit tests for {@link QueryEngineResultPostMethodInvocationProcessor}. - * - * @author Tom Page - * @since 3.0.a - */ -public class QueryEngineResultsPostMethodInvocationProcessorUnitTest -{ - private static final Set KEY_1 = Sets.newHashSet("KEY_1"); - private static final Set KEY_2 = Sets.newHashSet("KEY_2"); - private static final Set KEY_3 = Sets.newHashSet("KEY_3"); - private static final Set KEY_4 = Sets.newHashSet("KEY_4"); - private static final ResultSet UNCLASSIFIED_RESULT_SET = mock(ResultSet.class); - private static final ResultSet CLASSIFIED_RESULT_SET = mock(ResultSet.class); - - @InjectMocks - private QueryEngineResultsPostMethodInvocationProcessor processor = new QueryEngineResultsPostMethodInvocationProcessor(); - @Mock - private PostMethodInvocationProcessor mockPostMethodInvocationProcessor; - @Mock - private ResultSetPostMethodInvocationProcessor mockResultSetPMIP; - - @Before - public void setUp() - { - initMocks(this); - - when(mockPostMethodInvocationProcessor.getProcessor(Mockito.any())).thenReturn(mockResultSetPMIP); - - when(mockResultSetPMIP.process(UNCLASSIFIED_RESULT_SET)).thenReturn(UNCLASSIFIED_RESULT_SET); - when(mockResultSetPMIP.process(CLASSIFIED_RESULT_SET)).thenReturn(null); - } - - /** Check that {@code process} filters out the classified result sets. */ - @Test - public void testProcess() - { - Map, ResultSet> resultsMap = new HashMap<>(); - resultsMap.put(KEY_1, UNCLASSIFIED_RESULT_SET); - resultsMap.put(KEY_2, CLASSIFIED_RESULT_SET); - resultsMap.put(KEY_3, UNCLASSIFIED_RESULT_SET); - resultsMap.put(KEY_4, CLASSIFIED_RESULT_SET); - QueryEngineResults queryEngineResults = new QueryEngineResults(resultsMap); - - QueryEngineResults returnedQueryEngineResults = processor.process(queryEngineResults); - - Map, ResultSet> expectedResultSet = new HashMap<>(); - expectedResultSet.put(KEY_1, UNCLASSIFIED_RESULT_SET); - expectedResultSet.put(KEY_3, UNCLASSIFIED_RESULT_SET); - assertEquals("Unexpected results from query.", expectedResultSet, returnedQueryEngineResults.getResults()); - } -} From 1613bba6e1a2814e7303fb4d26989a4f67c5a445 Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Thu, 13 Aug 2015 03:46:43 +0000 Subject: [PATCH 3/5] Classification enforecment refactor * rename veto as permission pre-processor * add support for permission post-processors * add transaction cache to classification enforcement * add records management permission post processor to remove code from extended permission service git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/DEV/ROYTEST@110013 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../classified-content-context.xml | 7 +- .../extended-repository-context.xml | 17 ++- .../org_alfresco_module_rm/module-context.xml | 9 +- .../ClassificationPermissionPreProcessor.java | 138 ++++++++++++++++++ .../veto/ClassificationPermissionVeto.java | 68 --------- ...ordsManagementPermissionPostProcessor.java | 73 +++++++++ .../impl/ExtendedPermissionService.java | 6 + .../impl/ExtendedPermissionServiceImpl.java | 64 ++++---- .../PermissionPostProcessor.java} | 35 ++--- .../PermissionPreProcessor.java} | 19 ++- .../PermissionProcessorRegistry.java | 77 ++++++++++ .../impl/PermissionPostProcessorBaseImpl.java | 42 ++++++ .../impl/PermissionPreProcessorBaseImpl.java} | 27 ++-- .../impl/PermissionProcessorBaseImpl.java | 49 +++++++ 14 files changed, 483 insertions(+), 148 deletions(-) create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/permission/ClassificationPermissionPreProcessor.java delete mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/veto/ClassificationPermissionVeto.java create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/permission/RecordsManagementPermissionPostProcessor.java rename rm-server/source/java/org/alfresco/repo/security/permissions/{veto/PermissionVetoRegistry.java => processor/PermissionPostProcessor.java} (56%) rename rm-server/source/java/org/alfresco/repo/security/permissions/{veto/PermissionVeto.java => processor/PermissionPreProcessor.java} (65%) create mode 100644 rm-server/source/java/org/alfresco/repo/security/permissions/processor/PermissionProcessorRegistry.java create mode 100644 rm-server/source/java/org/alfresco/repo/security/permissions/processor/impl/PermissionPostProcessorBaseImpl.java rename rm-server/source/java/org/alfresco/repo/security/permissions/{veto/PermissionVetoBaseImpl.java => processor/impl/PermissionPreProcessorBaseImpl.java} (57%) create mode 100644 rm-server/source/java/org/alfresco/repo/security/permissions/processor/impl/PermissionProcessorBaseImpl.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 fcec3ce501..4538616042 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 @@ -40,11 +40,14 @@ - - + + + diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/extended-repository-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/extended-repository-context.xml index 2e6f353638..45629a6076 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/extended-repository-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/extended-repository-context.xml @@ -96,19 +96,24 @@ - - + + - - - + + + + + + + + - + diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml index 9e2d78befd..d41aee942e 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml @@ -18,9 +18,8 @@ - - + + + + + + + diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/permission/ClassificationPermissionPreProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/permission/ClassificationPermissionPreProcessor.java new file mode 100644 index 0000000000..81fecae508 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/permission/ClassificationPermissionPreProcessor.java @@ -0,0 +1,138 @@ +/* + * 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.permission; + +import java.util.Map; +import java.util.Set; + +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.AuthenticationUtil; +import org.alfresco.module.org_alfresco_module_rm.util.TransactionalResourceHelper; +import org.alfresco.repo.security.permissions.processor.impl.PermissionPreProcessorBaseImpl; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.util.Triple; + +/** + * Classification permission pre-processor implementation. + * + * @author Roy Wetherall + * @since 3.0.a + */ +public class ClassificationPermissionPreProcessor extends PermissionPreProcessorBaseImpl +{ + /** transaction resource keys */ + private static final String KEY_PROCESSING = ClassificationPermissionPreProcessor.class.getName() + ".processing"; + private static final String KEY_CACHE = ClassificationPermissionPreProcessor.class.getName() + ".cache"; + + /** content classification service */ + private ContentClassificationService contentClassificationService; + + /** transaction resource helper */ + private TransactionalResourceHelper transactionalResourceHelper; + + /** classificaiton service bootstrap */ + private ClassificationServiceBootstrap classificationServiceBootstrap; + + /** authentication util */ + private AuthenticationUtil authenticationUtil; + + /** + * @param contentClassificationService content classification service + */ + public void setContentClassificationService(ContentClassificationService contentClassificationService) + { + this.contentClassificationService = contentClassificationService; + } + + /** + * @param transactionalResourceHelper transaction resource helper + */ + public void setTransactionalResourceHelper(TransactionalResourceHelper transactionalResourceHelper) + { + this.transactionalResourceHelper = transactionalResourceHelper; + } + + /** + * @param classificationServiceBootstrap classification service bootstrap + */ + public void setClassificationServiceBootstrap(ClassificationServiceBootstrap classificationServiceBootstrap) + { + this.classificationServiceBootstrap = classificationServiceBootstrap; + } + + /** + * @param authenticationUtil authentication util + */ + public void setAuthenticationUtil(AuthenticationUtil authenticationUtil) + { + this.authenticationUtil = authenticationUtil; + } + + /** + * @see org.alfresco.repo.security.permissions.processor.PermissionPreProcessor#process(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) + */ + @Override + public AccessStatus process(NodeRef nodeRef, String perm) + { + AccessStatus result = AccessStatus.UNDETERMINED; + + // ensure the classification bootstrap has been initialised + if (classificationServiceBootstrap.isInitialised()) + { + // do not process a node that is already being processed + Set processing = transactionalResourceHelper.getSet(KEY_PROCESSING); + if (!processing.contains(nodeRef)) + { + processing.add(nodeRef); + try + { + // create key + final String currentUser = authenticationUtil.getRunAsUser(); + Triple key = new Triple(nodeRef, perm, currentUser); + + // get transaction cache (the purpose of this is prevent duplicate tests within the same transaction) + Map, AccessStatus> cache = transactionalResourceHelper.getMap(KEY_CACHE); + if (!cache.containsKey(key)) + { + // determine whether the current user has clearance for the node + if (!contentClassificationService.hasClearance(nodeRef)) + { + result = AccessStatus.DENIED; + } + + // cache value (in transaction) + cache.put(key, result); + } + else + { + result = cache.get(key); + } + } + finally + { + processing.remove(nodeRef); + } + } + } + + return result; + } +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/veto/ClassificationPermissionVeto.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/veto/ClassificationPermissionVeto.java deleted file mode 100644 index e3619272f0..0000000000 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/veto/ClassificationPermissionVeto.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * - */ -package org.alfresco.module.org_alfresco_module_rm.classification.veto; - -import java.util.Set; - -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.TransactionalResourceHelper; -import org.alfresco.repo.security.permissions.veto.PermissionVetoBaseImpl; -import org.alfresco.service.cmr.repository.NodeRef; - -/** - * @author Roy Wetherall - * @since 3.0.a - */ -public class ClassificationPermissionVeto extends PermissionVetoBaseImpl -{ - private ContentClassificationService contentClassificationService; - - private TransactionalResourceHelper transactionalResourceHelper; - - private ClassificationServiceBootstrap classificationServiceBootstrap; - - public void setContentClassificationService(ContentClassificationService contentClassificationService) - { - this.contentClassificationService = contentClassificationService; - } - - public void setTransactionalResourceHelper(TransactionalResourceHelper transactionalResourceHelper) - { - this.transactionalResourceHelper = transactionalResourceHelper; - } - - public void setClassificationServiceBootstrap(ClassificationServiceBootstrap classificationServiceBootstrap) - { - this.classificationServiceBootstrap = classificationServiceBootstrap; - } - - /** - * @see org.alfresco.repo.security.permissions.veto.PermissionVeto#isVetoed(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) - */ - @Override - public boolean isVetoed(NodeRef nodeRef, String perm) - { - boolean result = false; - - if (classificationServiceBootstrap.isInitialised()) - { - Set processing = transactionalResourceHelper.getSet(ClassificationPermissionVeto.class.getName()); - if (!processing.contains(nodeRef)) - { - processing.add(nodeRef); - try - { - result = !contentClassificationService.hasClearance(nodeRef); - } - finally - { - processing.remove(nodeRef); - } - } - } - - return result; - } -} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/permission/RecordsManagementPermissionPostProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/permission/RecordsManagementPermissionPostProcessor.java new file mode 100644 index 0000000000..8650a2aab1 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/permission/RecordsManagementPermissionPostProcessor.java @@ -0,0 +1,73 @@ +/* + * 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.permission; + +import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.repo.security.permissions.processor.impl.PermissionPostProcessorBaseImpl; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; + +/** + * Records management permission post processor. + * + * @author Roy Wetherall + * @since 3.0.a + */ +public class RecordsManagementPermissionPostProcessor extends PermissionPostProcessorBaseImpl +{ + /** node service */ + private NodeService nodeService; + public void setNodeService(NodeService nodeService) {this.nodeService=nodeService;} + + /** permission service */ + private PermissionService permissionService; + public void setPermissionService(PermissionService permissionService) {this.permissionService=permissionService;} + + /** + * @see org.alfresco.repo.security.permissions.processor.PermissionPostProcessor#process(org.alfresco.service.cmr.security.AccessStatus, org.alfresco.service.cmr.repository.NodeRef, java.lang.String) + */ + @Override + public AccessStatus process(AccessStatus accessStatus, NodeRef nodeRef, String perm) + { + AccessStatus result = accessStatus; + if (AccessStatus.DENIED.equals(accessStatus) && + nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT)) + { + // if read denied on rm artifact + if (PermissionService.READ.equals(perm)) + { + // check for read record + result = permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS); + } + // if write deinied on rm artificat + else if (PermissionService.WRITE.equals(perm)) + { + // check for file record + result = permissionService.hasPermission(nodeRef, RMPermissionModel.FILE_RECORDS); + } + } + + return result; + + } + +} diff --git a/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionService.java b/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionService.java index 779301e83d..a3fcc5d0bf 100644 --- a/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionService.java +++ b/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionService.java @@ -30,5 +30,11 @@ import org.alfresco.service.cmr.security.PermissionService; */ public interface ExtendedPermissionService extends PermissionService { + /** + * Get a set of all the authorities that have write access. + * + * @param aclId acl id + * @return {@link Set}<{@link String}> set of authorities with write access + */ Set getWriters(Long aclId); } diff --git a/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java b/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java index dde345990f..5cc2a0a552 100644 --- a/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java +++ b/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java @@ -35,8 +35,9 @@ import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamic import org.alfresco.repo.cache.SimpleCache; import org.alfresco.repo.security.permissions.AccessControlEntry; import org.alfresco.repo.security.permissions.AccessControlList; -import org.alfresco.repo.security.permissions.veto.PermissionVeto; -import org.alfresco.repo.security.permissions.veto.PermissionVetoRegistry; +import org.alfresco.repo.security.permissions.processor.PermissionPostProcessor; +import org.alfresco.repo.security.permissions.processor.PermissionPreProcessor; +import org.alfresco.repo.security.permissions.processor.PermissionProcessorRegistry; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AuthorityType; @@ -53,7 +54,7 @@ import org.springframework.context.ApplicationEvent; * @author Roy Wetherall */ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl - implements ExtendedPermissionService + implements ExtendedPermissionService { /** Writers simple cache */ protected SimpleCache> writersCache; @@ -61,8 +62,8 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl /** File plan service */ private FilePlanService filePlanService; - /** Permission veto registry */ - private PermissionVetoRegistry permissionVetoRegistry; + /** Permission processor registry */ + private PermissionProcessorRegistry permissionProcessorRegistry; /** * Gets the file plan service @@ -84,9 +85,14 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl this.filePlanService = filePlanService; } - public void setPermissionVetoRegistry(PermissionVetoRegistry permissionVetoRegistry) + /** + * Sets the permission processor registry + * + * @param permissionProcessorRegistry the permissions processor registry + */ + public void setPermissionProcessorRegistry(PermissionProcessorRegistry permissionProcessorRegistry) { - this.permissionVetoRegistry = permissionVetoRegistry; + this.permissionProcessorRegistry = permissionProcessorRegistry; } /** @@ -130,34 +136,34 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl @Override public AccessStatus hasPermission(NodeRef nodeRef, String perm) { - // check permission vetos - List permissionVetos = permissionVetoRegistry.getPermissionVetos(); - for (PermissionVeto permissionVeto : permissionVetos) + AccessStatus result = AccessStatus.UNDETERMINED; + + // permission pre-processors + List preProcessors = permissionProcessorRegistry.getPermissionPreProcessors(); + for (PermissionPreProcessor preProcessor : preProcessors) { - if (permissionVeto.isVetoed(nodeRef, perm)) + // pre process permission + result = preProcessor.process(nodeRef, perm); + + // veto if denied + if (AccessStatus.DENIED.equals(result)) { - // TODO add logging so veto cause can be diagnosed - - // veto access to node - return AccessStatus.DENIED; + return result; } } - AccessStatus acs = super.hasPermission(nodeRef, perm); - if (AccessStatus.DENIED.equals(acs) && - PermissionService.READ.equals(perm) && - nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT)) + // evaluate permission + result = super.hasPermission(nodeRef, perm); + + // permission post-processors + List postProcessors = permissionProcessorRegistry.getPermissionPostProcessors(); + for (PermissionPostProcessor postProcessor : postProcessors) { - return super.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS); - } - else if (AccessStatus.DENIED.equals(acs) && - PermissionService.WRITE.equals(perm) && - nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT)) - { - return super.hasPermission(nodeRef, RMPermissionModel.FILE_RECORDS); - } - - return acs; + // post process permission + result = postProcessor.process(result, nodeRef, perm); + } + + return result; } /** diff --git a/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoRegistry.java b/rm-server/source/java/org/alfresco/repo/security/permissions/processor/PermissionPostProcessor.java similarity index 56% rename from rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoRegistry.java rename to rm-server/source/java/org/alfresco/repo/security/permissions/processor/PermissionPostProcessor.java index ef117cbb8b..1854bca008 100644 --- a/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoRegistry.java +++ b/rm-server/source/java/org/alfresco/repo/security/permissions/processor/PermissionPostProcessor.java @@ -16,33 +16,28 @@ * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ -package org.alfresco.repo.security.permissions.veto; +package org.alfresco.repo.security.permissions.processor; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.AccessStatus; + -import java.util.ArrayList; -import java.util.List; /** + * Permission Post Processor. + * * @author Roy Wetherall * @since 3.0.a */ -public class PermissionVetoRegistry +public interface PermissionPostProcessor { - /** list of vetos to apply */ - private List permissionVetos = new ArrayList(); - /** - * @param permissionVeto permission veto + * Process permission. + * + * @param accessStatus current access status + * @param nodeRef node reference + * @param perm permission + * @return {@link AccessStatus} */ - public void addPermissionVeto(PermissionVeto permissionVeto) - { - permissionVetos.add(permissionVeto); - } - - /** - * @return {@link List}<{@link PermissionVeto}> list of permission vetos - */ - public List getPermissionVetos() - { - return permissionVetos; - } + AccessStatus process(AccessStatus accessStatus, NodeRef nodeRef, String perm); } diff --git a/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVeto.java b/rm-server/source/java/org/alfresco/repo/security/permissions/processor/PermissionPreProcessor.java similarity index 65% rename from rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVeto.java rename to rm-server/source/java/org/alfresco/repo/security/permissions/processor/PermissionPreProcessor.java index e180858e58..e501cc59df 100644 --- a/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVeto.java +++ b/rm-server/source/java/org/alfresco/repo/security/permissions/processor/PermissionPreProcessor.java @@ -16,21 +16,28 @@ * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ -package org.alfresco.repo.security.permissions.veto; +package org.alfresco.repo.security.permissions.processor; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.AccessStatus; + /** + * Permission Veto Interface + * * @author Roy Wetherall * @since 3.0.a */ -public interface PermissionVeto +public interface PermissionPreProcessor { /** + * Process permission. * - * @param nodeRef - * @param perm - * @return + * @param accessStatus current access status + * @param nodeRef node reference + * @param perm permission + * @return {@link AccessStatus} */ - boolean isVetoed(NodeRef nodeRef, String perm); + AccessStatus process(NodeRef nodeRef, String perm); + } diff --git a/rm-server/source/java/org/alfresco/repo/security/permissions/processor/PermissionProcessorRegistry.java b/rm-server/source/java/org/alfresco/repo/security/permissions/processor/PermissionProcessorRegistry.java new file mode 100644 index 0000000000..5ce81841c5 --- /dev/null +++ b/rm-server/source/java/org/alfresco/repo/security/permissions/processor/PermissionProcessorRegistry.java @@ -0,0 +1,77 @@ +/* + * 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.repo.security.permissions.processor; + +import java.util.ArrayList; +import java.util.List; + +/** + * Permission Processor Registry + * + * @author Roy Wetherall + * @since 3.0.a + */ +public class PermissionProcessorRegistry +{ + /** permission pre-processors */ + private List permissionPreProcessors = new ArrayList(); + + /** permission post-processors */ + private List permissionPostProcessors = new ArrayList(); + + /** + * Add a permission pre-processor. + * + * @param permissionPreProcessor permission pre-processor + */ + public void addPermissionPreProcessor(PermissionPreProcessor permissionPreProcessor) + { + permissionPreProcessors.add(permissionPreProcessor); + } + + /** + * Add a permission post-processor. + * + * @param permissionPostProcessor permission post-processor + */ + public void addPermissionPostProcessor(PermissionPostProcessor permissionPostProcessor) + { + permissionPostProcessors.add(permissionPostProcessor); + } + + /** + * Get a list of the registered permission pre-processors. + * + * @return {@link List}<{@link PermissionPreProcessor}> list of permission pre-processors + */ + public List getPermissionPreProcessors() + { + return permissionPreProcessors; + } + + /** + * Get a list of the registered permission post-processors. + * + * @return <{@link List}>{@link PermissionPreProcessor} list of permission post-processors + */ + public List getPermissionPostProcessors() + { + return permissionPostProcessors; + } +} diff --git a/rm-server/source/java/org/alfresco/repo/security/permissions/processor/impl/PermissionPostProcessorBaseImpl.java b/rm-server/source/java/org/alfresco/repo/security/permissions/processor/impl/PermissionPostProcessorBaseImpl.java new file mode 100644 index 0000000000..3a1944cbdf --- /dev/null +++ b/rm-server/source/java/org/alfresco/repo/security/permissions/processor/impl/PermissionPostProcessorBaseImpl.java @@ -0,0 +1,42 @@ +/* + * 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.repo.security.permissions.processor.impl; + +import org.alfresco.repo.security.permissions.processor.PermissionPostProcessor; + +/** + * Permission post processor base implementation. + *

+ * Helper class that can be extended when providing a custom permission + * post processor implementation. + * + * @author Roy Wetherall + * @since 3.0.a + */ +public abstract class PermissionPostProcessorBaseImpl extends PermissionProcessorBaseImpl + implements PermissionPostProcessor +{ + /** + * Init method to add this permission extensions to the registry + */ + public void init() + { + getPermissionProcessorRegistry().addPermissionPostProcessor(this); + } +} diff --git a/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoBaseImpl.java b/rm-server/source/java/org/alfresco/repo/security/permissions/processor/impl/PermissionPreProcessorBaseImpl.java similarity index 57% rename from rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoBaseImpl.java rename to rm-server/source/java/org/alfresco/repo/security/permissions/processor/impl/PermissionPreProcessorBaseImpl.java index 5ec384e6d7..8bf62d6a62 100644 --- a/rm-server/source/java/org/alfresco/repo/security/permissions/veto/PermissionVetoBaseImpl.java +++ b/rm-server/source/java/org/alfresco/repo/security/permissions/processor/impl/PermissionPreProcessorBaseImpl.java @@ -16,30 +16,27 @@ * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ -package org.alfresco.repo.security.permissions.veto; +package org.alfresco.repo.security.permissions.processor.impl; + +import org.alfresco.repo.security.permissions.processor.PermissionPreProcessor; /** + * Permission pre-processor base implementation. + *

+ * Helper class that can be extended when providing a custom permission + * pre-processor implementation. + * * @author Roy Wetherall * @since 3.0.a */ -public abstract class PermissionVetoBaseImpl implements PermissionVeto +public abstract class PermissionPreProcessorBaseImpl extends PermissionProcessorBaseImpl + implements PermissionPreProcessor { - /** permission veto refistry */ - private PermissionVetoRegistry permissionVetoRegistry; - /** - * @param permissionVetoRegistry permission veto registry - */ - public void setPermissionVetoRegistry(PermissionVetoRegistry permissionVetoRegistry) - { - this.permissionVetoRegistry = permissionVetoRegistry; - } - - /** - * Init method to add this permission veto to the registry + * Init method to add this permission extensions to the registry */ public void init() { - permissionVetoRegistry.addPermissionVeto(this); + getPermissionProcessorRegistry().addPermissionPreProcessor(this); } } diff --git a/rm-server/source/java/org/alfresco/repo/security/permissions/processor/impl/PermissionProcessorBaseImpl.java b/rm-server/source/java/org/alfresco/repo/security/permissions/processor/impl/PermissionProcessorBaseImpl.java new file mode 100644 index 0000000000..8f0abbb52a --- /dev/null +++ b/rm-server/source/java/org/alfresco/repo/security/permissions/processor/impl/PermissionProcessorBaseImpl.java @@ -0,0 +1,49 @@ +/* + * 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.repo.security.permissions.processor.impl; + +import org.alfresco.repo.security.permissions.processor.PermissionProcessorRegistry; + +/** + * Commonality found in both pre and post permission processor implementations. + * + * @author Roy Wetherall + * @since 3.0.a + */ +/*package*/ abstract class PermissionProcessorBaseImpl +{ + /** permission processor registry */ + private PermissionProcessorRegistry permissionProcessorRegistry; + + /** + * @param PermissionProcessorRegistry permission processor registry + */ + public void setPermissionProcessorRegistry(PermissionProcessorRegistry permissionProcessorRegistry) + { + this.permissionProcessorRegistry = permissionProcessorRegistry; + } + + /** + * @return {@link PermissionProcessorRegistry} permission processor registry + */ + protected PermissionProcessorRegistry getPermissionProcessorRegistry() + { + return permissionProcessorRegistry; + } +} From 08b43e39b067eb1db35777cf5cf2f8c078d57221 Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Mon, 17 Aug 2015 04:35:31 +0000 Subject: [PATCH 4/5] Extended permission service unit test +review RM-166 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/DEV/ROYTEST@110191 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../impl/ExtendedPermissionServiceImpl.java | 16 ++- ...ExtendedPermissionServiceImplUnitTest.java | 125 ++++++++++++++++++ 2 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 rm-server/unit-test/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImplUnitTest.java diff --git a/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java b/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java index 5cc2a0a552..dee2ee1e89 100644 --- a/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java +++ b/rm-server/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java @@ -153,7 +153,7 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl } // evaluate permission - result = super.hasPermission(nodeRef, perm); + result = hasPermissionImpl(nodeRef, perm); // permission post-processors List postProcessors = permissionProcessorRegistry.getPermissionPostProcessors(); @@ -165,6 +165,20 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl return result; } + + /** + * Implementation of hasPermission method call. + *

+ * Separation also convenient for unit testing. + * + * @param nodeRef node reference + * @param perm permission + * @return {@link AccessStatus} access status result + */ + protected AccessStatus hasPermissionImpl(NodeRef nodeRef, String perm) + { + return super.hasPermission(nodeRef, perm); + } /** * @see org.alfresco.repo.security.permissions.impl.PermissionServiceImpl#canRead(java.lang.Long) diff --git a/rm-server/unit-test/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImplUnitTest.java new file mode 100644 index 0000000000..fb5807a659 --- /dev/null +++ b/rm-server/unit-test/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImplUnitTest.java @@ -0,0 +1,125 @@ +/* + * 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.repo.security.permissions.impl; + +import static java.util.Arrays.asList; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.when; +import static org.junit.Assert.assertEquals; + +import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; +import org.alfresco.repo.security.permissions.processor.PermissionPostProcessor; +import org.alfresco.repo.security.permissions.processor.PermissionPreProcessor; +import org.alfresco.repo.security.permissions.processor.PermissionProcessorRegistry; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.AccessStatus; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +/** + * Extended permission service implementation unit test + * + * @author Roy Wetherall + * @since 3.0.a + */ +public class ExtendedPermissionServiceImplUnitTest extends BaseUnitTest +{ + private @InjectMocks @Spy ExtendedPermissionServiceImpl extendedPermissionServiceImpl = new ExtendedPermissionServiceImpl() + { + protected AccessStatus hasPermissionImpl(NodeRef nodeRef, String perm) { return AccessStatus.UNDETERMINED; }; + }; + + private @Mock PermissionProcessorRegistry mockedPermissionProcessorRegistry; + private @Mock PermissionPreProcessor mockedPermissionPreProcessor; + private @Mock PermissionPostProcessor mockedPermissionPostProcessor; + + /** + * Given a permission pre-processor has been registered + * And does not DENY + * When hasPermission is called + * Then the pre-processor is executed + * And the ACL's are evaluated as normal + */ + @Test + public void preProcessorDoesNotDeny() + { + NodeRef nodeRef = generateCmContent("anyname"); + String perm = AlfMock.generateText(); + when(mockedPermissionProcessorRegistry.getPermissionPreProcessors()) + .thenReturn(asList(mockedPermissionPreProcessor)); + when(mockedPermissionPreProcessor.process(nodeRef, perm)) + .thenReturn(AccessStatus.UNDETERMINED); + + AccessStatus result = extendedPermissionServiceImpl.hasPermission(nodeRef, perm); + + assertEquals(AccessStatus.UNDETERMINED, result); + verify(mockedPermissionPreProcessor).process(nodeRef, perm); + verify(extendedPermissionServiceImpl).hasPermissionImpl(nodeRef, perm); + } + + /** + * Given a permission pre-processor has been registered + * And DENY's + * When hasPermission is called + * Then the pre-processor is executed + * And the remaining permission evaluations do not take place + */ + @Test + public void preProcessorDenys() + { + NodeRef nodeRef = generateCmContent("anyname"); + String perm = AlfMock.generateText(); + when(mockedPermissionProcessorRegistry.getPermissionPreProcessors()) + .thenReturn(asList(mockedPermissionPreProcessor)); + when(mockedPermissionPreProcessor.process(nodeRef, perm)) + .thenReturn(AccessStatus.DENIED); + + AccessStatus result = extendedPermissionServiceImpl.hasPermission(nodeRef, perm); + + assertEquals(AccessStatus.DENIED, result); + verify(mockedPermissionPreProcessor).process(nodeRef, perm); + verify(extendedPermissionServiceImpl, never()).hasPermissionImpl(nodeRef, perm); + } + + /** + * Given a permission post-processor has been registered + * When hasPermission is called + * Then the permission post-processor is called + */ + @Test + public void postProcessorRegistered() + { + NodeRef nodeRef = generateCmContent("anyname"); + String perm = AlfMock.generateText(); + when(mockedPermissionProcessorRegistry.getPermissionPostProcessors()) + .thenReturn(asList(mockedPermissionPostProcessor)); + when(mockedPermissionPostProcessor.process(AccessStatus.UNDETERMINED, nodeRef, perm)) + .thenReturn(AccessStatus.ALLOWED); + + AccessStatus result = extendedPermissionServiceImpl.hasPermission(nodeRef, perm); + + assertEquals(AccessStatus.ALLOWED, result); + verify(mockedPermissionPostProcessor).process(AccessStatus.UNDETERMINED, nodeRef, perm); + verify(extendedPermissionServiceImpl).hasPermissionImpl(nodeRef, perm); + } +} From 2bcebc2abe32f12bd013294a9fa9ac51b6f2e417 Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Tue, 18 Aug 2015 04:38:47 +0000 Subject: [PATCH 5/5] Classification permission pre-processor unit test +review RM-166 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/DEV/ROYTEST@110301 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../ClassificationPermissionPreProcessor.java | 4 +- ...icationPermissionPreProcessorUnitTest.java | 193 ++++++++++++++++++ 2 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/permission/ClassificationPermissionPreProcessorUnitTest.java diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/permission/ClassificationPermissionPreProcessor.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/permission/ClassificationPermissionPreProcessor.java index 81fecae508..52dc89bec5 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/permission/ClassificationPermissionPreProcessor.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/permission/ClassificationPermissionPreProcessor.java @@ -39,8 +39,8 @@ import org.alfresco.util.Triple; public class ClassificationPermissionPreProcessor extends PermissionPreProcessorBaseImpl { /** transaction resource keys */ - private static final String KEY_PROCESSING = ClassificationPermissionPreProcessor.class.getName() + ".processing"; - private static final String KEY_CACHE = ClassificationPermissionPreProcessor.class.getName() + ".cache"; + /*package*/ static final String KEY_PROCESSING = ClassificationPermissionPreProcessor.class.getName() + ".processing"; + /*package*/ static final String KEY_CACHE = ClassificationPermissionPreProcessor.class.getName() + ".cache"; /** content classification service */ private ContentClassificationService contentClassificationService; diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/permission/ClassificationPermissionPreProcessorUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/permission/ClassificationPermissionPreProcessorUnitTest.java new file mode 100644 index 0000000000..1b9be12e89 --- /dev/null +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/permission/ClassificationPermissionPreProcessorUnitTest.java @@ -0,0 +1,193 @@ +/* + * 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.permission; + +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.Map; + +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.test.util.AlfMock; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.util.Triple; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import com.google.common.collect.Sets; + +/** + * Classification permission pre-processor unit test + * + * @author Roy Wetherall + * @since 3.0.a + */ +public class ClassificationPermissionPreProcessorUnitTest extends BaseUnitTest +{ + /** test artifact */ + private @InjectMocks ClassificationPermissionPreProcessor processor; + + /** mocks */ + private @Mock ClassificationServiceBootstrap mockedClassificationServiceBootstrap; + private @Mock ContentClassificationService mockedContentClassificationService; + + /** test data */ + private NodeRef nodeRef; + private String perm = AlfMock.generateText(); + private String user = AlfMock.generateText(); + + @Before + @Override + public void before() throws Exception + { + super.before(); + nodeRef = generateCmContent(AlfMock.generateText()); + } + + /** + * Given that the classification hierarchy hasn't been bootstraped + * When the classification permission pre processor is executed + * Then an undetermined result will be returned + */ + @Test + public void classificationServiceNotBootstraped() + { + when(mockedClassificationServiceBootstrap.isInitialised()) + .thenReturn(false); + + assertEquals(AccessStatus.UNDETERMINED, processor.process(nodeRef, perm)); + + verify(mockedContentClassificationService, never()) + .hasClearance(nodeRef); + } + + /** + * Given that the node being evaluated is already being processed + * When the classification permission pre processor is executed + * Then an undetermined result will be returned + */ + @Test + public void nodeBeingProcessed() + { + when(mockedClassificationServiceBootstrap.isInitialised()) + .thenReturn(true); + when(mockedTransactionalResourceHelper.getSet(ClassificationPermissionPreProcessor.KEY_PROCESSING)) + .thenReturn(Sets.newHashSet(nodeRef)); + + assertEquals(AccessStatus.UNDETERMINED, processor.process(nodeRef, perm)); + + verify(mockedContentClassificationService, never()) + .hasClearance(nodeRef); + } + + /** + * Given that the node already exists in the transaction cache + * When the classification permission pre processor is executed + * Then the result will be returned from the cache + */ + @Test + public void resultAlreadyCached() + { + when(mockedClassificationServiceBootstrap.isInitialised()) + .thenReturn(true); + NodeRef notTheNodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedTransactionalResourceHelper.getSet(ClassificationPermissionPreProcessor.KEY_PROCESSING)) + .thenReturn(Sets.newHashSet(notTheNodeRef)); + when(mockedAuthenticationUtil.getRunAsUser()) + .thenReturn(user); + + Map cache = new HashMap(1); + cache.put(new Triple(nodeRef, perm, user), AccessStatus.ALLOWED); + when(mockedTransactionalResourceHelper.getMap(ClassificationPermissionPreProcessor.KEY_CACHE)) + .thenReturn(cache); + + assertEquals(AccessStatus.ALLOWED, processor.process(nodeRef, perm)); + + verify(mockedContentClassificationService, never()) + .hasClearance(nodeRef); + } + + /** + * Given that the user does have clearance + * When the classification permission pre processor is executed + * Then an undetermined result will be returned + */ + @Test + public void userHasClearance() + { + when(mockedClassificationServiceBootstrap.isInitialised()) + .thenReturn(true); + NodeRef notTheNodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedTransactionalResourceHelper.getSet(ClassificationPermissionPreProcessor.KEY_PROCESSING)) + .thenReturn(Sets.newHashSet(notTheNodeRef)); + when(mockedAuthenticationUtil.getRunAsUser()) + .thenReturn(user); + + Map cache = new HashMap(1); + cache.put(new Triple(notTheNodeRef, perm, user), AccessStatus.ALLOWED); + when(mockedTransactionalResourceHelper.getMap(ClassificationPermissionPreProcessor.KEY_CACHE)) + .thenReturn(cache); + + when(mockedContentClassificationService.hasClearance(nodeRef)) + .thenReturn(true); + + assertEquals(AccessStatus.UNDETERMINED, processor.process(nodeRef, perm)); + + verify(mockedContentClassificationService) + .hasClearance(nodeRef); + } + + /** + * Given that the user doesn't have clearance + * When the classification permission pre processor is executed + * Then an undetermined result will be returned + */ + @Test + public void userDoesNotHaveClearance() + { + when(mockedClassificationServiceBootstrap.isInitialised()) + .thenReturn(true); + NodeRef notTheNodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedTransactionalResourceHelper.getSet(ClassificationPermissionPreProcessor.KEY_PROCESSING)) + .thenReturn(Sets.newHashSet(notTheNodeRef)); + when(mockedAuthenticationUtil.getRunAsUser()) + .thenReturn(user); + + Map cache = new HashMap(1); + cache.put(new Triple(notTheNodeRef, perm, user), AccessStatus.ALLOWED); + when(mockedTransactionalResourceHelper.getMap(ClassificationPermissionPreProcessor.KEY_CACHE)) + .thenReturn(cache); + + when(mockedContentClassificationService.hasClearance(nodeRef)) + .thenReturn(false); + + assertEquals(AccessStatus.DENIED, processor.process(nodeRef, perm)); + + verify(mockedContentClassificationService) + .hasClearance(nodeRef); + } +}