Package dk.brics.jwig.persistence.security

Source Code of dk.brics.jwig.persistence.security.DirectObjectSecurityManagerImpl

package dk.brics.jwig.persistence.security;

import dk.brics.jwig.AccessDeniedException;
import dk.brics.jwig.DispatchAdapter;
import dk.brics.jwig.JWIGException;
import dk.brics.jwig.WebApp;
import dk.brics.jwig.persistence.Persistable;
import dk.brics.jwig.persistence.Querier;
import dk.brics.jwig.server.DispatchListener;
import dk.brics.jwig.server.ThreadDispatchEvent;
import dk.brics.jwig.server.WebMethodDispatchEvent;
import dk.brics.jwig.server.cache.ProxyObject;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
* See {@link DirectObjectSecurityManager}
*/
public class DirectObjectSecurityManagerImpl extends DispatchAdapter implements DirectObjectSecurityManager {
    private final WebApp webapp;
    private final Querier querier;
    private final ThreadLocal<Map<ProxyObject, Boolean>> persistenceCache = new ThreadLocal<Map<ProxyObject, Boolean>>();

    public DirectObjectSecurityManagerImpl(WebApp webapp, Querier querier) {
        this.webapp = webapp;
        this.querier = querier;
    }

    @Override
  public boolean hasAccess(Persistable persistable) { //FIXME: Should it be safe to assume that we can cache the result?
        ProxyObject proxyObject = new ProxyObject(webapp.getWebSite().getQuerier(), persistable);
        Map<ProxyObject, Boolean> objectBooleanMap = persistenceCache.get();
        if (objectBooleanMap.containsKey(proxyObject)) {
            return objectBooleanMap.get(proxyObject);
        }
        boolean b = hasAccess(persistable, 0);
        objectBooleanMap.put(proxyObject, b);
        return b;
    }

    public boolean hasAccess(Persistable persistable, int depth) {
        if (depth == 100) {
            throw new AccessDeniedException("Failed to prove access in depth 100");
        }
        if (persistable == null) {
            return false;
        }
        //First check the value returned by the access method
        boolean accessMethodResult = true;
        boolean hasAccessMethod = false;
        try {
            Method m = webapp.getClass().getMethod("access", querier.getClass(persistable));
            Class<?> returnType = m.getReturnType();
            if (returnType == boolean.class || returnType == Boolean.class) {
                Object o = m.invoke(webapp, persistable);
                if (o instanceof Boolean) {
                    accessMethodResult = (Boolean) o;
                    hasAccessMethod = true;
                }
            }
        } catch (NoSuchMethodException e) {
            //
        } catch (Exception e) {
            throw new JWIGException(e);
        }
        if (!accessMethodResult) {
            return false;
        }
        //If the access method returns true, make sure the constraints from the @AccessScope annotations are also satisfied
        boolean accessScopeAnnotationResult = true;
        boolean hasAccessScopeAnnotation = false;
        for (Method m : querier.getClass(persistable).getMethods()) {
            if (m.getAnnotation(AccessScope.class) != null) {
                if (m.getParameterTypes().length == 0 && Persistable.class.isAssignableFrom(m.getReturnType())) {
                    m.setAccessible(true);
                    hasAccessScopeAnnotation = true;
                    try {
                        accessScopeAnnotationResult &= hasAccess((Persistable) m.invoke(persistable), depth + 1);
                    } catch (Exception e) {
                        throw new JWIGException(e);
                    }
                }
            }
        }
        if (!hasAccessScopeAnnotation && !hasAccessMethod) return false;
        if (!hasAccessScopeAnnotation && hasAccessMethod) { //We know that the access method returned true
            return true;
        } else
            return accessScopeAnnotationResult;
    }

    @Override
  public void threadDispatched(ThreadDispatchEvent t) {
        persistenceCache.set(new HashMap<ProxyObject, Boolean>());
    }

    @Override
  public void threadDismissed(ThreadDispatchEvent t) {
        persistenceCache.set(null);
    }
}
TOP

Related Classes of dk.brics.jwig.persistence.security.DirectObjectSecurityManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.