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