Merged HEAD (5.1) to 5.1.N (5.1.1)

120082 bhorje: ACE-4845 added definition retrieval transaction enforcement and denial of unauthenticated virtualization


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.1.N/root@120200 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Andreea Dragoi
2015-12-15 14:28:20 +00:00
parent 502d394f94
commit 884bb19489
5 changed files with 228 additions and 64 deletions

View File

@@ -29,7 +29,6 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.jscript.ClasspathScriptLocation; import org.alfresco.repo.jscript.ClasspathScriptLocation;
import org.alfresco.repo.model.Repository; import org.alfresco.repo.model.Repository;
import org.alfresco.repo.virtual.config.NodeRefResolver; import org.alfresco.repo.virtual.config.NodeRefResolver;
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.InvalidAspectException; import org.alfresco.service.cmr.dictionary.InvalidAspectException;
import org.alfresco.service.cmr.dictionary.InvalidTypeException; import org.alfresco.service.cmr.dictionary.InvalidTypeException;
@@ -79,6 +78,11 @@ public class AlfrescoEnviroment implements ActualEnvironment
this.serviceRegistry = serviceRegistry; this.serviceRegistry = serviceRegistry;
} }
public ServiceRegistry getServiceRegistry()
{
return this.serviceRegistry;
}
public void setRepositoryHelper(Repository repository) public void setRepositoryHelper(Repository repository)
{ {
this.repositoryHelper = repository; this.repositoryHelper = repository;

View File

@@ -136,23 +136,23 @@ public class Reference
} }
} }
// Average reference length DEBUG trace // Average reference length log trace
private static long _debug_refLength = 0; private static long _trace_refLength = 0;
private static long _debug_refCount = 0; private static long _trace_refCount = 0;
private static final long _debug_refBatchSize = 256; private static final long _trace_refBatchSize = 4096*2;
private static synchronized void debug_avg_ref_length(long refLength) private static synchronized void _trace_avg_ref_length(long refLength)
{ {
_debug_refLength += refLength; _trace_refLength += refLength;
_debug_refCount++; _trace_refCount++;
if (_debug_refBatchSize > 0 && _debug_refCount % _debug_refBatchSize == 0) if (_trace_refBatchSize > 0 && _trace_refCount % _trace_refBatchSize == 0)
{ {
logger.debug("Average reference encoding size : " + (_debug_refLength / _debug_refCount)); logger.trace("Average reference encoding size : " + (_trace_refLength / _trace_refCount));
_debug_refCount = 0; _trace_refCount = 0;
_debug_refLength = 0; _trace_refLength = 0;
} }
} }
@@ -281,9 +281,9 @@ public class Reference
NodeRef theNode = new NodeRef(storeRef, NodeRef theNode = new NodeRef(storeRef,
idBuilder.toString()); idBuilder.toString());
if (logger.isDebugEnabled()) if (logger.isTraceEnabled())
{ {
debug_avg_ref_length(theNode.toString().length()); _trace_avg_ref_length(theNode.toString().length());
} }
return theNode; return theNode;

View File

