mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
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:
@@ -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>
|
||||||
|
@@ -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" />
|
||||||
|
@@ -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">
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -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");
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -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
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
@@ -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
|
||||||
|
@@ -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));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@@ -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
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user