Consolidating usage patterns around CannedQuery

- Removed executionID from AbstractCannedQuery constructors
 - Removed authenticationToken from CannedQueryParameters and applyPostQueryPermissions
 - Created common MethodSecurityBean to abstract permission checks
 - Pushed security definitions into public-services-security-context.xml (except blog-context.xml)
 - BlogServiceImpl now just returns the results of the CQ
 - CopyService CQ start
 - JIRAs
   - ALF-7167: RINF 11: Canned queries
   - ALF-9322: RINF 11: Remove AbstractCannedQueryPermissions
   - ALF-8969, ALF-8806, ALF-9033, ALF-8805


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28680 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2011-06-29 02:25:37 +00:00
parent b3b9c36a08
commit 6600f32e30
27 changed files with 931 additions and 736 deletions

View File

@@ -18,24 +18,17 @@
*/
package org.alfresco.repo.security.permissions.impl.acegi;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.ConfigAttributeDefinition;
import net.sf.acegisecurity.context.Context;
import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.security.SecureContext;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.query.AbstractCannedQuery;
import org.alfresco.query.CannedQueryParameters;
import org.alfresco.query.PagingResults;
import org.alfresco.repo.security.authentication.AlfrescoSecureContext;
import org.alfresco.util.Pair;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -48,47 +41,25 @@ import org.apache.commons.logging.LogFactory;
public abstract class AbstractCannedQueryPermissions<R> extends AbstractCannedQuery<R>
{
private Log logger = LogFactory.getLog(AbstractCannedQueryPermissions.class);
private MethodSecurityBean<R> methodSecurity;
private MethodSecurityInterceptor methodSecurityInterceptor;
private Method method;
protected AbstractCannedQueryPermissions(CannedQueryParameters parameters, String queryExecutionId, MethodSecurityInterceptor methodSecurityInterceptor, Object methodService, String methodName)
protected AbstractCannedQueryPermissions(CannedQueryParameters parameters, MethodSecurityBean<R> methodSecurity)
{
super(parameters, queryExecutionId);
Method method = null;
for (Method m : methodService.getClass().getMethods())
{
// note: currently matches first found
if (m.getName().equals(methodName))
{
method = m;
break;
}
}
if (method == null)
{
throw new AlfrescoRuntimeException("Method not found: "+methodName);
}
this.methodSecurityInterceptor = methodSecurityInterceptor;
this.method = method;
super(parameters);
this.methodSecurity = methodSecurity;
}
protected List<R> applyPostQueryPermissions(List<R> results, String authenticationToken, int requestedCount)
protected List<R> applyPostQueryPermissions(List<R> results, int requestedCount)
{
int requestTotalCountMax = getParameters().requestTotalResultCountMax();
int maxChecks = (((requestTotalCountMax > 0) && (requestTotalCountMax > requestedCount)) ? requestTotalCountMax : requestedCount);
return applyPermissions(results, authenticationToken, maxChecks);
return applyPermissions(results, maxChecks);
}
@SuppressWarnings("unchecked")
protected List<R> applyPermissions(List<R> results, String authenticationToken, int maxChecks)
protected List<R> applyPermissions(List<R> results, int maxChecks)
{
long start = System.currentTimeMillis();
Context context = ContextHolder.getContext();
if ((context == null) || (! (context instanceof AlfrescoSecureContext)))
{
@@ -99,57 +70,10 @@ public abstract class AbstractCannedQueryPermissions<R> extends AbstractCannedQu
return new WrappedList<R>(new ArrayList<R>(0), true, false); // empty result
}
Authentication authentication = (((SecureContext) context).getAuthentication());
ConfigAttributeDefinition cad = methodSecurityInterceptor.getObjectDefinitionSource().getAttributes(new InternalMethodInvocation(method));
List<R> ret = (WrappedList<R>)methodSecurityInterceptor.getAfterInvocationManager().decide(authentication, null, cad, new WrappedList<R>(results, maxChecks));
if (logger.isTraceEnabled())
{
logger.trace("applyPermissions: "+ret.size()+" items in "+(System.currentTimeMillis()-start)+" msecs");
}
return ret;
}
class InternalMethodInvocation implements MethodInvocation
{
Method method;
public InternalMethodInvocation(Method method)
{
this.method = method;
}
protected InternalMethodInvocation()
{
throw new UnsupportedOperationException();
}
public Object[] getArguments()
{
throw new UnsupportedOperationException();
}
public Method getMethod()
{
return this.method;
}
public AccessibleObject getStaticPart()
{
throw new UnsupportedOperationException();
}
public Object getThis()
{
throw new UnsupportedOperationException();
}
public Object proceed() throws Throwable
{
throw new UnsupportedOperationException();
}
List<R> resultsOut = methodSecurity.applyPermissions(results, authentication, maxChecks);
// Done
return resultsOut;
}
}

