Hello,

   Here is the next patch for User life cycle that introduces
   del/mod/find and show stageuser plugin commands.

 * 0000-User Life Cycle (create containers and scoping  DS plugins):
   *pushed*
 * 0001-User-Life-Cycle-Exclude-subtree-for-ipaUniqueID-gene.patch:
   *pushed*
 * 0002-User-life-cycle-stageuser-add-verb.patch: *pushed*
 * 0007-User-life-cycle-allows-MODRDN-from-ldap2.patch: *pushed*
 * 0003-User-life-cycle-new-stageuser-commands-del-mod-find-*under
   review *(this one)**
 * 0004-User-life-cycle-new-stageuser-commands-activate.patch
 * 0005-User-life-cycle-new-stageuser-commands-activate-prov.patch
 * 0006-User-life-cycle-user-del-supports-permanently-preser.patch
 * 0008-User-life-cycle-user-find-support-finding-delete-use.patch
 * 0009-User-life-cycle-support-of-user-undel.patch
 * 0010-User-life-cycle-DNA-DS-plugin-should-exclude-provisi.patch
 * 0011-User-life-cycle-lockout-provisioning-stage-and-delet.patch
 * 0012-User-life-cycle-Create-stage-Admin-provisioning-acco.patch
 * 0013-User-life-cycle-Stage-Admin-permission-priviledge.patch

Thanks
thierry

From 1393b393468584579212e84be30142ae3049a625 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbor...@redhat.com>
Date: Thu, 16 Apr 2015 10:17:31 +0200
Subject: [PATCH] User life cycle: new stageuser commands del/mod/find/show

Add plugin commands to stageuser plugin:
	stageuser_del
	stageuser_mod
	stageuser_find
	stageuser_show

https://fedorahosted.org/freeipa/ticket/3813
---
 API.txt                     | 128 ++++++++++++++++++++++++++++++++++++++
 VERSION                     |   4 +-
 ipalib/plugins/stageuser.py | 147 +++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 276 insertions(+), 3 deletions(-)

