Merged BRANCHES/V2.2 to HEAD:

76115: Update version to 2.1.1
   83912: Updated the Alfresco dependency from 4.2.2 to 4.2.3.1 for RM 2.2
   89173: Merged BRANCHES/v2.1.0.x to BRANCHES/v2.2:
        68559: (RECORD ONLY) Change base Alfresco version from 4.2.0-RC4 to 4.2.0
        68568: (RECORD ONLY) Merge from HEAD to BRANCHES/V2.1.0.x
        68569: (RECORD ONLY) Update module version to 2.1.0.1
        76475: (RECORD ONLY) Merge HEAD to BRANCHES/V2.1.0.x:
        76597: (RECORD ONLY) Merge HEAD to BRANCHES/V2.1.0.x:
            74932: RM-1461: CLONE - RM slower then standard repo/sites when rendering document details when folder contains 15k documents
        76598: (RECORD ONLY) Merged HEAD to BRANCHES/V2.1.0.x:
             75102: RM Performance testing
        76599: (RECORD ONLY) Update module version to 2.1.0.2
        76601: (RECORD ONLY) Merged HEAD to BRANCHES/V2.1.0.x:
             75186: RM Performance Improvements
   89251: Merge BRANCHES/V2.1.0.x to BRANCHES/V2.2:
        68559: Change base Alfresco version from 4.2.0-RC4 to 4.2.0
        68568: Merge from HEAD to BRANCHES/V2.1.0.x
        68569: Update module version to 2.1.0.1
        76475: Merge HEAD to BRANCHES/V2.1.0.x:
        76597: Merge HEAD to BRANCHES/V2.1.0.x:
            74932: RM-1461: CLONE - RM slower then standard repo/sites when rendering document details when folder contains 15k documents
        76598: Merged HEAD to BRANCHES/V2.1.0.x:
             75102: RM Performance testing
        76599: Update module version to 2.1.0.2
        76601: Merged HEAD to BRANCHES/V2.1.0.x:
             75186: RM Performance Improvements
        76673: Root container cache to improve unfiled record browse performance
            * relates to RM-1594 and RM-1595
        76850: RM performance enhancements
            * serach improvements
            * in-place record browse improvements
            * saved search via file plan browse improvements
        76851: Additional unit test to check extended security with cache is working as expected.
        76852: Rollback checked in config
        77709: RM-1630: Error on manage references page
            * regression caused by performance improvements
        84337: Update version to 2.1.0.3
        84421: Transaction level cahcing of declarative capability evaluation
        84676: Fix build
        84677: Prevent unnessary repeated creation of QName
        84678: Improvements to extended dynamic authorities
            * requiredFor set
            * direct access to extended permission information, not via service
        84679: Correct requiredFor value
        88087: RM-1661 (Performance on setting permissions at a high category level)
        88092: RM-1661 (Performance on setting permissions at a high category level)
             * Fixed failing unit tests
        88144: RM-1661 (Performance on setting permissions at a high category level)
        88182: RM-1724 (Inheritance is not off for root categories, unfiled records, holds and transfers)
        88192: RM-1661 (Performance on setting permissions at a high category level)
             * Added unit tests
        88193: RM-1661 (Performance on setting permissions at a high category level)
             * Fixed failing unit tests
        88358: RM-1661 (Performance on setting permissions at a high category level)
             * Added unit tests
        88685: RM-1742 (Locally Set Permissions for moved Record duplicate parent folder Locally Set Permissions)
        88686: RM-1741 (Moved root category doesn't inherit permissions)
        88687: RM-1741 (Moved root category doesn't inherit permissions)
             * Unit test added
        88688: RM-1742 (Locally Set Permissions for moved Record duplicate parent folder Locally Set Permissions)
             * Unit test added
        88691: RM-1745 (RM Admin role can only be added with read permission on the manage permission page)
        88772: RM-1741 (Moved root category doesn't inherit permissions)
        88860: RM-1661 (Performance on setting permissions at a high category level)
        88864: RM-1661 (Performance on setting permissions at a high category level)
             * Fixed failing unit tests
        88959: RM-1746 (Moved record/category always have the inheritance on)
        88960: RM-1661 (Performance on setting permissions at a high category level)
             * Fixed failing unit tests
        88961: RM-1661 (Performance on setting permissions at a high category level)
             * Fixed failing unit tests
        88962: RM-1661 (Performance on setting permissions at a high category level)
             * Fixed failing unit tests
   89252: Added missing test
   89253: Removed warnings
   89348: RM-1751 (Merge performance improvements made for RM 2.1.0.3 onto RM 2.2.1)
   89455: RM-1751 (Merge performance improvements made for RM 2.1.0.3 onto RM 2.2.1)

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@89458 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Tuna Aksoy
2014-10-29 22:40:00 +00:00
45 changed files with 2180 additions and 1060 deletions

View File

@@ -134,6 +134,9 @@
<ref bean="extendedReaderDynamicAuthority" /> <ref bean="extendedReaderDynamicAuthority" />
</list> </list>
</property> </property>
<property name="filePlanService">
<ref bean="filePlanService" />
</property>
</bean> </bean>
<bean id="extendedReaderDynamicAuthority" class="org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority" /> <bean id="extendedReaderDynamicAuthority" class="org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority" />
@@ -229,20 +232,17 @@
<property name="dictionaryService" ref="dictionaryService"/> <property name="dictionaryService" ref="dictionaryService"/>
<property name="policyComponent" ref="policyComponent"/> <property name="policyComponent" ref="policyComponent"/>
<property name="permissionService" ref="permissionService"/> <property name="permissionService" ref="permissionService"/>
<property name="nodeRulesCache" ref="nodeRulesCache"/> <property name="nodeRulesCache" ref="nodeRulesCache"/>
<property name="rulesDisabled"> <property name="rulesDisabled">
<value>false</value> <value>false</value>
</property> </property>
<!-- Since RM 2.1 -->
<!-- Since RM 2.1 --> <property name="filePlanService" ref="FilePlanService" />
<property name="filePlanService" ref="FilePlanService" /> <property name="runAsAdmin">
<property name="runAsAdmin"> <value>${rm.rule.runasadmin}</value>
<value>${rm.rule.runasadmin}</value> </property>
</property>
<property name="recordService" ref="RecordService" /> <property name="recordService" ref="RecordService" />
</bean>
</bean>
<bean id="FormService_security" class="org.alfresco.module.org_alfresco_module_rm.security.RMMethodSecurityInterceptor"> <bean id="FormService_security" class="org.alfresco.module.org_alfresco_module_rm.security.RMMethodSecurityInterceptor">
<property name="authenticationManager"><ref bean="authenticationManager"/></property> <property name="authenticationManager"><ref bean="authenticationManager"/></property>

View File

@@ -16,7 +16,7 @@ log4j.logger.org.alfresco.module.org_alfresco_module_rm.patch=info
log4j.logger.org.alfresco.module.org_alfresco_module_rm.security.RMMethodSecurityInterceptor=debug log4j.logger.org.alfresco.module.org_alfresco_module_rm.security.RMMethodSecurityInterceptor=debug
# #
# RM permission debug # RM permission debug
# #
#log4j.logger.org.alfresco.module.org_alfresco_module_rm.capability.RMEntryVoter=debug #log4j.logger.org.alfresco.module.org_alfresco_module_rm.capability.RMEntryVoter=debug
#log4j.logger.org.alfresco.module.org_alfresco_module_rm.capability.RMAfterInvocationProvider=debug #log4j.logger.org.alfresco.module.org_alfresco_module_rm.capability.RMAfterInvocationProvider=debug
@@ -46,4 +46,13 @@ log4j.logger.org.alfresco.module.org_alfresco_module_rm.behaviour.BaseBehaviourB
# #
# Patch debug # Patch debug
# #
log4j.logger.org.alfresco.module.org_alfresco_module_rm.patch=info log4j.logger.org.alfresco.module.org_alfresco_module_rm.patch=info
#
# RM Audit service debug
#
#log4j.logger.org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditService=debug
#
# Job debug
#
#log4j.logger.org.alfresco.module.org_alfresco_module_rm.job=debug

View File

@@ -45,7 +45,7 @@
<bean id="RMSecurityCommon" abstract="true"> <bean id="RMSecurityCommon" abstract="true">
<property name="nodeService" ref="nodeService"/> <property name="nodeService" ref="nodeService"/>
<property name="permissionService" ref="permissionService"/> <property name="permissionService" ref="permissionServiceImpl"/>
<property name="caveatConfigComponent" ref="caveatConfigComponent"/> <property name="caveatConfigComponent" ref="caveatConfigComponent"/>
</bean> </bean>

View File

@@ -378,11 +378,12 @@
<!-- File Plan Service --> <!-- File Plan Service -->
<bean id="filePlanService" <bean id="rootContainerCache" class="org.alfresco.repo.cache.DefaultSimpleCache" />
parent="baseService"
<bean id="filePlanService"
parent="baseService"
class="org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanServiceImpl"> class="org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanServiceImpl">
<property name="nodeDAO" ref="nodeDAO"/> <property name="rootContainerCache" ref="rootContainerCache" />
<property name="filePlanPermissionService" ref="FilePlanPermissionService" />
</bean> </bean>
<bean id="FilePlanService" class="org.springframework.aop.framework.ProxyFactoryBean"> <bean id="FilePlanService" class="org.springframework.aop.framework.ProxyFactoryBean">
@@ -444,6 +445,7 @@
<property name="permissionService" ref="PermissionService"/> <property name="permissionService" ref="PermissionService"/>
<property name="policyComponent" ref="policyComponent"/> <property name="policyComponent" ref="policyComponent"/>
<property name="ownableService" ref="ownableService" /> <property name="ownableService" ref="ownableService" />
<property name="authorityService" ref="AuthorityService" />
</bean> </bean>
<bean id="FilePlanPermissionService" class="org.springframework.aop.framework.ProxyFactoryBean"> <bean id="FilePlanPermissionService" class="org.springframework.aop.framework.ProxyFactoryBean">

View File

@@ -399,6 +399,7 @@
<property name="kinds"> <property name="kinds">
<set> <set>
<value>FILE_PLAN</value> <value>FILE_PLAN</value>
<value>RECORD</value>
<value>RECORD_CATEGORY</value> <value>RECORD_CATEGORY</value>
<value>RECORD_FOLDER</value> <value>RECORD_FOLDER</value>
<value>UNFILED_RECORD_CONTAINER</value> <value>UNFILED_RECORD_CONTAINER</value>

View File

@@ -1,9 +0,0 @@
<webscript>
<shortname>Records Management Permissions</shortname>
<description>Retrieve the Permissions set against a Records Management node.</description>
<url>/api/node/{store_type}/{store_id}/{id}/rmpermissions</url>
<format default="json">argument</format>
<authentication>user</authentication>
<transaction allow="readonly">required</transaction>
<lifecycle>internal</lifecycle>
</webscript>

View File

@@ -1,86 +0,0 @@
/**
* Entry point for rmpermissions GET data webscript.
* Queries the permissions from an RM node and constructs the data-model for the template.
*
* @method main
*/
function main()
{
// Get the node from the URL
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
var node = search.findNode(pathSegments[2], reference);
// 404 if the node is not found
if (node == null)
{
status.setCode(status.STATUS_NOT_FOUND, "The node could not be found");
return;
}
// retrieve permissions applied to this node
var permissions = node.getFullPermissions();
// split tokens - results are in the format:
// [ALLOWED|DENIED];[USERNAME|GROUPNAME];PERMISSION;[INHERITED|DIRECT]
var result = [];
for (var i=0; i<permissions.length; i++)
{
var tokens = permissions[i].split(";");
if (tokens[0] == "ALLOWED")
{
// we are only interested in the RM specific object level permissions
// Filing and ReadRecords
var id = tokens[2];
switch (id)
{
case "Filing":
case "ReadRecords":
{
var auth = null;
var authId = tokens[1];
var displayName;
if (authId.indexOf("GROUP_") === 0)
{
auth = groups.getGroupForFullAuthorityName(authId);
if (auth != null)
{
displayName = auth.displayName;
}
}
else
{
auth = people.getPerson(authId);
if (auth != null)
{
displayName = auth.properties.firstName + " " + auth.properties.lastName;
}
}
// check for null authority - this could happen if a group is removed
// from the system or similar and should be handled here
if (auth != null)
{
result.push(
{
id: id,
authority:
{
id: authId,
label: displayName
},
inherited: (tokens[3] == "INHERITED")
}
);
}
}
}
}
}
// apply result data-model
model.permissions = result;
model.inherited = node.inheritsPermissions();
}
main();

View File

@@ -1,22 +0,0 @@
<#escape x as jsonUtils.encodeJSONString(x)>
{
"data":
{
"permissions":
[
<#list permissions as perm>
{
"id": "${perm.id}",
"authority":
{
"id": "${perm.authority.id}",
"label": "${perm.authority.label}"
},
"inherited": ${perm.inherited?string}
}<#if perm_has_next>,</#if>
</#list>
],
"inherited": ${inherited?string}
}
}
</#escape>

View File

@@ -1,7 +1,7 @@
/** /**
* Entry point for rmpermissions POST data webscript. * Entry point for rmpermissions POST data webscript.
* Applies supplied RM permissions to an RM node. * Applies supplied RM permissions to an RM node.
* *
* @method main * @method main
*/ */
function main() function main()
@@ -10,41 +10,46 @@ function main()
var pathSegments = url.match.split("/"); var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/")); var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
var node = search.findNode(pathSegments[2], reference); var node = search.findNode(pathSegments[2], reference);
// 404 if the node is not found // 404 if the node is not found
if (node == null) if (node == null)
{ {
status.setCode(status.STATUS_NOT_FOUND, "The node could not be found"); status.setCode(status.STATUS_NOT_FOUND, "The node could not be found");
return; return;
} }
if (json.has("permissions") == false) if (json.has("permissions") == false)
{ {
status.setCode(status.STATUS_BAD_REQUEST, "Permissions value missing from request."); status.setCode(status.STATUS_BAD_REQUEST, "Permissions value missing from request.");
} }
if (json.has("isInherited"))
{
node.setInheritsPermissions(json.getBoolean("isInherited"));
}
var permissions = json.getJSONArray("permissions"); var permissions = json.getJSONArray("permissions");
for (var i=0; i<permissions.length(); i++) for (var i=0; i<permissions.length(); i++)
{ {
var p = permissions.getJSONObject(i); var p = permissions.getJSONObject(i);
// collect values for the permission setting // collect values for the permission setting
var id = p.getString("id"); var role = p.getString("role");
var authority = p.getString("authority"); var authority = p.getString("authority");
var remove = false; var remove = false;
if (p.has("remove")) if (p.has("remove"))
{ {
remove = p.getBoolean("remove"); remove = p.getBoolean("remove");
} }
// apply or remove permission // apply or remove permission
if (remove) if (remove)
{ {
rmService.deletePermission(node, id, authority); rmService.deletePermission(node, role, authority);
} }
else else
{ {
rmService.setPermission(node, id, authority); rmService.setPermission(node, role, authority);
} }
} }
} }

View File

@@ -19,6 +19,7 @@
package org.alfresco.module.org_alfresco_module_rm.capability; package org.alfresco.module.org_alfresco_module_rm.capability;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference; import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
/** /**
@@ -34,13 +35,32 @@ public interface RMPermissionModel
String FILE_RECORDS = "FileRecords"; String FILE_RECORDS = "FileRecords";
// Roles // Roles
String ROLE_NAME_USER = "User"; /**
String ROLE_NAME_POWER_USER = "PowerUser"; * @deprecated as of 2.1.0.3, please use {@link FilePlanRoleService.ROLE_USER} instead
String ROLE_NAME_SECURITY_OFFICER = "SecurityOfficer"; */
String ROLE_NAME_RECORDS_MANAGER = "RecordsManager"; @Deprecated
public static final String ROLE_NAME_USER = FilePlanRoleService.ROLE_USER;
String ROLE_NAME_ADMINISTRATOR = "Administrator"; /**
String ROLE_ADMINISTRATOR = SimplePermissionReference.getPermissionReference(RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT, ROLE_NAME_ADMINISTRATOR).toString(); * @deprecated as of 2.1.0.3, please use {@link FilePlanRoleService.ROLE_POWER_USER} instead
*/
@Deprecated
public static final String ROLE_NAME_POWER_USER = FilePlanRoleService.ROLE_POWER_USER;
/**
* @deprecated as of 2.1.0.3, please use {@link FilePlanRoleService.ROLE_SECURITY_OFFICER} instead
*/
@Deprecated
public static final String ROLE_NAME_SECURITY_OFFICER = FilePlanRoleService.ROLE_SECURITY_OFFICER;
/**
* @deprecated as of 2.1.0.3, please use {@link FilePlanRoleService.ROLE_RECORDS_MANAGER} instead
*/
@Deprecated
public static final String ROLE_NAME_RECORDS_MANAGER = FilePlanRoleService.ROLE_RECORDS_MANAGER;
/**
* @deprecated as of 2.1.0.3, please use {@link FilePlanRoleService.ROLE_ADMIN} instead
*/
@Deprecated
public static final String ROLE_NAME_ADMINISTRATOR = FilePlanRoleService.ROLE_ADMIN;
public static final String ROLE_ADMINISTRATOR = SimplePermissionReference.getPermissionReference(RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT, FilePlanRoleService.ROLE_ADMIN).toString();
// Capability permissions // Capability permissions

View File

@@ -18,14 +18,16 @@
*/ */
package org.alfresco.module.org_alfresco_module_rm.capability; package org.alfresco.module.org_alfresco_module_rm.capability;
import java.util.Map;
import net.sf.acegisecurity.vote.AccessDecisionVoter; import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.alfresco.module.org_alfresco_module_rm.caveat.RMCaveatConfigComponent; import org.alfresco.module.org_alfresco_module_rm.caveat.RMCaveatConfigComponent;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; 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.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.security.RMMethodSecurityInterceptor;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.TransactionalResourceHelper;
import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -33,6 +35,7 @@ import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.util.Pair;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -201,54 +204,82 @@ public class RMSecurityCommon implements ApplicationContextAware
} }
/** /**
* Core RM read check
* *
* @param nodeRef * @param nodeRef node reference
* @return * @return int see {@link AccessDecisionVoter}
*/ */
public int checkRmRead(NodeRef nodeRef) public int checkRmRead(NodeRef nodeRef)
{ {
int result = getTransactionCache("checkRmRead", nodeRef); int result = AccessDecisionVoter.ACCESS_ABSTAIN;
if (result != NOSET_VALUE)
{
return result;
}
if (permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS) == AccessStatus.DENIED) Map<Pair<String, NodeRef>, Integer> transactionCache = TransactionalResourceHelper.getMap("rm.security.checkRMRead");
{ Pair<String, NodeRef> key = new Pair<String, NodeRef>(AuthenticationUtil.getRunAsUser(), nodeRef);
// log message
RMMethodSecurityInterceptor.addMessage("User does not have read record permission on node, access denied. (nodeRef={0}, user={1})", nodeRef, AuthenticationUtil.getRunAsUser());
if (logger.isDebugEnabled()) if (transactionCache.containsKey(key))
{ {
logger.debug("\t\tUser does not have read record permission on node, access denied. (nodeRef=" + nodeRef.toString() + ", user=" + AuthenticationUtil.getRunAsUser() + ")"); result = transactionCache.get(key);
} }
else
{
if (permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS) == AccessStatus.DENIED)
{
if (logger.isDebugEnabled())
{
logger.debug("\t\tUser does not have read record permission on node, access denied. (nodeRef=" + nodeRef.toString() + ", user=" + AuthenticationUtil.getRunAsUser() + ")");
}
result = AccessDecisionVoter.ACCESS_DENIED;
}
else
{
// Get the file plan for the node
NodeRef filePlan = getFilePlanService().getFilePlan(nodeRef);
if (hasViewCapability(filePlan) == AccessStatus.DENIED)
{
if (logger.isDebugEnabled())
{
logger.debug("\t\tUser does not have view records capability permission on node, access denied. (filePlan=" + filePlan.toString() + ", user=" + AuthenticationUtil.getRunAsUser() + ")");
}
result = AccessDecisionVoter.ACCESS_DENIED;
}
else if (!caveatConfigComponent.hasAccess(nodeRef))
{
result = AccessDecisionVoter.ACCESS_DENIED;
}
else
{
result = AccessDecisionVoter.ACCESS_GRANTED;
}
}
return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_DENIED); // cache result
} transactionCache.put(key, result);
}
// Get the file plan for the node
NodeRef filePlan = getFilePlanService().getFilePlan(nodeRef);
if (permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS) == AccessStatus.DENIED)
{
// log capability details
RMMethodSecurityInterceptor.reportCapabilityStatus(RMPermissionModel.VIEW_RECORDS, AccessDecisionVoter.ACCESS_DENIED);
if (logger.isDebugEnabled()) return result;
{ }
logger.debug("\t\tUser does not have view records capability permission on node, access denied. (filePlan=" + filePlan.toString() + ", user=" + AuthenticationUtil.getRunAsUser() + ")");
}
return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_DENIED);
}
if (caveatConfigComponent.hasAccess(nodeRef)) /**
{ * Helper method to determine whether the current user has view capability on the file plan
return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_GRANTED); *
} * @param filePlan file plan
else * @return {@link AccessStatus}
{ */
return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_DENIED); private AccessStatus hasViewCapability(NodeRef filePlan)
} {
Map<Pair<String, NodeRef>, AccessStatus> transactionCache = TransactionalResourceHelper.getMap("rm.security.hasViewCapability");
Pair<String, NodeRef> key = new Pair<String, NodeRef>(AuthenticationUtil.getRunAsUser(), filePlan);
if (transactionCache.containsKey(key))
{
return transactionCache.get(key);
}
else
{
AccessStatus result = permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS);
transactionCache.put(key, result);
return result;
}
} }
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")

