mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
RM-477: RM 2.0 does not work with SOLR
* first pass at supporting SOLR in RM2 * currently requires reimplementation of permissionServiceImpl due to visibility of methods and member variables * job execution delayed to try and prevent start up errors * fetchSOLR task added to gradle to retrieve SOLR zip from Maven (could do with some scripts to help with setup for module) * TODO more testing and refinement of solution git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/BRANCHES/V2.0-BUG-FIX@40344 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -239,6 +239,13 @@ subprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task localisationPackage (type: Copy) << {
|
||||||
|
|
||||||
|
from configDir
|
||||||
|
include "**/*.properties"
|
||||||
|
into "${assembleDir}/i18n"
|
||||||
|
}
|
||||||
|
|
||||||
task deployExploded(dependsOn: 'jar') << {
|
task deployExploded(dependsOn: 'jar') << {
|
||||||
|
|
||||||
def jarFileObj = file(jarFilePath)
|
def jarFileObj = file(jarFilePath)
|
||||||
|
@@ -13,6 +13,17 @@ dependencies {
|
|||||||
testRuntime files(testResourceDir)
|
testRuntime files(testResourceDir)
|
||||||
|
|
||||||
testRuntime group: 'org.alfresco.enterprise', name: 'alfresco', version: alfrescoBaseVersion, type: 'war'
|
testRuntime group: 'org.alfresco.enterprise', name: 'alfresco', version: alfrescoBaseVersion, type: 'war'
|
||||||
|
testRuntime group: 'org.alfresco.enterprise', name: 'alfresco-solr', version: alfrescoBaseVersion, type: 'zip'
|
||||||
|
}
|
||||||
|
|
||||||
|
task fetchSOLR(type:Copy) {
|
||||||
|
from configurations.testRuntime
|
||||||
|
into '.'
|
||||||
|
include '*.zip'
|
||||||
|
rename { String filename -> solrFile }
|
||||||
|
}
|
||||||
|
|
||||||
|
task useSOLR << {
|
||||||
}
|
}
|
||||||
|
|
||||||
task resetDatabase << {
|
task resetDatabase << {
|
||||||
|
@@ -2,6 +2,53 @@
|
|||||||
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||||
|
|
||||||
<beans>
|
<beans>
|
||||||
|
<bean id="permissionServiceImpl" class="org.alfresco.module.org_alfresco_module_rm.permission.PermissionServiceImpl" init-method="init">
|
||||||
|
<property name="nodeService">
|
||||||
|
<ref bean="mtAwareNodeService" />
|
||||||
|
</property>
|
||||||
|
<property name="tenantService">
|
||||||
|
<ref bean="tenantService"/>
|
||||||
|
</property>
|
||||||
|
<property name="dictionaryService">
|
||||||
|
<ref bean="dictionaryService" />
|
||||||
|
</property>
|
||||||
|
<property name="permissionsDaoComponent">
|
||||||
|
<ref bean="permissionsDaoComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="modelDAO">
|
||||||
|
<ref bean="permissionsModelDAO" />
|
||||||
|
</property>
|
||||||
|
<property name="authorityService">
|
||||||
|
<ref bean="authorityService" />
|
||||||
|
</property>
|
||||||
|
<property name="accessCache">
|
||||||
|
<ref bean="permissionsAccessCache" />
|
||||||
|
</property>
|
||||||
|
<property name="readersCache">
|
||||||
|
<ref bean="readersCache" />
|
||||||
|
</property>
|
||||||
|
<property name="readersDeniedCache">
|
||||||
|
<ref bean="readersDeniedCache" />
|
||||||
|
</property>
|
||||||
|
<property name="policyComponent">
|
||||||
|
<ref bean="policyComponent" />
|
||||||
|
</property>
|
||||||
|
<property name="aclDAO">
|
||||||
|
<ref bean="aclDAO" />
|
||||||
|
</property>
|
||||||
|
<property name="ownableService">
|
||||||
|
<ref bean="ownableService" />
|
||||||
|
</property>
|
||||||
|
<property name="anyDenyDenies">
|
||||||
|
<value>${security.anyDenyDenies}</value>
|
||||||
|
</property>
|
||||||
|
<property name="dynamicAuthorities">
|
||||||
|
<list>
|
||||||
|
<ref bean="ownerDynamicAuthority" />
|
||||||
|
<ref bean="lockOwnerDynamicAuthority" />
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<!-- Bootstrap records management data -->
|
<!-- Bootstrap records management data -->
|
||||||
<bean id="org_alfresco_module_rm_bootstrapData"
|
<bean id="org_alfresco_module_rm_bootstrapData"
|
||||||
|
@@ -292,7 +292,7 @@
|
|||||||
{
|
{
|
||||||
"name" : "Vital Records Due For Review",
|
"name" : "Vital Records Due For Review",
|
||||||
"description" : "All records currently due for review.",
|
"description" : "All records currently due for review.",
|
||||||
"search" : "reviewAsOf:[MIN TO TODAY]",
|
"search" : "rma:reviewAsOf:[MIN TO TODAY]",
|
||||||
"searchparams" :
|
"searchparams" :
|
||||||
{
|
{
|
||||||
"records" : true,
|
"records" : true,
|
||||||
|
@@ -3,5 +3,6 @@ moduleid=org_alfresco_module_rm
|
|||||||
|
|
||||||
webAppName=alfresco
|
webAppName=alfresco
|
||||||
warFile=alfresco.war
|
warFile=alfresco.war
|
||||||
|
solrFile=alfresco-solr.zip
|
||||||
|
|
||||||
tomcatEnv=TOMCAT_HOME
|
tomcatEnv=TOMCAT_HOME
|
@@ -473,8 +473,11 @@ public class RMAfterInvocationProvider extends RMSecurityCommon
|
|||||||
{
|
{
|
||||||
inclusionMask.set(i, true);
|
inclusionMask.set(i, true);
|
||||||
}
|
}
|
||||||
filteringResultSet.setResultSetMetaData(new SimpleResultSetMetaData(returnedObject.getResultSetMetaData().getLimitedBy(), PermissionEvaluationMode.EAGER, returnedObject.getResultSetMetaData()
|
filteringResultSet.setResultSetMetaData(
|
||||||
.getSearchParameters()));
|
new SimpleResultSetMetaData(
|
||||||
|
returnedObject.getResultSetMetaData().getLimitedBy(),
|
||||||
|
PermissionEvaluationMode.EAGER,
|
||||||
|
returnedObject.getResultSetMetaData().getSearchParameters()));
|
||||||
return filteringResultSet;
|
return filteringResultSet;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -483,27 +486,37 @@ public class RMAfterInvocationProvider extends RMSecurityCommon
|
|||||||
{
|
{
|
||||||
inclusionMask.set(i, true);
|
inclusionMask.set(i, true);
|
||||||
}
|
}
|
||||||
filteringResultSet.setResultSetMetaData(new SimpleResultSetMetaData(returnedObject.getResultSetMetaData().getLimitedBy(), PermissionEvaluationMode.EAGER, returnedObject.getResultSetMetaData()
|
filteringResultSet.setResultSetMetaData(
|
||||||
.getSearchParameters()));
|
new SimpleResultSetMetaData(
|
||||||
|
returnedObject.getResultSetMetaData().getLimitedBy(),
|
||||||
|
PermissionEvaluationMode.EAGER,
|
||||||
|
returnedObject.getResultSetMetaData().getSearchParameters()));
|
||||||
return filteringResultSet;
|
return filteringResultSet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// record the start time
|
// record the start time
|
||||||
long startTimeMillis = System.currentTimeMillis();
|
long startTimeMillis = System.currentTimeMillis();
|
||||||
|
|
||||||
// set the default, unlimited resultset type
|
// set the default, unlimited resultset type
|
||||||
filteringResultSet.setResultSetMetaData(new SimpleResultSetMetaData(returnedObject.getResultSetMetaData().getLimitedBy(), PermissionEvaluationMode.EAGER, returnedObject.getResultSetMetaData()
|
filteringResultSet.setResultSetMetaData(
|
||||||
.getSearchParameters()));
|
new SimpleResultSetMetaData(
|
||||||
|
returnedObject.getResultSetMetaData().getLimitedBy(),
|
||||||
|
PermissionEvaluationMode.EAGER,
|
||||||
|
returnedObject.getResultSetMetaData().getSearchParameters()));
|
||||||
|
|
||||||
for (int i = 0; i < returnedObject.length(); i++)
|
for (int i = 0; i < returnedObject.length(); i++)
|
||||||
{
|
{
|
||||||
long currentTimeMillis = System.currentTimeMillis();
|
long currentTimeMillis = System.currentTimeMillis();
|
||||||
if (i >= maxChecks || (currentTimeMillis - startTimeMillis) > maxCheckTime)
|
// if (i >= maxChecks || (currentTimeMillis - startTimeMillis) > maxCheckTime)
|
||||||
{
|
// {
|
||||||
filteringResultSet.setResultSetMetaData(new SimpleResultSetMetaData(LimitBy.NUMBER_OF_PERMISSION_EVALUATIONS, PermissionEvaluationMode.EAGER, returnedObject
|
// filteringResultSet.setResultSetMetaData(
|
||||||
.getResultSetMetaData().getSearchParameters()));
|
// new SimpleResultSetMetaData(
|
||||||
break;
|
// LimitBy.NUMBER_OF_PERMISSION_EVALUATIONS,
|
||||||
}
|
// PermissionEvaluationMode.EAGER,
|
||||||
|
// returnedObject.getResultSetMetaData().getSearchParameters()));
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
// All permission checks must pass
|
// All permission checks must pass
|
||||||
inclusionMask.set(i, true);
|
inclusionMask.set(i, true);
|
||||||
|
@@ -106,13 +106,14 @@ public class RMSecurityCommon
|
|||||||
*/
|
*/
|
||||||
public int checkRead(NodeRef nodeRef)
|
public int checkRead(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
|
int result = AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||||
if (nodeRef != null)
|
if (nodeRef != null)
|
||||||
{
|
{
|
||||||
// now we know the node - we can abstain for certain types and aspects (eg, rm)
|
// now we know the node - we can abstain for certain types and aspects (eg, rm)
|
||||||
return checkRead(nodeRef, false);
|
result = checkRead(nodeRef, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return AccessDecisionVoter.ACCESS_ABSTAIN;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,35 +124,32 @@ public class RMSecurityCommon
|
|||||||
*/
|
*/
|
||||||
public int checkRead(NodeRef nodeRef, boolean allowDMRead)
|
public int checkRead(NodeRef nodeRef, boolean allowDMRead)
|
||||||
{
|
{
|
||||||
if (nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT))
|
int result = AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||||
|
|
||||||
|
if (rmService.isFilePlanComponent(nodeRef) == true)
|
||||||
{
|
{
|
||||||
return checkRmRead(nodeRef);
|
result = checkRmRead(nodeRef);
|
||||||
}
|
}
|
||||||
else
|
else if (allowDMRead == true)
|
||||||
{
|
{
|
||||||
if (allowDMRead)
|
// Check DM read for copy etc
|
||||||
|
// DM does not grant - it can only deny
|
||||||
|
if (permissionService.hasPermission(nodeRef, PermissionService.READ) == AccessStatus.DENIED)
|
||||||
{
|
{
|
||||||
// Check DM read for copy etc
|
if (logger.isDebugEnabled())
|
||||||
// DM does not grant - it can only deny
|
|
||||||
if (permissionService.hasPermission(nodeRef, PermissionService.READ) == AccessStatus.DENIED)
|
|
||||||
{
|
{
|
||||||
if (logger.isDebugEnabled())
|
logger.debug("\t\tPermission is denied");
|
||||||
{
|
Thread.dumpStack();
|
||||||
logger.debug("\t\tPermission is denied");
|
|
||||||
Thread.dumpStack();
|
|
||||||
}
|
|
||||||
return AccessDecisionVoter.ACCESS_DENIED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
|
||||||
}
|
}
|
||||||
|
result = AccessDecisionVoter.ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return AccessDecisionVoter.ACCESS_ABSTAIN;
|
result = AccessDecisionVoter.ACCESS_GRANTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -72,7 +72,7 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
|
|||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.job.RecordsManagementJobExecuter#execute()
|
* @see org.alfresco.module.org_alfresco_module_rm.job.RecordsManagementJobExecuter#execute()
|
||||||
*/
|
*/
|
||||||
public void execute()
|
public void executeImpl()
|
||||||
{
|
{
|
||||||
logger.debug("Job Starting");
|
logger.debug("Job Starting");
|
||||||
|
|
||||||
|
@@ -69,7 +69,7 @@ public class NotifyOfRecordsDueForReviewJobExecuter extends RecordsManagementJob
|
|||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.job.RecordsManagementJobExecuter#execute()
|
* @see org.alfresco.module.org_alfresco_module_rm.job.RecordsManagementJobExecuter#execute()
|
||||||
*/
|
*/
|
||||||
public void execute()
|
public void executeImpl()
|
||||||
{
|
{
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
|
@@ -80,7 +80,7 @@ public class PublishUpdatesJobExecuter extends RecordsManagementJobExecuter
|
|||||||
this.behaviourFilter = behaviourFilter;
|
this.behaviourFilter = behaviourFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute()
|
public void executeImpl()
|
||||||
{
|
{
|
||||||
if (logger.isDebugEnabled() == true)
|
if (logger.isDebugEnabled() == true)
|
||||||
{
|
{
|
||||||
|
@@ -20,18 +20,73 @@ package org.alfresco.module.org_alfresco_module_rm.job;
|
|||||||
|
|
||||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Records management job executer base class.
|
||||||
|
*
|
||||||
* @author Roy Wetherall
|
* @author Roy Wetherall
|
||||||
*/
|
*/
|
||||||
public abstract class RecordsManagementJobExecuter implements RecordsManagementModel
|
public abstract class RecordsManagementJobExecuter extends AbstractLifecycleBean
|
||||||
|
implements RecordsManagementModel
|
||||||
{
|
{
|
||||||
|
/** Retrying transaction helper */
|
||||||
protected RetryingTransactionHelper retryingTransactionHelper;
|
protected RetryingTransactionHelper retryingTransactionHelper;
|
||||||
|
|
||||||
|
/** Indicates whether the application bootstrap is complete or not */
|
||||||
|
protected boolean bootstrapComplete = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param retryingTransactionHelper retrying transaction helper
|
||||||
|
*/
|
||||||
public void setRetryingTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
|
public void setRetryingTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
|
||||||
{
|
{
|
||||||
this.retryingTransactionHelper = retryingTransactionHelper;
|
this.retryingTransactionHelper = retryingTransactionHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void execute();
|
/**
|
||||||
|
* Executes the jobs work.
|
||||||
|
*/
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
// jobs not allowed to execute unless bootstrap is complete
|
||||||
|
if (bootstrapComplete == true)
|
||||||
|
{
|
||||||
|
executeImpl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jobs work implementation.
|
||||||
|
*/
|
||||||
|
public abstract void executeImpl();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.springframework.extensions.surf.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void onBootstrap(ApplicationEvent arg0)
|
||||||
|
{
|
||||||
|
// record that the bootstrap has complete
|
||||||
|
bootstrapComplete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.springframework.extensions.surf.util.AbstractLifecycleBean#onShutdown(org.springframework.context.ApplicationEvent)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void onShutdown(ApplicationEvent arg0)
|
||||||
|
{
|
||||||
|
// no implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.springframework.extensions.surf.util.AbstractLifecycleBean#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(ApplicationEvent arg0)
|
||||||
|
{
|
||||||
|
// no implementation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,370 @@
|
|||||||
|
package org.alfresco.module.org_alfresco_module_rm.permission;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||||
|
import org.alfresco.repo.cache.SimpleCache;
|
||||||
|
import org.alfresco.repo.domain.permissions.AclDAO;
|
||||||
|
import org.alfresco.repo.security.permissions.AccessControlEntry;
|
||||||
|
import org.alfresco.repo.security.permissions.AccessControlList;
|
||||||
|
import org.alfresco.repo.security.permissions.PermissionEntry;
|
||||||
|
import org.alfresco.repo.security.permissions.PermissionReference;
|
||||||
|
import org.alfresco.repo.security.permissions.impl.ModelDAO;
|
||||||
|
import org.alfresco.repo.security.permissions.impl.PermissionServiceImpl;
|
||||||
|
import org.alfresco.repo.security.permissions.impl.RequiredPermission;
|
||||||
|
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
|
||||||
|
import org.alfresco.service.cmr.security.AccessStatus;
|
||||||
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
|
||||||
|
public class OtherImpl extends PermissionServiceImpl
|
||||||
|
{
|
||||||
|
static SimplePermissionReference RM_OLD_ALL_PERMISSIONS_REFERENCE = SimplePermissionReference.getPermissionReference(
|
||||||
|
QName.createQName("", PermissionService.ALL_PERMISSIONS),
|
||||||
|
PermissionService.ALL_PERMISSIONS);
|
||||||
|
|
||||||
|
private SimpleCache<Serializable, Set<String>> rmReadersCache;
|
||||||
|
|
||||||
|
private AclDAO rmAclDaoComponent;
|
||||||
|
|
||||||
|
private ModelDAO rmModelDao;
|
||||||
|
|
||||||
|
public void setRmReadersCache(SimpleCache<Serializable, Set<String>> rmReadersCache)
|
||||||
|
{
|
||||||
|
this.rmReadersCache = rmReadersCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRmAclDAO(AclDAO rmAclDaoComponent)
|
||||||
|
{
|
||||||
|
this.rmAclDaoComponent = rmAclDaoComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRmModelDAO(ModelDAO rmModelDao)
|
||||||
|
{
|
||||||
|
this.rmModelDao = rmModelDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAnyDenyDenies(boolean anyDenyDenies)
|
||||||
|
{
|
||||||
|
super.setAnyDenyDenies(anyDenyDenies);
|
||||||
|
rmReadersCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getReaders(Long aclId)
|
||||||
|
{
|
||||||
|
Set<String> dmReaders = super.getReaders(aclId);
|
||||||
|
|
||||||
|
Set<String> rmReaders = rmReadersCache.get(aclId);
|
||||||
|
if (rmReaders == null)
|
||||||
|
{
|
||||||
|
rmReaders = buildRMReaders(aclId);
|
||||||
|
rmReadersCache.put(aclId, rmReaders);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> result = new HashSet<String>();
|
||||||
|
result.addAll(dmReaders);
|
||||||
|
result.addAll(rmReaders);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> buildRMReaders(Long aclId)
|
||||||
|
{
|
||||||
|
AccessControlList acl = rmAclDaoComponent.getAccessControlList(aclId);
|
||||||
|
if (acl == null)
|
||||||
|
{
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<String> assigned = new HashSet<String>();
|
||||||
|
HashSet<String> readers = new HashSet<String>();
|
||||||
|
|
||||||
|
for (AccessControlEntry ace : acl.getEntries())
|
||||||
|
{
|
||||||
|
assigned.add(ace.getAuthority());
|
||||||
|
}
|
||||||
|
|
||||||
|
PermissionReference permissionRef = getPermissionReference(RMPermissionModel.READ_RECORDS);
|
||||||
|
|
||||||
|
for (String authority : assigned)
|
||||||
|
{
|
||||||
|
RMUnconditionalAclTest rmTest = new RMUnconditionalAclTest(permissionRef);
|
||||||
|
if (rmTest.evaluate(authority, aclId))
|
||||||
|
{
|
||||||
|
readers.add(authority);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableSet(readers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ignores type and aspect requirements on the node
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private class RMUnconditionalAclTest
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The required permission.
|
||||||
|
*/
|
||||||
|
PermissionReference required;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Granters of the permission
|
||||||
|
*/
|
||||||
|
Set<PermissionReference> granters;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The additional permissions required at the node level.
|
||||||
|
*/
|
||||||
|
Set<PermissionReference> nodeRequirements = new HashSet<PermissionReference>();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constructor just gets the additional requirements
|
||||||
|
*/
|
||||||
|
RMUnconditionalAclTest(PermissionReference required)
|
||||||
|
{
|
||||||
|
this.required = required;
|
||||||
|
|
||||||
|
// Set the required node permissions
|
||||||
|
if (required.equals(getPermissionReference(ALL_PERMISSIONS)))
|
||||||
|
{
|
||||||
|
nodeRequirements = rmModelDao.getUnconditionalRequiredPermissions(getPermissionReference(PermissionService.FULL_CONTROL), RequiredPermission.On.NODE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nodeRequirements = rmModelDao.getUnconditionalRequiredPermissions(required, RequiredPermission.On.NODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rmModelDao.getUnconditionalRequiredPermissions(required, RequiredPermission.On.PARENT).size() > 0)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Parent permissions can not be checked for an acl");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rmModelDao.getUnconditionalRequiredPermissions(required, RequiredPermission.On.CHILDREN).size() > 0)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Child permissions can not be checked for an acl");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find all the permissions that grant the allowed permission
|
||||||
|
// All permissions are treated specially.
|
||||||
|
granters = new LinkedHashSet<PermissionReference>(128, 1.0f);
|
||||||
|
granters.addAll(rmModelDao.getGrantingPermissions(required));
|
||||||
|
granters.add(getAllPermissionReference());
|
||||||
|
granters.add(RM_OLD_ALL_PERMISSIONS_REFERENCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal hook point for recursion
|
||||||
|
*
|
||||||
|
* @param authorisations
|
||||||
|
* @param nodeRef
|
||||||
|
* @param denied
|
||||||
|
* @param recursiveIn
|
||||||
|
* @return true if granted
|
||||||
|
*/
|
||||||
|
boolean evaluate(String authority, Long aclId)
|
||||||
|
{
|
||||||
|
// Start out true and "and" all other results
|
||||||
|
boolean success = true;
|
||||||
|
|
||||||
|
// Check the required permissions but not for sets they rely on
|
||||||
|
// their underlying permissions
|
||||||
|
//if (modelDAO.checkPermission(required))
|
||||||
|
//{
|
||||||
|
|
||||||
|
// We have to do the test as no parent will help us out
|
||||||
|
success &= hasSinglePermission(authority, aclId);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Check the other permissions required on the node
|
||||||
|
for (PermissionReference pr : nodeRequirements)
|
||||||
|
{
|
||||||
|
// Build a new test
|
||||||
|
RMUnconditionalAclTest nt = new RMUnconditionalAclTest(pr);
|
||||||
|
success &= nt.evaluate(authority, aclId);
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasSinglePermission(String authority, Long aclId)
|
||||||
|
{
|
||||||
|
// Check global permission
|
||||||
|
|
||||||
|
if (checkGlobalPermissions(authority))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(aclId == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return checkRequired(authority, aclId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if we have a global permission
|
||||||
|
*
|
||||||
|
* @param authorisations
|
||||||
|
* @return true if granted
|
||||||
|
*/
|
||||||
|
private boolean checkGlobalPermissions(String authority)
|
||||||
|
{
|
||||||
|
for (PermissionEntry pe : rmModelDao.getGlobalPermissionEntries())
|
||||||
|
{
|
||||||
|
if (isGranted(pe, authority))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that a given authentication is available on a node
|
||||||
|
*
|
||||||
|
* @param authorisations
|
||||||
|
* @param nodeRef
|
||||||
|
* @param denied
|
||||||
|
* @return true if a check is required
|
||||||
|
*/
|
||||||
|
boolean checkRequired(String authority, Long aclId)
|
||||||
|
{
|
||||||
|
AccessControlList acl = rmAclDaoComponent.getAccessControlList(aclId);
|
||||||
|
|
||||||
|
if (acl == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Pair<String, PermissionReference>> denied = new HashSet<Pair<String, PermissionReference>>();
|
||||||
|
|
||||||
|
// Check if each permission allows - the first wins.
|
||||||
|
// We could have other voting style mechanisms here
|
||||||
|
for (AccessControlEntry ace : acl.getEntries())
|
||||||
|
{
|
||||||
|
if (isGranted(ace, authority, denied))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a permission granted
|
||||||
|
*
|
||||||
|
* @param pe -
|
||||||
|
* the permissions entry to consider
|
||||||
|
* @param granters -
|
||||||
|
* the set of granters
|
||||||
|
* @param authorisations -
|
||||||
|
* the set of authorities
|
||||||
|
* @param denied -
|
||||||
|
* the set of denied permissions/authority pais
|
||||||
|
* @return true if granted
|
||||||
|
*/
|
||||||
|
private boolean isGranted(AccessControlEntry ace, String authority, Set<Pair<String, PermissionReference>> denied)
|
||||||
|
{
|
||||||
|
// If the permission entry denies then we just deny
|
||||||
|
if (ace.getAccessStatus() == AccessStatus.DENIED)
|
||||||
|
{
|
||||||
|
denied.add(new Pair<String, PermissionReference>(ace.getAuthority(), ace.getPermission()));
|
||||||
|
|
||||||
|
Set<PermissionReference> granters = rmModelDao.getGrantingPermissions(ace.getPermission());
|
||||||
|
for (PermissionReference granter : granters)
|
||||||
|
{
|
||||||
|
denied.add(new Pair<String, PermissionReference>(ace.getAuthority(), granter));
|
||||||
|
}
|
||||||
|
|
||||||
|
// All the things granted by this permission must be
|
||||||
|
// denied
|
||||||
|
Set<PermissionReference> grantees = rmModelDao.getGranteePermissions(ace.getPermission());
|
||||||
|
for (PermissionReference grantee : grantees)
|
||||||
|
{
|
||||||
|
denied.add(new Pair<String, PermissionReference>(ace.getAuthority(), grantee));
|
||||||
|
}
|
||||||
|
|
||||||
|
// All permission excludes all permissions available for
|
||||||
|
// the node.
|
||||||
|
if (ace.getPermission().equals(getAllPermissionReference()) || ace.getPermission().equals(RM_OLD_ALL_PERMISSIONS_REFERENCE))
|
||||||
|
{
|
||||||
|
for (PermissionReference deny : rmModelDao.getAllPermissions())
|
||||||
|
{
|
||||||
|
denied.add(new Pair<String, PermissionReference>(ace.getAuthority(), deny));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The permission is allowed but we deny it as it is in the denied
|
||||||
|
// set
|
||||||
|
|
||||||
|
if (denied != null)
|
||||||
|
{
|
||||||
|
Pair<String, PermissionReference> specific = new Pair<String, PermissionReference>(ace.getAuthority(), required);
|
||||||
|
if (denied.contains(specific))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the permission has a match in both the authorities and
|
||||||
|
// granters list it is allowed
|
||||||
|
// It applies to the current user and it is granted
|
||||||
|
if (authority.equals(ace.getAuthority()) && granters.contains(ace.getPermission()))
|
||||||
|
{
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default deny
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isGranted(PermissionEntry pe, String authority)
|
||||||
|
{
|
||||||
|
// If the permission entry denies then we just deny
|
||||||
|
if (pe.isDenied())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the permission has a match in both the authorities and
|
||||||
|
// granters list it is allowed
|
||||||
|
// It applies to the current user and it is granted
|
||||||
|
if (granters.contains(pe.getPermissionReference()) && authority.equals(pe.getAuthority()))
|
||||||
|
{
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default deny
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user