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