View File

@@ -30,6 +30,8 @@ import org.alfresco.module.org_alfresco_module_rm.capability.AbstractCapability;
import org.alfresco.module.org_alfresco_module_rm.capability.Capability; import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanComponentKind; import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanComponentKind;
import org.alfresco.module.org_alfresco_module_rm.security.RMMethodSecurityInterceptor; import org.alfresco.module.org_alfresco_module_rm.security.RMMethodSecurityInterceptor;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.TransactionalResourceHelper;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AccessStatus;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@@ -289,29 +291,41 @@ public class DeclarativeCapability extends AbstractCapability
{ {
int result = AccessDecisionVoter.ACCESS_ABSTAIN; int result = AccessDecisionVoter.ACCESS_ABSTAIN;
// Check we are dealing with a file plan component // check transaction cache
if (getFilePlanService().isFilePlanComponent(nodeRef)) Map<String, Integer> map = TransactionalResourceHelper.getMap("rm.declarativeCapability");
String key = getName() + "|" + nodeRef.toString() + "|" + AuthenticationUtil.getRunAsUser();
if (map.containsKey(key))
{ {
// Check the kind of the object, the permissions and the conditions result = map.get(key);
if (checkKinds(nodeRef) && checkPermissions(nodeRef) && checkConditions(nodeRef))
{
// Opportunity for child implementations to extend
result = evaluateImpl(nodeRef);
}
else
{
result = AccessDecisionVoter.ACCESS_DENIED;
}
} }
else
// Last chance for child implementations to veto/change the result
result = onEvaluate(nodeRef, result);
// log access denied to help with debug
if (LOGGER.isDebugEnabled() && AccessDecisionVoter.ACCESS_DENIED == result)
{ {
LOGGER.debug("FAIL: Capability " + getName() + " returned an Access Denied result during evaluation of node " + nodeRef.toString()); // Check we are dealing with a file plan component
} if (getFilePlanService().isFilePlanComponent(nodeRef) == true)
{
// Check the kind of the object, the permissions and the conditions
if (checkKinds(nodeRef) == true && checkPermissions(nodeRef) == true && checkConditions(nodeRef) == true)
{
// Opportunity for child implementations to extend
result = evaluateImpl(nodeRef);
}
else
{
result = AccessDecisionVoter.ACCESS_DENIED;
}
}
// Last chance for child implementations to veto/change the result
result = onEvaluate(nodeRef, result);
// log access denied to help with debug
if (LOGGER.isDebugEnabled() == true && AccessDecisionVoter.ACCESS_DENIED == result)
{
LOGGER.debug("Capability " + getName() + " returned an Access Denied result during evaluation of node " + nodeRef.toString());
}
map.put(key, result);
}
return result; return result;
} }

View File

