Package org.apache.sling.resourceaccesssecurity.impl

Source Code of org.apache.sling.resourceaccesssecurity.impl.ResourceAccessSecurityImpl

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sling.resourceaccesssecurity.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.security.AccessSecurityException;
import org.apache.sling.api.security.ResourceAccessSecurity;
import org.apache.sling.resourceaccesssecurity.ResourceAccessGate;
import org.apache.sling.resourceaccesssecurity.ResourceAccessGate.GateResult;
import org.osgi.framework.ServiceReference;

public abstract class ResourceAccessSecurityImpl implements ResourceAccessSecurity {

    private List<ResourceAccessGateHandler> allHandlers = Collections.emptyList();

    private final boolean defaultAllowIfNoGateMatches;

    public ResourceAccessSecurityImpl(final boolean defaultAllowIfNoGateMatches) {
        this.defaultAllowIfNoGateMatches = defaultAllowIfNoGateMatches;
    }

    /**
     * This method returns either an iterator delivering the matching handlers
     * or <code>null</code>.
     */
    private Iterator<ResourceAccessGateHandler> getMatchingResourceAccessGateHandlerIterator(
            final String path, final ResourceAccessGate.Operation operation) {
        //
        // TODO: maybe caching some frequent paths with read operation would be
        // a good idea
        //
        final List<ResourceAccessGateHandler> handlers = allHandlers;
        if (handlers.size() > 0) {

            final Iterator<ResourceAccessGateHandler> iter = handlers.iterator();
            return new Iterator<ResourceAccessGateHandler>() {

                private ResourceAccessGateHandler next;

                {
                    peek();
                }

                private void peek() {
                    this.next = null;
                    while ( iter.hasNext() && next == null ) {
                        final ResourceAccessGateHandler handler = iter.next();
                        if (handler.matches(path, operation)) {
                            next = handler;
                        }
                    }
                }

                @Override
                public boolean hasNext() {
                    return next != null;
                }

                @Override
                public ResourceAccessGateHandler next() {
                    if ( next == null ) {
                        throw new NoSuchElementException();
                    }
                    final ResourceAccessGateHandler handler = this.next;
                    peek();
                    return handler;
                }

                @Override
                public void remove() {
                    throw new UnsupportedOperationException();
                }
            };
        }

        return null;
    }

    @Override
    public Resource getReadableResource(final Resource resource) {
        Resource returnValue = null;

        final Iterator<ResourceAccessGateHandler> accessGateHandlers = getMatchingResourceAccessGateHandlerIterator(
                resource.getPath(), ResourceAccessGate.Operation.READ);

        GateResult finalGateResult = null;
        List<ResourceAccessGate> accessGatesForReadValues = null;
        boolean canReadAllValues = false;


        if ( accessGateHandlers != null ) {

            boolean noGateMatched = true;
           
            while ( accessGateHandlers.hasNext() ) {
                noGateMatched = false;
                final ResourceAccessGateHandler resourceAccessGateHandler  = accessGateHandlers.next();

                final GateResult gateResult = !resourceAccessGateHandler
                        .getResourceAccessGate().hasReadRestrictions(resource.getResourceResolver()) ? GateResult.GRANTED
                        : resourceAccessGateHandler.getResourceAccessGate()
                                .canRead(resource);
                if (!canReadAllValues && gateResult == GateResult.GRANTED) {
                    if (resourceAccessGateHandler.getResourceAccessGate().canReadAllValues(resource)) {
                        canReadAllValues = true;
                        accessGatesForReadValues = null;
                    } else {
                        if (accessGatesForReadValues == null) {
                            accessGatesForReadValues = new ArrayList<ResourceAccessGate>();
                        }
                        accessGatesForReadValues.add(resourceAccessGateHandler.getResourceAccessGate());
                    }
                }
                if (finalGateResult == null) {
                    finalGateResult = gateResult;
                } else if (finalGateResult != GateResult.GRANTED && gateResult != GateResult.CANT_DECIDE) {
                    finalGateResult = gateResult;
                }
                // stop checking if the operation is final and the result not GateResult.CANT_DECIDE
                if (gateResult != GateResult.CANT_DECIDE  && resourceAccessGateHandler.isFinalOperation(ResourceAccessGate.Operation.READ)) {
                    break;
                }
            }


            // return null if access is denied or no ResourceAccessGate is present
            if (finalGateResult == GateResult.DENIED) {
                returnValue = null;
            } else if (finalGateResult == GateResult.GRANTED ) {
                returnValue = resource;
            } else if (noGateMatched && this.defaultAllowIfNoGateMatches)
            {
                returnValue = resource;
            }
        }

        boolean canUpdateResource = canUpdate(resource);

        // wrap Resource if read access is not or partly (values) not granted
        if (returnValue != null) {
            if( !canReadAllValues || !canUpdateResource ) {
                returnValue = new AccessGateResourceWrapper(returnValue,
                        accessGatesForReadValues,
                        canUpdateResource);
            }
        }

        return returnValue;
    }

