mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Merged V2.2 to HEAD
8014: Extended support for RunAs - real and effctive authorities 8032: Build Fix - there is a special check for the effective user 8094: Fix for NPE in AuthenticationUtil noticed on first upgrade from V2.1.x to V2.2 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@8471 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -30,6 +30,7 @@ import java.util.Map;
|
||||
import org.alfresco.repo.avm.AVMDAOs;
|
||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||
import org.alfresco.repo.domain.PropertyValue;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.repo.workflow.jbpm.JBPMNode;
|
||||
import org.alfresco.repo.workflow.jbpm.JBPMSpringActionHandler;
|
||||
@@ -47,9 +48,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.jbpm.graph.exe.ExecutionContext;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
|
||||
public class AVMSubmitPackageHandler
|
||||
extends JBPMSpringActionHandler
|
||||
implements Serializable
|
||||
public class AVMSubmitPackageHandler extends JBPMSpringActionHandler implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 4113360751217684995L;
|
||||
|
||||
@@ -65,21 +64,22 @@ public class AVMSubmitPackageHandler
|
||||
private AVMLockingService fAVMLockingService;
|
||||
|
||||
/**
|
||||
* The AVMSubmitTransactionListener instance
|
||||
* (for JMX notification of virtualization server after commit/rollback).
|
||||
* The AVMSubmitTransactionListener instance (for JMX notification of virtualization server after commit/rollback).
|
||||
*/
|
||||
private AVMSubmitTransactionListener fAVMSubmitTransactionListener;
|
||||
|
||||
/**
|
||||
* Initialize service references.
|
||||
* @param factory The BeanFactory to get references from.
|
||||
*
|
||||
* @param factory
|
||||
* The BeanFactory to get references from.
|
||||
*/
|
||||
@Override
|
||||
protected void initialiseHandler(final BeanFactory factory)
|
||||
{
|
||||
fAVMService = (AVMService)factory.getBean(ServiceRegistry.AVM_SERVICE.getLocalName());
|
||||
fAVMSyncService = (AVMSyncService)factory.getBean(ServiceRegistry.AVM_SYNC_SERVICE.getLocalName());
|
||||
fAVMLockingService = (AVMLockingService)factory.getBean(ServiceRegistry.AVM_LOCKING_SERVICE.getLocalName());
|
||||
fAVMService = (AVMService) factory.getBean(ServiceRegistry.AVM_SERVICE.getLocalName());
|
||||
fAVMSyncService = (AVMSyncService) factory.getBean(ServiceRegistry.AVM_SYNC_SERVICE.getLocalName());
|
||||
fAVMLockingService = (AVMLockingService) factory.getBean(ServiceRegistry.AVM_LOCKING_SERVICE.getLocalName());
|
||||
fAVMSubmitTransactionListener = (AVMSubmitTransactionListener) factory.getBean("AVMSubmitTransactionListener");
|
||||
|
||||
AlfrescoTransactionSupport.bindListener(fAVMSubmitTransactionListener);
|
||||
@@ -87,25 +87,25 @@ public class AVMSubmitPackageHandler
|
||||
|
||||
/**
|
||||
* Do the actual work.
|
||||
* @param executionContext The context to get stuff from.
|
||||
*
|
||||
* @param executionContext
|
||||
* The context to get stuff from.
|
||||
*/
|
||||
public void execute(final ExecutionContext executionContext)
|
||||
throws Exception
|
||||
public void execute(final ExecutionContext executionContext) throws Exception
|
||||
{
|
||||
// TODO: Allow submit parameters to be passed into this action handler
|
||||
// rather than pulling directly from execution context
|
||||
final NodeRef pkg = ((JBPMNode)executionContext.getContextInstance().getVariable("bpm_package")).getNodeRef();
|
||||
// rather than pulling directly from execution context
|
||||
final NodeRef pkg = ((JBPMNode) executionContext.getContextInstance().getVariable("bpm_package")).getNodeRef();
|
||||
final Pair<Integer, String> pkgPath = AVMNodeConverter.ToAVMVersionPath(pkg);
|
||||
final AVMNodeDescriptor pkgDesc = fAVMService.lookup(pkgPath.getFirst(), pkgPath.getSecond());
|
||||
final String from = (String)executionContext.getContextInstance().getVariable("wcmwf_fromPath");
|
||||
final String from = (String) executionContext.getContextInstance().getVariable("wcmwf_fromPath");
|
||||
final String targetPath = pkgDesc.getIndirection();
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("handling submit of " + pkgPath.getSecond() + " from " + from + " to " + targetPath);
|
||||
|
||||
// submit the package changes
|
||||
final String description = (String)executionContext.getContextInstance().getVariable("bpm_workflowDescription");
|
||||
final String tag = (String)executionContext.getContextInstance().getVariable("wcmwf_label");
|
||||
|
||||
final String description = (String) executionContext.getContextInstance().getVariable("bpm_workflowDescription");
|
||||
final String tag = (String) executionContext.getContextInstance().getVariable("wcmwf_label");
|
||||
|
||||
final Map<QName, PropertyValue> dnsProperties = this.fAVMService.queryStorePropertyKey(targetPath.split(":")[0], QName.createQName(null, ".dns%"));
|
||||
String webProject = dnsProperties.keySet().iterator().next().getLocalName();
|
||||
@@ -116,23 +116,32 @@ public class AVMSubmitPackageHandler
|
||||
String p = diff.getSourcePath();
|
||||
if (from != null && from.length() != 0)
|
||||
{
|
||||
p = from + p.substring(pkgPath.getSecond().length());
|
||||
p = from + p.substring(pkgPath.getSecond().length());
|
||||
}
|
||||
this.recursivelyRemoveLocks(webProject, -1, p);
|
||||
}
|
||||
|
||||
// Allow AVMSubmitTransactionListener to inspect the staging diffs
|
||||
// so it can notify the virtualization server via JMX if when this
|
||||
// submit succeeds or fails. This allows virtual webapps devoted
|
||||
// submit succeeds or fails. This allows virtual webapps devoted
|
||||
// to the workarea to be destroyed, and staging to be updated in
|
||||
// the event that some of the files alter the behavior of the
|
||||
// webapp itself (e.g.: WEB-INF/web.xml, WEB-INF/lib/*.jar), etc.
|
||||
|
||||
AlfrescoTransactionSupport.bindResource("staging_diffs", stagingDiffs);
|
||||
|
||||
fAVMSyncService.update(stagingDiffs, null, false, false, true, true, tag, description);
|
||||
AVMDAOs.Instance().fAVMNodeDAO.flush();
|
||||
fAVMSyncService.flatten(pkgPath.getSecond(), targetPath);
|
||||
// Workflow does this as system as the staging area has restricted access
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
|
||||
{
|
||||
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
fAVMSyncService.update(stagingDiffs, null, false, false, true, true, tag, description);
|
||||
AVMDAOs.Instance().fAVMNodeDAO.flush();
|
||||
fAVMSyncService.flatten(pkgPath.getSecond(), targetPath);
|
||||
return null;
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
|
||||
// flatten source folder where changes were submitted from
|
||||
if (from != null && from.length() > 0)
|
||||
@@ -140,7 +149,7 @@ public class AVMSubmitPackageHandler
|
||||
// first, submit changes back to sandbox forcing addition of edits in workflow (and submission
|
||||
// flag removal). second, flatten sandbox, removing modified items that have been submitted
|
||||
// TODO: Without locking on the sandbox, it's possible that a change to a "submitted" item
|
||||
// may get lost when the item is finally approved
|
||||
// may get lost when the item is finally approved
|
||||
final List<AVMDifference> sandboxDiffs = fAVMSyncService.compare(pkgPath.getFirst(), pkgPath.getSecond(), -1, from, null);
|
||||
fAVMSyncService.update(sandboxDiffs, null, true, true, false, false, tag, description);
|
||||
AVMDAOs.Instance().fAVMNodeDAO.flush();
|
||||
@@ -149,8 +158,7 @@ public class AVMSubmitPackageHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively remove locks from a path. Walking child folders looking for files
|
||||
* to remove locks from.
|
||||
* Recursively remove locks from a path. Walking child folders looking for files to remove locks from.
|
||||
*/
|
||||
private void recursivelyRemoveLocks(final String webProject, final int version, final String path)
|
||||
{
|
||||
@@ -163,14 +171,14 @@ public class AVMSubmitPackageHandler
|
||||
}
|
||||
else
|
||||
{
|
||||
if (desc.isDeletedDirectory() == false)
|
||||
{
|
||||
Map<String, AVMNodeDescriptor> list = fAVMService.getDirectoryListing(desc, true);
|
||||
for (AVMNodeDescriptor child : list.values())
|
||||
{
|
||||
recursivelyRemoveLocks(webProject, version, child.getPath());
|
||||
}
|
||||
}
|
||||
if (desc.isDeletedDirectory() == false)
|
||||
{
|
||||
Map<String, AVMNodeDescriptor> list = fAVMService.getDirectoryListing(desc, true);
|
||||
for (AVMNodeDescriptor child : list.values())
|
||||
{
|
||||
recursivelyRemoveLocks(webProject, version, child.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -474,8 +474,9 @@ public class LockServiceImpl implements LockService,
|
||||
// Ensure we have found a node reference
|
||||
if (nodeRef != null && userName != null)
|
||||
{
|
||||
String effectiveUserName = AuthenticationUtil.getCurrentEffectiveUserName();
|
||||
// Check to see if should just ignore this node - note: special MT System due to AuditableAspect
|
||||
if (!(this.ignoreNodeRefs.contains(nodeRef) || tenantService.getBaseNameUser(userName).equals(AuthenticationUtil.getSystemUserName())))
|
||||
if (!(this.ignoreNodeRefs.contains(nodeRef) || tenantService.getBaseNameUser(effectiveUserName).equals(AuthenticationUtil.getSystemUserName())))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.context.security.SecureContext;
|
||||
|
||||
/**
|
||||
* Extensions for the Alfresco security context.
|
||||
*
|
||||
* This is based on the Linux model and supports real, effective and stored authorities
|
||||
*
|
||||
* The real authority is used for auditing and reporting who the user is etc.
|
||||
* The effective authority is used for permission checks.
|
||||
*
|
||||
* RunAs support leaves the real authority and changes only the effective authority
|
||||
* That means "special" code can run code as system but still be audited as Joe
|
||||
*
|
||||
* In the future scrips etc can support a setUId flag and run as the owner of the script.
|
||||
* If the script chooses to do this ....
|
||||
* A method invocation could do the same (after entry security checks)
|
||||
*
|
||||
* TODO: extent runAs to take a nodeRef context - it can then set the stored atc and set this as effective if required.
|
||||
*
|
||||
* @author andyh
|
||||
*
|
||||
*/
|
||||
public interface AlfrescoSecureContext extends SecureContext
|
||||
{
|
||||
/**
|
||||
* Get the effective authentication - used for permission checks
|
||||
* @return
|
||||
*/
|
||||
public Authentication getEffectiveAuthentication();
|
||||
|
||||
/**
|
||||
* Get the real authenticaiton - used for auditing and everything else
|
||||
* @return
|
||||
*/
|
||||
public Authentication getRealAuthentication();
|
||||
|
||||
/**
|
||||
* Get the store authentication - used for setuid scripts and methods
|
||||
* @return
|
||||
*/
|
||||
public Authentication getStoredAuthentication();
|
||||
|
||||
/**
|
||||
* Set the effective authentication held by the context
|
||||
*
|
||||
* @param effictiveAuthentication
|
||||
*/
|
||||
public void setEffectiveAuthentication(Authentication effictiveAuthentication);
|
||||
|
||||
/**
|
||||
* Set the real authentication held by the context
|
||||
*
|
||||
* @param realAuthentication
|
||||
*/
|
||||
public void setRealAuthentication(Authentication realAuthentication);
|
||||
|
||||
/**
|
||||
* Set the stored authentication held by the context
|
||||
*
|
||||
* @param storedAuthentication
|
||||
*/
|
||||
public void setStoredAuthentication(Authentication storedAuthentication);
|
||||
|
||||
}
|
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program 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 General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.context.ContextInvalidException;
|
||||
|
||||
/**
|
||||
* Hold an Alfresco extended security context
|
||||
*
|
||||
* @author andyh
|
||||
*
|
||||
*/
|
||||
public class AlfrescoSecureContextImpl implements AlfrescoSecureContext
|
||||
{
|
||||
Authentication storedAuthentication;
|
||||
|
||||
Authentication realAuthentication;
|
||||
|
||||
Authentication effectiveAuthentication;
|
||||
|
||||
/**
|
||||
* ACEGI
|
||||
*/
|
||||
public Authentication getAuthentication()
|
||||
{
|
||||
return getEffectiveAuthentication();
|
||||
}
|
||||
|
||||
/**
|
||||
* ACEGI
|
||||
*/
|
||||
public void setAuthentication(Authentication newAuthentication)
|
||||
{
|
||||
setEffectiveAuthentication(newAuthentication);
|
||||
setRealAuthentication(newAuthentication);
|
||||
}
|
||||
|
||||
/**
|
||||
* ACEGI
|
||||
*/
|
||||
public void validate() throws ContextInvalidException
|
||||
{
|
||||
if (effectiveAuthentication == null)
|
||||
{
|
||||
throw new ContextInvalidException("Effective authentication not set");
|
||||
}
|
||||
}
|
||||
|
||||
public Authentication getEffectiveAuthentication()
|
||||
{
|
||||
return effectiveAuthentication;
|
||||
}
|
||||
|
||||
public Authentication getRealAuthentication()
|
||||
{
|
||||
return realAuthentication;
|
||||
}
|
||||
|
||||
public Authentication getStoredAuthentication()
|
||||
{
|
||||
return storedAuthentication;
|
||||
}
|
||||
|
||||
public void setEffectiveAuthentication(Authentication effictiveAuthentication)
|
||||
{
|
||||
this.effectiveAuthentication = effictiveAuthentication;
|
||||
}
|
||||
|
||||
public void setRealAuthentication(Authentication realAuthentication)
|
||||
{
|
||||
this.realAuthentication = realAuthentication;
|
||||
}
|
||||
|
||||
public void setStoredAuthentication(Authentication storedAuthentication)
|
||||
{
|
||||
this.storedAuthentication = storedAuthentication;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int PRIME = 31;
|
||||
int result = 1;
|
||||
result = PRIME * result + ((effectiveAuthentication == null) ? 0 : effectiveAuthentication.hashCode());
|
||||
result = PRIME * result + ((realAuthentication == null) ? 0 : realAuthentication.hashCode());
|
||||
result = PRIME * result + ((storedAuthentication == null) ? 0 : storedAuthentication.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final AlfrescoSecureContextImpl other = (AlfrescoSecureContextImpl) obj;
|
||||
if (effectiveAuthentication == null)
|
||||
{
|
||||
if (other.effectiveAuthentication != null)
|
||||
return false;
|
||||
}
|
||||
else if (!effectiveAuthentication.equals(other.effectiveAuthentication))
|
||||
return false;
|
||||
if (realAuthentication == null)
|
||||
{
|
||||
if (other.realAuthentication != null)
|
||||
return false;
|
||||
}
|
||||
else if (!realAuthentication.equals(other.realAuthentication))
|
||||
return false;
|
||||
if (storedAuthentication == null)
|
||||
{
|
||||
if (other.storedAuthentication != null)
|
||||
return false;
|
||||
}
|
||||
else if (!storedAuthentication.equals(other.storedAuthentication))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
if (realAuthentication == null)
|
||||
{
|
||||
builder.append("Real authenticaion = null");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.append("Real authenticaion = " + realAuthentication.toString());
|
||||
}
|
||||
builder.append(", ");
|
||||
|
||||
if (effectiveAuthentication == null)
|
||||
{
|
||||
builder.append("Effective authenticaion = null");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.append("Effective authenticaion = " + effectiveAuthentication.toString());
|
||||
}
|
||||
builder.append(", ");
|
||||
|
||||
if (storedAuthentication == null)
|
||||
{
|
||||
builder.append("Stored authenticaion = null");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.append("Stored authenticaion = " + storedAuthentication.toString());
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
@@ -63,10 +63,10 @@ public abstract class AuthenticationUtil
|
||||
|
||||
public static void setMtEnabled(boolean mtEnabled)
|
||||
{
|
||||
if (! AuthenticationUtil.mtEnabled)
|
||||
{
|
||||
AuthenticationUtil.mtEnabled = mtEnabled;
|
||||
}
|
||||
if (!AuthenticationUtil.mtEnabled)
|
||||
{
|
||||
AuthenticationUtil.mtEnabled = mtEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isMtEnabled()
|
||||
@@ -79,16 +79,31 @@ public abstract class AuthenticationUtil
|
||||
return setCurrentUser(userName, getDefaultUserDetails(userName));
|
||||
}
|
||||
|
||||
public static Authentication setCurrentRealUser(String userName)
|
||||
{
|
||||
return setCurrentRealUser(userName, getDefaultUserDetails(userName));
|
||||
}
|
||||
|
||||
public static Authentication setCurrentEffectiveUser(String userName)
|
||||
{
|
||||
return setCurrentEffectiveUser(userName, getDefaultUserDetails(userName));
|
||||
}
|
||||
|
||||
public static Authentication setCurrentStoredUser(String userName)
|
||||
{
|
||||
return setCurrentStoredUser(userName, getDefaultUserDetails(userName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly set the current user to be authenticated.
|
||||
*
|
||||
* @param userName - String user id
|
||||
* @param providedDetails - provided details for the user
|
||||
*
|
||||
* @param userName -
|
||||
* String user id
|
||||
* @param providedDetails -
|
||||
* provided details for the user
|
||||
* @return Authentication
|
||||
*/
|
||||
public static Authentication setCurrentUser(String userName, UserDetails providedDetails)
|
||||
throws AuthenticationException
|
||||
public static Authentication setCurrentUser(String userName, UserDetails providedDetails) throws AuthenticationException
|
||||
{
|
||||
if (userName == null)
|
||||
{
|
||||
@@ -97,34 +112,7 @@ public abstract class AuthenticationUtil
|
||||
|
||||
try
|
||||
{
|
||||
UserDetails ud = null;
|
||||
if (userName.equals(SYSTEM_USER_NAME))
|
||||
{
|
||||
GrantedAuthority[] gas = new GrantedAuthority[1];
|
||||
gas[0] = new GrantedAuthorityImpl("ROLE_SYSTEM");
|
||||
ud = new User(SYSTEM_USER_NAME, "", true, true, true, true, gas);
|
||||
}
|
||||
else if (userName.equalsIgnoreCase(PermissionService.GUEST_AUTHORITY))
|
||||
{
|
||||
GrantedAuthority[] gas = new GrantedAuthority[0];
|
||||
ud = new User(PermissionService.GUEST_AUTHORITY.toLowerCase(), "", true, true, true, true, gas);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (providedDetails.getUsername().equals(userName))
|
||||
{
|
||||
ud = providedDetails;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AuthenticationException("Provided user details do not match the user name");
|
||||
}
|
||||
}
|
||||
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(ud, "", ud
|
||||
.getAuthorities());
|
||||
auth.setDetails(ud);
|
||||
auth.setAuthenticated(true);
|
||||
UsernamePasswordAuthenticationToken auth = getAuthenticationToken(userName, providedDetails);
|
||||
return setCurrentAuthentication(auth);
|
||||
}
|
||||
catch (net.sf.acegisecurity.AuthenticationException ae)
|
||||
@@ -133,6 +121,92 @@ public abstract class AuthenticationUtil
|
||||
}
|
||||
}
|
||||
|
||||
public static Authentication setCurrentRealUser(String userName, UserDetails providedDetails) throws AuthenticationException
|
||||
{
|
||||
if (userName == null)
|
||||
{
|
||||
throw new AuthenticationException("Null user name");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
UsernamePasswordAuthenticationToken auth = getAuthenticationToken(userName, providedDetails);
|
||||
return setCurrentRealAuthentication(auth);
|
||||
}
|
||||
catch (net.sf.acegisecurity.AuthenticationException ae)
|
||||
{
|
||||
throw new AuthenticationException(ae.getMessage(), ae);
|
||||
}
|
||||
}
|
||||
|
||||
public static Authentication setCurrentEffectiveUser(String userName, UserDetails providedDetails) throws AuthenticationException
|
||||
{
|
||||
if (userName == null)
|
||||
{
|
||||
throw new AuthenticationException("Null user name");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
UsernamePasswordAuthenticationToken auth = getAuthenticationToken(userName, providedDetails);
|
||||
return setCurrentEffectiveAuthentication(auth);
|
||||
}
|
||||
catch (net.sf.acegisecurity.AuthenticationException ae)
|
||||
{
|
||||
throw new AuthenticationException(ae.getMessage(), ae);
|
||||
}
|
||||
}
|
||||
|
||||
public static Authentication setCurrentStoredUser(String userName, UserDetails providedDetails) throws AuthenticationException
|
||||
{
|
||||
if (userName == null)
|
||||
{
|
||||
throw new AuthenticationException("Null user name");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
UsernamePasswordAuthenticationToken auth = getAuthenticationToken(userName, providedDetails);
|
||||
return setCurrentStoredAuthentication(auth);
|
||||
}
|
||||
catch (net.sf.acegisecurity.AuthenticationException ae)
|
||||
{
|
||||
throw new AuthenticationException(ae.getMessage(), ae);
|
||||
}
|
||||
}
|
||||
|
||||
private static UsernamePasswordAuthenticationToken getAuthenticationToken(String userName, UserDetails providedDetails)
|
||||
{
|
||||
UserDetails ud = null;
|
||||
if (userName.equals(SYSTEM_USER_NAME))
|
||||
{
|
||||
GrantedAuthority[] gas = new GrantedAuthority[1];
|
||||
gas[0] = new GrantedAuthorityImpl("ROLE_SYSTEM");
|
||||
ud = new User(SYSTEM_USER_NAME, "", true, true, true, true, gas);
|
||||
}
|
||||
else if (userName.equalsIgnoreCase(PermissionService.GUEST_AUTHORITY))
|
||||
{
|
||||
GrantedAuthority[] gas = new GrantedAuthority[0];
|
||||
ud = new User(PermissionService.GUEST_AUTHORITY.toLowerCase(), "", true, true, true, true, gas);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (providedDetails.getUsername().equals(userName))
|
||||
{
|
||||
ud = providedDetails;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AuthenticationException("Provided user details do not match the user name");
|
||||
}
|
||||
}
|
||||
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(ud, "", ud.getAuthorities());
|
||||
auth.setDetails(ud);
|
||||
auth.setAuthenticated(true);
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation that makes an ACEGI object on the fly
|
||||
*
|
||||
@@ -163,17 +237,18 @@ public abstract class AuthenticationUtil
|
||||
else
|
||||
{
|
||||
Context context = ContextHolder.getContext();
|
||||
SecureContext sc = null;
|
||||
if ((context == null) || !(context instanceof SecureContext))
|
||||
AlfrescoSecureContext sc = null;
|
||||
if ((context == null) || !(context instanceof AlfrescoSecureContext))
|
||||
{
|
||||
sc = new SecureContextImpl();
|
||||
sc = new AlfrescoSecureContextImpl();
|
||||
ContextHolder.setContext(sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
sc = (SecureContext) context;
|
||||
sc = (AlfrescoSecureContext) context;
|
||||
}
|
||||
authentication.setAuthenticated(true);
|
||||
// Sets real and effective
|
||||
sc.setAuthentication(authentication);
|
||||
|
||||
// Support for logging tenant domain / username (via log4j NDC)
|
||||
@@ -196,18 +271,96 @@ public abstract class AuthenticationUtil
|
||||
if (isMtEnabled())
|
||||
{
|
||||
int idx = userName.indexOf(TenantService.SEPARATOR);
|
||||
if ((idx != -1) && (idx < (userName.length()-1)))
|
||||
if ((idx != -1) && (idx < (userName.length() - 1)))
|
||||
{
|
||||
NDC.push("Tenant:"+userName.substring(idx+1)+" User:"+userName.substring(0,idx));
|
||||
NDC.push("Tenant:" + userName.substring(idx + 1) + " User:" + userName.substring(0, idx));
|
||||
}
|
||||
else
|
||||
{
|
||||
NDC.push("User:"+userName);
|
||||
NDC.push("User:" + userName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NDC.push("User:"+userName);
|
||||
NDC.push("User:" + userName);
|
||||
}
|
||||
}
|
||||
|
||||
public static Authentication setCurrentRealAuthentication(Authentication authentication)
|
||||
{
|
||||
if (authentication == null)
|
||||
{
|
||||
clearCurrentSecurityContext();
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Context context = ContextHolder.getContext();
|
||||
AlfrescoSecureContext sc = null;
|
||||
if ((context == null) || !(context instanceof AlfrescoSecureContext))
|
||||
{
|
||||
sc = new AlfrescoSecureContextImpl();
|
||||
ContextHolder.setContext(sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
sc = (AlfrescoSecureContext) context;
|
||||
}
|
||||
authentication.setAuthenticated(true);
|
||||
sc.setRealAuthentication(authentication);
|
||||
return authentication;
|
||||
}
|
||||
}
|
||||
|
||||
public static Authentication setCurrentEffectiveAuthentication(Authentication authentication)
|
||||
{
|
||||
if (authentication == null)
|
||||
{
|
||||
clearCurrentSecurityContext();
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Context context = ContextHolder.getContext();
|
||||
AlfrescoSecureContext sc = null;
|
||||
if ((context == null) || !(context instanceof AlfrescoSecureContext))
|
||||
{
|
||||
sc = new AlfrescoSecureContextImpl();
|
||||
ContextHolder.setContext(sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
sc = (AlfrescoSecureContext) context;
|
||||
}
|
||||
authentication.setAuthenticated(true);
|
||||
sc.setEffectiveAuthentication(authentication);
|
||||
return authentication;
|
||||
}
|
||||
}
|
||||
|
||||
public static Authentication setCurrentStoredAuthentication(Authentication authentication)
|
||||
{
|
||||
if (authentication == null)
|
||||
{
|
||||
clearCurrentSecurityContext();
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Context context = ContextHolder.getContext();
|
||||
AlfrescoSecureContext sc = null;
|
||||
if ((context == null) || !(context instanceof AlfrescoSecureContext))
|
||||
{
|
||||
sc = new AlfrescoSecureContextImpl();
|
||||
ContextHolder.setContext(sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
sc = (AlfrescoSecureContext) context;
|
||||
}
|
||||
authentication.setAuthenticated(true);
|
||||
sc.setStoredAuthentication(authentication);
|
||||
return authentication;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,13 +371,56 @@ public abstract class AuthenticationUtil
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public static Authentication getCurrentAuthentication() throws AuthenticationException
|
||||
{
|
||||
return getCurrentRealAuthentication();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current real authentication context
|
||||
*
|
||||
* @return Authentication
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public static Authentication getCurrentRealAuthentication() throws AuthenticationException
|
||||
{
|
||||
Context context = ContextHolder.getContext();
|
||||
if ((context == null) || !(context instanceof SecureContext))
|
||||
if ((context == null) || !(context instanceof AlfrescoSecureContext))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return ((SecureContext) context).getAuthentication();
|
||||
return ((AlfrescoSecureContext) context).getRealAuthentication();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current effective authentication context
|
||||
*
|
||||
* @return Authentication
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public static Authentication getCurrentEffectiveAuthentication() throws AuthenticationException
|
||||
{
|
||||
Context context = ContextHolder.getContext();
|
||||
if ((context == null) || !(context instanceof AlfrescoSecureContext))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return ((AlfrescoSecureContext) context).getEffectiveAuthentication();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current stored authentication context
|
||||
*
|
||||
* @return Authentication
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public static Authentication getCurrentStoredAuthentication() throws AuthenticationException
|
||||
{
|
||||
Context context = ContextHolder.getContext();
|
||||
if ((context == null) || !(context instanceof AlfrescoSecureContext))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return ((AlfrescoSecureContext) context).getStoredAuthentication();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,13 +430,53 @@ public abstract class AuthenticationUtil
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public static String getCurrentUserName() throws AuthenticationException
|
||||
{
|
||||
return getCurrentRealUserName();
|
||||
}
|
||||
|
||||
public static String getCurrentRealUserName() throws AuthenticationException
|
||||
{
|
||||
Context context = ContextHolder.getContext();
|
||||
if ((context == null) || !(context instanceof SecureContext))
|
||||
if ((context == null) || !(context instanceof AlfrescoSecureContext))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return getUserName(((SecureContext) context).getAuthentication());
|
||||
AlfrescoSecureContext ctx = (AlfrescoSecureContext) context;
|
||||
if (ctx.getRealAuthentication() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return getUserName(ctx.getRealAuthentication());
|
||||
}
|
||||
|
||||
public static String getCurrentEffectiveUserName() throws AuthenticationException
|
||||
{
|
||||
Context context = ContextHolder.getContext();
|
||||
if ((context == null) || !(context instanceof AlfrescoSecureContext))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AlfrescoSecureContext ctx = (AlfrescoSecureContext) context;
|
||||
if (ctx.getEffectiveAuthentication() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return getUserName(ctx.getEffectiveAuthentication());
|
||||
}
|
||||
|
||||
public static String getCurrentStoredUserName() throws AuthenticationException
|
||||
{
|
||||
Context context = ContextHolder.getContext();
|
||||
if ((context == null) || !(context instanceof AlfrescoSecureContext))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AlfrescoSecureContext ctx = (AlfrescoSecureContext) context;
|
||||
if (ctx.getStoredAuthentication() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return getUserName(ctx.getStoredAuthentication());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,33 +540,42 @@ public abstract class AuthenticationUtil
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a unit of work as a given user. The thread's authenticated user will be
|
||||
* returned to its normal state after the call.
|
||||
* Execute a unit of work as a given user. The thread's authenticated user will be returned to its normal state
|
||||
* after the call.
|
||||
*
|
||||
* @param runAsWork the unit of work to do
|
||||
* @param uid the user ID
|
||||
* @return Returns the work's return value
|
||||
* @param runAsWork
|
||||
* the unit of work to do
|
||||
* @param uid
|
||||
* the user ID
|
||||
* @return Returns the work's return value
|
||||
*/
|
||||
public static <R> R runAs(RunAsWork<R> runAsWork, String uid)
|
||||
{
|
||||
String currentUser = AuthenticationUtil.getCurrentUserName();
|
||||
String effectiveUser = AuthenticationUtil.getCurrentEffectiveUserName();
|
||||
String realUser = AuthenticationUtil.getCurrentRealUserName();
|
||||
|
||||
R result = null;
|
||||
try
|
||||
{
|
||||
if ((currentUser != null) && (isMtEnabled()))
|
||||
{
|
||||
int idx = currentUser.indexOf(TenantService.SEPARATOR);
|
||||
if ((idx != -1) && (idx < (currentUser.length()-1)))
|
||||
|
||||
if ((realUser != null) && (isMtEnabled()))
|
||||
{
|
||||
int idx = realUser.indexOf(TenantService.SEPARATOR);
|
||||
if ((idx != -1) && (idx < (realUser.length() - 1)))
|
||||
{
|
||||
if (uid.equals(AuthenticationUtil.getSystemUserName()))
|
||||
{
|
||||
uid = uid + TenantService.SEPARATOR + currentUser.substring(idx+1);
|
||||
uid = uid + TenantService.SEPARATOR + realUser.substring(idx + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AuthenticationUtil.setCurrentUser(uid);
|
||||
if (realUser == null)
|
||||
{
|
||||
AuthenticationUtil.setCurrentRealUser(uid);
|
||||
}
|
||||
AuthenticationUtil.setCurrentEffectiveUser(uid);
|
||||
|
||||
result = runAsWork.doWork();
|
||||
return result;
|
||||
}
|
||||
@@ -349,10 +594,13 @@ public abstract class AuthenticationUtil
|
||||
}
|
||||
finally
|
||||
{
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
if (currentUser != null)
|
||||
if (realUser == null)
|
||||
{
|
||||
AuthenticationUtil.setCurrentUser(currentUser);
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthenticationUtil.setCurrentEffectiveUser(effectiveUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -392,9 +392,19 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
perm = permIn;
|
||||
}
|
||||
|
||||
if(AuthenticationUtil.getCurrentEffectiveUserName() == null)
|
||||
{
|
||||
return AccessStatus.DENIED;
|
||||
}
|
||||
|
||||
if(AuthenticationUtil.getCurrentEffectiveUserName().equals(AuthenticationUtil.getSystemUserName()))
|
||||
{
|
||||
return AccessStatus.ALLOWED;
|
||||
}
|
||||
|
||||
// Get the current authentications
|
||||
// Use the smart authentication cache to improve permissions performance
|
||||
Authentication auth = authenticationComponent.getCurrentAuthentication();
|
||||
Authentication auth = AuthenticationUtil.getCurrentEffectiveAuthentication();
|
||||
final Set<String> authorisations = getAuthorisations(auth, nodeRef);
|
||||
|
||||
// If the node does not support the given permission there is no point
|
||||
@@ -496,9 +506,19 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
|
||||
return AccessStatus.DENIED;
|
||||
}
|
||||
|
||||
if(AuthenticationUtil.getCurrentEffectiveUserName() == null)
|
||||
{
|
||||
return AccessStatus.DENIED;
|
||||
}
|
||||
|
||||
if(AuthenticationUtil.getCurrentEffectiveUserName().equals(AuthenticationUtil.getSystemUserName()))
|
||||
{
|
||||
return AccessStatus.ALLOWED;
|
||||
}
|
||||
|
||||
// Get the current authentications
|
||||
// Use the smart authentication cache to improve permissions performance
|
||||
Authentication auth = authenticationComponent.getCurrentAuthentication();
|
||||
Authentication auth = AuthenticationUtil.getCurrentEffectiveAuthentication();
|
||||
if (auth == null)
|
||||
{
|
||||
throw new IllegalStateException("Unauthenticated");
|
||||
|
@@ -89,6 +89,34 @@ public class PermissionServiceTest extends AbstractPermissionTest
|
||||
allowAndyReadChildren = new SimplePermissionEntry(rootNodeRef, getPermission(PermissionService.READ_CHILDREN), "andy", AccessStatus.ALLOWED);
|
||||
}
|
||||
|
||||
public void testRunAsRealAndEffectiveUsers()
|
||||
{
|
||||
runAs("admin");
|
||||
|
||||
final NodeRef n1 = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, QName.createQName("{namespace}one"), ContentModel.TYPE_FOLDER).getChildRef();
|
||||
|
||||
runAs("andy");
|
||||
assertTrue(permissionService.hasPermission(n1, getPermission(PermissionService.CONTRIBUTOR)) == AccessStatus.DENIED);
|
||||
|
||||
assertEquals("andy", AuthenticationUtil.getCurrentRealUserName());
|
||||
assertEquals("andy", AuthenticationUtil.getCurrentEffectiveUserName());
|
||||
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>() {
|
||||
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
assertTrue(permissionService.hasPermission(n1, getPermission(PermissionService.CONTRIBUTOR)) == AccessStatus.ALLOWED);
|
||||
|
||||
assertEquals("andy", AuthenticationUtil.getCurrentRealUserName());
|
||||
assertEquals("admin", AuthenticationUtil.getCurrentEffectiveUserName());
|
||||
return null;
|
||||
}}, "admin");
|
||||
|
||||
assertEquals("andy", AuthenticationUtil.getCurrentRealUserName());
|
||||
assertEquals("andy", AuthenticationUtil.getCurrentEffectiveUserName());
|
||||
|
||||
}
|
||||
|
||||
public void testDefaultModelPermissions()
|
||||
{
|
||||
runAs("admin");
|
||||
|
Reference in New Issue
Block a user