package org.molgenis.security.core.runas;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.Advised;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import java.lang.reflect.Method;
/**
* Proxy that set a SystemSecurityToken in the security context for the duration of a method
*/
public class RunAsSystemProxy implements Advice, MethodInterceptor
{
private final Object targetObject;
public RunAsSystemProxy(Object targetObject)
{
this.targetObject = targetObject;
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable
{
Method interfaceMethod = invocation.getMethod();
Class<?> clazz = targetObject instanceof Advised ? ((Advised) targetObject).getTargetClass() : targetObject
.getClass();
Method targetMethod = clazz.getMethod(interfaceMethod.getName(), interfaceMethod.getParameterTypes());
if (!targetMethod.isAnnotationPresent(RunAsSystem.class))
{
return invocation.proceed();
}
return runAsSystem(invocation::proceed);
}
public static void runAsSystem(Runnable runnable)
{
runAsSystem(() ->
{
runnable.run();
return null;
});
}
public static <T, X extends Throwable> T runAsSystem(RunnableAsSystem<T, X> runnable) throws X
{
// Remember the original context
SecurityContext origCtx = SecurityContextHolder.getContext();
try
{
// Set a SystemSecurityToken
SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());
SecurityContextHolder.getContext().setAuthentication(new SystemSecurityToken());
return runnable.run();
}
finally
{
// Set the original context back when method is finished
SecurityContextHolder.setContext(origCtx);
}
}
}