pgreco / rpms / ipa

Forked from forks/areguera/rpms/ipa 4 years ago
Clone

Blame SOURCES/0091-improve-the-usability-of-ipa-user-del-preserve-comma.patch

590d18
From 8208a3b4a642b19ebf112d29f4b3f4feae1a6011 Mon Sep 17 00:00:00 2001
590d18
From: Martin Babinsky <mbabinsk@redhat.com>
590d18
Date: Wed, 19 Aug 2015 14:43:14 +0200
590d18
Subject: [PATCH] improve the usability of `ipa user-del --preserve` command
590d18
590d18
`ipa user-del` with `--preserve` option will now process multiple entries and
590d18
handle `--continue` option in a manner analogous to `ipa user-del` in normal
590d18
mode.
590d18
590d18
In addition, it is now no longer possible to permanently delete a user by
590d18
accidentally running `ipa user-del --preserve` twice.
590d18
590d18
https://fedorahosted.org/freeipa/ticket/5234
590d18
https://fedorahosted.org/freeipa/ticket/5236
590d18
590d18
Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
590d18
Reviewed-By: Martin Basti <mbasti@redhat.com>
590d18
---
590d18
 ipalib/plugins/user.py | 123 ++++++++++++++++++++++++++-----------------------
590d18
 1 file changed, 66 insertions(+), 57 deletions(-)
590d18
590d18
diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
590d18
index d7cf9666d43b69b0cab91cfa0c98a8373f095ab5..cb47cbb4869cb978f87603817033580647cc2d17 100644
590d18
--- a/ipalib/plugins/user.py
590d18
+++ b/ipalib/plugins/user.py
590d18
@@ -593,6 +593,60 @@ class user_del(baseuser_del):
590d18
         ),
590d18
     )
590d18
 
590d18
+    def _preserve_user(self, pkey, delete_container, **options):
590d18
+        assert isinstance(delete_container, DN)
590d18
+
590d18
+        dn = self.obj.get_either_dn(pkey, **options)
590d18
+        delete_dn = DN(dn[0], delete_container)
590d18
+        ldap = self.obj.backend
590d18
+        self.log.debug("preserve move %s -> %s" % (dn, delete_dn))
590d18
+
590d18
+        if dn.endswith(delete_container):
590d18
+            raise errors.ExecutionError(
590d18
+                _('%s: user is already preserved' % pkey)
590d18
+            )
590d18
+        # Check that this value is a Active user
590d18
+        try:
590d18
+            original_entry_attrs = self._exc_wrapper(
590d18
+                pkey, options, ldap.get_entry)(dn, ['dn'])
590d18
+        except errors.NotFound:
590d18
+            self.obj.handle_not_found(pkey)
590d18
+
590d18
+        # start to move the entry to Delete container
590d18
+        self._exc_wrapper(pkey, options, ldap.move_entry)(dn, delete_dn,
590d18
+                                                          del_old=True)
590d18
+
590d18
+        # Then clear the credential attributes
590d18
+        attrs_to_clear = ['krbPrincipalKey', 'krbLastPwdChange',
590d18
+                          'krbPasswordExpiration', 'userPassword']
590d18
+
590d18
+        entry_attrs = self._exc_wrapper(pkey, options, ldap.get_entry)(
590d18
+            delete_dn, attrs_to_clear)
590d18
+
590d18
+        clearedCredential = False
590d18
+        for attr in attrs_to_clear:
590d18
+            if attr.lower() in entry_attrs:
590d18
+                del entry_attrs[attr]
590d18
+                clearedCredential = True
590d18
+        if clearedCredential:
590d18
+            self._exc_wrapper(pkey, options, ldap.update_entry)(entry_attrs)
590d18
+
590d18
+        # Then restore some original entry attributes
590d18
+        attrs_to_restore = ['secretary', 'managedby', 'manager', 'ipauniqueid',
590d18
+                            'uidnumber', 'gidnumber', 'passwordHistory']
590d18
+
590d18
+        entry_attrs = self._exc_wrapper(
590d18
+            pkey, options, ldap.get_entry)(delete_dn, attrs_to_restore)
590d18
+
590d18
+        restoreAttr = False
590d18
+        for attr in attrs_to_restore:
590d18
+            if ((attr.lower() in original_entry_attrs) and
590d18
+                    not (attr.lower() in entry_attrs)):
590d18
+                restoreAttr = True
590d18
+                entry_attrs[attr.lower()] = original_entry_attrs[attr.lower()]
590d18
+        if restoreAttr:
590d18
+            self._exc_wrapper(pkey, options, ldap.update_entry)(entry_attrs)
590d18
+
590d18
     def forward(self, *keys, **options):
