diff --git a/core/src/test/java/org/acegisecurity/vote/DenyVoter.java b/core/src/test/java/org/acegisecurity/vote/DenyVoter.java new file mode 100644 index 0000000000..bc79d41d92 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/vote/DenyVoter.java @@ -0,0 +1,67 @@ +/* Copyright 2004 Acegi Technology Pty Limited + * + * 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 net.sf.acegisecurity.vote; + +import net.sf.acegisecurity.Authentication; +import net.sf.acegisecurity.ConfigAttribute; +import net.sf.acegisecurity.ConfigAttributeDefinition; + +import org.aopalliance.intercept.MethodInvocation; + +import java.util.Iterator; + + +/** + * Implementation of an {@link AccessDecisionVoter} for unit testing. + * + *
+ * If the {@link ConfigAttribute#getAttribute()} has a value of
+ * DENY_FOR_SURE, the voter will vote to deny access.
+ *
+ * All comparisons are case sensitive. + *
+ * + * @author Ben Alex + * @version $Id$ + */ +public class DenyVoter implements AccessDecisionVoter { + //~ Methods ================================================================ + + public boolean supports(ConfigAttribute attribute) { + if ("DENY_FOR_SURE".equals(attribute.getAttribute())) { + return true; + } else { + return false; + } + } + + public int vote(Authentication authentication, MethodInvocation invocation, + ConfigAttributeDefinition config) { + Iterator iter = config.getConfigAttributes(); + + while (iter.hasNext()) { + ConfigAttribute attribute = (ConfigAttribute) iter.next(); + + if (this.supports(attribute)) { + return ACCESS_DENIED; + } + } + + return ACCESS_ABSTAIN; + } +} diff --git a/core/src/test/java/org/acegisecurity/vote/VoterManagerTests.java b/core/src/test/java/org/acegisecurity/vote/VoterManagerTests.java index a79f6585f2..e1206cb946 100644 --- a/core/src/test/java/org/acegisecurity/vote/VoterManagerTests.java +++ b/core/src/test/java/org/acegisecurity/vote/VoterManagerTests.java @@ -27,6 +27,9 @@ import net.sf.acegisecurity.providers.TestingAuthenticationToken; import org.springframework.context.support.ClassPathXmlApplicationContext; +import java.util.List; +import java.util.Vector; + /** * Tests voter decision managers. @@ -61,8 +64,54 @@ public class VoterManagerTests extends TestCase { junit.textui.TestRunner.run(VoterManagerTests.class); } + public void testAbstractAccessDecisionManagerSetter() + throws Exception { + AffirmativeBased affirmative = new AffirmativeBased(); + affirmative.setAllowIfAllAbstainDecisions(false); + assertTrue(!affirmative.isAllowIfAllAbstainDecisions()); + affirmative.setAllowIfAllAbstainDecisions(true); + assertTrue(affirmative.isAllowIfAllAbstainDecisions()); + } + + public void testAbstractAccessDecisionManagerVoterListHandling() + throws Exception { + XVoter x = new XVoter(); + List xVoterList = new Vector(); + xVoterList.add(x); + + AffirmativeBased affirmative = new AffirmativeBased(); + affirmative.setDecisionVoters(xVoterList); + + try { + affirmative.setDecisionVoters(null); + fail("Should have thrown IllegalArgumentException as list null"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + + List sampleList = new Vector(); + + try { + affirmative.setDecisionVoters(sampleList); + fail("Should have thrown IllegalArgumentException as list empty"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + + sampleList.add(x); // valid (is AccessDecisionVoter) + sampleList.add("Hello world"); // invalid (not AccessDecisionVoter) + + try { + affirmative.setDecisionVoters(sampleList); + fail( + "Should have thrown IllegalArgumentException as list has invalid entries"); + } catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + public void testAffirmative() throws Exception { - AccessDecisionManager mgr = (AccessDecisionManager) ctx.getBean( + AffirmativeBased mgr = (AffirmativeBased) ctx.getBean( "affirmativeBased"); ConfigAttributeDefinition config; TestingAuthenticationToken auth; @@ -71,6 +120,24 @@ public class VoterManagerTests extends TestCase { new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_1"), new GrantedAuthorityImpl( "ROLE_2"), new GrantedAuthorityImpl("ROLE_MAGIC")}); + // Check if we'd be given access, even with a definite deny vote + config = new ConfigAttributeDefinition(); + config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant + config.addConfigAttribute(new SecurityConfig("DENY_FOR_SURE")); // deny + mgr.decide(auth, null, config); + assertTrue(true); + + // Check if we'd be denied access, with only one definite deny vote + config = new ConfigAttributeDefinition(); + config.addConfigAttribute(new SecurityConfig("DENY_FOR_SURE")); // deny + + try { + mgr.decide(auth, null, config); + fail("Should have thrown AccessDeniedException"); + } catch (AccessDeniedException expected) { + assertTrue(true); + } + // Check if we'd get access if ROLE_2 was all that is acceptable config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant @@ -132,11 +199,26 @@ public class VoterManagerTests extends TestCase { } catch (AccessDeniedException expected) { assertTrue(true); } + + // Check if we'd be denied access if all abstained + config = new ConfigAttributeDefinition(); + config.addConfigAttribute(new SecurityConfig("NONE_WILL_VOTE")); // abstain + + try { + mgr.decide(auth, null, config); + fail("Should have thrown AccessDeniedException"); + } catch (AccessDeniedException expected) { + assertTrue(true); + } + + // Now check it works given we approve access if all abstain + mgr.setAllowIfAllAbstainDecisions(true); + mgr.decide(auth, null, config); + assertTrue(true); } public void testConsensus() throws Exception { - AccessDecisionManager mgr = (AccessDecisionManager) ctx.getBean( - "consensusBased"); + ConsensusBased mgr = (ConsensusBased) ctx.getBean("consensusBased"); ConfigAttributeDefinition config; TestingAuthenticationToken auth; @@ -144,6 +226,24 @@ public class VoterManagerTests extends TestCase { new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_1"), new GrantedAuthorityImpl( "ROLE_2"), new GrantedAuthorityImpl("ROLE_MAGIC")}); + // Check if we'd be given access, even with a definite deny vote + config = new ConfigAttributeDefinition(); + config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant + config.addConfigAttribute(new SecurityConfig("DENY_FOR_SURE")); // deny + mgr.decide(auth, null, config); + assertTrue(true); + + // Check if we'd be denied access, with only one definite deny vote + config = new ConfigAttributeDefinition(); + config.addConfigAttribute(new SecurityConfig("DENY_FOR_SURE")); // deny + + try { + mgr.decide(auth, null, config); + fail("Should have thrown AccessDeniedException"); + } catch (AccessDeniedException expected) { + assertTrue(true); + } + // Check if we'd get access if ROLE_2 was all that is acceptable config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant @@ -205,11 +305,40 @@ public class VoterManagerTests extends TestCase { } catch (AccessDeniedException expected) { assertTrue(true); } + + // Check if we'd get denied access if equal votes, after changing setting + assertTrue(mgr.isAllowIfEqualGrantedDeniedDecisions()); // check default + mgr.setAllowIfEqualGrantedDeniedDecisions(false); + config = new ConfigAttributeDefinition(); + config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant + config.addConfigAttribute(new SecurityConfig("DENY_FOR_SURE")); // deny + + try { + mgr.decide(auth, null, config); + fail("Should have thrown AccessDeniedException"); + } catch (AccessDeniedException expected) { + assertTrue(true); + } + + // Check if we'd be denied access if all abstained + config = new ConfigAttributeDefinition(); + config.addConfigAttribute(new SecurityConfig("NONE_WILL_VOTE")); // abstain + + try { + mgr.decide(auth, null, config); + fail("Should have thrown AccessDeniedException"); + } catch (AccessDeniedException expected) { + assertTrue(true); + } + + // Now check it works given we approve access if all abstain + mgr.setAllowIfAllAbstainDecisions(true); + mgr.decide(auth, null, config); + assertTrue(true); } public void testUnanimous() throws Exception { - AccessDecisionManager mgr = (AccessDecisionManager) ctx.getBean( - "unanimousBased"); + UnanimousBased mgr = (UnanimousBased) ctx.getBean("unanimousBased"); ConfigAttributeDefinition config; TestingAuthenticationToken auth; @@ -217,6 +346,19 @@ public class VoterManagerTests extends TestCase { new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_1"), new GrantedAuthorityImpl( "ROLE_2"), new GrantedAuthorityImpl("ROLE_MAGIC")}); + // Check if we'd be denied access, with only one definite deny vote and many affirmative + config = new ConfigAttributeDefinition(); + config.addConfigAttribute(new SecurityConfig("DENY_FOR_SURE")); // deny + config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant + config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant + + try { + mgr.decide(auth, null, config); + fail("Should have thrown AccessDeniedException"); + } catch (AccessDeniedException expected) { + assertTrue(true); + } + // Check if we'd get access if ROLE_2 was all that is required config = new ConfigAttributeDefinition(); config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant @@ -272,5 +414,21 @@ public class VoterManagerTests extends TestCase { } catch (AccessDeniedException expected) { assertTrue(true); } + + // Check if we'd be denied access if all abstained + config = new ConfigAttributeDefinition(); + config.addConfigAttribute(new SecurityConfig("NONE_WILL_VOTE")); // abstain + + try { + mgr.decide(auth, null, config); + fail("Should have thrown AccessDeniedException"); + } catch (AccessDeniedException expected) { + assertTrue(true); + } + + // Now check it works given we approve access if all abstain + mgr.setAllowIfAllAbstainDecisions(true); + mgr.decide(auth, null, config); + assertTrue(true); } } diff --git a/core/src/test/java/org/acegisecurity/vote/applicationContext.xml b/core/src/test/java/org/acegisecurity/vote/applicationContext.xml index fb1fd5a121..f0e7324a32 100644 --- a/core/src/test/java/org/acegisecurity/vote/applicationContext.xml +++ b/core/src/test/java/org/acegisecurity/vote/applicationContext.xml @@ -19,11 +19,15 @@