Patch #61 cleans up the user preservation code a bit
Patch #62 does some guerrila rectofaring

Patches need my patch 60 to apply.

https://fedorahosted.org/freeipa/ticket/5236

--
Martin^3 Babinsky
From fe62db943c8c8516ae14b6838cb2bef8355d1012 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Thu, 20 Aug 2015 11:32:06 +0200
Subject: [PATCH 3/3] factor out the user preservation to separate API command

the new API command is not callable by CLI, but it is invoked when `user-del`
is called with `--preserve` option.

https://fedorahosted.org/freeipa/ticket/5236
---
 API.txt                |  8 +++++
 VERSION                |  4 +--
 ipalib/plugins/user.py | 81 ++++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 78 insertions(+), 15 deletions(-)

diff --git a/API.txt b/API.txt
index dd6bcc3c39895e6af213fcece85505fa0bd6d2f2..e84db9435f2860a70ce9d9028090922fa3fc571f 100644
--- a/API.txt
+++ b/API.txt
@@ -5348,6 +5348,14 @@ option: Str('version?', exclude='webui')
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: PrimaryKey('value', None, None)
+command: user_preserve
+args: 1,2,3
+arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=True, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, query=True, required=True)
+option: Flag('continue', autofill=True, cli_name='continue', default=False)
+option: Str('version?', exclude='webui')
+output: Output('result', <type 'dict'>, None)
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: ListOfPrimaryKeys('value', None, None)
 command: user_remove_cert
 args: 1,5,3
 arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, query=True, required=True)
diff --git a/VERSION b/VERSION
index 0ccfd09ee797ecfc2ff33a25c9c5282bdea71ae0..57c16eeda3a9a272c71911505e1df13315bff4d2 100644
--- a/VERSION
+++ b/VERSION
@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=151
-# Last change: cheimes - Add flag to list all service and user vaults
+IPA_API_VERSION_MINOR=152
+# Last change: mbabinsk - factor out user preservation to separate API command
diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index a4fab41e2123c85f2c9c5cf1174d0433833c6ebe..cab34b221ea96e26a01dfa3a31b03b6560dc2319 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -676,24 +676,79 @@ class user_del(baseuser_del):
 
         # The user to delete is active and there is no 'no_preserve' option
         if options.get('preserve', False):
-            failed = []
-            preserved = []
-            for pkey in keys[-1]:
-                try:
-                    self._preserve_user(pkey, delete_container, **options)
-                    preserved.append(pkey_to_value(pkey, options))
-                except:
-                    if not options.get('continue', False):
-                        raise
-                    failed.append(pkey_to_value(pkey, options))
-
-            val = dict(result=dict(failed=failed), value=preserved)
-            return val
+            options.pop('preserve', None)
+            return self.api.Command.user_preserve(
+                *keys, **options)
         else:
             return super(user_del, self).execute(*keys, **options)
 
 
 @register()
