/**
 * OWASP Enterprise Security API (ESAPI)
 * 
 * This file is part of the Open Web Application Security Project (OWASP)
 * Enterprise Security API (ESAPI) project. For details, please see
 * <a href="http://www.owasp.org/index.php/ESAPI">http://www.owasp.org/index.php/ESAPI</a>.
 *
 * Copyright (c) 2007 - The OWASP Foundation
 * 
 * The ESAPI is published by OWASP under the BSD license. You should read and accept the
 * LICENSE before you use, modify, and/or redistribute this software.
 * 
 * @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
 * @created 2007
 */
package org.owasp.esapi.reference;

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

import org.owasp.esapi.ESAPI;
import org.owasp.esapi.AccessController;
import org.owasp.esapi.Authenticator;
import org.owasp.esapi.User;
import org.owasp.esapi.errors.AccessControlException;


/**
 * The Class AccessControllerTest.
 * 
 * @author Jeff Williams (jeff.williams@aspectsecurity.com)
 */
public class AccessControllerTest extends TestCase {

	/**
	 * Instantiates a new access controller test.
	 * 
	 * @param testName
     *            the test name
     * @throws Exception
	 */
	public AccessControllerTest(String testName) throws Exception {
		super(testName);
		
		Authenticator authenticator = ESAPI.authenticator();
		String password = authenticator.generateStrongPassword();

		// create a user with the "user" role for this test
		User alice = authenticator.getUser("testuser1");
		if ( alice == null ) {
			alice = authenticator.createUser( "testuser1", password, password);
		}
		alice.addRole("user");		

		// create a user with the "admin" role for this test
		User bob = authenticator.getUser("testuser2");
		if ( bob == null ) {
			bob = authenticator.createUser( "testuser2", password, password);
		}
		bob.addRole("admin");
		
		// create a user with the "user" and "admin" roles for this test
		User mitch = authenticator.getUser("testuser3");
		if ( mitch == null ) {
			mitch = authenticator.createUser( "testuser3", password, password);
		}
		mitch.addRole("admin");
		mitch.addRole("user");
	}

    /**
     * {@inheritDoc}
     *
     * @throws Exception
     */
	protected void setUp() throws Exception {
	}

    /**
     * {@inheritDoc}
     *
     * @throws Exception
     */
	protected void tearDown() throws Exception {
		// none
	}

	/**
	 * Suite.
	 * 
	 * @return the test
	 */
	public static Test suite() {
		TestSuite suite = new TestSuite(AccessControllerTest.class);
		return suite;
	}

    /**
     *
     */
    public void testMatchRule() {
		ESAPI.authenticator().setCurrentUser(null);
		assertFalse(ESAPI.accessController().isAuthorizedForURL("/nobody"));
	}
	
	/**
	 * Test of isAuthorizedForURL method, of class
	 * org.owasp.esapi.AccessController.
     *
     * @throws Exception
     */
	public void testIsAuthorizedForURL() throws Exception {
		System.out.println("isAuthorizedForURL");
		AccessController instance = ESAPI.accessController();
		Authenticator auth = ESAPI.authenticator();
		
		auth.setCurrentUser( auth.getUser("testuser1") );
		assertFalse(instance.isAuthorizedForURL("/nobody"));
		assertFalse(instance.isAuthorizedForURL("/test/admin"));
		assertTrue(instance.isAuthorizedForURL("/test/user"));
		assertTrue(instance.isAuthorizedForURL("/test/all"));
		assertFalse(instance.isAuthorizedForURL("/test/none"));
		assertTrue(instance.isAuthorizedForURL("/test/none/test.gif"));
		assertFalse(instance.isAuthorizedForURL("/test/none/test.exe"));
		assertTrue(instance.isAuthorizedForURL("/test/none/test.png"));
		assertFalse(instance.isAuthorizedForURL("/test/moderator"));
		assertTrue(instance.isAuthorizedForURL("/test/profile"));
		assertFalse(instance.isAuthorizedForURL("/upload"));

		auth.setCurrentUser( auth.getUser("testuser2") );
		assertFalse(instance.isAuthorizedForURL("/nobody"));
		assertTrue(instance.isAuthorizedForURL("/test/admin"));
		assertFalse(instance.isAuthorizedForURL("/test/user"));
		assertTrue(instance.isAuthorizedForURL("/test/all"));
		assertFalse(instance.isAuthorizedForURL("/test/none"));
		assertTrue(instance.isAuthorizedForURL("/test/none/test.png"));
		assertFalse(instance.isAuthorizedForURL("/test/moderator"));
		assertTrue(instance.isAuthorizedForURL("/test/profile"));
		assertFalse(instance.isAuthorizedForURL("/upload"));
		
		auth.setCurrentUser( auth.getUser("testuser3") );
		assertFalse(instance.isAuthorizedForURL("/nobody"));
		assertTrue(instance.isAuthorizedForURL("/test/admin"));
		assertTrue(instance.isAuthorizedForURL("/test/user"));
		assertTrue(instance.isAuthorizedForURL("/test/all"));
		assertFalse(instance.isAuthorizedForURL("/test/none"));
		assertTrue(instance.isAuthorizedForURL("/test/none/test.png"));
		assertFalse(instance.isAuthorizedForURL("/test/moderator"));
		assertTrue(instance.isAuthorizedForURL("/test/profile"));
		assertFalse(instance.isAuthorizedForURL("/upload"));
		
		try {
			instance.assertAuthorizedForURL("/test/admin");
			instance.assertAuthorizedForURL( "/nobody" );
			fail();
		} catch ( AccessControlException e ) {
			// expected
		}
	}

