RM-1440: Edit Non Record Metadata capability is required to file a record

* can now file an electronic record with only CreateRecord capability
  * tidied up some of the policy code as I went
  * integration test
  * non-electronic records to follow



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@73961 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2014-06-17 06:44:19 +00:00
parent 901a8fd8c8
commit c9223cb510
18 changed files with 361 additions and 142 deletions

View File

@@ -43,13 +43,13 @@
<ref bean="rmEditRecordMetadataCapability"/> <ref bean="rmEditRecordMetadataCapability"/>
<ref bean="rmModifyUnfiledRecordsContainerFolderCapability"/> <ref bean="rmModifyUnfiledRecordsContainerFolderCapability"/>
<ref bean="rmModifyHoldCapability"/> <ref bean="rmModifyHoldCapability"/>
<ref bean="rmCreateRecordsCapability"/>
</list> </list>
</property> </property>
</bean> </bean>
<bean id="rmUpdateProperties" <bean id="rmUpdateProperties"
parent="compositeCapability" parent="compositeCapability">
class="org.alfresco.module.org_alfresco_module_rm.capability.impl.UpdatePropertiesCapability">
<property name="name" value="UpdateProperties"/> <property name="name" value="UpdateProperties"/>
<property name="private" value="true"/> <property name="private" value="true"/>
<property name="capabilities"> <property name="capabilities">
@@ -62,6 +62,7 @@
<ref bean="rmEditRecordMetadataCapability"/> <ref bean="rmEditRecordMetadataCapability"/>
<ref bean="rmModifyUnfiledRecordsContainerFolderCapability"/> <ref bean="rmModifyUnfiledRecordsContainerFolderCapability"/>
<ref bean="rmModifyHoldCapability"/> <ref bean="rmModifyHoldCapability"/>
<ref bean="rmCreateRecordsCapability"/>
</list> </list>
</property> </property>
</bean> </bean>

View File

@@ -211,7 +211,7 @@
<property name="group"><ref bean="recordsGroup"/></property> <property name="group"><ref bean="recordsGroup"/></property>
<property name="index" value="10" /> <property name="index" value="10" />
</bean> </bean>
<bean id="rmEditNonRecordMetadataCapability" <bean id="rmEditNonRecordMetadataCapability"
parent="declarativeCapability"> parent="declarativeCapability">
<property name="name" value="EditNonRecordMetadata"/> <property name="name" value="EditNonRecordMetadata"/>
@@ -254,6 +254,7 @@
<property name="index" value="30" /> <property name="index" value="30" />
</bean> </bean>
<bean id="rmMoveRecordsCapability" <bean id="rmMoveRecordsCapability"
parent="declarativeCapability" > parent="declarativeCapability" >
<property name="name" value="MoveRecords" /> <property name="name" value="MoveRecords" />

View File

@@ -9,6 +9,22 @@
<property name="beanName" value="NodeService_security" /> <property name="beanName" value="NodeService_security" />
<property name="extendingBeanName" value="rm.NodeService_security" /> <property name="extendingBeanName" value="rm.NodeService_security" />
</bean> </bean>
<!-- extended file folder bean definition -->
<bean id="rm.fileFolderService" abstract="true" class="org.alfresco.repo.model.filefolder.ExtendedFileFolderServiceImpl">
<property name="recordService" ref="RecordService" />
</bean>
<bean class="org.alfresco.module.org_alfresco_module_rm.util.BeanExtender">
<property name="beanName" value="fileFolderService" />
<property name="extendingBeanName" value="rm.fileFolderService" />
</bean>
<!-- extend file folder service security to report capability details on failure -->
<bean id="rm.FileFolderService_security" abstract="true" class="org.alfresco.module.org_alfresco_module_rm.security.RMMethodSecurityInterceptor"/>
<bean class="org.alfresco.module.org_alfresco_module_rm.util.BeanExtender">
<property name="beanName" value="FileFolderService_security" />
<property name="extendingBeanName" value="rm.FileFolderService_security" />
</bean>
<bean id="ExtendedPermissionService" class="org.springframework.aop.framework.ProxyFactoryBean"> <bean id="ExtendedPermissionService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"> <property name="proxyInterfaces">

View File

