Move, copy, link issues

* RM-912: Copy to, Link to and Delete actions are available for cutoff folders/records but not working
  * RM-1286: Strange behavior of copied cutoff record
  * Relates to RM-1342
  * create RM version of copy/move/link webscripts so that error reporting to client could be improved (now reasons for failure are reported)
  * add model behaviours for aspects that shouldn't be copied



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@67548 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2014-04-16 06:02:40 +00:00
parent dc99973c0e
commit 82a39c2563
18 changed files with 636 additions and 3 deletions

View File

@@ -26,6 +26,11 @@ log4j.logger.org.alfresco.module.org_alfresco_module_rm.patch=info
#
#log4j.logger.org.alfresco.module.org_alfresco_module_rm.job=debug
#
# Script logging level
#
log4j.logger.org.alfresco.repo.jscript.ScriptLogger=error
#
# Behaviour debug
#

View File

@@ -138,6 +138,21 @@
<property name="extendedSecurityService" ref="ExtendedSecurityService"/>
</bean>
<bean id="rma.cutOff" class="org.alfresco.module.org_alfresco_module_rm.model.rma.aspect.CutoffAspect" parent="rm.baseBehaviour">
</bean>
<bean id="rma.accended" class="org.alfresco.module.org_alfresco_module_rm.model.rma.aspect.AccendedAspect" parent="rm.baseBehaviour">
</bean>
<bean id="rma.transferred" class="org.alfresco.module.org_alfresco_module_rm.model.rma.aspect.TransferredAspect" parent="rm.baseBehaviour">
</bean>
<bean id="rma.transferring" class="org.alfresco.module.org_alfresco_module_rm.model.rma.aspect.TransferringAspect" parent="rm.baseBehaviour">
</bean>
<bean id="rma.declaredRecord" class="org.alfresco.module.org_alfresco_module_rm.model.rma.aspect.DeclaredRecordAspect" parent="rm.baseBehaviour">
</bean>
<!-- Base bean definition for customisable types bootstrap -->
<bean id="customisableTypesBootstrap"
abstract="true"

View File

@@ -0,0 +1,13 @@
<webscript>
<shortname>rm-copy-to</shortname>
<description>Document List Action - Copy multiple files</description>
<url>/slingshot/doclib/action/rm-copy-to/site/{site}/{container}/{path}</url>
<url>/slingshot/doclib/action/rm-copy-to/site/{site}/{container}</url>
<url>/slingshot/doclib/action/rm-copy-to/node/{store_type}/{store_id}/{id}/{path}</url>
<url>/slingshot/doclib/action/rm-copy-to/node/{store_type}/{store_id}/{id}</url>
<url>/slingshot/doclib/action/rm-copy-to/node/{store_type}/{store_id}</url>
<format default="json">argument</format>
<authentication>user</authentication>
<transaction>required</transaction>
<lifecycle>internal</lifecycle>
</webscript>

View File

@@ -0,0 +1,2 @@
<#import "action.lib.ftl" as actionLib />
<@actionLib.resultsJSON results=results />

View File

