summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2010-10-18 14:53:32 -0400
committerSimo Sorce <ssorce@redhat.com>2010-10-28 08:39:10 -0400
commit70a57924c8e265df1e97b7f0be1adf8da802fbfd (patch)
tree40731984730ee48d8161e0cca67c34581e55d246
parent93290c8a72bcd5c4ab34eedf0ec443469b36f8c1 (diff)
downloadfreeipa-70a57924c8e265df1e97b7f0be1adf8da802fbfd.tar.gz
freeipa-70a57924c8e265df1e97b7f0be1adf8da802fbfd.tar.xz
freeipa-70a57924c8e265df1e97b7f0be1adf8da802fbfd.zip
Allow RDN changes for users, groups, rolegroups and taskgroups.
To do a change right now you have to perform a setattr like: ipa user-mod --setattr uid=newuser olduser The RDN change is performed before the rest of the mods. If the RDN change is the only change done then the EmptyModlist that update_entry() throws is ignored. ticket 323
-rw-r--r--ipalib/plugins/baseldap.py18
-rw-r--r--ipalib/plugins/group.py1
-rw-r--r--ipalib/plugins/rolegroup.py1
-rw-r--r--ipalib/plugins/taskgroup.py1
-rw-r--r--ipalib/plugins/user.py1
-rw-r--r--ipaserver/plugins/ldap2.py2
-rw-r--r--tests/test_xmlrpc/test_group_plugin.py40
-rw-r--r--tests/test_xmlrpc/test_host_plugin.py7
-rw-r--r--tests/test_xmlrpc/test_rolegroup_plugin.py36
-rw-r--r--tests/test_xmlrpc/test_taskgroup_plugin.py38
-rw-r--r--tests/test_xmlrpc/test_user_plugin.py51
11 files changed, 196 insertions, 0 deletions
diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py
index 40f9d6a58..78ce8e023 100644
--- a/ipalib/plugins/baseldap.py
+++ b/ipalib/plugins/baseldap.py
@@ -77,6 +77,7 @@ class LDAPObject(Object):
rdn_attribute = ''
uuid_attribute = ''
attribute_members = {}
+ rdnattr = None
container_not_found_msg = _('container entry (%(container)s) not found')
parent_not_found_msg = _('%(parent)s: %(oname)s not found')
@@ -541,14 +542,31 @@ class LDAPUpdate(LDAPQuery, crud.Update):
_check_single_value_attrs(self.params, entry_attrs)
+ rdnupdate = False
try:
+ if self.obj.rdnattr and self.obj.rdnattr in entry_attrs:
+ # RDN change
+ ldap.update_entry_rdn(dn, unicode('%s=%s' % (self.obj.rdnattr,
+ entry_attrs[self.obj.rdnattr])))
+ dn = self.obj.get_dn(entry_attrs[self.obj.rdnattr])
+ del entry_attrs[self.obj.rdnattr]
+ options['rdnupdate'] = True
+ rdnupdate = True
+
ldap.update_entry(dn, entry_attrs, normalize=self.obj.normalize_dn)
except errors.ExecutionError, e:
+ # Exception callbacks will need to test for options['rdnupdate']
+ # to decide what to do. An EmptyModlist in this context doesn't
+ # mean an error occurred, just that there were no other updates to
+ # perform.
try:
self._call_exc_callbacks(
keys, options, e, ldap.update_entry, dn, entry_attrs,
normalize=self.obj.normalize_dn
)
+ except errors.EmptyModlist, e:
+ if not rdnupdate:
+ raise e
except errors.NotFound:
self.obj.handle_not_found(*keys)
diff --git a/ipalib/plugins/group.py b/ipalib/plugins/group.py
index 2b8dc1af1..975915b42 100644
--- a/ipalib/plugins/group.py
+++ b/ipalib/plugins/group.py
@@ -90,6 +90,7 @@ class group(LDAPObject):
'member': ['user', 'group'],
'memberof': ['group', 'netgroup', 'rolegroup', 'taskgroup'],
}
+ rdnattr = 'cn'
label = _('User Groups')
diff --git a/ipalib/plugins/rolegroup.py b/ipalib/plugins/rolegroup.py
index 99560c46c..feffa0d49 100644
--- a/ipalib/plugins/rolegroup.py
+++ b/ipalib/plugins/rolegroup.py
@@ -75,6 +75,7 @@ class rolegroup(LDAPObject):
'member': ['user', 'group', 'host', 'hostgroup'],
'memberof': ['taskgroup'],
}
+ rdnattr='cn'
label = _('Role Groups')
diff --git a/ipalib/plugins/taskgroup.py b/ipalib/plugins/taskgroup.py
index 0ee90474d..11bef4860 100644
--- a/ipalib/plugins/taskgroup.py
+++ b/ipalib/plugins/taskgroup.py
@@ -47,6 +47,7 @@ class taskgroup(LDAPObject):
'member': ['user', 'group', 'rolegroup'],
# FIXME: taskgroup can be member of ???
}
+ rdnattr='cn'
label = _('Task Groups')
diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index 68ca24a0c..fb0da4800 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -72,6 +72,7 @@ class user(LDAPObject):
attribute_members = {
'memberof': ['group', 'netgroup', 'rolegroup', 'taskgroup'],
}
+ rdnattr = 'uid'
label = _('Users')
diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py
index 05292ce7c..4117e47b7 100644
--- a/ipaserver/plugins/ldap2.py
+++ b/ipaserver/plugins/ldap2.py
@@ -681,6 +681,8 @@ class ldap2(CrudBackend, Encoder):
del_old -- delete old RDN value (default True)
"""
dn = self.normalize_dn(dn)
+ if dn.startswith(new_rdn + ","):
+ raise errors.EmptyModlist()
try:
self.conn.rename_s(dn, new_rdn, delold=int(del_old))
except _ldap.LDAPError, e:
diff --git a/tests/test_xmlrpc/test_group_plugin.py b/tests/test_xmlrpc/test_group_plugin.py
index 55bb9cde1..6218ebe59 100644
--- a/tests/test_xmlrpc/test_group_plugin.py
+++ b/tests/test_xmlrpc/test_group_plugin.py
@@ -27,6 +27,7 @@ from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid
group1 = u'testgroup1'
group2 = u'testgroup2'
+renamedgroup1 = u'testgroup'
user1 = u'tuser1'
invalidgroup1=u'+tgroup1'
@@ -66,6 +67,13 @@ class test_group(Declarative):
dict(
+ desc='Try to rename non-existent %r' % group1,
+ command=('group_mod', [group1], dict(setattr=u'cn=%s' % renamedgroup1)),
+ expected=errors.NotFound(reason='no such entry'),
+ ),
+
+
+ dict(
desc='Create non-POSIX %r' % group1,
command=(
'group_add', [group1], dict(description=u'Test desc 1',nonposix=True)
@@ -327,6 +335,8 @@ class test_group(Declarative):
'gidnumber': [fuzzy_digits],
'cn': [u'admins'],
'description': [u'Account administrators group'],
+ 'memberof_rolegroup': [u'replicaadmin'],
+ 'memberof_taskgroup': [u'managereplica', u'deletereplica'],
},
{
'dn': u'cn=ipausers,cn=groups,cn=accounts,%s' % api.env.basedn,
@@ -453,6 +463,36 @@ class test_group(Declarative):
),
+ dict(
+ desc='Rename %r' % group1,
+ command=('group_mod', [group1], dict(setattr=u'cn=%s' % renamedgroup1)),
+ expected=dict(
+ value=group1,
+ result=dict(
+ cn=[renamedgroup1],
+ description=[u'New desc 1'],
+ gidnumber=[fuzzy_digits],
+ ),
+ summary=u'Modified group "%s"' % group1
+ )
+ ),
+
+
+ dict(
+ desc='Rename %r back' % renamedgroup1,
+ command=('group_mod', [renamedgroup1], dict(setattr=u'cn=%s' % group1)),
+ expected=dict(
+ value=renamedgroup1,
+ result=dict(
+ cn=[group1],
+ description=[u'New desc 1'],
+ gidnumber=[fuzzy_digits],
+ ),
+ summary=u'Modified group "%s"' % renamedgroup1
+ )
+ ),
+
+
################
# delete group1:
diff --git a/tests/test_xmlrpc/test_host_plugin.py b/tests/test_xmlrpc/test_host_plugin.py
index 6a07763c6..631a5de7d 100644
--- a/tests/test_xmlrpc/test_host_plugin.py
+++ b/tests/test_xmlrpc/test_host_plugin.py
@@ -234,6 +234,13 @@ class test_host(Declarative):
dict(
+ desc='Try to rename %r' % fqdn1,
+ command=('host_mod', [fqdn1], dict(setattr=u'fqdn=changed')),
+ expected=errors.NotAllowedOnRDN()
+ ),
+
+
+ dict(
desc='Delete %r' % fqdn1,
command=('host_del', [fqdn1], {}),
expected=dict(
diff --git a/tests/test_xmlrpc/test_rolegroup_plugin.py b/tests/test_xmlrpc/test_rolegroup_plugin.py
index c66bdc474..46922cd4e 100644
--- a/tests/test_xmlrpc/test_rolegroup_plugin.py
+++ b/tests/test_xmlrpc/test_rolegroup_plugin.py
@@ -31,6 +31,7 @@ rolegroup1 = u'test-rolegroup-1'
rolegroup1_dn = u'cn=%s,cn=rolegroups,cn=accounts,%s' % (
rolegroup1, api.env.basedn
)
+renamedrolegroup1 = u'test-rolegroup'
rolegroup2 = u'test-rolegroup-2'
rolegroup2_dn = u'cn=%s,cn=rolegroups,cn=accounts,%s' % (
@@ -73,6 +74,13 @@ class test_rolegroup(Declarative):
dict(
+ desc='Try to rename non-existent %r' % rolegroup1,
+ command=('rolegroup_del', [rolegroup1], dict(setattr=u'cn=%s' % renamedrolegroup1)),
+ expected=errors.NotFound(reason='no such entry'),
+ ),
+
+
+ dict(
desc='Search for non-existent %r' % rolegroup1,
command=('rolegroup_find', [rolegroup1], {}),
expected=dict(
@@ -357,6 +365,34 @@ class test_rolegroup(Declarative):
dict(
+ desc='Rename %r' % rolegroup1,
+ command=('rolegroup_mod', [rolegroup1], dict(setattr=u'cn=%s' % renamedrolegroup1)),
+ expected=dict(
+ value=rolegroup1,
+ result=dict(
+ cn=[renamedrolegroup1],
+ description=[u'New desc 1'],
+ ),
+ summary=u'Modified rolegroup "%s"' % rolegroup1
+ )
+ ),
+
+
+ dict(
+ desc='Rename %r back' % renamedrolegroup1,
+ command=('rolegroup_mod', [renamedrolegroup1], dict(setattr=u'cn=%s' % rolegroup1)),
+ expected=dict(
+ value=renamedrolegroup1,
+ result=dict(
+ cn=[rolegroup1],
+ description=[u'New desc 1'],
+ ),
+ summary=u'Modified rolegroup "%s"' % renamedrolegroup1
+ )
+ ),
+
+
+ dict(
desc='Delete %r' % rolegroup1,
command=('rolegroup_del', [rolegroup1], {}),
expected=dict(
diff --git a/tests/test_xmlrpc/test_taskgroup_plugin.py b/tests/test_xmlrpc/test_taskgroup_plugin.py
index 8401fbdc3..ce3166020 100644
--- a/tests/test_xmlrpc/test_taskgroup_plugin.py
+++ b/tests/test_xmlrpc/test_taskgroup_plugin.py
@@ -32,6 +32,7 @@ taskgroup1 = u'test-taskgroup-1'
taskgroup1_dn = u'cn=%s,cn=taskgroups,cn=accounts,%s' % (
taskgroup1, api.env.basedn
)
+renamedtaskgroup1 = u'test-taskgroup1'
taskgroup2 = u'test-taskgroup-2'
taskgroup2_dn = u'cn=%s,cn=taskgroups,cn=accounts,%s' % (
@@ -80,6 +81,13 @@ class test_taskgroup(Declarative):
dict(
+ desc='Try to rename non-existent %r' % taskgroup1,
+ command=('taskgroup_del', [taskgroup1], dict(setattr=u'cn=%s' % renamedtaskgroup1)),
+ expected=errors.NotFound(reason='no such entry'),
+ ),
+
+
+ dict(
desc='Search for non-existent %r' % taskgroup1,
command=('taskgroup_find', [taskgroup1], {}),
expected=dict(
@@ -362,6 +370,36 @@ class test_taskgroup(Declarative):
dict(
+ desc='Rename %r' % taskgroup1,
+ command=('taskgroup_mod', [taskgroup1], dict(setattr=u'cn=%s' % renamedtaskgroup1)),
+ expected=dict(
+ value=taskgroup1,
+ result=dict(
+ cn=[renamedtaskgroup1],
+ description=[u'New desc 1'],
+ member_rolegroup=[u'test-rolegroup-1'],
+ ),
+ summary=u'Modified taskgroup "%s"' % taskgroup1
+ )
+ ),
+
+
+ dict(
+ desc='Rename %r back' % renamedtaskgroup1,
+ command=('taskgroup_mod', [renamedtaskgroup1], dict(setattr=u'cn=%s' % taskgroup1)),
+ expected=dict(
+ value=renamedtaskgroup1,
+ result=dict(
+ cn=[taskgroup1],
+ description=[u'New desc 1'],
+ member_rolegroup=[u'test-rolegroup-1'],
+ ),
+ summary=u'Modified taskgroup "%s"' % renamedtaskgroup1
+ )
+ ),
+
+
+ dict(
desc='Delete %r' % taskgroup1,
command=('taskgroup_del', [taskgroup1], {}),
expected=dict(
diff --git a/tests/test_xmlrpc/test_user_plugin.py b/tests/test_xmlrpc/test_user_plugin.py
index ee02a0f81..8c2bae499 100644
--- a/tests/test_xmlrpc/test_user_plugin.py
+++ b/tests/test_xmlrpc/test_user_plugin.py
@@ -31,6 +31,7 @@ from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid
user_memberof = (u'cn=ipausers,cn=groups,cn=accounts,%s' % api.env.basedn,)
user1=u'tuser1'
user2=u'tuser2'
+renameduser1=u'tuser'
invaliduser1=u'+tuser1'
invaliduser2=u'tuser1234567890123456789012345678901234567890'
@@ -66,6 +67,13 @@ class test_user(Declarative):
dict(
+ desc='Try to rename non-existent %r' % user1,
+ command=('user_mod', [user1], dict(setattr=u'uid=tuser')),
+ expected=errors.NotFound(reason='no such entry'),
+ ),
+
+
+ dict(
desc='Create %r' % user1,
command=(
'user_add', [user1], dict(givenname=u'Test', sn=u'User1')
@@ -301,6 +309,49 @@ class test_user(Declarative):
dict(
+ desc='Rename %r' % user1,
+ command=('user_mod', [user1], dict(setattr=u'uid=%s' % renameduser1)),
+ expected=dict(
+ result=dict(
+ givenname=[u'Finkle'],
+ homedirectory=[u'/home/tuser1'],
+ loginshell=[u'/bin/sh'],
+ sn=[u'User1'],
+ uid=[renameduser1],
+ memberof_group=[u'ipausers'],
+ ),
+ summary=u'Modified user "%s"' % user1,
+ value=user1,
+ ),
+ ),
+
+
+ dict(
+ desc='Rename %r to same value' % renameduser1,
+ command=('user_mod', [renameduser1], dict(setattr=u'uid=%s' % renameduser1)),
+ expected=errors.EmptyModlist(),
+ ),
+
+
+ dict(
+ desc='Rename back %r' % renameduser1,
+ command=('user_mod', [renameduser1], dict(setattr=u'uid=%s' % user1)),
+ expected=dict(
+ result=dict(
+ givenname=[u'Finkle'],
+ homedirectory=[u'/home/tuser1'],
+ loginshell=[u'/bin/sh'],
+ sn=[u'User1'],
+ uid=[user1],
+ memberof_group=[u'ipausers'],
+ ),
+ summary=u'Modified user "%s"' % renameduser1,
+ value=renameduser1,
+ ),
+ ),
+
+
+ dict(
desc='Delete %r' % user1,
command=('user_del', [user1], {}),
expected=dict(