@@ -1090,6 +1090,7 @@
org.alfresco.module.org_alfresco_module_rm.record.RecordService.isDeclared=RM.Read.0 org.alfresco.module.org_alfresco_module_rm.record.RecordService.isDeclared=RM.Read.0
org.alfresco.module.org_alfresco_module_rm.record.RecordService.isFiled=RM.Read.0 org.alfresco.module.org_alfresco_module_rm.record.RecordService.isFiled=RM.Read.0
org.alfresco.module.org_alfresco_module_rm.record.RecordService.createRecord=RM_ALLOW org.alfresco.module.org_alfresco_module_rm.record.RecordService.createRecord=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.record.RecordService.createRecordFromContent=RM.Create.0
org.alfresco.module.org_alfresco_module_rm.record.RecordService.file=RM_ALLOW org.alfresco.module.org_alfresco_module_rm.record.RecordService.file=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.record.RecordService.hideRecord=RM_ALLOW org.alfresco.module.org_alfresco_module_rm.record.RecordService.hideRecord=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.record.RecordService.isPropertyEditable=RM.Read.0 org.alfresco.module.org_alfresco_module_rm.record.RecordService.isPropertyEditable=RM.Read.0

View File

@@ -65,7 +65,7 @@ rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.rename=RM.Upd
rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.move=RM.Move.0.1 rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.move=RM.Move.0.1
rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.moveFrom=RM.Move.0.2 rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.moveFrom=RM.Move.0.2
rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.copy=RM.Read.0,RM.Create.1.0 rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.copy=RM.Read.0,RM.Create.1.0
rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.create=RM.Create.0.2 rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.create=RM.Create.0
rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.delete=RM.Delete.0 rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.delete=RM.Delete.0
rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.getNamePath=RM.Read.1 rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.getNamePath=RM.Read.1
rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.getNameOnlyPath=RM.Read.1 rm.methodsecurity.org.alfresco.service.cmr.model.FileFolderService.getNameOnlyPath=RM.Read.1

View File