	/**
	 * Test of isAuthorizedForFunction method, of class
	 * org.owasp.esapi.AccessController.
	 */
	public void testIsAuthorizedForFunction() {
		System.out.println("isAuthorizedForFunction");
		AccessController instance = ESAPI.accessController();
		Authenticator auth = ESAPI.authenticator();
		
		auth.setCurrentUser( auth.getUser("testuser1") );
		assertTrue(instance.isAuthorizedForFunction("/FunctionA"));
		assertFalse(instance.isAuthorizedForFunction("/FunctionAdeny"));
		assertFalse(instance.isAuthorizedForFunction("/FunctionB"));
		assertFalse(instance.isAuthorizedForFunction("/FunctionBdeny"));
		assertTrue(instance.isAuthorizedForFunction("/FunctionC"));
		assertFalse(instance.isAuthorizedForFunction("/FunctionCdeny"));

		auth.setCurrentUser( auth.getUser("testuser2") );
		assertFalse(instance.isAuthorizedForFunction("/FunctionA"));
		assertFalse(instance.isAuthorizedForFunction("/FunctionAdeny"));
		assertTrue(instance.isAuthorizedForFunction("/FunctionB"));
		assertFalse(instance.isAuthorizedForFunction("/FunctionBdeny"));
		assertTrue(instance.isAuthorizedForFunction("/FunctionD"));
		assertFalse(instance.isAuthorizedForFunction("/FunctionDdeny"));

		auth.setCurrentUser( auth.getUser("testuser3") );
		assertTrue(instance.isAuthorizedForFunction("/FunctionA"));
		assertFalse(instance.isAuthorizedForFunction("/FunctionAdeny"));
		assertTrue(instance.isAuthorizedForFunction("/FunctionB"));
		assertFalse(instance.isAuthorizedForFunction("/FunctionBdeny"));
		assertTrue(instance.isAuthorizedForFunction("/FunctionC"));
		assertFalse(instance.isAuthorizedForFunction("/FunctionCdeny"));

		try {
			instance.assertAuthorizedForFunction("/FunctionA");
			instance.assertAuthorizedForFunction( "/FunctionDdeny" );
			fail();
		} catch ( AccessControlException e ) {
			// expected
		}
	}

	/**
	 * Test of isAuthorizedForData method, of class
	 * org.owasp.esapi.AccessController.
	 */
	public void testIsAuthorizedForData() {
		System.out.println("isAuthorizedForData");
		AccessController instance = ESAPI.accessController();
		Authenticator auth = ESAPI.authenticator();
		
		Class adminR = null;
		Class adminRW = null;
		Class userW = null;
		Class userRW = null;
		Class anyR = null;
		Class userAdminR = null;
		Class userAdminRW = null;
		Class undefined = null;
		
		try{
			adminR = Class.forName("java.util.ArrayList");
			adminRW = Class.forName("java.lang.Math");
			userW = Class.forName("java.util.Date");
			userRW = Class.forName("java.lang.String");
			anyR = Class.forName("java.io.BufferedReader");
			userAdminR = Class.forName("java.util.Random");
			userAdminRW = Class.forName("javax.crypto.Cipher");
			undefined = Class.forName("java.io.FileWriter");
			
		}catch(ClassNotFoundException cnf){
			System.out.println("CLASS NOT FOUND.");
			cnf.printStackTrace();
		}
		//test User
		auth.setCurrentUser( auth.getUser("testuser1") );
		assertTrue(instance.isAuthorizedForData("read", userRW));
		assertFalse(instance.isAuthorizedForData("read", undefined));
		assertFalse(instance.isAuthorizedForData("write", undefined));
		assertFalse(instance.isAuthorizedForData("read", userW));
		assertFalse(instance.isAuthorizedForData("read", adminRW));
		assertTrue(instance.isAuthorizedForData("write", userRW));
		assertTrue(instance.isAuthorizedForData("write", userW));
		assertFalse(instance.isAuthorizedForData("write", anyR));
		assertTrue(instance.isAuthorizedForData("read", anyR));
		assertTrue(instance.isAuthorizedForData("read", userAdminR));
		assertTrue(instance.isAuthorizedForData("write", userAdminRW));
		
		//test Admin
		auth.setCurrentUser( auth.getUser("testuser2") );
		assertTrue(instance.isAuthorizedForData("read", adminRW));
		assertFalse(instance.isAuthorizedForData("read", undefined));
		assertFalse(instance.isAuthorizedForData("write", undefined));
		assertFalse(instance.isAuthorizedForData("read", userRW));
		assertTrue(instance.isAuthorizedForData("write", adminRW));
		assertFalse(instance.isAuthorizedForData("write", anyR));
		assertTrue(instance.isAuthorizedForData("read", anyR));
		assertTrue(instance.isAuthorizedForData("read", userAdminR));
		assertTrue(instance.isAuthorizedForData("write", userAdminRW));
		
		//test User/Admin
		auth.setCurrentUser( auth.getUser("testuser3") );
		assertTrue(instance.isAuthorizedForData("read", userRW));
		assertFalse(instance.isAuthorizedForData("read", undefined));
		assertFalse(instance.isAuthorizedForData("write", undefined));
		assertFalse(instance.isAuthorizedForData("read", userW));
		assertTrue(instance.isAuthorizedForData("read", adminR));
		assertTrue(instance.isAuthorizedForData("write", userRW));
		assertTrue(instance.isAuthorizedForData("write", userW));
		assertFalse(instance.isAuthorizedForData("write", anyR));
		assertTrue(instance.isAuthorizedForData("read", anyR));
		assertTrue(instance.isAuthorizedForData("read", userAdminR));
		assertTrue(instance.isAuthorizedForData("write", userAdminRW));
		try {
			instance.assertAuthorizedForData("read", userRW);
			instance.assertAuthorizedForData( "write", adminR );
			fail();
		} catch ( AccessControlException e ) {
			// expected
		}
		
	}

