ACS-5325 Invoke required policy (#2215)

---------

Co-authored-by: Domenico Sibilio <domenicosibilio@gmail.com>
This commit is contained in:
Damian Ujma
2023-10-03 13:28:15 +02:00
committed by GitHub
parent daf573e24a
commit 456adc2aa2
6 changed files with 59 additions and 37 deletions

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited * Copyright (C) 2005 - 2023 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
@@ -48,19 +48,31 @@ public class NodePropertyFilter extends AbstractNodeEventFilter
ContentModel.PROP_CREATOR, ContentModel.PROP_CREATOR,
ContentModel.PROP_CREATED, ContentModel.PROP_CREATED,
ContentModel.PROP_CONTENT); ContentModel.PROP_CONTENT);
// These properties should not be excluded from the properties object
private static final Set<QName> ALLOWED_PROPERTIES = Set.of(ContentModel.PROP_CASCADE_TX,
ContentModel.PROP_CASCADE_CRC);
private final List<String> nodeAspectsBlackList; private final List<String> nodePropertiesBlackList;
public NodePropertyFilter() public NodePropertyFilter()
{ {
this.nodeAspectsBlackList = parseFilterList(FILTERED_PROPERTIES); this.nodePropertiesBlackList = parseFilterList(FILTERED_PROPERTIES);
} }
@Override @Override
public Set<QName> getExcludedTypes() public Set<QName> getExcludedTypes()
{ {
Set<QName> result = new HashSet<>(EXCLUDED_TOP_LEVEL_PROPS); Set<QName> result = new HashSet<>(EXCLUDED_TOP_LEVEL_PROPS);
nodeAspectsBlackList.forEach(nodeAspect -> result.addAll(expandTypeDef(nodeAspect))); nodePropertiesBlackList.forEach(nodeProperty-> result.addAll(expandTypeDef(nodeProperty)));
return result; return result;
} }
@Override
public boolean isExcluded(QName qName)
{
if(qName != null && ALLOWED_PROPERTIES.contains(qName)){
return false;
}
return super.isExcluded(qName);
}
} }

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited * Copyright (C) 2005 - 2023 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
@@ -3203,13 +3203,16 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
// Invoke policy behaviour // Invoke policy behaviour
invokeBeforeUpdateNode(parentNodeRef); invokeBeforeUpdateNode(parentNodeRef);
Map<QName, Serializable> propertiesBefore = nodeDAO.getNodeProperties(parentNodeId);
// Touch the node; it is cm:auditable // Touch the node; it is cm:auditable
boolean changed = nodeDAO.setModifiedProperties(parentNodeId, modifiedDate, modifiedByToPropagate); boolean changed = nodeDAO.setModifiedProperties(parentNodeId, modifiedDate, modifiedByToPropagate);
if (changed) if (changed)
{ {
Map<QName, Serializable> propertiesAfter = nodeDAO.getNodeProperties(parentNodeId);
// Invoke policy behaviour // Invoke policy behaviour
invokeOnUpdateNode(parentNodeRef); invokeOnUpdateNode(parentNodeRef);
invokeOnUpdateProperties(parentNodeRef, propertiesBefore, propertiesAfter);
} }
return null; return null;

View File

