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.AccessDeniedException;
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  
35  /**
36   * Tests {@link BasicAclEntryAfterInvocationProvider}.
37   *
38   * @author Ben Alex
39   * @version $Id: BasicAclEntryAfterInvocationProviderTests.java 1496 2006-05-23 13:38:33Z benalex $
40   */
41  public class BasicAclEntryAfterInvocationProviderTests extends TestCase {
42      //~ Constructors ===================================================================================================
43  
44      public BasicAclEntryAfterInvocationProviderTests() {
45          super();
46      }
47  
48      public BasicAclEntryAfterInvocationProviderTests(String arg0) {
49          super(arg0);
50      }
51  
52      //~ Methods ========================================================================================================
53  
54      public static void main(String[] args) {
55          junit.textui.TestRunner.run(BasicAclEntryAfterInvocationProviderTests.class);
56      }
57  
58      public final void setUp() throws Exception {
59          super.setUp();
60      }
61  
62      public void testCorrectOperationWhenPrincipalHasIncorrectPermissionToDomainObject()
63          throws Exception {
64          // Create an AclManager, granting scott only ADMINISTRATION rights
65          AclManager aclManager = new MockAclManager("belmont", "scott",
66                  new AclEntry[] {
67                      new SimpleAclEntry("scott", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION)
68                  });
69  
70          BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
71          provider.setAclManager(aclManager);
72          provider.afterPropertiesSet();
73  
74          // Create the Authentication and Config Attribs we'll be presenting
75          UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("scott", "NOT_USED");
76          ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
77          attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_READ"));
78  
79          try {
80              provider.decide(auth, new SimpleMethodInvocation(), attr, "belmont");
81              fail("Should have thrown AccessDeniedException");
82          } catch (AccessDeniedException expected) {
83              assertTrue(true);
84          }
85      }
86  
87      public void testCorrectOperationWhenPrincipalHasNoPermissionToDomainObject()
88          throws Exception {
89          // Create an AclManager
90          AclManager aclManager = new MockAclManager("belmont", "marissa",
91                  new AclEntry[] {
92                      new MockAclEntry(),
93                      new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
94                      new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
95                      new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
96                  });
97  
98          BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
99          provider.setAclManager(aclManager);
100         provider.afterPropertiesSet();
101 
102         // Create the Authentication and Config Attribs we'll be presenting
103         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("scott", "NOT_USED");
104         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
105         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_READ"));
106 
107         try {
108             provider.decide(auth, new SimpleMethodInvocation(), attr, "belmont");
109             fail("Should have thrown AccessDeniedException");
110         } catch (AccessDeniedException expected) {
111             assertTrue(true);
112         }
113     }
114 
115     public void testCorrectOperationWhenPrincipalIsAuthorised()
116         throws Exception {
117         // Create an AclManager
118         AclManager aclManager = new MockAclManager("belmont", "marissa",
119                 new AclEntry[] {
120                     new MockAclEntry(),
121                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
122                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
123                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)
124                 });
125 
126         BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
127         provider.setAclManager(aclManager);
128         assertEquals(aclManager, provider.getAclManager());
129         provider.afterPropertiesSet();
130 
131         // Create the Authentication and Config Attribs we'll be presenting
132         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED");
133         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
134         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_READ"));
135 
136         // Filter
137         assertEquals("belmont", provider.decide(auth, new SimpleMethodInvocation(), attr, "belmont"));
138     }
139 
140     public void testGrantsAccessIfReturnedObjectIsNull()
141         throws Exception {
142         // Create an AclManager
143         AclManager aclManager = new MockAclManager("belmont", "marissa",
144                 new AclEntry[] {
145                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
146                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
147                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE),
148                     new MockAclEntry()
149                 });
150 
151         BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
152         provider.setAclManager(aclManager);
153         provider.afterPropertiesSet();
154 
155         // Create the Authentication and Config Attribs we'll be presenting
156         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED");
157         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
158         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_READ"));
159 
160         // Filter
161         assertNull(provider.decide(auth, new SimpleMethodInvocation(), attr, null));
162     }
163 
164     public void testRespectsModificationsToProcessConfigAttribute()
165         throws Exception {
166         // Create an AclManager
167         AclManager aclManager = new MockAclManager("sydney", "marissa",
168                 new AclEntry[] {
169                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.READ),
170                     new MockAclEntry()
171                 });
172 
173         BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
174         provider.setAclManager(aclManager);
175         assertEquals("AFTER_ACL_READ", provider.getProcessConfigAttribute());
176         provider.setProcessConfigAttribute("AFTER_ACL_ADMIN");
177         assertEquals("AFTER_ACL_ADMIN", provider.getProcessConfigAttribute());
178         provider.afterPropertiesSet();
179 
180         // Create the Authentication and Config Attribs we'll be presenting
181         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED");
182         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
183         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_READ"));
184 
185         // As no matching config attrib, ensure provider returns original obj
186         assertEquals("sydney", provider.decide(auth, new SimpleMethodInvocation(), attr, "sydney"));
187 
188         // Filter, this time with the conf attrib provider setup to answer
189         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_ADMIN"));
190         assertEquals("sydney", provider.decide(auth, new SimpleMethodInvocation(), attr, "sydney"));
191     }
192 
193     public void testRespectsModificationsToRequirePermissions()
194         throws Exception {
195         // Create an AclManager
196         AclManager aclManager = new MockAclManager("sydney", "marissa",
197                 new AclEntry[] {
198                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
199                     new MockAclEntry()
200                 });
201 
202         BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
203         provider.setAclManager(aclManager);
204         assertEquals(SimpleAclEntry.READ, provider.getRequirePermission()[0]);
205         provider.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION});
206         assertEquals(SimpleAclEntry.ADMINISTRATION, provider.getRequirePermission()[0]);
207         provider.afterPropertiesSet();
208 
209         // Create the Authentication and Config Attribs we'll be presenting
210         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("marissa", "NOT_USED");
211         ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
212         attr.addConfigAttribute(new SecurityConfig("AFTER_ACL_READ"));
213 
214         // Filter
215         assertEquals("sydney", provider.decide(auth, new SimpleMethodInvocation(), attr, "sydney"));
216     }
217 
218     public void testStartupDetectsMissingAclManager() throws Exception {
219         BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
220 
221         try {
222             provider.afterPropertiesSet();
223             fail("Should have thrown IllegalArgumentException");
224         } catch (IllegalArgumentException expected) {
225             assertEquals("An aclManager is mandatory", expected.getMessage());
226         }
227     }
228 
229     public void testStartupDetectsMissingProcessConfigAttribute()
230         throws Exception {
231         BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
232         AclManager aclManager = new MockAclManager("sydney", "marissa",
233                 new AclEntry[] {
234                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
235                     new MockAclEntry()
236                 });
237         provider.setAclManager(aclManager);
238 
239         provider.setProcessConfigAttribute(null);
240 
241         try {
242             provider.afterPropertiesSet();
243             fail("Should have thrown IllegalArgumentException");
244         } catch (IllegalArgumentException expected) {
245             assertEquals("A processConfigAttribute is mandatory", expected.getMessage());
246         }
247     }
248 
249     public void testStartupDetectsMissingRequirePermission()
250         throws Exception {
251         BasicAclEntryAfterInvocationProvider provider = new BasicAclEntryAfterInvocationProvider();
252         AclManager aclManager = new MockAclManager("sydney", "marissa",
253                 new AclEntry[] {
254                     new SimpleAclEntry("marissa", new MockAclObjectIdentity(), null, SimpleAclEntry.ADMINISTRATION),
255                     new MockAclEntry()
256                 });
257         provider.setAclManager(aclManager);
258 
259         provider.setRequirePermission(null);
260 
261         try {
262             provider.afterPropertiesSet();
263             fail("Should have thrown IllegalArgumentException");
264         } catch (IllegalArgumentException expected) {
265             assertEquals("One or more requirePermission entries is mandatory", expected.getMessage());
266         }
267     }
268 
269     public void testSupportsAnything() {
270         assertTrue(new BasicAclEntryAfterInvocationProvider().supports(String.class));
271     }
272 
273     //~ Inner Classes ==================================================================================================
274 
275     private class MockAclEntry implements AclEntry {
276         // just so AclTag iterates some different types of AclEntrys
277     }
278 }