diff --git a/API.txt b/API.txt
index f747765d7f9c87761fed0277cd59d1bc3fbd57e9..f2d9af90cc1c0fd373ab9847d2d1327f68671414 100644
--- a/API.txt
+++ b/API.txt
@@ -3740,6 +3740,134 @@ 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: stageuser_del
+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: stageuser_find
+args: 1,52,4
+arg: Str('criteria?', noextrawhitespace=False)
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Str('carlicense', attribute=True, autofill=False, cli_name='carlicense', multivalue=True, query=True, required=False)
+option: Str('cn', attribute=True, autofill=False, cli_name='cn', multivalue=False, query=True, required=False)
+option: Str('departmentnumber', attribute=True, autofill=False, cli_name='departmentnumber', multivalue=True, query=True, required=False)
+option: Str('displayname', attribute=True, autofill=False, cli_name='displayname', multivalue=False, query=True, required=False)
+option: Str('employeenumber', attribute=True, autofill=False, cli_name='employeenumber', multivalue=False, query=True, required=False)
+option: Str('employeetype', attribute=True, autofill=False, cli_name='employeetype', multivalue=False, query=True, required=False)
+option: Str('facsimiletelephonenumber', attribute=True, autofill=False, cli_name='fax', multivalue=True, query=True, required=False)
+option: Str('gecos', attribute=True, autofill=False, cli_name='gecos', multivalue=False, query=True, required=False)
+option: Int('gidnumber', attribute=True, autofill=False, cli_name='gidnumber', minvalue=1, multivalue=False, query=True, required=False)
+option: Str('givenname', attribute=True, autofill=False, cli_name='first', multivalue=False, query=True, required=False)
+option: Str('homedirectory', attribute=True, autofill=False, cli_name='homedir', multivalue=False, query=True, required=False)
+option: Str('in_group*', cli_name='in_groups', csv=True)
+option: Str('in_hbacrule*', cli_name='in_hbacrules', csv=True)
+option: Str('in_netgroup*', cli_name='in_netgroups', csv=True)
+option: Str('in_role*', cli_name='in_roles', csv=True)
+option: Str('in_sudorule*', cli_name='in_sudorules', csv=True)
+option: Str('initials', attribute=True, autofill=False, cli_name='initials', multivalue=False, query=True, required=False)
+option: Str('ipatokenradiusconfiglink', attribute=True, autofill=False, cli_name='radius', multivalue=False, query=True, required=False)
+option: Str('ipatokenradiususername', attribute=True, autofill=False, cli_name='radius_username', multivalue=False, query=True, required=False)
+option: StrEnum('ipauserauthtype', attribute=True, autofill=False, cli_name='user_auth_type', csv=True, multivalue=True, query=True, required=False, values=(u'password', u'radius', u'otp'))
+option: DateTime('krbprincipalexpiration', attribute=True, autofill=False, cli_name='principal_expiration', multivalue=False, query=True, required=False)
+option: Str('krbprincipalname', attribute=True, autofill=False, cli_name='principal', multivalue=False, query=True, required=False)
+option: Str('l', attribute=True, autofill=False, cli_name='city', multivalue=False, query=True, required=False)
+option: Str('loginshell', attribute=True, autofill=False, cli_name='shell', multivalue=False, query=True, required=False)
+option: Str('mail', attribute=True, autofill=False, cli_name='email', multivalue=True, query=True, required=False)
+option: Str('manager', attribute=True, autofill=False, cli_name='manager', multivalue=False, query=True, required=False)
+option: Str('mobile', attribute=True, autofill=False, cli_name='mobile', multivalue=True, query=True, required=False)
+option: Flag('no_members', autofill=True, default=False, exclude='webui')
+option: Str('not_in_group*', cli_name='not_in_groups', csv=True)
+option: Str('not_in_hbacrule*', cli_name='not_in_hbacrules', csv=True)
+option: Str('not_in_netgroup*', cli_name='not_in_netgroups', csv=True)
+option: Str('not_in_role*', cli_name='not_in_roles', csv=True)
+option: Str('not_in_sudorule*', cli_name='not_in_sudorules', csv=True)
+option: Str('ou', attribute=True, autofill=False, cli_name='orgunit', multivalue=False, query=True, required=False)
+option: Str('pager', attribute=True, autofill=False, cli_name='pager', multivalue=True, query=True, required=False)
+option: Flag('pkey_only?', autofill=True, default=False)
+option: Str('postalcode', attribute=True, autofill=False, cli_name='postalcode', multivalue=False, query=True, required=False)
+option: Str('preferredlanguage', attribute=True, autofill=False, cli_name='preferredlanguage', multivalue=False, pattern='^(([a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?(;q\\=((0(\\.[0-9]{0,3})?)|(1(\\.0{0,3})?)))?(\\s*,\\s*[a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?(;q\\=((0(\\.[0-9]{0,3})?)|(1(\\.0{0,3})?)))?)*)|(\\*))$', query=True, required=False)
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Int('sizelimit?', autofill=False, minvalue=0)
+option: Str('sn', attribute=True, autofill=False, cli_name='last', multivalue=False, query=True, required=False)
+option: Str('st', attribute=True, autofill=False, cli_name='state', multivalue=False, query=True, required=False)
+option: Str('street', attribute=True, autofill=False, cli_name='street', multivalue=False, query=True, required=False)
+option: Str('telephonenumber', attribute=True, autofill=False, cli_name='phone', multivalue=True, query=True, required=False)
+option: Int('timelimit?', autofill=False, minvalue=0)
+option: Str('title', attribute=True, autofill=False, cli_name='title', multivalue=False, query=True, required=False)
+option: Str('uid', attribute=True, autofill=False, 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=False)
+option: Int('uidnumber', attribute=True, autofill=False, cli_name='uid', minvalue=1, multivalue=False, query=True, required=False)
+option: Str('userclass', attribute=True, autofill=False, cli_name='class', multivalue=True, query=True, required=False)
+option: Password('userpassword', attribute=True, autofill=False, cli_name='password', exclude='webui', multivalue=False, query=True, required=False)
+option: Str('version?', exclude='webui')
+output: Output('count', <type 'int'>, None)
+output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list of LDAP entries', domain='ipa', localedir=None))
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: Output('truncated', <type 'bool'>, None)
+command: stageuser_mod
+args: 1,44,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)
+option: Str('addattr*', cli_name='addattr', exclude='webui')
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Str('carlicense', attribute=True, autofill=False, cli_name='carlicense', multivalue=True, required=False)
+option: Str('cn', attribute=True, autofill=False, cli_name='cn', multivalue=False, required=False)
+option: Str('delattr*', cli_name='delattr', exclude='webui')
+option: Str('departmentnumber', attribute=True, autofill=False, cli_name='departmentnumber', multivalue=True, required=False)
+option: Str('displayname', attribute=True, autofill=False, cli_name='displayname', multivalue=False, required=False)
+option: Str('employeenumber', attribute=True, autofill=False, cli_name='employeenumber', multivalue=False, required=False)
+option: Str('employeetype', attribute=True, autofill=False, cli_name='employeetype', multivalue=False, required=False)
+option: Str('facsimiletelephonenumber', attribute=True, autofill=False, cli_name='fax', multivalue=True, required=False)
+option: Str('gecos', attribute=True, autofill=False, cli_name='gecos', multivalue=False, required=False)
+option: Int('gidnumber', attribute=True, autofill=False, cli_name='gidnumber', minvalue=1, multivalue=False, required=False)
+option: Str('givenname', attribute=True, autofill=False, cli_name='first', multivalue=False, required=False)
+option: Str('homedirectory', attribute=True, autofill=False, cli_name='homedir', multivalue=False, required=False)
+option: Str('initials', attribute=True, autofill=False, cli_name='initials', multivalue=False, required=False)
+option: Str('ipasshpubkey', attribute=True, autofill=False, cli_name='sshpubkey', csv=True, multivalue=True, required=False)
+option: Str('ipatokenradiusconfiglink', attribute=True, autofill=False, cli_name='radius', multivalue=False, required=False)
+option: Str('ipatokenradiususername', attribute=True, autofill=False, cli_name='radius_username', multivalue=False, required=False)
+option: StrEnum('ipauserauthtype', attribute=True, autofill=False, cli_name='user_auth_type', csv=True, multivalue=True, required=False, values=(u'password', u'radius', u'otp'))
+option: DateTime('krbprincipalexpiration', attribute=True, autofill=False, cli_name='principal_expiration', multivalue=False, required=False)
+option: Str('l', attribute=True, autofill=False, cli_name='city', multivalue=False, required=False)
+option: Str('loginshell', attribute=True, autofill=False, cli_name='shell', multivalue=False, required=False)
+option: Str('mail', attribute=True, autofill=False, cli_name='email', multivalue=True, required=False)
+option: Str('manager', attribute=True, autofill=False, cli_name='manager', multivalue=False, required=False)
+option: Str('mobile', attribute=True, autofill=False, cli_name='mobile', multivalue=True, required=False)
+option: Flag('no_members', autofill=True, default=False, exclude='webui')
+option: Str('ou', attribute=True, autofill=False, cli_name='orgunit', multivalue=False, required=False)
+option: Str('pager', attribute=True, autofill=False, cli_name='pager', multivalue=True, required=False)
+option: Str('postalcode', attribute=True, autofill=False, cli_name='postalcode', multivalue=False, required=False)
+option: Str('preferredlanguage', attribute=True, autofill=False, cli_name='preferredlanguage', multivalue=False, pattern='^(([a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?(;q\\=((0(\\.[0-9]{0,3})?)|(1(\\.0{0,3})?)))?(\\s*,\\s*[a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?(;q\\=((0(\\.[0-9]{0,3})?)|(1(\\.0{0,3})?)))?)*)|(\\*))$', required=False)
+option: Flag('random', attribute=False, autofill=True, cli_name='random', default=False, multivalue=False, required=False)
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Str('rename', cli_name='rename', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, required=False)
+option: Flag('rights', autofill=True, default=False)
+option: Str('setattr*', cli_name='setattr', exclude='webui')
+option: Str('sn', attribute=True, autofill=False, cli_name='last', multivalue=False, required=False)
+option: Str('st', attribute=True, autofill=False, cli_name='state', multivalue=False, required=False)
+option: Str('street', attribute=True, autofill=False, cli_name='street', multivalue=False, required=False)
+option: Str('telephonenumber', attribute=True, autofill=False, cli_name='phone', multivalue=True, required=False)
+option: Str('title', attribute=True, autofill=False, cli_name='title', multivalue=False, required=False)
+option: Int('uidnumber', attribute=True, autofill=False, cli_name='uid', minvalue=1, multivalue=False, required=False)
+option: Str('userclass', attribute=True, autofill=False, cli_name='class', multivalue=True, required=False)
+option: Password('userpassword', attribute=True, autofill=False, cli_name='password', exclude='webui', multivalue=False, required=False)
+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: stageuser_show
+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)
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Flag('no_members', autofill=True, default=False, exclude='webui')
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Flag('rights', autofill=True, default=False)
+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: sudocmd_add
 args: 1,7,3
 arg: Str('sudocmd', attribute=True, cli_name='command', multivalue=False, primary_key=True, required=True)
