1   /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
2    *
3    * Licensed under the Apache License, Version 2.0 (the "License");
4    * you may not use this file except in compliance with the License.
5    * You may obtain a copy of the License at
6    *
7    *     http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  
16  package org.acegisecurity.afterinvocation;
17  
18  import junit.framework.TestCase;
19  
20  import org.acegisecurity.AuthorizationServiceException;
21  import org.acegisecurity.ConfigAttributeDefinition;
22  import org.acegisecurity.MockAclManager;
23  import org.acegisecurity.SecurityConfig;
24  
25  import org.acegisecurity.acl.AclEntry;
26  import org.acegisecurity.acl.AclManager;
27  import org.acegisecurity.acl.basic.MockAclObjectIdentity;
28  import org.acegisecurity.acl.basic.SimpleAclEntry;
29  
30  import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
31  
32  import org.acegisecurity.util.SimpleMethodInvocation;
33  
34  import java.util.List;
35  import java.util.Vector;
36  
37  
38  /**
39   * Tests {@link BasicAclEntryAfterInvocationCollectionFilteringProvider}.
40   *
41   * @author Ben Alex
42   * @version $Id: BasicAclEntryAfterInvocationCollectionFilteringProviderTests.java 1496 2006-05-23 13:38:33Z benalex $
43   */
44  public class BasicAclEntryAfterInvocationCollectionFilteringProviderTests extends TestCase {
45      //~ Constructors ===================================================================================================
46  
47      public BasicAclEntryAfterInvocationCollectionFilteringProviderTests() {
48          super();
49      }
50  
51      public BasicAclEntryAfterInvocationCollectionFilteringProviderTests(String arg0) {
52          super(arg0);
53      }
54  
55      //~ Methods ========================================================================================================
56  
57      public static void main(String[] args) {
58          junit.textui.TestRunner.run(BasicAclEntryAfterInvocationCollectionFilteringProviderTests.class);
59      }
60  
61      public final void setUp() throws Exception {
62          super.setUp();
63      }
64  
65      public void testCorrectOperationWhenPrincipalHasIncorrectPermissionToDomainObject()
66          throws Exception {
67          // Create an AclManager, granting scott only ADMINISTRATION rights
68          AclManager aclManager = new MockAclManager("belmont", "scott",
69                  new AclEntry[] {
70                      new SimpleAclEntry("scott", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION)
71                  });
72  
73          BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
74          provider.setAclManager(aclManager);
75          provider.afterPropertiesSet();
76  
77          // Create a Collection containing many items
78          List list = new Vector();
79          list.add("sydney");
80          list.add("melbourne");
81          list.add("belmont");
82          list.add("brisbane");
83  
84          // Create the Authentication and Config Attribs we'll be presenting
85          UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("scott", "NOT_USED");
86          ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
87          attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ"));
88  
89          // Filter
90          List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list);
91  
92          assertEquals(0, filteredList.size());
93      }
94  
95      public void testCorrectOperationWhenPrincipalHasNoPermissionToDomainObject()
96          throws Exception {
97          // Create an AclManager
98          AclManager aclManager = new MockAclManager("belmont", "marissa",
99                  new AclEntry[] {
100                     new MockAclEntry(),
101                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
102                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
103                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
104                 });
105 
106         BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
107         provider.setAclManager(aclManager);
108         provider.afterPropertiesSet();
109 
110         // Create a Collection containing many items, which only "belmont"
111         // should remain in after filtering by provider
112         List list = new Vector();
113         list.add("sydney");
114         list.add("melbourne");
115         list.add("belmont");
116         list.add("brisbane");
117 
118         // Create the Authentication and Config Attribs we'll be presenting
119         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("scott", "NOT_USED");
120         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
121         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ"));
122 
123         // Filter
124         List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list);
125 
126         assertEquals(0, filteredList.size());
127     }
128 
129     public void testCorrectOperationWhenPrincipalIsAuthorised()
130         throws Exception {
131         // Create an AclManager
132         AclManager aclManager = new MockAclManager("belmont", "marissa",
133                 new AclEntry[] {
134                     new MockAclEntry(),
135                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
136                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
137                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
138                 });
139 
140         BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
141         provider.setAclManager(aclManager);
142         assertEquals(aclManager, provider.getAclManager());
143         provider.afterPropertiesSet();
144 
145         // Create a Collection containing many items, which only "belmont"
146         // should remain in after filtering by provider
147         List list = new Vector();
148         list.add("sydney");
149         list.add("melbourne");
150         list.add("belmont");
151         list.add("brisbane");
152 
153         // Create the Authentication and Config Attribs we'll be presenting
154         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED");
155         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
156         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ"));
157 
158         // Filter
159         List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list);
160 
161         assertEquals(1, filteredList.size());
162         assertEquals("belmont", filteredList.get(0));
163     }
164 
165     public void testCorrectOperationWhenReturnedObjectIsArray()
166         throws Exception {
167         // Create an AclManager
168         AclManager aclManager = new MockAclManager("belmont", "marissa",
169                 new AclEntry[] {
170                     new MockAclEntry(),
171                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
172                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
173                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
174                 });
175 
176         BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
177         provider.setAclManager(aclManager);
178         assertEquals(aclManager, provider.getAclManager());
179         provider.afterPropertiesSet();
180 
181         // Create a Collection containing many items, which only "belmont"
182         // should remain in after filtering by provider
183         String[] list = new String[4];
184         list[0] = "sydney";
185         list[1] = "melbourne";
186         list[2] = "belmont";
187         list[3] = "brisbane";
188 
189         // Create the Authentication and Config Attribs we'll be presenting
190         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED");
191         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
192         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ"));
193 
194         // Filter
195         String[] filteredList = (String[]) provider.decide(auth, new SimpleMethodInvocation(), attr, list);
196 
197         assertEquals(1, filteredList.length);
198         assertEquals("belmont", filteredList[0]);
199     }
200 
201     public void testDetectsIfReturnedObjectIsNotACollection()
202         throws Exception {
203         // Create an AclManager
204         AclManager aclManager = new MockAclManager("belmont", "marissa",
205                 new AclEntry[] {
206                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
207                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
208                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE),
209                     new MockAclEntry()
210                 });
211 
212         BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
213         provider.setAclManager(aclManager);
214         provider.afterPropertiesSet();
215 
216         // Create the Authentication and Config Attribs we'll be presenting
217         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED");
218         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
219         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ"));
220 
221         // Filter
222         try {
223             provider.decide(auth, new SimpleMethodInvocation(), attr, new String("RETURN_OBJECT_NOT_COLLECTION"));
224             fail("Should have thrown AuthorizationServiceException");
225         } catch (AuthorizationServiceException expected) {
226             assertTrue(true);
227         }
228     }
229 
230     public void testGrantsAccessIfReturnedObjectIsNull()
231         throws Exception {
232         // Create an AclManager
233         AclManager aclManager = new MockAclManager("belmont", "marissa",
234                 new AclEntry[] {
235                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
236                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
237                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE),
238                     new MockAclEntry()
239                 });
240 
241         BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
242         provider.setAclManager(aclManager);
243         provider.afterPropertiesSet();
244 
245         // Create the Authentication and Config Attribs we'll be presenting
246         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED");
247         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
248         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ"));
249 
250         // Filter
251         List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, null);
252 
253         assertNull(filteredList);
254     }
255 
256     public void testRespectsModificationsToProcessConfigAttribute()
257         throws Exception {
258         // Create an AclManager
259         AclManager aclManager = new MockAclManager("sydney", "marissa",
260                 new AclEntry[] {
261                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
262                     new MockAclEntry()
263                 });
264 
265         BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
266         provider.setAclManager(aclManager);
267         assertEquals("AFTER_ACL_COLLECTION_READ", provider.getProcessConfigAttribute());
268         provider.setProcessConfigAttribute("AFTER_ACL_COLLECTION_ADMIN");
269         assertEquals("AFTER_ACL_COLLECTION_ADMIN", provider.getProcessConfigAttribute());
270         provider.afterPropertiesSet();
271 
272         // Create a Collection containing many items, which only "sydney"
273         // should remain in after filtering by provider
274         List list = new Vector();
275         list.add("sydney");
276         list.add("melbourne");
277         list.add("belmont");
278         list.add("brisbane");
279 
280         // Create the Authentication and Config Attribs we'll be presenting
281         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED");
282         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
283         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ"));
284 
285         // As no matching config attrib, ensure provider doesn't change list
286         assertEquals(4, ((List) provider.decide(auth, new SimpleMethodInvocation(), attr, list)).size());
287 
288         // Filter, this time with the conf attrib provider setup to answer
289         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_ADMIN"));
290 
291         List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list);
292 
293         assertEquals(1, filteredList.size());
294         assertEquals("sydney", filteredList.get(0));
295     }
296 
297     public void testRespectsModificationsToRequirePermissions()
298         throws Exception {
299         // Create an AclManager
300         AclManager aclManager = new MockAclManager("sydney", "marissa",
301                 new AclEntry[] {
302                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
303                     new MockAclEntry()
304                 });
305 
306         BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
307         provider.setAclManager(aclManager);
308         assertEquals(SimpleAclEntry.READ, provider.getRequirePermission()[0]);
309         provider.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION});
310         assertEquals(SimpleAclEntry.ADMINISTRATION, provider.getRequirePermission()[0]);
311         provider.afterPropertiesSet();
312 
313         // Create a Collection containing many items, which only "sydney"
314         // should remain in after filtering by provider
315         List list = new Vector();
316         list.add("sydney");
317         list.add("melbourne");
318         list.add("belmont");
319         list.add("brisbane");
320 
321         // Create the Authentication and Config Attribs we'll be presenting
322         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED");
323         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
324         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_COLLECTION_READ"));
325 
326         // Filter
327         List filteredList = (List) provider.decide(auth, new SimpleMethodInvocation(), attr, list);
328 
329         assertEquals(1, filteredList.size());
330         assertEquals("sydney", filteredList.get(0));
331     }
332 
333     public void testStartupDetectsMissingAclManager() throws Exception {
334         BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
335 
336         try {
337             provider.afterPropertiesSet();
338             fail("Should have thrown IllegalArgumentException");
339         } catch (IllegalArgumentException expected) {
340             assertEquals("An aclManager is mandatory", expected.getMessage());
341         }
342     }
343 
344     public void testStartupDetectsMissingProcessConfigAttribute()
345         throws Exception {
346         BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
347         AclManager aclManager = new MockAclManager("sydney", "marissa",
348                 new AclEntry[] {
349                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
350                     new MockAclEntry()
351                 });
352         provider.setAclManager(aclManager);
353 
354         provider.setProcessConfigAttribute(null);
355 
356         try {
357             provider.afterPropertiesSet();
358             fail("Should have thrown IllegalArgumentException");
359         } catch (IllegalArgumentException expected) {
360             assertEquals("A processConfigAttribute is mandatory", expected.getMessage());
361         }
362     }
363 
364     public void testStartupDetectsMissingRequirePermission()
365         throws Exception {
366         BasicAclEntryAfterInvocationCollectionFilteringProvider provider = new BasicAclEntryAfterInvocationCollectionFilteringProvider();
367         AclManager aclManager = new MockAclManager("sydney", "marissa",
368                 new AclEntry[] {
369                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
370                     new MockAclEntry()
371                 });
372         provider.setAclManager(aclManager);
373 
374         provider.setRequirePermission(null);
375 
376         try {
377             provider.afterPropertiesSet();
378             fail("Should have thrown IllegalArgumentException");
379         } catch (IllegalArgumentException expected) {
380             assertEquals("One or more requirePermission entries is mandatory", expected.getMessage());
381         }
382     }
383 
384     public void testSupportsAnything() {
385         assertTrue(new BasicAclEntryAfterInvocationCollectionFilteringProvider().supports(String.class));
386     }
387 
388     //~ Inner Classes ==================================================================================================
389 
390     private class MockAclEntry implements AclEntry {
391         // just so AclTag iterates some different types of AclEntrys
392     }
393 }