    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 }