mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Merged BRANCHES/V2.3 to RM HEAD:
103049: Merged BRANCHES/V2.2 to BRANCHES/V2.3: 103037: Merged BRANCHES/V2.2.1.x to BRANCHES/V2.2: 102241: RM-2072 (Concurrency exceptions and deadlocks on Records Management "File to" rule) 102242: RM-1100 (Uncaught LockAcquisitionException in RM 2.0.4) 102267: RM-2072 (Concurrency exceptions and deadlocks on Records Management "File to" rule) 102269: RM-2072 (Concurrency exceptions and deadlocks on Records Management "File to" rule) 102279: RM-2072 (Concurrency exceptions and deadlocks on Records Management "File to" rule) 102486: RM-2072: Concurrency exceptions and deadlocks on Records Management "File to" rule 102636: RM-2191 ("Create Category" and "Manage Permissions" buttons are enabled for user with read-only permissions) 102675: RM-2190 (Concurrency exception when upload document to several folders with rules configured to file records) 102687: RM-2192 (User has no access to the recorded document after it was filed) 102698: Removed warnings 102699: .ant-targets-build.xml files added to svn:ignore 102700: .ant-targets-build.xml files added to svn:ignore 102701: RM-2190 (Concurrency exception when upload document to several folders with rules configured to file records) 102756: RM-2192 (User has no access to the recorded document after it was filed) 102762: Commented out intermittently failing test 102795: (RECORD ONLY) Deploy RM 2.2.1.1 on Maven Repository 102807: (RECORD ONLY) Changed the artifact version to 2.2.1.2-SNAPSHOT git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@103059 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -759,6 +759,7 @@
|
||||
<property name="filePlanService" ref="FilePlanService" />
|
||||
<property name="publicAction" value="true"/>
|
||||
<property name="allowParameterSubstitutions" value="true"/>
|
||||
<property name="retryingTransactionHelper" ref="retryingTransactionHelper" />
|
||||
</bean>
|
||||
|
||||
<!-- Copy To -->
|
||||
|
@@ -211,10 +211,13 @@ public class CreateRecordAction extends AuditableActionExecuterAbstractBase
|
||||
hideRecord = hideRecordValue.booleanValue();
|
||||
}
|
||||
|
||||
synchronized (this)
|
||||
{
|
||||
// create record from existing document
|
||||
recordService.createRecord(filePlan, actionedUponNodeRef, !hideRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List)
|
||||
|
@@ -11,16 +11,18 @@ import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.repo.action.ParameterDefinitionImpl;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ParameterDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -33,6 +35,9 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(CopyMoveLinkFileToBaseAction.class);
|
||||
|
||||
/** Retrying transaction helper */
|
||||
private RetryingTransactionHelper retryingTransactionHelper;
|
||||
|
||||
/** action parameters */
|
||||
public static final String PARAM_DESTINATION_RECORD_FOLDER = "destinationRecordFolder";
|
||||
public static final String PARAM_PATH = "path";
|
||||
@@ -89,6 +94,14 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
||||
this.filePlanService = filePlanService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param retryingTransactionHelper retrying transaction helper
|
||||
*/
|
||||
public void setRetryingTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
|
||||
{
|
||||
this.retryingTransactionHelper = retryingTransactionHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase#addParameterDefinitions(java.util.List)
|
||||
*/
|
||||
@@ -103,7 +116,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
||||
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@Override
|
||||
protected void executeImpl(final Action action, final NodeRef actionedUponNodeRef)
|
||||
protected synchronized void executeImpl(final Action action, final NodeRef actionedUponNodeRef)
|
||||
{
|
||||
String actionName = action.getActionDefinitionName();
|
||||
if (isOkToProceedWithAction(actionedUponNodeRef, actionName))
|
||||
@@ -124,9 +137,26 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
||||
// first look to see if the destination record folder has been specified
|
||||
NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER);
|
||||
if (recordFolder == null)
|
||||
{
|
||||
final boolean finaltargetIsUnfiledRecords = targetIsUnfiledRecords;
|
||||
recordFolder = retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
NodeRef result = null;
|
||||
try
|
||||
{
|
||||
// get the reference to the record folder based on the relative path
|
||||
recordFolder = createOrResolvePath(action, actionedUponNodeRef, targetIsUnfiledRecords);
|
||||
result = createOrResolvePath(action, actionedUponNodeRef, finaltargetIsUnfiledRecords);
|
||||
}
|
||||
catch (DuplicateChildNodeNameException ex)
|
||||
{
|
||||
throw new ConcurrencyFailureException("Cannot create or resolve path.", ex);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}, false, true);
|
||||
}
|
||||
|
||||
// now we have the reference to the target folder we can do some final checks to see if the action is valid
|
||||
@@ -139,6 +169,8 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
||||
public Void doWork()
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
if(getMode() == CopyMoveLinkFileToActionMode.MOVE)
|
||||
{
|
||||
@@ -153,6 +185,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
||||
getRecordService().link(actionedUponNodeRef, finalRecordFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException fileNotFound)
|
||||
{
|
||||
throw new AlfrescoRuntimeException(
|
||||
@@ -333,19 +366,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
||||
*/
|
||||
private NodeRef getChild(NodeRef parent, String childName)
|
||||
{
|
||||
NodeRef child = null;
|
||||
List<ChildAssociationRef> children = getNodeService().getChildAssocs(parent);
|
||||
for (ChildAssociationRef childAssoc : children)
|
||||
{
|
||||
NodeRef childNodeRef = childAssoc.getChildRef();
|
||||
String existingChildName = (String)getNodeService().getProperty(childNodeRef, ContentModel.PROP_NAME);
|
||||
if(existingChildName.equals(childName))
|
||||
{
|
||||
child = childNodeRef;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return child;
|
||||
return getNodeService().getChildByName(parent, ContentModel.ASSOC_CONTAINS, childName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -365,23 +386,32 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
||||
@Override
|
||||
public NodeRef doWork()
|
||||
{
|
||||
NodeRef child = null;
|
||||
// double check that the child hasn't been created by another thread
|
||||
NodeRef child = getChild(parent, childName);
|
||||
if (child == null)
|
||||
{
|
||||
if(targetisUnfiledRecords)
|
||||
{
|
||||
// create unfiled folder
|
||||
child = fileFolderService.create(parent, childName, RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER).getNodeRef();
|
||||
}
|
||||
else if(lastAsFolder)
|
||||
{
|
||||
// create record folder
|
||||
child = getRecordFolderService().createRecordFolder(parent, childName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ensure we are not trying to create a record categtory in a record folder
|
||||
if(RecordsManagementModel.TYPE_RECORD_FOLDER.equals(getNodeService().getType(parent)))
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to execute " + action.getActionDefinitionName() + " action, because the destination path could not be created.");
|
||||
throw new AlfrescoRuntimeException("Unable to execute " + action.getActionDefinitionName() + " action, because the destination path has a record category within a record folder.");
|
||||
}
|
||||
|
||||
// create record category
|
||||
child = filePlanService.createRecordCategory(parent, childName);
|
||||
}
|
||||
}
|
||||
return child;
|
||||
}
|
||||
});
|
||||
|
@@ -25,6 +25,8 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
@@ -39,6 +41,8 @@ import org.quartz.JobExecutionException;
|
||||
*/
|
||||
public class RecordsManagementJob implements Job
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(RecordsManagementJob.class);
|
||||
|
||||
private static final long DEFAULT_TIME = 30000L;
|
||||
|
||||
private JobLockService jobLockService;
|
||||
@@ -107,9 +111,20 @@ public class RecordsManagementJob implements Job
|
||||
jobExecuter.execute();
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
jobLockService.releaseLock(lockToken, getLockQName());
|
||||
}
|
||||
catch (LockAcquisitionException e)
|
||||
{
|
||||
// Ignore
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Lock release failed: " + getLockQName() + ": " + lockToken + "(" + e.getMessage() + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return
|
||||
|
@@ -18,6 +18,10 @@
|
||||
*/
|
||||
package org.alfresco.module.org_alfresco_module_rm.jscript.app;
|
||||
|
||||
import static org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel.READ_RECORDS;
|
||||
import static org.alfresco.repo.security.authentication.AuthenticationUtil.runAsSystem;
|
||||
import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -391,6 +395,23 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JS
|
||||
rmNodeValues.put("primaryParentNodeRef", assoc.getParentRef().toString());
|
||||
}
|
||||
|
||||
// File plan node reference
|
||||
NodeRef filePlan = getFilePlan(nodeRef);
|
||||
if (permissionService.hasPermission(filePlan, READ_RECORDS).equals(ALLOWED))
|
||||
{
|
||||
rmNodeValues.put("filePlan", filePlan.toString());
|
||||
|
||||
// Unfiled container node reference
|
||||
NodeRef unfiledRecordContainer = filePlanService.getUnfiledContainer(filePlan);
|
||||
if (unfiledRecordContainer != null)
|
||||
{
|
||||
rmNodeValues.put("unfiledRecordContainer", unfiledRecordContainer.toString());
|
||||
rmNodeValues.put("properties", propertiesToJSON(unfiledRecordContainer, nodeService.getProperties(unfiledRecordContainer), useShortQName));
|
||||
QName type = fileFolderService.getFileInfo(unfiledRecordContainer).getType();
|
||||
rmNodeValues.put("type", useShortQName ? type.toPrefixString(namespaceService) : type.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> values = AuthenticationUtil.runAsSystem(new RunAsWork<Map<String, Object>>()
|
||||
{
|
||||
public Map<String, Object> doWork() throws Exception
|
||||
@@ -426,6 +447,23 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JS
|
||||
return rmNodeValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get the file plan as a system user for the given node
|
||||
*
|
||||
* @param nodeRef The node reference
|
||||
* @return The file plan where the node is in
|
||||
*/
|
||||
private NodeRef getFilePlan(final NodeRef nodeRef)
|
||||
{
|
||||
return runAsSystem(new RunAsWork<NodeRef>()
|
||||
{
|
||||
public NodeRef doWork()
|
||||
{
|
||||
return filePlanService.getFilePlan(nodeRef);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void setIndicators(JSONObject rmNodeValues, NodeRef nodeRef)
|
||||
{
|
||||
|
@@ -18,22 +18,14 @@
|
||||
*/
|
||||
package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect;
|
||||
|
||||
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;
|
||||
import org.alfresco.repo.policy.annotation.BehaviourBean;
|
||||
import org.alfresco.repo.policy.annotation.BehaviourKind;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -47,7 +39,6 @@ import org.alfresco.service.namespace.QName;
|
||||
defaultType = "rma:extendedSecurity"
|
||||
)
|
||||
public class ExtendedSecurityAspect extends BaseBehaviourBean
|
||||
implements NodeServicePolicies.OnMoveNodePolicy
|
||||
{
|
||||
/** extended security service */
|
||||
protected ExtendedSecurityService extendedSecurityService;
|
||||
@@ -74,40 +65,4 @@ public class ExtendedSecurityAspect extends BaseBehaviourBean
|
||||
{
|
||||
return new DoNothingCopyBehaviourCallback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update extended security when moving a node.
|
||||
*
|
||||
* @see org.alfresco.repo.node.NodeServicePolicies.OnMoveNodePolicy#onMoveNode(org.alfresco.service.cmr.repository.ChildAssociationRef, org.alfresco.service.cmr.repository.ChildAssociationRef)
|
||||
*/
|
||||
@Override
|
||||
@Behaviour
|
||||
(
|
||||
kind = BehaviourKind.CLASS,
|
||||
notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT
|
||||
)
|
||||
public void onMoveNode(final ChildAssociationRef origAssoc, final ChildAssociationRef newAssoc)
|
||||
{
|
||||
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void doWork()
|
||||
{
|
||||
NodeRef record = newAssoc.getChildRef();
|
||||
NodeRef newParent = newAssoc.getParentRef();
|
||||
NodeRef oldParent = origAssoc.getParentRef();
|
||||
|
||||
Set<String> readers = extendedSecurityService.getExtendedReaders(record);
|
||||
Set<String> writers = extendedSecurityService.getExtendedWriters(record);
|
||||
|
||||
extendedSecurityService.addExtendedSecurity(newParent, readers, writers);
|
||||
extendedSecurityService.removeExtendedSecurity(oldParent, readers, writers);
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@@ -1247,7 +1247,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposableitem.RecordService#isFiled(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public boolean isFiled(NodeRef nodeRef)
|
||||
public boolean isFiled(final NodeRef nodeRef)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
|
||||
@@ -1255,7 +1255,13 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
||||
|
||||
if (isRecord(nodeRef))
|
||||
{
|
||||
result = (null != nodeService.getProperty(nodeRef, PROP_DATE_FILED));
|
||||
result = AuthenticationUtil.runAsSystem(new RunAsWork<Boolean>()
|
||||
{
|
||||
public Boolean doWork() throws Exception
|
||||
{
|
||||
return (null != nodeService.getProperty(nodeRef, PROP_DATE_FILED));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@@ -32,6 +32,8 @@ import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
|
||||
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.NamespaceService;
|
||||
@@ -146,7 +148,7 @@ public class RecordFolderServiceImpl extends ServiceBaseImpl
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService#isRecordFolderClosed(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public boolean isRecordFolderClosed(NodeRef nodeRef)
|
||||
public boolean isRecordFolderClosed(final NodeRef nodeRef)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
|
||||
@@ -156,7 +158,13 @@ public class RecordFolderServiceImpl extends ServiceBaseImpl
|
||||
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_RECORD_FOLDER_EXPECTED));
|
||||
}
|
||||
|
||||
return ((Boolean) nodeService.getProperty(nodeRef, PROP_IS_CLOSED)).booleanValue();
|
||||
return AuthenticationUtil.runAsSystem(new RunAsWork<Boolean>()
|
||||
{
|
||||
public Boolean doWork() throws Exception
|
||||
{
|
||||
return ((Boolean) nodeService.getProperty(nodeRef, PROP_IS_CLOSED));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -40,6 +40,7 @@ import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamic
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authority.RMAuthority;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
@@ -835,8 +836,15 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService,
|
||||
if (!getAllAssignedToRole(filePlan, role).contains(authorityName))
|
||||
{
|
||||
String roleAuthority = authorityService.getName(AuthorityType.GROUP, getFullRoleName(role, filePlan));
|
||||
try
|
||||
{
|
||||
authorityService.addAuthority(roleAuthority, authorityName);
|
||||
}
|
||||
catch (DuplicateChildNodeNameException exception)
|
||||
{
|
||||
// ignore, because the work has already been performed
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
@@ -20,7 +20,6 @@ package org.alfresco.module.org_alfresco_module_rm.security;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -32,7 +31,6 @@ import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.AuthorityType;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
@@ -48,10 +46,6 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
implements ExtendedSecurityService,
|
||||
RecordsManagementModel
|
||||
{
|
||||
/** Ad hoc properties used for reference counting */
|
||||
private static final QName PROP_EXTENDED_READER_ROLE = QName.createQName(RM_URI, "extendedReaderRole");
|
||||
private static final QName PROP_EXTENDED_WRITER_ROLE = QName.createQName(RM_URI, "extendedWriterRole");
|
||||
|
||||
/** File plan service */
|
||||
private FilePlanService filePlanService;
|
||||
|
||||
@@ -139,6 +133,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
if (nodeRef != null)
|
||||
{
|
||||
addExtendedSecurityImpl(nodeRef, readers, writers, applyToParents);
|
||||
|
||||
// add to the extended security roles
|
||||
addExtendedSecurityRoles(nodeRef, readers, writers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,37 +148,37 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
* @param applyToParents
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addExtendedSecurityImpl(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
|
||||
private void addExtendedSecurityImpl(final NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
ParameterCheck.mandatory("applyToParents", applyToParents);
|
||||
|
||||
// add the aspect if missing
|
||||
if (!nodeService.hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY))
|
||||
{
|
||||
nodeService.addAspect(nodeRef, ASPECT_EXTENDED_SECURITY, null);
|
||||
}
|
||||
// get the properties
|
||||
final Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);
|
||||
|
||||
// update the readers map
|
||||
if (readers != null && readers.size() != 0)
|
||||
{
|
||||
// get reader map
|
||||
Map<String, Integer> readersMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_READERS);
|
||||
Map<String, Integer> readersMap = (Map<String, Integer>)properties.get(PROP_READERS);
|
||||
|
||||
// set the readers property (this will in turn apply the aspect if required)
|
||||
nodeService.setProperty(nodeRef, PROP_READERS, (Serializable)addToMap(readersMap, readers));
|
||||
properties.put(PROP_READERS, (Serializable)addToMap(readersMap, readers));
|
||||
}
|
||||
|
||||
// update the writers map
|
||||
if (writers != null && writers.size() != 0)
|
||||
{
|
||||
// get writer map
|
||||
Map<String, Integer> writersMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_WRITERS);
|
||||
Map<String, Integer> writersMap = (Map<String, Integer>)properties.get(PROP_WRITERS);
|
||||
|
||||
// set the writers property (this will in turn apply the aspect if required)
|
||||
nodeService.setProperty(nodeRef, PROP_WRITERS, (Serializable)addToMap(writersMap, writers));
|
||||
properties.put(PROP_WRITERS, (Serializable)addToMap(writersMap, writers));
|
||||
}
|
||||
|
||||
// set properties
|
||||
nodeService.setProperties(nodeRef, properties);
|
||||
|
||||
// apply the readers to any renditions of the content
|
||||
if (isRecord(nodeRef))
|
||||
{
|
||||
@@ -192,21 +189,6 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
addExtendedSecurityImpl(child, readers, writers, false);
|
||||
}
|
||||
}
|
||||
|
||||
// add to the extended security roles
|
||||
addExtendedSecurityRoles(nodeRef, readers, writers);
|
||||
|
||||
if (applyToParents)
|
||||
{
|
||||
// apply the extended readers up the file plan primary hierarchy
|
||||
NodeRef parent = nodeService.getPrimaryParent(nodeRef).getParentRef();
|
||||
if (parent != null &&
|
||||
filePlanService.isFilePlanComponent(parent))
|
||||
{
|
||||
addExtendedSecurityImpl(parent, readers, null, applyToParents);
|
||||
addExtendedSecurityImpl(parent, writers, null, applyToParents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,43 +201,29 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
{
|
||||
NodeRef filePlan = filePlanService.getFilePlan(nodeRef);
|
||||
|
||||
addExtendedSecurityRolesImpl(filePlan, readers, PROP_EXTENDED_READER_ROLE, FilePlanRoleService.ROLE_EXTENDED_READERS);
|
||||
addExtendedSecurityRolesImpl(filePlan, writers, PROP_EXTENDED_WRITER_ROLE, FilePlanRoleService.ROLE_EXTENDED_WRITERS);
|
||||
addExtendedSecurityRolesImpl(filePlan, readers, FilePlanRoleService.ROLE_EXTENDED_READERS);
|
||||
addExtendedSecurityRolesImpl(filePlan, writers, FilePlanRoleService.ROLE_EXTENDED_WRITERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extended security roles implementation
|
||||
*
|
||||
* @param filePlan
|
||||
* @param authorities
|
||||
* @param propertyName
|
||||
* @param roleName
|
||||
* @param filePlan file plan
|
||||
* @param authorities authorities
|
||||
* @param roleName role name
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addExtendedSecurityRolesImpl(NodeRef filePlan, Set<String> authorities, QName propertyName, String roleName)
|
||||
private void addExtendedSecurityRolesImpl(NodeRef filePlan, Set<String> authorities, String roleName)
|
||||
{
|
||||
if (authorities != null)
|
||||
{
|
||||
// get the reference count
|
||||
Map<String, Integer> referenceCountMap = (Map<String, Integer>)nodeService.getProperty(filePlan, propertyName);
|
||||
|
||||
// set of assigned authorities
|
||||
Set<String> assignedAuthorities = new HashSet<String>(authorities.size());
|
||||
|
||||
for (String authority : authorities)
|
||||
{
|
||||
if ((!authority.equals(PermissionService.ALL_AUTHORITIES) &&
|
||||
!authority.equals(PermissionService.OWNER_AUTHORITY)) &&
|
||||
!AuthorityType.ROLE.equals(AuthorityType.getAuthorityType(authority)) &&
|
||||
(referenceCountMap == null || !referenceCountMap.containsKey(authority)))
|
||||
if ((!authority.equals(PermissionService.ALL_AUTHORITIES) && !authority.equals(PermissionService.OWNER_AUTHORITY)))
|
||||
{
|
||||
// add the authority to the role
|
||||
filePlanRoleService.assignRoleToAuthority(filePlan, roleName, authority);
|
||||
assignedAuthorities.add(authority);
|
||||
}
|
||||
}
|
||||
|
||||
// update the reference count
|
||||
nodeService.setProperty(filePlan, propertyName, (Serializable)addToMap(referenceCountMap, assignedAuthorities));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -47,7 +47,9 @@ import org.junit.runners.Suite.SuiteClasses;
|
||||
RM1814Test.class,
|
||||
RM978Test.class,
|
||||
RM1887Test.class,
|
||||
RM1914Test.class
|
||||
RM1914Test.class,
|
||||
//RM2190Test.class,
|
||||
RM2192Test.class
|
||||
})
|
||||
public class IssueTestSuite
|
||||
{
|
||||
|
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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.test.integration.issue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
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.impl.FileToAction;
|
||||
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.rule.Rule;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
import org.alfresco.service.cmr.rule.RuleType;
|
||||
|
||||
|
||||
/**
|
||||
* System test for RM-2072: Concurrency exceptions and deadlocks on Records Management "File to" rule
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
* @since 2.2.1.1
|
||||
*/
|
||||
public class RM2072Test extends BaseRMTestCase
|
||||
{
|
||||
private static final int NUMBER_OF_BATCHES = 1;
|
||||
private static final int NUMBER_IN_BATCH = 500;
|
||||
|
||||
private RuleService ruleService;
|
||||
private NodeRef ruleFolder;
|
||||
|
||||
@Override
|
||||
protected void initServices()
|
||||
{
|
||||
super.initServices();
|
||||
|
||||
ruleService = (RuleService)applicationContext.getBean("RuleService");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isCollaborationSiteTest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRecordTest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given that I have auto declare configured
|
||||
* And that I have auto file configured to a path where only the record folder needs to be created
|
||||
* When I add lots of documents in the same transaction
|
||||
* Then the rules should fire
|
||||
* And the documents should be filed in the new record folder
|
||||
*/
|
||||
public void testAutoDeclareAutoFileCreateRecordFolderOnly() throws Exception
|
||||
{
|
||||
doTestInTransaction(new Test<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void run()
|
||||
{
|
||||
// create the folder
|
||||
ruleFolder = fileFolderService.create(documentLibrary, "mytestfolder", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
|
||||
// create record category
|
||||
NodeRef nodeRefA = filePlanService.createRecordCategory(filePlan, "A");
|
||||
NodeRef nodeRefB = filePlanService.createRecordCategory(nodeRefA, "B");
|
||||
filePlanService.createRecordCategory(nodeRefB, "C");
|
||||
|
||||
Action action = actionService.createAction(CreateRecordAction.NAME);
|
||||
action.setParameterValue(CreateRecordAction.PARAM_FILE_PLAN, filePlan);
|
||||
|
||||
Rule rule = new Rule();
|
||||
rule.setRuleType(RuleType.INBOUND);
|
||||
rule.setTitle("my rule");
|
||||
rule.setAction(action);
|
||||
rule.setExecuteAsynchronously(true);
|
||||
ruleService.saveRule(ruleFolder, rule);
|
||||
|
||||
Action fileAction = actionService.createAction(FileToAction.NAME);
|
||||
fileAction.setParameterValue(FileToAction.PARAM_PATH, "/A/B/C/{date.year.long}/{date.month.long}/{date.day.month}");
|
||||
fileAction.setParameterValue(FileToAction.PARAM_CREATE_RECORD_PATH, true);
|
||||
|
||||
Rule fileRule = new Rule();
|
||||
fileRule.setRuleType(RuleType.INBOUND);
|
||||
fileRule.setTitle("my rule");
|
||||
fileRule.setAction(fileAction);
|
||||
fileRule.setExecuteAsynchronously(true);
|
||||
ruleService.saveRule(filePlanService.getUnfiledContainer(filePlan), fileRule);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void test(Void result) throws Exception
|
||||
{
|
||||
assertFalse(ruleService.getRules(ruleFolder).isEmpty());
|
||||
}
|
||||
});
|
||||
|
||||
List<NodeRef> records = new ArrayList<NodeRef>(NUMBER_OF_BATCHES*NUMBER_IN_BATCH);
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_BATCHES; i++)
|
||||
{
|
||||
final int finali = i;
|
||||
records.addAll(doTestInTransaction(new Test<List<NodeRef>>()
|
||||
{
|
||||
@Override
|
||||
public List<NodeRef> run() throws Exception
|
||||
{
|
||||
List<NodeRef> records = new ArrayList<NodeRef>(NUMBER_IN_BATCH);
|
||||
for (int j = 0; j < NUMBER_IN_BATCH; j++)
|
||||
{
|
||||
int count = (finali+1)*(j+1);
|
||||
String name = "content" + count + ".txt";
|
||||
System.out.println(name + " - creating");
|
||||
|
||||
NodeRef record = fileFolderService.create(ruleFolder, name, ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
records.add(record);
|
||||
}
|
||||
return records;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
while(!records.isEmpty())
|
||||
{
|
||||
Thread.sleep(1000);
|
||||
|
||||
final Iterator<NodeRef> temp = records.iterator();
|
||||
doTestInTransaction(new Test<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void run() throws Exception
|
||||
{
|
||||
while (temp.hasNext())
|
||||
{
|
||||
NodeRef record = temp.next();
|
||||
if (nodeService.hasAspect(record, ASPECT_RECORD) && recordService.isFiled(record))
|
||||
{
|
||||
String name = (String) nodeService.getProperty(record, ContentModel.PROP_NAME);
|
||||
System.out.println(name + " - complete");
|
||||
temp.remove();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
exception.printStackTrace();
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,201 @@
|
||||
package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.alfresco.service.cmr.rule.RuleType.INBOUND;
|
||||
import static org.alfresco.util.GUID.generate;
|
||||
import static org.springframework.util.StringUtils.tokenizeToStringArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction;
|
||||
import org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction;
|
||||
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.rule.Rule;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
|
||||
/**
|
||||
* System test for RM-2190: Concurrency exception when upload document to several folders with rules configured to file records
|
||||
*
|
||||
* @author Tuna Aksoy
|
||||
* @since 2.2.1.1
|
||||
*/
|
||||
public class RM2190Test extends BaseRMTestCase
|
||||
{
|
||||
private static final int NUMBER_OF_BATCHES = 1;
|
||||
private static final int NUMBER_IN_BATCH = 10;
|
||||
|
||||
private static final String PATH = "/111/222/333";
|
||||
|
||||
private RuleService ruleService;
|
||||
|
||||
private NodeRef rootFolder;
|
||||
private NodeRef folder1;
|
||||
private NodeRef folder2;
|
||||
|
||||
@Override
|
||||
protected void initServices()
|
||||
{
|
||||
super.initServices();
|
||||
|
||||
ruleService = (RuleService) applicationContext.getBean("RuleService");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isCollaborationSiteTest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRecordTest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void testUploadDocumentsSimultaneouslyWithRules()
|
||||
{
|
||||
doTestInTransaction(new Test<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void run()
|
||||
{
|
||||
rootFolder = fileFolderService.create(documentLibrary, generate(), TYPE_FOLDER).getNodeRef();
|
||||
|
||||
Action createAction = actionService.createAction(CreateRecordAction.NAME);
|
||||
createAction.setParameterValue(CreateRecordAction.PARAM_FILE_PLAN, filePlan);
|
||||
|
||||
Rule declareRule = new Rule();
|
||||
declareRule.setRuleType(INBOUND);
|
||||
declareRule.setTitle(generate());
|
||||
declareRule.setAction(createAction);
|
||||
declareRule.setExecuteAsynchronously(true);
|
||||
declareRule.applyToChildren(true);
|
||||
ruleService.saveRule(rootFolder, declareRule);
|
||||
|
||||
folder1 = fileFolderService.create(rootFolder, generate(), TYPE_FOLDER).getNodeRef();
|
||||
folder2 = fileFolderService.create(rootFolder, generate(), TYPE_FOLDER).getNodeRef();
|
||||
|
||||
Action fileAction = actionService.createAction(FileToAction.NAME);
|
||||
fileAction.setParameterValue(FileToAction.PARAM_PATH, PATH);
|
||||
fileAction.setParameterValue(FileToAction.PARAM_CREATE_RECORD_PATH, true);
|
||||
|
||||
Rule fileRule = new Rule();
|
||||
fileRule.setRuleType(INBOUND);
|
||||
fileRule.setTitle(generate());
|
||||
fileRule.setAction(fileAction);
|
||||
fileRule.setExecuteAsynchronously(true);
|
||||
ruleService.saveRule(unfiledContainer, fileRule);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void test(Void result) throws Exception
|
||||
{
|
||||
assertFalse(ruleService.getRules(rootFolder).isEmpty());
|
||||
assertFalse(ruleService.getRules(unfiledContainer).isEmpty());
|
||||
}
|
||||
});
|
||||
|
||||
doTestInTransaction(new Test<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void run() throws FileNotFoundException, InterruptedException
|
||||
{
|
||||
Thread thread1 = new Thread()
|
||||
{
|
||||
public void run() {
|
||||
List<NodeRef> files = addFilesToFolder(folder1);
|
||||
waitForFilesToBeDeclared(files);
|
||||
}
|
||||
};
|
||||
|
||||
Thread thread2 = new Thread()
|
||||
{
|
||||
public void run() {
|
||||
List<NodeRef> files = addFilesToFolder(folder2);
|
||||
waitForFilesToBeDeclared(files);
|
||||
}
|
||||
};
|
||||
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
|
||||
thread1.join(300000);
|
||||
thread2.join(300000);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void test(Void result) throws Exception
|
||||
{
|
||||
FileInfo category = fileFolderService.resolveNamePath(filePlan, asList(tokenizeToStringArray(PATH, "/", false, true)));
|
||||
assertEquals(NUMBER_IN_BATCH * 2, nodeService.getChildAssocs(category.getNodeRef()).size());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private List<NodeRef> addFilesToFolder(final NodeRef folder)
|
||||
{
|
||||
List<NodeRef> records = new ArrayList<NodeRef>(NUMBER_OF_BATCHES * NUMBER_IN_BATCH);
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_BATCHES; i++)
|
||||
{
|
||||
final int finali = i;
|
||||
records.addAll(doTestInTransaction(new Test<List<NodeRef>>()
|
||||
{
|
||||
@Override
|
||||
public List<NodeRef> run() throws Exception
|
||||
{
|
||||
List<NodeRef> files = new ArrayList<NodeRef>(NUMBER_IN_BATCH);
|
||||
for (int j = 0; j < NUMBER_IN_BATCH; j++)
|
||||
{
|
||||
int count = (finali+1)*(j+1);
|
||||
String name = folder.getId() + " - content" + count + ".txt";
|
||||
System.out.println(name + " - creating");
|
||||
|
||||
NodeRef file = fileFolderService.create(folder, name, TYPE_CONTENT).getNodeRef();
|
||||
files.add(file);
|
||||
}
|
||||
return files;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
return records;
|
||||
}
|
||||
|
||||
private void waitForFilesToBeDeclared(List<NodeRef> files)
|
||||
{
|
||||
while (!files.isEmpty())
|
||||
{
|
||||
final Iterator<NodeRef> temp = files.iterator();
|
||||
doTestInTransaction(new Test<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void run() throws Exception
|
||||
{
|
||||
while (temp.hasNext())
|
||||
{
|
||||
NodeRef record = temp.next();
|
||||
if (nodeService.hasAspect(record, ASPECT_RECORD) && recordService.isFiled(record))
|
||||
{
|
||||
String name = (String) nodeService.getProperty(record, PROP_NAME);
|
||||
System.out.println(name + " - complete");
|
||||
temp.remove();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,155 @@
|
||||
package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
|
||||
|
||||
import static org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService.ROLE_RECORDS_MANAGER;
|
||||
import static org.alfresco.repo.site.SiteModel.SITE_MANAGER;
|
||||
import static org.alfresco.repo.site.SiteServiceImpl.getSiteContainer;
|
||||
import static org.alfresco.service.cmr.rule.RuleType.INBOUND;
|
||||
import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
|
||||
import static org.alfresco.service.cmr.site.SiteService.DOCUMENT_LIBRARY;
|
||||
import static org.alfresco.service.cmr.site.SiteVisibility.PUBLIC;
|
||||
import static org.alfresco.util.GUID.generate;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction;
|
||||
import org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction;
|
||||
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||
import org.alfresco.repo.jscript.app.JSONConversionComponent;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.rule.Rule;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
|
||||
/**
|
||||
* Integration test for RM-2192
|
||||
*
|
||||
* @author Tuna Aksoy
|
||||
* @since 2.2.1.1
|
||||
*/
|
||||
public class RM2192Test extends BaseRMTestCase
|
||||
{
|
||||
private static final String PATH = "/111/222/333";
|
||||
|
||||
private RuleService ruleService;
|
||||
private JSONConversionComponent converter;
|
||||
|
||||
private NodeRef folder;
|
||||
private String user;
|
||||
private NodeRef documentLibrary2;
|
||||
|
||||
@Override
|
||||
protected void initServices()
|
||||
{
|
||||
super.initServices();
|
||||
|
||||
ruleService = (RuleService) applicationContext.getBean("RuleService");
|
||||
converter = (JSONConversionComponent) applicationContext.getBean("jsonConversionComponent");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isCollaborationSiteTest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRecordTest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isUserTest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupCollaborationSiteTestDataImpl()
|
||||
{
|
||||
super.setupCollaborationSiteTestDataImpl();
|
||||
|
||||
String collabSiteId2 = generate();
|
||||
siteService.createSite("site-dashboard", collabSiteId2, generate(), generate(), PUBLIC);
|
||||
documentLibrary2 = getSiteContainer(
|
||||
collabSiteId2,
|
||||
DOCUMENT_LIBRARY,
|
||||
true,
|
||||
siteService,
|
||||
transactionService,
|
||||
taggingService);
|
||||
|
||||
assertNotNull("Collaboration site document library component was not successfully created.", documentLibrary2);
|
||||
|
||||
user = generate();
|
||||
createPerson(user);
|
||||
|
||||
siteService.setMembership(collabSiteId2, user, SITE_MANAGER);
|
||||
|
||||
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_RECORDS_MANAGER, user);
|
||||
}
|
||||
|
||||
public void testAccessToRecordAfterDeclaring()
|
||||
{
|
||||
doTestInTransaction(new Test<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void run()
|
||||
{
|
||||
folder = fileFolderService.create(documentLibrary2, generate(), TYPE_FOLDER).getNodeRef();
|
||||
|
||||
Action createAction = actionService.createAction(CreateRecordAction.NAME);
|
||||
createAction.setParameterValue(CreateRecordAction.PARAM_FILE_PLAN, filePlan);
|
||||
|
||||
Rule declareRule = new Rule();
|
||||
declareRule.setRuleType(INBOUND);
|
||||
declareRule.setTitle(generate());
|
||||
declareRule.setAction(createAction);
|
||||
declareRule.setExecuteAsynchronously(true);
|
||||
declareRule.applyToChildren(true);
|
||||
ruleService.saveRule(folder, declareRule);
|
||||
|
||||
Action fileAction = actionService.createAction(FileToAction.NAME);
|
||||
fileAction.setParameterValue(FileToAction.PARAM_PATH, PATH);
|
||||
fileAction.setParameterValue(FileToAction.PARAM_CREATE_RECORD_PATH, true);
|
||||
|
||||
Rule fileRule = new Rule();
|
||||
fileRule.setRuleType(INBOUND);
|
||||
fileRule.setTitle(generate());
|
||||
fileRule.setAction(fileAction);
|
||||
fileRule.setExecuteAsynchronously(true);
|
||||
ruleService.saveRule(unfiledContainer, fileRule);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void test(Void result) throws Exception
|
||||
{
|
||||
assertFalse(ruleService.getRules(folder).isEmpty());
|
||||
assertFalse(ruleService.getRules(unfiledContainer).isEmpty());
|
||||
}
|
||||
});
|
||||
|
||||
doTestInTransaction(new Test<Void>()
|
||||
{
|
||||
NodeRef document;
|
||||
|
||||
@Override
|
||||
public Void run()
|
||||
{
|
||||
document = fileFolderService.create(folder, generate(), TYPE_CONTENT).getNodeRef();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void test(Void result) throws InterruptedException
|
||||
{
|
||||
Thread.sleep(10000);
|
||||
|
||||
assertEquals(permissionService.hasPermission(document, READ_RECORDS), ALLOWED);
|
||||
assertTrue(recordService.isFiled(document));
|
||||
assertNotNull(converter.toJSON(document, true));
|
||||
}
|
||||
}, user);
|
||||
}
|
||||
}
|
@@ -29,6 +29,7 @@ import org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction;
|
||||
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
|
||||
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
@@ -113,10 +114,18 @@ public class FileToActionTest extends BaseRMTestCase
|
||||
assertTrue(recordService.isRecord(dmDocument));
|
||||
assertFalse(recordService.isFiled(dmDocument));
|
||||
|
||||
AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Void>()
|
||||
{
|
||||
public Void doWork() throws Exception
|
||||
{
|
||||
// is the unfiled container the primary parent of the filed record
|
||||
NodeRef parent = nodeService.getPrimaryParent(dmDocument).getParentRef();
|
||||
assertEquals(filePlanService.getUnfiledContainer(filePlan), parent);
|
||||
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}});
|
||||
|
||||
return null;
|
||||
}
|
||||
}, dmCollaborator);
|
||||
@@ -203,12 +212,17 @@ public class FileToActionTest extends BaseRMTestCase
|
||||
|
||||
private void createRecord(final String path, final String name, final String resolvedPath)
|
||||
{
|
||||
final String[] pathValues = StringUtils.tokenizeToStringArray(resolvedPath, "/");
|
||||
|
||||
// set parameters
|
||||
Map<String, Serializable> params = new HashMap<String, Serializable>(1);
|
||||
params.put(FileToAction.PARAM_PATH, path);
|
||||
params.put(FileToAction.PARAM_CREATE_RECORD_PATH, true);
|
||||
|
||||
doTestInTransaction(new Test<Void>()
|
||||
{
|
||||
public Void run() throws Exception
|
||||
{
|
||||
String[] pathValues = StringUtils.tokenizeToStringArray(resolvedPath, "/");
|
||||
|
||||
// show the folder doesn't exist to begin with
|
||||
FileInfo createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList<String>(Arrays.asList(pathValues)), false);
|
||||
assertNull(createdRecordFolder);
|
||||
@@ -218,11 +232,19 @@ public class FileToActionTest extends BaseRMTestCase
|
||||
params.put(FileToAction.PARAM_PATH, path);
|
||||
params.put(FileToAction.PARAM_CREATE_RECORD_PATH, true);
|
||||
|
||||
return null;
|
||||
}
|
||||
}, ADMIN_USER);
|
||||
|
||||
// execute file-to action
|
||||
rmActionService.executeRecordsManagementAction(dmDocument, FileToAction.NAME, params);
|
||||
|
||||
doTestInTransaction(new Test<Void>()
|
||||
{
|
||||
public Void run() throws Exception
|
||||
{
|
||||
// show the folder has now been created
|
||||
createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList<String>(Arrays.asList(pathValues)), false);
|
||||
FileInfo createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList<String>(Arrays.asList(pathValues)), false);
|
||||
assertNotNull(createdRecordFolder);
|
||||
assertEquals(name, createdRecordFolder.getName());
|
||||
NodeRef createdRecordFolderNodeRef = createdRecordFolder.getNodeRef();
|
||||
|
@@ -105,9 +105,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
||||
testMap.put(monkey, Integer.valueOf(1));
|
||||
testMap.put(elephant, Integer.valueOf(1));
|
||||
|
||||
checkExtendedReaders(filePlan, testMap);
|
||||
checkExtendedReaders(rmContainer, testMap);
|
||||
checkExtendedReaders(rmFolder, testMap);
|
||||
checkExtendedReaders(record, testMap);
|
||||
|
||||
Set<String> extendedReadersToo = new HashSet<String>(2);
|
||||
@@ -125,9 +122,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
||||
testMapThree.put(elephant, Integer.valueOf(1));
|
||||
testMapThree.put(snake, Integer.valueOf(1));
|
||||
|
||||
checkExtendedReaders(filePlan, testMapThree);
|
||||
checkExtendedReaders(rmContainer, testMapThree);
|
||||
checkExtendedReaders(rmFolder, testMapThree);
|
||||
checkExtendedReaders(recordToo, testMapToo);
|
||||
|
||||
// test remove (with no parent inheritance)
|
||||
@@ -142,9 +136,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
||||
testMapFour.put(monkey, Integer.valueOf(1));
|
||||
testMapFour.put(snake, Integer.valueOf(1));
|
||||
|
||||
checkExtendedReaders(filePlan, testMapThree);
|
||||
checkExtendedReaders(rmContainer, testMapThree);
|
||||
checkExtendedReaders(rmFolder, testMapFour);
|
||||
checkExtendedReaders(recordToo, testMapToo);
|
||||
|
||||
// test remove (apply to parents)
|
||||
@@ -158,9 +149,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
||||
testMapFour.remove(snake);
|
||||
testMapToo.remove(snake);
|
||||
|
||||
checkExtendedReaders(filePlan, testMapThree);
|
||||
checkExtendedReaders(rmContainer, testMapThree);
|
||||
checkExtendedReaders(rmFolder, testMapFour);
|
||||
checkExtendedReaders(recordToo, testMapToo);
|
||||
|
||||
return null;
|
||||
@@ -197,9 +185,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
||||
|
||||
extendedSecurityService.addExtendedSecurity(record, extendedReaders, null);
|
||||
|
||||
checkExtendedReaders(filePlan, testMap);
|
||||
checkExtendedReaders(rmContainer, testMap);
|
||||
checkExtendedReaders(rmFolder, testMap);
|
||||
checkExtendedReaders(record, testMap);
|
||||
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordCategory));
|
||||
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordFolder));
|
||||
@@ -212,11 +197,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
||||
@Override
|
||||
public void test(Void result) throws Exception
|
||||
{
|
||||
checkExtendedReaders(filePlan, testMap);
|
||||
assertFalse(extendedSecurityService.hasExtendedSecurity(rmContainer));
|
||||
// assertEquals(0, extendedSecurityService.getExtendedReaders(rmFolder).size());
|
||||
checkExtendedReaders(moveRecordCategory, testMap);
|
||||
checkExtendedReaders(moveRecordFolder, testMap);
|
||||
checkExtendedReaders(record, testMap);
|
||||
}
|
||||
});
|
||||
|
@@ -28,7 +28,6 @@ import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
|
||||
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.role.Role;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
|
||||
@@ -38,7 +37,6 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.AccessPermission;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.GUID;
|
||||
@@ -304,15 +302,12 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
||||
|
||||
public void test(Void result)
|
||||
{
|
||||
checkPermissions(READ_RECORDS, AccessStatus.ALLOWED, // file
|
||||
// plan
|
||||
AccessStatus.ALLOWED, // unfiled container
|
||||
checkPermissions(READ_RECORDS, AccessStatus.DENIED, // file plan
|
||||
AccessStatus.DENIED, // unfiled container
|
||||
AccessStatus.DENIED, // record category
|
||||
AccessStatus.DENIED, // record folder
|
||||
AccessStatus.ALLOWED); // doc/record
|
||||
|
||||
permissionReport();
|
||||
|
||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(filePlan,
|
||||
RMPermissionModel.VIEW_RECORDS));
|
||||
|
||||
@@ -362,9 +357,8 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
||||
@Override
|
||||
public Void run()
|
||||
{
|
||||
checkPermissions(READ_RECORDS, AccessStatus.ALLOWED, // file
|
||||
// plan
|
||||
AccessStatus.ALLOWED, // unfiled container
|
||||
checkPermissions(READ_RECORDS, AccessStatus.DENIED, // file plan
|
||||
AccessStatus.DENIED, // unfiled container
|
||||
AccessStatus.DENIED, // record category
|
||||
AccessStatus.DENIED, // record folder
|
||||
AccessStatus.ALLOWED); // doc/record
|
||||
@@ -394,38 +388,6 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
||||
}, dmConsumer);
|
||||
}
|
||||
|
||||
private void permissionReport()
|
||||
{
|
||||
Set<String> writers = extendedSecurityService.getExtendedWriters(dmDocument);
|
||||
for (String writer : writers)
|
||||
{
|
||||
System.out.println("writer: " + writer);
|
||||
}
|
||||
|
||||
System.out.println("Users assigned to extended writers role:");
|
||||
Set<String> assignedUsers = filePlanRoleService.getUsersAssignedToRole(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS);
|
||||
for (String assignedUser : assignedUsers)
|
||||
{
|
||||
System.out.println(" ... " + assignedUser);
|
||||
}
|
||||
|
||||
Set<AccessPermission> perms = permissionService.getAllSetPermissions(filePlan);
|
||||
for (AccessPermission perm : perms)
|
||||
{
|
||||
if (perm.getPermission().contains(RMPermissionModel.EDIT_NON_RECORD_METADATA))
|
||||
{
|
||||
System.out.println(" ... " + perm.getAuthority() + " - " + perm.getPermission() + " - " + perm.getAccessStatus().toString());
|
||||
}
|
||||
}
|
||||
for (AccessPermission perm : perms)
|
||||
{
|
||||
if (perm.getPermission().contains(RMPermissionModel.VIEW_RECORDS))
|
||||
{
|
||||
System.out.println(" ... " + perm.getAuthority() + " - " + perm.getPermission() + " - " + perm.getAccessStatus().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateRecordNoLink() throws Exception
|
||||
{
|
||||
// show that users without WRITE can not create a record from a document
|
||||
|
Reference in New Issue
Block a user