From c20009123f3e4456bdf63b9d406543cb0e50ffce Mon Sep 17 00:00:00 2001 From: Thierry Bordaz Date: Wed, 15 Apr 2015 15:48:21 +0200 Subject: User life cycle: allows MODRDN from ldap2 enhance update_entry_rdn so that is allows to move an entry a new superior https://fedorahosted.org/freeipa/ticket/3813 Reviewed-By: Jan Cholasta --- ipalib/plugins/baseldap.py | 8 +++++--- ipapython/ipaldap.py | 29 +++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py index 4b1c70192..0b1a48107 100644 --- a/ipalib/plugins/baseldap.py +++ b/ipalib/plugins/baseldap.py @@ -1417,10 +1417,12 @@ class LDAPUpdate(LDAPQuery, crud.Update): if self.obj.rdn_is_primary_key and self.obj.primary_key.name in entry_attrs: try: # RDN change - self._exc_wrapper(keys, options, ldap.update_entry_rdn)( + new_dn = DN((self.obj.primary_key.name, + entry_attrs[self.obj.primary_key.name]), + *entry_attrs.dn[1:]) + self._exc_wrapper(keys, options, ldap.move_entry)( entry_attrs.dn, - RDN((self.obj.primary_key.name, - entry_attrs[self.obj.primary_key.name]))) + new_dn) rdnkeys = keys[:-1] + (entry_attrs[self.obj.primary_key.name], ) entry_attrs.dn = self.obj.get_dn(*rdnkeys) diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py index ce07006eb..fd5e203c2 100644 --- a/ipapython/ipaldap.py +++ b/ipapython/ipaldap.py @@ -581,6 +581,9 @@ class IPASimpleLDAPObject(object): dn = str(dn) assert isinstance(newrdn, (DN, RDN)) newrdn = str(newrdn) + if newsuperior: + assert isinstance(newsuperior, DN) + newsuperior = str(newsuperior) return self.conn.rename_s(dn, newrdn, newsuperior, delold) def result(self, msgid=ldap.RES_ANY, all=1, timeout=None): @@ -1593,21 +1596,35 @@ class LDAPClient(object): entry.reset_modlist() - def update_entry_rdn(self, dn, new_rdn, del_old=True): + def move_entry(self, dn, new_dn, del_old=True): """ - Update entry's relative distinguished name. + Move an entry (either to a new superior or/and changing relative distinguished name) Keyword arguments: + dn: DN of the source entry + new_dn: DN of the target entry del_old -- delete old RDN value (default True) - """ + :raises: + errors.NotFound if source entry or target superior entry doesn't exist + errors.EmptyModlist if source and target are identical + """ assert isinstance(dn, DN) - assert isinstance(new_rdn, RDN) + assert isinstance(new_dn, DN) - if dn[0] == new_rdn: + if new_dn == dn: raise errors.EmptyModlist() + + new_rdn = new_dn[0] + + if new_dn[1:] == dn[1:]: + new_superior = None + else: + new_superior = DN(*new_dn[1:]) + with self.error_handler(): - self.conn.rename_s(dn, new_rdn, delold=int(del_old)) + self.conn.rename_s(dn, new_rdn, newsuperior=new_superior, + delold=int(del_old)) time.sleep(.3) # Give memberOf plugin a chance to work def update_entry(self, entry, entry_attrs=None): -- cgit