@@ -158,7 +158,7 @@ public class AccessAuditorTest
{ {
Object[] args = invocation.getArguments(); Object[] args = invocation.getArguments();
Map<String, Serializable> auditMap = (Map<String, Serializable>)args[1]; Map<String, Serializable> auditMap = (Map<String, Serializable>)args[1];
if ("/alfresco-access/transaction".equals(args[0])) if ("/alfresco-access/transaction".equals(args[0]) && !"updateNodeProperties".equals(auditMap.get("action")))
{ {
auditMapList.add(auditMap); auditMapList.add(auditMap);
} }

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited * Copyright (C) 2005 - 2023 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
@@ -77,9 +77,9 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
assertEquals(1, childAssociationRefs.size()); assertEquals(1, childAssociationRefs.size());
assertFalse(childAssociationRefs.get(0).isPrimary()); assertFalse(childAssociationRefs.get(0).isPrimary());
checkNumOfEvents(3); checkNumOfEvents(4);
final RepoEvent<EventData<ChildAssociationResource>> childAssocRepoEvent = getRepoEventWithoutWait(3); final RepoEvent<EventData<ChildAssociationResource>> childAssocRepoEvent = getFilteredEvent(EventType.CHILD_ASSOC_CREATED, 0);
assertEquals("Wrong repo event type.", EventType.CHILD_ASSOC_CREATED.getType(), childAssocRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.CHILD_ASSOC_CREATED.getType(), childAssocRepoEvent.getType());
assertNotNull("Repo event ID is not available.", childAssocRepoEvent.getId()); assertNotNull("Repo event ID is not available.", childAssocRepoEvent.getId());
@@ -131,7 +131,7 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
assertEquals(1, childAssociationRefs.size()); assertEquals(1, childAssociationRefs.size());
assertFalse(childAssociationRefs.get(0).isPrimary()); assertFalse(childAssociationRefs.get(0).isPrimary());
checkNumOfEvents(3); checkNumOfEvents(4);
retryingTransactionHelper.doInTransaction(() -> retryingTransactionHelper.doInTransaction(() ->
nodeService.removeChildAssociation(childAssociationRef)); nodeService.removeChildAssociation(childAssociationRef));
@@ -141,9 +141,9 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
assertEquals(0, childAssociationRefs.size()); assertEquals(0, childAssociationRefs.size());
checkNumOfEvents(4); checkNumOfEvents(6);
final RepoEvent<EventData<ChildAssociationResource>> childAssocRepoEvent = getRepoEventWithoutWait(4); final RepoEvent<EventData<ChildAssociationResource>> childAssocRepoEvent = getFilteredEvent(EventType.CHILD_ASSOC_DELETED, 0);
assertEquals("Wrong repo event type.", EventType.CHILD_ASSOC_DELETED.getType(), childAssocRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.CHILD_ASSOC_DELETED.getType(), childAssocRepoEvent.getType());
assertNotNull("Repo event ID is not available. ", childAssocRepoEvent.getId()); assertNotNull("Repo event ID is not available. ", childAssocRepoEvent.getId());
@@ -212,7 +212,7 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
return null; return null;
}); });
checkNumOfEvents(7); checkNumOfEvents(8);
// 3 assoc.child.Created events should be created // 3 assoc.child.Created events should be created
@@ -268,7 +268,7 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
return null; return null;
}); });
checkNumOfEvents(7); checkNumOfEvents(8);
// 3 assoc.child.Created events should be created // 3 assoc.child.Created events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED);
assertEquals("Wrong association events number",3, childAssocEvents.size()); assertEquals("Wrong association events number",3, childAssocEvents.size());
@@ -330,7 +330,7 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
return null; return null;
}); });
checkNumOfEvents(7); checkNumOfEvents(10);
// 3 assoc.child.Created events should be created // 3 assoc.child.Created events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED);
assertEquals("Wrong association events number",3, childAssocEvents.size()); assertEquals("Wrong association events number",3, childAssocEvents.size());
@@ -388,7 +388,7 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
return null; return null;
}); });
checkNumOfEvents(7); checkNumOfEvents(10);
// 3 assoc.child.Created events should be created // 3 assoc.child.Created events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED);
assertEquals("Wrong association events number",3, childAssocEvents.size()); assertEquals("Wrong association events number",3, childAssocEvents.size());
@@ -432,7 +432,7 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
return null; return null;
}); });
checkNumOfEvents(7); checkNumOfEvents(10);
// 3 assoc.child.Created events should be created // 3 assoc.child.Created events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_CREATED);
assertEquals("Wrong association events number",3, childAssocEvents.size()); assertEquals("Wrong association events number",3, childAssocEvents.size());
@@ -501,7 +501,7 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
return null; return null;
}); });
checkNumOfEvents(10); checkNumOfEvents(12);
// 3 assoc.child.Deleted events should be created // 3 assoc.child.Deleted events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED);
@@ -557,7 +557,7 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
nodeService.removeChildAssociation(childAssociationRef)); nodeService.removeChildAssociation(childAssociationRef));
} }
checkNumOfEvents(10); checkNumOfEvents(14);
// 3 assoc.child.Deleted events should be created // 3 assoc.child.Deleted events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED);
@@ -619,7 +619,7 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
deleteNode(parentNodeRef); deleteNode(parentNodeRef);
checkNumOfEvents(11); checkNumOfEvents(17);
// 3 assoc.child.Deleted events should be created // 3 assoc.child.Deleted events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED);
@@ -670,7 +670,7 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
deleteNode(childNodeRef); deleteNode(childNodeRef);
checkNumOfEvents(11); checkNumOfEvents(12);
// 3 assoc.child.Deleted events should be created // 3 assoc.child.Deleted events should be created
List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED); List<RepoEvent<EventData<ChildAssociationResource>>> childAssocEvents = getFilteredEvents(EventType.CHILD_ASSOC_DELETED);
@@ -708,13 +708,14 @@ public class ChildAssociationRepoEventIT extends AbstractContextAwareRepoEvent
assertEquals(1, childAssociationRefs.size()); assertEquals(1, childAssociationRefs.size());
assertFalse(childAssociationRefs.get(0).isPrimary()); assertFalse(childAssociationRefs.get(0).isPrimary());
checkNumOfEvents(4); checkNumOfEvents(5);
// Check the node events occur before the child association event // Check the node events occur before the child association event
List<RepoEvent<?>> repoEvents = getRepoEventsContainer().getEvents(); List<RepoEvent<?>> repoEvents = getRepoEventsContainer().getEvents();
assertEquals("org.alfresco.event.node.Created", repoEvents.get(0).getType()); assertEquals("org.alfresco.event.node.Created", repoEvents.get(0).getType());
assertEquals("org.alfresco.event.node.Created", repoEvents.get(1).getType()); assertEquals("org.alfresco.event.node.Created", repoEvents.get(1).getType());
assertEquals("org.alfresco.event.node.Updated", repoEvents.get(2).getType()); assertEquals("org.alfresco.event.node.Updated", repoEvents.get(2).getType());
assertEquals("org.alfresco.event.assoc.child.Created", repoEvents.get(3).getType()); assertEquals("org.alfresco.event.node.Updated", repoEvents.get(3).getType());
assertEquals("org.alfresco.event.assoc.child.Created", repoEvents.get(4).getType());
} }
} }