@@ -43,6 +43,11 @@ public class AtLeastOneCondition extends AbstractCapabilityCondition
this.conditions = conditions; this.conditions = conditions;
} }
/**
* Don't use the transaction cache for the composite condition
*
* @see org.alfresco.module.org_alfresco_module_rm.capability.declarative.AbstractCapabilityCondition#evaluate(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override @Override
public boolean evaluate(NodeRef nodeRef) public boolean evaluate(NodeRef nodeRef)
{ {

View File

@@ -34,6 +34,7 @@ public class IsPropertySetCondition extends AbstractCapabilityCondition
{ {
/** property name (eg: rma:location) */ /** property name (eg: rma:location) */
private String propertyName; private String propertyName;
private QName propertyQName;
/** namespace service */ /** namespace service */
private NamespaceService namespaceService; private NamespaceService namespaceService;
@@ -59,7 +60,11 @@ public class IsPropertySetCondition extends AbstractCapabilityCondition
*/ */
protected QName getPropertyQName() protected QName getPropertyQName()
{ {
return QName.createQName(propertyName, namespaceService); if (propertyQName == null)
{
propertyQName = QName.createQName(propertyName, namespaceService);
}
return propertyQName;
} }
/** /**

View File

@@ -30,12 +30,18 @@ import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionService; 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.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl; import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.domain.node.NodeDAO; import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
@@ -52,7 +58,8 @@ import org.springframework.extensions.surf.util.I18NUtil;
* @since 2.1 * @since 2.1
*/ */
public class FilePlanServiceImpl extends ServiceBaseImpl public class FilePlanServiceImpl extends ServiceBaseImpl
implements FilePlanService implements FilePlanService,
RecordsManagementModel
{ {
/** I18N */ /** I18N */
private static final String MSG_DUP_ROOT = "rm.service.dup-root"; private static final String MSG_DUP_ROOT = "rm.service.dup-root";
@@ -72,34 +79,75 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
/** RM site file plan container */ /** RM site file plan container */
private static final String FILE_PLAN_CONTAINER = "documentLibrary"; private static final String FILE_PLAN_CONTAINER = "documentLibrary";
/** node DAO */ /** root container cache */
private SimpleCache<Pair<NodeRef, String>, NodeRef> rootContainerCache;
/** File plan role service */
private FilePlanRoleService filePlanRoleService;
/** Permission service */
private PermissionService permissionService;
/** Node DAO */
private NodeDAO nodeDAO; private NodeDAO nodeDAO;
/** file plan permission service */ /** Site service */
private FilePlanPermissionService filePlanPermissionService; private SiteService siteService;
/** /**
* @param nodeDAO node DAO * Gets the file plan role service
*
* @return The file plan role service
*/ */
public void setNodeDAO(NodeDAO nodeDAO) public FilePlanRoleService getFilePlanRoleService()
{ {
this.nodeDAO = nodeDAO; if (filePlanRoleService == null)
{
filePlanRoleService = (FilePlanRoleService) applicationContext.getBean("FilePlanRoleService");
}
return filePlanRoleService;
} }
/** /**
* @return site service * Gets the permission service
*
* @return The permission service
*/ */
protected SiteService getSiteService() public PermissionService getPermissionService()
{ {
return (SiteService)applicationContext.getBean("siteService"); if (permissionService == null)
{
permissionService = (PermissionService) applicationContext.getBean("permissionService");
}
return permissionService;
} }
/** /**
* @param filePlanPermissionService file plan permission service * Gets the node DAO
*
* @return The node DAO
*/ */
public void setFilePlanPermissionService(FilePlanPermissionService filePlanPermissionService) public NodeDAO getNodeDAO()
{ {
this.filePlanPermissionService = filePlanPermissionService; if (nodeDAO == null)
{
nodeDAO = (NodeDAO) applicationContext.getBean("nodeDAO");
}
return nodeDAO;
}
/**
* Gets the site service
*
* @return The site service
*/
public SiteService getSiteService()
{
if (siteService == null)
{
siteService = (SiteService) applicationContext.getBean("SiteService");
}
return siteService;
} }
/** /**
@@ -111,6 +159,14 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
return getFilePlans(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); return getFilePlans(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
} }
/**
* @param rootContainerCache root container cache
*/
public void setRootContainerCache(SimpleCache<Pair<NodeRef, String>, NodeRef> rootContainerCache)
{
this.rootContainerCache = rootContainerCache;
}
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService#getFilePlans(org.alfresco.service.cmr.repository.StoreRef) * @see org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService#getFilePlans(org.alfresco.service.cmr.repository.StoreRef)
*/ */
@@ -122,7 +178,7 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
final Set<NodeRef> results = new HashSet<NodeRef>(); final Set<NodeRef> results = new HashSet<NodeRef>();
Set<QName> aspects = new HashSet<QName>(1); Set<QName> aspects = new HashSet<QName>(1);
aspects.add(ASPECT_RECORDS_MANAGEMENT_ROOT); aspects.add(ASPECT_RECORDS_MANAGEMENT_ROOT);
nodeDAO.getNodesWithAspects(aspects, Long.MIN_VALUE, Long.MAX_VALUE, new NodeDAO.NodeRefQueryCallback() getNodeDAO().getNodesWithAspects(aspects, Long.MIN_VALUE, Long.MAX_VALUE, new NodeDAO.NodeRefQueryCallback()
{ {
@Override @Override
public boolean handle(Pair<Long, NodeRef> nodePair) public boolean handle(Pair<Long, NodeRef> nodePair)
@@ -146,12 +202,11 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
public NodeRef getFilePlanBySiteId(String siteId) public NodeRef getFilePlanBySiteId(String siteId)
{ {
NodeRef filePlan = null; NodeRef filePlan = null;
SiteService siteService = getSiteService();
SiteInfo siteInfo = siteService.getSite(siteId); SiteInfo siteInfo = getSiteService().getSite(siteId);
if (siteInfo != null && siteService.hasContainer(siteId, FILE_PLAN_CONTAINER)) if (siteInfo != null && getSiteService().hasContainer(siteId, FILE_PLAN_CONTAINER))
{ {
NodeRef nodeRef = siteService.getContainer(siteId, FILE_PLAN_CONTAINER); NodeRef nodeRef = getSiteService().getContainer(siteId, FILE_PLAN_CONTAINER);
if (instanceOf(nodeRef, TYPE_FILE_PLAN)) if (instanceOf(nodeRef, TYPE_FILE_PLAN))
{ {
filePlan = nodeRef; filePlan = nodeRef;
@@ -198,10 +253,11 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
} }
/** /**
* Get the file root container for the given type.
* *
* @param filePlan * @param filePlan file plan
* @param containerName * @param containerName container type
* @return * @return {@link NodeRef} file plan container
*/ */
private NodeRef getFilePlanRootContainer(NodeRef filePlan, String containerName) private NodeRef getFilePlanRootContainer(NodeRef filePlan, String containerName)
{ {
@@ -212,16 +268,25 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
} }
NodeRef result = null; NodeRef result = null;
Pair<NodeRef, String> key = new Pair<NodeRef, String>(filePlan, containerName);
// try and get the unfiled record container if (!rootContainerCache.contains(key))
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(filePlan, ContentModel.ASSOC_CONTAINS, QName.createQName(RM_URI, containerName));
if (assocs.size() > 1)
{ {
throw new AlfrescoRuntimeException("Unable to get unfiled conatiner " + containerName + "."); // try and get the unfiled record container
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(filePlan, ContentModel.ASSOC_CONTAINS, QName.createQName(RM_URI, containerName));
if (assocs.size() > 1)
{
throw new AlfrescoRuntimeException("Unable to get unfiled conatiner " + containerName + ".");
}
else if (assocs.size() == 1)
{
result = assocs.get(0).getChildRef();
rootContainerCache.put(key, result);
}
} }
else if (assocs.size() == 1) else
{ {
result = assocs.get(0).getChildRef(); result = rootContainerCache.get(key);
} }
return result; return result;
@@ -269,6 +334,8 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
throw new AlfrescoRuntimeException("Unable to create file plan root container, because passed node is not a file plan."); throw new AlfrescoRuntimeException("Unable to create file plan root container, because passed node is not a file plan.");
} }
String allRoles = getFilePlanRoleService().getAllRolesContainerGroup(filePlan);
// create the properties map // create the properties map
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(1); Map<QName, Serializable> properties = new HashMap<QName, Serializable>(1);
properties.put(ContentModel.PROP_NAME, containerName); properties.put(ContentModel.PROP_NAME, containerName);
@@ -281,8 +348,23 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
containerType, containerType,
properties).getChildRef(); properties).getChildRef();
// setup the permissions // if (inheritPermissions == false)
filePlanPermissionService.setupPermissions(filePlan, container); // {
// set inheritance to false
getPermissionService().setInheritParentPermissions(container, false);
getPermissionService().setPermission(container, allRoles, RMPermissionModel.READ_RECORDS, true);
getPermissionService().setPermission(container, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true);
getPermissionService().setPermission(container, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true);
// TODO set the admin users to have filing permissions on the unfiled container!!!
// TODO we will need to be able to get a list of the admin roles from the service
// }
// else
// {
// just inherit eveything
// TODO will change this when we are able to set permissions on holds and transfers!
// getPermissionService().setInheritParentPermissions(container, true);
// }
return container; return container;
} }

View File

@@ -38,7 +38,6 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
@@ -107,109 +106,6 @@ public class FreezeServiceImpl extends ServiceBaseImpl
return nodeService.hasAspect(nodeRef, ASPECT_FROZEN); return nodeService.hasAspect(nodeRef, ASPECT_FROZEN);
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#hasFrozenChildren(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public boolean hasFrozenChildren(final NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
boolean result = false;
// check that we are dealing with a record folder
if (isRecordFolder(nodeRef))
{
int heldCount = 0;
if (nodeService.hasAspect(nodeRef, ASPECT_HELD_CHILDREN))
{
heldCount = (Integer)getInternalNodeService().getProperty(nodeRef, PROP_HELD_CHILDREN_COUNT);
}
else
{
final TransactionService transactionService = (TransactionService)applicationContext.getBean("transactionService");
heldCount = AuthenticationUtil.runAsSystem(new RunAsWork<Integer>()
{
@Override
public Integer doWork()
{
return transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Integer>()
{
public Integer execute() throws Throwable
{
int heldCount = 0;
// NOTE: this process remains to 'patch' older systems to improve performance next time around
List<ChildAssociationRef> childAssocs = getInternalNodeService().getChildAssocs(nodeRef, ContentModel.ASSOC_CONTAINS,
RegexQNamePattern.MATCH_ALL);
if (childAssocs != null && !childAssocs.isEmpty())
{
for (ChildAssociationRef childAssociationRef : childAssocs)
{
NodeRef record = childAssociationRef.getChildRef();
if (childAssociationRef.isPrimary() && isRecord(record) && isFrozen(record))
{
heldCount ++;
}
}
}
// add aspect and set count
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1);
props.put(PROP_HELD_CHILDREN_COUNT, heldCount);
getInternalNodeService().addAspect(nodeRef, ASPECT_HELD_CHILDREN, props);
return heldCount;
}
},
false, true);
}
});
}
// true if more than one child held
result = (heldCount > 0);
}
return result;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#getFreezeDate(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public Date getFreezeDate(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
if (isFrozen(nodeRef))
{
Serializable property = nodeService.getProperty(nodeRef, PROP_FROZEN_AT);
if (property != null) { return (Date) property; }
}
return null;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#getFreezeInitiator(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public String getFreezeInitiator(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
if (isFrozen(nodeRef))
{
Serializable property = nodeService.getProperty(nodeRef, PROP_FROZEN_BY);
if (property != null) { return (String) property; }
}
return null;
}
/** /**
* Deprecated Method Implementations * Deprecated Method Implementations
*/ */
@@ -357,6 +253,112 @@ public class FreezeServiceImpl extends ServiceBaseImpl
return new HashSet<NodeRef>(getHoldService().getHolds(filePlan)); return new HashSet<NodeRef>(getHoldService().getHolds(filePlan));
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#hasFrozenChildren(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public boolean hasFrozenChildren(final NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
boolean result = false;
// check that we are dealing with a record folder
if (isRecordFolder(nodeRef))
{
int heldCount = 0;
if (nodeService.hasAspect(nodeRef, ASPECT_HELD_CHILDREN))
{
heldCount = (Integer)getInternalNodeService().getProperty(nodeRef, PROP_HELD_CHILDREN_COUNT);
}
else
{
final TransactionService transactionService = (TransactionService)applicationContext.getBean("transactionService");
heldCount = AuthenticationUtil.runAsSystem(new RunAsWork<Integer>()
{
@Override
public Integer doWork()
{
return transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Integer>()
{
public Integer execute() throws Throwable
{
int heldCount = 0;
// NOTE: this process remains to 'patch' older systems to improve performance next time around
List<ChildAssociationRef> childAssocs = getInternalNodeService().getChildAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, null);
if (childAssocs != null && !childAssocs.isEmpty())
{
for (ChildAssociationRef childAssociationRef : childAssocs)
{
NodeRef record = childAssociationRef.getChildRef();
if (childAssociationRef.isPrimary() && isRecord(record) && isFrozen(record))
{
heldCount ++;
}
}
}
// add aspect and set count
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1);
props.put(PROP_HELD_CHILDREN_COUNT, heldCount);
getInternalNodeService().addAspect(nodeRef, ASPECT_HELD_CHILDREN, props);
return heldCount;
}
},
false, true);
}
});
}
// true if more than one child held
result = (heldCount > 0);
}
return result;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#getFreezeDate(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public Date getFreezeDate(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
if (isFrozen(nodeRef))
{
Serializable property = nodeService.getProperty(nodeRef, PROP_FROZEN_AT);
if (property != null) { return (Date) property; }
}
return null;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#getFreezeInitiator(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public String getFreezeInitiator(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
if (isFrozen(nodeRef))
{
Serializable property = nodeService.getProperty(nodeRef, PROP_FROZEN_BY);
if (property != null) { return (String) property; }
}
return null;
}
/**
* Helper Methods
*/
/** /**
* Creates a hold using the given nodeRef and reason * Creates a hold using the given nodeRef and reason
* *

View File

@@ -262,7 +262,7 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel
// @since 2.2 // @since 2.2
QName ASPECT_HELD_CHILDREN = QName.createQName(RM_URI, "heldChildren"); QName ASPECT_HELD_CHILDREN = QName.createQName(RM_URI, "heldChildren");
QName PROP_HELD_CHILDREN_COUNT = QName.createQName(RM_URI, "heldChildrenCount"); QName PROP_HELD_CHILDREN_COUNT = QName.createQName(RM_URI, "heldChildrenCount");
// Countable aspect // Countable aspect
QName ASPECT_COUNTABLE = QName.createQName(RM_URI, "countable"); QName ASPECT_COUNTABLE = QName.createQName(RM_URI, "countable");
QName PROP_COUNT = QName.createQName(RM_URI, "count"); QName PROP_COUNT = QName.createQName(RM_URI, "count");

View File

@@ -68,7 +68,7 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService,
/** Location of bootstrap role JSON */ /** Location of bootstrap role JSON */
private static final String BOOTSTRAP_ROLE_JSON_LOCATION = "alfresco/module/org_alfresco_module_rm/security/rm-default-roles-bootstrap.json"; private static final String BOOTSTRAP_ROLE_JSON_LOCATION = "alfresco/module/org_alfresco_module_rm/security/rm-default-roles-bootstrap.json";
/** JSON names */ /** JSON names */
private static final String JSON_NAME = "name"; private static final String JSON_NAME = "name";
private static final String JSON_DISPLAY_LABEL = "displayLabel"; private static final String JSON_DISPLAY_LABEL = "displayLabel";
@@ -242,7 +242,7 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService,
/** /**
* Bootstraps the default roles * Bootstraps the default roles
* *
* @param filePlan file plan * @param filePlan file plan
* @param systemContainers system containers * @param systemContainers system containers
*/ */
@@ -327,7 +327,7 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService,
// Add any additional admin permissions // Add any additional admin permissions
if (isAdmin) if (isAdmin)
{ {
// Admin has filing // Admin has filing
permissionService.setPermission(filePlan, role.getRoleGroupName(), RMPermissionModel.FILING, true); permissionService.setPermission(filePlan, role.getRoleGroupName(), RMPermissionModel.FILING, true);
if (systemContainers != null) if (systemContainers != null)

View File

@@ -33,9 +33,7 @@ import org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearch
import org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService; import org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService;
import org.alfresco.module.org_alfresco_module_rm.search.SavedSearchDetailsCompatibility; import org.alfresco.module.org_alfresco_module_rm.search.SavedSearchDetailsCompatibility;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
@@ -44,6 +42,7 @@ import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.extensions.webscripts.Cache; import org.springframework.extensions.webscripts.Cache;
@@ -199,20 +198,20 @@ public class RMSearchGet extends DeclarativeWebScript
} }
// Execute search // Execute search
List<NodeRef> results = recordsManagementSearchService.search(siteId, query, searchParameters); List<Pair<NodeRef, NodeRef>> results = recordsManagementSearchService.search(siteId, query, searchParameters);
// Reset person data cache // Reset person data cache
personDataCache = new HashMap<String, String>(57); personDataCache = new HashMap<String, String>(57);
// Process the result items // Process the result items
List<Item> items = new ArrayList<Item>(results.size()); List<Item> items = new ArrayList<Item>(results.size());
for (NodeRef nodeRef : results) for (Pair<NodeRef, NodeRef> pair : results)
{ {
// FIXME: See RM-478 // FIXME: See RM-478
// TC 3-3 Create User Groups // TC 3-3 Create User Groups
try try
{ {
Item item = new Item(nodeRef); Item item = new Item(pair.getFirst(), pair.getSecond());
items.add(item); items.add(item);
} }
catch(Exception e) {} catch(Exception e) {}
@@ -245,7 +244,7 @@ public class RMSearchGet extends DeclarativeWebScript
private Map<QName, Serializable> nodeProperties; private Map<QName, Serializable> nodeProperties;
private Map<String, Serializable> properties; private Map<String, Serializable> properties;
public Item(NodeRef nodeRef) public Item(NodeRef parent, NodeRef nodeRef)
{ {
// Set node ref // Set node ref
this.nodeRef = nodeRef; this.nodeRef = nodeRef;
@@ -265,12 +264,12 @@ public class RMSearchGet extends DeclarativeWebScript
} }
// Get parent node reference // Get parent node reference
NodeRef parent = null; // NodeRef parent = null;
ChildAssociationRef assoc = nodeService.getPrimaryParent(nodeRef); // ChildAssociationRef assoc = nodeService.getPrimaryParent(nodeRef);
if (assoc != null) // if (assoc != null)
{ // {
parent = assoc.getParentRef(); // parent = assoc.getParentRef();
} // }
if (isContainer) if (isContainer)
{ {
@@ -334,16 +333,6 @@ public class RMSearchGet extends DeclarativeWebScript
if (!NamespaceService.SYSTEM_MODEL_1_0_URI.equals(qName.getNamespaceURI())) if (!NamespaceService.SYSTEM_MODEL_1_0_URI.equals(qName.getNamespaceURI()))
{ {
String prefixName = qName.getPrefixString().replace(":", "_"); String prefixName = qName.getPrefixString().replace(":", "_");
Serializable value = entry.getValue();
if (value instanceof NodeRef)
{
value = value.toString();
}
else if (value instanceof ContentData)
{
ContentReader contentReader = contentService.getReader(nodeRef, qName);
value = contentReader.getContentString();
}
properties.put(prefixName, entry.getValue()); properties.put(prefixName, entry.getValue());
} }
} }

View File

@@ -21,6 +21,7 @@ package org.alfresco.module.org_alfresco_module_rm.search;
import java.util.List; import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.Pair;
/** /**
* Records management search service. * Records management search service.
@@ -33,10 +34,10 @@ public interface RecordsManagementSearchService
* Execute a records management search * Execute a records management search
* @param siteId the id of the rm site to query * @param siteId the id of the rm site to query
* @param query search query string * @param query search query string
* @param searchParameters search parameters * @param searchParameters search parameters
* @return {@link List}<{@link NodeRef}> search results * @return {@link List}<{@link Pair}<{@link NodeRef}, {@link NodeRef}> search results as pairs for parent and child nodes
*/ */
List<NodeRef> search(String siteId, String query, RecordsManagementSearchParameters searchParameters); List<Pair<NodeRef, NodeRef>> search(String siteId, String query, RecordsManagementSearchParameters searchParameters);
/** /**
* Get all the searches saved on the given records management site. * Get all the searches saved on the given records management site.

View File

@@ -30,6 +30,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -41,6 +42,7 @@ import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075; import org.alfresco.util.ISO9075;
import org.alfresco.util.Pair;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
@@ -173,7 +175,7 @@ public class RecordsManagementSearchServiceImpl implements RecordsManagementSear
* @see org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService#search(java.lang.String, java.lang.String, org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchParameters) * @see org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService#search(java.lang.String, java.lang.String, org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchParameters)
*/ */
@Override @Override
public List<NodeRef> search(String siteId, String query, RecordsManagementSearchParameters rmSearchParameters) public List<Pair<NodeRef, NodeRef>> search(String siteId, String query, RecordsManagementSearchParameters rmSearchParameters)
{ {
// build the full RM query // build the full RM query
StringBuilder fullQuery = new StringBuilder(1024); StringBuilder fullQuery = new StringBuilder(1024);
@@ -206,9 +208,16 @@ public class RecordsManagementSearchServiceImpl implements RecordsManagementSear
// execute query // execute query
ResultSet resultSet = searchService.query(searchParameters); ResultSet resultSet = searchService.query(searchParameters);
// process results
List<Pair<NodeRef, NodeRef>> result = new ArrayList<Pair<NodeRef, NodeRef>>(resultSet.length());
for (ChildAssociationRef childAssoc : resultSet.getChildAssocRefs())
{
result.add(new Pair<NodeRef, NodeRef>(childAssoc.getParentRef(), childAssoc.getChildRef()));
}
// return results // return results
return resultSet.getNodeRefs(); return result;
} }
/** /**

View File

@@ -18,8 +18,12 @@
*/ */
package org.alfresco.module.org_alfresco_module_rm.security; package org.alfresco.module.org_alfresco_module_rm.security;
import java.util.Collections;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.repo.security.permissions.PermissionReference;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
@@ -40,13 +44,45 @@ public class ExtendedReaderDynamicAuthority extends ExtendedSecurityBaseDynamicA
public String getAuthority() public String getAuthority()
{ {
return EXTENDED_READER; return EXTENDED_READER;
}
/**
* @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
*/
@Override
public Set<PermissionReference> requiredFor()
{
if (requiredFor == null)
{
requiredFor = Collections.singleton(getModelDAO().getPermissionReference(null, RMPermissionModel.READ_RECORDS));
}
return requiredFor;
} }
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef)
*/ */
protected Set<String> getAuthorites(NodeRef nodeRef) @SuppressWarnings("unchecked")
protected Set<String> getAuthorites(NodeRef nodeRef)
{ {
return getExtendedSecurityService().getExtendedReaders(nodeRef); Set<String> result = null;
Map<String, Integer> readerMap = (Map<String, Integer>)getNodeService().getProperty(nodeRef, PROP_READERS);
if (readerMap != null)
{
result = readerMap.keySet();
}
return result;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName()
*/
@Override
protected String getTransactionCacheName()
{
return "rm.extendedreaderdynamicauthority";
} }
} }

