001 /**
002 *
003 */
004 package org.springframework.richclient.security.support;
005
006 import java.util.ArrayList;
007
008 import junit.framework.TestCase;
009
010 import org.springframework.security.AccessDecisionManager;
011 import org.springframework.security.AccessDeniedException;
012 import org.springframework.security.Authentication;
013 import org.springframework.security.ConfigAttribute;
014 import org.springframework.security.ConfigAttributeDefinition;
015 import org.springframework.security.providers.TestingAuthenticationToken;
016
017 /**
018 * @author Larry Streepy
019 *
020 */
021 public class SecurityControllerTests extends TestCase {
022
023 private TestAbstractSecurityController controller;
024 private TestAccessDecisionManager accessDecisionManager;
025
026 /*
027 * @see TestCase#setUp()
028 */
029 protected void setUp() throws Exception {
030 super.setUp();
031 controller = new TestAbstractSecurityController();
032 accessDecisionManager = new TestAccessDecisionManager();
033 controller.setAccessDecisionManager(accessDecisionManager);
034 }
035
036 /**
037 * Test that setting the authentication token updates all controlled objects.
038 */
039 public void testSetAuthenticationToken() {
040
041 // Validate that the controller updates the controlled objects whenever the
042 // Authentication token is updated
043 TestAuthorizable a1 = new TestAuthorizable( true );
044 TestAuthorizable a2 = new TestAuthorizable( true );
045 controller.addControlledObject( a1 );
046 controller.addControlledObject( a2 );
047 assertFalse( "Object should not be authorized", a1.isAuthorized() );
048 assertFalse( "Object should not be authorized", a2.isAuthorized() );
049
050 a1.resetAuthCount();
051 a2.resetAuthCount();
052
053 // Set the decision manager to authorize
054 accessDecisionManager.setDecisionValue( true );
055
056 // Now install a token, a should be updated
057 controller.setAuthenticationToken( new TestingAuthenticationToken( "USER2", "FOO") );
058 assertTrue( "Object should be authorized", a1.isAuthorized() );
059 assertEquals( "Object should be updated", a1.getAuthCount(), 1 );
060 assertTrue( "Object should be authorized", a2.isAuthorized() );
061 assertEquals( "Object should be updated", a2.getAuthCount(), 1 );
062
063 controller.setAuthenticationToken( null );
064 assertFalse( "Object should not be authorized", a1.isAuthorized() );
065 assertEquals( "Object should be updated", a1.getAuthCount(), 2 );
066 assertFalse( "Object should not be authorized", a2.isAuthorized() );
067 assertEquals( "Object should be updated", a2.getAuthCount(), 2 );
068
069 // Set the decision manager to NOT authorize
070 accessDecisionManager.setDecisionValue( false );
071
072 // Now install a token, a should be updated
073 controller.setAuthenticationToken( new TestingAuthenticationToken( "USER2", "FOO") );
074 assertFalse( "Object should not be authorized", a1.isAuthorized() );
075 assertEquals( "Object should be updated", a1.getAuthCount(), 3 );
076 assertFalse( "Object should not be authorized", a2.isAuthorized() );
077 assertEquals( "Object should be updated", a2.getAuthCount(), 3 );
078 }
079
080 public void testSetControlledObjects() {
081
082 TestAuthorizable a1 = new TestAuthorizable( true );
083 TestAuthorizable a2 = new TestAuthorizable( true );
084 ArrayList goodList = new ArrayList();
085 goodList.add( a1 );
086 goodList.add( a2 );
087
088 ArrayList badList = new ArrayList();
089 badList.add( new Object() );
090
091 try {
092 controller.setControlledObjects( badList );
093 fail( "Should reject objects that aren't Authorizable" );
094 } catch( IllegalArgumentException e ) {
095 // expected
096 }
097
098 controller.setControlledObjects( goodList );
099 assertFalse( "Object should not be authorized", a1.isAuthorized() );
100 assertTrue( "Object should be updated", a1.getAuthCount() == 1 );
101 assertFalse( "Object should not be authorized", a2.isAuthorized() );
102 assertTrue( "Object should be updated", a2.getAuthCount() == 1 );
103 }
104
105 /**
106 * Test that added objects are initially configured.
107 */
108 public void testAddControlledObject() {
109
110 // Install an authentication token
111 controller.setAuthenticationToken( new TestingAuthenticationToken( "USER2", "FOO") );
112
113 // Set the decision manager to authorize
114 accessDecisionManager.setDecisionValue( true );
115
116 TestAuthorizable a1 = new TestAuthorizable( false );
117 controller.addControlledObject( a1 );
118 assertTrue( "Object should be authorized", a1.isAuthorized() );
119 assertTrue( "Object should be updated", a1.getAuthCount() == 1 );
120
121 // Set the decision manager to NOT authorize
122 accessDecisionManager.setDecisionValue( false );
123
124 TestAuthorizable a2 = new TestAuthorizable( true );
125 controller.addControlledObject( a2 );
126 assertFalse( "Object should not be authorized", a2.isAuthorized() );
127 assertTrue( "Object should be updated", a2.getAuthCount() == 1 );
128 }
129
130 /**
131 * Test that once removed an object is no longer updated.
132 */
133 public void testRemoveControlledObject() {
134 TestAuthorizable a = new TestAuthorizable( true );
135 controller.addControlledObject( a );
136 assertFalse( "Object should not be authorized", a.isAuthorized() );
137 assertTrue( "Object should be updated", a.getAuthCount() == 1 );
138
139 controller.removeControlledObject( a );
140 a.resetAuthCount();
141
142 // Set the decision manager to authorize
143 accessDecisionManager.setDecisionValue( true );
144 controller.setAuthenticationToken( new TestingAuthenticationToken( "USER2", "FOO" ) );
145
146 assertFalse( "Object should not be authorized", a.isAuthorized() );
147 assertTrue( "Object should not be updated", a.getAuthCount() == 0 );
148 }
149
150 /**
151 * Concrete implementation under test.
152 */
153 public class TestAbstractSecurityController extends AbstractSecurityController {
154
155 public TestAbstractSecurityController() {
156 }
157
158 protected Object getSecuredObject() {
159 return null;
160 }
161
162 protected ConfigAttributeDefinition getConfigAttributeDefinition(Object securedObject) {
163 return null;
164 }
165 }
166
167 /**
168 * Controllable AccessDecisionManager
169 */
170 public class TestAccessDecisionManager implements AccessDecisionManager {
171
172 private boolean decisionValue;
173
174 public void setDecisionValue(boolean decisionValue) {
175 this.decisionValue = decisionValue;
176 }
177
178 public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
179 throws AccessDeniedException {
180 if( !decisionValue) {
181 throw new AccessDeniedException( "access denied" );
182 }
183 }
184
185 public boolean supports(ConfigAttribute attribute) {
186 return false;
187 }
188
189 public boolean supports(Class clazz) {
190 return false;
191 }
192 }
193 }