) () -> {
+
if (nodeService.exists(nodeRef) &&
(isRecord(nodeRef) || instanceOf(nodeRef, TYPE_CONTENT)))
{
// get the owning folder
- NodeRef owningFolder = nodeService.getPrimaryParent(nodeRef).getParentRef();
+ final NodeRef owningFolder = nodeService.getPrimaryParent(nodeRef).getParentRef();
// check that the aspect has been added
if (nodeService.hasAspect(owningFolder, ASPECT_HELD_CHILDREN))
{
// decrement current count
- int currentCount = (Integer) nodeService.getProperty(owningFolder, PROP_HELD_CHILDREN_COUNT);
+ final int currentCount = (Integer) nodeService.getProperty(owningFolder, PROP_HELD_CHILDREN_COUNT);
if (currentCount > 0)
{
nodeService.setProperty(owningFolder, PROP_HELD_CHILDREN_COUNT, currentCount - 1);
@@ -214,4 +201,91 @@ public class FrozenAspect extends BaseBehaviourBean
});
}
+ /**
+ * Behaviour associated with moving a frozen node
+ *
+ * Prevent frozen items being moved
+ */
+ @Override
+ @Behaviour
+ (
+ kind = BehaviourKind.ASSOCIATION,
+ notificationFrequency = NotificationFrequency.FIRST_EVENT
+ )
+ public void onMoveNode(final ChildAssociationRef oldChildAssocRef, final ChildAssociationRef newChildAssocRef)
+ {
+ AuthenticationUtil.runAsSystem((RunAsWork) () -> {
+ if (nodeService.exists(newChildAssocRef.getParentRef()) &&
+ nodeService.exists(newChildAssocRef.getChildRef()))
+ {
+ throw new AccessDeniedException("Frozen nodes can not be moved.");
+ }
+ return null;
+ });
+ }
+
+ /**
+ * Behaviour associated with updating properties
+ *
+ * Prevents frozen items being updated
+ */
+ @Override
+ @Behaviour
+ (
+ kind = BehaviourKind.CLASS,
+ notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT
+ )
+ public void onUpdateProperties(NodeRef nodeRef, Map before, Map after)
+
+ {
+ AuthenticationUtil.runAsSystem((RunAsWork) () -> {
+ // check to not throw exception when the aspect is being added
+ if (nodeService.exists(nodeRef) && freezeService.isFrozen(nodeRef) &&
+ !transactionalResourceHelper.getSet(nodeRef).contains("frozen") )
+ {
+ throw new AccessDeniedException("Frozen nodes can not be updated.");
+ }
+ return null;
+ });
+ }
+
+ /**
+ * Behaviour associated with updating the content
+ *
+ * Ensures that the content of a frozen node can not be updated
+ */
+ @Override
+ @Behaviour
+ (
+ kind = BehaviourKind.CLASS,
+ notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT
+ )
+ public void onContentUpdate(NodeRef nodeRef, boolean newContent)
+ {
+ AuthenticationUtil.runAsSystem((RunAsWork) () -> {
+ if (nodeService.exists(nodeRef) && freezeService.isFrozen(nodeRef))
+ {
+ // never allow to update the content of a frozen node
+ throw new AccessDeniedException("Frozen nodes content can not be updated.");
+ }
+ return null;
+ });
+ }
+
+ @Override
+ @Behaviour
+ (
+ kind = BehaviourKind.CLASS
+ )
+ public void beforeCopy(QName classRef, NodeRef sourceNodeRef, NodeRef targetNodeRef)
+ {
+ AuthenticationUtil.runAsSystem((RunAsWork) () -> {
+ if (nodeService.exists(sourceNodeRef) && freezeService.isFrozen(sourceNodeRef))
+ {
+ throw new AccessDeniedException("Frozen nodes can not be copied.");
+ }
+
+ return null;
+ });
+ }
}
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/hold/RemoveActiveContentToHoldTest.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/hold/RemoveActiveContentFromHoldTest.java
similarity index 99%
rename from rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/hold/RemoveActiveContentToHoldTest.java
rename to rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/hold/RemoveActiveContentFromHoldTest.java
index 6c597f15d4..8a4181116e 100644
--- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/hold/RemoveActiveContentToHoldTest.java
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/hold/RemoveActiveContentFromHoldTest.java
@@ -42,7 +42,7 @@ import org.springframework.extensions.webscripts.GUID;
* @author Ross Gale
* @since 3.2
*/
-public class RemoveActiveContentToHoldTest extends BaseRMTestCase
+public class RemoveActiveContentFromHoldTest extends BaseRMTestCase
{
@Override
protected boolean isCollaborationSiteTest()
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/FrozenAspectUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/FrozenAspectUnitTest.java
index a6ca309f0a..2a4010142a 100644
--- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/FrozenAspectUnitTest.java
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/FrozenAspectUnitTest.java
@@ -29,15 +29,25 @@ package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect;
import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.ASPECT_HELD_CHILDREN;
import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.ASPECT_RECORD;
import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.PROP_HELD_CHILDREN_COUNT;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyMap;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService;
import org.alfresco.module.org_alfresco_module_rm.util.NodeTypeUtility;
+import org.alfresco.module.org_alfresco_module_rm.util.TransactionalResourceHelper;
+import org.alfresco.repo.security.permissions.AccessDeniedException;
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.namespace.QName;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
@@ -64,12 +74,37 @@ public class FrozenAspectUnitTest
@Mock
private NodeTypeUtility mockedNodeTypeUtility;
+ @Mock
+ private FreezeService mockFreezeService;
+
+ @Mock
+ private TransactionalResourceHelper mockResourceHelper;
+
+ @Mock
+ private ChildAssociationRef mockChildRef;
+
+ @Mock
+ private ChildAssociationRef mockParentRef;
+
+ @Mock
+ private ChildAssociationRef mockOldRef;
+
+ @Mock
+ private ChildAssociationRef mockNewRef;
+
+ @Mock
+ private Set mockSet;
+
@InjectMocks
private FrozenAspect frozenAspect;
+ private final List children = new ArrayList<>();
+
private NodeRef record = new NodeRef("workspace://record/node");
private NodeRef folder = new NodeRef("workspace://folder/node");
private NodeRef content = new NodeRef("workspace://content/node");
+ private NodeRef child = new NodeRef("workspace://content/child");
+ private NodeRef parent = new NodeRef("workspace://content/parent");
@Before
public void setUp()
@@ -80,6 +115,11 @@ public class FrozenAspectUnitTest
when(mockNodeService.hasAspect(folder, ASPECT_HELD_CHILDREN)).thenReturn(true);
when(mockNodeService.getProperty(folder, PROP_HELD_CHILDREN_COUNT)).thenReturn(1);
when(mockApplicationContext.getBean("dbNodeService")).thenReturn(mockNodeService);
+ when(mockNodeService.exists(content)).thenReturn(true);
+ when(mockFreezeService.isFrozen(content)).thenReturn(false);
+ children.add(mockChildRef);
+ when(mockNodeService.getChildAssocs(content)).thenReturn(children);
+ when(mockChildRef.isPrimary()).thenReturn(true);
}
/**
@@ -122,4 +162,111 @@ public class FrozenAspectUnitTest
frozenAspect.onRemoveAspect(content, null);
verify(mockNodeService, times(0)).setProperty(folder, PROP_HELD_CHILDREN_COUNT, 0);
}
+
+ /**
+ * Test before delete throws an error if a node is frozen
+ */
+ @Test(expected = AccessDeniedException.class)
+ public void testBeforeDeleteNodeThrowsExceptionIfNodeFrozen()
+ {
+ when(mockFreezeService.isFrozen(content)).thenReturn(true);
+ frozenAspect.beforeDeleteNode(content);
+ }
+
+ /**
+ * Test before delete is fine for non-frozen nodes
+ */
+ @Test
+ public void testBeforeDeleteForNonFrozenNodes()
+ {
+ frozenAspect.beforeDeleteNode(content);
+ verify(mockNodeService, times(1)).getChildAssocs(content);
+ verify(mockChildRef, times(1)).getChildRef();
+ }
+
+ /**
+ * Test before delete throws an error for a node with frozen children
+ */
+ @Test (expected = AccessDeniedException.class)
+ public void testBeforeDeleteThrowsExceptionForFrozenChild()
+ {
+ when(mockChildRef.getChildRef()).thenReturn(child);
+ when(mockFreezeService.isFrozen(child)).thenReturn(true);
+ frozenAspect.beforeDeleteNode(content);
+ }
+
+ /**
+ * Test on add aspect for a record node
+ */
+ @Test
+ public void testOnAddAspectForRecord()
+ {
+ when(mockNodeService.getType(record)).thenReturn(ContentModel.TYPE_CONTENT);
+ when(mockNodeService.getPrimaryParent(record)).thenReturn(mockParentRef);
+ when(mockParentRef.getParentRef()).thenReturn(parent);
+ when(mockNodeService.hasAspect(parent, ASPECT_HELD_CHILDREN)).thenReturn(true);
+ when(mockNodeService.getProperty(parent, PROP_HELD_CHILDREN_COUNT)).thenReturn(0);
+ frozenAspect.onAddAspect(record,null);
+ verify(mockNodeService, times(1)).setProperty(parent, PROP_HELD_CHILDREN_COUNT,1);
+ }
+
+ /**
+ * Test on add for a content node
+ */
+ @Test
+ public void testOnAddAspectForContent()
+ {
+ when(mockNodeService.getType(record)).thenReturn(ContentModel.TYPE_CONTENT);
+ when(mockNodeService.getPrimaryParent(record)).thenReturn(mockParentRef);
+ when(mockParentRef.getParentRef()).thenReturn(parent);
+ when(mockNodeService.hasAspect(parent, ASPECT_HELD_CHILDREN)).thenReturn(false);
+ when(mockNodeService.getType(parent)).thenReturn(ContentModel.TYPE_FOLDER);
+ frozenAspect.onAddAspect(record, null);
+ verify(mockNodeService, times(1)).addAspect(any(NodeRef.class), any(QName.class), anyMap());
+ }
+
+ /**
+ * Test on move throws an error for a frozen node
+ */
+ @Test(expected = AccessDeniedException.class)
+ public void testOnMoveThrowsExceptionForFrozenNode()
+ {
+ when(mockNewRef.getParentRef()).thenReturn(parent);
+ when(mockNewRef.getChildRef()).thenReturn(child);
+ when(mockNodeService.exists(parent)).thenReturn(true);
+ when(mockNodeService.exists(child)).thenReturn(true);
+ frozenAspect.onMoveNode(mockOldRef, mockNewRef);
+ }
+
+ /**
+ * Test update properties throws an error for frozen nodes
+ */
+ @Test(expected = AccessDeniedException.class)
+ public void testUpdatePropertiesThrowsExceptionForFrozenNode()
+ {
+ when(mockFreezeService.isFrozen(content)).thenReturn(true);
+ when(mockResourceHelper.getSet(content)).thenReturn(mockSet);
+ when(mockSet.contains("frozen")).thenReturn(false);
+ frozenAspect.onUpdateProperties(content, null, null);
+ }
+
+ /**
+ * Test on content update throws an error for frozen nodes
+ */
+ @Test(expected = AccessDeniedException.class)
+ public void testOnContentUpdateThrowsExceptionForFrozenNode()
+ {
+ when(mockFreezeService.isFrozen(content)).thenReturn(true);
+ frozenAspect.onContentUpdate(content, false);
+ }
+
+ /**
+ * Test before copy throws an error for frozen node
+ */
+ @Test(expected = AccessDeniedException.class)
+ public void testBeforeCopyThrowsExceptionForFrozenNode()
+ {
+ when(mockFreezeService.isFrozen(content)).thenReturn(true);
+ frozenAspect.beforeCopy(null, content, null);
+ }
}