View File

@@ -24,10 +24,12 @@ import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.security.permissions.DynamicAuthority; import org.alfresco.repo.security.permissions.DynamicAuthority;
import org.alfresco.repo.security.permissions.PermissionReference; import org.alfresco.repo.security.permissions.PermissionReference;
import org.alfresco.repo.security.permissions.impl.ModelDAO;
import org.alfresco.repo.transaction.TransactionalResourceHelper; import org.alfresco.repo.transaction.TransactionalResourceHelper;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.util.Pair;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
@@ -41,9 +43,6 @@ public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAut
RecordsManagementModel, RecordsManagementModel,
ApplicationContextAware ApplicationContextAware
{ {
/** transaction cache key */
private static final String KEY_HAS_AUTHORITY_CACHE = "rm.transaction.hasAuthority";
/** Authority service */ /** Authority service */
private AuthorityService authorityService; private AuthorityService authorityService;
@@ -56,6 +55,12 @@ public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAut
/** Application context */ /** Application context */
protected ApplicationContext applicationContext; protected ApplicationContext applicationContext;
/** model DAO */
protected ModelDAO modelDAO;
/** permission reference */
protected Set<PermissionReference> requiredFor;
// NOTE: we get the services directly from the application context in this way to avoid // NOTE: we get the services directly from the application context in this way to avoid
// cyclic relationships and issues when loading the application context // cyclic relationships and issues when loading the application context
@@ -95,6 +100,23 @@ public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAut
return nodeService; return nodeService;
} }
/**
* @return model DAO
*/
protected ModelDAO getModelDAO()
{
if (modelDAO == null)
{
modelDAO = (ModelDAO)applicationContext.getBean("permissionsModelDAO");
}
return modelDAO;
}
/**
* @return String transaction cache name
*/
protected abstract String getTransactionCacheName();
/** /**
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/ */
@@ -121,63 +143,40 @@ public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAut
{ {
boolean result = false; boolean result = false;
if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY)) Map<Pair<NodeRef, String>, Boolean> transactionCache = TransactionalResourceHelper.getMap(getTransactionCacheName());
Pair<NodeRef, String> key = new Pair<NodeRef, String>(nodeRef, userName);
if (transactionCache.containsKey(key))
{ {
Set<String> authorities = getAuthorites(nodeRef); result = transactionCache.get(key);
if (authorities != null) }
{ else
for (String authority : authorities) {
{ if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY) == true)
if ("GROUP_EVERYONE".equals(authority)) {
{ Set<String> authorities = getAuthorites(nodeRef);
// 'eveyone' is there so break if (authorities != null)
result = true; {
break; // check for everyone or the user
} if (authorities.contains("GROUP_EVEYONE") ||
else if (authority.startsWith("GROUP_")) authorities.contains(userName))
{ {
Map<String, Boolean> transactionCache = TransactionalResourceHelper.getMap(KEY_HAS_AUTHORITY_CACHE); result = true;
String key = authority + "|" + userName; }
if (transactionCache.containsKey(key)) else
{ {
result = transactionCache.get(key); // determine whether any of the users groups are in the extended security
break; Set<String> contained = getAuthorityService().getAuthoritiesForUser(userName);
} authorities.retainAll(contained);
else result = (authorities.size() != 0);
{ }
Set<String> contained = getAuthorityService().getAuthoritiesForUser(userName); }
if (contained.contains(authority)) }
{
result = true; // cache result
transactionCache.put(key, result); transactionCache.put(key, result);
break;
}
}
}
else
{
// presume we have a user
if (authority.equals(userName))
{
result = true;
break;
}
}
}
}
} }
return result; return result;
} }
/**
* Base implementation
*
* @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
*/
@Override
public Set<PermissionReference> requiredFor()
{
return null;
}
} }

View File

@@ -18,8 +18,13 @@
*/ */
package org.alfresco.module.org_alfresco_module_rm.security; package org.alfresco.module.org_alfresco_module_rm.security;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.repo.security.permissions.PermissionReference;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
@@ -41,12 +46,48 @@ public class ExtendedWriterDynamicAuthority extends ExtendedSecurityBaseDynamicA
{ {
return EXTENDED_WRITER; return EXTENDED_WRITER;
} }
/**
* @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
*/
@Override
public Set<PermissionReference> requiredFor()
{
if (requiredFor == null)
{
requiredFor = new HashSet<PermissionReference>(3);
Collections.addAll(requiredFor,
getModelDAO().getPermissionReference(null, RMPermissionModel.READ_RECORDS),
getModelDAO().getPermissionReference(null, RMPermissionModel.FILING),
getModelDAO().getPermissionReference(null, RMPermissionModel.FILE_RECORDS));
}
return requiredFor;
}
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef)
*/ */
protected Set<String> getAuthorites(NodeRef nodeRef) @SuppressWarnings("unchecked")
protected Set<String> getAuthorites(NodeRef nodeRef)
{ {
return getExtendedSecurityService().getExtendedWriters(nodeRef); Set<String> result = null;
}
Map<String, Integer> map = (Map<String, Integer>)getNodeService().getProperty(nodeRef, PROP_WRITERS);
if (map != null)
{
result = map.keySet();
}
return result;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName()
*/
@Override
protected String getTransactionCacheName()
{
return "rm.extendedwriterdynamicauthority";
}
} }

View File

