diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml index 46cc7a2483..91ff7f93eb 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml @@ -32,4 +32,12 @@ + + + + + + + + \ No newline at end of file diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml index 7fdded0880..f3e8e1f0c1 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-record-context.xml @@ -211,7 +211,7 @@ - + @@ -340,4 +340,16 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml index c884558fad..a17e7410f5 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml @@ -1039,6 +1039,7 @@ + @@ -1100,6 +1101,7 @@ org.alfresco.module.org_alfresco_module_rm.record.RecordService.addRecordType=RM_ALLOW org.alfresco.module.org_alfresco_module_rm.record.RecordService.makeRecord=RM_ALLOW org.alfresco.module.org_alfresco_module_rm.record.RecordService.link=RM_ALLOW + org.alfresco.module.org_alfresco_module_rm.record.RecordService.moveRecord=RM.Write.0 org.alfresco.module.org_alfresco_module_rm.record.RecordService.*=RM_DENY ]]> diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml index 96be6476a8..1c1cb4115c 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml @@ -860,7 +860,7 @@ - + @@ -871,4 +871,15 @@ + + + + + + RECORD + + + + \ No newline at end of file diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/HideRecordAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/HideRecordAction.java index b3e50912ac..9eef3871f7 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/HideRecordAction.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/HideRecordAction.java @@ -39,7 +39,7 @@ import org.apache.commons.logging.LogFactory; * @since 2.1 */ public class HideRecordAction extends AuditableActionExecuterAbstractBase - implements RecordsManagementModel + implements RecordsManagementModel { /** Logger */ diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/MoveDmRecordAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/MoveDmRecordAction.java new file mode 100644 index 0000000000..adc33c01e7 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/MoveDmRecordAction.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * 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 . + */ +package org.alfresco.module.org_alfresco_module_rm.action.dm; + +import java.util.List; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.module.org_alfresco_module_rm.action.AuditableActionExecuterAbstractBase; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ParameterDefinition; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Moves a record within a collaboration site. + * The record can be moved only within the collaboration site where it was declared. + * + * @author Tuna Aksoy + * @since 2.3 + */ +public class MoveDmRecordAction extends AuditableActionExecuterAbstractBase implements RecordsManagementModel +{ + /** Logger */ + private static Log logger = LogFactory.getLog(MoveDmRecordAction.class); + + /** Action name */ + public static final String NAME = "move-dm-record"; + + /** Constant for target node reference parameter */ + public static final String PARAM_TARGET_NODE_REF = "targetNodeRef"; + + /** Node service */ + private NodeService nodeService; + + /** Record service */ + private RecordService recordService; + + /** + * Gets the node service + * + * @return Node service + */ + protected NodeService getNodeService() + { + return this.nodeService; + } + + /** + * Sets the node service + * + * @param nodeService Node service + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * Gets the record service + * + * @return Record service + */ + protected RecordService getRecordService() + { + return this.recordService; + } + + /** + * Sets the record service + * + * @param recordService Record service + */ + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } + + /** + * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef) + */ + @Override + protected void executeImpl(Action action, NodeRef actionedUponNodeRef) + { + // Cannot move a document which is not a record + if (!getNodeService().hasAspect(actionedUponNodeRef, ASPECT_RECORD) && logger.isDebugEnabled()) + { + logger.debug("Cannot move the document, because '" + actionedUponNodeRef.toString() + "' is not a record."); + } + else + { + // Move the record within the collaboration site + getRecordService().moveRecord(actionedUponNodeRef, getTargetNodeRef(action)); + } + } + + /** + * Helper method to get the target node reference from the action parameter + * + * @param action The action + * @return Node reference of the target + */ + private NodeRef getTargetNodeRef(Action action) + { + String targetNodeRef = (String) action.getParameterValue(PARAM_TARGET_NODE_REF); + + if (StringUtils.isBlank(targetNodeRef)) + { + throw new AlfrescoRuntimeException("Could not find target node reference."); + } + + return new NodeRef(targetNodeRef); + } + + /** + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) + */ + @Override + protected void addParameterDefinitions(List paramList) + { + // Intentionally empty + } +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java index 92a17e9b86..d1705b3ea0 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java @@ -56,10 +56,10 @@ public interface RecordService * Disables the property editable check. */ void disablePropertyEditableCheck(); - + /** * Disables the property editable check for a given node in this transaction only. - * + * * @param nodeRef node reference * @since 2.2 */ @@ -231,4 +231,12 @@ public interface RecordService * @param folder The folder in which the link will be created */ void link(NodeRef nodeRef, NodeRef folder); + + /** + * Moves a record within a collaboration site + * + * @param nodeRef The record which should be moved + * @param targetNodeRef The target node reference where it should be moved to + */ + void moveRecord(NodeRef nodeRef, NodeRef targetNodeRef); } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java index 0cc4cd45f2..a1f5bf7033 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java @@ -80,6 +80,8 @@ import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.OwnableService; import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.site.SiteInfo; +import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; @@ -194,6 +196,9 @@ public class RecordServiceImpl extends BaseBehaviourBean /** Permission service */ private PermissionService permissionService; + /** Site service */ + private SiteService siteService; + /** list of available record meta-data aspects and the file plan types the are applicable to */ private Map> recordMetaDataAspects; @@ -315,6 +320,14 @@ public class RecordServiceImpl extends BaseBehaviourBean this.permissionService = permissionService; } + /** + * @param siteService site service + */ + public void setSiteService(SiteService siteService) + { + this.siteService = siteService; + } + /** * Init method */ @@ -1475,4 +1488,68 @@ public class RecordServiceImpl extends BaseBehaviourBean nodeService.addChild(folder, nodeRef, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, nodeService.getProperty(nodeRef, ContentModel.PROP_NAME).toString())); } } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#moveRecord(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef) + */ + @Override + public void moveRecord(final NodeRef nodeRef, final NodeRef targetNodeRef) + { + ParameterCheck.mandatory("nodeRef", nodeRef); + ParameterCheck.mandatory("targetNodeRef", targetNodeRef); + + NodeRef sourceParentNodeRef = null; + + NodeRef originatingLocation = (NodeRef) nodeService.getProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION); + for (ChildAssociationRef parentAssoc : nodeService.getParentAssocs(nodeRef)) + { + if (!parentAssoc.isPrimary() && parentAssoc.getParentRef().equals(originatingLocation)) + { + sourceParentNodeRef = parentAssoc.getParentRef(); + break; + } + } + + if (sourceParentNodeRef == null) + { + throw new AlfrescoRuntimeException("Could not find source parent node reference."); + } + + SiteInfo sourceSite = siteService.getSite(sourceParentNodeRef); + SiteInfo targetSite = siteService.getSite(targetNodeRef); + + if (!sourceSite.equals(targetSite)) + { + throw new AlfrescoRuntimeException("The record can only be moved within the same collaboration site."); + } + + if (!sourceSite.getSitePreset().equals("site-dashboard")) + { + throw new AlfrescoRuntimeException("Only records within a collaboration site can be moved."); + } + + final NodeRef source = sourceParentNodeRef; + + AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public Void doWork() + { + try + { + // Move the record + fileFolderService.moveFrom(nodeRef, source, targetNodeRef, null); + + // Update the originating location property + nodeService.setProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION, targetNodeRef); + } + catch (FileExistsException | FileNotFoundException ex) + { + throw new AlfrescoRuntimeException("Can't move node: " + ex); + } + + return null; + } + }); + } } diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/HideRecordActionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/HideRecordActionTest.java index db2d00e3d4..8660f761b5 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/HideRecordActionTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/HideRecordActionTest.java @@ -21,9 +21,7 @@ package org.alfresco.module.org_alfresco_module_rm.test.legacy.action; import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction; import org.alfresco.module.org_alfresco_module_rm.action.dm.HideRecordAction; -import org.alfresco.module.org_alfresco_module_rm.role.Role; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; -import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.repository.NodeRef; @@ -49,19 +47,6 @@ public class HideRecordActionTest extends BaseRMTestCase public void testHideRecordAction() { - doTestInTransaction(new Test() - { - public Void run() - { - // The user must have the appropriate rights - Role role = filePlanRoleService.getRole(filePlan, "RecordsManager"); - authorityService.addAuthority(role.getRoleGroupName(), dmCollaborator); - - return null; - } - }, - AuthenticationUtil.getAdminUserName()); - doTestInTransaction(new Test() { public Void run() diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/MoveRecordActionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/MoveRecordActionTest.java new file mode 100644 index 0000000000..71c7a50c81 --- /dev/null +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/MoveRecordActionTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * 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 . + */ +package org.alfresco.module.org_alfresco_module_rm.test.legacy.action; + +import org.alfresco.model.ContentModel; +import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction; +import org.alfresco.module.org_alfresco_module_rm.action.dm.MoveDmRecordAction; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * Move Record Action Unit Test. + * + * @author Tuna Aksoy + * @since 2.2 + */ +public class MoveRecordActionTest extends BaseRMTestCase +{ + @Override + protected boolean isUserTest() + { + return true; + } + + @Override + protected boolean isCollaborationSiteTest() + { + return true; + } + + public void testMoveRecordAction() + { + doTestInTransaction(new Test() + { + public Void run() + { + // Create a new folder in a collaboration site + NodeRef testFolder = fileFolderService.create(dmFolder, "myTestFolder", ContentModel.TYPE_FOLDER).getNodeRef(); + + // Create a document so that the user has the write permissions for that document + NodeRef document = fileFolderService.create(testFolder, "moveFile.txt", ContentModel.TYPE_CONTENT).getNodeRef(); + + // Create destination folder + String destination = fileFolderService.create(testFolder, "newDest", ContentModel.TYPE_FOLDER).getNodeRef().toString(); + + // Create a record from that document + Action createAction = actionService.createAction(CreateRecordAction.NAME); + createAction.setParameterValue(CreateRecordAction.PARAM_FILE_PLAN, filePlan); + actionService.executeAction(createAction, document); + + // Check if the document is a record now + assertTrue(recordService.isRecord(document)); + + // The record should have the original location information + assertNotNull(nodeService.getProperty(document, PROP_RECORD_ORIGINATING_LOCATION)); + + // Check the parents. In this case the document should have two parents (doclib and fileplan) + assertEquals(nodeService.getParentAssocs(document).size(), 2); + + // Check the number of children of dmFolder before move + assertEquals(nodeService.getChildAssocs(testFolder).size(), 2); + + // Move the record + Action moveRecordAction = actionService.createAction(MoveDmRecordAction.NAME); + moveRecordAction.setParameterValue(MoveDmRecordAction.PARAM_TARGET_NODE_REF, destination); + actionService.executeAction(moveRecordAction, document); + + // Check the number of children of dmFolder after move + assertEquals(nodeService.getChildAssocs(testFolder).size(), 1); + + // Check the new document parent + ChildAssociationRef parent1 = nodeService.getParentAssocs(document).get(0); + ChildAssociationRef parent2 = nodeService.getParentAssocs(document).get(1); + NodeRef newDocParent = (parent1.isPrimary() ? parent2 : parent1).getParentRef(); + assertEquals(destination, newDocParent.toString()); + + // Check if the original location information has been updated + assertEquals((NodeRef) nodeService.getProperty(document, PROP_RECORD_ORIGINATING_LOCATION), newDocParent); + + return null; + } + }, + dmCollaborator); + } +} diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java index 38ba4304e0..1683e05449 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java @@ -723,7 +723,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase { // create collaboration site collabSiteId = GUID.generate(); - collaborationSite = siteService.createSite("preset", collabSiteId, "title", "description", SiteVisibility.PRIVATE); + collaborationSite = siteService.createSite("site-dashboard", collabSiteId, "title", "description", SiteVisibility.PRIVATE); documentLibrary = SiteServiceImpl.getSiteContainer( collabSiteId, SiteService.DOCUMENT_LIBRARY, @@ -818,7 +818,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase protected abstract class BehaviourDrivenTest { protected boolean runInTransactionTests = true; - + protected Class expectedException; public BehaviourDrivenTest() @@ -829,7 +829,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase { this.expectedException = expectedException; } - + public BehaviourDrivenTest(boolean runInTransactionTests) { this.runInTransactionTests = runInTransactionTests; @@ -875,7 +875,7 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase when(); } }); - + doTestInTransaction(new VoidTest() { @Override