diff --git a/repository/src/main/java/org/alfresco/repo/domain/permissions/ADMAccessControlListDAO.java b/repository/src/main/java/org/alfresco/repo/domain/permissions/ADMAccessControlListDAO.java index b0d0f708b7..f0f9b77bcc 100644 --- a/repository/src/main/java/org/alfresco/repo/domain/permissions/ADMAccessControlListDAO.java +++ b/repository/src/main/java/org/alfresco/repo/domain/permissions/ADMAccessControlListDAO.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * Copyright (C) 2005 - 2024 Alfresco Software Limited * %% * This file is part of the Alfresco software. * If the software was purchased under a paid Alfresco license, the terms of @@ -25,32 +25,32 @@ */ package org.alfresco.repo.domain.permissions; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.domain.node.NodeDAO; -import org.alfresco.repo.domain.node.NodeIdAndAclId; -import org.alfresco.repo.policy.BehaviourFilter; -import org.alfresco.repo.security.permissions.ACLType; -import org.alfresco.repo.security.permissions.AccessControlList; -import org.alfresco.repo.security.permissions.AccessControlListProperties; -import org.alfresco.repo.security.permissions.SimpleAccessControlListProperties; -import org.alfresco.repo.security.permissions.impl.AclChange; -import org.alfresco.repo.transaction.AlfrescoTransactionSupport; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.InvalidNodeRefException; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.Pair; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.domain.node.NodeDAO; +import org.alfresco.repo.domain.node.NodeIdAndAclId; +import org.alfresco.repo.policy.BehaviourFilter; +import org.alfresco.repo.security.permissions.ACLType; +import org.alfresco.repo.security.permissions.AccessControlList; +import org.alfresco.repo.security.permissions.AccessControlListProperties; +import org.alfresco.repo.security.permissions.SimpleAccessControlListProperties; +import org.alfresco.repo.security.permissions.impl.AclChange; +import org.alfresco.repo.transaction.AlfrescoTransactionSupport; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.dao.ConcurrencyFailureException; /** @@ -69,7 +69,7 @@ public class ADMAccessControlListDAO implements AccessControlListDAO private AclDAO aclDaoComponent; - private BehaviourFilter behaviourFilter; + private BehaviourFilter behaviourFilter; private boolean preserveAuditableData = true; /**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) { this.behaviourFilter = behaviourFilter; - } + } 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) { - //If the node already has the pending ACL aspect, just update the new inheritFrom value - if (nodeDAO.hasNodeAspect(nodeId, ContentModel.ASPECT_PENDING_FIX_ACL)) + Pair nodePair = nodeDAO.getNodePair(nodeId); + if (nodePair == null) { - Map pendingAclProperties = new HashMap<>(); - pendingAclProperties.put(ContentModel.PROP_INHERIT_FROM_ACL, inheritFrom); - nodeDAO.addNodeProperties(nodeId, pendingAclProperties); return; } + NodeRef nodeRef = nodePair.getSecond(); - Set aspect = new HashSet<>(); - aspect.add(ContentModel.ASPECT_PENDING_FIX_ACL); - nodeDAO.addNodeAspects(nodeId, aspect); - Map 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()) + try { - 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 pendingAclProperties = new HashMap<>(); + pendingAclProperties.put(ContentModel.PROP_INHERIT_FROM_ACL, inheritFrom); + nodeDAO.addNodeProperties(nodeId, pendingAclProperties); + return; + } + + Set aspect = new HashSet<>(); + aspect.add(ContentModel.ASPECT_PENDING_FIX_ACL); + nodeDAO.addNodeAspects(nodeId, aspect); + Map 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) { - Set aspects = new HashSet<>(1); - aspects.add(ContentModel.ASPECT_PENDING_FIX_ACL); - Set 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); + Pair nodePair = nodeDAO.getNodePair(nodeId); + if (nodePair == null) + { + return; + } + NodeRef nodeRef = nodePair.getSecond(); + + try + { + behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE); + behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_VERSIONABLE); + + Set aspects = new HashSet<>(1); + aspects.add(ContentModel.ASPECT_PENDING_FIX_ACL); + Set 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); + } } /** diff --git a/repository/src/test/java/org/alfresco/repo/domain/permissions/FixedAclUpdaterTest.java b/repository/src/test/java/org/alfresco/repo/domain/permissions/FixedAclUpdaterTest.java index 5bd0796347..ad0dabfaf3 100644 --- a/repository/src/test/java/org/alfresco/repo/domain/permissions/FixedAclUpdaterTest.java +++ b/repository/src/test/java/org/alfresco/repo/domain/permissions/FixedAclUpdaterTest.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2021 Alfresco Software Limited + * Copyright (C) 2005 - 2024 Alfresco Software Limited * %% * This file is part of the Alfresco software. * 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.Collections; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; 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 public void testSyncTimeOut() @@ -178,6 +179,7 @@ public class FixedAclUpdaterTest try { + long timestampBeforePermissions = System.currentTimeMillis(); setPermissionsOnTree(folderRef, false, true); // Get current ACLS on non pending nodes and validate @@ -186,6 +188,13 @@ public class FixedAclUpdaterTest // Validate values in pending ACL node 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); assertEquals("Pending inheritFrom value should be the parent ACL id", aclComparator.getParentAcl(), aclComparatorForPending.getPendingInheritFromAcl()); @@ -202,6 +211,10 @@ public class FixedAclUpdaterTest assertEquals("Processed Pending ACL children doesn't have correct ACL", aclComparator.getChildAcl(), aclComparatorForPending.getChildAcl()); 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 {