@@ -18,31 +18,36 @@
*/ */
package org.alfresco.module.org_alfresco_module_rm.security; package org.alfresco.module.org_alfresco_module_rm.security;
import static org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority.EXTENDED_READER;
import static org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority.EXTENDED_WRITER;
import static org.alfresco.repo.policy.Behaviour.NotificationFrequency.TRANSACTION_COMMIT;
import static org.alfresco.repo.policy.annotation.BehaviourKind.CLASS;
import static org.alfresco.repo.security.authentication.AuthenticationUtil.getSystemUserName;
import static org.alfresco.service.cmr.security.OwnableService.NO_OWNER;
import static org.alfresco.util.ParameterCheck.mandatory;
import static org.apache.commons.lang.BooleanUtils.isTrue;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanComponentKind; import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl; import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.policy.annotation.Behaviour; import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean; 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;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.OwnableService; import org.alfresco.service.cmr.security.OwnableService;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -59,30 +64,43 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
RMPermissionModel RMPermissionModel
{ {
/** Permission service */ /** Permission service */
protected PermissionService permissionService; private PermissionService permissionService;
/** Ownable service */ /** Ownable service */
protected OwnableService ownableService; private OwnableService ownableService;
/** Policy component */ /** Policy component */
protected PolicyComponent policyComponent; private PolicyComponent policyComponent;
/** Authority service */
private AuthorityService authorityService;
/** Logger */ /** Logger */
protected static final Log LOGGER = LogFactory.getLog(FilePlanPermissionServiceImpl.class); private static final Log LOGGER = LogFactory.getLog(FilePlanPermissionServiceImpl.class);
/** /**
* Initialisation method * Initialisation method
*/ */
public void init() public void init()
{ {
policyComponent.bindClassBehaviour( getPolicyComponent().bindClassBehaviour(
NodeServicePolicies.OnAddAspectPolicy.QNAME, NodeServicePolicies.OnAddAspectPolicy.QNAME,
ASPECT_RECORD, ASPECT_RECORD,
new JavaBehaviour(this, "onAddRecord", NotificationFrequency.TRANSACTION_COMMIT)); new JavaBehaviour(this, "onAddRecord", TRANSACTION_COMMIT));
policyComponent.bindClassBehaviour( getPolicyComponent().bindClassBehaviour(
NodeServicePolicies.OnMoveNodePolicy.QNAME, NodeServicePolicies.OnMoveNodePolicy.QNAME,
ASPECT_RECORD, ASPECT_RECORD,
new JavaBehaviour(this, "onMoveRecord", NotificationFrequency.TRANSACTION_COMMIT)); new JavaBehaviour(this, "onMoveRecord", TRANSACTION_COMMIT));
}
/**
* Gets the permission service
*
* @return The permission service
*/
protected PermissionService getPermissionService()
{
return this.permissionService;
} }
/** /**
@@ -93,6 +111,16 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
this.permissionService = permissionService; this.permissionService = permissionService;
} }
/**
* Gets the policy component
*
* @return The policy component
*/
protected PolicyComponent getPolicyComponent()
{
return this.policyComponent;
}
/** /**
* @param policyComponent policy component * @param policyComponent policy component
*/ */
@@ -101,6 +129,16 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
this.policyComponent = policyComponent; this.policyComponent = policyComponent;
} }
/**
* Gets the ownable service
*
* @return The ownable service
*/
protected OwnableService getOwnableService()
{
return this.ownableService;
}
/** /**
* @param ownableService ownable service * @param ownableService ownable service
*/ */
@@ -109,13 +147,33 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
this.ownableService = ownableService; this.ownableService = ownableService;
} }
/**
* Gets the authority service
*
* @return The authority service
*/
public AuthorityService getAuthorityService()
{
return this.authorityService;
}
/**
* Sets the authority service
*
* @param authorityService The authority service
*/
public void setAuthorityService(AuthorityService authorityService)
{
this.authorityService = authorityService;
}
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionService#setupRecordCategoryPermissions(org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionService#setupRecordCategoryPermissions(org.alfresco.service.cmr.repository.NodeRef)
*/ */
@Override @Override
public void setupRecordCategoryPermissions(final NodeRef recordCategory) public void setupRecordCategoryPermissions(final NodeRef recordCategory)
{ {
ParameterCheck.mandatory("recordCategory", recordCategory); mandatory("recordCategory", recordCategory);
// assert that we have a record category in our hands // assert that we have a record category in our hands
if (!instanceOf(recordCategory, TYPE_RECORD_CATEGORY)) if (!instanceOf(recordCategory, TYPE_RECORD_CATEGORY))
@@ -136,12 +194,13 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
@Behaviour @Behaviour
( (
type = "rma:unfiledRecordFolder", type = "rma:unfiledRecordFolder",
kind = BehaviourKind.CLASS, kind = CLASS,
policy = "alf:onCreateNode", policy = "alf:onCreateNode",
notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT notificationFrequency = TRANSACTION_COMMIT
) )
public void onCreateUnfiledRecordFolder(ChildAssociationRef childAssocRef) public void onCreateUnfiledRecordFolder(ChildAssociationRef childAssocRef)
{ {
mandatory("childAssocRef", childAssocRef);
setupPermissions(childAssocRef.getParentRef(), childAssocRef.getChildRef()); setupPermissions(childAssocRef.getParentRef(), childAssocRef.getChildRef());
} }
@@ -153,12 +212,13 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
@Behaviour @Behaviour
( (
type = "rma:recordFolder", type = "rma:recordFolder",
kind = BehaviourKind.CLASS, kind = CLASS,
policy = "alf:onCreateNode", policy = "alf:onCreateNode",
notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT notificationFrequency = TRANSACTION_COMMIT
) )
public void onCreateRecordFolder(ChildAssociationRef childAssocRef) public void onCreateRecordFolder(ChildAssociationRef childAssocRef)
{ {
mandatory("childAssocRef", childAssocRef);
setupPermissions(childAssocRef.getParentRef(), childAssocRef.getChildRef()); setupPermissions(childAssocRef.getParentRef(), childAssocRef.getChildRef());
} }
@@ -170,12 +230,13 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
@Behaviour @Behaviour
( (
type = "rma:hold", type = "rma:hold",
kind = BehaviourKind.CLASS, kind = CLASS,
policy = "alf:onCreateNode", policy = "alf:onCreateNode",
notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT notificationFrequency = TRANSACTION_COMMIT
) )
public void onCreateHold(final ChildAssociationRef childAssocRef) public void onCreateHold(final ChildAssociationRef childAssocRef)
{ {
mandatory("childAssocRef", childAssocRef);
setupPermissions(childAssocRef.getParentRef(), childAssocRef.getChildRef()); setupPermissions(childAssocRef.getParentRef(), childAssocRef.getChildRef());
} }
@@ -187,13 +248,14 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
@Behaviour @Behaviour
( (
type = "rma:transfer", type = "rma:transfer",
kind = BehaviourKind.CLASS, kind = CLASS,
policy = "alf:onCreateNode", policy = "alf:onCreateNode",
notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT notificationFrequency = TRANSACTION_COMMIT
) )
public void onCreateTransfer(final ChildAssociationRef childAssocRef) public void onCreateTransfer(final ChildAssociationRef childAssocRef)
{ {
setupPermissions(childAssocRef.getParentRef(), childAssocRef.getChildRef(), false); mandatory("childAssocRef", childAssocRef);
setupPermissions(childAssocRef.getParentRef(), childAssocRef.getChildRef());
} }
/** /**
@@ -204,90 +266,53 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
*/ */
public void setupPermissions(final NodeRef parent, final NodeRef nodeRef) public void setupPermissions(final NodeRef parent, final NodeRef nodeRef)
{ {
ParameterCheck.mandatory("parent", parent); mandatory("parent", parent);
ParameterCheck.mandatory("nodeRef", nodeRef); mandatory("nodeRef", nodeRef);
setupPermissions(parent, nodeRef, true);
}
/**
* Helper method to setup permissions.
*
* @param parent parent node reference
* @param nodeRef child node reference
* @param includeInPlace true if in-place permissions should be included, false otherwise
*/
private void setupPermissions(final NodeRef parent, final NodeRef nodeRef, final boolean includeInPlace)
{
if (nodeService.exists(nodeRef))
{
// initialise permissions
initPermissions(nodeRef, includeInPlace);
if (nodeService.exists(parent)) if (nodeService.exists(nodeRef) && nodeService.exists(parent))
{
authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>()
{ {
authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>() public Object doWork()
{ {
public Object doWork() // set inheritance
boolean isParentNodeFilePlan = isRecordCategory(nodeRef) && isFilePlan(parent);
boolean inheritanceAllowed = isInheritanceAllowed(nodeRef, isParentNodeFilePlan);
getPermissionService().setInheritParentPermissions(nodeRef, inheritanceAllowed);
// clear all existing permissions
getPermissionService().clearPermission(nodeRef, null);
if (!inheritanceAllowed)
{ {
// setup inherited permissions getPermissionService().setPermission(nodeRef, EXTENDED_READER, READ_RECORDS, true);
Set<AccessPermission> perms = permissionService.getAllSetPermissions(parent); getPermissionService().setPermission(nodeRef, EXTENDED_WRITER, FILING, true);
for (AccessPermission perm : perms) String adminRole = getAdminRole(nodeRef);
{ getPermissionService().setPermission(nodeRef, adminRole, RMPermissionModel.FILING, true);
// only copy filling permissions if the parent is the file plan
if (!inheritFillingOnly(parent, nodeRef) ||
RMPermissionModel.FILING.equals(perm.getPermission()))
{
// don't copy the extended reader or writer permissions as they have already been set
if (!ExtendedReaderDynamicAuthority.EXTENDED_READER.equals(perm.getAuthority()) &&
!ExtendedWriterDynamicAuthority.EXTENDED_WRITER.equals(perm.getAuthority()))
{
// get the access status details
AccessStatus accessStatus = perm.getAccessStatus();
boolean allow = false;
if (AccessStatus.ALLOWED.equals(accessStatus))
{
allow = true;
}
// set the permission on the target node
permissionService.setPermission(
nodeRef,
perm.getAuthority(),
perm.getPermission(),
allow);
}
}
}
return null;
} }
});
} // remove owner
getOwnableService().setOwner(nodeRef, NO_OWNER);
return null;
}
});
} }
} }
/** private String getAdminRole(NodeRef nodeRef)
* Helper method to determine whether all or just filling permissions should be inherited.
*
* @param parent parent node
* @param child child node
* @return boolean true if inherit filling only, false otherwise
*/
private boolean inheritFillingOnly(NodeRef parent, NodeRef child)
{ {
boolean result = false; NodeRef filePlan = getFilePlan(nodeRef);
if (filePlan == null)
// if root category or
// if in root of unfiled container or
// if in root of hold container
if ((isFilePlan(parent) && isRecordCategory(child)) ||
FilePlanComponentKind.UNFILED_RECORD_CONTAINER.equals(getFilePlanComponentKind(parent)) ||
FilePlanComponentKind.HOLD_CONTAINER.equals(getFilePlanComponentKind(parent)))
{ {
result = true; throw new AlfrescoRuntimeException("The file plan could not be found for the give node: '" + nodeRef + "'.");
} }
return authorityService.getName(AuthorityType.GROUP, FilePlanRoleService.ROLE_ADMIN + filePlan.getId());
}
return result; private boolean isInheritanceAllowed(NodeRef nodeRef, Boolean isParentNodeFilePlan)
{
return !(isFilePlan(nodeRef) || isTransfer(nodeRef) || isHold(nodeRef) || isUnfiledRecordsContainer(nodeRef) || (isRecordCategory(nodeRef) && isTrue(isParentNodeFilePlan)));
} }
/** /**
@@ -300,6 +325,9 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
*/ */
public void onAddRecord(final NodeRef record, final QName aspectTypeQName) public void onAddRecord(final NodeRef record, final QName aspectTypeQName)
{ {
mandatory("childAssocRef", record);
mandatory("childAssocRef", aspectTypeQName);
authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>() authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>()
{ {
public Object doWork() public Object doWork()
@@ -323,27 +351,32 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
*/ */
public void onMoveRecord(final ChildAssociationRef sourceAssocRef, final ChildAssociationRef destinationAssocRef) public void onMoveRecord(final ChildAssociationRef sourceAssocRef, final ChildAssociationRef destinationAssocRef)
{ {
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Void>() mandatory("sourceAssocRef", sourceAssocRef);
mandatory("destinationAssocRef", destinationAssocRef);
authenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Void>()
{ {
public Void doWork() public Void doWork()
{ {
NodeRef record = sourceAssocRef.getChildRef(); NodeRef record = sourceAssocRef.getChildRef();
if (nodeService.exists(record) && nodeService.hasAspect(record, ASPECT_RECORD)) if (nodeService.exists(record) && nodeService.hasAspect(record, ASPECT_RECORD))
{ {
Set<AccessPermission> keepPerms = new HashSet<AccessPermission>(5); boolean inheritParentPermissions = permissionService.getInheritParentPermissions(record);
// record any permissions specifically set on the record (ie any filling or record_file permisions not on the parent) Set<AccessPermission> keepPerms = new HashSet<AccessPermission>(5);
Set<AccessPermission> origionalParentPerms = permissionService.getAllSetPermissions(sourceAssocRef.getParentRef());
Set<AccessPermission> origionalRecordPerms= permissionService.getAllSetPermissions(record); Set<AccessPermission> origionalRecordPerms= permissionService.getAllSetPermissions(record);
for (AccessPermission perm : origionalRecordPerms)
for (AccessPermission recordPermission : origionalRecordPerms)
{ {
if (!ExtendedReaderDynamicAuthority.EXTENDED_READER.equals(perm.getAuthority()) && String permission = recordPermission.getPermission();
!ExtendedWriterDynamicAuthority.EXTENDED_WRITER.equals(perm.getAuthority()) && String authority = recordPermission.getAuthority();
(perm.getPermission().equals(RMPermissionModel.FILING) || perm.getPermission().equals(RMPermissionModel.FILE_RECORDS)) && if ((RMPermissionModel.FILING.equals(permission) || RMPermissionModel.READ_RECORDS.equals(permission)) &&
!origionalParentPerms.contains(perm)) recordPermission.isSetDirectly() &&
!ExtendedReaderDynamicAuthority.EXTENDED_READER.equals(authority) &&
!ExtendedWriterDynamicAuthority.EXTENDED_WRITER.equals(authority))
{ {
// then we can assume this is a permission we want to preserve // then we can assume this is a permission we want to preserve
keepPerms.add(perm); keepPerms.add(recordPermission);
} }
} }
@@ -358,47 +391,13 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
{ {
setPermission(record, keeper.getAuthority(), keeper.getPermission()); setPermission(record, keeper.getAuthority(), keeper.getPermission());
} }
permissionService.setInheritParentPermissions(record, inheritParentPermissions);
} }
return null; return null;
} }
}, AuthenticationUtil.getSystemUserName()); }, getSystemUserName());
}
/**
* Init the permissions for the given node.
*
* @param nodeRef node reference
* @param includeInPlace true if in-place
*/
private void initPermissions(final NodeRef nodeRef, final boolean includeInPlace)
{
if (nodeService.exists(nodeRef))
{
authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>()
{
public Object doWork()
{
// break inheritance
permissionService.setInheritParentPermissions(nodeRef, false);
// clear all existing permissions
permissionService.clearPermission(nodeRef, null);
if (includeInPlace)
{
// set extended reader permissions
permissionService.setPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true);
permissionService.setPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true);
}
// remove owner
ownableService.setOwner(nodeRef, OwnableService.NO_OWNER);
return null;
}
});
}
} }
/** /**
@@ -414,21 +413,10 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
{ {
public Void doWork() public Void doWork()
{ {
if (isFilePlan(nodeRef)) if (canPerformPermissionAction(nodeRef))
{ {
// set the permission down the file plan hierarchy // Set the permission on the node
setPermissionDown(nodeRef, authority, permission); getPermissionService().setPermission(nodeRef, authority, permission, true);
}
else if (isFilePlanContainer(nodeRef) ||
isRecordFolder(nodeRef) ||
isRecord(nodeRef) ||
isHold(nodeRef))
{
// set read permission to the parents of the node
setReadPermissionUp(nodeRef, authority);
// set the permission on the node and it's children
setPermissionDown(nodeRef, authority, permission);
} }
else else
{ {
@@ -443,146 +431,29 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
}); });
} }
/**
* Helper method to set the read permission up the hierarchy
*
* @param nodeRef node reference
* @param authority authority
*/
private void setReadPermissionUp(NodeRef nodeRef, String authority)
{
NodeRef parent = nodeService.getPrimaryParent(nodeRef).getParentRef();
if (parent != null && isFilePlanComponent(parent))
{
setReadPermissionUpImpl(parent, authority);
}
}
/**
* Helper method used to set the read permission up the hierarchy
*
* @param nodeRef node reference
* @param authority authority
*/
private void setReadPermissionUpImpl(NodeRef nodeRef, String authority)
{
setPermissionImpl(nodeRef, authority, RMPermissionModel.READ_RECORDS);
NodeRef parent = nodeService.getPrimaryParent(nodeRef).getParentRef();
if (parent != null && isFilePlanComponent(parent))
{
setReadPermissionUpImpl(parent, authority);
}
}
/**
* Helper method to set the permission down the hierarchy
*
* @param nodeRef node reference
* @param authority authority
* @param permission permission
*/
private void setPermissionDown(NodeRef nodeRef, String authority, String permission)
{
// skip out node's that inherit (for example hold and transfer)
if (!permissionService.getInheritParentPermissions(nodeRef))
{
// set permissions
setPermissionImpl(nodeRef, authority, permission);
if (isFilePlanContainer(nodeRef) ||
isRecordFolder(nodeRef))
{
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
for (ChildAssociationRef assoc : assocs)
{
NodeRef child = assoc.getChildRef();
if (isFilePlanContainer(child) ||
isRecordFolder(child) ||
isRecord(child) ||
isHold(child) ||
instanceOf(child, TYPE_TRANSFER))
{
setPermissionDown(child, authority, permission);
}
}
}
}
}
/**
* Set the permission, taking into account that filing is a superset of read
*
* @param nodeRef node reference
* @param authority authority
* @param permission permission
*/
private void setPermissionImpl(NodeRef nodeRef, String authority, String permission)
{
boolean hasRead = false;
boolean hasFilling = false;
Set<AccessPermission> perms = permissionService.getAllSetPermissions(nodeRef);
for (AccessPermission perm : perms)
{
if (perm.getAuthority().equals(authority))
{
if (perm.getPermission().equals(FILING))
{
hasFilling = true;
}
else if (perm.getPermission().equals(READ_RECORDS))
{
hasRead = true;
}
}
}
if (FILING.equals(permission) && hasRead)
{
// remove read permission
permissionService.deletePermission(nodeRef, authority, RMPermissionModel.READ_RECORDS);
hasRead = false;
}
if (!hasRead && !hasFilling)
{
// add permission
permissionService.setPermission(nodeRef, authority, permission, true);
}
}
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#deletePermission(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.lang.String) * @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#deletePermission(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.lang.String)
*/ */
public void deletePermission(final NodeRef nodeRef, final String authority, final String permission) public void deletePermission(final NodeRef nodeRef, final String authority, final String permission)
{ {
ParameterCheck.mandatory("nodeRef", nodeRef);
ParameterCheck.mandatory("authority", authority);
ParameterCheck.mandatory("permission", permission);
authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>() authenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Object>()
{ {
public Void doWork() public Void doWork()
{ {
// can't delete permissions if inherited (eg hold and transfer containers) if (canPerformPermissionAction(nodeRef))
if (!permissionService.getInheritParentPermissions(nodeRef))
{ {
// Delete permission on this node // Delete permission on this node
permissionService.deletePermission(nodeRef, authority, permission); getPermissionService().deletePermission(nodeRef, authority, permission);
}
if (isFilePlanContainer(nodeRef) || else
isRecordFolder(nodeRef)) {
if (LOGGER.isWarnEnabled())
{ {
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); LOGGER.warn("Deleting permissions for this node is not supported. (nodeRef=" + nodeRef + ", authority=" + authority + ", permission=" + permission + ")");
for (ChildAssociationRef assoc : assocs)
{
NodeRef child = assoc.getChildRef();
if (isFilePlanContainer(child) ||
isRecordFolder(child) ||
isRecord(child)||
isHold(child) ||
instanceOf(child, TYPE_TRANSFER))
{
deletePermission(child, authority, permission);
}
}
} }
} }
@@ -590,4 +461,9 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
} }
}); });
} }
private boolean canPerformPermissionAction(NodeRef nodeRef)
{
return isFilePlanContainer(nodeRef) || isRecordFolder(nodeRef) || isRecord(nodeRef);
}
} }

View File

