/*
 *   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed 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.ldap.server.authz;


import org.apache.ldap.common.message.LockableAttributesImpl;
import org.apache.ldap.common.message.LockableAttributeImpl;
import org.apache.ldap.common.name.LdapName;
import org.apache.ldap.common.exception.LdapNameNotFoundException;
import org.apache.ldap.common.exception.LdapNoPermissionException;

import javax.naming.NamingException;
import javax.naming.Name;
import javax.naming.NamingEnumeration;
import javax.naming.directory.*;


/**
 * Tests whether or not authorization around search, list and lookup operations
 * work properly.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * @version $Rev$
 */
public class SearchAuthorizationTest extends AbstractAuthorizationTest
{
    /**
     * Generates a set of simple organizationalUnit entries where the
     * ou of the entry returned is the index of the entry in the array.
     *
     * @param count the number of entries to produce
     * @return an array of entries with length = count
     */
    private Attributes[] getTestNodes( final int count )
    {
        Attributes[] attributes = new Attributes[count];
        for ( int ii = 0; ii < count; ii++ )
        {
            attributes[ii] = new LockableAttributesImpl();
            Attribute oc = new LockableAttributeImpl( "objectClass" );
            oc.add( "top" );
            oc.add( "organizationalUnit" );
            attributes[ii].put( oc );
            attributes[ii].put( "ou", String.valueOf( count ) );
        }

        return attributes;
    }


    private void recursivelyAddSearchData( Name parent, Attributes[] children, final int sizeLimit, int[] count )
            throws NamingException
    {
        Name[] childRdns = new Name[children.length];
        for ( int ii = 0; ii < children.length && count[0] < sizeLimit; ii++ )
        {
            Name childRdn = new LdapName();
            childRdn.addAll( parent );
            childRdn.add( "ou=" + ii );
            childRdns[ii] = childRdn;
            sysRoot.createSubcontext( childRdn, children[ii] );
            count[0]++;
        }

        if ( count[0] >= sizeLimit )
        {
            return;
        }

        for ( int ii = 0; ii < children.length && count[0] < sizeLimit; ii++ )
        {
            recursivelyAddSearchData( childRdns[ii], children, sizeLimit, count );
        }
    }


    /**
     * Starts creating nodes under a parent with a set number of children.  First
     * a single node is created under the parent.  Thereafter a number of children
     * determined by the branchingFactor is added.  Until a sizeLimit is reached
     * descendants are created this way in a breath first recursive descent.
     *
     * @param parent the parent under which the first node is created
     * @param branchingFactor
     * @param sizelimit
     * @return the immediate child node created under parent which contains the subtree
     * @throws NamingException
     */
    private Name addSearchData( Name parent, int branchingFactor, int sizelimit ) throws NamingException
    {
        parent = ( Name ) parent.clone();
        parent.add( "ou=tests" );
        sysRoot.createSubcontext( parent, getTestNodes(1)[0] );
        recursivelyAddSearchData( parent, getTestNodes( branchingFactor ), sizelimit, new int[] { 1 } );
        return parent;
    }


    /**
     * Recursively deletes all entries including the base specified.
     *
     * @param rdn the relative dn from ou=system of the entry to delete recursively
     * @throws NamingException if there are problems deleting entries
     */
    private void recursivelyDelete( Name rdn ) throws NamingException
    {
        NamingEnumeration results = sysRoot.search( rdn, "(objectClass=*)", new SearchControls() );
        while ( results.hasMore() )
        {
            SearchResult result = ( SearchResult ) results.next();
            Name childRdn = new LdapName( result.getName() );
            childRdn.remove( 0 );
            recursivelyDelete( childRdn );
        }
        sysRoot.destroySubcontext( rdn );
    }