@@ -0,0 +1,100 @@
<import resource="classpath:/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/action/action.lib.js">
/**
* Copy multiple files action
* @method POST
*/
/**
* Entrypoint required by action.lib.js
*
* @method runAction
* @param p_params {object} Object literal containing files array
* @return {object|null} object representation of action results
*/
function runAction(p_params)
{
var results = [],
destNode = p_params.destNode,
files = p_params.files,
file, fileNode, result, nodeRef,
fromSite, copiedNode;
// Must have array of files
if (!files || files.length == 0)
{
status.setCode(status.STATUS_BAD_REQUEST, "No files.");
return;
}
for (file in files)
{
nodeRef = files[file];
result =
{
nodeRef: nodeRef,
action: "copyFile",
success: false
};
try
{
fileNode = search.findNode(nodeRef);
if (fileNode == null)
{
result.id = file;
result.nodeRef = nodeRef;
result.success = false;
result.error = "Can't find source node.";
}
else
{
result.id = fileNode.name;
result.name = fileNode.name;
result.type = fileNode.isContainer ? "folder" : "document"
// Retain the name of the site the node is currently in. Null if it's not in a site.
fromSite = String(fileNode.siteShortName);
// copy the node (deep copy for containers)
if (fileNode.isContainer)
{
copiedNode = fileNode.copy(destNode, true);
}
else
{
copiedNode = fileNode.copy(destNode);
}
result.nodeRef = copiedNode.nodeRef.toString();
result.success = (result.nodeRef != null);
if (result.success)
{
// If this was an inter-site copy, we'll need to clean up the permissions on the node
if (fromSite != String(copiedNode.siteShortName))
{
siteService.cleanSitePermissions(copiedNode);
}
}
}
}
catch (e)
{
result.id = file;
result.nodeRef = nodeRef;
result.success = false;
result.error = e.message;
// log the error
logger.error(e.message);
}
results.push(result);
}
return results;
}
/* Bootstrap action script */
main();

View File

@@ -0,0 +1,12 @@
<webscript>
<shortname>rm-link</shortname>
<description>Document List Action - Link records</description>
<url>/slingshot/doclib/action/rm-link/site/{site}/{container}/{path}</url>
<url>/slingshot/doclib/action/rm-link/site/{site}/{container}</url>
<url>/slingshot/doclib/action/rm-link/node/{store_type}/{store_id}/{id}/{path}</url>
<url>/slingshot/doclib/action/rm-link/node/{store_type}/{store_id}/{id}</url>
<format default="json">argument</format>
<authentication>user</authentication>
<transaction>required</transaction>
<lifecycle>internal</lifecycle>
</webscript>

View File

@@ -0,0 +1,2 @@
<#import "action.lib.ftl" as actionLib />
<@actionLib.resultsJSON results=results />

View File

@@ -0,0 +1,75 @@
<import resource="classpath:/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/action/action.lib.js">
/**
* Add multiple files as children action
* @method POST
*/
/**
* Entrypoint required by action.lib.js
*
* @method runAction
* @param p_params {object} Object literal containing files array
* @return {object|null} object representation of action results
*/
function runAction(p_params)
{
var results = [],
destNode = p_params.destNode,
files = p_params.files,
file, fileNode, result, nodeRef;
// Must have array of files
if (!files || files.length == 0)
{
status.setCode(status.STATUS_BAD_REQUEST, "No files.");
return;
}
for (file in files)
{
nodeRef = files[file];
result =
{
nodeRef: nodeRef,
action: "addChild",
success: false
}
try
{
fileNode = search.findNode(nodeRef);
if (fileNode === null)
{
result.id = file;
result.nodeRef = nodeRef;
result.success = false;
}
else
{
result.id = fileNode.name;
result.name = fileNode.name;
result.type = fileNode.isContainer ? "folder" : "document";
destNode.addNode(fileNode);
result.success = true;
}
}
catch (e)
{
result.id = file;
result.nodeRef = nodeRef;
result.success = false;
result.error = e.message;
// log the error
logger.error(e.message);
}
results.push(result);
}
return results;
}
/* Bootstrap action script */
main();

View File

@@ -0,0 +1,12 @@
<webscript>
<shortname>rm-move-to</shortname>
<description>Document List Action - Move multiple files</description>
<url>/slingshot/doclib/action/rm-move-to/site/{site}/{container}/{path}</url>
<url>/slingshot/doclib/action/rm-move-to/site/{site}/{container}</url>
<url>/slingshot/doclib/action/rm-move-to/node/{store_type}/{store_id}/{id}/{path}</url>
<url>/slingshot/doclib/action/rm-move-to/node/{store_type}/{store_id}/{id}</url>
<format default="json">argument</format>
<authentication>user</authentication>
<transaction>required</transaction>
<lifecycle>internal</lifecycle>
</webscript>

View File

@@ -0,0 +1,2 @@
<#import "action.lib.ftl" as actionLib />
<@actionLib.resultsJSON results=results />