@@ -53,10 +53,10 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
/** Application context */ /** Application context */
protected ApplicationContext applicationContext; protected ApplicationContext applicationContext;
/** internal node service */ /** internal node service */
private NodeService internalNodeService; private NodeService internalNodeService;
/** authentication helper */ /** authentication helper */
protected AuthenticationUtil authenticationUtil; protected AuthenticationUtil authenticationUtil;
@@ -84,7 +84,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
{ {
this.dictionaryService = dictionaryService; this.dictionaryService = dictionaryService;
} }
/** /**
* @param authenticationUtil authentication util helper * @param authenticationUtil authentication util helper
*/ */
@@ -92,7 +92,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
{ {
this.authenticationUtil = authenticationUtil; this.authenticationUtil = authenticationUtil;
} }
/** /**
* Helper to get internal node service. * Helper to get internal node service.
* <p> * <p>
@@ -104,10 +104,10 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
{ {
internalNodeService = (NodeService)applicationContext.getBean("dbNodeService"); internalNodeService = (NodeService)applicationContext.getBean("dbNodeService");
} }
return internalNodeService; return internalNodeService;
} }
/** /**
* Gets the file plan component kind from the given node reference * Gets the file plan component kind from the given node reference
* *
@@ -127,7 +127,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
if (isFilePlanComponent(nodeRef)) if (isFilePlanComponent(nodeRef))
{ {
result = FilePlanComponentKind.FILE_PLAN_COMPONENT; result = FilePlanComponentKind.FILE_PLAN_COMPONENT;
if (isFilePlan(nodeRef)) if (isFilePlan(nodeRef))
{ {
result = FilePlanComponentKind.FILE_PLAN; result = FilePlanComponentKind.FILE_PLAN;
@@ -173,7 +173,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
result = FilePlanComponentKind.UNFILED_RECORD_FOLDER; result = FilePlanComponentKind.UNFILED_RECORD_FOLDER;
} }
} }
if (result != null) if (result != null)
{ {
map.put(nodeRef, result); map.put(nodeRef, result);
@@ -319,7 +319,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("nodeRef", nodeRef);
boolean isHold = false; boolean isHold = false;
if (getInternalNodeService().exists(nodeRef) && if (getInternalNodeService().exists(nodeRef) &&
instanceOf(nodeRef, TYPE_HOLD)) instanceOf(nodeRef, TYPE_HOLD))
{ {
isHold = true; isHold = true;
@@ -338,10 +338,23 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
return instanceOf(nodeRef, TYPE_TRANSFER); return instanceOf(nodeRef, TYPE_TRANSFER);
} }
/**
* Indicates whether the given node reference is an unfiled records container or not.
*
* @param nodeRef node reference
* @return boolean true if rma:unfiledRecordContainer or sub-type, false otherwise
*/
public boolean isUnfiledRecordsContainer(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
return instanceOf(nodeRef, TYPE_UNFILED_RECORD_CONTAINER);
}
/** /**
* Indicates whether a record is complete or not. * Indicates whether a record is complete or not.
* *
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#isDeclared(org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#isDeclared(org.alfresco.service.cmr.repository.NodeRef)
*/ */
public boolean isDeclared(NodeRef record) public boolean isDeclared(NodeRef record)
@@ -361,22 +374,33 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
{ {
NodeRef result = null; NodeRef result = null;
if (nodeRef != null) if (nodeRef != null)
{ {
result = (NodeRef)getInternalNodeService().getProperty(nodeRef, PROP_ROOT_NODEREF); Map<NodeRef, NodeRef> transactionCache = TransactionalResourceHelper.getMap("rm.servicebase.getFilePlan");
if (result == null || !instanceOf(result, TYPE_FILE_PLAN)) if (transactionCache.containsKey(nodeRef))
{ {
if (instanceOf(nodeRef, TYPE_FILE_PLAN)) result = transactionCache.get(nodeRef);
}
else
{
result = (NodeRef)getInternalNodeService().getProperty(nodeRef, PROP_ROOT_NODEREF);
if (result == null || !instanceOf(result, TYPE_FILE_PLAN))
{ {
result = nodeRef; if (instanceOf(nodeRef, TYPE_FILE_PLAN))
}
else
{
ChildAssociationRef parentAssocRef = getInternalNodeService().getPrimaryParent(nodeRef);
if (parentAssocRef != null)
{ {
result = getFilePlan(parentAssocRef.getParentRef()); result = nodeRef;
}
else
{
ChildAssociationRef parentAssocRef = getInternalNodeService().getPrimaryParent(nodeRef);
if (parentAssocRef != null)
{
result = getFilePlan(parentAssocRef.getParentRef());
}
} }
} }
// cache result in transaction
transactionCache.put(nodeRef, result);
} }
} }
@@ -392,11 +416,11 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
protected boolean instanceOf(NodeRef nodeRef, QName ofClassName) protected boolean instanceOf(NodeRef nodeRef, QName ofClassName)
{ {
ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("nodeRef", nodeRef);
ParameterCheck.mandatory("ofClassName", ofClassName); ParameterCheck.mandatory("ofClassName", ofClassName);
QName className = getInternalNodeService().getType(nodeRef); QName className = getInternalNodeService().getType(nodeRef);
return instanceOf(className, ofClassName); return instanceOf(className, ofClassName);
} }
private static Map<String, Boolean> instanceOfCache = new HashMap<String, Boolean>(); private static Map<String, Boolean> instanceOfCache = new HashMap<String, Boolean>();
/** /**
@@ -410,25 +434,25 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
{ {
ParameterCheck.mandatory("className", className); ParameterCheck.mandatory("className", className);
ParameterCheck.mandatory("ofClassName", ofClassName); ParameterCheck.mandatory("ofClassName", ofClassName);
boolean result = false; boolean result = false;
String key = className.toString() + "|" + ofClassName.toString(); String key = className.toString() + "|" + ofClassName.toString();
if (instanceOfCache.containsKey(key)) if (instanceOfCache.containsKey(key))
{ {
result = instanceOfCache.get(key); result = instanceOfCache.get(key);
} }
else else
{ {
if (ofClassName.equals(className) || if (ofClassName.equals(className) ||
dictionaryService.isSubClass(className, ofClassName)) dictionaryService.isSubClass(className, ofClassName))
{ {
result = true; result = true;
} }
instanceOfCache.put(key, result); instanceOfCache.put(key, result);
} }
return result; return result;
} }

View File

@@ -18,18 +18,26 @@
*/ */
package org.alfresco.repo.security.permissions.impl; package org.alfresco.repo.security.permissions.impl;
import static org.apache.commons.lang.StringUtils.isNotBlank;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
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.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
import org.alfresco.repo.cache.SimpleCache; import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.security.permissions.AccessControlEntry; import org.alfresco.repo.security.permissions.AccessControlEntry;
import org.alfresco.repo.security.permissions.AccessControlList; import org.alfresco.repo.security.permissions.AccessControlList;
import org.alfresco.service.cmr.repository.NodeRef; 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.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.util.PropertyCheck; import org.alfresco.util.PropertyCheck;
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEvent;
@@ -48,6 +56,29 @@ public class RMPermissionServiceImpl extends PermissionServiceImpl
/** Writers simple cache */ /** Writers simple cache */
protected SimpleCache<Serializable, Set<String>> writersCache; protected SimpleCache<Serializable, Set<String>> writersCache;
/** File plan service */
private FilePlanService filePlanService;
/**
* Gets the file plan service
*
* @return the filePlanService
*/
public FilePlanService getFilePlanService()
{
return this.filePlanService;
}
/**
* Sets the file plan service
*
* @param filePlanService the filePlanService to set
*/
public void setFilePlanService(FilePlanService filePlanService)
{
this.filePlanService = filePlanService;
}
/** /**
* @see org.alfresco.repo.security.permissions.impl.PermissionServiceImpl#setAnyDenyDenies(boolean) * @see org.alfresco.repo.security.permissions.impl.PermissionServiceImpl#setAnyDenyDenies(boolean)
*/ */
@@ -87,15 +118,15 @@ public class RMPermissionServiceImpl extends PermissionServiceImpl
public AccessStatus hasPermission(NodeRef nodeRef, String perm) public AccessStatus hasPermission(NodeRef nodeRef, String perm)
{ {
AccessStatus acs = super.hasPermission(nodeRef, perm); AccessStatus acs = super.hasPermission(nodeRef, perm);
if (AccessStatus.DENIED.equals(acs) && if (AccessStatus.DENIED.equals(acs) == true &&
PermissionService.READ.equals(perm) && PermissionService.READ.equals(perm) == true &&
nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT)) nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT) == true)
{ {
return super.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS); return super.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS);
} }
else if (AccessStatus.DENIED.equals(acs) && else if (AccessStatus.DENIED.equals(acs) == true &&
PermissionService.WRITE.equals(perm) && PermissionService.WRITE.equals(perm) == true &&
nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT)) nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT) == true)
{ {
return super.hasPermission(nodeRef, RMPermissionModel.FILE_RECORDS); return super.hasPermission(nodeRef, RMPermissionModel.FILE_RECORDS);
} }
@@ -263,4 +294,50 @@ public class RMPermissionServiceImpl extends PermissionServiceImpl
writersCache.put((Serializable)acl.getProperties(), aclWriters); writersCache.put((Serializable)acl.getProperties(), aclWriters);
return aclWriters; return aclWriters;
} }
/**
* @see org.alfresco.repo.security.permissions.impl.PermissionServiceImpl#setInheritParentPermissions(org.alfresco.service.cmr.repository.NodeRef, boolean)
*/
@Override
public void setInheritParentPermissions(final NodeRef nodeRef, boolean inheritParentPermissions)
{
final String adminRole = getAdminRole(nodeRef);
if (nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT) && isNotBlank(adminRole))
{
if (inheritParentPermissions)
{
Set<AccessPermission> accessPermissions = getAllSetPermissions(nodeRef);
for (AccessPermission accessPermission : accessPermissions)
{
String authority = accessPermission.getAuthority();
String permission = accessPermission.getPermission();
if (accessPermission.isSetDirectly() &&
(RMPermissionModel.FILING.equals(permission) || RMPermissionModel.READ_RECORDS.equals(permission)) &&
(ExtendedReaderDynamicAuthority.EXTENDED_READER.equals(authority) || ExtendedWriterDynamicAuthority.EXTENDED_WRITER.equals(authority)) || adminRole.equals(authority))
{
// FIXME!!!
//deletePermission(nodeRef, authority, permission);
}
}
}
else
{
setPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true);
setPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true);
setPermission(nodeRef, adminRole, RMPermissionModel.FILING, true);
}
}
super.setInheritParentPermissions(nodeRef, inheritParentPermissions);
}
private String getAdminRole(NodeRef nodeRef)
{
String adminRole = null;
NodeRef filePlan = getFilePlanService().getFilePlan(nodeRef);
if (filePlan != null)
{
adminRole = authorityService.getName(AuthorityType.GROUP, FilePlanRoleService.ROLE_ADMIN + filePlan.getId());
}
return adminRole;
}
} }

View File

@@ -40,7 +40,8 @@ import org.junit.runners.Suite.SuiteClasses;
RM1464Test.class, RM1464Test.class,
RM452Test.class, RM452Test.class,
RM804Test.class, RM804Test.class,
RM994Test.class RM994Test.class,
RM1039Test.class
}) })
public class IssueTestSuite public class IssueTestSuite
{ {

View File

@@ -181,8 +181,9 @@ public class RM1008Test extends BaseRMTestCase
Capability viewRecords = capabilityService.getCapability("ViewRecords"); Capability viewRecords = capabilityService.getCapability("ViewRecords");
assertNotNull(viewRecords); assertNotNull(viewRecords);
assertEquals(AccessStatus.ALLOWED, viewRecords.hasPermission(hold)); assertEquals(AccessStatus.DENIED, viewRecords.hasPermission(hold));
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(hold, RMPermissionModel.FILING)); assertEquals(AccessStatus.DENIED, permissionService.hasPermission(hold, RMPermissionModel.READ_RECORDS));
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(hold, RMPermissionModel.FILING));
return null; return null;
} }
@@ -292,7 +293,7 @@ public class RM1008Test extends BaseRMTestCase
Capability viewRecords = capabilityService.getCapability("ViewRecords"); Capability viewRecords = capabilityService.getCapability("ViewRecords");
assertNotNull(viewRecords); assertNotNull(viewRecords);
assertEquals(AccessStatus.ALLOWED, viewRecords.hasPermission(transfer)); assertEquals(AccessStatus.DENIED, viewRecords.hasPermission(transfer));
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(transfer, RMPermissionModel.FILING)); assertEquals(AccessStatus.DENIED, permissionService.hasPermission(transfer, RMPermissionModel.FILING));
return null; return null;
@@ -318,8 +319,9 @@ public class RM1008Test extends BaseRMTestCase
Capability viewRecords = capabilityService.getCapability("ViewRecords"); Capability viewRecords = capabilityService.getCapability("ViewRecords");
assertNotNull(viewRecords); assertNotNull(viewRecords);
assertEquals(AccessStatus.ALLOWED, viewRecords.hasPermission(transfer)); assertEquals(AccessStatus.DENIED, viewRecords.hasPermission(transfer));
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(transfer, RMPermissionModel.FILING)); assertEquals(AccessStatus.DENIED, permissionService.hasPermission(transfer, RMPermissionModel.READ_RECORDS));
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(transfer, RMPermissionModel.FILING));
return null; return null;
} }
@@ -344,7 +346,7 @@ public class RM1008Test extends BaseRMTestCase
Capability viewRecords = capabilityService.getCapability("ViewRecords"); Capability viewRecords = capabilityService.getCapability("ViewRecords");
assertNotNull(viewRecords); assertNotNull(viewRecords);
assertEquals(AccessStatus.ALLOWED, viewRecords.hasPermission(transfer)); assertEquals(AccessStatus.DENIED, viewRecords.hasPermission(transfer));
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(transfer, RMPermissionModel.FILING)); assertEquals(AccessStatus.DENIED, permissionService.hasPermission(transfer, RMPermissionModel.FILING));
return null; return null;

View File

@@ -0,0 +1,186 @@
/*
* Copyright (C) 2005-2013 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.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.action.impl.CompleteEventAction;
import org.alfresco.module.org_alfresco_module_rm.action.impl.CutOffAction;
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionAction;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
import org.alfresco.module.org_alfresco_module_rm.test.util.CommonRMTestUtils;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Unit test for RM-1039 ... can't move a folder into a category with a disposition schedule
*
* @author Roy Wetherall
* @since 2.1
*/
public class RM1039Test extends BaseRMTestCase
{
@Override
protected boolean isRecordTest()
{
return true;
}
// try and move a folder from no disposition schedule to a disposition schedule
public void testMoveRecordFolderFromNoDisToDis() throws Exception
{
final NodeRef recordFolder = doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run()
{
// create a record category (no disposition schedule)
NodeRef recordCategory = filePlanService.createRecordCategory(filePlan, "Caitlin Reed");
// create a record folder
return recordFolderService.createRecordFolder(recordCategory, "Grace Wetherall");
}
@Override
public void test(NodeRef result) throws Exception
{
assertNotNull(result);
assertNull(dispositionService.getDispositionSchedule(result));
assertFalse(nodeService.hasAspect(result, ASPECT_DISPOSITION_LIFECYCLE));
}
});
final NodeRef record = doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run()
{
// create a record
return fileFolderService.create(recordFolder, "mytest.txt", ContentModel.TYPE_CONTENT).getNodeRef();
}
@Override
public void test(NodeRef result) throws Exception
{
assertNotNull(result);
assertNull(dispositionService.getDispositionSchedule(result));
assertFalse(nodeService.hasAspect(result, ASPECT_DISPOSITION_LIFECYCLE));
}
});
doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run() throws Exception
{
Capability capability = capabilityService.getCapability("CreateModifyDestroyFolders");
assertEquals(AccessDecisionVoter.ACCESS_GRANTED, capability.evaluate(recordFolder));
assertEquals(AccessDecisionVoter.ACCESS_GRANTED, capability.evaluate(recordFolder, rmContainer));
// take a look at the move capability
Capability moveCapability = capabilityService.getCapability("Move");
assertEquals(AccessDecisionVoter.ACCESS_GRANTED, moveCapability.evaluate(recordFolder, rmContainer));
// move the node
return fileFolderService.move(recordFolder, rmContainer, null).getNodeRef();
}
@Override
public void test(NodeRef result) throws Exception
{
assertNotNull(result);
assertNotNull(dispositionService.getDispositionSchedule(result));
assertTrue(nodeService.hasAspect(result, ASPECT_DISPOSITION_LIFECYCLE));
DispositionAction dispositionAction = dispositionService.getNextDispositionAction(result);
assertNotNull(dispositionAction);
assertNull(dispositionAction.getAsOfDate());
assertEquals("cutoff", dispositionAction.getName());
assertEquals(1, dispositionAction.getEventCompletionDetails().size());
// take a look at the record and check things are as we would expect
assertFalse(nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE));
}
});
}
// move from a disposition schedule to another .. both record folder level
// move from a disposition schedule to another .. from record to folder level
// try and move a cutoff folder
public void testMoveCutoffRecordFolder() throws Exception
{
final NodeRef destination = doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run()
{
// create a record category (no disposition schedule)
return filePlanService.createRecordCategory(filePlan, "Caitlin Reed");
}
});
final NodeRef testFolder = doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run()
{
// create folder
NodeRef testFolder = recordFolderService.createRecordFolder(rmContainer, "Peter Edward Francis");
// complete event
Map<String, Serializable> params = new HashMap<String, Serializable>(1);
params.put(CompleteEventAction.PARAM_EVENT_NAME, CommonRMTestUtils.DEFAULT_EVENT_NAME);
rmActionService.executeRecordsManagementAction(testFolder, CompleteEventAction.NAME, params);
// cutoff folder
rmActionService.executeRecordsManagementAction(testFolder, CutOffAction.NAME);
return testFolder;
}
@Override
public void test(NodeRef result) throws Exception
{
// take a look at the move capability
Capability moveCapability = capabilityService.getCapability("Move");
assertEquals(AccessDecisionVoter.ACCESS_DENIED, moveCapability.evaluate(result, destination));
}
});
doTestInTransaction(new FailureTest()
{
@Override
public void run() throws Exception
{
fileFolderService.move(testFolder, destination, null).getNodeRef();
}
});
}
}

