1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.core.authz.support;
21  
22  
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.Collections;
26  import java.util.HashSet;
27  import java.util.Set;
28  
29  import javax.naming.NamingException;
30  import javax.naming.directory.Attribute;
31  
32  import org.apache.directory.server.core.DefaultDirectoryService;
33  import org.apache.directory.server.core.DirectoryService;
34  import org.apache.directory.server.core.authz.support.OperationScope;
35  import org.apache.directory.server.core.authz.support.RelatedProtectedItemFilter;
36  import org.apache.directory.server.core.authz.support.RelatedUserClassFilter;
37  import org.apache.directory.server.core.entry.DefaultServerAttribute;
38  import org.apache.directory.server.core.entry.DefaultServerEntry;
39  import org.apache.directory.server.core.entry.ServerAttribute;
40  import org.apache.directory.server.core.entry.ServerEntry;
41  import org.apache.directory.server.core.entry.ServerEntryUtils;
42  import org.apache.directory.server.core.event.ExpressionEvaluator;
43  import org.apache.directory.server.core.subtree.RefinementEvaluator;
44  import org.apache.directory.server.core.subtree.RefinementLeafEvaluator;
45  import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
46  import org.apache.directory.server.schema.registries.OidRegistry;
47  import org.apache.directory.shared.ldap.aci.ACITuple;
48  import org.apache.directory.shared.ldap.aci.MicroOperation;
49  import org.apache.directory.shared.ldap.aci.ProtectedItem;
50  import org.apache.directory.shared.ldap.aci.UserClass;
51  import org.apache.directory.shared.ldap.aci.ProtectedItem.MaxValueCountItem;
52  import org.apache.directory.shared.ldap.aci.ProtectedItem.RestrictedByItem;
53  import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
54  import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
55  import org.apache.directory.shared.ldap.name.LdapDN;
56  import org.apache.directory.shared.ldap.schema.AttributeType;
57  
58  
59  import org.junit.BeforeClass;
60  import org.junit.Test;
61  
62  import static org.junit.Assert.assertEquals;
63  
64  /**
65   * Tests {@link RelatedUserClassFilter}.
66   *
67   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
68   * @version $Rev: 691847 $, $Date: 2008-09-04 03:23:12 +0200 (Do, 04 Sep 2008) $
69   */
70  public class RelatedProtectedItemFilterTest
71  {
72      private static final Collection<UserClass> EMPTY_USER_CLASS_COLLECTION = Collections.unmodifiableCollection( new ArrayList<UserClass>() );
73      private static final Collection<ACITuple> EMPTY_ACI_TUPLE_COLLECTION = Collections.unmodifiableCollection( new ArrayList<ACITuple>() );
74      private static final Set<MicroOperation> EMPTY_MICRO_OPERATION_SET = Collections.unmodifiableSet( new HashSet<MicroOperation>() );
75  
76      private static LdapDN GROUP_NAME;
77      private static LdapDN USER_NAME;
78      private static Set<LdapDN> USER_NAMES = new HashSet<LdapDN>();
79      private static Set<LdapDN> GROUP_NAMES = new HashSet<LdapDN>();
80  
81      private static final AttributeTypeRegistry ATTR_TYPE_REGISTRY_A = new DummyAttributeTypeRegistry( false );
82      private static final AttributeTypeRegistry ATTR_TYPE_REGISTRY_B = new DummyAttributeTypeRegistry( true );
83      private static OidRegistry OID_REGISTRY;
84  
85      private static RelatedProtectedItemFilter filterA;
86      private static RelatedProtectedItemFilter filterB;
87  
88      /** A reference to the directory service */
89      private static DirectoryService service;
90      
91      /** The CN attribute Type */
92      private static AttributeType CN_AT;
93  
94      /** The SN attribute Type */
95      private static AttributeType SN_AT;
96  
97      
98      @BeforeClass public static void setup() throws NamingException
99      {
100         service = new DefaultDirectoryService();
101         OID_REGISTRY = service.getRegistries().getOidRegistry();
102 
103         GROUP_NAME = new LdapDN( "ou=test,ou=groups,ou=system" );
104         USER_NAME = new LdapDN( "ou=test, ou=users, ou=system" );
105 
106         filterA = new RelatedProtectedItemFilter( new RefinementEvaluator( new RefinementLeafEvaluator(
107             OID_REGISTRY ) ), new ExpressionEvaluator( OID_REGISTRY, ATTR_TYPE_REGISTRY_A ), OID_REGISTRY, ATTR_TYPE_REGISTRY_A );
108 
109         filterB = new RelatedProtectedItemFilter( new RefinementEvaluator( new RefinementLeafEvaluator(
110             OID_REGISTRY ) ), new ExpressionEvaluator( OID_REGISTRY, ATTR_TYPE_REGISTRY_B ), OID_REGISTRY, ATTR_TYPE_REGISTRY_B );
111 
112         USER_NAMES.add( USER_NAME );
113         GROUP_NAMES.add( GROUP_NAME );
114         CN_AT = service.getRegistries().getAttributeTypeRegistry().lookup( "cn" );
115         SN_AT = service.getRegistries().getAttributeTypeRegistry().lookup( "sn" );
116     }
117 
118     
119     private Collection<Attribute> convert( Collection<ServerAttribute> attributes )
120     {
121         Set<Attribute> jndiAttributes = new HashSet<Attribute>();
122         
123         for ( ServerAttribute attribute:attributes )
124         {
125             jndiAttributes.add( ServerEntryUtils.toBasicAttribute( attribute ) );
126         }
127         
128         return jndiAttributes;
129     }
130 
131     @Test public void testZeroTuple() throws Exception
132     {
133         assertEquals( 0, filterA.filter( null, EMPTY_ACI_TUPLE_COLLECTION, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null,
134             null, null, null, null, null, null, null, null, null ).size() );
135     }
136 
137 
138     @Test public void testEntry() throws Exception
139     {
140         Collection<ACITuple> tuples = getTuples( ProtectedItem.ENTRY );
141 
142         assertEquals( 1, filterA.filter( null, tuples, OperationScope.ENTRY, null, null, null, null,
143             AuthenticationLevel.NONE, null, "ou", null, null, null, null ).size() );
144     }
145 
146 
147     @Test public void testAllUserAttributeTypes() throws Exception
148     {
149         Collection<ACITuple> tuples = getTuples( ProtectedItem.ALL_USER_ATTRIBUTE_TYPES );
150 
151         // Test wrong scope
152         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ENTRY, null, null, USER_NAME, null, null, null,
153             "cn", null, null, null, null ).size() );
154 
155         tuples = getTuples( ProtectedItem.ALL_USER_ATTRIBUTE_TYPES );
156 
157         assertEquals( 1, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE, null, null, USER_NAME, null,
158             null, null, "cn", null, null, null, null ).size() );
159     }
160 
161 
162     @Test public void testAllUserAttributeTypesAndValues() throws Exception
163     {
164         Collection<ACITuple> tuples = getTuples( ProtectedItem.ALL_USER_ATTRIBUTE_TYPES_AND_VALUES );
165 
166         // Test wrong scope
167         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ENTRY, null, null, USER_NAME, null, null, null,
168             "cn", null, null, null, null ).size() );
169 
170         tuples = getTuples( ProtectedItem.ALL_USER_ATTRIBUTE_TYPES_AND_VALUES );
171 
172         assertEquals( 1, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE, null, null, USER_NAME, null,
173             null, null, "cn", null, null, null, null ).size() );
174     }
175 
176 
177     @Test public void testAllAttributeValues() throws Exception
178     {
179         Collection<String> attrTypes = new ArrayList<String>();
180         attrTypes.add( "cn" );
181         Collection<ACITuple> tuples = getTuples( new ProtectedItem.AllAttributeValues( attrTypes ) );
182 
183         // Test wrong scope
184         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ENTRY, null, null, USER_NAME, null, null, null,
185             "cn", null, null, null, null ).size() );
186 
187         tuples = getTuples( new ProtectedItem.AllAttributeValues( attrTypes ) );
188 
189         assertEquals( 1, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, USER_NAME, null,
190             null, null, "cn", null, null, null, null ).size() );
191 
192         assertEquals( 0, filterB.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, USER_NAME, null,
193             null, null, "sn", null, null, null, null ).size() );
194     }
195 
196 
197     @Test public void testAttributeType() throws Exception
198     {
199         Collection<String> attrTypes = new ArrayList<String>();
200         attrTypes.add( "cn" );
201         Collection<ACITuple> tuples = getTuples( new ProtectedItem.AttributeType( attrTypes ) );
202 
203         // Test wrong scope
204         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ENTRY, null, null, USER_NAME, null, null, null,
205             "cn", null, null, null, null ).size() );
206 
207         tuples = getTuples( new ProtectedItem.AttributeType( attrTypes ) );
208 
209         assertEquals( 1, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE, null, null, USER_NAME, null,
210             null, null, "cn", null, null, null, null ).size() );
211 
212         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE, null, null, USER_NAME, null,
213             null, null, "sn", null, null, null, null ).size() );
214     }
215 
216 
217     @Test public void testAttributeValue() throws Exception
218     {
219         Collection<ServerAttribute> attributes = new ArrayList<ServerAttribute>();
220         attributes.add( new DefaultServerAttribute( "cn", CN_AT, "valueA" ) );
221         Collection<ACITuple> tuples = getTuples( new ProtectedItem.AttributeValue( convert( attributes ) ) );
222 
223         // Test wrong scope
224         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ENTRY, null, null, USER_NAME, null, null, null,
225             "cn", null, null, null, null ).size() );
226         tuples = getTuples( new ProtectedItem.AttributeValue( convert( attributes )  ) );
227         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE, null, null, USER_NAME, null,
228             null, null, "cn", null, null, null, null ).size() );
229 
230         tuples = getTuples( new ProtectedItem.AttributeValue( convert( attributes )  ) );
231 
232         assertEquals( 1, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, USER_NAME,
233             null, null, null, "cn", new ClientStringValue( "valueA" ), null, null, null ).size() );
234 
235         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, USER_NAME,
236             null, null, null, "cn", new ClientStringValue( "valueB" ), null, null, null ).size() );
237 
238         tuples = getTuples( new ProtectedItem.AttributeValue( convert( attributes )  ) );
239 
240         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, USER_NAME,
241             null, null, null, "sn", new ClientStringValue( "valueA" ), null, null, null ).size() );
242     }
243 
244 
245     public void testClasses() throws Exception
246     {
247         // TODO I don't know how to test with Refinement yet.
248     }
249 
250 
251     @Test public void testMaxImmSub() throws Exception
252     {
253         Collection<ACITuple> tuples = getTuples( new ProtectedItem.MaxImmSub( 2 ) );
254 
255         // Should always retain tuples.
256         assertEquals( 1, filterA.filter( null, tuples, OperationScope.ENTRY, null, null, USER_NAME, null, null, null,
257             "cn", null, null, null, null ).size() );
258     }
259 
260 
261     @Test public void testMaxValueCount() throws Exception
262     {
263         Collection<MaxValueCountItem> mvcItems = new ArrayList<MaxValueCountItem>();
264         mvcItems.add( new MaxValueCountItem( "cn", 3 ) );
265         Collection<ACITuple> tuples = getTuples( new ProtectedItem.MaxValueCount( mvcItems ) );
266 
267         // Test wrong scope
268         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ENTRY, null, null, USER_NAME, null, null, null,
269             "cn", null, null, null, null ).size() );
270         tuples = getTuples( new ProtectedItem.MaxValueCount( mvcItems ) );
271         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE, null, null, USER_NAME, null,
272             null, null, "cn", null, null, null, null ).size() );
273 
274         tuples = getTuples( new ProtectedItem.MaxValueCount( mvcItems ) );
275 
276         assertEquals( 1, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, USER_NAME,
277             null, null, null, "cn", null, null, null, null ).size() );
278 
279         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, USER_NAME,
280             null, null, null, "sn", null, null, null, null ).size() );
281     }
282 
283 
284     /* this test requires a real registry with real values or the dummy registry
285      * needs to be altered to contain some usable mock data.  This is a result of
286      * using the registry now in this operation.    
287      *
288     public void testRangeOfValues() throws Exception
289     {
290         ServerEntry entry = new DefaultServerEntry( service.getRegistries(), USER_NAME );
291         entry.put( "cn", "valueA" );
292         Collection<ACITuple> tuples = getTuples( new ProtectedItem.RangeOfValues( new PresenceNode( "cn" ) ) );
293 
294         Assert.assertEquals( 1, filterA.filter( tuples, OperationScope.ENTRY, null, null, USER_NAME, null, null,
295             new LdapDN( "ou=testEntry" ), null, null, entry, null ).size() );
296 
297         entry.remove( "cn" );
298         Assert.assertEquals( 0, filterA.filter( service.getRegistries(), tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, USER_NAME,
299             null, null, new LdapDN( "ou=testEntry" ), null, null, entry, null ).size() );
300     }
301     */
302 
303 
304     @Test public void testRestrictedBy() throws Exception
305     {
306         Collection<RestrictedByItem> rbItems = new ArrayList<RestrictedByItem>();
307         rbItems.add( new RestrictedByItem( "cn", "sn" ) );
308         Collection<ACITuple> tuples = getTuples( new ProtectedItem.RestrictedBy( rbItems ) );
309 
310         // Test wrong scope
311         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ENTRY, null, null, USER_NAME, null, null, null,
312             "cn", null, null, null, null ).size() );
313         tuples = getTuples( new ProtectedItem.RestrictedBy( rbItems ) );
314         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE, null, null, USER_NAME, null,
315             null, null, "cn", null, null, null, null ).size() );
316 
317         tuples = getTuples( new ProtectedItem.RestrictedBy( rbItems ) );
318 
319         assertEquals( 1, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, USER_NAME,
320             null, null, null, "cn", null, null, null, null ).size() );
321 
322         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, USER_NAME,
323             null, null, null, "sn", null, null, null, null ).size() );
324     }
325 
326 
327     @Test public void testSelfValue() throws Exception
328     {
329         Collection<String> attrTypes = new ArrayList<String>();
330         attrTypes.add( "cn" );
331         Collection<ACITuple> tuples = getTuples( new ProtectedItem.SelfValue( attrTypes ) );
332 
333         ServerEntry entry = new DefaultServerEntry( service.getRegistries(), USER_NAME );
334         entry.put( "cn", USER_NAME.toNormName() );
335 
336         // Test wrong scope
337         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ENTRY, null, null, USER_NAME, null, null, null,
338             "cn", null, entry, null, null ).size() );
339 
340         tuples = getTuples( new ProtectedItem.SelfValue( attrTypes ) );
341 
342         assertEquals( 1, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, USER_NAME,
343             null, null, null, "cn", null, entry, null, null ).size() );
344 
345         entry.removeAttributes( "cn" );
346         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, USER_NAME,
347             null, null, null, "cn", null, entry, null, null ).size() );
348 
349         tuples = getTuples( new ProtectedItem.SelfValue( attrTypes ) );
350         assertEquals( 0, filterA.filter( null, tuples, OperationScope.ATTRIBUTE_TYPE_AND_VALUE, null, null, USER_NAME,
351             null, null, null, "sn", null, entry, null, null ).size() );
352     }
353 
354 
355     private static Collection<ACITuple> getTuples( ProtectedItem protectedItem )
356     {
357         Collection<ProtectedItem> protectedItems = new ArrayList<ProtectedItem>();
358         protectedItems.add( protectedItem );
359 
360         Collection<ACITuple> tuples = new ArrayList<ACITuple>();
361         tuples.add( new ACITuple( EMPTY_USER_CLASS_COLLECTION, AuthenticationLevel.NONE, protectedItems, EMPTY_MICRO_OPERATION_SET, true, 0 ) );
362 
363         return tuples;
364     }
365 }