mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
[MNT-24085] - Fixed ACL Updater job is updating the cm:modifier details (#2406)
* Disabled audibled and versionable behaviour on add and remove pending acl aspect and properties * Added validations to the unit test to assert modification date is not changed
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2024 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
|
||||||
@@ -25,32 +25,32 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.domain.permissions;
|
package org.alfresco.repo.domain.permissions;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.domain.node.NodeDAO;
|
import org.alfresco.repo.domain.node.NodeDAO;
|
||||||
import org.alfresco.repo.domain.node.NodeIdAndAclId;
|
import org.alfresco.repo.domain.node.NodeIdAndAclId;
|
||||||
import org.alfresco.repo.policy.BehaviourFilter;
|
import org.alfresco.repo.policy.BehaviourFilter;
|
||||||
import org.alfresco.repo.security.permissions.ACLType;
|
import org.alfresco.repo.security.permissions.ACLType;
|
||||||
import org.alfresco.repo.security.permissions.AccessControlList;
|
import org.alfresco.repo.security.permissions.AccessControlList;
|
||||||
import org.alfresco.repo.security.permissions.AccessControlListProperties;
|
import org.alfresco.repo.security.permissions.AccessControlListProperties;
|
||||||
import org.alfresco.repo.security.permissions.SimpleAccessControlListProperties;
|
import org.alfresco.repo.security.permissions.SimpleAccessControlListProperties;
|
||||||
import org.alfresco.repo.security.permissions.impl.AclChange;
|
import org.alfresco.repo.security.permissions.impl.AclChange;
|
||||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||||
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;
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
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.springframework.dao.ConcurrencyFailureException;
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,7 +69,7 @@ public class ADMAccessControlListDAO implements AccessControlListDAO
|
|||||||
|
|
||||||
private AclDAO aclDaoComponent;
|
private AclDAO aclDaoComponent;
|
||||||
|
|
||||||
private BehaviourFilter behaviourFilter;
|
private BehaviourFilter behaviourFilter;
|
||||||
private boolean preserveAuditableData = true;
|
private boolean preserveAuditableData = true;
|
||||||
|
|
||||||
/**maxim transaction time allowed for {@link #setFixedAcls(Long, Long, Long, Long, List, boolean, AsyncCallParameters, boolean)} */
|
/**maxim transaction time allowed for {@link #setFixedAcls(Long, Long, Long, Long, List, boolean, AsyncCallParameters, boolean)} */
|
||||||
@@ -93,7 +93,7 @@ public class ADMAccessControlListDAO implements AccessControlListDAO
|
|||||||
public void setBehaviourFilter(BehaviourFilter behaviourFilter)
|
public void setBehaviourFilter(BehaviourFilter behaviourFilter)
|
||||||
{
|
{
|
||||||
this.behaviourFilter = behaviourFilter;
|
this.behaviourFilter = behaviourFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPreserveAuditableData(boolean preserveAuditableData)
|
public void setPreserveAuditableData(boolean preserveAuditableData)
|
||||||
{
|
{
|
||||||
@@ -582,37 +582,73 @@ public class ADMAccessControlListDAO implements AccessControlListDAO
|
|||||||
|
|
||||||
private void addFixedAclPendingAspect(Long nodeId, Long sharedAclToReplace, Long inheritFrom, Long mergeFrom)
|
private void addFixedAclPendingAspect(Long nodeId, Long sharedAclToReplace, Long inheritFrom, Long mergeFrom)
|
||||||
{
|
{
|
||||||
//If the node already has the pending ACL aspect, just update the new inheritFrom value
|
Pair<Long, NodeRef> nodePair = nodeDAO.getNodePair(nodeId);
|
||||||
if (nodeDAO.hasNodeAspect(nodeId, ContentModel.ASPECT_PENDING_FIX_ACL))
|
if (nodePair == null)
|
||||||
{
|
{
|
||||||
Map<QName, Serializable> pendingAclProperties = new HashMap<>();
|
|
||||||
pendingAclProperties.put(ContentModel.PROP_INHERIT_FROM_ACL, inheritFrom);
|
|
||||||
nodeDAO.addNodeProperties(nodeId, pendingAclProperties);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
NodeRef nodeRef = nodePair.getSecond();
|
||||||
|
|
||||||
Set<QName> aspect = new HashSet<>();
|
try
|
||||||
aspect.add(ContentModel.ASPECT_PENDING_FIX_ACL);
|
|
||||||
nodeDAO.addNodeAspects(nodeId, aspect);
|
|
||||||
Map<QName, Serializable> pendingAclProperties = new HashMap<>();
|
|
||||||
pendingAclProperties.put(ContentModel.PROP_SHARED_ACL_TO_REPLACE, sharedAclToReplace);
|
|
||||||
pendingAclProperties.put(ContentModel.PROP_INHERIT_FROM_ACL, inheritFrom);
|
|
||||||
nodeDAO.addNodeProperties(nodeId, pendingAclProperties);
|
|
||||||
if (log.isDebugEnabled())
|
|
||||||
{
|
{
|
||||||
log.debug("Set Fixed Acl Pending : " + nodeId + " " + nodeDAO.getNodePair(nodeId).getSecond());
|
behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||||
|
behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_VERSIONABLE);
|
||||||
|
|
||||||
|
//If the node already has the pending ACL aspect, just update the new inheritFrom value
|
||||||
|
if (nodeDAO.hasNodeAspect(nodeId, ContentModel.ASPECT_PENDING_FIX_ACL))
|
||||||
|
{
|
||||||
|
Map<QName, Serializable> pendingAclProperties = new HashMap<>();
|
||||||
|
pendingAclProperties.put(ContentModel.PROP_INHERIT_FROM_ACL, inheritFrom);
|
||||||
|
nodeDAO.addNodeProperties(nodeId, pendingAclProperties);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<QName> aspect = new HashSet<>();
|
||||||
|
aspect.add(ContentModel.ASPECT_PENDING_FIX_ACL);
|
||||||
|
nodeDAO.addNodeAspects(nodeId, aspect);
|
||||||
|
Map<QName, Serializable> pendingAclProperties = new HashMap<>();
|
||||||
|
pendingAclProperties.put(ContentModel.PROP_SHARED_ACL_TO_REPLACE, sharedAclToReplace);
|
||||||
|
pendingAclProperties.put(ContentModel.PROP_INHERIT_FROM_ACL, inheritFrom);
|
||||||
|
nodeDAO.addNodeProperties(nodeId, pendingAclProperties);
|
||||||
|
if (log.isDebugEnabled())
|
||||||
|
{
|
||||||
|
log.debug("Set Fixed Acl Pending : nodeId " + nodeId + " nodeUUID " + nodeRef.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
behaviourFilter.enableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||||
|
behaviourFilter.enableBehaviour(nodeRef, ContentModel.ASPECT_VERSIONABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removePendingAclAspect(Long nodeId)
|
public void removePendingAclAspect(Long nodeId)
|
||||||
{
|
{
|
||||||
Set<QName> aspects = new HashSet<>(1);
|
Pair<Long, NodeRef> nodePair = nodeDAO.getNodePair(nodeId);
|
||||||
aspects.add(ContentModel.ASPECT_PENDING_FIX_ACL);
|
if (nodePair == null)
|
||||||
Set<QName> pendingFixAclProperties = new HashSet<>();
|
{
|
||||||
pendingFixAclProperties.add(ContentModel.PROP_SHARED_ACL_TO_REPLACE);
|
return;
|
||||||
pendingFixAclProperties.add(ContentModel.PROP_INHERIT_FROM_ACL);
|
}
|
||||||
nodeDAO.removeNodeAspects(nodeId, aspects);
|
NodeRef nodeRef = nodePair.getSecond();
|
||||||
nodeDAO.removeNodeProperties(nodeId, pendingFixAclProperties);
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||||
|
behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_VERSIONABLE);
|
||||||
|
|
||||||
|
Set<QName> aspects = new HashSet<>(1);
|
||||||
|
aspects.add(ContentModel.ASPECT_PENDING_FIX_ACL);
|
||||||
|
Set<QName> pendingFixAclProperties = new HashSet<>();
|
||||||
|
pendingFixAclProperties.add(ContentModel.PROP_SHARED_ACL_TO_REPLACE);
|
||||||
|
pendingFixAclProperties.add(ContentModel.PROP_INHERIT_FROM_ACL);
|
||||||
|
nodeDAO.removeNodeAspects(nodeId, aspects);
|
||||||
|
nodeDAO.removeNodeProperties(nodeId, pendingFixAclProperties);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
behaviourFilter.enableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||||
|
behaviourFilter.enableBehaviour(nodeRef, ContentModel.ASPECT_VERSIONABLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
* Copyright (C) 2005 - 2024 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
|
||||||
@@ -32,6 +32,7 @@ import static org.junit.Assert.assertTrue;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -168,7 +169,7 @@ public class FixedAclUpdaterTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test setting permissions explicitly as sync, but the operaration times out
|
* Test setting permissions explicitly as sync, but the operation times out
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testSyncTimeOut()
|
public void testSyncTimeOut()
|
||||||
@@ -178,6 +179,7 @@ public class FixedAclUpdaterTest
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
long timestampBeforePermissions = System.currentTimeMillis();
|
||||||
setPermissionsOnTree(folderRef, false, true);
|
setPermissionsOnTree(folderRef, false, true);
|
||||||
|
|
||||||
// Get current ACLS on non pending nodes and validate
|
// Get current ACLS on non pending nodes and validate
|
||||||
@@ -186,6 +188,13 @@ public class FixedAclUpdaterTest
|
|||||||
|
|
||||||
// Validate values in pending ACL node
|
// Validate values in pending ACL node
|
||||||
NodeRef folderWithPendingAcl = getFirstNodeWithAclPending(ContentModel.TYPE_FOLDER);
|
NodeRef folderWithPendingAcl = getFirstNodeWithAclPending(ContentModel.TYPE_FOLDER);
|
||||||
|
|
||||||
|
// - Validate modification date
|
||||||
|
long folderWithPendingAclNodeId = nodeDAO.getNodePair(folderWithPendingAcl).getFirst();
|
||||||
|
Date modificationDate = (Date) nodeDAO.getNodeProperty(folderWithPendingAclNodeId, ContentModel.PROP_MODIFIED);
|
||||||
|
assertTrue("Changing permissions updated cm:modified",modificationDate.getTime() < timestampBeforePermissions);
|
||||||
|
|
||||||
|
// - Validate pending values
|
||||||
ACLComparator aclComparatorForPending = new ACLComparator(folderWithPendingAcl);
|
ACLComparator aclComparatorForPending = new ACLComparator(folderWithPendingAcl);
|
||||||
assertEquals("Pending inheritFrom value should be the parent ACL id", aclComparator.getParentAcl(),
|
assertEquals("Pending inheritFrom value should be the parent ACL id", aclComparator.getParentAcl(),
|
||||||
aclComparatorForPending.getPendingInheritFromAcl());
|
aclComparatorForPending.getPendingInheritFromAcl());
|
||||||
@@ -202,6 +211,10 @@ public class FixedAclUpdaterTest
|
|||||||
assertEquals("Processed Pending ACL children doesn't have correct ACL", aclComparator.getChildAcl(),
|
assertEquals("Processed Pending ACL children doesn't have correct ACL", aclComparator.getChildAcl(),
|
||||||
aclComparatorForPending.getChildAcl());
|
aclComparatorForPending.getChildAcl());
|
||||||
assertTrue("Permissions not applied on pending nodes", aclComparatorForPending.firstChildHasOriginalPermission());
|
assertTrue("Permissions not applied on pending nodes", aclComparatorForPending.firstChildHasOriginalPermission());
|
||||||
|
|
||||||
|
//Verify removing the pendingAcl aspect did not change the modification date
|
||||||
|
Date modificationDateAfterJob = (Date) nodeDAO.getNodeProperty(folderWithPendingAclNodeId, ContentModel.PROP_MODIFIED);
|
||||||
|
assertEquals("Running the job updated cm:modified",modificationDate.getTime(),modificationDateAfterJob.getTime());
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user