View File

@@ -119,6 +119,9 @@ public class EventFilterUnitTest
assertTrue("System properties are excluded by default.", assertTrue("System properties are excluded by default.",
propertyFilter.isExcluded(ContentModel.PROP_NODE_DBID)); propertyFilter.isExcluded(ContentModel.PROP_NODE_DBID));
assertFalse("Property cascadeTx is not excluded", propertyFilter.isExcluded(ContentModel.PROP_CASCADE_TX));
assertFalse("Property cascadeCRC is not excluded", propertyFilter.isExcluded(ContentModel.PROP_CASCADE_CRC));
assertFalse(propertyFilter.isExcluded(ContentModel.PROP_TITLE)); assertFalse(propertyFilter.isExcluded(ContentModel.PROP_TITLE));
} }

View File

@@ -87,7 +87,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
}); });
checkNumOfEvents(2); checkNumOfEvents(2);
resultRepoEvent = getRepoEvent(2); resultRepoEvent = getRepoEvent(2);
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(), assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
resultRepoEvent.getType()); resultRepoEvent.getType());
@@ -227,7 +227,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
}); });
checkNumOfEvents(2); checkNumOfEvents(2);
resultRepoEvent = getRepoEvent(2); resultRepoEvent = getRepoEvent(2);
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(), resultRepoEvent.getType());
@@ -625,7 +625,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
// Create active model // Create active model
CustomModelDefinition modelDefinition = CustomModelDefinition modelDefinition =
retryingTransactionHelper.doInTransaction(() -> customModelService.createCustomModel(model, true)); retryingTransactionHelper.doInTransaction(() -> customModelService.createCustomModel(model, true));
assertNotNull(modelDefinition); assertNotNull(modelDefinition);
assertEquals(modelName, modelDefinition.getName().getLocalName()); assertEquals(modelName, modelDefinition.getName().getLocalName());
@@ -635,8 +635,11 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
Collection<TypeDefinition> types = modelDefinition.getTypeDefinitions(); Collection<TypeDefinition> types = modelDefinition.getTypeDefinitions();
assertEquals(1, types.size()); assertEquals(1, types.size());
// we should have only 2 events, node.Created and node.Updated
checkNumOfEvents(2);
// node.Created event should be generated for the model // node.Created event should be generated for the model
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEvent(1); RepoEvent<EventData<NodeResource>> resultRepoEvent = getFilteredEvent(EventType.NODE_CREATED, 0);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
NodeResource nodeResource = getNodeResource(resultRepoEvent); NodeResource nodeResource = getNodeResource(resultRepoEvent);
assertEquals("Incorrect node type was found", "cm:dictionaryModel", nodeResource.getNodeType()); assertEquals("Incorrect node type was found", "cm:dictionaryModel", nodeResource.getNodeType());
@@ -647,9 +650,9 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
assertEquals(ContentModel.TYPE_CONTENT, nodeService.getType(nodeRef)); assertEquals(ContentModel.TYPE_CONTENT, nodeService.getType(nodeRef));
// node.Created event should be generated // node.Created event should be generated
resultRepoEvent = getRepoEvent(2); resultRepoEvent = getRepoEvent(3);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
nodeResource = getNodeResource(resultRepoEvent); nodeResource = getNodeResource(resultRepoEvent);
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
assertEquals("cm:content node type was not found", "cm:content", nodeResource.getNodeType()); assertEquals("cm:content node type was not found", "cm:content", nodeResource.getNodeType());
QName typeQName = QName.createQName("{" + namespacePair.getFirst()+ "}" + typeName); QName typeQName = QName.createQName("{" + namespacePair.getFirst()+ "}" + typeName);
@@ -661,15 +664,15 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
return null; return null;
}); });
// we should have 3 events, node.Created for the model, node.Created for the node and node.Updated // we should have 4 events, node.Created for the model, node.Updated for the parent, node.Created for the node and node.Updated
checkNumOfEvents(3); checkNumOfEvents(4);
resultRepoEvent = getRepoEvent(3); resultRepoEvent = getRepoEvent(4);
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(), resultRepoEvent.getType()); assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(), resultRepoEvent.getType());
nodeResource = getNodeResource(resultRepoEvent); nodeResource = getNodeResource(resultRepoEvent);
assertEquals("Incorrect node type was found", namespacePair.getSecond() + QName.NAMESPACE_PREFIX + typeName, nodeResource.getNodeType()); assertEquals("Incorrect node type was found", namespacePair.getSecond() + QName.NAMESPACE_PREFIX + typeName, nodeResource.getNodeType());
NodeResource resourceBefore = getNodeResourceBefore(3); NodeResource resourceBefore = getNodeResourceBefore(4);
assertEquals("Incorrect node type was found", "cm:content", resourceBefore.getNodeType()); assertEquals("Incorrect node type was found", "cm:content", resourceBefore.getNodeType());
assertNull(resourceBefore.getId()); assertNull(resourceBefore.getId());
assertNull(resourceBefore.getContent()); assertNull(resourceBefore.getContent());
@@ -788,7 +791,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
}); });
checkNumOfEvents(4); checkNumOfEvents(4);
NodeResource resourceBefore = getNodeResourceBefore(4); NodeResource resourceBefore = getNodeResourceBefore(4);
NodeResource resource = getNodeResource(4); NodeResource resource = getNodeResource(4);
@@ -808,7 +811,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
assertNull(resourceBefore.getModifiedByUser()); assertNull(resourceBefore.getModifiedByUser());
assertNull(resourceBefore.getCreatedAt()); assertNull(resourceBefore.getCreatedAt());
assertNull(resourceBefore.getCreatedByUser()); assertNull(resourceBefore.getCreatedByUser());
assertNull(resourceBefore.getProperties()); assertNotNull(resourceBefore.getProperties());
assertNull(resourceBefore.getAspectNames()); assertNull(resourceBefore.getAspectNames());
assertNotNull(resourceBefore.getPrimaryHierarchy()); assertNotNull(resourceBefore.getPrimaryHierarchy());
assertNull("Content should have been null.", resource.getContent()); assertNull("Content should have been null.", resource.getContent());
@@ -818,7 +821,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
assertNotNull(resource.getModifiedByUser()); assertNotNull(resource.getModifiedByUser());
assertNotNull(resource.getAspectNames()); assertNotNull(resource.getAspectNames());
assertNull(resource.getContent()); assertNull(resource.getContent());
assertTrue(resource.getProperties().isEmpty()); assertFalse(resource.getProperties().isEmpty());
} }
@Test @Test
@@ -1020,7 +1023,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
NodeResource resource = getNodeResource(1); NodeResource resource = getNodeResource(1);
final Set<String> originalAspects = resource.getAspectNames(); final Set<String> originalAspects = resource.getAspectNames();
assertNotNull(originalAspects); assertNotNull(originalAspects);
retryingTransactionHelper.doInTransaction(() -> { retryingTransactionHelper.doInTransaction(() -> {
// Add cm:geographic aspect with default value // Add cm:geographic aspect with default value
nodeService.addAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC, null); nodeService.addAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC, null);