@@ -38,8 +38,11 @@ import org.alfresco.query.PagingResults;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.NodePermissionEntry; import org.alfresco.repo.security.permissions.NodePermissionEntry;
import org.alfresco.repo.security.permissions.PermissionReference; import org.alfresco.repo.security.permissions.PermissionReference;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.repo.transaction.TransactionalResourceHelper; import org.alfresco.repo.transaction.TransactionalResourceHelper;
import org.alfresco.repo.virtual.ActualEnvironment; import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.AlfrescoEnviroment;
import org.alfresco.repo.virtual.VirtualContentModel; import org.alfresco.repo.virtual.VirtualContentModel;
import org.alfresco.repo.virtual.VirtualizationException; import org.alfresco.repo.virtual.VirtualizationException;
import org.alfresco.repo.virtual.page.PageCollationException; import org.alfresco.repo.virtual.page.PageCollationException;
@@ -68,6 +71,7 @@ import org.alfresco.repo.virtual.template.PropertyValueConstraint;
import org.alfresco.repo.virtual.template.VirtualFolderDefinition; import org.alfresco.repo.virtual.template.VirtualFolderDefinition;
import org.alfresco.repo.virtual.template.VirtualQuery; import org.alfresco.repo.virtual.template.VirtualQuery;
import org.alfresco.repo.virtual.template.VirtualQueryConstraint; import org.alfresco.repo.virtual.template.VirtualQueryConstraint;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -82,9 +86,13 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.QNamePattern; import org.alfresco.service.namespace.QNamePattern;
import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class VirtualStoreImpl implements VirtualStore, VirtualFolderDefinitionResolver public class VirtualStoreImpl implements VirtualStore, VirtualFolderDefinitionResolver
{ {
private static Log logger = LogFactory.getLog(VirtualStoreImpl.class);
private static final String VIRTUAL_FOLDER_DEFINITION = "virtualfolder.definition"; private static final String VIRTUAL_FOLDER_DEFINITION = "virtualfolder.definition";
private List<VirtualizationMethod> virtualizationMethods = null; private List<VirtualizationMethod> virtualizationMethods = null;
@@ -121,6 +129,20 @@ public class VirtualStoreImpl implements VirtualStore, VirtualFolderDefinitionRe
@Override @Override
public boolean canVirtualize(NodeRef nodeRef) throws VirtualizationException public boolean canVirtualize(NodeRef nodeRef) throws VirtualizationException
{ {
String runAsUser = AuthenticationUtil.getRunAsUser();
if (runAsUser == null)
{
if (logger.isTraceEnabled())
{
RuntimeException stackTracingException = new RuntimeException("Stack trace.");
logger.trace("Virtualization check call in unauthenticated-context - stack trace follows:",
stackTracingException);
}
return false;
}
if (Reference.isReference(nodeRef)) if (Reference.isReference(nodeRef))
{ {
return true; return true;
@@ -156,8 +178,8 @@ public class VirtualStoreImpl implements VirtualStore, VirtualFolderDefinitionRe
} }
} }
private NodeRef nodeProtocolNodeRef(NodeRef nodeRef) private NodeRef nodeProtocolNodeRef(NodeRef nodeRef) throws ProtocolMethodException, ReferenceParseException,
throws ProtocolMethodException, ReferenceParseException, ReferenceEncodingException ReferenceEncodingException
{ {
NodeRef theNodeRef = nodeRef; NodeRef theNodeRef = nodeRef;
if (Reference.isReference(nodeRef)) if (Reference.isReference(nodeRef))
@@ -373,23 +395,40 @@ public class VirtualStoreImpl implements VirtualStore, VirtualFolderDefinitionRe
return childReferences; return childReferences;
} }
public VirtualFolderDefinition resolveVirtualFolderDefinition(Reference reference) throws ProtocolMethodException public VirtualFolderDefinition resolveVirtualFolderDefinition(final Reference reference)
throws VirtualizationException
{ {
NodeRef key = reference.toNodeRef(); ServiceRegistry serviceRegistry = ((AlfrescoEnviroment) environment).getServiceRegistry();
Map<NodeRef, VirtualFolderDefinition> definitionsCache = TransactionalResourceHelper RetryingTransactionHelper transactionHelper = serviceRegistry.getRetryingTransactionHelper();
.getMap(VIRTUAL_FOLDER_DEFINITION);
VirtualFolderDefinition virtualFolderDefinition = definitionsCache.get(key); return transactionHelper.doInTransaction(new RetryingTransactionCallback<VirtualFolderDefinition>()
{
if (virtualFolderDefinition == null) @Override
{ public VirtualFolderDefinition execute() throws Throwable
{
NodeRef key = reference.toNodeRef();
virtualFolderDefinition = reference.execute(new ApplyTemplateMethod(environment)); Map<NodeRef, VirtualFolderDefinition> definitionsCache = TransactionalResourceHelper
definitionsCache.put(key, .getMap(VIRTUAL_FOLDER_DEFINITION);
virtualFolderDefinition);
}
return virtualFolderDefinition; VirtualFolderDefinition virtualFolderDefinition = definitionsCache
.get(key);
if (virtualFolderDefinition == null)
{
virtualFolderDefinition = reference
.execute(new ApplyTemplateMethod(environment));
definitionsCache.put(key,
virtualFolderDefinition);
}
return virtualFolderDefinition;
}
},
true,
false);
} }
@Override @Override
@@ -397,7 +436,7 @@ public class VirtualStoreImpl implements VirtualStore, VirtualFolderDefinitionRe
final boolean folders, final String pattern, final Set<QName> searchTypeQNames, final boolean folders, final String pattern, final Set<QName> searchTypeQNames,
final Set<QName> ignoreTypeQNames, final Set<QName> ignoreAspectQNames, final Set<QName> ignoreTypeQNames, final Set<QName> ignoreAspectQNames,
final List<Pair<QName, Boolean>> sortProps, final PagingRequest pagingRequest) final List<Pair<QName, Boolean>> sortProps, final PagingRequest pagingRequest)
throws VirtualizationException throws VirtualizationException
{ {
VirtualFolderDefinition structure = resolveVirtualFolderDefinition(ref); VirtualFolderDefinition structure = resolveVirtualFolderDefinition(ref);
@@ -471,8 +510,8 @@ public class VirtualStoreImpl implements VirtualStore, VirtualFolderDefinitionRe
} }
@Override @Override
public PagingResults<Reference> list(Reference ref, boolean actual, boolean virtual, boolean files, boolean folders, public PagingResults<Reference> list(Reference ref, boolean actual, boolean virtual, boolean files,
String pattern, Set<QName> ignoreTypeQNames, Set<QName> ignoreAspectQNames, boolean folders, String pattern, Set<QName> ignoreTypeQNames, Set<QName> ignoreAspectQNames,
List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest) throws VirtualizationException List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest) throws VirtualizationException
{ {
return list(ref, return list(ref,

View File

@@ -30,6 +30,7 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import javax.transaction.Status;
import javax.transaction.UserTransaction; import javax.transaction.UserTransaction;
import junit.framework.TestCase; import junit.framework.TestCase;
@@ -59,10 +60,12 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
import org.alfresco.traitextender.SpringExtensionBundle; import org.alfresco.traitextender.SpringExtensionBundle;
import org.alfresco.util.ApplicationContextHelper; import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.transaction.TransactionSupportUtil;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.junit.Ignore; import org.junit.Ignore;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@Ignore @Ignore
public abstract class VirtualizationIntegrationTest extends TestCase implements VirtualizationTest public abstract class VirtualizationIntegrationTest extends TestCase implements VirtualizationTest
@@ -149,11 +152,15 @@ public abstract class VirtualizationIntegrationTest extends TestCase implements
protected NodeRef rootNodeRef; protected NodeRef rootNodeRef;
protected NodeRef companyHomeNodeRef;
protected ActualEnvironment environment; protected ActualEnvironment environment;
protected TypeAndAspectsFormProcessor typeAndAspectsFormProcessor; protected TypeAndAspectsFormProcessor typeAndAspectsFormProcessor;
private UserTransaction txn; protected String txnTamperHint;
protected UserTransaction txn;
protected AuthenticationComponent authenticationComponent; protected AuthenticationComponent authenticationComponent;
@@ -179,7 +186,7 @@ public abstract class VirtualizationIntegrationTest extends TestCase implements
contentService = serviceRegistry.getContentService(); contentService = serviceRegistry.getContentService();
fileAndFolderService = serviceRegistry.getFileFolderService(); fileAndFolderService = serviceRegistry.getFileFolderService();
permissionService = serviceRegistry.getPermissionService(); permissionService = serviceRegistry.getPermissionService();
searchService=serviceRegistry.getSearchService(); searchService = serviceRegistry.getSearchService();
authenticationComponent = ctx.getBean("authenticationComponent", authenticationComponent = ctx.getBean("authenticationComponent",
AuthenticationComponent.class); AuthenticationComponent.class);
@@ -215,8 +222,8 @@ public abstract class VirtualizationIntegrationTest extends TestCase implements
txn.begin(); txn.begin();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
NodeRef root = repository.getCompanyHome(); companyHomeNodeRef = repository.getCompanyHome();
testRootFolder = fileAndFolderService.create(root, testRootFolder = fileAndFolderService.create(companyHomeNodeRef,
TEST_ROOT_FOLDER_NAME, TEST_ROOT_FOLDER_NAME,
ContentModel.TYPE_FOLDER); ContentModel.TYPE_FOLDER);
@@ -243,7 +250,17 @@ public abstract class VirtualizationIntegrationTest extends TestCase implements
configuredTemplatesClassPath = null; configuredTemplatesClassPath = null;
} }
authenticationComponent.clearCurrentSecurityContext(); authenticationComponent.clearCurrentSecurityContext();
txn.rollback(); try
{
txn.rollback();
}
catch (Exception e)
{
logger.error("Test tear down failed. Has the test setup transaction been tempered with ? Hint : "
+ txnTamperHint,
e);
}
super.tearDown(); super.tearDown();
} }

