mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
MNT-21706 NodeService setAssociations list of elements is now handled. (#746)
MNT-21706 NodeService setAssociations list of elements is now handled.
This commit is contained in:
@@ -1,30 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
* the paid license agreement will prevail. Otherwise, the software is
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
* provided under the following open source license terms:
|
* provided under the following open source license terms:
|
||||||
*
|
*
|
||||||
* Alfresco is free software: you can redistribute it and/or modify
|
* 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
|
* 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
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* Alfresco is distributed in the hope that it will be useful,
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
package org.alfresco.repo.security.permissions.impl.acegi;
|
package org.alfresco.repo.security.permissions.impl.acegi;
|
||||||
|
|
||||||
|
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.getNodeRef;
|
||||||
|
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.shouldAbstainOrDeny;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -46,8 +49,6 @@ import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
|
|||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
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.repository.NodeService;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
|
||||||
import org.alfresco.service.cmr.security.AccessStatus;
|
|
||||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||||
import org.alfresco.service.cmr.security.AuthorityService;
|
import org.alfresco.service.cmr.security.AuthorityService;
|
||||||
import org.alfresco.service.cmr.security.OwnableService;
|
import org.alfresco.service.cmr.security.OwnableService;
|
||||||
@@ -59,6 +60,7 @@ import org.apache.commons.logging.Log;
|
|||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author andyh
|
* @author andyh
|
||||||
*/
|
*/
|
||||||
@@ -395,61 +397,53 @@ public class ACLEntryVoter implements AccessDecisionVoter, InitializingBean
|
|||||||
{
|
{
|
||||||
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
|
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
|
||||||
}
|
}
|
||||||
else if (StoreRef.class.isAssignableFrom(params[cad.parameter[0]]))
|
|
||||||
|
if (List.class.isAssignableFrom(params[cad.parameter[0]]))
|
||||||
{
|
{
|
||||||
StoreRef storeRef = getArgument(invocation, cad.parameter[0]);
|
List<?> listArgument = getArgument(invocation, cad.parameter[0]);
|
||||||
if (storeRef != null)
|
if (listArgument != null)
|
||||||
{
|
{
|
||||||
if (log.isDebugEnabled())
|
NodeRef listNodeRef;
|
||||||
|
Integer accessAbstainOrDeny = null;
|
||||||
|
for (Object listElement : listArgument)
|
||||||
{
|
{
|
||||||
log.debug("\tPermission test against the store - using permissions on the root node");
|
listNodeRef = getNodeRef(listElement, nodeService);
|
||||||
}
|
Integer currentValue = shouldAbstainOrDeny(cad.required, listNodeRef, abstainForClassQNames, nodeService, permissionService);
|
||||||
if (nodeService.exists(storeRef))
|
|
||||||
{
|
if (currentValue != null)
|
||||||
testNodeRef = nodeService.getRootNode(storeRef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (NodeRef.class.isAssignableFrom(params[cad.parameter[0]]))
|
|
||||||
{
|
|
||||||
testNodeRef = getArgument(invocation, cad.parameter[0]);
|
|
||||||
if (log.isDebugEnabled())
|
|
||||||
{
|
|
||||||
if (testNodeRef != null)
|
|
||||||
{
|
|
||||||
if (nodeService.exists(testNodeRef))
|
|
||||||
{
|
{
|
||||||
log.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
|
if (currentValue == AccessDecisionVoter.ACCESS_DENIED)
|
||||||
|
{
|
||||||
|
return AccessDecisionVoter.ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
accessAbstainOrDeny = currentValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
log.debug("\tPermission test on non-existing node " +testNodeRef);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
if (accessAbstainOrDeny != null)
|
||||||
else if (ChildAssociationRef.class.isAssignableFrom(params[cad.parameter[0]]))
|
|
||||||
{
|
|
||||||
ChildAssociationRef testChildRef = getArgument(invocation, cad.parameter[0]);
|
|
||||||
if (testChildRef != null)
|
|
||||||
{
|
|
||||||
testNodeRef = testChildRef.getChildRef();
|
|
||||||
if (log.isDebugEnabled())
|
|
||||||
{
|
{
|
||||||
if (nodeService.exists(testNodeRef))
|
return accessAbstainOrDeny;
|
||||||
{
|
|
||||||
log.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log.debug("\tPermission test on non-existing node " + testNodeRef);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if((hasMethodEntry == null) || (hasMethodEntry.booleanValue()))
|
||||||
|
{
|
||||||
|
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return AccessDecisionVoter.ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
|
Object testObject = getArgument(invocation, cad.parameter[0]);
|
||||||
|
//If the execution reaches here, then testNodeRef is always null
|
||||||
|
testNodeRef = getNodeRef(testObject, nodeService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cad.typeString.equals(ACL_ITEM))
|
else if (cad.typeString.equals(ACL_ITEM))
|
||||||
@@ -584,44 +578,10 @@ public class ACLEntryVoter implements AccessDecisionVoter, InitializingBean
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (testNodeRef != null)
|
Integer accessAbstainOrDeny = shouldAbstainOrDeny(cad.required, testNodeRef, abstainForClassQNames, nodeService, permissionService);
|
||||||
|
if (accessAbstainOrDeny != null)
|
||||||
{
|
{
|
||||||
// now we know the node - we can abstain for certain types and aspects (eg. RM)
|
return accessAbstainOrDeny;
|
||||||
if(abstainForClassQNames.size() > 0)
|
|
||||||
{
|
|
||||||
// check node exists
|
|
||||||
if (nodeService.exists(testNodeRef))
|
|
||||||
{
|
|
||||||
QName typeQName = nodeService.getType(testNodeRef);
|
|
||||||
if(abstainForClassQNames.contains(typeQName))
|
|
||||||
{
|
|
||||||
return AccessDecisionVoter.ACCESS_ABSTAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<QName> aspectQNames = nodeService.getAspects(testNodeRef);
|
|
||||||
for(QName abstain : abstainForClassQNames)
|
|
||||||
{
|
|
||||||
if(aspectQNames.contains(abstain))
|
|
||||||
{
|
|
||||||
return AccessDecisionVoter.ACCESS_ABSTAIN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (log.isDebugEnabled())
|
|
||||||
{
|
|
||||||
log.debug("\t\tNode ref is not null");
|
|
||||||
}
|
|
||||||
if (permissionService.hasPermission(testNodeRef, cad.required.toString()) == AccessStatus.DENIED)
|
|
||||||
{
|
|
||||||
if (log.isDebugEnabled())
|
|
||||||
{
|
|
||||||
log.debug("\t\tPermission is denied");
|
|
||||||
Thread.dumpStack();
|
|
||||||
}
|
|
||||||
return AccessDecisionVoter.ACCESS_DENIED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.security.permissions.impl.acegi;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.vote.AccessDecisionVoter;
|
||||||
|
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.cmr.security.AccessStatus;
|
||||||
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods extracted from AclEntryVoter
|
||||||
|
*
|
||||||
|
* @author Lev Belava
|
||||||
|
*/
|
||||||
|
final class ACLEntryVoterUtils
|
||||||
|
{
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(ACLEntryVoterUtils.class);
|
||||||
|
|
||||||
|
private ACLEntryVoterUtils()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets NodeRef for testObject based on inferred type
|
||||||
|
*
|
||||||
|
* @param testObject Tested object to work on
|
||||||
|
* @param nodeService Node service to perform checks on refs
|
||||||
|
* @return NodeRef for testObject or null if (testObject is null or StoreRef from testObject does not exist in the provided NodeService)
|
||||||
|
* @throws ACLEntryVoterException if testObject is not null and not one of a NodeRef or ChildAssociationRef types
|
||||||
|
*/
|
||||||
|
static NodeRef getNodeRef(Object testObject, NodeService nodeService)
|
||||||
|
{
|
||||||
|
if (testObject == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StoreRef.class.isAssignableFrom(testObject.getClass()))
|
||||||
|
{
|
||||||
|
LOG.debug("Permission test against the store - using permissions on the root node");
|
||||||
|
StoreRef storeRef = (StoreRef) testObject;
|
||||||
|
if (nodeService.exists(storeRef))
|
||||||
|
{
|
||||||
|
return nodeService.getRootNode(storeRef);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.debug("StoreRef does not exist");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NodeRef.class.isAssignableFrom(testObject.getClass()))
|
||||||
|
{
|
||||||
|
NodeRef result = (NodeRef) testObject;
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
{
|
||||||
|
if (nodeService.exists(result))
|
||||||
|
{
|
||||||
|
LOG.debug("Permission test on node {}", nodeService.getPath(result));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.debug("Permission test on non-existing node {}", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ChildAssociationRef.class.isAssignableFrom(testObject.getClass()))
|
||||||
|
{
|
||||||
|
ChildAssociationRef testChildRef = (ChildAssociationRef) testObject;
|
||||||
|
NodeRef result = testChildRef.getChildRef();
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
{
|
||||||
|
if (nodeService.exists(result))
|
||||||
|
{
|
||||||
|
LOG.debug("Permission test on node {}", nodeService.getPath(result));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.debug("Permission test on non-existing node {}", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if tested NodeRef instance is abstained or denied based on set of QNames to abstain and
|
||||||
|
*
|
||||||
|
* @param requiredPermissionReference Required permissions
|
||||||
|
* @param testNodeRef NodeRef to be verified
|
||||||
|
* @param abstainForClassQNames Set of QNames to abstain
|
||||||
|
* @param nodeService Node service to perform checks on tested NodeRef
|
||||||
|
* @param permissionService Permission service to check for required permissions
|
||||||
|
* @return null if testNodeRef is not abstained or denied, otherwise returns appropriate status.
|
||||||
|
*/
|
||||||
|
static Integer shouldAbstainOrDeny(SimplePermissionReference requiredPermissionReference, NodeRef testNodeRef, Set<QName> abstainForClassQNames,
|
||||||
|
NodeService nodeService, PermissionService permissionService)
|
||||||
|
{
|
||||||
|
if (testNodeRef == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.debug("Node ref is not null");
|
||||||
|
|
||||||
|
if (abstainForClassQNames.size() > 0 && nodeService.exists(testNodeRef))
|
||||||
|
{
|
||||||
|
if (abstainForClassQNames.contains(nodeService.getType(testNodeRef)))
|
||||||
|
{
|
||||||
|
return AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||||
|
}
|
||||||
|
Set<QName> testNodeRefAspects = nodeService.getAspects(testNodeRef);
|
||||||
|
for (QName abstain : abstainForClassQNames)
|
||||||
|
{
|
||||||
|
if (testNodeRefAspects.contains(abstain))
|
||||||
|
{
|
||||||
|
return AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AccessStatus.DENIED == permissionService.hasPermission(testNodeRef, requiredPermissionReference.toString()))
|
||||||
|
{
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
{
|
||||||
|
LOG.debug("Permission is denied");
|
||||||
|
Thread.dumpStack();
|
||||||
|
}
|
||||||
|
return AccessDecisionVoter.ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -209,6 +209,7 @@ import org.junit.runners.Suite;
|
|||||||
org.alfresco.repo.security.authentication.AuthorizationTest.class,
|
org.alfresco.repo.security.authentication.AuthorizationTest.class,
|
||||||
org.alfresco.repo.security.permissions.PermissionCheckedCollectionTest.class,
|
org.alfresco.repo.security.permissions.PermissionCheckedCollectionTest.class,
|
||||||
org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSetTest.class,
|
org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSetTest.class,
|
||||||
|
org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtilsTest.class,
|
||||||
org.alfresco.repo.security.authentication.ChainingAuthenticationServiceTest.class,
|
org.alfresco.repo.security.authentication.ChainingAuthenticationServiceTest.class,
|
||||||
org.alfresco.repo.security.authentication.NameBasedUserNameGeneratorTest.class,
|
org.alfresco.repo.security.authentication.NameBasedUserNameGeneratorTest.class,
|
||||||
org.alfresco.repo.version.common.VersionImplTest.class,
|
org.alfresco.repo.version.common.VersionImplTest.class,
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -96,6 +96,8 @@ public abstract class AbstractPermissionTest extends TestCase
|
|||||||
|
|
||||||
protected NodeRef systemNodeRef;
|
protected NodeRef systemNodeRef;
|
||||||
|
|
||||||
|
protected NodeRef abstainedNode;
|
||||||
|
|
||||||
protected AuthenticationComponent authenticationComponent;
|
protected AuthenticationComponent authenticationComponent;
|
||||||
|
|
||||||
protected ModelDAO permissionModelDAO;
|
protected ModelDAO permissionModelDAO;
|
||||||
@@ -186,6 +188,8 @@ public abstract class AbstractPermissionTest extends TestCase
|
|||||||
props = createPersonProperties(USER2_LEMUR);
|
props = createPersonProperties(USER2_LEMUR);
|
||||||
nodeService.createNode(typesNodeRef, children, ContentModel.TYPE_PERSON, container, props).getChildRef();
|
nodeService.createNode(typesNodeRef, children, ContentModel.TYPE_PERSON, container, props).getChildRef();
|
||||||
|
|
||||||
|
abstainedNode= nodeService.createNode(rootNodeRef, ContentModel.ASSOC_FAILED_THUMBNAIL, system, ContentModel.TYPE_FAILED_THUMBNAIL).getChildRef();
|
||||||
|
|
||||||
// create an authentication object e.g. the user
|
// create an authentication object e.g. the user
|
||||||
if(authenticationDAO.userExists(USER1_ANDY))
|
if(authenticationDAO.userExists(USER1_ANDY))
|
||||||
{
|
{
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.security.permissions.impl.acegi;
|
||||||
|
|
||||||
|
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.getNodeRef;
|
||||||
|
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.shouldAbstainOrDeny;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.ArgumentMatchers.nullable;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.vote.AccessDecisionVoter;
|
||||||
|
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.cmr.security.AccessStatus;
|
||||||
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class ACLEntryVoterUtilsTest
|
||||||
|
{
|
||||||
|
private final NodeRef testNodeRef = new NodeRef("workspace://testNodeRef/testNodeRef");
|
||||||
|
private final NodeRef rootNodeRef = new NodeRef("workspace://rootNodeRef/rootNodeRef");
|
||||||
|
private final NodeRef refNodeForTestObject = new NodeRef("workspace://refNodeForTestObject/refNodeForTestObject");
|
||||||
|
private final NodeRef childRefNode = new NodeRef("workspace://childRefNode/childRefNode");
|
||||||
|
private final StoreRef testStoreNodeRef = new StoreRef("system://testStoreRefMock/testStoreRefMock");
|
||||||
|
private final SimplePermissionReference simplePermissionReference = SimplePermissionReference.getPermissionReference(QName.createQName("uri", "local"), "Write");
|
||||||
|
private final QName qNameToAbstain1 = QName.createQName("{test}testnode1");
|
||||||
|
private final QName qNameToAbstain2 = QName.createQName("{test}testnode2");
|
||||||
|
private final QName qNameToAbstain3 = QName.createQName("{test}testnode3");
|
||||||
|
private final QName qNameNotFromTheAbstainSet = QName.createQName("{test}testnodeAbstain");
|
||||||
|
private final Set<QName> qNamesToAbstain = Set.of(qNameToAbstain1, qNameToAbstain2, qNameToAbstain3);
|
||||||
|
@Mock
|
||||||
|
private PermissionService permissionServiceMock;
|
||||||
|
@Mock
|
||||||
|
private NodeService nodeServiceMock;
|
||||||
|
@Mock
|
||||||
|
private ChildAssociationRef childAssocRefMock;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
when(nodeServiceMock.exists(testStoreNodeRef)).thenReturn(Boolean.TRUE);
|
||||||
|
when(nodeServiceMock.exists(testNodeRef)).thenReturn(Boolean.TRUE);
|
||||||
|
when(nodeServiceMock.getRootNode(testStoreNodeRef)).thenReturn(rootNodeRef);
|
||||||
|
when(nodeServiceMock.getType(testNodeRef)).thenReturn(qNameNotFromTheAbstainSet);
|
||||||
|
when(nodeServiceMock.getAspects(testNodeRef)).thenReturn(Set.of(qNameNotFromTheAbstainSet));
|
||||||
|
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.DENIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void returnsAccessDeniedFromPermissionService()
|
||||||
|
{
|
||||||
|
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
|
||||||
|
is(AccessDecisionVoter.ACCESS_DENIED));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void returnsNullOnNullTestObject()
|
||||||
|
{
|
||||||
|
assertThat(getNodeRef(null, nodeServiceMock), is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = ACLEntryVoterException.class)
|
||||||
|
public void throwsExceptionWhenParameterIsNotNodeRefOrChildAssociationRef()
|
||||||
|
{
|
||||||
|
getNodeRef("TEST", nodeServiceMock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void returnsGivenTestNodeRefWhenStoreRefDoesNotExist()
|
||||||
|
{
|
||||||
|
when(nodeServiceMock.exists(testStoreNodeRef)).thenReturn(Boolean.FALSE);
|
||||||
|
assertThat(getNodeRef(testStoreNodeRef, nodeServiceMock), is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void returnsRootNode()
|
||||||
|
{
|
||||||
|
assertThat(getNodeRef(testStoreNodeRef, nodeServiceMock), is(rootNodeRef));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void returnsNodeRefFromTestObject()
|
||||||
|
{
|
||||||
|
assertThat(getNodeRef(refNodeForTestObject, nodeServiceMock), is(refNodeForTestObject));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void returnsChildRefFromChildAssocRef()
|
||||||
|
{
|
||||||
|
when(childAssocRefMock.getChildRef()).thenReturn(childRefNode);
|
||||||
|
assertThat(getNodeRef(childAssocRefMock, nodeServiceMock), is(childRefNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void returnsNullOnNullTestNodeRef()
|
||||||
|
{
|
||||||
|
assertThat(shouldAbstainOrDeny(simplePermissionReference, null, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
|
||||||
|
is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void returnsNullOnAbstainClassQnamesIsEmptyAndThereAreNoDeniedPermissions()
|
||||||
|
{
|
||||||
|
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.ALLOWED);
|
||||||
|
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, Collections.emptySet(), nodeServiceMock, permissionServiceMock),
|
||||||
|
is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void returnsNullOnTestNodeRefDoesNotExistAndThereAreNoDeniedPermissions()
|
||||||
|
{
|
||||||
|
when(nodeServiceMock.exists(testNodeRef)).thenReturn(Boolean.FALSE);
|
||||||
|
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.ALLOWED);
|
||||||
|
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
|
||||||
|
is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void returnsNullOnNodeTypeAndNodeAspectsAreNotInSetToAbstainAndThereAreNoDeniedPermissions()
|
||||||
|
{
|
||||||
|
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.ALLOWED);
|
||||||
|
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
|
||||||
|
is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void returnsAbstainWhenNodeRefTypeIsInSetToAbstain()
|
||||||
|
{
|
||||||
|
when(nodeServiceMock.getType(testNodeRef)).thenReturn(qNameToAbstain2);
|
||||||
|
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
|
||||||
|
is(AccessDecisionVoter.ACCESS_ABSTAIN));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void returnsAbstainWhenAtLeastOneAspectIsInSetToAbstain()
|
||||||
|
{
|
||||||
|
when(nodeServiceMock.getAspects(testNodeRef)).thenReturn(Set.of(qNameNotFromTheAbstainSet, qNameToAbstain3));
|
||||||
|
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
|
||||||
|
is(AccessDecisionVoter.ACCESS_ABSTAIN));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user