View File

@@ -0,0 +1,94 @@
<import resource="classpath:/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/action/action.lib.js">
/**
* Move multiple files action
* @method POST
*/
/**
* Entrypoint required by action.lib.js
*
* @method runAction
* @param p_params {object} Object literal containing files array
* @return {object|null} object representation of action results
*/
function runAction(p_params)
{
var results = [],
destNode = p_params.destNode,
files = p_params.files,
parent = null,
file, fileNode, result, nodeRef,
fromSite;
// Must have array of files
if (!files || files.length == 0)
{
status.setCode(status.STATUS_BAD_REQUEST, "No files.");
return;
}
for (file in files)
{
nodeRef = files[file];
result =
{
nodeRef: nodeRef,
action: "moveFile",
success: false
}
try
{
fileNode = search.findNode(nodeRef);
if (fileNode == null)
{
result.id = file;
result.nodeRef = nodeRef;
result.success = false;
}
else
{
if (p_params.parent && p_params.parent != null)
{
parent = search.findNode(p_params.parent);
}
result.id = fileNode.name;
result.name = fileNode.name;
result.type = fileNode.isContainer ? "folder" : "document";
// Retain the name of the site the node is currently in. Null if it's not in a site.
fromSite = fileNode.siteShortName;
// move the node
result.success = fileNode.move(parent, destNode);
if (result.success)
{
// If this was an inter-site move, we'll need to clean up the permissions on the node
if (String(fromSite) !== String(fileNode.siteShortName))
{
siteService.cleanSitePermissions(fileNode);
}
}
}
}
catch (e)
{
result.id = file;
result.nodeRef = nodeRef;
result.success = false;
result.error = e.message;
// log the error
logger.error(e.message);
}
results.push(result);
}
return results;
}
/* Bootstrap action script */
main();

View File

@@ -0,0 +1,56 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect;
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
import org.alfresco.repo.copy.CopyBehaviourCallback;
import org.alfresco.repo.copy.CopyDetails;
import org.alfresco.repo.copy.DoNothingCopyBehaviourCallback;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.service.namespace.QName;
/**
* rma:ascended behaviour bean
*
* @author Roy Wetherall
* @since 2.2
*/
@BehaviourBean
(
defaultType = "rma:ascended"
)
public class AccendedAspect extends BaseBehaviourBean
{
/**
* Copy callback.
*
* Aspect should not be copied.
*/
@Behaviour
(
kind = BehaviourKind.CLASS,
policy = "alf:getCopyCallback"
)
public CopyBehaviourCallback getCopyCallback(QName classRef, CopyDetails copyDetails)
{
return new DoNothingCopyBehaviourCallback();
}
}

View File

@@ -0,0 +1,56 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect;
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
import org.alfresco.repo.copy.CopyBehaviourCallback;
import org.alfresco.repo.copy.CopyDetails;
import org.alfresco.repo.copy.DoNothingCopyBehaviourCallback;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.service.namespace.QName;
/**
* rma:cutoff behaviour bean
*
* @author Roy Wetherall
* @since 2.2
*/
@BehaviourBean
(
defaultType = "rma:cutOff"
)
public class CutoffAspect extends BaseBehaviourBean
{
/**
* Copy callback.
*
* Cutoff aspect should not be copied.
*/
@Behaviour
(
kind = BehaviourKind.CLASS,
policy = "alf:getCopyCallback"
)
public CopyBehaviourCallback getCopyCallback(QName classRef, CopyDetails copyDetails)
{
return new DoNothingCopyBehaviourCallback();
}
}

View File

