blob: 8a1edb65d03991e7ce4f9d1c675478fdab5172be [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.server.core.authz;
import static org.apache.directory.server.core.authz.AutzIntegUtils.addUserToGroup;
import static org.apache.directory.server.core.authz.AutzIntegUtils.changePresciptiveACI;
import static org.apache.directory.server.core.authz.AutzIntegUtils.createAccessControlSubentry;
import static org.apache.directory.server.core.authz.AutzIntegUtils.createGroup;
import static org.apache.directory.server.core.authz.AutzIntegUtils.createUser;
import static org.apache.directory.server.core.authz.AutzIntegUtils.deleteAccessControlSubentry;
import static org.apache.directory.server.core.authz.AutzIntegUtils.getAdminConnection;
import static org.apache.directory.server.core.authz.AutzIntegUtils.getConnectionAs;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.server.core.annotations.CreateDS;
import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
import org.apache.directory.server.core.integ.FrameworkRunner;
import org.apache.directory.server.core.integ.IntegrationUtils;
import org.apache.directory.shared.ldap.constants.SchemaConstants;
import org.apache.directory.shared.ldap.entry.DefaultEntry;
import org.apache.directory.shared.ldap.entry.DefaultEntryAttribute;
import org.apache.directory.shared.ldap.entry.DefaultModification;
import org.apache.directory.shared.ldap.entry.Entry;
import org.apache.directory.shared.ldap.entry.EntryAttribute;
import org.apache.directory.shared.ldap.entry.Modification;
import org.apache.directory.shared.ldap.entry.ModificationOperation;
import org.apache.directory.shared.ldap.message.ModifyRequest;
import org.apache.directory.shared.ldap.message.ModifyRequestImpl;
import org.apache.directory.shared.ldap.message.ModifyResponse;
import org.apache.directory.shared.ldap.message.ResultCodeEnum;
import org.apache.directory.shared.ldap.name.DN;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Tests whether or not authorization around entry modify operations work properly.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
@RunWith(FrameworkRunner.class)
@CreateDS(enableAccessControl = true, name = "ModifyAuthorizationIT")
public class ModifyAuthorizationIT extends AbstractLdapTestUnit
{
@Before
public void setService()
{
AutzIntegUtils.service = service;
}
@After
public void closeConnections()
{
IntegrationUtils.closeConnections();
}
/**
* Checks if an attribute of a simple entry (an organizationalUnit) with an RDN
* relative to ou=system can be modified by a specific non-admin user. If a
* permission exception is encountered it is caught and false is returned,
* otherwise true is returned. The entry is deleted after being created just in case
* subsequent calls to this method are made in the same test case: the admin account
* is used to add and delete this test entry so permissions to add and delete are not
* required to test the modify operation by the user.
*
* @param uid the unique identifier for the user (presumed to exist under ou=users,ou=system)
* @param password the password of this user
* @param entryRdn the relative DN, relative to ou=system where entry is created
* for modification test
* @param mods the modifications to make to the entry
* @return true if the modifications can be made by the user at the specified location,
* false otherwise.
* @throws javax.naming.Exception if there are problems conducting the test
*/
public boolean checkCanModifyAs( String uid, String password, String entryRdn, Modification[] mods )
throws Exception
{
DN entryDN = new DN( entryRdn + ",ou=system" );
boolean result;
// create the entry with the telephoneNumber attribute to compare
Entry testEntry = new DefaultEntry( entryDN );
testEntry.add( SchemaConstants.OBJECT_CLASS_AT, "organizationalUnit" );
testEntry.add( SchemaConstants.OU_AT, "testou" );
testEntry.add( "telephoneNumber", "867-5309" ); // jenny don't change your number
LdapConnection adminConnection = getAdminConnection();
// create the entry as admin
adminConnection.add( testEntry );
DN userName = new DN( "uid=" + uid + ",ou=users,ou=system" );
// compare the telephone numbers
LdapConnection userConnection = getConnectionAs( userName, password );
// modify the entry as the user
ModifyRequest modReq = new ModifyRequestImpl();
modReq.setName( entryDN );
for ( Modification modification : mods )
{
modReq.addModification( modification );
}
ModifyResponse resp = userConnection.modify( modReq );
if ( resp.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
{
result = true;
}
else
{
result = false;
}
// let's clean up
adminConnection.delete( entryDN );
return result;
}
/**
* Checks if an attribute of a simple entry (an organizationalUnit) with an RDN
* relative to ou=system can be modified by a specific non-admin user. If a
* permission exception is encountered it is caught and false is returned,
* otherwise true is returned. The entry is deleted after being created just in case
* subsequent calls to this method are made in the same test case: the admin account
* is used to add and delete this test entry so permissions to add and delete are not
* required to test the modify operation by the user.
*
* @param uid the unique identifier for the user (presumed to exist under ou=users,ou=system)
* @param password the password of this user
* @param entryRdn the relative DN, relative to ou=system where entry is created
* for modification test
* @param mods the attributes to modify in the entry
* @param modOp the modification operation to use for all attributes
* @return true if the modifications can be made by the user at the specified location,
* false otherwise.
* @throws javax.naming.Exception if there are problems conducting the test
*/
public boolean checkCanModifyAs( String uid, String password, String entryRdn, ModificationOperation modOp,
EntryAttribute attr ) throws Exception
{
DN entryDN = new DN( entryRdn + ",ou=system" );
boolean result;
// create the entry with the telephoneNumber attribute to compare
Entry testEntry = new DefaultEntry( entryDN );
testEntry.add( SchemaConstants.OBJECT_CLASS_AT, "organizationalUnit" );
testEntry.add( SchemaConstants.OU_AT, "testou" );
testEntry.add( "telephoneNumber", "867-5309" ); // jenny don't change your number
LdapConnection adminConnection = getAdminConnection();
adminConnection.add( testEntry );
// create the entry as admin
DN userName = new DN( "uid=" + uid + ",ou=users,ou=system" );
// modify the entry as the user
LdapConnection userConnection = getConnectionAs( userName, password );
ModifyRequest modReq = new ModifyRequestImpl();
modReq.setName( entryDN );
modReq.addModification( attr, modOp );
ModifyResponse resp = userConnection.modify( modReq );
if ( resp.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
{
result = true;
}
else
{
result = false;
}
// let's clean up
adminConnection.delete( entryDN );
return result;
}
/**
* Checks if a user can modify an attribute of their own entry. Users are
* presumed to reside under ou=users,ou=system. If a permission exception is
* encountered it is caught and false is returned, otherwise true is returned.
*
* @param uid the unique identifier for the user (presumed to exist under ou=users,ou=system)
* @param password the password of this user
* @param mods the attributes to modify in the entry
* @return true if the modifications can be made by the user his/her own entry,
* false otherwise.
* @throws javax.naming.Exception if there are problems conducting the test
*/
public boolean checkCanSelfModify( String uid, String password, Modification[] mods ) throws Exception
{
// modify the entry as the user
DN userDN = new DN( "uid=" + uid + ",ou=users,ou=system" );
LdapConnection connection = getConnectionAs( userDN, password );
ModifyRequest modReq = new ModifyRequestImpl();
modReq.setName( userDN );
for ( Modification modification : mods )
{
modReq.addModification( modification );
}
ModifyResponse resp = connection.modify( modReq );
return resp.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS;
}
/**
* Converts a set of attributes and a modification operation type into a MoficationItem array.
*
* @param modOp the modification operation to perform
* @param changes the modifications to the attribute
* @return the array of modification items represting the changes
* @throws Exception if there are problems accessing attributes
*/
private Modification[] toItems( ModificationOperation modOp, EntryAttribute... attrs ) throws Exception
{
Modification[] mods = new Modification[attrs.length];
for ( int i = 0; i < attrs.length; i++ )
{
EntryAttribute ea = attrs[i];
mods[i] = new DefaultModification( modOp, ea );
}
return mods;
}
@Test
public void testSelfModification() throws Exception
{
// ----------------------------------------------------------------------------------
// Modify with Attribute Addition
// ----------------------------------------------------------------------------------
// create the non-admin user
createUser( "billyd", "billyd" );
// create the password modification
Modification[] mods = toItems( ModificationOperation.REPLACE_ATTRIBUTE, new DefaultEntryAttribute(
"userPassword", "williams" ) );
// try a modify operation which should fail without any ACI
assertFalse( checkCanSelfModify( "billyd", "billyd", mods ) );
// Gives grantModify, and grantRead perm to all users in the Administrators group for
// entries and all attribute types and values
createAccessControlSubentry( "selfModifyUserPassword", "{ " + " identificationTag \"addAci\", "
+ " precedence 14, " + " authenticationLevel none, " + " itemOrUserFirst userFirst: " + " { "
+ " userClasses { thisEntry }, " + " userPermissions " + " { " + " { "
+ " protectedItems {entry}, " + " grantsAndDenials { grantModify, grantBrowse, grantRead } "
+ " }, " + " { " + " protectedItems {allAttributeValues {userPassword}}, "
+ " grantsAndDenials { grantAdd, grantRemove } " + " } " + " } " + " } " + "}" );
// try a modify operation which should succeed with ACI
assertTrue( checkCanSelfModify( "billyd", "billyd", mods ) );
deleteAccessControlSubentry( "selfModifyUserPassword" );
}
/**
* Checks to make sure group membership based userClass works for modify operations.
*
* @throws javax.naming.Exception if the test encounters an error
*/
@Test
public void testGrantModifyByTestGroup() throws Exception
{
// ----------------------------------------------------------------------------------
// Modify with Attribute Addition
// ----------------------------------------------------------------------------------
// create the add modifications
EntryAttribute attr = new DefaultEntryAttribute( "registeredAddress", "100 Park Ave." );
Modification[] mods = toItems( ModificationOperation.ADD_ATTRIBUTE, attr );
// create the non-admin user
createUser( "billyd", "billyd" );
createGroup( "TestGroup" );
// try a modify operation which should fail without any ACI
assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
// Gives grantModify, and grantRead perm to all users in the TestGroup group for
// entries and all attribute types and values
createAccessControlSubentry( "administratorModifyAdd", "{ " + " identificationTag \"addAci\", "
+ " precedence 14, " + " authenticationLevel none, " + " itemOrUserFirst userFirst: " + " { "
+ " userClasses { userGroup { \"cn=TestGroup,ou=groups,ou=system\" } }, " + " userPermissions "
+ " { " + " { " + " protectedItems {entry}, "
+ " grantsAndDenials { grantModify, grantBrowse } " + " }, " + " { "
+ " protectedItems " + " {" + " attributeType {registeredAddress}, "
+ " allAttributeValues {registeredAddress}" + " }, "
+ " grantsAndDenials { grantAdd } " + " } " + " } " + " } " + "}" );
// see if we can now add that test entry which we could not before
// add op should still fail since billd is not in the admin group
assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
// now add billyd to the TestGroup group and try again
addUserToGroup( "billyd", "TestGroup" );
// try a modify operation which should succeed with ACI and group membership change
assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
deleteAccessControlSubentry( "administratorModifyAdd" );
// ----------------------------------------------------------------------------------
// Modify with Attribute Removal
// ----------------------------------------------------------------------------------
// now let's test to see if we can perform a modify with a delete op
mods = toItems( ModificationOperation.REMOVE_ATTRIBUTE, new DefaultEntryAttribute( "telephoneNumber",
"867-5309" ) );
// make sure we cannot remove the telephone number from the test entry
assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
// Gives grantModify, and grantRead perm to all users in the TestGroup group for
// entries and all attribute types and values
createAccessControlSubentry( "administratorModifyRemove", "{ " + " identificationTag \"addAci\", "
+ " precedence 14, " + " authenticationLevel none, " + " itemOrUserFirst userFirst: " + " { "
+ " userClasses { userGroup { \"cn=TestGroup,ou=groups,ou=system\" } }, " + " userPermissions "
+ " { " + " { " + " protectedItems {entry}, "
+ " grantsAndDenials { grantModify, grantBrowse } " + " }, " + " { "
+ " protectedItems " + " {" + " attributeType {telephoneNumber}, "
+ " allAttributeValues {telephoneNumber}" + " }, "
+ " grantsAndDenials { grantRemove } " + " } " + " } " + " } " + "}" );
// try a modify operation which should succeed with ACI and group membership change
assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
deleteAccessControlSubentry( "administratorModifyRemove" );
// ----------------------------------------------------------------------------------
// Modify with Attribute Replace (requires both grantRemove and grantAdd on attrs)
// ----------------------------------------------------------------------------------
// now let's test to see if we can perform a modify with a delete op
mods = toItems( ModificationOperation.REPLACE_ATTRIBUTE, new DefaultEntryAttribute( "telephoneNumber",
"867-5309" ) );
// make sure we cannot remove the telephone number from the test entry
assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
// Gives grantModify, and grantRead perm to all users in the TestGroup group for
// entries and all attribute types and values
createAccessControlSubentry( "administratorModifyReplace", "{ " + " identificationTag \"addAci\", "
+ " precedence 14, " + " authenticationLevel none, " + " itemOrUserFirst userFirst: " + " { "
+ " userClasses { userGroup { \"cn=TestGroup,ou=groups,ou=system\" } }, " + " userPermissions "
+ " { " + " { " + " protectedItems {entry}, "
+ " grantsAndDenials { grantModify, grantBrowse } " + " }, " + " { "
+ " protectedItems " + " {" + " attributeType {registeredAddress}, "
+ " allAttributeValues {telephoneNumber}" + " }, "
+ " grantsAndDenials { grantAdd, grantRemove } " + " } " + " } " + " } " + "}" );
// try a modify operation which should succeed with ACI and group membership change
assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
deleteAccessControlSubentry( "administratorModifyReplace" );
/* =================================================================================
* DO IT ALL OVER AGAIN BUT USE THE OTHER MODIFY METHOD
* ================================================================================= */
// ----------------------------------------------------------------------------------
// Modify with Attribute Addition
// ----------------------------------------------------------------------------------
// create the add modifications
EntryAttribute changes = new DefaultEntryAttribute( "registeredAddress", "100 Park Ave." );
// try a modify operation which should fail without any ACI
assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", ModificationOperation.ADD_ATTRIBUTE, changes ) );
// Gives grantModify, and grantRead perm to all users in the TestGroup group for
// entries and all attribute types and values
createAccessControlSubentry( "administratorModifyAdd", "{ " + " identificationTag \"addAci\", "
+ " precedence 14, " + " authenticationLevel none, " + " itemOrUserFirst userFirst: " + " { "
+ " userClasses { userGroup { \"cn=TestGroup,ou=groups,ou=system\" } }, " + " userPermissions "
+ " { " + " { " + " protectedItems {entry}, "
+ " grantsAndDenials { grantModify, grantBrowse } " + " }, " + " { "
+ " protectedItems " + " {" + " attributeType {registeredAddress}, "
+ " allAttributeValues {registeredAddress}" + " }, "
+ " grantsAndDenials { grantAdd } " + " } " + " } " + " } " + "}" );
// try a modify operation which should succeed with ACI and group membership change
assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", ModificationOperation.ADD_ATTRIBUTE, changes ) );
deleteAccessControlSubentry( "administratorModifyAdd" );
// ----------------------------------------------------------------------------------
// Modify with Attribute Removal
// ----------------------------------------------------------------------------------
// now let's test to see if we can perform a modify with a delete op
changes = new DefaultEntryAttribute( "telephoneNumber", "867-5309" );
// make sure we cannot remove the telephone number from the test entry
assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", ModificationOperation.REMOVE_ATTRIBUTE, changes ) );
// Gives grantModify, and grantRead perm to all users in the TestGroup group for
// entries and all attribute types and values
createAccessControlSubentry( "administratorModifyRemove", "{ " + " identificationTag \"addAci\", "
+ " precedence 14, " + " authenticationLevel none, " + " itemOrUserFirst userFirst: " + " { "
+ " userClasses { userGroup { \"cn=TestGroup,ou=groups,ou=system\" } }, " + " userPermissions "
+ " { " + " { " + " protectedItems {entry}, "
+ " grantsAndDenials { grantModify, grantBrowse } " + " }, " + " { "
+ " protectedItems " + " {" + " attributeType {telephoneNumber}, "
+ " allAttributeValues {telephoneNumber}" + " }, "
+ " grantsAndDenials { grantRemove } " + " } " + " } " + " } " + "}" );
// try a modify operation which should succeed with ACI and group membership change
assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", ModificationOperation.REMOVE_ATTRIBUTE, changes ) );
deleteAccessControlSubentry( "administratorModifyRemove" );
// ----------------------------------------------------------------------------------
// Modify with Attribute Replace (requires both grantRemove and grantAdd on attrs)
// ----------------------------------------------------------------------------------
// now let's test to see if we can perform a modify with a delete op
changes = new DefaultEntryAttribute( "telephoneNumber", "867-5309" );
// make sure we cannot remove the telephone number from the test entry
assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", ModificationOperation.REPLACE_ATTRIBUTE,
changes ) );
// Gives grantModify, and grantRead perm to all users in the TestGroup group for
// entries and all attribute types and values
createAccessControlSubentry( "administratorModifyReplace", "{ " + " identificationTag \"addAci\", "
+ " precedence 14, " + " authenticationLevel none, " + " itemOrUserFirst userFirst: " + " { "
+ " userClasses { userGroup { \"cn=TestGroup,ou=groups,ou=system\" } }, " + " userPermissions "
+ " { " + " { " + " protectedItems {entry}, "
+ " grantsAndDenials { grantModify, grantBrowse } " + " }, " + " { "
+ " protectedItems " + " {" + " attributeType {registeredAddress}, "
+ " allAttributeValues {telephoneNumber}" + " }, "
+ " grantsAndDenials { grantAdd, grantRemove } " + " } " + " } " + " } " + "}" );
// try a modify operation which should succeed with ACI and group membership change
assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", ModificationOperation.REPLACE_ATTRIBUTE, changes ) );
deleteAccessControlSubentry( "administratorModifyReplace" );
}
/**
* Checks to make sure name based userClass works for modify operations.
*
* @throws javax.naming.Exception if the test encounters an error
*/
@Test
public void testGrantModifyByName() throws Exception
{
Modification[] mods = toItems( ModificationOperation.ADD_ATTRIBUTE, new DefaultEntryAttribute(
"telephoneNumber", "012-3456" ) );
// create the non-admin user
createUser( "billyd", "billyd" );
// try an modify operation which should fail without any ACI
assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
// now add a subentry that enables user billyd to modify an entry below ou=system
createAccessControlSubentry( "billydAdd", "{ " + " identificationTag \"addAci\", " + " precedence 14, "
+ " authenticationLevel none, " + " itemOrUserFirst userFirst: " + " { "
+ " userClasses { name { \"uid=billyd,ou=users,ou=system\" } }, " + " userPermissions " + " { "
+ " { " + " protectedItems {entry}, "
+ " grantsAndDenials { grantModify, grantRead, grantBrowse } " + " }, " + " { "
+ " protectedItems {allUserAttributeTypesAndValues}, "
+ " grantsAndDenials { grantAdd, grantRead, grantRemove } " + " } " + " } " + " } " + "}" );
// should work now that billyd is authorized by name
assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
}
/**
* Checks to make sure subtree based userClass works for modify operations.
*
* @throws javax.naming.Exception if the test encounters an error
*/
@Test
public void testGrantModifyBySubtree() throws Exception
{
Modification[] mods = toItems( ModificationOperation.ADD_ATTRIBUTE, new DefaultEntryAttribute(
"telephoneNumber", "012-345678" ) );
// create the non-admin user
createUser( "billyd", "billyd" );
// try a modify operation which should fail without any ACI
assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
// now add a subentry that enables user billyd to modify an entry below ou=system
createAccessControlSubentry( "billyAddBySubtree", "{ " + " identificationTag \"addAci\", "
+ " precedence 14, " + " authenticationLevel none, " + " itemOrUserFirst userFirst: " + " { "
+ " userClasses " + " {" + " subtree { { base \"ou=users,ou=system\" } } " + " }, "
+ " userPermissions " + " { " + " { " + " protectedItems {entry}, "
+ " grantsAndDenials { grantModify, grantRead, grantBrowse } " + " }, " + " { "
+ " protectedItems {allUserAttributeTypesAndValues}, "
+ " grantsAndDenials { grantAdd, grantRead, grantRemove } " + " } " + " } " + " } " + "}" );
//
// should work now that billyd is authorized by the subtree userClass
assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
}
//
//
/**
* Checks to make sure <b>allUsers</b> userClass works for modify operations.
*
* @throws javax.naming.Exception if the test encounters an error
*/
@Test
public void testGrantModifyAllUsers() throws Exception
{
Modification[] mods = toItems( ModificationOperation.ADD_ATTRIBUTE, new DefaultEntryAttribute(
"telephoneNumber", "001-012345" ) );
// create the non-admin user
createUser( "billyd", "billyd" );
// try an add operation which should fail without any ACI
assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
// now add a subentry that enables anyone to add an entry below ou=system
createAccessControlSubentry( "anybodyAdd", "{ " + " identificationTag \"addAci\", " + " precedence 14, "
+ " authenticationLevel none, " + " itemOrUserFirst userFirst: " + " { "
+ " userClasses { allUsers }, " + " userPermissions " + " { " + " { "
+ " protectedItems {entry}, " + " grantsAndDenials { grantModify, grantRead, grantBrowse } "
+ " }, " + " { " + " protectedItems {allUserAttributeTypesAndValues}, "
+ " grantsAndDenials { grantAdd, grantRead, grantRemove } " + " } " + " } " + " } " + "}" );
// see if we can now modify that test entry's number which we could not before
// should work with billyd now that all users are authorized
assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
}
@Test
public void testPresciptiveACIModification() throws Exception
{
Modification[] mods = toItems( ModificationOperation.ADD_ATTRIBUTE, new DefaultEntryAttribute(
"registeredAddress", "100 Park Ave." ) );
createUser( "billyd", "billyd" );
createAccessControlSubentry( "modifyACI", "{ " + " identificationTag \"modifyAci\", " + " precedence 14, "
+ " authenticationLevel none, " + " itemOrUserFirst userFirst: " + " { "
+ " userClasses { allUsers }, " + " userPermissions " + " { " + " { "
+ " protectedItems {entry, allUserAttributeTypesAndValues}, "
+ " grantsAndDenials { grantModify, grantBrowse, grantAdd, grantRemove } " + " } " + " } "
+ " } " + "}" );
assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
mods = toItems( ModificationOperation.REPLACE_ATTRIBUTE, new DefaultEntryAttribute( "registeredAddress",
"200 Park Ave." ) );
changePresciptiveACI( "modifyACI", "{ " + " identificationTag \"modifyAci\", " + " precedence 14, "
+ " authenticationLevel none, " + " itemOrUserFirst userFirst: " + " { "
+ " userClasses { allUsers }, " + " userPermissions " + " { " + " { "
+ " protectedItems {entry, allUserAttributeTypesAndValues}, "
+ " grantsAndDenials { denyModify } " + " } " + " } " + " } " + "}" );
assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
deleteAccessControlSubentry( "modifyACI" );
}
@Test
public void testMaxValueCountProtectedItem() throws Exception
{
createUser( "billyd", "billyd" );
createAccessControlSubentry( "mvcACI", "{" + " identificationTag \"mvcACI\"," + " precedence 10,"
+ " authenticationLevel simple," + " itemOrUserFirst userFirst:" + " {"
+ " userClasses { allUsers }," + " userPermissions" + " {" + " {"
+ " protectedItems { entry }," + " grantsAndDenials { grantModify, grantBrowse }"
+ " }," + " {" + " protectedItems" + " {"
+ " attributeType { description }," + " allAttributeValues { description },"
+ " maxValueCount { { type description, maxCount 1 } }" + " } ,"
+ " grantsAndDenials { grantRemove, grantAdd }" + " }" + " }" + " }" + "}" );
Modification[] mods = toItems( ModificationOperation.ADD_ATTRIBUTE, new DefaultEntryAttribute( "description",
"description 1" ) );
assertTrue( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
EntryAttribute attr = new DefaultEntryAttribute( "description" );
attr.add( "description 1" );
attr.add( "description 2" );
mods = toItems( ModificationOperation.ADD_ATTRIBUTE, attr );
assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
mods = toItems( ModificationOperation.REPLACE_ATTRIBUTE, attr );
assertFalse( checkCanModifyAs( "billyd", "billyd", "ou=testou", mods ) );
}
}