+class user_preserve(baseuser_del):
+    __doc__ = _('Preserve a user')
+
+    msg_summary = _('Preserved user "%(value)s"')
+
+    NO_CLI = True
+
+    def _preserve_user(self, pkey, delete_container, **options):
+        assert isinstance(delete_container, DN)
+
+        dn = self.obj.get_either_dn(pkey, **options)
+        delete_dn = DN(dn[0], delete_container)
+        ldap = self.obj.backend
+        self.log.debug("preserve move %s -> %s" % (dn, delete_dn))
+
+        if dn.endswith(delete_container):
+            raise errors.ExecutionError(
+                _('%s: user is already preserved' % pkey)
+            )
+        # Check that this value is a Active user
+        try:
+            self._exc_wrapper(
+                pkey, options, ldap.get_entry)(dn, ['dn'])
+        except errors.NotFound:
+            self.obj.handle_not_found(pkey)
+
+        # start to move the entry to Delete container
+        self._exc_wrapper(pkey, options, ldap.move_entry)(dn, delete_dn,
+                                                          del_old=True)
+
+        # Then clear the credential attributes
+        attrs_to_clear = ['krbprincipalkey', 'krblastpwdchange',
+                          'krbpasswordexpiration', 'userpassword']
+
+        entry_attrs = self._exc_wrapper(pkey, options, ldap.get_entry)(
+            delete_dn, attrs_to_clear)
+
+        for attr in attrs_to_clear:
+            entry_attrs.pop(attr, None)
+
+        try:
+            self._exc_wrapper(pkey, options, ldap.update_entry)(entry_attrs)
+        except errors.EmptyModlist:
+            pass
+
+    def execute(self, *keys, **options):
+
+        delete_container = DN(self.obj.delete_container_dn,
+                              self.api.env.basedn)
+
+        failed = []
+        preserved = []
+        for pkey in keys[-1]:
+            try:
+                self._preserve_user(pkey, delete_container, **options)
+                preserved.append(pkey_to_value(pkey, options))
+            except:
+                if not options.get('continue', False):
+                    raise
+                failed.append(pkey_to_value(pkey, options))
+
+        return dict(result=dict(failed=failed), value=preserved)
+
+
+@register()
 class user_mod(baseuser_mod):
     __doc__ = _('Modify a user.')
 
-- 
2.4.3

From 069b9daf4d4efa465eb7f49103126f01795a9c4a Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Thu, 20 Aug 2015 09:49:53 +0200
Subject: [PATCH 2/3] user-del: clean up the user preservation code

This patch simplifies some of the code which handles moving the users into
deleted container and also removes some dead code.

https://fedorahosted.org/freeipa/ticket/5236
---
 ipalib/plugins/user.py | 30 +++++++-----------------------
 1 file changed, 7 insertions(+), 23 deletions(-)

diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index 9f8dc993bb6225668aeb1cabafd20c6b98cdfd8c..a4fab41e2123c85f2c9c5cf1174d0433833c6ebe 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -607,7 +607,7 @@ class user_del(baseuser_del):
             )
         # Check that this value is a Active user
         try:
-            original_entry_attrs = self._exc_wrapper(
+            self._exc_wrapper(
                 pkey, options, ldap.get_entry)(dn, ['dn'])
         except errors.NotFound:
             self.obj.handle_not_found(pkey)
@@ -617,35 +617,19 @@ class user_del(baseuser_del):
                                                           del_old=True)
 
         # Then clear the credential attributes
-        attrs_to_clear = ['krbPrincipalKey', 'krbLastPwdChange',
-                          'krbPasswordExpiration', 'userPassword']
+        attrs_to_clear = ['krbprincipalkey', 'krblastpwdchange',
+                          'krbpasswordexpiration', 'userpassword']
 
         entry_attrs = self._exc_wrapper(pkey, options, ldap.get_entry)(
             delete_dn, attrs_to_clear)
 
-        clearedCredential = False
         for attr in attrs_to_clear:
-            if attr.lower() in entry_attrs:
-                del entry_attrs[attr]
-                clearedCredential = True
-        if clearedCredential:
-            self._exc_wrapper(pkey, options, ldap.update_entry)(entry_attrs)
-
-        # Then restore some original entry attributes
-        attrs_to_restore = ['secretary', 'managedby', 'manager', 'ipauniqueid',
-                            'uidnumber', 'gidnumber', 'passwordHistory']
-
-        entry_attrs = self._exc_wrapper(
-            pkey, options, ldap.get_entry)(delete_dn, attrs_to_restore)
+            entry_attrs.pop(attr, None)
 
-        restoreAttr = False
-        for attr in attrs_to_restore:
-            if ((attr.lower() in original_entry_attrs) and
-                    not (attr.lower() in entry_attrs)):
-                restoreAttr = True
-                entry_attrs[attr.lower()] = original_entry_attrs[attr.lower()]
-        if restoreAttr:
+        try:
             self._exc_wrapper(pkey, options, ldap.update_entry)(entry_attrs)
+        except errors.EmptyModlist:
+            pass
 
     def forward(self, *keys, **options):
         if self.api.env.context == 'cli':
-- 
2.4.3

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to