diff --git a/VERSION b/VERSION
index b584eb4584ea45881e5329a846dae0df7e231844..e518f8d862cb8b9fa918124c9bbe43e8f20145fb 100644
--- a/VERSION
+++ b/VERSION
@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=116
-# Last change: tbordaz - Add stageuser_add command"
+IPA_API_VERSION_MINOR=117
+# Last change: tbordaz - Add stageuser_find, stageuser_mod, stageuser_del, stageuser_show
diff --git a/ipalib/plugins/stageuser.py b/ipalib/plugins/stageuser.py
index 2a9a7f41323837a78ff5133cd3c2ffe0c1a3a8a0..0c66810208c4218df6a529d3bcd25aab2532abb8 100644
--- a/ipalib/plugins/stageuser.py
+++ b/ipalib/plugins/stageuser.py
@@ -27,7 +27,8 @@ from ipalib import Flag, Int, Password, Str, Bool, StrEnum, DateTime
 from ipalib.plugable import Registry
 from ipalib.plugins.baseldap import LDAPCreate, DN, entry_to_dict
 from ipalib.plugins import baseldap
-from ipalib.plugins.baseuser import baseuser, baseuser_add, baseuser_mod, baseuser_find, \
+from ipalib.plugins.baseuser import baseuser, baseuser_add, baseuser_del, \
+    baseuser_mod, baseuser_find, baseuser_show, \
     NO_UPG_MAGIC, radius_dn2pk, \
     baseuser_pwdchars, fix_addressbook_permission_bindrule, normalize_principal, validate_principal, \
     baseuser_output_params, status_baseuser_output_params