View File

@@ -0,0 +1,189 @@
/*
* Copyright (C) 2005-2011 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.repo.security.permissions.impl.acegi;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.List;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.ConfigAttributeDefinition;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.util.PropertyCheck;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
/**
* Support to simulate interceptor-driven permissions.
*
* @author janv, Derek Hulley
* @since 4.0
*/
public class MethodSecurityBean<R> implements InitializingBean
{
private Log logger = LogFactory.getLog(MethodSecurityBean.class);
private MethodSecurityInterceptor methodSecurityInterceptor;
private Class<?> service;
private String methodName;
private ConfigAttributeDefinition cad;
/**
* Default constructor. Use setter methods for initialization.
*/
public MethodSecurityBean()
{
}
/**
* Helper constructor to supply necessary values
*/
public MethodSecurityBean(MethodSecurityInterceptor methodSecurityInterceptor, Class<?> service, String methodName)
{
this.methodSecurityInterceptor = methodSecurityInterceptor;
this.service = service;
this.methodName = methodName;
}
public void setMethodSecurityInterceptor(MethodSecurityInterceptor methodSecurityInterceptor)
{
this.methodSecurityInterceptor = methodSecurityInterceptor;
}
public void setService(Class<?> service)
{
this.service = service;
}
public void setMethodName(String methodName)
{
this.methodName = methodName;
}
@Override
public String toString()
{
return "MethodSecurityBean [serviceInterface=" + service.getName() + ", methodName=" + methodName + "]";
}
@Override
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "methodSecurityInterceptor", methodSecurityInterceptor);
PropertyCheck.mandatory(this, "service", service);
PropertyCheck.mandatory(this, "methodName", methodName);
// Get the method from the service
Method method = null;
for (Method m : service.getMethods())
{
// Note: currently matches first found
// This is fine because the interceptor requires the same defininition for all overloaded methods
if (m.getName().equals(methodName))
{
method = m;
break;
}
}
if (method == null)
{
throw new AlfrescoRuntimeException(
"Method not found: \n" +
" Interface: " + service.getClass() + "\n" +
" Method: " + methodName);
}
else
{
this.cad = methodSecurityInterceptor.getObjectDefinitionSource().getAttributes(new InternalMethodInvocation(method));
// Null means there are no applicable permissions
}
}
@SuppressWarnings("unchecked")
public List<R> applyPermissions(List<R> results, Authentication authentication, int maxChecks)
{
if (cad == null)
{
// Ignore permissions
if (logger.isTraceEnabled())
{
logger.trace("applyPermissions ignored: " + this);
}
return new WrappedList<R>(results, true, false);
}
long start = System.currentTimeMillis();
List<R> ret = (WrappedList<R>) methodSecurityInterceptor.getAfterInvocationManager().decide(
authentication,
null,
cad,
new WrappedList<R>(results, maxChecks));
if (logger.isTraceEnabled())
{
logger.trace("applyPermissions: " + ret.size() + " items in " + (System.currentTimeMillis() - start) + " msecs");
}
return ret;
}
/**
* Helper to provide method for permissions interceptor
*/
class InternalMethodInvocation implements MethodInvocation
{
Method method;
public InternalMethodInvocation(Method method)
{
this.method = method;
}
protected InternalMethodInvocation()
{
throw new UnsupportedOperationException();
}
public Object[] getArguments()
{
throw new UnsupportedOperationException();
}
public Method getMethod()
{
return this.method;
}
public AccessibleObject getStaticPart()
{
throw new UnsupportedOperationException();
}
public Object getThis()
{
throw new UnsupportedOperationException();
}
public Object proceed() throws Throwable
{
throw new UnsupportedOperationException();
}
}
}