View File

@@ -23,6 +23,7 @@ import java.util.List;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; 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.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.test.integration.hold.DeleteHoldTest; import org.alfresco.module.org_alfresco_module_rm.test.integration.hold.DeleteHoldTest;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -65,7 +66,7 @@ public class RM1424Test extends DeleteHoldTest
assertEquals(HOLD1_DESC, (String) nodeService.getProperty(hold1, PROP_DESCRIPTION)); assertEquals(HOLD1_DESC, (String) nodeService.getProperty(hold1, PROP_DESCRIPTION));
// Add the user to the RM Manager role // Add the user to the RM Manager role
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_NAME_RECORDS_MANAGER, userName); filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, userName);
return null; return null;
} }

View File

@@ -20,6 +20,7 @@ package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.test.integration.hold.DeleteHoldTest; import org.alfresco.module.org_alfresco_module_rm.test.integration.hold.DeleteHoldTest;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -43,7 +44,7 @@ public class RM1429Test extends DeleteHoldTest
public Void run() public Void run()
{ {
// Add the user to the RM Manager role // Add the user to the RM Manager role
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_NAME_RECORDS_MANAGER, userName); filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, userName);
// Give the user filing permissions on the hold // Give the user filing permissions on the hold
permissionService.setPermission(hold, userName, RMPermissionModel.FILING, true); permissionService.setPermission(hold, userName, RMPermissionModel.FILING, true);

View File

@@ -20,6 +20,7 @@ package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.test.integration.hold.DeleteHoldTest; import org.alfresco.module.org_alfresco_module_rm.test.integration.hold.DeleteHoldTest;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -43,7 +44,7 @@ public class RM1463Test extends DeleteHoldTest
public Void run() public Void run()
{ {
// Add the user to the RM Manager role // Add the user to the RM Manager role
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_NAME_RECORDS_MANAGER, userName); filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, userName);
// Give the user filing permissions on the hold // Give the user filing permissions on the hold
permissionService.setPermission(hold, userName, RMPermissionModel.FILING, true); permissionService.setPermission(hold, userName, RMPermissionModel.FILING, true);

View File

@@ -20,6 +20,7 @@ package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.test.integration.hold.DeleteHoldTest; import org.alfresco.module.org_alfresco_module_rm.test.integration.hold.DeleteHoldTest;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -43,7 +44,7 @@ public class RM1464Test extends DeleteHoldTest
public Void run() public Void run()
{ {
// Add the user to the RM Manager role // Add the user to the RM Manager role
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_NAME_RECORDS_MANAGER, userName); filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, userName);
// Give the user read permissions on the hold // Give the user read permissions on the hold
permissionService.setPermission(hold, userName, RMPermissionModel.READ_RECORDS, true); permissionService.setPermission(hold, userName, RMPermissionModel.READ_RECORDS, true);

View File

@@ -19,6 +19,7 @@
package org.alfresco.module.org_alfresco_module_rm.test.integration.issue; package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.site.SiteRole; import org.alfresco.service.cmr.site.SiteRole;
@@ -142,7 +143,7 @@ public class RM804Test extends BaseRMTestCase
@Override @Override
public Void run() public Void run()
{ {
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_NAME_USER, userName); filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_USER, userName);
return null; return null;
} }
@@ -167,7 +168,7 @@ public class RM804Test extends BaseRMTestCase
@Override @Override
public Void run() public Void run()
{ {
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_NAME_ADMINISTRATOR, userName); filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_ADMIN, userName);
return null; return null;
} }

View File

@@ -31,38 +31,38 @@ import org.springframework.extensions.webscripts.GUID;
/** /**
* reject record tests. * reject record tests.
* *
* @author Roy Wetherall * @author Roy Wetherall
* @since 2.2 * @since 2.2
*/ */
public class RejectRecordTest extends BaseRMTestCase public class RejectRecordTest extends BaseRMTestCase
{ {
private VersionService versionService; private VersionService versionService;
private static final String REASON = GUID.generate(); private static final String REASON = GUID.generate();
@Override @Override
protected boolean isUserTest() protected boolean isUserTest()
{ {
return true; return true;
} }
@Override @Override
protected boolean isCollaborationSiteTest() protected boolean isCollaborationSiteTest()
{ {
return true; return true;
} }
@Override @Override
protected void initServices() protected void initServices()
{ {
super.initServices(); super.initServices();
versionService = (VersionService)applicationContext.getBean("VersionService"); versionService = (VersionService)applicationContext.getBean("VersionService");
} }
/** /**
* *
*/ */
public void testRejectedRecordInCorrectState() throws Exception public void testRejectedRecordInCorrectState() throws Exception
{ {
@@ -71,30 +71,30 @@ public class RejectRecordTest extends BaseRMTestCase
public void given() public void given()
{ {
assertFalse(recordService.isRecord(dmDocument)); assertFalse(recordService.isRecord(dmDocument));
ownableService.setOwner(dmDocument, userName); ownableService.setOwner(dmDocument, userName);
// document is declared as a record by user // document is declared as a record by user
AuthenticationUtil.runAs(new RunAsWork<Void>() AuthenticationUtil.runAs(new RunAsWork<Void>()
{ {
public Void doWork() throws Exception public Void doWork() throws Exception
{ {
// declare record // declare record
recordService.createRecord(filePlan, dmDocument); recordService.createRecord(filePlan, dmDocument);
return null; return null;
} }
}, userName); }, userName);
} }
public void when() public void when()
{ {
// sanity checks // sanity checks
assertTrue(recordService.isRecord(dmDocument)); assertTrue(recordService.isRecord(dmDocument));
assertFalse(permissionService.getInheritParentPermissions(dmDocument)); assertTrue(permissionService.getInheritParentPermissions(dmDocument));
// declare record // declare record
recordService.rejectRecord(dmDocument, REASON); recordService.rejectRecord(dmDocument, REASON);
} }
public void then() public void then()
{ {
// document is no longer a record // document is no longer a record
@@ -105,47 +105,47 @@ public class RejectRecordTest extends BaseRMTestCase
assertTrue(permissionService.getInheritParentPermissions(dmDocument)); assertTrue(permissionService.getInheritParentPermissions(dmDocument));
assertFalse(nodeService.hasAspect(dmDocument, ASPECT_FILE_PLAN_COMPONENT)); assertFalse(nodeService.hasAspect(dmDocument, ASPECT_FILE_PLAN_COMPONENT));
} }
}); });
} }
/** /**
* *
*/ */
public void testRevertAfterReject() throws Exception public void testRevertAfterReject() throws Exception
{ {
doBehaviourDrivenTest(new BehaviourDrivenTest() doBehaviourDrivenTest(new BehaviourDrivenTest()
{; {;
private NodeRef document; private NodeRef document;
public void given() public void given()
{ {
NodeRef folder = fileFolderService.create(documentLibrary, GUID.generate(), TYPE_FOLDER).getNodeRef(); NodeRef folder = fileFolderService.create(documentLibrary, GUID.generate(), TYPE_FOLDER).getNodeRef();
document = fileFolderService.create(folder, GUID.generate(), TYPE_CONTENT).getNodeRef(); document = fileFolderService.create(folder, GUID.generate(), TYPE_CONTENT).getNodeRef();
assertFalse(recordService.isRecord(document)); assertFalse(recordService.isRecord(document));
ownableService.setOwner(document, userName); ownableService.setOwner(document, userName);
versionService.ensureVersioningEnabled(document, null); versionService.ensureVersioningEnabled(document, null);
// document is declared as a record by user // document is declared as a record by user
AuthenticationUtil.runAs(new RunAsWork<Void>() AuthenticationUtil.runAs(new RunAsWork<Void>()
{ {
public Void doWork() throws Exception public Void doWork() throws Exception
{ {
// declare record // declare record
recordService.createRecord(filePlan, document); recordService.createRecord(filePlan, document);
return null; return null;
} }
}, userName); }, userName);
assertTrue(nodeService.hasAspect(document, ASPECT_FILE_PLAN_COMPONENT)); assertTrue(nodeService.hasAspect(document, ASPECT_FILE_PLAN_COMPONENT));
} }
public void when() public void when()
{ {
// reject the record // reject the record
recordService.rejectRecord(document, REASON); recordService.rejectRecord(document, REASON);
assertFalse(nodeService.hasAspect(document, ASPECT_FILE_PLAN_COMPONENT)); assertFalse(nodeService.hasAspect(document, ASPECT_FILE_PLAN_COMPONENT));
// upload a new version of the document // upload a new version of the document
AuthenticationUtil.runAs(new RunAsWork<Void>() AuthenticationUtil.runAs(new RunAsWork<Void>()
{ {
@@ -154,31 +154,31 @@ public class RejectRecordTest extends BaseRMTestCase
ContentWriter writer = contentService.getWriter(document, ContentModel.PROP_CONTENT, true); ContentWriter writer = contentService.getWriter(document, ContentModel.PROP_CONTENT, true);
writer.putContent("This is a change to the content and should force a new version"); writer.putContent("This is a change to the content and should force a new version");
versionService.createVersion(document, null); versionService.createVersion(document, null);
return null; return null;
} }
}, userName); }, userName);
assertFalse(nodeService.hasAspect(document, ASPECT_FILE_PLAN_COMPONENT)); assertFalse(nodeService.hasAspect(document, ASPECT_FILE_PLAN_COMPONENT));
VersionHistory history = versionService.getVersionHistory(document); VersionHistory history = versionService.getVersionHistory(document);
assertEquals(2, history.getAllVersions().size()); assertEquals(2, history.getAllVersions().size());
final Version initial = history.getRootVersion(); final Version initial = history.getRootVersion();
assertFalse(nodeService.hasAspect(initial.getFrozenStateNodeRef(), ASPECT_FILE_PLAN_COMPONENT)); assertFalse(nodeService.hasAspect(initial.getFrozenStateNodeRef(), ASPECT_FILE_PLAN_COMPONENT));
AuthenticationUtil.runAs(new RunAsWork<Void>() AuthenticationUtil.runAs(new RunAsWork<Void>()
{ {
public Void doWork() throws Exception public Void doWork() throws Exception
{ {
// revert the document to a previous version // revert the document to a previous version
versionService.revert(document, initial); versionService.revert(document, initial);
return null; return null;
} }
}, userName); }, userName);
} }
public void then() public void then()
{ {
// document is no longer a record // document is no longer a record
@@ -187,6 +187,6 @@ public class RejectRecordTest extends BaseRMTestCase
// expected owner has be re-set // expected owner has be re-set
assertEquals(userName, ownableService.getOwner(document)); assertEquals(userName, ownableService.getOwner(document));
} }
}); });
} }
} }

View File

@@ -60,7 +60,7 @@ public class DeclarativeCapabilityTest extends BaseRMTestCase
private NodeRef moveToFolder; private NodeRef moveToFolder;
private NodeRef moveToCategory; private NodeRef moveToCategory;
private NodeRef hold; private NodeRef hold;
@Override @Override
@@ -109,9 +109,9 @@ public class DeclarativeCapabilityTest extends BaseRMTestCase
utils.completeRecord(declaredRecord); utils.completeRecord(declaredRecord);
utils.completeRecord(frozenRecord); utils.completeRecord(frozenRecord);
utils.completeRecord(frozenRecord2); utils.completeRecord(frozenRecord2);
hold = holdService.createHold(filePlan, GUID.generate(), "reason", "description"); hold = holdService.createHold(filePlan, GUID.generate(), "reason", "description");
holdService.addToHold(hold, frozenRecord); holdService.addToHold(hold, frozenRecord);
holdService.addToHold(hold, frozenRecordFolder); holdService.addToHold(hold, frozenRecordFolder);
holdService.addToHold(hold, frozenRecord2); holdService.addToHold(hold, frozenRecord2);
@@ -141,6 +141,7 @@ public class DeclarativeCapabilityTest extends BaseRMTestCase
for (String user : testUsers) for (String user : testUsers)
{ {
filePlanPermissionService.setPermission(rmFolder, user, RMPermissionModel.FILING); filePlanPermissionService.setPermission(rmFolder, user, RMPermissionModel.FILING);
filePlanPermissionService.setPermission(rmContainer, user, RMPermissionModel.READ_RECORDS);
filePlanPermissionService.setPermission(moveToFolder, user, RMPermissionModel.READ_RECORDS); filePlanPermissionService.setPermission(moveToFolder, user, RMPermissionModel.READ_RECORDS);
filePlanPermissionService.setPermission(moveToCategory, user, RMPermissionModel.READ_RECORDS); filePlanPermissionService.setPermission(moveToCategory, user, RMPermissionModel.READ_RECORDS);
} }

View File

