RM-6869 removing linked record during rejection

This commit is contained in:
Ross Gale
2019-06-03 11:10:16 +01:00
parent 5e0b15fb51
commit d06ac5abc5
4 changed files with 216 additions and 2 deletions

View File

@@ -75,4 +75,30 @@ public class ActionsExecutionAPI extends RMModelRequest
return getRmRestWrapper().withCoreAPI().usingActions() return getRmRestWrapper().withCoreAPI().usingActions()
.executeAction(ActionsOnRule.DECLARE_AS_RECORD.getActionValue(), targetNode); .executeAction(ActionsOnRule.DECLARE_AS_RECORD.getActionValue(), targetNode);
} }
/**
* Links a record to a new record folder using v1 actions api
*
* @param targetNode the node on which the action is executed
* @param destination the path of the category/folder to create and place the link
*/
public JSONObject linkRecord(RepoTestModel targetNode, String destination) throws Exception
{
return getRmRestWrapper().withCoreAPI().usingActions()
.executeAction(ActionsOnRule.LINK_TO.getActionValue(), targetNode,
ImmutableMap.of("path", destination, "createRecordPath", "true"));
}
/**
* Rejects a record using v1 actions api
*
* @param targetNode record to reject
* @param reason reason for rejection
*/
public JSONObject rejectRecord(RepoTestModel targetNode, String reason) throws Exception
{
return getRmRestWrapper().withCoreAPI().usingActions()
.executeAction(ActionsOnRule.REJECT.getActionValue(), targetNode,
ImmutableMap.of("reason", reason));
}
} }

View File

@@ -0,0 +1,113 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.records;
import static org.alfresco.utility.data.RandomData.getRandomName;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.junit.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.util.Optional;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChildCollection;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChildEntry;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.Utility;
import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.SiteModel;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* API tests for rejecting records
* @author Ross Gale
* @since 3.1
*/
public class RejectRecordTests extends BaseRMRestTest
{
private SiteModel publicSite;
private RecordCategory recordCategory;
private RecordCategoryChild recordFolder;
@BeforeClass (alwaysRun = true)
public void setUp() throws Exception
{
createRMSiteIfNotExists();
publicSite = dataSite.usingAdmin().createPublicRandomSite();
recordCategory = createRootCategory(getRandomName("recordCategory"));
recordFolder = createFolder(recordCategory.getId(), getRandomName("recordFolder"));
}
/**
* Test that when rejecting a linked record that the link is also removed
*/
@Test
@AlfrescoTest(jira = "RM-6869")
public void declareAndFileToValidLocationUsingActionsAPI() throws Exception
{
STEP("Create a document in the collaboration site");
FileModel testFile = dataContent.usingSite(publicSite)
.usingAdmin()
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
STEP("Declare document as record with a location parameter value");
getRestAPIFactory().getActionsAPI(getAdminUser()).declareAndFile(testFile,
Utility.buildPath(recordCategory.getName(), recordFolder.getName()));
STEP("Link record to new folder");
getRestAPIFactory().getActionsAPI().linkRecord(testFile, recordCategory.getName() + "/" + recordFolder.getName() + "_2");
RecordCategoryChildCollection recordFolders = getRestAPIFactory().getRecordCategoryAPI().getRecordCategoryChildren(recordCategory.getId());
Optional<RecordCategoryChildEntry> linkedFolder = recordFolders.getEntries().stream().filter(child -> child.getEntry().getName().equals(recordFolder.getName() + "_2"))
.findFirst();
if (linkedFolder.isPresent())
{
STEP("Verify the linked record has been added");
assertFalse(getRestAPIFactory().getRecordFolderAPI().getRecordFolderChildren(linkedFolder.get().getEntry().getId()).isEmpty());
STEP("Reject record");
getRestAPIFactory().getActionsAPI().rejectRecord(testFile, "Just because");
STEP("Check record has been rejected");
assertFalse(isMatchingRecordInRecordFolder(testFile, recordFolder));
STEP("Verify the linked record has been removed");
assertTrue(getRestAPIFactory().getRecordFolderAPI().getRecordFolderChildren(linkedFolder.get().getEntry().getId()).isEmpty());
}
}
@AfterClass (alwaysRun = true)
public void cleanUp()
{
deleteRecordCategory(recordCategory.getId());
dataSite.deleteSite(publicSite);
}
}

View File

@@ -1497,10 +1497,11 @@ public class RecordServiceImpl extends BaseBehaviourBean
final List<ChildAssociationRef> parentAssocs = nodeService.getParentAssocs(nodeRef); final List<ChildAssociationRef> parentAssocs = nodeService.getParentAssocs(nodeRef);
for (ChildAssociationRef childAssociationRef : parentAssocs) for (ChildAssociationRef childAssociationRef : parentAssocs)
{ {
if (!childAssociationRef.isPrimary() && childAssociationRef.getParentRef().equals(originatingLocation)) if (!childAssociationRef.isPrimary() &&
(childAssociationRef.getParentRef().equals(originatingLocation) ||
nodeService.getType(childAssociationRef.getParentRef()).equals(TYPE_RECORD_FOLDER)))
{ {
nodeService.removeChildAssociation(childAssociationRef); nodeService.removeChildAssociation(childAssociationRef);
break;
} }
} }