View File

@@ -19,8 +19,18 @@
package org.alfresco.repo.virtual.store; package org.alfresco.repo.virtual.store;
import org.alfresco.repo.virtual.VirtualizationIntegrationTest; import java.nio.charset.StandardCharsets;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.virtual.VirtualizationException; import org.alfresco.repo.virtual.VirtualizationException;
import org.alfresco.repo.virtual.VirtualizationIntegrationTest;
import org.alfresco.repo.virtual.ref.Protocols;
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.repo.virtual.ref.VanillaProtocol;
import org.alfresco.repo.virtual.ref.VirtualProtocol;
import org.alfresco.repo.virtual.template.ApplyTemplateMethodTest;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
@@ -44,6 +54,69 @@ public class VirtualStoreImplTest extends VirtualizationIntegrationTest
} }
public void testResolveVirtualFolderDefinition_inactiveSynchronization() throws Exception
{
txnTamperHint = "VirtualStoreImplTest::testResolveVirtualFolderDefinition_inactiveSynchronization";
txn.rollback();
NodeRef ntVirtualizedFolder = null;
NodeRef jsonTemplateContent = null;
try
{
final String templateName = "template1.json";
jsonTemplateContent = nodeService.getChildByName(companyHomeNodeRef,
ContentModel.ASSOC_CONTAINS,
templateName);
if (jsonTemplateContent == null)
{
ChildAssociationRef templateChild = createContent(companyHomeNodeRef,
templateName,
ApplyTemplateMethodTest.class
.getResourceAsStream(TEST_TEMPLATE_1_JSON_NAME),
MimetypeMap.MIMETYPE_JSON,
StandardCharsets.UTF_8.name());
jsonTemplateContent = templateChild.getChildRef();
}
final String folderName = "testCanVirtualize_nonTransactional";
ntVirtualizedFolder = nodeService.getChildByName(companyHomeNodeRef,
ContentModel.ASSOC_CONTAINS,
folderName);
if (ntVirtualizedFolder == null)
{
ChildAssociationRef folderChild = createFolder(companyHomeNodeRef,
folderName);
ntVirtualizedFolder = folderChild.getChildRef();
}
Reference aVanillaRef = ((VanillaProtocol) Protocols.VANILLA.protocol)
.newReference(VANILLA_PROCESSOR_JS_CLASSPATH,
"/1",
ntVirtualizedFolder,
jsonTemplateContent);
// We use transactional-synchronized resources for caching. In
// non-transactional contexts they might not be available.
virtualStore.resolveVirtualFolderDefinition(aVanillaRef);
}
finally
{
txn = transactionService.getUserTransaction();
txn.begin();
if (ntVirtualizedFolder != null)
{
nodeService.deleteNode(ntVirtualizedFolder);
}
if (jsonTemplateContent != null)
{
nodeService.deleteNode(jsonTemplateContent);
}
txn.commit();
}
}
@Test @Test
public void testNonVirtualizable() throws Exception public void testNonVirtualizable() throws Exception
{ {
@@ -71,46 +144,77 @@ public class VirtualStoreImplTest extends VirtualizationIntegrationTest
assertEquals(false, assertEquals(false,
canVirtualize); canVirtualize);
} }
private String asTypedPermission(String perm) private String asTypedPermission(String perm)
{ {
return virtualStore.getUserPermissions().getPermissionTypeQName()+"."+perm; return virtualStore.getUserPermissions().getPermissionTypeQName() + "." + perm;
} }
private void assertHasQueryNodePermission(AccessStatus accessStatus,String perm) private void assertHasQueryNodePermission(AccessStatus accessStatus, String perm)
{ {
VirtualUserPermissions virtualUserPermissions = virtualStore.getUserPermissions(); VirtualUserPermissions virtualUserPermissions = virtualStore.getUserPermissions();
assertEquals(AccessStatus.DENIED,virtualUserPermissions.hasQueryNodePermission(perm)); assertEquals(AccessStatus.DENIED,
assertEquals(AccessStatus.DENIED,virtualUserPermissions.hasQueryNodePermission(asTypedPermission(perm))); virtualUserPermissions.hasQueryNodePermission(perm));
assertEquals(AccessStatus.DENIED,
virtualUserPermissions.hasQueryNodePermission(asTypedPermission(perm)));
} }
private void assertHasVirtualNodePermission(AccessStatus accessStatus,String perm,boolean readonly) private void assertHasVirtualNodePermission(AccessStatus accessStatus, String perm, boolean readonly)
{ {
VirtualUserPermissions virtualUserPermissions = virtualStore.getUserPermissions(); VirtualUserPermissions virtualUserPermissions = virtualStore.getUserPermissions();
assertEquals(AccessStatus.DENIED,virtualUserPermissions.hasVirtualNodePermission(perm,readonly)); assertEquals(AccessStatus.DENIED,
assertEquals(AccessStatus.DENIED,virtualUserPermissions.hasVirtualNodePermission(asTypedPermission(perm),readonly)); virtualUserPermissions.hasVirtualNodePermission(perm,
readonly));
assertEquals(AccessStatus.DENIED,
virtualUserPermissions.hasVirtualNodePermission(asTypedPermission(perm),
readonly));
} }
@Test @Test
public void testConfiguredUserPermissions() throws Exception public void testConfiguredUserPermissions() throws Exception
{ {
assertHasQueryNodePermission(AccessStatus.DENIED,PermissionService.DELETE); assertHasQueryNodePermission(AccessStatus.DENIED,
assertHasQueryNodePermission(AccessStatus.DENIED,PermissionService.DELETE_NODE); PermissionService.DELETE);
assertHasQueryNodePermission(AccessStatus.DENIED,PermissionService.CHANGE_PERMISSIONS); assertHasQueryNodePermission(AccessStatus.DENIED,
PermissionService.DELETE_NODE);
assertHasQueryNodePermission(AccessStatus.DENIED,
PermissionService.CHANGE_PERMISSIONS);
assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.CREATE_ASSOCIATIONS,true); assertHasVirtualNodePermission(AccessStatus.DENIED,
assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.UNLOCK,true); PermissionService.CREATE_ASSOCIATIONS,
assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.CANCEL_CHECK_OUT,true); true);
assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.DELETE,true); assertHasVirtualNodePermission(AccessStatus.DENIED,
assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.DELETE_NODE,true); PermissionService.UNLOCK,
assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.CHANGE_PERMISSIONS,true); true);
assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.WRITE_CONTENT,true); assertHasVirtualNodePermission(AccessStatus.DENIED,
assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.WRITE,true); PermissionService.CANCEL_CHECK_OUT,
assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.WRITE_PROPERTIES,true); true);
assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.WRITE,false); assertHasVirtualNodePermission(AccessStatus.DENIED,
assertHasVirtualNodePermission(AccessStatus.DENIED,PermissionService.WRITE_PROPERTIES,false); PermissionService.DELETE,
true);
assertHasVirtualNodePermission(AccessStatus.DENIED,
PermissionService.DELETE_NODE,
true);
assertHasVirtualNodePermission(AccessStatus.DENIED,
PermissionService.CHANGE_PERMISSIONS,
true);
assertHasVirtualNodePermission(AccessStatus.DENIED,
PermissionService.WRITE_CONTENT,
true);
assertHasVirtualNodePermission(AccessStatus.DENIED,
PermissionService.WRITE,
true);
assertHasVirtualNodePermission(AccessStatus.DENIED,
PermissionService.WRITE_PROPERTIES,
true);
assertHasVirtualNodePermission(AccessStatus.DENIED,
PermissionService.WRITE,
false);
assertHasVirtualNodePermission(AccessStatus.DENIED,
PermissionService.WRITE_PROPERTIES,
false);
} }
} }