1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.acegisecurity.vote;
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 org.aopalliance.intercept.MethodInvocation;
32
33 import org.aspectj.lang.JoinPoint;
34
35 import java.lang.reflect.Method;
36
37
38 /***
39 * Tests {@link BasicAclEntryVoter}.
40 *
41 * @author Ben Alex
42 * @version $Id: BasicAclEntryVoterTests.java,v 1.4 2005/11/25 04:17:24 benalex Exp $
43 */
44 public class BasicAclEntryVoterTests extends TestCase {
45
46
47 public BasicAclEntryVoterTests() {
48 super();
49 }
50
51 public BasicAclEntryVoterTests(String arg0) {
52 super(arg0);
53 }
54
55
56
57 public final void setUp() throws Exception {
58 super.setUp();
59 }
60
61 public static void main(String[] args) {
62 junit.textui.TestRunner.run(BasicAclEntryVoterTests.class);
63 }
64
65 public void testNormalOperation() throws Exception {
66
67 SomeDomainObject domainObject = new SomeDomainObject("foo");
68
69
70 AclManager aclManager = new MockAclManager(domainObject, "marissa",
71 new AclEntry[] {new MockAclEntry(), new SimpleAclEntry(
72 "marissa", new MockAclObjectIdentity(), null,
73 SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry(
74 "marissa", new MockAclObjectIdentity(), null,
75 SimpleAclEntry.READ), new SimpleAclEntry("marissa",
76 new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)});
77
78
79 BasicAclEntryVoter voter = new BasicAclEntryVoter();
80 voter.setAclManager(aclManager);
81 assertEquals(aclManager, voter.getAclManager());
82 voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
83 assertEquals("FOO_ADMIN_OR_WRITE_ACCESS",
84 voter.getProcessConfigAttribute());
85 voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
86 assertEquals(2, voter.getRequirePermission().length);
87 voter.setProcessDomainObjectClass(SomeDomainObject.class);
88 assertEquals(SomeDomainObject.class, voter.getProcessDomainObjectClass());
89 voter.afterPropertiesSet();
90
91
92 ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
93 attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS"));
94
95
96 MethodInvocation mi = getMethodInvocation(domainObject);
97
98 assertEquals(AccessDecisionVoter.ACCESS_GRANTED,
99 voter.vote(
100 new UsernamePasswordAuthenticationToken("marissa", null), mi,
101 attr));
102 }
103
104 public void testOnlySupportsMethodInvocation() {
105 BasicAclEntryVoter voter = new BasicAclEntryVoter();
106 assertTrue(voter.supports(MethodInvocation.class));
107 assertFalse(voter.supports(JoinPoint.class));
108 }
109
110 public void testStartupRejectsMissingAclManager() throws Exception {
111 AclManager aclManager = new MockAclManager("domain1", "marissa",
112 new AclEntry[] {new MockAclEntry(), new SimpleAclEntry(
113 "marissa", new MockAclObjectIdentity(), null,
114 SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry(
115 "marissa", new MockAclObjectIdentity(), null,
116 SimpleAclEntry.READ), new SimpleAclEntry("marissa",
117 new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)});
118
119
120 BasicAclEntryVoter voter = new BasicAclEntryVoter();
121 voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
122 voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
123 voter.setProcessDomainObjectClass(SomeDomainObject.class);
124
125 try {
126 voter.afterPropertiesSet();
127 fail("Should have thrown IllegalArgumentException");
128 } catch (IllegalArgumentException expected) {
129 assertTrue(true);
130 }
131 }
132
133 public void testStartupRejectsMissingProcessConfigAttribute()
134 throws Exception {
135 AclManager aclManager = new MockAclManager("domain1", "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
144 BasicAclEntryVoter voter = new BasicAclEntryVoter();
145 voter.setAclManager(aclManager);
146 voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
147 voter.setProcessDomainObjectClass(SomeDomainObject.class);
148
149 try {
150 voter.afterPropertiesSet();
151 fail("Should have thrown IllegalArgumentException");
152 } catch (IllegalArgumentException expected) {
153 assertTrue(true);
154 }
155 }
156
157 public void testStartupRejectsMissingProcessDomainObjectClass()
158 throws Exception {
159 BasicAclEntryVoter voter = new BasicAclEntryVoter();
160
161 try {
162 voter.setProcessDomainObjectClass(null);
163 fail("Should have thrown IllegalArgumentException");
164 } catch (IllegalArgumentException expected) {
165 assertTrue(true);
166 }
167 }
168
169 public void testStartupRejectsMissingRequirePermission()
170 throws Exception {
171 AclManager aclManager = new MockAclManager("domain1", "marissa",
172 new AclEntry[] {new MockAclEntry(), new SimpleAclEntry(
173 "marissa", new MockAclObjectIdentity(), null,
174 SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry(
175 "marissa", new MockAclObjectIdentity(), null,
176 SimpleAclEntry.READ), new SimpleAclEntry("marissa",
177 new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)});
178
179
180 BasicAclEntryVoter voter = new BasicAclEntryVoter();
181 voter.setAclManager(aclManager);
182 voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
183 voter.setProcessDomainObjectClass(SomeDomainObject.class);
184
185 try {
186 voter.afterPropertiesSet();
187 fail("Should have thrown IllegalArgumentException");
188 } catch (IllegalArgumentException expected) {
189 assertTrue(true);
190 }
191 }
192
193 public void testSupportsConfigAttribute() {
194 BasicAclEntryVoter voter = new BasicAclEntryVoter();
195 voter.setProcessConfigAttribute("foobar");
196 assertTrue(voter.supports(new SecurityConfig("foobar")));
197 }
198
199 public void testVoterAbstainsIfDomainObjectIsNull()
200 throws Exception {
201
202 SomeDomainObject domainObject = new SomeDomainObject("foo");
203
204
205 AclManager aclManager = new MockAclManager(domainObject, "marissa",
206 new AclEntry[] {new MockAclEntry(), new SimpleAclEntry(
207 "marissa", new MockAclObjectIdentity(), null,
208 SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry(
209 "marissa", new MockAclObjectIdentity(), null,
210 SimpleAclEntry.READ), new SimpleAclEntry("marissa",
211 new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)});
212
213
214 BasicAclEntryVoter voter = new BasicAclEntryVoter();
215 voter.setAclManager(aclManager);
216 voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
217 voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
218 voter.setProcessDomainObjectClass(SomeDomainObject.class);
219 voter.afterPropertiesSet();
220
221
222 ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
223 attr.addConfigAttribute(new SecurityConfig("A_DIFFERENT_ATTRIBUTE"));
224
225
226 MethodInvocation mi = getMethodInvocation(domainObject);
227
228 assertEquals(AccessDecisionVoter.ACCESS_ABSTAIN,
229 voter.vote(
230 new UsernamePasswordAuthenticationToken("marissa", null), mi,
231 attr));
232 }
233
234 public void testVoterAbstainsIfNotMatchingConfigAttribute()
235 throws Exception {
236
237 SomeDomainObject domainObject = null;
238
239
240 AclManager aclManager = new MockAclManager(domainObject, "marissa",
241 new AclEntry[] {new MockAclEntry(), new SimpleAclEntry(
242 "marissa", new MockAclObjectIdentity(), null,
243 SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry(
244 "marissa", new MockAclObjectIdentity(), null,
245 SimpleAclEntry.READ), new SimpleAclEntry("marissa",
246 new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)});
247
248
249 BasicAclEntryVoter voter = new BasicAclEntryVoter();
250 voter.setAclManager(aclManager);
251 voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
252 voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
253 voter.setProcessDomainObjectClass(SomeDomainObject.class);
254 voter.afterPropertiesSet();
255
256
257 ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
258 attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS"));
259
260
261 MethodInvocation mi = getMethodInvocation(domainObject);
262
263 assertEquals(AccessDecisionVoter.ACCESS_ABSTAIN,
264 voter.vote(
265 new UsernamePasswordAuthenticationToken("marissa", null), mi,
266 attr));
267 }
268
269 public void testVoterCanDenyAccessBasedOnInternalMethodOfDomainObject()
270 throws Exception {
271
272 SomeDomainObject domainObject = new SomeDomainObject("foo");
273
274
275 AclManager aclManager = new MockAclManager(domainObject.getParent(),
276 "marissa",
277 new AclEntry[] {new MockAclEntry(), new SimpleAclEntry(
278 "marissa", new MockAclObjectIdentity(), null,
279 SimpleAclEntry.DELETE)});
280
281
282 BasicAclEntryVoter voter = new BasicAclEntryVoter();
283 voter.setAclManager(aclManager);
284 voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
285 voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
286 voter.setProcessDomainObjectClass(SomeDomainObject.class);
287 voter.setInternalMethod("getParent");
288 voter.afterPropertiesSet();
289
290
291 ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
292 attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS"));
293
294
295 MethodInvocation mi = getMethodInvocation(domainObject);
296
297 assertEquals(AccessDecisionVoter.ACCESS_DENIED,
298 voter.vote(
299 new UsernamePasswordAuthenticationToken("marissa", null), mi,
300 attr));
301 }
302
303 public void testVoterCanDenyAccessIfPrincipalHasNoPermissionsAtAllToDomainObject()
304 throws Exception {
305
306 SomeDomainObject domainObject = new SomeDomainObject("foo");
307
308
309 AclManager aclManager = new MockAclManager(domainObject, "marissa",
310 new AclEntry[] {new MockAclEntry(), new SimpleAclEntry(
311 "marissa", new MockAclObjectIdentity(), null,
312 SimpleAclEntry.DELETE)});
313
314
315 BasicAclEntryVoter voter = new BasicAclEntryVoter();
316 voter.setAclManager(aclManager);
317 voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
318 voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
319 voter.setProcessDomainObjectClass(SomeDomainObject.class);
320 voter.setInternalMethod("getParent");
321 voter.afterPropertiesSet();
322
323
324 ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
325 attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS"));
326
327
328 MethodInvocation mi = getMethodInvocation(domainObject);
329
330
331 assertEquals(AccessDecisionVoter.ACCESS_DENIED,
332 voter.vote(new UsernamePasswordAuthenticationToken("scott", null),
333 mi, attr));
334 }
335
336 public void testVoterCanGrantAccessBasedOnInternalMethodOfDomainObject()
337 throws Exception {
338
339 SomeDomainObject domainObject = new SomeDomainObject("foo");
340
341
342 AclManager aclManager = new MockAclManager(domainObject.getParent(),
343 "marissa",
344 new AclEntry[] {new MockAclEntry(), new SimpleAclEntry(
345 "marissa", new MockAclObjectIdentity(), null,
346 SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry(
347 "marissa", new MockAclObjectIdentity(), null,
348 SimpleAclEntry.READ), new SimpleAclEntry("marissa",
349 new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)});
350
351
352 BasicAclEntryVoter voter = new BasicAclEntryVoter();
353 voter.setAclManager(aclManager);
354 voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
355 voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
356 voter.setProcessDomainObjectClass(SomeDomainObject.class);
357 voter.setInternalMethod("getParent");
358 assertEquals("getParent", voter.getInternalMethod());
359 voter.afterPropertiesSet();
360
361
362 ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
363 attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS"));
364
365
366
367 MethodInvocation mi = getMethodInvocation(domainObject);
368
369 assertEquals(AccessDecisionVoter.ACCESS_GRANTED,
370 voter.vote(
371 new UsernamePasswordAuthenticationToken("marissa", null), mi,
372 attr));
373 }
374
375 public void testVoterThrowsExceptionIfInvalidInternalMethodOfDomainObject()
376 throws Exception {
377
378 SomeDomainObject domainObject = new SomeDomainObject("foo");
379
380
381 AclManager aclManager = new MockAclManager(domainObject.getParent(),
382 "marissa",
383 new AclEntry[] {new MockAclEntry(), new SimpleAclEntry(
384 "marissa", new MockAclObjectIdentity(), null,
385 SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry(
386 "marissa", new MockAclObjectIdentity(), null,
387 SimpleAclEntry.READ), new SimpleAclEntry("marissa",
388 new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)});
389
390
391 BasicAclEntryVoter voter = new BasicAclEntryVoter();
392 voter.setAclManager(aclManager);
393 voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
394 voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
395 voter.setProcessDomainObjectClass(SomeDomainObject.class);
396 voter.setInternalMethod("getNonExistentParentName");
397 voter.afterPropertiesSet();
398
399
400 ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
401 attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS"));
402
403
404
405 MethodInvocation mi = getMethodInvocation(domainObject);
406
407 try {
408 voter.vote(new UsernamePasswordAuthenticationToken("marissa", null),
409 mi, attr);
410 fail("Should have thrown AuthorizationServiceException");
411 } catch (AuthorizationServiceException expected) {
412 assertTrue(true);
413 }
414 }
415
416 public void testVoterThrowsExceptionIfProcessDomainObjectNotFound()
417 throws Exception {
418
419 SomeDomainObject domainObject = new SomeDomainObject("foo");
420
421
422 AclManager aclManager = new MockAclManager(domainObject.getParent(),
423 "marissa",
424 new AclEntry[] {new MockAclEntry(), new SimpleAclEntry(
425 "marissa", new MockAclObjectIdentity(), null,
426 SimpleAclEntry.ADMINISTRATION), new SimpleAclEntry(
427 "marissa", new MockAclObjectIdentity(), null,
428 SimpleAclEntry.READ), new SimpleAclEntry("marissa",
429 new MockAclObjectIdentity(), null, SimpleAclEntry.DELETE)});
430
431
432 BasicAclEntryVoter voter = new BasicAclEntryVoter();
433 voter.setAclManager(aclManager);
434 voter.setProcessConfigAttribute("FOO_ADMIN_OR_WRITE_ACCESS");
435 voter.setRequirePermission(new int[] {SimpleAclEntry.ADMINISTRATION, SimpleAclEntry.WRITE});
436 voter.setProcessDomainObjectClass(SomeDomainObject.class);
437 voter.afterPropertiesSet();
438
439
440 ConfigAttributeDefinition attr = new ConfigAttributeDefinition();
441 attr.addConfigAttribute(new SecurityConfig("FOO_ADMIN_OR_WRITE_ACCESS"));
442
443
444 Class clazz = String.class;
445 Method method = clazz.getMethod("toString", new Class[] {});
446
447 MethodInvocation mi = new SimpleMethodInvocation(method,
448 new Object[] {domainObject});
449
450 try {
451 voter.vote(new UsernamePasswordAuthenticationToken("marissa", null),
452 mi, attr);
453 fail("Should have thrown AuthorizationServiceException");
454 } catch (AuthorizationServiceException expected) {
455 assertTrue(true);
456 }
457 }
458
459 private MethodInvocation getMethodInvocation(SomeDomainObject domainObject)
460 throws Exception {
461 Class clazz = SomeDomainObjectManager.class;
462 Method method = clazz.getMethod("someServiceMethod",
463 new Class[] {SomeDomainObject.class});
464
465 return new SimpleMethodInvocation(method, new Object[] {domainObject});
466 }
467
468
469
470 private class MockAclEntry implements AclEntry {
471
472 }
473 }