Merged HEAD-BUG-FIX (5.0/Cloud) to HEAD (4.3/Cloud)

73688: Merged V4.2-BUG-FIX (4.2.3) to HEAD-BUG-FIX (4.3/Cloud)
      73548: MNT-10165: Merged DEV to V4.2-BUG-FIX (4.2.3)
         61161: MNT-10165: CMIS 1.1 API: Impossible to remove ACL through Atom binding
            - Detect permission to delete for principal and also find and delete all the concomitant basic CMIS permissions. Add unit test.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@74803 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Will Abson
2014-06-25 16:07:21 +00:00
parent f8eb3f7f62
commit b1bb208eb8
2 changed files with 165 additions and 1 deletions

View File

@@ -2641,6 +2641,7 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
}
Set<AccessPermission> currentAces = permissionService.getAllSetPermissions(nodeRef);
Acl currentACL = getACL(nodeRef, false);
// remove all permissions
permissionService.deletePermissions(nodeRef);
@@ -2654,7 +2655,9 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
principalId = AuthenticationUtil.getFullyAuthenticatedUser();
}
List<String> permissions = translatePermissionsFromCMIS(ace.getPermissions());
List<String> acePermissions = ace.getPermissions();
normaliseAcePermissions(currentACL, ace, acePermissions);
List<String> permissions = translatePermissionsFromCMIS(acePermissions);
normalisePermissions(currentAces, permissions);
for (String permission : permissions)
{
@@ -2663,6 +2666,38 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
}
}
/*
* MNT-10165: CMIS 1.1 API: Impossible to remove ACL through Atom binding
*
* Detect permission to delete for principal and
* also delete all the concomitant basic permissions
*/
private void normaliseAcePermissions(Acl currentACL, Ace newAce, List<String> acePermissions)
{
for (Ace oldAce : currentACL.getAces())
{
if (oldAce.getPrincipalId().equals(newAce.getPrincipalId()))
{
// detect what permissions were deleted for principal
Set<String> permissionsDeletedForPrincipal = new HashSet<String>(oldAce.getPermissions());
Set<String> newPermissions = new HashSet<String>(newAce.getPermissions());
permissionsDeletedForPrincipal.removeAll(newPermissions);
for (String permissionDeleted : permissionsDeletedForPrincipal)
{
// for deleted permission also delete all attendant basic permissions
List<String> onePermissionList = new ArrayList<String>();
onePermissionList.add(permissionDeleted);
List<String> cmisPermissions = translatePermmissionsToCMIS(onePermissionList, false);
for (String cmisPermission : cmisPermissions)
{
acePermissions.remove(cmisPermission);
}
}
}
}
}
/*
* ALF-11868: the cmis client library may incorrectly send READ or WRITE permissions to applyAcl.
* This method works around this by "normalising" permissions:

View File

@@ -37,6 +37,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.cmis.CMISAccessControlService;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.model.ContentModel;
import org.alfresco.opencmis.search.CMISQueryOptions;
@@ -62,6 +63,10 @@ import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.rule.Rule;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.cmr.rule.RuleType;
import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.tagging.TaggingService;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.NamespaceService;
@@ -70,6 +75,7 @@ import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.Pair;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.Ace;
import org.apache.chemistry.opencmis.commons.data.AllowableActions;
import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement;
import org.apache.chemistry.opencmis.commons.data.ObjectData;
@@ -80,6 +86,7 @@ import org.apache.chemistry.opencmis.commons.data.Properties;
import org.apache.chemistry.opencmis.commons.data.PropertyData;
import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
import org.apache.chemistry.opencmis.commons.enums.Action;
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
@@ -87,6 +94,9 @@ import org.apache.chemistry.opencmis.commons.enums.VersioningState;
import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisUpdateConflictException;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlEntryImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlListImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlPrincipalDataImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.CmisExtensionElementImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ExtensionDataImpl;
@@ -123,6 +133,8 @@ public class CMISTest
private LockService lockService;
private TaggingService taggingService;
private NamespaceService namespaceService;
private AuthorityService authorityService;
private PermissionService permissionService;
private AlfrescoCmisServiceFactory factory;
@@ -289,6 +301,8 @@ public class CMISTest
this.factory = (AlfrescoCmisServiceFactory)ctx.getBean("CMISServiceFactory");
this.cmisConnector = (CMISConnector) ctx.getBean("CMISConnector");
this.nodeDAO = (NodeDAO) ctx.getBean("nodeDAO");
this.authorityService = (AuthorityService)ctx.getBean("AuthorityService");
this.permissionService = (PermissionService) ctx.getBean("permissionService");
}
/**
@@ -2015,4 +2029,119 @@ public class CMISTest
AuthenticationUtil.popAuthentication();
}
}
/**
* MNT-10165: Check that all concomitant basic CMIS permissions are deleted
* when permission is deleted vai CMIS 1.1 API. For Atom binding it applies
* new set of permissions instead of deleting the old ones.
*/
@Test
public void testRemoveACL() throws Exception
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
try
{
// preconditions: create test document
final String testGroup = PermissionService.GROUP_PREFIX + "group1";
if (!authorityService.authorityExists(testGroup))
{
authorityService.createAuthority(AuthorityType.GROUP, "group1");
}
final FileInfo document = transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionCallback<FileInfo>()
{
@Override
public FileInfo execute() throws Throwable
{
NodeRef companyHomeNodeRef = repositoryHelper.getCompanyHome();
String folderName = GUID.generate();
FileInfo folderInfo = fileFolderService.create(companyHomeNodeRef, folderName, ContentModel.TYPE_FOLDER);
nodeService.setProperty(folderInfo.getNodeRef(), ContentModel.PROP_NAME, folderName);
assertNotNull(folderInfo);
String docName = GUID.generate();
FileInfo document = fileFolderService.create(folderInfo.getNodeRef(), docName, ContentModel.TYPE_CONTENT);
assertNotNull(document);
nodeService.setProperty(document.getNodeRef(), ContentModel.PROP_NAME, docName);
return document;
}
});
Set<AccessPermission> permissions = permissionService.getAllSetPermissions(document.getNodeRef());
assertEquals(permissions.size(), 1);
AccessPermission current = permissions.iterator().next();
assertEquals(current.getAuthority(), "GROUP_EVERYONE");
assertEquals(current.getPermission(), "Consumer");
// add group1 with Coordinator permissions
permissionService.setPermission(document.getNodeRef(), testGroup, PermissionService.COORDINATOR, true);
permissions = permissionService.getAllSetPermissions(document.getNodeRef());
Map<String , String> docPermissions = new HashMap<String, String>();
for (AccessPermission permission : permissions)
{
docPermissions.put(permission.getAuthority(), permission.getPermission());
}
assertTrue(docPermissions.keySet().contains(testGroup));
assertEquals(docPermissions.get(testGroup), PermissionService.COORDINATOR);
// update permissions for group1 via CMIS 1.1 API
withCmisService(new CmisServiceCallback<Void>()
{
@Override
public Void execute(CmisService cmisService)
{
List<RepositoryInfo> repositories = cmisService.getRepositoryInfos(null);
assertNotNull(repositories);
assertTrue(repositories.size() > 0);
RepositoryInfo repo = repositories.iterator().next();
String repositoryId = repo.getId();
String docIdStr = document.getNodeRef().toString();
// when removing Coordinator ACE from workbench-0.10.0 it sends PUT request
// to apply basic cmis:write, cmis:read, cmis:all for principal
AccessControlListImpl acesToPut = new AccessControlListImpl();
List<Ace> acesList = new ArrayList<Ace>();
acesToPut.setAces(acesList);
AccessControlEntryImpl ace = new AccessControlEntryImpl();
ace.setPrincipal(new AccessControlPrincipalDataImpl(testGroup));
List<String> putPermissions = new ArrayList<String>();
putPermissions.add(CMISAccessControlService.CMIS_ALL_PERMISSION);
putPermissions.add(CMISAccessControlService.CMIS_READ_PERMISSION);
putPermissions.add(CMISAccessControlService.CMIS_WRITE_PERMISSION);
ace.setPermissions(putPermissions);
ace.setDirect(true);
acesList.add(ace);
cmisService.applyAcl(repositoryId, docIdStr, acesToPut, AclPropagation.REPOSITORYDETERMINED);
return null;
}
}, CmisVersion.CMIS_1_1);
// check that permissions are the same as they were before Coordinator was added
permissions = permissionService.getAllSetPermissions(document.getNodeRef());
docPermissions = new HashMap<String, String>();
for (AccessPermission permission : permissions)
{
docPermissions.put(permission.getAuthority(), permission.getPermission());
}
assertFalse(docPermissions.keySet().contains(testGroup));
assertEquals(permissions.size(), 1);
current = permissions.iterator().next();
assertEquals(current.getAuthority(), "GROUP_EVERYONE");
assertEquals(current.getPermission(), "Consumer");
}
catch (CmisConstraintException e)
{
fail(e.toString());
}
finally
{
AuthenticationUtil.popAuthentication();
}
}
}