@@ -275,3 +276,147 @@ class stageuser_add(baseuser_add):
         convert_sshpubkey_post(ldap, dn, entry_attrs)
         radius_dn2pk(self.api, entry_attrs)
         return dn
+
+@register()
+class stageuser_del(baseuser_del):
+    __doc__ = _('Delete a stage user.')
+
+    msg_summary = _('Deleted stage user "%(value)s"')
+
+    def pre_callback(self, ldap, dn, *keys, **options):
+        assert isinstance(dn, DN)
+        return dn
+
+@register()
+class stageuser_mod(baseuser_mod):
+    __doc__ = _('Modify a stage user.')
+
+    msg_summary = _('Modified stage user "%(value)s"')
+
+    has_output_params = baseuser_mod.has_output_params + stageuser_output_params
+
+    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
+        assert isinstance(dn, DN)
+        if options.get('rename') is not None:
+            config = ldap.get_ipa_config()
+            if 'ipamaxusernamelength' in config:
+                if len(options['rename']) > int(config.get('ipamaxusernamelength')[0]):
+                    raise errors.ValidationError(
+                        name=self.obj.primary_key.cli_name,
+                        error=_('can be at most %(len)d characters') % dict(
+                            len = int(config.get('ipamaxusernamelength')[0])
+                        )
+                    )
+        if 'mail' in entry_attrs:
+            entry_attrs['mail'] = self.obj.normalize_and_validate_email(entry_attrs['mail'])
+
+        # If the manager is defined, check it is a ACTIVE user to validate it
+        if 'manager' in entry_attrs:
+            entry_attrs['manager'] = self.obj.normalize_manager(entry_attrs['manager'], self.obj.active_container_dn)
+
+        # Make sure it is not possible to authenticate with a Stage user account
+        if 'nsaccountlock' in entry_attrs:
+            del entry_attrs['nsaccountlock']
+
+        # If requested, generate a userpassword
+        if 'userpassword' not in entry_attrs and options.get('random'):
+            entry_attrs['userpassword'] = ipa_generate_password(baseuser_pwdchars)
+            # save the password so it can be displayed in post_callback
+            setattr(context, 'randompassword', entry_attrs['userpassword'])
+
+        if ('ipasshpubkey' in entry_attrs or 'ipauserauthtype' in entry_attrs
+            or 'userclass' in entry_attrs or 'ipatokenradiusconfiglink' in entry_attrs):
+            if 'objectclass' in entry_attrs:
+                obj_classes = entry_attrs['objectclass']
+            else:
+                _entry_attrs = ldap.get_entry(dn, ['objectclass'])
+                obj_classes = entry_attrs['objectclass'] = _entry_attrs['objectclass']
+
+            if 'ipasshpubkey' in entry_attrs and 'ipasshuser' not in obj_classes:
+                obj_classes.append('ipasshuser')
+
+            if 'ipauserauthtype' in entry_attrs and 'ipauserauthtypeclass' not in obj_classes:
+                obj_classes.append('ipauserauthtypeclass')
+
+            if 'userclass' in entry_attrs and 'ipauser' not in obj_classes:
+                obj_classes.append('ipauser')
+
+            if 'ipatokenradiusconfiglink' in entry_attrs:
+                cl = entry_attrs['ipatokenradiusconfiglink']
+                if cl:
+                    if 'ipatokenradiusproxyuser' not in obj_classes:
+                        obj_classes.append('ipatokenradiusproxyuser')
+
+                    answer = self.api.Object['radiusproxy'].get_dn_if_exists(cl)
+                    entry_attrs['ipatokenradiusconfiglink'] = answer
+
+        return dn
+
+    def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
+        assert isinstance(dn, DN)
+        if options.get('random', False):
+            try:
+                entry_attrs['randompassword'] = unicode(getattr(context, 'randompassword'))
+            except AttributeError:
+                # if both randompassword and userpassword options were used
+                pass
+        self.obj.convert_manager(entry_attrs, **options)
+        self.obj.get_password_attributes(ldap, dn, entry_attrs)
+        convert_sshpubkey_post(ldap, dn, entry_attrs)
+        radius_dn2pk(self.api, entry_attrs)
+        return dn
+
+@register()
+class stageuser_find(baseuser_find):
+    __doc__ = _('Search for stage users.')
+
+    member_attributes = ['memberof']
+    has_output_params = baseuser_find.has_output_params + stageuser_output_params
+
+
+    def execute(self, *args, **options):
+        # assure the manager attr is a dn, not just a bare uid
+        manager = options.get('manager')
+        if manager is not None:
+            options['manager'] = self.obj.normalize_manager(manager, self.obj.active_container_dn)
+
+        # Ensure that the RADIUS config link is a dn, not just the name
+        cl = 'ipatokenradiusconfiglink'
+        if cl in options:
+            options[cl] = self.api.Object['radiusproxy'].get_dn(options[cl])
+
+        return super(stageuser_find, self).execute(self, *args, **options)
+
+    def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *keys, **options):
+        assert isinstance(base_dn, DN)
+
+        return (filter, base_dn, scope)
+
+    def post_callback(self, ldap, entries, truncated, *args, **options):
+        if options.get('pkey_only', False):
+            return truncated
+        for attrs in entries:
+            self.obj.convert_manager(attrs, **options)
+            self.obj.get_password_attributes(ldap, attrs.dn, attrs)
+            attrs['nsaccountlock'] = True
+            convert_sshpubkey_post(ldap, attrs.dn, attrs)
+        return truncated
+
+    msg_summary = ngettext(
+        '%(count)d user matched', '%(count)d users matched', 0
+    )
+
+@register()
+class stageuser_show(baseuser_show):
+    __doc__ = _('Display information about a stage user.')
+
+    has_output_params = baseuser_show.has_output_params + stageuser_output_params
+
+    def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
+        assert isinstance(dn, DN)
+        entry_attrs['nsaccountlock'] = True
+        self.obj.convert_manager(entry_attrs, **options)
+        self.obj.get_password_attributes(ldap, dn, entry_attrs)
+        convert_sshpubkey_post(ldap, dn, entry_attrs)
+        radius_dn2pk(self.api, entry_attrs)
+        return dn
-- 
1.7.11.7

-- 
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