    /**
     * Performs a single level search as a specific user on newly created data and checks
     * that result set count is 3.  The basic (objectClass=*) filter is used.
     *
     * @param uid the uid RDN attribute value for the user under ou=users,ou=system
     * @param password the password of the user
     * @return true if the search succeeds as expected, false otherwise
     * @throws NamingException if there are problems conducting the search
     */
    private boolean checkCanSearchAs( String uid, String password ) throws NamingException
    {
        return checkCanSearchAs( uid, password, "(objectClass=*)", null, 3 );
    }


    /**
     * Performs a single level search as a specific user on newly created data and checks
     * that result set count is equal to a user specified amount.  The basic
     * (objectClass=*) filter is used.
     *
     * @param uid the uid RDN attribute value for the user under ou=users,ou=system
     * @param password the password of the user
     * @param resultSetSz the expected size of the results
     * @return true if the search succeeds as expected, false otherwise
     * @throws NamingException if there are problems conducting the search
     */
    private boolean checkCanSearchAs( String uid, String password, int resultSetSz ) throws NamingException
    {
        return checkCanSearchAs( uid, password, "(objectClass=*)", null, resultSetSz );
    }


    /**
     * Performs a search as a specific user on newly created data and checks
     * that result set count is equal to a user specified amount.  The basic
     * (objectClass=*) filter is used.
     *
     * @param uid the uid RDN attribute value for the user under ou=users,ou=system
     * @param password the password of the user
     * @param resultSetSz the expected size of the results
     * @return true if the search succeeds as expected, false otherwise
     * @throws NamingException if there are problems conducting the search
     */
    private boolean checkCanSearchAs( String uid, String password, SearchControls cons, int resultSetSz )
            throws NamingException
    {
        return checkCanSearchAs( uid, password, "(objectClass=*)", cons, resultSetSz );
    }


    /**
     * Performs a search as a specific user on newly created data and checks
     * that result set count is equal to a user specified amount.
     *
     * @param uid the uid RDN attribute value for the user under ou=users,ou=system
     * @param password the password of the user
     * @param filter the search filter to use
     * @param resultSetSz the expected size of the results
     * @return true if the search succeeds as expected, false otherwise
     * @throws NamingException if there are problems conducting the search
     */
    private boolean checkCanSearchAs( String uid, String password, String filter,
                                      SearchControls cons, int resultSetSz ) throws NamingException
    {
        if ( cons == null )
        {
            cons = new SearchControls();
        }

        Name base = addSearchData( new LdapName(), 3, 10 );
        Name userDn = new LdapName( "uid="+uid+",ou=users,ou=system" );
        try
        {
            DirContext userCtx = getContextAs( userDn, password );
            NamingEnumeration list = userCtx.search( base, filter, cons );
            int counter = 0;
            while ( list.hasMore() )
            {
                list.next();
                counter++;
            }
            return counter == resultSetSz;
        }
        catch ( LdapNoPermissionException e )
        {
            return false;
        }
        finally
        {
            recursivelyDelete( base );
        }
    }