View File

@@ -41,7 +41,10 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -49,10 +52,12 @@ import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
import org.alfresco.module.org_alfresco_module_rm.notification.RecordsManagementNotificationHelper;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
import org.alfresco.repo.node.integrity.IntegrityException; import org.alfresco.repo.node.integrity.IntegrityException;
import org.alfresco.repo.policy.Behaviour; import org.alfresco.repo.policy.Behaviour;
import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.rendition.RenditionService;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AccessStatus;
@@ -63,6 +68,7 @@ import org.apache.commons.collections.CollectionUtils;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy; import org.mockito.Spy;
/** /**
@@ -81,6 +87,24 @@ public class RecordServiceImplUnitTest extends BaseUnitTest
private NodeRef closedRecordFolder; private NodeRef closedRecordFolder;
private ChildAssociationRef parentAssoc; private ChildAssociationRef parentAssoc;
private final String recordId = "recordId";
private final String documentOwner = "Bob";
private final String originalName = "originalName";
private final NodeRef originatingLocation = new NodeRef("workspace://SpacesStore/originalLocation");
private final NodeRef link = new NodeRef("workspace://SpacesStore/linkLocation");
@Mock
private RenditionService mockedRenditionService;
@Mock
private RecordsManagementNotificationHelper mockedNotificationHelper;
@Mock
private ChildAssociationRef mockedChildAssoc;
@Mock
private ChildAssociationRef mockedLinkAssoc;
@Mock
private ChildAssociationRef mockedParentAssoc;
private static QName TYPE_MY_FILE_PLAN = generateQName(); private static QName TYPE_MY_FILE_PLAN = generateQName();
private static QName ASPECT_FOR_FILE_PLAN = generateQName(); private static QName ASPECT_FOR_FILE_PLAN = generateQName();
@@ -639,4 +663,54 @@ public class RecordServiceImplUnitTest extends BaseUnitTest
when(mockedVersionService.getVersionHistory(dmNodeRef)).thenReturn(null); when(mockedVersionService.getVersionHistory(dmNodeRef)).thenReturn(null);
} }
/**
* Setup the mocks for the reject record scenarios
* @param mockProperties the mock for the node properties
*/
private void setUpReject(Map mockProperties)
{
when(mockedNodeService.getProperties(dmNodeRef)).thenReturn(mockProperties);
when(mockedVersionService.getVersionHistory(dmNodeRef)).thenReturn(null);
when(mockProperties.get(PROP_IDENTIFIER)).thenReturn(recordId);
when(mockProperties.get(PROP_ORIGIONAL_NAME)).thenReturn(originalName);
when(mockProperties.get(PROP_RECORD_ORIGINATING_LOCATION)).thenReturn(originatingLocation);
List<ChildAssociationRef> assocs = new ArrayList<>();
assocs.add(mockedChildAssoc);
assocs.add(mockedLinkAssoc);
when(mockedNodeService.getParentAssocs(dmNodeRef)).thenReturn(assocs);
when(mockedChildAssoc.getParentRef()).thenReturn(originatingLocation);
when(mockedLinkAssoc.getParentRef()).thenReturn(dmNodeRef);
when(mockedLinkAssoc.getParentRef()).thenReturn(link);
when(mockedNodeService.getType(link)).thenReturn(TYPE_RECORD_FOLDER);
when(mockedNodeService.getPrimaryParent(dmNodeRef)).thenReturn(mockedParentAssoc);
when(mockedParentAssoc.getQName()).thenReturn(ContentModel.TYPE_CATEGORY);
doNothing().when(recordService).invokeBeforeRecordRejection(dmNodeRef);
doNothing().when(recordService).invokeOnRecordRejection(dmNodeRef);
}
/**
* Test for the reject record method
*/
@Test
public void testRejectRecord()
{
Map mockProperties = mock(HashMap.class);
setUpReject(mockProperties);
when(mockProperties.get(PROP_RECORD_ORIGINATING_USER_ID)).thenReturn(documentOwner);
recordService.rejectRecord(dmNodeRef, "Just because..");
verify(mockedNodeService, times(1)).removeChildAssociation(mockedChildAssoc);
verify(mockedNodeService, times(1)).removeChildAssociation(mockedLinkAssoc);
}
/**
* Test for the reject record method throws an error without document owner
*/
@Test (expected = AlfrescoRuntimeException.class)
public void testRejectRecordThrowsErrorWithoutDocumentOwner()
{
Map mockProperties = mock(HashMap.class);
setUpReject(mockProperties);
when(mockProperties.get(PROP_RECORD_ORIGINATING_USER_ID)).thenReturn(null);
recordService.rejectRecord(dmNodeRef, "Just because..");
}
} }