@@ -0,0 +1,56 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect;
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
import org.alfresco.repo.copy.CopyBehaviourCallback;
import org.alfresco.repo.copy.CopyDetails;
import org.alfresco.repo.copy.DoNothingCopyBehaviourCallback;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.service.namespace.QName;
/**
* rma:declaredRecord behaviour bean
*
* @author Roy Wetherall
* @since 2.2
*/
@BehaviourBean
(
defaultType = "rma:declaredRecord"
)
public class DeclaredRecordAspect extends BaseBehaviourBean
{
/**
* Copy callback.
*
* Aspect should not be copied.
*/
@Behaviour
(
kind = BehaviourKind.CLASS,
policy = "alf:getCopyCallback"
)
public CopyBehaviourCallback getCopyCallback(QName classRef, CopyDetails copyDetails)
{
return new DoNothingCopyBehaviourCallback();
}
}

View File

@@ -22,6 +22,9 @@ import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
import org.alfresco.repo.copy.CopyBehaviourCallback;
import org.alfresco.repo.copy.CopyDetails;
import org.alfresco.repo.copy.DoNothingCopyBehaviourCallback;
import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.annotation.Behaviour;
@@ -31,6 +34,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
* rma:extendedSecurity behaviour bean
@@ -56,6 +60,21 @@ public class ExtendedSecurityAspect extends BaseBehaviourBean
this.extendedSecurityService = extendedSecurityService;
}
/**
* Copy callback.
*
* Aspect should not be copied.
*/
@Behaviour
(
kind = BehaviourKind.CLASS,
policy = "alf:getCopyCallback"
)
public CopyBehaviourCallback getCopyCallback(QName classRef, CopyDetails copyDetails)
{
return new DoNothingCopyBehaviourCallback();
}
/**
* Update extended security when moving a node.
*
@@ -64,8 +83,8 @@ public class ExtendedSecurityAspect extends BaseBehaviourBean
@Override
@Behaviour
(
kind = BehaviourKind.CLASS,
notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT
kind = BehaviourKind.CLASS,
notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT
)
public void onMoveNode(final ChildAssociationRef origAssoc, final ChildAssociationRef newAssoc)
{
@@ -89,4 +108,6 @@ public class ExtendedSecurityAspect extends BaseBehaviourBean
});
}
}

View File

@@ -0,0 +1,56 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect;
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
import org.alfresco.repo.copy.CopyBehaviourCallback;
import org.alfresco.repo.copy.CopyDetails;
import org.alfresco.repo.copy.DoNothingCopyBehaviourCallback;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.service.namespace.QName;
/**
* rma:transferred behaviour bean
*
* @author Roy Wetherall
* @since 2.2
*/
@BehaviourBean
(
defaultType = "rma:transferred"
)
public class TransferredAspect extends BaseBehaviourBean
{
/**
* Copy callback.
*
* Aspect should not be copied.
*/
@Behaviour
(
kind = BehaviourKind.CLASS,
policy = "alf:getCopyCallback"
)
public CopyBehaviourCallback getCopyCallback(QName classRef, CopyDetails copyDetails)
{
return new DoNothingCopyBehaviourCallback();
}
}

View File

@@ -0,0 +1,56 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect;
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
import org.alfresco.repo.copy.CopyBehaviourCallback;
import org.alfresco.repo.copy.CopyDetails;
import org.alfresco.repo.copy.DoNothingCopyBehaviourCallback;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.service.namespace.QName;
/**
* rma:transferring behaviour bean
*
* @author Roy Wetherall
* @since 2.2
*/
@BehaviourBean
(
defaultType = "rma:transferring"
)
public class TransferringAspect extends BaseBehaviourBean
{
/**
* Copy callback.
*
* Aspect should not be copied.
*/
@Behaviour
(
kind = BehaviourKind.CLASS,
policy = "alf:getCopyCallback"
)
public CopyBehaviourCallback getCopyCallback(QName classRef, CopyDetails copyDetails)
{
return new DoNothingCopyBehaviourCallback();
}
}

View File

@@ -288,7 +288,7 @@ public class ModelSecurityServiceImpl extends BaseBehaviourBean
throw new ModelAccessDeniedException(
"The user " + AuthenticationUtil.getFullyAuthenticatedUser() +
" does not have the permission to add the protected aspect " + aspect.toPrefixString(namespaceService) +
" from the node " + nodeRef.toString());
" to the node " + nodeRef.toString());
}
}