590d18
         if self.api.env.context == 'cli':
590d18
             if options['no_preserve'] and options['preserve']:
590d18
@@ -633,68 +687,23 @@ class user_del(baseuser_del):
590d18
 
590d18
     def execute(self, *keys, **options):
590d18
 
590d18
-        dn = self.obj.get_either_dn(*keys, **options)
590d18
-
590d18
         # We are going to permanent delete or the user is already in the delete container.
590d18
         delete_container = DN(self.obj.delete_container_dn, self.api.env.basedn)
590d18
-        user_from_delete_container = dn.endswith(delete_container)
590d18
-
590d18
-        if not options.get('preserve', True) or user_from_delete_container:
590d18
-            # Remove any ID overrides tied with this user
590d18
-            remove_ipaobject_overrides(self.obj.backend, self.obj.api, dn)
590d18
-
590d18
-            # Issue a true DEL on that entry
590d18
-            return super(user_del, self).execute(*keys, **options)
590d18
 
590d18
         # The user to delete is active and there is no 'no_preserve' option
590d18
         if options.get('preserve', False):
590d18
-
590d18
-            ldap = self.obj.backend
590d18
-
590d18
-            # need to handle multiple keys (e.g. keys[-1]=(u'tb8', u'tb9')..
590d18
-            active_dn = self.obj.get_either_dn(*keys, **options)
590d18
-            superior_dn = DN(self.obj.delete_container_dn, api.env.basedn)
590d18
-            delete_dn = DN(active_dn[0], self.obj.delete_container_dn, api.env.basedn)
590d18
-            self.log.debug("preserve move %s -> %s" % (active_dn, delete_dn))
590d18
-
590d18
-            # Check that this value is a Active user
590d18
-            try:
590d18
-                original_entry_attrs = self._exc_wrapper(keys, options, ldap.get_entry)(active_dn, ['dn'])
590d18
-            except errors.NotFound:
590d18
-                raise
590d18
-
590d18
-            # start to move the entry to Delete container
590d18
-            self._exc_wrapper(keys, options, ldap.move_entry)(active_dn, delete_dn, del_old=True)
590d18
-
590d18
-            # Then clear the credential attributes
590d18
-            attrs_to_clear = ['krbPrincipalKey', 'krbLastPwdChange', 'krbPasswordExpiration', 'userPassword']
590d18
-            try:
590d18
-                entry_attrs = self._exc_wrapper(keys, options, ldap.get_entry)(delete_dn, attrs_to_clear)
590d18
-            except errors.NotFound:
590d18
-                raise
590d18
-            clearedCredential = False
590d18
-            for attr in attrs_to_clear:
590d18
-                if attr.lower() in entry_attrs:
590d18
-                    del entry_attrs[attr]
590d18
-                    clearedCredential = True
590d18
-            if clearedCredential:
590d18
-                self._exc_wrapper(keys, options, ldap.update_entry)(entry_attrs)
590d18
-
590d18
-            # Then restore some original entry attributes
590d18
-            attrs_to_restore = [ 'secretary', 'managedby', 'manager', 'ipauniqueid', 'uidnumber', 'gidnumber', 'passwordHistory']
590d18
-            try:
590d18
-                entry_attrs = self._exc_wrapper(keys, options, ldap.get_entry)(delete_dn, attrs_to_restore)
590d18
-            except errors.NotFound:
590d18
-                raise
590d18
-            restoreAttr = False
590d18
-            for attr in attrs_to_restore:
590d18
-                if (attr.lower() in original_entry_attrs) and not (attr.lower() in entry_attrs):
590d18
-                    restoreAttr = True
590d18
-                    entry_attrs[attr.lower()] = original_entry_attrs[attr.lower()]
590d18
-            if restoreAttr:
590d18
-                self._exc_wrapper(keys, options, ldap.update_entry)(entry_attrs)
590d18
-
590d18
-            val = dict(result=dict(failed=[]), value=[keys[-1][0]])
590d18
+            failed = []
590d18
+            preserved = []
590d18
+            for pkey in keys[-1]:
590d18
+                try:
590d18
+                    self._preserve_user(pkey, delete_container, **options)
590d18
+                    preserved.append(pkey_to_value(pkey, options))
590d18
+                except:
590d18
+                    if not options.get('continue', False):
590d18
+                        raise
590d18
+                    failed.append(pkey_to_value(pkey, options))
590d18
+
590d18
+            val = dict(result=dict(failed=failed), value=preserved)
590d18
             return val
590d18
         else:
590d18
             return super(user_del, self).execute(*keys, **options)
590d18
-- 
590d18
2.4.3
590d18