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