    @Override
    public boolean canCreate(final String path,
            final ResourceResolver resolver) {
        final Iterator<ResourceAccessGateHandler> handlers = getMatchingResourceAccessGateHandlerIterator(
                path, ResourceAccessGate.Operation.CREATE);
        boolean result = false;
        if ( handlers != null ) {
            GateResult finalGateResult = null;
            boolean noGateMatched = true;

            while ( handlers.hasNext() ) {
                noGateMatched = false;
                final ResourceAccessGateHandler resourceAccessGateHandler  = handlers.next();

                final GateResult gateResult = !resourceAccessGateHandler
                        .getResourceAccessGate().hasCreateRestrictions(resolver) ? GateResult.GRANTED
                        : resourceAccessGateHandler.getResourceAccessGate()
                                .canCreate(path, resolver);
                if (finalGateResult == null) {
                    finalGateResult = gateResult;
                } else if (finalGateResult != GateResult.GRANTED && gateResult != GateResult.CANT_DECIDE) {
                    finalGateResult = gateResult;
                }
                if (finalGateResult == GateResult.GRANTED || gateResult != GateResult.CANT_DECIDE &&
                        resourceAccessGateHandler.isFinalOperation(ResourceAccessGate.Operation.CREATE)) {
                    break;
                }
            }

            if ( finalGateResult == GateResult.GRANTED ) {
                result = true;
            } else if ( finalGateResult == GateResult.DENIED ) {
                result = false;
            } else if ( noGateMatched && this.defaultAllowIfNoGateMatches )
            {
                result = true;
            }
        }
        return result;
    }

    @Override
    public boolean canUpdate(final Resource resource) {
        final Iterator<ResourceAccessGateHandler> handlers = getMatchingResourceAccessGateHandlerIterator(
                resource.getPath(), ResourceAccessGate.Operation.UPDATE);
        boolean result = this.defaultAllowIfNoGateMatches;
        if ( handlers != null ) {
            GateResult finalGateResult = null;
            boolean noGateMatched = true;

            while ( handlers.hasNext() ) {
                noGateMatched = false;
                final ResourceAccessGateHandler resourceAccessGateHandler  = handlers.next();

                final GateResult gateResult = !resourceAccessGateHandler
                        .getResourceAccessGate().hasUpdateRestrictions(resource.getResourceResolver()) ? GateResult.GRANTED
                        : resourceAccessGateHandler.getResourceAccessGate()
                                .canUpdate(resource);
                if (finalGateResult == null) {
                    finalGateResult = gateResult;
                } else if (finalGateResult != GateResult.GRANTED && gateResult != GateResult.CANT_DECIDE) {
                    finalGateResult = gateResult;
                }
                if (finalGateResult == GateResult.GRANTED || gateResult != GateResult.CANT_DECIDE &&
                        resourceAccessGateHandler.isFinalOperation(ResourceAccessGate.Operation.UPDATE)) {
                    break;
                }
            }

            if ( finalGateResult == GateResult.GRANTED ) {
                result = true;
            } else if ( finalGateResult == GateResult.DENIED ) {
                result = false;
            } else if ( noGateMatched && this.defaultAllowIfNoGateMatches )
            {
                result = true;
            }
        }
        return result;
    }