	/**
	 * Test of isAuthorizedForFile method, of class
	 * org.owasp.esapi.AccessController.
	 */
	public void testIsAuthorizedForFile() {
		System.out.println("isAuthorizedForFile");
		AccessController instance = ESAPI.accessController();
		Authenticator auth = ESAPI.authenticator();
		
		auth.setCurrentUser( auth.getUser("testuser1") );
		assertTrue(instance.isAuthorizedForFile("/Dir/File1"));
		assertFalse(instance.isAuthorizedForFile("/Dir/File2"));
		assertTrue(instance.isAuthorizedForFile("/Dir/File3"));
		assertFalse(instance.isAuthorizedForFile("/Dir/ridiculous"));

		auth.setCurrentUser( auth.getUser("testuser2") );
		assertFalse(instance.isAuthorizedForFile("/Dir/File1"));
		assertTrue(instance.isAuthorizedForFile("/Dir/File2"));
		assertTrue(instance.isAuthorizedForFile("/Dir/File4"));
		assertFalse(instance.isAuthorizedForFile("/Dir/ridiculous"));

		auth.setCurrentUser( auth.getUser("testuser3") );
		assertTrue(instance.isAuthorizedForFile("/Dir/File1"));
		assertTrue(instance.isAuthorizedForFile("/Dir/File2"));
		assertFalse(instance.isAuthorizedForFile("/Dir/File5"));
		assertFalse(instance.isAuthorizedForFile("/Dir/ridiculous"));

		try {
			instance.assertAuthorizedForFile("/Dir/File1");
			instance.assertAuthorizedForFile( "/Dir/File6" );
			fail();
		} catch ( AccessControlException e ) {
			// expected
		}
	}

	/**
	 * Test of isAuthorizedForService method, of class
	 * org.owasp.esapi.AccessController.
	 */
	public void testIsAuthorizedForService() {
		System.out.println("isAuthorizedForService");
		AccessController instance = ESAPI.accessController();
		Authenticator auth = ESAPI.authenticator();
		
		auth.setCurrentUser( auth.getUser("testuser1") );
		assertTrue(instance.isAuthorizedForService("/services/ServiceA"));
		assertFalse(instance.isAuthorizedForService("/services/ServiceB"));
		assertTrue(instance.isAuthorizedForService("/services/ServiceC"));
		
		assertFalse(instance.isAuthorizedForService("/test/ridiculous"));

		auth.setCurrentUser( auth.getUser("testuser2") );
		assertFalse(instance.isAuthorizedForService("/services/ServiceA"));
		assertTrue(instance.isAuthorizedForService("/services/ServiceB"));
		assertFalse(instance.isAuthorizedForService("/services/ServiceF"));
		assertFalse(instance.isAuthorizedForService("/test/ridiculous"));

		auth.setCurrentUser( auth.getUser("testuser3") );
		assertTrue(instance.isAuthorizedForService("/services/ServiceA"));
		assertTrue(instance.isAuthorizedForService("/services/ServiceB"));
		assertFalse(instance.isAuthorizedForService("/services/ServiceE"));
		assertFalse(instance.isAuthorizedForService("/test/ridiculous"));

		try {
			instance.assertAuthorizedForService("/services/ServiceD");
			instance.assertAuthorizedForService( "/test/ridiculous" );
			fail();
		} catch ( AccessControlException e ) {
			// expected
		}
	}

}
