/*
 *   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.directory.fortress.core.samples;


import java.util.Enumeration;
import java.util.List;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.directory.fortress.core.AccessMgr;
import org.apache.directory.fortress.core.AccessMgrFactory;
import org.apache.directory.fortress.core.SecurityException;
import org.apache.directory.fortress.core.model.Permission;
import org.apache.directory.fortress.core.model.Session;
import org.apache.directory.fortress.core.impl.TestUtils;
import org.apache.directory.fortress.core.model.User;
import org.apache.directory.fortress.core.model.UserAdminRole;
import org.apache.directory.fortress.core.model.UserRole;


/**
 * AccessMgrSample JUnit Test. The APIs exercised within this class are used to perform
 * runtime security policy enforcement for data center applications.  These APIs are thread safe and can be
 * executed within high-volume Java transactional environments like Java EE Web,EJB and Service tier applications,
 * Because these APIs require direct access to the LDAP server, it is not recommended that they be called from
 * thick client applications (i.e. Applets) unless the thick client is running on a machine that is "behind the firewall" (or on VPN) that
 * are common to enterprise data center runtime environments.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class AccessMgrSample extends TestCase
{
    private static final String CLS_NM = AccessMgrSample.class.getName();
    private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );


    public AccessMgrSample( String name )
    {
        super( name );
    }


    /**
     * Run the Fortress AccessMgr samples.
     */
    public static Test suite()
    {
        TestSuite suite = new TestSuite();
        suite.addTest( new AccessMgrSample( "testCheckAccess" ) );
        suite.addTest( new AccessMgrSample( "testSessionPermissions" ) );
        suite.addTest( new AccessMgrSample( "testSessionRoles" ) );
        suite.addTest( new AccessMgrSample( "testAddActiveRoles" ) );
        suite.addTest( new AccessMgrSample( "testDropActiveRoles" ) );
        suite.addTest( new AccessMgrSample( "testDisplayUserSession" ) );

        return suite;
    }


    /**
     * The checkAccess API is used to perform authorization on User.  It will return a 'true' if User is authorized to
     * perform operation or a 'false' if User is not.  This API is useful for performing method or service level authorization
     * within Server side programs.  It is expected that this API will be wrapped by other application Security frameworks
     * i.e. Spring or Java EE to provide fine-grained permission check authorization capabilities to business applications
     * running in the datacenter.
     */
    public static void testCheckAccess()
    {
        String szLocation = ".testCheckAccess";
        try
        {
            // Instantiate the AccessMgr implementation.
            AccessMgr accessMgr = AccessMgrFactory.createInstance( TestUtils.getContext() );

            // utility function will create an Fortress Session.  The Session contains the user's activated
            // roles along with other related attributes and status information (i.e. password status)
            Session session = createSession( CreateUserSample.TEST_USERID,
                CreateUserSample.TEST_PASSWORD.toCharArray(), accessMgr );
            assertNotNull( session );

            for ( int i = 1; i < 6; i++ )
            {
                // Fortress Permissions have an Object name and Operation name.  There is a one to many relationship between
                // objects and operations.  An example is object name "MyDataBaseTable" operations "READ", "WRITE", "DELETE". or object "MyFile" operations "R", "W", "C" or "MyClassName" "methodA", "methodB", "methodC", or "MyPageName.ControlName" "checkOut", "applyDiscount".
                Permission inPerm = new Permission( CreatePermSample.TEST_PERM_OBJECT,
                    CreatePermSample.TEST_PERM_OPERATION_PREFIX + i );
                // method will return a 'true' if authorized or 'false' if not.
                boolean result = accessMgr.checkAccess( session, inPerm );
                assertTrue( szLocation, result );
                LOG.info( szLocation + " user [" + session.getUserId() + "] permission object ["
                    + inPerm.getObjName() + "] operation name [" + inPerm.getOpName() + "] success" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( szLocation + " caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    /**
     * The sessionPermissions API is useful for GUI programs that need to cache all of the User's Permissions in the
     * HTTP Session or application cache.  This is useful when providing access control lists for menu items and other
     * controls that sometimes need to check authorizations on.  This API will return all permissions that are granted
     * to User's activated Roles along with Permissions that have been granted directly to the User entity itself.
     */
    public static void testSessionPermissions()
    {
        String szLocation = ".testSessionPermissions";
        try
        {
            // Instantiate the AccessMgr implementation.
            AccessMgr accessMgr = AccessMgrFactory.createInstance( TestUtils.getContext() );

            // utility function will create an Fortress Session.  The Session contains the user's activated
            // roles along with other related attributes and status information (i.e. password status)
            Session session = createSession( CreateUserSample.TEST_USERID,
                CreateUserSample.TEST_PASSWORD.toCharArray(), accessMgr );
            assertNotNull( session );
            List<Permission> perms = accessMgr.sessionPermissions( session );
            assertNotNull( perms );
            assertTrue( szLocation + " list check, expected: 5, actual:" + perms.size(), perms.size() == 5 );

            // iterate over expected permissions to make sure they are returned from sessionPermissions API.
            for ( int i = 1; i < 6; i++ )
            {
                // A Permission consists of an object name and operation name.
                Permission checkPerm = new Permission( CreatePermSample.TEST_PERM_OBJECT,
                    CreatePermSample.TEST_PERM_OPERATION_PREFIX + i );
                boolean result = accessMgr.checkAccess( session, checkPerm );
                assertTrue( szLocation, result );
                LOG.info( szLocation + " user [" + session.getUserId() + "] permission object ["
                    + checkPerm.getObjName() + "] operation name [" + checkPerm.getOpName() + "] success" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( szLocation + " caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    /**
     * The RBAC Session can be interrogated to return the list of all activated Roles within a User's Session.  The API
     * will cache these Roles in the User's Session object.  The Roles will also include temporal data that is used to
     * enforce the day, date and time for which a given Role may be placed in the User's Session.
     */
    public static void testSessionRoles()
    {
        String szLocation = ".testSessionRoles";
        User inUser = new User( CreateUserSample.TEST_USERID );
        try
        {
            // Instantiate the AccessMgr implementation.
            AccessMgr accessMgr = AccessMgrFactory.createInstance( TestUtils.getContext() );
            // utility function will create an Fortress Session.  The Session contains the user's activated
            // roles along with other related attributes and status information (i.e. password status)
            Session session = createSession( CreateUserSample.TEST_USERID,
                CreateUserSample.TEST_PASSWORD.toCharArray(), accessMgr );
            // A null Session would be a bug and should never happen.  Fortress will throw a SecurityException if it cannot create.
            assertNotNull( session );
            // Get the activated Roles from the Session.
            List<UserRole> uRoles = accessMgr.sessionRoles( session );
            // The list of Roles could be null if User has not been assigned any or if all assigned failed activation checks.
            assertNotNull( uRoles );
            // Test to see that the list size is same as expected.
            assertTrue( szLocation + " list check, expected: 10, actual:" + uRoles.size(), uRoles.size() == 10 );

            // Test to ensure that all of the roles activated are returned in the uRoles list.  In a real
            // program this would not be necessary.
            for ( int i = 1; i < 11; i++ )
            {
                UserRole inUserRole = new UserRole( inUser.getUserId(), CreateRoleSample.TEST_ROLE_PREFIX + i );
                assertTrue(
                    szLocation + " contains check userId [" + inUserRole.getUserId() + "] role ["
                        + inUserRole.getName() + "]", uRoles.contains( inUserRole ) );
                LOG.info( szLocation + " userId [" + inUserRole.getUserId() + "] activated role ["
                    + inUserRole.getName() + "] found in session" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( szLocation + " caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    /**
     * The addActivateRole API allows only Roles that have been assigned to a given User to be activated in their
     * RBAC Session.  The API will also ensure that a given Role has passed its constraint tests which include
     * Static Separation of Duty (SSD) and RBAC Role temporal constraint validations.
     */
    public static void testAddActiveRoles()
    {
        String szLocation = ".testAddActiveRoles";
        try
        {
            // Instantiate the AccessMgr implementation.
            AccessMgr accessMgr = AccessMgrFactory.createInstance( TestUtils.getContext() );
            // authenticate will check the password but will not activated any roles into Session.
            Session session = authenticate( CreateUserSample.TEST_USERID, CreateUserSample.TEST_PASSWORD.toCharArray(),
                accessMgr );
            assertNotNull( session );
            // now, activate roles into User's Session one at a time:
            for ( int i = 1; i < 11; i++ )
            {
                UserRole addUserRole = new UserRole( CreateUserSample.TEST_USERID, CreateRoleSample.TEST_ROLE_PREFIX
                    + i );
                accessMgr.addActiveRole( session, addUserRole );
                LOG.info( szLocation + " userId [" + addUserRole.getUserId() + "] activated role ["
                    + addUserRole.getName() + "] added to session" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( szLocation + " caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    /**
     * RBAC compliant systems allow User Roles to be activated and deactivated from their Session.  This facilitates
     * the principle of least privilege which prescribes only giving User's as much capability as they need to complete
     * their job duties.  This means not all Roles that a User may be authorized to activated will necessarily be active
     * at any one point in time.  This allows for separation of duty restrictions to be enforced.
     */
    public static void testDropActiveRoles()
    {
        String szLocation = ".testDropActiveRoles";
        User inUser = new User( CreateUserSample.TEST_USERID );
        try
        {
            // Instantiate the AccessMgr implementation.
            AccessMgr accessMgr = AccessMgrFactory.createInstance( TestUtils.getContext() );
            // Calling createSession and not setting any roles on User beforehand will attempt to activate all assigned Roles:
            Session session = createSession( CreateUserSample.TEST_USERID,
                CreateUserSample.TEST_PASSWORD.toCharArray(), accessMgr );
            assertNotNull( session );
            // now, drop roles from User's Session one at a time:
            for ( int i = 1; i < 11; i++ )
            {
                UserRole dropUserRole = new UserRole( inUser.getUserId(), CreateRoleSample.TEST_ROLE_PREFIX + i );
                accessMgr.dropActiveRole( session, dropUserRole );
                LOG.info( szLocation + " userId [" + dropUserRole.getUserId() + "] deactivated role ["
                    + dropUserRole.getName() + "] removed from session" );
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( szLocation + " caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    /**
     * This test will display all of the User Session attributes to the System out of test machine.  It is intended
     * to demonstrate what data is carried within a User's Fortress Session object.
     */
    public static void testDisplayUserSession()
    {
        String szLocation = ".testDisplayUserSession";
        try
        {
            // Instantiate the AccessMgr implementation.
            AccessMgr accessMgr = AccessMgrFactory.createInstance( TestUtils.getContext() );
            // utility function will create an Fortress Session.  The Session contains the user's activated
            // roles along with other related attributes and status information (i.e. password status)
            Session session = createSession( CreateUserSample.TEST_USERID,
                CreateUserSample.TEST_PASSWORD.toCharArray(), accessMgr );
            assertNotNull( session );
            User user = accessMgr.getUser( session );
            assertNotNull( user );
            LOG.info( szLocation );
            LOG.info( "S   UID  [" + session.getUserId() + "]:" );
            LOG.info( "S   IID  [" + session.getInternalUserId() + "]" );
            LOG.info( "S   ERR  [" + session.getErrorId() + "]" );
            LOG.info( "S   WARN [" + session.getWarnings() + "]" );
            LOG.info( "S   MSG  [" + session.getMsg() + "]" );
            LOG.info( "S   EXP  [" + session.getExpirationSeconds() + "]" );
            LOG.info( "S   GRAC [" + session.getGraceLogins() + "]" );
            LOG.info( "S   AUTH [" + session.isAuthenticated() + "]" );
            LOG.info( "S   LAST [" + session.getLastAccess() + "]" );
            LOG.info( "S   SID  [" + session.getSessionId() + "]" );
            LOG.info( "------------------------------------------" );
            LOG.info( "U   UID  [" + user.getUserId() + "]" );
            LOG.info( "U   IID  [" + user.getInternalId() + "]" );
            LOG.info( "U   CN   [" + user.getCn() + "]" );
            LOG.info( "U   DESC [" + user.getDescription() + "]" );
            LOG.info( "U   OU   [" + user.getOu() + "]" );
            LOG.info( "U   SN   [" + user.getSn() + "]" );
            LOG.info( "U   BDTE [" + user.getBeginDate() + "]" );
            LOG.info( "U   EDTE [" + user.getEndDate() + "]" );
            LOG.info( "U   BLDT [" + user.getBeginLockDate() + "]" );
            LOG.info( "U   ELDT [" + user.getEndLockDate() + "]" );
            LOG.info( "U   DMSK [" + user.getDayMask() + "]" );
            LOG.info( "U   TO   [" + user.getTimeout() + "]" );
            LOG.info( "U   REST [" + user.isReset() + "]" );
            if ( user.getProperties() != null && user.getProperties().size() > 0 )
            {
                int ctr = 0;
                for ( Enumeration e = user.getProperties().propertyNames(); e.hasMoreElements(); )
                {
                    String key = ( String ) e.nextElement();
                    String val = user.getProperty( key );
                    LOG.info( "U   PROP[" + ctr++ + "]=" + key + " VAL=" + val );
                }
            }

            List<UserRole> roles = session.getRoles();
            if ( roles != null )
            {
                for ( int i = 0; i < roles.size(); i++ )
                {
                    UserRole ur = roles.get( i );
                    LOG.info( "    USER ROLE[" + i + "]:" );
                    LOG.info( "        role name [" + ur.getName() + "]" );
                    LOG.info( "        begin time [" + ur.getBeginTime() + "]" );
                    LOG.info( "        end time [" + ur.getEndTime() + "]" );
                    LOG.info( "        begin date [" + ur.getBeginDate() + "]" );
                    LOG.info( "        end date [" + ur.getEndDate() + "]" );
                    LOG.info( "        begin lock [" + ur.getBeginLockDate() + "]" );
                    LOG.info( "        end lock [" + ur.getEndLockDate() + "]" );
                    LOG.info( "        day mask [" + ur.getDayMask() + "]" );
                    LOG.info( "        time out [" + ur.getTimeout() + "]" );
                }
            }

            List<UserAdminRole> aRoles = session.getAdminRoles();
            if ( aRoles != null )
            {
                for ( int i = 0; i < aRoles.size(); i++ )
                {
                    UserAdminRole ur = aRoles.get( i );
                    LOG.info( "    USER ADMIN ROLE[" + i + "]:" );
                    LOG.info( "        admin role name [" + ur.getName() + "]" );
                    LOG.info( "        OsU [" + ur.getOsUSet() + "]" );
                    LOG.info( "        OsP [" + ur.getOsPSet() + "]" );
                    LOG.info( "        begin range [" + ur.getBeginRange() + "]" );
                    LOG.info( "        end range [" + ur.getEndRange() + "]" );
                    LOG.info( "        begin time [" + ur.getBeginTime() + "]" );
                    LOG.info( "        end time [" + ur.getEndTime() + "]" );
                    LOG.info( "        begin date [" + ur.getBeginDate() + "]" );
                    LOG.info( "        end date [" + ur.getEndDate() + "]" );
                    LOG.info( "        begin lock [" + ur.getBeginLockDate() + "]" );
                    LOG.info( "        end lock [" + ur.getEndLockDate() + "]" );
                    LOG.info( "        day mask [" + ur.getDayMask() + "]" );
                    LOG.info( "        time out [" + ur.getTimeout() + "]" );
                }
            }

            java.util.Properties jProps = System.getProperties();
            if ( jProps != null && jProps.size() > 0 )
            {
                int ctr = 0;
                for ( Enumeration e = jProps.propertyNames(); e.hasMoreElements(); )
                {
                    String key = ( String ) e.nextElement();
                    String val = jProps.getProperty( key );
                    LOG.info( "J   PROP[" + ctr++ + "]=" + key + " VAL=" + val );
                }
            }
        }
        catch ( SecurityException ex )
        {
            LOG.error( szLocation + " caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
    }


    /**
     * @param userId   String contains case insensitive userId field.
     * @param password String contains case sensitive, clear text password field.
     * @return User RBAC Session that is used for subsequent AccessMgr API calls.
     */
    private static Session createSession( String userId, char[] password, AccessMgr accessMgr )
    {
        String szLocation = ".createSession";
        Session session = null;

        try
        {
            User user = new User( userId, password );
            // These properties will be persisted within User's audit trail in OpenLDAP:
            user.addProperty( "system.user.name", System.getProperty( "user.name" ) );
            //user.addProperty("system.timezone VAL", System.getProperty("user.timezone VAL"));
            user.addProperty( "system.country", System.getProperty( "user.country" ) );

            // utility function will create an Fortress Session.  The Session contains the user's activated
            // roles along with other related attributes and status information (i.e. password status)
            session = accessMgr.createSession( user, false );
            LOG.info( szLocation + " successful" );
        }
        catch ( SecurityException ex )
        {
            LOG.error( szLocation + " caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }

        return session;
    }


    /**
     * Test Utility wraps OpenAcccessManager createSession API.
     *
     * @param userId          String contains case insensitive userId field.
     * @param password        String contains case sensitive, clear text password field.
     * @param activationRoles array of Role names targeted for activation into User's RBAC Session.
     * @return User RBAC Session that is used for subsequent AccessMgr API calls.
     */
    private static Session createSession( String userId, char[] password, String[] activationRoles, AccessMgr accessMgr )
    {
        String szLocation = ".createSession";
        Session session = null;
        try
        {
            User user = new User( userId, password, activationRoles );
            user.addProperty( "system.user.name", System.getProperty( "user.name" ) );
            //user.addProperty("system.timezone VAL", System.getProperty("user.timezone VAL"));
            user.addProperty( "system.country", System.getProperty( "user.country" ) );

            // Create an Fortress Session.  The Session contains the user's activated
            // roles along with other related attributes and status information (i.e. password status)
            session = accessMgr.createSession( user, false );
            LOG.info( szLocation + " with roles successful" );
        }
        catch ( SecurityException ex )
        {
            LOG.error(
                szLocation + " with roles caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(),
                ex );
            fail( ex.getMessage() );
        }
        return session;
    }


    /**
     * The authenticate API is used for use cases where RBAC authorization is not required.  This API will authenticate
     * the User's password and will check password policies but will not activate User's Roles into the return Session.
     *
     * @param userId   String contains case insensitive userId field.
     * @param password String contains case sensitive, clear text password field.
     * @return User Session that has no Roles activated thus will fail checkAccess and sessionPermission calls.
     */
    private static Session authenticate( String userId, char[] password, AccessMgr accessMgr )
    {
        String szLocation = ".authenticate";
        Session session = null;
        try
        {
            // authenticate will check the password but will not activated any roles into Session.
            session = accessMgr.authenticate( userId, password );
            LOG.info( szLocation + " successful" );
        }
        catch ( SecurityException ex )
        {
            LOG.error( szLocation + " caught SecurityException rc=" + ex.getErrorId() + ", msg=" + ex.getMessage(), ex );
            fail( ex.getMessage() );
        }
        return session;
    }
}