    @Override
    public boolean canDelete(final Resource resource) {
        final Iterator<ResourceAccessGateHandler> handlers = getMatchingResourceAccessGateHandlerIterator(
                resource.getPath(), ResourceAccessGate.Operation.DELETE);
        boolean result = this.defaultAllowIfNoGateMatches;
        if ( handlers != null ) {
            GateResult finalGateResult = null;
            boolean noGateMatched = true;

            while ( handlers.hasNext() ) {
                noGateMatched = false;
                final ResourceAccessGateHandler resourceAccessGateHandler  = handlers.next();

                final GateResult gateResult = !resourceAccessGateHandler
                        .getResourceAccessGate().hasDeleteRestrictions(resource.getResourceResolver()) ? GateResult.GRANTED
                        : resourceAccessGateHandler.getResourceAccessGate()
                                .canDelete(resource);
                if (finalGateResult == null) {
                    finalGateResult = gateResult;
                } else if (finalGateResult != GateResult.GRANTED && gateResult != GateResult.CANT_DECIDE) {
                    finalGateResult = gateResult;
                }
                if (finalGateResult == GateResult.GRANTED || gateResult != GateResult.CANT_DECIDE &&
                        resourceAccessGateHandler.isFinalOperation(ResourceAccessGate.Operation.DELETE)) {
                    break;
                }
            }

            if ( finalGateResult == GateResult.GRANTED ) {
                result = true;
            } else if ( finalGateResult == GateResult.DENIED ) {
                result = false;
            } else if ( noGateMatched && this.defaultAllowIfNoGateMatches )
            {
                result = true;
            }
        }
        return result;
    }

    @Override
    public boolean canExecute(final Resource resource) {
        final Iterator<ResourceAccessGateHandler> handlers = getMatchingResourceAccessGateHandlerIterator(
                resource.getPath(), ResourceAccessGate.Operation.EXECUTE);
        boolean result = this.defaultAllowIfNoGateMatches;
        if ( handlers != null ) {
            GateResult finalGateResult = null;
            boolean noGateMatched = true;

            while ( handlers.hasNext() ) {
                noGateMatched = false;
                final ResourceAccessGateHandler resourceAccessGateHandler  = handlers.next();

                final GateResult gateResult = !resourceAccessGateHandler
                        .getResourceAccessGate().hasExecuteRestrictions(resource.getResourceResolver()) ? GateResult.GRANTED
                        : resourceAccessGateHandler.getResourceAccessGate()
                                .canExecute(resource);
                if (finalGateResult == null) {
                    finalGateResult = gateResult;
                } else if (finalGateResult != GateResult.GRANTED && gateResult != GateResult.CANT_DECIDE) {
                    finalGateResult = gateResult;
                }
                if (finalGateResult == GateResult.GRANTED || gateResult != GateResult.CANT_DECIDE && resourceAccessGateHandler.isFinalOperation(ResourceAccessGate.Operation.EXECUTE)) {
                    break;
                }
            }

            if ( finalGateResult == GateResult.GRANTED ) {
                result = true;
            } else if ( finalGateResult == GateResult.DENIED ) {
                result = false;
            } else if ( noGateMatched && this.defaultAllowIfNoGateMatches )
            {
                result = true;
            }
        }
        return result;
    }

    @Override
    public boolean canReadValue(final Resource resource, final String valueName) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean canSetValue(final Resource resource, final String valueName) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean canDeleteValue(final Resource resource, final String valueName) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public String transformQuery(final String query,
            final String language,
            final ResourceResolver resourceResolver)
    throws AccessSecurityException {
        String returnValue = query;

        for (ResourceAccessGateHandler handler : allHandlers) {
            returnValue = handler.getResourceAccessGate().transformQuery(
                    returnValue, language, resourceResolver);
            if (returnValue == null) {
                throw new AccessSecurityException(
                        "Method transformQuery in ResourceAccessGate "
                                + handler.getResourceAccessGate().getClass()
                                        .getName() + " returned null.");
            }
        }

        return returnValue;
    }

    /**
     * Add a new resource access gate
     */
    protected void bindResourceAccessGate(final ServiceReference ref) {
        synchronized ( this ) {
            final List<ResourceAccessGateHandler> newList = new ArrayList<ResourceAccessGateHandler>(this.allHandlers);

            final ResourceAccessGateHandler h = new ResourceAccessGateHandler(ref);
            newList.add(h);
            Collections.sort(newList);
            this.allHandlers = newList;
        }
    }

    /**
     * Remove a resource access gate
     */
    protected void unbindResourceAccessGate(final ServiceReference ref) {
        synchronized ( this ) {
            final List<ResourceAccessGateHandler> newList = new ArrayList<ResourceAccessGateHandler>(this.allHandlers);

            final ResourceAccessGateHandler h = new ResourceAccessGateHandler(ref);
            newList.remove(h);
            this.allHandlers = newList;
        }
    }
}
TOP

Related Classes of org.apache.sling.resourceaccesssecurity.impl.ResourceAccessSecurityImpl

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.