    /**
     * Checks to see that the addSearchData() and the recursiveDelete()
     * functions in this test work properly.
     *
     * @throws NamingException if there is a problem with the implementation of
     * these utility functions
     */
    public void testAddSearchData() throws NamingException
    {
//        Name base = addSearchData( new LdapName(), 3, 10 );
//        SearchControls controls = new SearchControls();
//        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
//        NamingEnumeration results = sysRoot.search( base, "(objectClass=*)", controls );
//        int counter = 0;
//        while ( results.hasMore() )
//        {
//            results.next();
//            counter++;
//        }
//
//        assertEquals( 10, counter );
//        recursivelyDelete( base );
//        try { sysRoot.lookup( base ); fail(); } catch ( LdapNameNotFoundException e ) {}
    }


//    /**
//     * Checks to make sure group membership based userClass works for add operations.
//     *
//     * @throws javax.naming.NamingException if the test encounters an error
//     */
//    public void testGrantAdministrators() throws NamingException
//    {
//        // create the non-admin user
//        createUser( "billyd", "billyd" );
//
//        // try an add operation which should fail without any ACI
//        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
//
//        // Gives grantAdd perm to all users in the Administrators group for
//        // entries and all attribute types and values
//        createAccessControlSubentry( "searchAdmin", "{ " +
//                "identificationTag \"addAci\", " +
//                "precedence 14, " +
//                "authenticationLevel none, " +
//                "itemOrUserFirst userFirst: { " +
//                "userClasses { userGroup { \"cn=Administrators,ou=groups,ou=system\" } }, " +
//                "userPermissions { { " +
//                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
//                "grantsAndDenials { grantRead, grantReturnDN, grantBrowse } } } } }" );
//
//        // see if we can now add that test entry which we could not before
//        // add op should still fail since billd is not in the admin group
//        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
//
//        // now add billyd to the Administrator group and try again
//        addUserToGroup( "billyd", "Administrators" );
//
//        // try an add operation which should succeed with ACI and group membership change
//        assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
//    }
//
//
//    /**
//     * Checks to make sure name based userClass works for add operations.
//     *
//     * @throws javax.naming.NamingException if the test encounters an error
//     */
//    public void testGrantAddByName() throws NamingException
//    {
//        // create the non-admin user
//        createUser( "billyd", "billyd" );
//
//        // try an add operation which should fail without any ACI
//        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
//
//        // now add a subentry that enables user billyd to add an entry below ou=system
//        createAccessControlSubentry( "billydAdd", "{ " +
//                "identificationTag \"addAci\", " +
//                "precedence 14, " +
//                "authenticationLevel none, " +
//                "itemOrUserFirst userFirst: { " +
//                "userClasses { name { \"uid=billyd,ou=users,ou=system\" } }, " +
//                "userPermissions { { " +
//                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
//                "grantsAndDenials { grantAdd, grantBrowse } } } } }" );
//
//        // should work now that billyd is authorized by name
//        assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
//    }
//
//
//    /**
//     * Checks to make sure subtree based userClass works for add operations.
//     *
//     * @throws javax.naming.NamingException if the test encounters an error
//     */
//    public void testGrantAddBySubtree() throws NamingException
//    {
//        // create the non-admin user
//        createUser( "billyd", "billyd" );
//
//        // try an add operation which should fail without any ACI
//        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
//
//        // now add a subentry that enables user billyd to add an entry below ou=system
//        createAccessControlSubentry( "billyAddBySubtree", "{ " +
//                "identificationTag \"addAci\", " +
//                "precedence 14, " +
//                "authenticationLevel none, " +
//                "itemOrUserFirst userFirst: { " +
//                "userClasses { subtree { { base \"ou=users,ou=system\" } } }, " +
//                "userPermissions { { " +
//                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
//                "grantsAndDenials { grantAdd, grantBrowse } } } } }" );
//
//        // should work now that billyd is authorized by the subtree userClass
//        assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
//    }
//
//
//    /**
//     * Checks to make sure <b>allUsers</b> userClass works for add operations.
//     *
//     * @throws javax.naming.NamingException if the test encounters an error
//     */
//    public void testGrantAddAllUsers() throws NamingException
//    {
//        // create the non-admin user
//        createUser( "billyd", "billyd" );
//
//        // try an add operation which should fail without any ACI
//        assertFalse( checkCanSearchAs( "billyd", "billyd" ) );
//
//        // now add a subentry that enables anyone to add an entry below ou=system
//        createAccessControlSubentry( "anybodyAdd", "{ " +
//                "identificationTag \"addAci\", " +
//                "precedence 14, " +
//                "authenticationLevel none, " +
//                "itemOrUserFirst userFirst: { " +
//                "userClasses { allUsers }, " +
//                "userPermissions { { " +
//                "protectedItems {entry, allUserAttributeTypesAndValues}, " +
//                "grantsAndDenials { grantAdd, grantBrowse } } } } }" );
//
//        // see if we can now add that test entry which we could not before
//        // should work now with billyd now that all users are authorized
//        assertTrue( checkCanSearchAs( "billyd", "billyd" ) );
//    }
}
