001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *  
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *  
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License. 
018 *  
019 */
020package org.apache.directory.server.core.authz.support;
021
022
023import java.util.ArrayList;
024import java.util.Collection;
025
026import org.apache.directory.api.ldap.aci.ACITuple;
027import org.apache.directory.api.ldap.aci.UserClass;
028import org.apache.directory.api.ldap.model.entry.Entry;
029import org.apache.directory.api.ldap.model.exception.LdapException;
030
031
032/**
033 * An {@link ACITupleFilter} that chooses the tuples with the most specific user
034 * class. (18.8.4.2)
035 * <p>
036 * If more than one tuple remains, choose the tuples with the most specific user
037 * class. If there are any tuples matching the requestor with UserClasses element
038 * name or thisEntry, discard all other tuples. Otherwise if there are any tuples
039 * matching UserGroup, discard all other tuples. Otherwise if there are any tuples
040 * matching subtree, discard all other tuples.
041 *
042 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
043 */
044public class MostSpecificUserClassFilter implements ACITupleFilter
045{
046    /**
047     * {@inheritDoc}
048     */
049    @Override
050    public Collection<ACITuple> filter( AciContext aciContext, OperationScope scope, Entry userEntry )
051        throws LdapException
052    {
053        if ( aciContext.getAciTuples().size() <= 1 )
054        {
055            return aciContext.getAciTuples();
056        }
057
058        Collection<ACITuple> filteredTuples = new ArrayList<>();
059
060        // If there are any tuples matching the requestor with UserClasses
061        // element name or thisEntry, discard all other tuples.
062        for ( ACITuple tuple : aciContext.getAciTuples() )
063        {
064            for ( UserClass userClass : tuple.getUserClasses() )
065            {
066                if ( userClass instanceof UserClass.Name || userClass instanceof UserClass.ThisEntry )
067                {
068                    filteredTuples.add( tuple );
069                    break;
070                }
071            }
072        }
073
074        if ( !filteredTuples.isEmpty() )
075        {
076            return filteredTuples;
077        }
078
079        // Otherwise if there are any tuples matching UserGroup,
080        // discard all other tuples.
081        for ( ACITuple tuple : aciContext.getAciTuples() )
082        {
083            for ( UserClass userClass : tuple.getUserClasses() )
084            {
085                if ( userClass instanceof UserClass.UserGroup )
086                {
087                    filteredTuples.add( tuple );
088                    break;
089                }
090            }
091        }
092
093        if ( !filteredTuples.isEmpty() )
094        {
095            return filteredTuples;
096        }
097
098        // Otherwise if there are any tuples matching subtree,
099        // discard all other tuples.
100        for ( ACITuple tuple : aciContext.getAciTuples() )
101        {
102            for ( UserClass userClass : tuple.getUserClasses() )
103            {
104                if ( userClass instanceof UserClass.Subtree )
105                {
106                    filteredTuples.add( tuple );
107                    break;
108                }
109            }
110        }
111
112        if ( !filteredTuples.isEmpty() )
113        {
114            return filteredTuples;
115        }
116
117        return aciContext.getAciTuples();
118    }
119
120}