@@ -23,9 +23,15 @@ import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.site.SiteModel;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.cmr.site.SiteVisibility;
import org.alfresco.util.GUID; import org.alfresco.util.GUID;
/** /**
@@ -237,4 +243,115 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
assertNotNull(readers); assertNotNull(readers);
assertEquals(testMap.size(), readers.size()); assertEquals(testMap.size(), readers.size());
} }
public void testDifferentUsersDifferentPermissions()
{
final String userNone = createTestUser();
final String userRead = createTestUser();
final String userWrite = createTestUser();
final String siteShortName = GUID.generate();
doTestInTransaction(new Test<Void>()
{
public Void run() throws Exception
{
siteService.createSite(null, siteShortName, "test", "test", SiteVisibility.PRIVATE);
return null;
}
});
final NodeRef documentLibrary = doTestInTransaction(new Test<NodeRef>()
{
public NodeRef run() throws Exception
{
siteService.setMembership(siteShortName, userRead, SiteModel.SITE_CONSUMER);
siteService.setMembership(siteShortName, userWrite, SiteModel.SITE_COLLABORATOR);
return siteService.createContainer(siteShortName, SiteService.DOCUMENT_LIBRARY, null, null);
}
});
final NodeRef record = doTestInTransaction(new Test<NodeRef>()
{
public NodeRef run() throws Exception
{
NodeRef record = fileFolderService.create(documentLibrary, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef();
recordService.createRecord(filePlan, record);
return record;
}
});
doTestInTransaction(new Test<Void>()
{
public Void run() throws Exception
{
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
// check permissions
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, READ_RECORDS));
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, FILING));
return null;
}
}, userNone);
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
// check permissions
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, READ_RECORDS));
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, FILING));
return null;
}
}, userRead);
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
// check permissions
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, READ_RECORDS));
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, FILING));
return null;
}
}, userWrite);
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
// check permissions
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, READ_RECORDS));
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, FILING));
return null;
}
}, userNone);
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
// check permissions
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, READ_RECORDS));
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, FILING));
return null;
}
}, userRead);
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
// check permissions
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, READ_RECORDS));
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, FILING));
return null;
}
}, userWrite);
return null;
}
});
}
} }

View File

@@ -107,9 +107,9 @@ public class FilePlanRoleServiceImplTest extends BaseRMTestCase
{ {
public Void run() public Void run()
{ {
Role role = filePlanRoleService.getRole(filePlan, ROLE_NAME_POWER_USER); Role role = filePlanRoleService.getRole(filePlan, FilePlanRoleService.ROLE_POWER_USER);
assertNotNull(role); assertNotNull(role);
assertEquals(ROLE_NAME_POWER_USER, role.getName()); assertEquals(FilePlanRoleService.ROLE_POWER_USER, role.getName());
role = filePlanRoleService.getRole(filePlan, "donkey"); role = filePlanRoleService.getRole(filePlan, "donkey");
assertNull(role); assertNull(role);
@@ -125,7 +125,7 @@ public class FilePlanRoleServiceImplTest extends BaseRMTestCase
{ {
public Void run() public Void run()
{ {
assertTrue(filePlanRoleService.existsRole(filePlan, ROLE_NAME_POWER_USER)); assertTrue(filePlanRoleService.existsRole(filePlan, FilePlanRoleService.ROLE_POWER_USER));
assertFalse(filePlanRoleService.existsRole(filePlan, "donkey")); assertFalse(filePlanRoleService.existsRole(filePlan, "donkey"));
return null; return null;
@@ -184,33 +184,33 @@ public class FilePlanRoleServiceImplTest extends BaseRMTestCase
assertNotNull(roles); assertNotNull(roles);
assertEquals(1, roles.size()); assertEquals(1, roles.size());
Set<String> authorities = filePlanRoleService.getUsersAssignedToRole(filePlan, ROLE_NAME_RECORDS_MANAGER); Set<String> authorities = filePlanRoleService.getUsersAssignedToRole(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER);
assertNotNull(authorities); assertNotNull(authorities);
assertEquals(1, authorities.size()); assertEquals(1, authorities.size());
authorities = filePlanRoleService.getGroupsAssignedToRole(filePlan, ROLE_NAME_RECORDS_MANAGER); authorities = filePlanRoleService.getGroupsAssignedToRole(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER);
assertNotNull(authorities); assertNotNull(authorities);
assertEquals(0, authorities.size()); assertEquals(0, authorities.size());
authorities = filePlanRoleService.getAllAssignedToRole(filePlan, ROLE_NAME_RECORDS_MANAGER); authorities = filePlanRoleService.getAllAssignedToRole(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER);
assertNotNull(authorities); assertNotNull(authorities);
assertEquals(1, authorities.size()); assertEquals(1, authorities.size());
filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_NAME_RECORDS_MANAGER, rmUserName); filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, rmUserName);
roles = filePlanRoleService.getRolesByUser(filePlan, rmUserName); roles = filePlanRoleService.getRolesByUser(filePlan, rmUserName);
assertNotNull(roles); assertNotNull(roles);
assertEquals(2, roles.size()); assertEquals(2, roles.size());
authorities = filePlanRoleService.getUsersAssignedToRole(filePlan, ROLE_NAME_RECORDS_MANAGER); authorities = filePlanRoleService.getUsersAssignedToRole(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER);
assertNotNull(authorities); assertNotNull(authorities);
assertEquals(2, authorities.size()); assertEquals(2, authorities.size());
authorities = filePlanRoleService.getGroupsAssignedToRole(filePlan, ROLE_NAME_RECORDS_MANAGER); authorities = filePlanRoleService.getGroupsAssignedToRole(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER);
assertNotNull(authorities); assertNotNull(authorities);
assertEquals(0, authorities.size()); assertEquals(0, authorities.size());
authorities = filePlanRoleService.getAllAssignedToRole(filePlan, ROLE_NAME_RECORDS_MANAGER); authorities = filePlanRoleService.getAllAssignedToRole(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER);
assertNotNull(authorities); assertNotNull(authorities);
assertEquals(2, authorities.size()); assertEquals(2, authorities.size());

View File

@@ -272,10 +272,12 @@ public class RecordServiceImplTest extends BaseRMTestCase
// create record from document // create record from document
doTestInTransaction(new Test<Void>() doTestInTransaction(new Test<Void>()
{ {
private NodeRef originalLocation;
@Override @Override
public Void run() public Void run()
{ {
NodeRef originalLocation = nodeService.getPrimaryParent(dmDocument).getParentRef(); originalLocation = nodeService.getPrimaryParent(dmDocument).getParentRef();
assertFalse(recordService.isRecord(dmDocument)); assertFalse(recordService.isRecord(dmDocument));
assertFalse(extendedSecurityService.hasExtendedSecurity(dmDocument)); assertFalse(extendedSecurityService.hasExtendedSecurity(dmDocument));
@@ -297,6 +299,11 @@ public class RecordServiceImplTest extends BaseRMTestCase
recordService.createRecord(filePlan, dmDocument); recordService.createRecord(filePlan, dmDocument);
return null;
}
public void test(Void result)
{
checkPermissions(READ_RECORDS, AccessStatus.ALLOWED, // file checkPermissions(READ_RECORDS, AccessStatus.ALLOWED, // file
// plan // plan
AccessStatus.ALLOWED, // unfiled container AccessStatus.ALLOWED, // unfiled container
@@ -345,8 +352,6 @@ public class RecordServiceImplTest extends BaseRMTestCase
Capability updateProperties = capabilityService.getCapability("UpdateProperties"); Capability updateProperties = capabilityService.getCapability("UpdateProperties");
assertEquals(AccessStatus.ALLOWED, updateProperties.hasPermission(dmDocument)); assertEquals(AccessStatus.ALLOWED, updateProperties.hasPermission(dmDocument));
return null;
} }
}, dmCollaborator); }, dmCollaborator);

View File

@@ -25,7 +25,7 @@ import org.alfresco.module.org_alfresco_module_rm.search.SavedSearchDetails;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.util.Pair;
import org.alfresco.util.TestWithUserUtils; import org.alfresco.util.TestWithUserUtils;
/** /**
@@ -148,7 +148,7 @@ public class RecordsManagementSearchServiceImplTest extends BaseRMTestCase
// String query = "keywords:\"elephant\""; // String query = "keywords:\"elephant\"";
// RecordsManagementSearchParameters params = new RecordsManagementSearchParameters(); // RecordsManagementSearchParameters params = new RecordsManagementSearchParameters();
// params.setIncludeUndeclaredRecords(true); // params.setIncludeUndeclaredRecords(true);
// List<NodeRef> results = rmSearchService.search(siteId, query, params); // List<Pair<NodeRef, NodeRef>> results = rmSearchService.search(siteId, query, params);
// assertNotNull(results); // assertNotNull(results);
// assertEquals(2, results.size()); // assertEquals(2, results.size());
// //

View File

@@ -6,6 +6,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
@@ -117,7 +118,7 @@ public class DataLoadSystemTest
final SiteInfo site = siteService.getSite("test"); final SiteInfo site = siteService.getSite("test");
if (site == null) if (site == null)
{ {
Assert.fail("The collab site test is not present."); throw new AlfrescoRuntimeException("The collab site test is not present.");
} }
final NodeRef filePlan = filePlanService.getFilePlanBySiteId(FilePlanService.DEFAULT_RM_SITE_ID); final NodeRef filePlan = filePlanService.getFilePlanBySiteId(FilePlanService.DEFAULT_RM_SITE_ID);
@@ -146,7 +147,6 @@ public class DataLoadSystemTest
// create content and declare as record // create content and declare as record
repeatInTransactionBatches(new RunAsWork<Void>() repeatInTransactionBatches(new RunAsWork<Void>()
{ {
@SuppressWarnings("null")
public Void doWork() throws Exception public Void doWork() throws Exception
{ {
// create document // create document

View File

@@ -173,6 +173,8 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
protected NodeRef rmFolder; protected NodeRef rmFolder;
protected NodeRef unfiledContainer; protected NodeRef unfiledContainer;
protected String collabSiteId; protected String collabSiteId;
protected NodeRef holdsContainer;
protected NodeRef transfersContainer;
/** multi-hierarchy test data /** multi-hierarchy test data
* *
@@ -506,6 +508,14 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
// unfiled container // unfiled container
unfiledContainer = filePlanService.getUnfiledContainer(filePlan); unfiledContainer = filePlanService.getUnfiledContainer(filePlan);
assertNotNull(unfiledContainer); assertNotNull(unfiledContainer);
// holds container
holdsContainer = filePlanService.getHoldContainer(filePlan);
assertNotNull(holdsContainer);
// transfers container
transfersContainer = filePlanService.getTransferContainer(filePlan);
assertNotNull(transfersContainer);
} }
} }
}, AuthenticationUtil.getSystemUserName()); }, AuthenticationUtil.getSystemUserName());

View File

@@ -36,43 +36,41 @@ import org.mockito.InjectMocks;
/** /**
* Unit test for RecordServiceImpl * Unit test for RecordServiceImpl
* *
* @author Roy Wetherall * @author Roy Wetherall
* @since 2.2 * @since 2.2
*/ */
public class RecordServiceImplUnitTest extends BaseUnitTest public class RecordServiceImplUnitTest extends BaseUnitTest
{ {
private NodeRef nonStandardFilePlanComponent; private NodeRef nonStandardFilePlanComponent;
private NodeRef nonStandardFilePlan; private NodeRef nonStandardFilePlan;
private static QName TYPE_MY_FILE_PLAN = generateQName(); private static QName TYPE_MY_FILE_PLAN = generateQName();
private static QName ASPECT_FOR_FILE_PLAN = generateQName(); private static QName ASPECT_FOR_FILE_PLAN = generateQName();
private static QName ASPECT_FOR_MY_FILE_PLAN = generateQName();
private static QName ASPECT_FOR_BOTH = generateQName();
@InjectMocks private RecordServiceImpl recordService; @InjectMocks private RecordServiceImpl recordService;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Before @Before
@Override @Override
public void before() throws Exception public void before() throws Exception
{ {
super.before(); super.before();
nonStandardFilePlanComponent = generateNodeRef(TYPE_RECORD_CATEGORY); nonStandardFilePlanComponent = generateNodeRef(TYPE_RECORD_CATEGORY);
nonStandardFilePlan = generateNodeRef(TYPE_MY_FILE_PLAN); nonStandardFilePlan = generateNodeRef(TYPE_MY_FILE_PLAN);
// set-up node service // set-up node service
when(mockedNodeService.getProperty(nonStandardFilePlanComponent, PROP_ROOT_NODEREF)).thenReturn(nonStandardFilePlan); when(mockedNodeService.getProperty(nonStandardFilePlanComponent, PROP_ROOT_NODEREF)).thenReturn(nonStandardFilePlan);
// set-up dictionary service // set-up dictionary service
when(mockedDictionaryService.getAllAspects()).thenReturn(CollectionUtils.EMPTY_COLLECTION); when(mockedDictionaryService.getAllAspects()).thenReturn(CollectionUtils.EMPTY_COLLECTION);
} }
@Test @Test
public void testRegisterRecordMetadataAspect() public void testRegisterRecordMetadataAspect()
{ {
Map<QName, Set<QName>> map = recordService.getRecordMetadataAspectsMap(); Map<QName, Set<QName>> map = recordService.getRecordMetadataAspectsMap();
assertTrue(map.isEmpty()); assertTrue(map.isEmpty());
recordService.registerRecordMetadataAspect(ASPECT_FOR_FILE_PLAN, TYPE_FILE_PLAN); recordService.registerRecordMetadataAspect(ASPECT_FOR_FILE_PLAN, TYPE_FILE_PLAN);
map = recordService.getRecordMetadataAspectsMap(); map = recordService.getRecordMetadataAspectsMap();
@@ -83,39 +81,4 @@ public class RecordServiceImplUnitTest extends BaseUnitTest
assertEquals(1, types.size()); assertEquals(1, types.size());
assertTrue(types.contains(TYPE_FILE_PLAN)); assertTrue(types.contains(TYPE_FILE_PLAN));
} }
@Test
public void testGetRecordMetadataAspects()
{
// register a couple of record meta-data aspects
recordService.registerRecordMetadataAspect(ASPECT_FOR_FILE_PLAN, TYPE_FILE_PLAN);
recordService.registerRecordMetadataAspect(ASPECT_FOR_MY_FILE_PLAN, TYPE_MY_FILE_PLAN);
recordService.registerRecordMetadataAspect(ASPECT_FOR_BOTH, TYPE_FILE_PLAN);
recordService.registerRecordMetadataAspect(ASPECT_FOR_BOTH, TYPE_MY_FILE_PLAN);
Set<QName> set = recordService.getRecordMetadataAspects(filePlanComponent);
assertNotNull(set);
assertEquals(2, set.size());
assertTrue(set.contains(ASPECT_FOR_FILE_PLAN));
assertTrue(set.contains(ASPECT_FOR_BOTH));
set = recordService.getRecordMetadataAspects(nonStandardFilePlanComponent);
assertNotNull(set);
assertEquals(2, set.size());
assertTrue(set.contains(ASPECT_FOR_MY_FILE_PLAN));
assertTrue(set.contains(ASPECT_FOR_BOTH));
set = recordService.getRecordMetadataAspects(TYPE_FILE_PLAN);
assertNotNull(set);
assertEquals(2, set.size());
assertTrue(set.contains(ASPECT_FOR_FILE_PLAN));
assertTrue(set.contains(ASPECT_FOR_BOTH));
set = recordService.getRecordMetadataAspects(TYPE_MY_FILE_PLAN);
assertNotNull(set);
assertEquals(2, set.size());
assertTrue(set.contains(ASPECT_FOR_MY_FILE_PLAN));
assertTrue(set.contains(ASPECT_FOR_BOTH));
}
} }