diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/CompositPolicyDecision.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/CompositPolicyDecision.java new file mode 100644 index 000000000..c0e9b1045 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/CompositPolicyDecision.java @@ -0,0 +1,21 @@ +package edu.cornell.mannlib.vitro.webapp.auth.policy; + +import java.util.List; + +import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization; +import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision; + +/** + * Policy decision that is made from some analysis of a set of decisions. + * @author bdc34 + * + */ +public class CompositPolicyDecision extends BasicPolicyDecision implements PolicyDecision { + List subDecisions; + + public CompositPolicyDecision(Authorization auth, String message, List subDecisions){ + super( auth, message); + this.subDecisions = subDecisions; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyList.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyList.java index d05f04bab..ca6e047ff 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyList.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyList.java @@ -4,6 +4,8 @@ package edu.cornell.mannlib.vitro.webapp.auth.policy; import java.util.ArrayList; import java.util.Collection; +import java.util.LinkedList; +import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -12,6 +14,8 @@ import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle; import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization; import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision; import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AllRequestedAction; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AnyRequestedAction; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction; /** @@ -38,8 +42,68 @@ public class PolicyList extends ArrayList implements PolicyIface{ @Override public PolicyDecision isAuthorized(IdentifierBundle whoToAuth, RequestedAction whatToAuth) { - PolicyDecision pd = null; - for(PolicyIface policy : this){ + + if( whatToAuth instanceof AllRequestedAction ){ + return doAllAction( whoToAuth, ((AllRequestedAction)whatToAuth)); + }else if ( whatToAuth instanceof AnyRequestedAction ){ + return doAnyAction(whoToAuth, ((AnyRequestedAction)whatToAuth)); + }else{ + return checkAgainstPolicys( whoToAuth , whatToAuth); + } + } + + /** + * Checks that at least one of the subRequestedActions are authorized. + */ + private PolicyDecision doAnyAction(IdentifierBundle whoToAuth, + AnyRequestedAction whatToAuth) { + boolean anyAuth = false; + List subPd = new LinkedList(); + for( RequestedAction subAct : whatToAuth.getRequestedActions()){ + PolicyDecision pd = isAuthorized(whoToAuth,subAct); + subPd.add(pd); + if( pd.getAuthorized() == Authorization.AUTHORIZED){ + anyAuth = true; + break; + } + } + if( anyAuth ) + return new CompositPolicyDecision( Authorization.AUTHORIZED, + "Some sub-RequestedAction authorized", subPd); + else + return new CompositPolicyDecision( Authorization.UNAUTHORIZED, + "None of the sub-RequestedAction were authorized", subPd); + } + + /** + * Checks that all the subRequestedActions are authorized. + */ + private PolicyDecision doAllAction(IdentifierBundle whoToAuth, AllRequestedAction whatToAuth) { + boolean allAuth = true; + + List subPd = new LinkedList(); + for( RequestedAction subAct : whatToAuth.getRequestedActions()){ + PolicyDecision pd = isAuthorized( whoToAuth, subAct) ; + subPd.add( pd ); + if( pd.getAuthorized() != Authorization.AUTHORIZED ){ + allAuth = false; + break; + } + } + + if( allAuth ) + return new CompositPolicyDecision( + Authorization.AUTHORIZED, + "All sub-RequestedActions authorized.", subPd ); + else + return new CompositPolicyDecision( + Authorization.UNAUTHORIZED, + "Not all sub-RequestedActions authorized.", subPd ); + } + + protected PolicyDecision checkAgainstPolicys( IdentifierBundle whoToAuth, RequestedAction whatToAuth){ + PolicyDecision pd = null; + for(PolicyIface policy : this){ try{ pd = policy.isAuthorized(whoToAuth, whatToAuth); if( pd != null ){ @@ -47,8 +111,8 @@ public class PolicyList extends ArrayList implements PolicyIface{ break; if( pd.getAuthorized() == Authorization.UNAUTHORIZED ) break; - // if( pd.getAuthorized() == Authorization.INCONCLUSIVE ) - // continue; + if( pd.getAuthorized() == Authorization.INCONCLUSIVE ) + continue; } else{ log.debug("policy " + policy.toString() + " returned a null PolicyDecision"); } @@ -58,6 +122,6 @@ public class PolicyList extends ArrayList implements PolicyIface{ } log.debug("decision " + pd + " for " + whatToAuth); return pd; - } + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/ifaces/PolicyDecision.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/ifaces/PolicyDecision.java index f5e942240..6cd869cca 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/ifaces/PolicyDecision.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/ifaces/PolicyDecision.java @@ -2,6 +2,11 @@ package edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces; +/** + * Object to represent a decision from a policy. The intent is + * that the message would be presented to users to indicate why + * they are not authorized for some action. + */ public interface PolicyDecision { public Authorization getAuthorized(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/Actions.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/Actions.java index 03e3a4573..04f79e966 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/Actions.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/Actions.java @@ -21,12 +21,16 @@ import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction; /** - * An immutable list of OR and AND relationships for the required - * authorizations. A group of AND relationships is a "clause", and the list of - * clauses are in an OR relationship. + * A list of RequiredAction objects. * - * Authorization is successful if ALL of the actions in ANY of the clauses are + * Authorization is considered successful if ALL of the actions are * authorized, or if there are NO clauses. + * + * A previous version of this class had a capability to do OR clauses but + * this feature was unused and hindered composition of Actions + * objects. The ability to do an OR has been moved to AnyRequestedAction + * and AllRequestedAction. + * */ public class Actions { private static final Log log = LogFactory.getLog(Actions.class); @@ -40,139 +44,193 @@ public class Actions { } /** - * This is a list of clauses that get ORed together. - * If all of the RequestedAction objects from any of the + * This is a set of RequestedActions that get ANDed together. + * + * If all of the RequestedAction objects from the * Sets are authorized, then the Actions object should * be considered authorized. */ - private List> clauseList; + private Set requestedActions; public Actions(){ - clauseList= new ArrayList>(); + requestedActions= Collections.emptySet(); } + /** + * AND together all the RequestedAction from all the actions. + */ + public Actions(Actions... actions){ + Set newActs = new HashSet(); + + for( Actions actionToAnd : actions){ + if( actionToAnd != null && actionToAnd.requestedActions != null ){ + newActs.addAll( actionToAnd.requestedActions ); + } + } + + this.requestedActions = Collections.unmodifiableSet( newActs ); + } + public Actions(RequestedAction... actions) { this(Arrays.asList(actions)); } - - public Actions(Actions... actions){ - Set accumActs = new HashSet(); - for( Actions actionToAnd : actions){ - if( actionToAnd != null ){ - for( Set ras : actionToAnd.clauseList){ - accumActs.addAll( ras ); - } - } - } - clauseList= new ArrayList>(); - clauseList.add( accumActs ); - } - + public Actions(Collection actions) { - this(Collections.> emptyList(), actions); + this(Collections. emptySet(), actions); } - - private Actions(List> oldList, - Collection newActions) { - List> newList = new ArrayList>(); - newList.addAll(oldList); - - Set newActionSet = new HashSet( - newActions); - if (!newActionSet.isEmpty()) { - newList.add(Collections.unmodifiableSet(newActionSet)); + private Actions(Set oldList, + Collection newActions) { + + Set newActs = new HashSet(); + + if( oldList != null ){ + newActs.addAll(oldList); } - this.clauseList = Collections.unmodifiableList(newList); + + if ( newActions != null ) { + newActs.addAll( newActions ); + } + + this.requestedActions = Collections.unmodifiableSet(newActs); } + /** require all RequestedActions on this and the ones in newActions to authorize.*/ public Actions and(RequestedAction... newActions){ return and(Arrays.asList( newActions)); } + /** require all RequestedActions on this and the ones in newActions to authorize.*/ public Actions and(Collection newActions){ - return new Actions( this.clauseList, newActions); + if( newActions == null || newActions.size() == 0) + return this; + else + return new Actions( this.requestedActions, newActions); + } + + /** require all RequestedActions on this and the ones in newActions to authorize.*/ + public Actions and(Actions newActions){ + return new Actions( this.requestedActions, newActions.requestedActions); } - public void and( Actions otherAct ) throws Exception{ - andWithAction(otherAct); - } - public Actions or(RequestedAction... newActions) { return or(Arrays.asList(newActions)); } - public Actions or(Collection newActions) { - return new Actions(this.clauseList, newActions); + /** + * OR together this.requestedActions and newActions. + */ + public Actions or(Collection newActions) { + RequestedAction acts; + + if( newActions == null || newActions.size() == 0 ){ + return this; + } + + int thisActionCount = this.requestedActions.size(); + int newActionCount = newActions.size(); + + /* This minimizes the number of extra RequestedActions + * that get created when there is only one in this + * or newActions.*/ + if( thisActionCount == 1 && newActionCount == 1 ){ + return new Actions( + new AnyRequestedAction( + this.requestedActions.iterator().next(), + newActions.iterator().next() )); + } + + if( thisActionCount == 1 && newActionCount > 1 ){ + return new Actions( + new AnyRequestedAction( + this.requestedActions.iterator().next(), + new AllRequestedAction( newActions ))); + } + + if( thisActionCount > 1 && newActionCount == 1){ + return new Actions( new AnyRequestedAction( + new AllRequestedAction( this.requestedActions), + newActions.iterator().next())); + } + + if( thisActionCount > 1 && newActionCount > 1 ){ + return new Actions( + new AnyRequestedAction( + new AllRequestedAction( this.requestedActions ), + new AllRequestedAction( newActions ))); + } + //should never be reached. + log.error("Could not properly create disjunction"); + return null; } public boolean isEmpty() { - for (Set clause : clauseList) { - if (!clause.isEmpty()) { - return false; - } - } - return true; + return this.requestedActions.isEmpty(); } - /** No clauses means everything is authorized */ + + /** + * Are the RequestedAction objects for this Actions authorized + * with the ids and policy? + */ public boolean isAuthorized(PolicyIface policy, IdentifierBundle ids) { - if (clauseList.isEmpty()) { + /* No clauses means everything is authorized */ + if (requestedActions.isEmpty()) { log.debug("Empty Actions is authorized"); return true; } - return isAuthorizedForClauseList(policy, ids); - } - - /** Any entire clause is good enough. */ - private boolean isAuthorizedForClauseList(PolicyIface policy, - IdentifierBundle ids) { - for (Set clause : clauseList) { - if (isAuthorizedForClause(policy, ids, clause)) { - return true; - } + + /* Are all the RequestedAction object authorized? */ + List decisions = new ArrayList(); + for (RequestedAction action : requestedActions) { + PolicyDecision decision = policy.isAuthorized(ids, action); + log.debug("decision for '" + action.getClass().getSimpleName() + "' was: " + + decision); + decisions.add( decision ); } - return false; + return areAllAuthorized( decisions ); } - /** All actions in a clause must be authorized. */ - private static boolean isAuthorizedForClause(PolicyIface policy, - IdentifierBundle ids, Set clause) { - for (RequestedAction action : clause) { - if (!isAuthorizedForAction(policy, ids, action)) { - log.debug("not authorized"); - return false; - } - } - return true; - } - - /** Is this action authorized? */ - private static boolean isAuthorizedForAction(PolicyIface policy, - IdentifierBundle ids, RequestedAction action) { - PolicyDecision decision = policy.isAuthorized(ids, action); - log.debug("decision for '" + action.getClass().getSimpleName() + "' was: " - + decision); - return (decision != null) - && (decision.getAuthorized() == Authorization.AUTHORIZED); + private boolean areAllAuthorized( List decisions ){ + for( PolicyDecision dec : decisions){ + if( dec == null || dec.getAuthorized() != Authorization.AUTHORIZED ){ + return false; + } + } + return true; } + +// /** All actions in a clause must be authorized. */ +// private static boolean isAuthorizedForClause(PolicyIface policy, +// IdentifierBundle ids, Set clause) { +// for (RequestedAction action : clause) { +// if (!isAuthorizedForAction(policy, ids, action)) { +// log.debug("not authorized"); +// return false; +// } +// } +// return true; +// } +// +// /** Is this action authorized? */ +// private static boolean isAuthorizedForAction(PolicyIface policy, +// IdentifierBundle ids, RequestedAction action) { +// PolicyDecision decision = policy.isAuthorized(ids, action); +// log.debug("decision for '" + action.getClass().getSimpleName() + "' was: " +// + decision); +// return (decision != null) +// && (decision.getAuthorized() == Authorization.AUTHORIZED); +// } @Override public String toString() { StringBuffer sb = new StringBuffer("Actions["); - for (Iterator> cit = clauseList.iterator(); cit.hasNext();) { - Set clause = cit.next(); - sb.append("("); - for (Iterator it = clause.iterator(); it.hasNext();) { - RequestedAction action = it.next(); - sb.append(action.getClass().getSimpleName()); - if (it.hasNext()) { - sb.append(", "); - } - } - sb.append(")"); - if (cit.hasNext()) { - sb.append(" or "); + Iterator it = this.requestedActions.iterator(); + while( it.hasNext() ){ + RequestedAction act = it.next(); + sb.append( act.toString() ); + if (it.hasNext()) { + sb.append(", "); } } sb.append("]"); @@ -189,37 +247,37 @@ public class Actions { * * @throws Exception when multiple disjoint clauses are present on both Actions. */ - private void andWithAction( Actions otherAct ) throws Exception{ - Set singleClauseToAnd; - List> clauses; - - if( otherAct.singleAndClause() ){ - clauses = this.clauseList; - singleClauseToAnd = otherAct.clauseList.get(0); - }else if( this.singleAndClause() ){ - clauses = new ArrayList>( otherAct.clauseList ); - singleClauseToAnd = this.clauseList.get(0); - }else{ - //both have multiple ORed clauses, give up - throw new Exception("ANDing with an Action with multiple disjoint clauses is not supported."); - } - - // - for( Set clause : clauses){ - clause.addAll( singleClauseToAnd ); - } - this.clauseList = clauses; - } + //private void andWithAction( Actions otherAct ) throws Exception{ +// Set singleClauseToAnd; +// List> clauses; +// +// if( otherAct.singleAndClause() ){ +// clauses = this.requestedActions; +// singleClauseToAnd = otherAct.requestedActions.get(0); +// }else if( this.singleAndClause() ){ +// clauses = new ArrayList>( otherAct.requestedActions ); +// singleClauseToAnd = this.requestedActions.get(0); +// }else{ +// //both have multiple ORed clauses, give up +// throw new Exception("ANDing with an Action with multiple disjoint clauses is not supported."); +// } +// +// // +// for( Set clause : clauses){ +// clause.addAll( singleClauseToAnd ); +// } +// this.requestedActions = clauses; + //} - private boolean singleAndClause(){ - return clauseList.size() == 1; - } +// private boolean singleAndClause(){ +// return requestedActions.size() == 1; +// } - /** - * Nobody knows about this action class, so only the root user should be - * authorized for it. - */ - private static class UnauthorizedAction extends RequestedAction { - // no members - } +// /** +// * Nobody knows about this action class, so only the root user should be +// * authorized for it. +// */ +// private static class UnauthorizedAction extends RequestedAction { +// // no members +// } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/AllRequestedAction.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/AllRequestedAction.java new file mode 100644 index 000000000..9863ca81d --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/AllRequestedAction.java @@ -0,0 +1,26 @@ +package edu.cornell.mannlib.vitro.webapp.auth.requestedAction; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction; + +/** + * This action should be authorized if all of its subActions are authorized. + * @author bdc34 + */ +public class AllRequestedAction extends RequestedAction{ + private final Collection subActions ; + + public AllRequestedAction(RequestedAction... actions ){ + this( Arrays.asList( actions )); + } + public AllRequestedAction(Collection subActions){ + this.subActions = Collections.unmodifiableCollection( subActions ); + } + + public Collection getRequestedActions(){ + return subActions; + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/AnyRequestedAction.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/AnyRequestedAction.java new file mode 100644 index 000000000..6b00dfa4c --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/AnyRequestedAction.java @@ -0,0 +1,25 @@ +package edu.cornell.mannlib.vitro.webapp.auth.requestedAction; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction; + +public class AnyRequestedAction extends RequestedAction { + private final Collection subActions ; + + public AnyRequestedAction(RequestedAction... acts){ + this( Arrays.asList( acts) ); + } + + public AnyRequestedAction(Collection subActions){ + this.subActions = Collections.unmodifiableCollection( subActions ); + } + + public Collection getRequestedActions(){ + return subActions; + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/AuthorizedAction.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/AuthorizedAction.java new file mode 100644 index 000000000..c8b9acfb7 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/AuthorizedAction.java @@ -0,0 +1,11 @@ +package edu.cornell.mannlib.vitro.webapp.auth.requestedAction; + +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction; + +/** + * Action that should always be authorized. Mainly for testing. + * @author bdc34 + */ +public class AuthorizedAction extends RequestedAction{ + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/UnauthorizedAction.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/UnauthorizedAction.java new file mode 100644 index 000000000..7f5a220d4 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/requestedAction/UnauthorizedAction.java @@ -0,0 +1,11 @@ +package edu.cornell.mannlib.vitro.webapp.auth.requestedAction; + +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction; + +/** + * Action that is always unauthorized. Mainly for testing. + * @author bdc34 + */ +public class UnauthorizedAction extends RequestedAction{ + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java index 45dc6cf3f..d082690f4 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/PageController.java @@ -100,12 +100,12 @@ public class PageController extends FreemarkerHttpServlet{ for( DataGetter dg : dgList){ if( dg instanceof RequiresActions ){ RequiresActions ra = (RequiresActions) dg; - Actions acts = ra.requiredActions(vreq); - if( acts != null ){ + Actions newActions = ra.requiredActions(vreq); + if( newActions != null ){ if( dgActs != null ){ - dgActs.and( acts ); + dgActs = dgActs.and( newActions ); }else{ - dgActs = acts; + dgActs = newActions; } } } diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyListTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyListTest.java new file mode 100644 index 000000000..855e368ad --- /dev/null +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyListTest.java @@ -0,0 +1,154 @@ +package edu.cornell.mannlib.vitro.webapp.auth.policy; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.Assert; + +import org.junit.Test; + +import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle; +import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization; +import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision; +import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AllRequestedAction; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AnyRequestedAction; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AuthorizedAction; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.UnauthorizedAction; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction; + +public class PolicyListTest { + + @Test + public void basicPolicyListTest() { + + List polis = new ArrayList(); + polis.add( new SimplePolicy() ); + PolicyIface policy = new PolicyList( polis ); + PolicyDecision decision = policy.isAuthorized(null, new UnauthorizedAction()); + Assert.assertEquals(Authorization.UNAUTHORIZED, decision.getAuthorized() ); + + decision = policy.isAuthorized(null, new AuthorizedAction()); + Assert.assertEquals(Authorization.AUTHORIZED, decision.getAuthorized() ); + } + + /** + * Tests the handling of the AnyRequestedAction by the PolicyList. + */ + @Test + public void anyActionTest(){ + List polis = new ArrayList(); + polis.add( new SimplePolicy() ); + PolicyIface policy = new PolicyList( polis ); + + AnyRequestedAction act = new AnyRequestedAction( new UnauthorizedAction() ); + PolicyDecision decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.UNAUTHORIZED, decision.getAuthorized() ); + + act = new AnyRequestedAction( new UnauthorizedAction() , new UnauthorizedAction()); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.UNAUTHORIZED, decision.getAuthorized() ); + + act = new AnyRequestedAction( new UnauthorizedAction(),new UnauthorizedAction(),new UnauthorizedAction()); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.UNAUTHORIZED, decision.getAuthorized() ); + + act = new AnyRequestedAction( new AuthorizedAction() ); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.AUTHORIZED, decision.getAuthorized() ); + + act = new AnyRequestedAction( new AuthorizedAction(),new UnauthorizedAction() ); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.AUTHORIZED, decision.getAuthorized() ); + + act = new AnyRequestedAction( new UnauthorizedAction(),new AuthorizedAction() ); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.AUTHORIZED, decision.getAuthorized() ); + + act = new AnyRequestedAction( new UnauthorizedAction(),new UnauthorizedAction(),new AuthorizedAction()); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.AUTHORIZED, decision.getAuthorized() ); + + act = new AnyRequestedAction( new UnauthorizedAction(),new AuthorizedAction(),new AuthorizedAction()); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.AUTHORIZED, decision.getAuthorized() ); + + act = new AnyRequestedAction( new AuthorizedAction(),new AuthorizedAction(),new AuthorizedAction()); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.AUTHORIZED, decision.getAuthorized() ); + } + + /** + * Tests the handling of the AllRequestedAction by the PolicyList. + */ + @Test + public void andActionTest(){ + List polis = new ArrayList(); + polis.add( new SimplePolicy() ); + PolicyIface policy = new PolicyList( polis ); + + AllRequestedAction act = new AllRequestedAction( new UnauthorizedAction(), new UnauthorizedAction(), new UnauthorizedAction()); + PolicyDecision decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.UNAUTHORIZED, decision.getAuthorized() ); + + act = new AllRequestedAction( new UnauthorizedAction() ); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.UNAUTHORIZED, decision.getAuthorized() ); + + act = new AllRequestedAction( new UnauthorizedAction() , new AuthorizedAction() ); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.UNAUTHORIZED, decision.getAuthorized() ); + + act = new AllRequestedAction( new AuthorizedAction() , new UnauthorizedAction() ); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.UNAUTHORIZED, decision.getAuthorized() ); + + act = new AllRequestedAction( new AuthorizedAction() , new AuthorizedAction() ,new UnauthorizedAction() ); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.UNAUTHORIZED, decision.getAuthorized() ); + + act = new AllRequestedAction( new AuthorizedAction() ); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.AUTHORIZED, decision.getAuthorized() ); + + act = new AllRequestedAction( new AuthorizedAction() , new AuthorizedAction(), new AuthorizedAction() ); + decision = policy.isAuthorized(null, act); + Assert.assertNotNull( decision ); + Assert.assertEquals(Authorization.AUTHORIZED, decision.getAuthorized() ); + } + + + /** + * policy that only responds to Unauthorized and Authorized actions. + */ + public class SimplePolicy implements PolicyIface { + + @Override + public PolicyDecision isAuthorized(IdentifierBundle whoToAuth, + RequestedAction whatToAuth) { + if( whatToAuth instanceof UnauthorizedAction ) + return new BasicPolicyDecision( Authorization.UNAUTHORIZED, "SimplePolicy unauthorized"); + if( whatToAuth instanceof AuthorizedAction ) + return new BasicPolicyDecision( Authorization.AUTHORIZED, "SimplePolicy authorized"); + else + return new BasicPolicyDecision(Authorization.INCONCLUSIVE, "SimplePolicy INCONCLUSIVE"); + } + + + } +}