@@ -61,7 +61,7 @@ public class ChangeOrDeleteReferencesCapability extends DeclarativeCapability
else else
{ {
if (checkConditions(source) && if (checkConditions(source) &&
checkPermissions(source)) checkPermissions(source))
{ {
return AccessDecisionVoter.ACCESS_GRANTED; return AccessDecisionVoter.ACCESS_GRANTED;
} }

View File

@@ -67,19 +67,18 @@ public class CreateCapability extends DeclarativeCapability
@Override @Override
public int evaluate(NodeRef nodeRef) public int evaluate(NodeRef nodeRef)
{ {
return evaluate(nodeRef, null, null, null); return evaluate(nodeRef, null, null);
} }
/** /**
* Evaluate capability. * Evaluate capability.
* *
* @param destination * @param destination destination node reference
* @param linkee * @param linkee linkee node reference, can be null
* @param type * @param assocType association type, can be null
* @param assocType
* @return * @return
*/ */
public int evaluate(NodeRef destination, NodeRef linkee, QName type, QName assocType) public int evaluate(NodeRef destination, NodeRef linkee, QName assocType)
{ {
if (linkee != null) if (linkee != null)
{ {
@@ -95,8 +94,9 @@ public class CreateCapability extends DeclarativeCapability
{ {
if (linkee == null) if (linkee == null)
{ {
if (recordService.isRecord(destination) && !recordService.isDeclared(destination) && if (recordService.isRecord(destination) &&
permissionService.hasPermission(destination, RMPermissionModel.FILE_RECORDS) == AccessStatus.ALLOWED) !recordService.isDeclared(destination) &&
permissionService.hasPermission(destination, RMPermissionModel.FILE_RECORDS) == AccessStatus.ALLOWED)
{ {
return AccessDecisionVoter.ACCESS_GRANTED; return AccessDecisionVoter.ACCESS_GRANTED;
} }

View File

@@ -1,50 +0,0 @@
/*
* 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.capability.impl;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.module.org_alfresco_module_rm.capability.declarative.DeclarativeCompositeCapability;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
* Update properties capability.
*
* @author andyh
*/
public class UpdatePropertiesCapability extends DeclarativeCompositeCapability
{
/**
* Evaluate capability, taking into account the protected properties.
*
* @param nodeRef node reference
* @param properties updated properties, if no null
*/
public int evaluate(NodeRef nodeRef, Map<QName, Serializable> properties)
{
// if ((properties != null) && (voter.includesProtectedPropertyChange(nodeRef, properties)))
// {
// return AccessDecisionVoter.ACCESS_DENIED;
// }
return evaluate(nodeRef);
}
}

View File

@@ -30,11 +30,14 @@ import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
/** /**
* RM security configuration definition.
*
* @author Roy Wetherall * @author Roy Wetherall
* @since 2.1 * @since 2.1
*/ */
public class ConfigAttributeDefinition public class ConfigAttributeDefinition
{ {
/** allowable RM security configurations */
public static final String RM = "RM"; public static final String RM = "RM";
public static final String RM_ALLOW = "RM_ALLOW"; public static final String RM_ALLOW = "RM_ALLOW";
public static final String RM_DENY = "RM_DENY"; public static final String RM_DENY = "RM_DENY";
@@ -42,18 +45,30 @@ public class ConfigAttributeDefinition
public static final String RM_ABSTAIN = "RM_ABSTAIN"; public static final String RM_ABSTAIN = "RM_ABSTAIN";
public static final String RM_QUERY = "RM_QUERY"; public static final String RM_QUERY = "RM_QUERY";
/** security type */
private String typeString; private String typeString;
/** policy name */
private String policyName; private String policyName;
/** simple permission reference */
private SimplePermissionReference required; private SimplePermissionReference required;
/** parameter position map */
private Map<Integer, Integer> parameters = new HashMap<Integer, Integer>(2, 1.0f); private Map<Integer, Integer> parameters = new HashMap<Integer, Integer>(2, 1.0f);
/** is parent */
private boolean parent = false; private boolean parent = false;
/**
* Default constructor
*
* @param attr configuration attribute instance
* @param namespacePrefixResolver namespace prefix resolver
*/
public ConfigAttributeDefinition(ConfigAttribute attr, NamespacePrefixResolver namespacePrefixResolver) public ConfigAttributeDefinition(ConfigAttribute attr, NamespacePrefixResolver namespacePrefixResolver)
{ {
// tokenize configuration string
StringTokenizer st = new StringTokenizer(attr.getAttribute(), ".", false); StringTokenizer st = new StringTokenizer(attr.getAttribute(), ".", false);
if (st.countTokens() < 1) if (st.countTokens() < 1)
{ {
@@ -61,8 +76,13 @@ public class ConfigAttributeDefinition
} }
typeString = st.nextToken(); typeString = st.nextToken();
if (!(typeString.equals(RM) || typeString.equals(RM_ALLOW) || typeString.equals(RM_CAP) || typeString.equals(RM_DENY) || typeString.equals(RM_QUERY) || typeString // check that the configuration is valid
.equals(RM_ABSTAIN))) if (!(typeString.equals(RM) ||
typeString.equals(RM_ALLOW) ||
typeString.equals(RM_CAP) ||
typeString.equals(RM_DENY) ||
typeString.equals(RM_QUERY) ||
typeString.equals(RM_ABSTAIN)))
{ {
throw new ACLEntryVoterException("Invalid type: must be ACL_NODE, ACL_PARENT or ACL_ALLOW"); throw new ACLEntryVoterException("Invalid type: must be ACL_NODE, ACL_PARENT or ACL_ALLOW");
} }

View File

@@ -31,18 +31,25 @@ public class CreatePolicy extends AbstractBasePolicy
Class[] params, Class[] params,
ConfigAttributeDefinition cad) ConfigAttributeDefinition cad)
{ {
NodeRef linkee = null;
NodeRef destination = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
QName type = getType(invocation, params, cad.getParameters().get(1), cad.isParent());
// linkee is not null for creating secondary child assocs
NodeRef linkee = getTestNode(invocation, params, cad.getParameters().get(1), cad.isParent());
QName assocType = null; QName assocType = null;
if(cad.getParameters().size() > 2)
// get the destination node
NodeRef destination = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
if (cad.getParameters().size() > 1)
{ {
assocType = getType(invocation, params, cad.getParameters().get(2), cad.isParent()); // get the linkee when present
linkee = getTestNode(invocation, params, cad.getParameters().get(1), cad.isParent());
// get the assoc type
if(cad.getParameters().size() > 2)
{
assocType = getType(invocation, params, cad.getParameters().get(2), cad.isParent());
}
} }
return ((CreateCapability)capabilityService.getCapability("Create")).evaluate(destination, linkee, type, assocType); return ((CreateCapability)capabilityService.getCapability("Create")).evaluate(destination, linkee, assocType);
} }
} }

View File

@@ -18,13 +18,7 @@
*/ */
package org.alfresco.module.org_alfresco_module_rm.capability.policy; package org.alfresco.module.org_alfresco_module_rm.capability.policy;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.module.org_alfresco_module_rm.capability.impl.UpdatePropertiesCapability;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
public class UpdatePropertiesPolicy extends AbstractBasePolicy public class UpdatePropertiesPolicy extends AbstractBasePolicy
@@ -35,29 +29,8 @@ public class UpdatePropertiesPolicy extends AbstractBasePolicy
Class[] params, Class[] params,
ConfigAttributeDefinition cad) ConfigAttributeDefinition cad)
{ {
NodeRef updatee = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent()); NodeRef nodeRef = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
Map<QName, Serializable> properties; return capabilityService.getCapability("UpdateProperties").evaluate(nodeRef);
if (QName.class.isAssignableFrom(params[cad.getParameters().get(1)]))
{
// single update/delete
// We have a specific property
QName propertyQName = getQName(invocation, params, cad.getParameters().get(1));
properties = new HashMap<QName, Serializable>(1, 1.0f);
if (cad.getParameters().size() > 2)
{
properties.put(propertyQName, getProperty(invocation, params, cad.getParameters().get(2)));
}
else
{
properties.put(propertyQName, null);
}
}
else
{
properties = getProperties(invocation, params, cad.getParameters().get(1));
}
return ((UpdatePropertiesCapability)capabilityService.getCapability("UpdateProperties")).evaluate(updatee, properties);
} }
} }

View File

@@ -56,6 +56,14 @@ public interface RecordService
* Disables the property editable check. * Disables the property editable check.
*/ */
void disablePropertyEditableCheck(); void disablePropertyEditableCheck();
/**
* Disables the property editable check for a given node in this transaction only.
*
* @param nodeRef node reference
* @since 2.2
*/
void disablePropertyEditableCheck(NodeRef nodeRef);
/** /**
* Enables the property editable check. By default this is always enabled. * Enables the property editable check. By default this is always enabled.
@@ -138,12 +146,13 @@ public interface RecordService
* Creates a new document in the unfiled records container if the given node reference is a file plan * Creates a new document in the unfiled records container if the given node reference is a file plan
* node reference otherwise the node reference will be used as the destination for the new record. * node reference otherwise the node reference will be used as the destination for the new record.
* *
* @param nodeRef * @param parent parent node reference
* @param name * @param name name of the new record
* @param type * @param type content type, cm:content if null
* @param properties * @param properties properties
* @param reader content reader
*/ */
NodeRef createRecord(NodeRef nodeRef, String name, QName type, Map<QName, Serializable> properties, ContentReader reader); NodeRef createRecordFromContent(NodeRef parent, String name, QName type, Map<QName, Serializable> properties, ContentReader reader);
/** /**
* Indicates whether the record is filed or not * Indicates whether the record is filed or not

View File

@@ -109,6 +109,9 @@ public class RecordServiceImpl extends BaseBehaviourBean
{ {
/** Logger */ /** Logger */
private static Log logger = LogFactory.getLog(RecordServiceImpl.class); private static Log logger = LogFactory.getLog(RecordServiceImpl.class);
/** transation data key */
private static final String IGNORE_ON_UPDATE = "ignoreOnUpdate";
/** I18N */ /** I18N */
private static final String MSG_NODE_HAS_ASPECT = "rm.service.node-has-aspect"; private static final String MSG_NODE_HAS_ASPECT = "rm.service.node-has-aspect";
@@ -335,8 +338,6 @@ public class RecordServiceImpl extends BaseBehaviourBean
onDeleteDeclaredRecordLink); onDeleteDeclaredRecordLink);
} }
/** /**
* @see org.alfresco.repo.node.NodeServicePolicies.OnRemoveAspectPolicy#onRemoveAspect(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName) * @see org.alfresco.repo.node.NodeServicePolicies.OnRemoveAspectPolicy#onRemoveAspect(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName)
*/ */
@@ -510,6 +511,15 @@ public class RecordServiceImpl extends BaseBehaviourBean
{ {
getBehaviour("onUpdateProperties").disable(); getBehaviour("onUpdateProperties").disable();
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#disablePropertyEditableCheck(org.alfresco.service.cmr.repository.NodeRef)
*/
public void disablePropertyEditableCheck(NodeRef nodeRef)
{
Set<NodeRef> ignoreOnUpdate = TransactionalResourceHelper.getSet(IGNORE_ON_UPDATE);
ignoreOnUpdate.add(nodeRef);
}
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#enablePropertyEditableCheck() * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#enablePropertyEditableCheck()
@@ -537,7 +547,8 @@ public class RecordServiceImpl extends BaseBehaviourBean
if (AuthenticationUtil.getFullyAuthenticatedUser() != null && if (AuthenticationUtil.getFullyAuthenticatedUser() != null &&
!AuthenticationUtil.isRunAsUserTheSystemUser() && !AuthenticationUtil.isRunAsUserTheSystemUser() &&
nodeService.exists(nodeRef) && nodeService.exists(nodeRef) &&
isRecord(nodeRef)) isRecord(nodeRef) &&
!TransactionalResourceHelper.getSet(IGNORE_ON_UPDATE).contains(nodeRef))
{ {
for (Map.Entry<QName, Serializable> entry : after.entrySet()) for (Map.Entry<QName, Serializable> entry : after.entrySet())
{ {
@@ -560,9 +571,10 @@ public class RecordServiceImpl extends BaseBehaviourBean
// otherwise // otherwise
propertyUnchanged = EqualsHelper.nullSafeEquals(beforeValue, afterValue); propertyUnchanged = EqualsHelper.nullSafeEquals(beforeValue, afterValue);
} }
if (!propertyUnchanged && if (!propertyUnchanged &&
!isPropertyEditable(nodeRef, property)) !(ContentModel.PROP_CONTENT.equals(property) && beforeValue == null) &&
!isPropertyEditable(nodeRef, property))
{ {
// the user can't edit the record property // the user can't edit the record property
throw new ModelAccessDeniedException( throw new ModelAccessDeniedException(
@@ -814,19 +826,21 @@ public class RecordServiceImpl extends BaseBehaviourBean
} }
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#createRecord(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, org.alfresco.service.namespace.QName, java.util.Map, org.alfresco.service.cmr.repository.ContentReader) * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#createNewRecord(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, org.alfresco.service.namespace.QName, java.util.Map, org.alfresco.service.cmr.repository.ContentReader)
*/ */
@Override @Override
public NodeRef createRecord(NodeRef nodeRef, String name, QName type, Map<QName, Serializable> properties, ContentReader reader) public NodeRef createRecordFromContent(NodeRef parent, String name, QName type, Map<QName, Serializable> properties, ContentReader reader)
{ {
ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("nodeRef", parent);
ParameterCheck.mandatory("name", name); ParameterCheck.mandatory("name", name);
NodeRef destination = nodeRef; NodeRef record = null;
if (isFilePlan(nodeRef)) NodeRef destination = parent;
if (isFilePlan(parent))
{ {
// get the unfiled record container for the file plan // get the unfiled record container for the file plan
destination = filePlanService.getUnfiledContainer(nodeRef); destination = filePlanService.getUnfiledContainer(parent);
if (destination == null) if (destination == null)
{ {
throw new AlfrescoRuntimeException("Unable to create record, because unfiled container could not be found."); throw new AlfrescoRuntimeException("Unable to create record, because unfiled container could not be found.");
@@ -838,24 +852,35 @@ public class RecordServiceImpl extends BaseBehaviourBean
{ {
type = ContentModel.TYPE_CONTENT; type = ContentModel.TYPE_CONTENT;
} }
// TODO ensure that the type is a sub-type of cm:content else if (!dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT))
// create the new record
NodeRef record = fileFolderService.create(destination, name, type).getNodeRef();
// set the properties
if (properties != null)
{ {
nodeService.addProperties(record, properties); throw new AlfrescoRuntimeException("Record can only be created from a sub-type of cm:content.");
} }
// set the content disablePropertyEditableCheck();
if (reader != null) try
{ {
ContentWriter writer = fileFolderService.getWriter(record); // create the new record
writer.setEncoding(reader.getEncoding()); record = fileFolderService.create(destination, name, type).getNodeRef();
writer.setMimetype(reader.getMimetype());
writer.putContent(reader); // set the properties
if (properties != null)
{
nodeService.addProperties(record, properties);
}
// set the content
if (reader != null)
{
ContentWriter writer = fileFolderService.getWriter(record);
writer.setEncoding(reader.getEncoding());
writer.setMimetype(reader.getMimetype());
writer.putContent(reader);
}
}
finally
{
enablePropertyEditableCheck();
} }
// Check if the "record" aspect has been applied already. // Check if the "record" aspect has been applied already.
@@ -882,6 +907,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
ParameterCheck.mandatory("document", document); ParameterCheck.mandatory("document", document);
ruleService.disableRules(); ruleService.disableRules();
disablePropertyEditableCheck();
try try
{ {
// get the record id // get the record id
@@ -921,6 +947,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
finally finally
{ {
ruleService.enableRules(); ruleService.enableRules();
enablePropertyEditableCheck();
} }
} }

View File

@@ -116,10 +116,10 @@ public class ReportServiceImpl extends ServiceBaseImpl
ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("nodeRef", nodeRef);
ParameterCheck.mandatory("report", report); ParameterCheck.mandatory("report", report);
return recordService.createRecord(nodeRef, return recordService.createRecordFromContent(nodeRef,
report.getReportName(), report.getReportName(),
report.getReportType(), report.getReportType(),
report.getReportProperties(), report.getReportProperties(),
report.getReportContent()); report.getReportContent());
} }
} }

View File

@@ -0,0 +1,61 @@
/**
*
*/
package org.alfresco.repo.model.filefolder;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
* @author Roy Wetherall
*/
public class ExtendedFileFolderServiceImpl extends FileFolderServiceImpl
{
protected RecordService recordService;
public void setRecordService(RecordService recordService)
{
this.recordService = recordService;
}
@Override
public FileInfo create(NodeRef parentNodeRef, String name, QName typeQName) throws FileExistsException
{
FileInfo result = null;
recordService.disablePropertyEditableCheck();
try
{
result = super.create(parentNodeRef, name, typeQName);
}
finally
{
recordService.enablePropertyEditableCheck();
recordService.disablePropertyEditableCheck(result.getNodeRef());
}
return result;
}
@Override
public FileInfo create(NodeRef parentNodeRef, String name, QName typeQName, QName assocQName) throws FileExistsException
{
FileInfo result = null;
recordService.disablePropertyEditableCheck();
try
{
result = super.create(parentNodeRef, name, typeQName, assocQName);
}
finally
{
recordService.enablePropertyEditableCheck();
recordService.disablePropertyEditableCheck(result.getNodeRef());
}
return result;
}
}

View File

@@ -22,7 +22,7 @@ import org.alfresco.module.org_alfresco_module_rm.test.integration.disposition.D
import org.alfresco.module.org_alfresco_module_rm.test.integration.dod.DoD5015TestSuite; import org.alfresco.module.org_alfresco_module_rm.test.integration.dod.DoD5015TestSuite;
import org.alfresco.module.org_alfresco_module_rm.test.integration.event.EventTestSuite; import org.alfresco.module.org_alfresco_module_rm.test.integration.event.EventTestSuite;
import org.alfresco.module.org_alfresco_module_rm.test.integration.issue.IssueTestSuite; import org.alfresco.module.org_alfresco_module_rm.test.integration.issue.IssueTestSuite;
import org.alfresco.module.org_alfresco_module_rm.test.integration.record.RejectRecordTest; import org.alfresco.module.org_alfresco_module_rm.test.integration.record.RecordTestSuite;
import org.alfresco.module.org_alfresco_module_rm.test.integration.recordfolder.RecordFolderTestSuite; import org.alfresco.module.org_alfresco_module_rm.test.integration.recordfolder.RecordFolderTestSuite;
import org.alfresco.module.org_alfresco_module_rm.test.integration.report.ReportTestSuite; import org.alfresco.module.org_alfresco_module_rm.test.integration.report.ReportTestSuite;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -44,7 +44,7 @@ import org.junit.runners.Suite.SuiteClasses;
EventTestSuite.class, EventTestSuite.class,
ReportTestSuite.class, ReportTestSuite.class,
DispositionTestSuite.class, DispositionTestSuite.class,
RejectRecordTest.class, RecordTestSuite.class,
RecordFolderTestSuite.class RecordFolderTestSuite.class
}) })
public class IntegrationTestSuite public class IntegrationTestSuite

View File

@@ -0,0 +1,152 @@
/*
* 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.record;
import java.util.HashSet;
import java.util.Set;
import org.alfresco.model.ContentModel;
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.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.GUID;
/**
* Create record tests.
*
* @author Roy Wetherall
* @since 2.2
*/
public class CreateRecordTest extends BaseRMTestCase
{
public void testCreateRecordCapabilityOnly() throws Exception
{
doBehaviourDrivenTest(new BehaviourDrivenTest()
{
/** test data */
String roleName = GUID.generate();
String user = GUID.generate();
NodeRef recordFolder;
NodeRef record;
public void given()
{
// create role
Set<Capability> capabilities = new HashSet<Capability>(2);
capabilities.add(capabilityService.getCapability("ViewRecords"));
capabilities.add(capabilityService.getCapability("CreateRecords"));
filePlanRoleService.createRole(filePlan, roleName, roleName, capabilities);
// create user and assign to role
createPerson(user, true);
filePlanRoleService.assignRoleToAuthority(filePlan, roleName, user);
// create file plan structure
NodeRef rc = filePlanService.createRecordCategory(filePlan, GUID.generate());
recordFolder = recordFolderService.createRecordFolder(rc, GUID.generate());
}
public void when()
{
// give read and file permissions to user
filePlanPermissionService.setPermission(recordFolder, user, RMPermissionModel.FILING);
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
record = recordService.createRecordFromContent(recordFolder, GUID.generate(), TYPE_CONTENT, null, null);
return null;
}
}, user);
}
public void then()
{
// check the details of the record
assertTrue(recordService.isRecord(record));
}
});
}
/**
* @see
*/
public void testCreateRecordCapabilityOnlyFromFileFolderService() throws Exception
{
doBehaviourDrivenTest(new BehaviourDrivenTest()
{
/** test data */
String roleName = GUID.generate();
String user = GUID.generate();
NodeRef recordFolder;
NodeRef record;
public void given()
{
// create role
Set<Capability> capabilities = new HashSet<Capability>(2);
capabilities.add(capabilityService.getCapability("ViewRecords"));
capabilities.add(capabilityService.getCapability("CreateRecords"));
filePlanRoleService.createRole(filePlan, roleName, roleName, capabilities);
// create user and assign to role
createPerson(user, true);
filePlanRoleService.assignRoleToAuthority(filePlan, roleName, user);
// create file plan structure
NodeRef rc = filePlanService.createRecordCategory(filePlan, GUID.generate());
recordFolder = recordFolderService.createRecordFolder(rc, GUID.generate());
}
public void when()
{
// give read and file permissions to user
filePlanPermissionService.setPermission(recordFolder, user, RMPermissionModel.FILING);
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
record = fileFolderService.create(recordFolder, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef();
ContentWriter writer = contentService.getWriter(record, ContentModel.TYPE_CONTENT, true);
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.setEncoding("UTF-8");
writer.putContent("Lucy Wetherall");
return null;
}
}, user);
}
public void then()
{
// check the details of the record
assertTrue(recordService.isRecord(record));
}
});
}
}

View File

@@ -31,7 +31,8 @@ import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class) @RunWith(Suite.class)
@SuiteClasses( @SuiteClasses(
{ {
RejectRecordTest.class RejectRecordTest.class,
CreateRecordTest.class
}) })
public class RecordTestSuite public class RecordTestSuite
{ {