From 6b8623848e46dec074cd2894c9fbcd0eb47d3247 Mon Sep 17 00:00:00 2001 From: Martin Basti Date: Aug 21 2015 10:29:03 +0000 Subject: Add user-stage command This patch replaces 'stageuser-add --from-delete' with new command user-stage. Original way always required to specify first and last name, and overall combination of options was hard to manage. The new command requires only login of deleted user (user-del --preserve). https://fedorahosted.org/freeipa/ticket/5041 Reviewed-By: Thierry Bordaz Reviewed-By: Jan Cholasta --- diff --git a/API.txt b/API.txt index f23d9a4..b0f456e 100644 --- a/API.txt +++ b/API.txt @@ -4211,7 +4211,7 @@ option: Str('displayname', attribute=True, autofill=True, cli_name='displayname' option: Str('employeenumber', attribute=True, cli_name='employeenumber', multivalue=False, required=False) option: Str('employeetype', attribute=True, cli_name='employeetype', multivalue=False, required=False) option: Str('facsimiletelephonenumber', attribute=True, cli_name='fax', multivalue=True, required=False) -option: Flag('from_delete?', autofill=True, cli_name='from_delete', default=False) +option: DeprecatedParam('from_delete?', cli_name='from_delete', default=False) option: Str('gecos', attribute=True, autofill=True, cli_name='gecos', multivalue=False, required=False) option: Int('gidnumber', attribute=True, cli_name='gidnumber', minvalue=1, multivalue=False, required=False) option: Str('givenname', attribute=True, cli_name='first', multivalue=False, required=True) @@ -5371,6 +5371,14 @@ option: Str('version?', exclude='webui') output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Output('summary', (, ), None) output: PrimaryKey('value', None, None) +command: user_stage +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', , None) +output: Output('summary', (, ), None) +output: ListOfPrimaryKeys('value', None, None) command: user_status args: 1,4,4 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 31a4af4..9fe2f4d 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: mbasti - add 'user-stage' command diff --git a/ipalib/plugins/stageuser.py b/ipalib/plugins/stageuser.py index 29739d5..f378853 100644 --- a/ipalib/plugins/stageuser.py +++ b/ipalib/plugins/stageuser.py @@ -23,7 +23,8 @@ import posixpath import os from copy import deepcopy from ipalib import api, errors -from ipalib import Flag, Int, Password, Str, Bool, StrEnum, DateTime +from ipalib import (Flag, Int, Password, Str, Bool, StrEnum, DateTime, + DeprecatedParam) from ipalib.plugable import Registry from ipalib.plugins.baseldap import LDAPCreate, LDAPQuery, LDAPSearch, DN, entry_to_dict, pkey_to_value from ipalib.plugins import baseldap @@ -260,7 +261,7 @@ class stageuser_add(baseuser_add): has_output_params = baseuser_add.has_output_params + stageuser_output_params takes_options = LDAPCreate.takes_options + ( - Flag('from_delete?', + DeprecatedParam('from_delete?', doc=_('Create Stage user in from a delete user'), cli_name='from_delete', default=False, @@ -270,13 +271,12 @@ class stageuser_add(baseuser_add): def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): assert isinstance(dn, DN) - if not options.get('from_delete'): - # then givenname and sn are required attributes - if 'givenname' not in entry_attrs: - raise errors.RequirementError(name='givenname', error=_('givenname is required')) + # then givenname and sn are required attributes + if 'givenname' not in entry_attrs: + raise errors.RequirementError(name='givenname', error=_('givenname is required')) - if 'sn' not in entry_attrs: - raise errors.RequirementError(name='sn', error=_('sn is required')) + if 'sn' not in entry_attrs: + raise errors.RequirementError(name='sn', error=_('sn is required')) # we don't want an user private group to be created for this user # add NO_UPG_MAGIC description attribute to let the DS plugin know @@ -367,34 +367,6 @@ class stageuser_add(baseuser_add): return dn - def execute(self, *keys, **options): - ''' - A stage entry may be taken from the Delete container. - In that case we rather do 'MODRDN' than 'ADD'. - ''' - if options.get('from_delete'): - ldap = self.obj.backend - - staging_dn = self.obj.get_dn(*keys, **options) - delete_dn = DN(staging_dn[0], self.obj.delete_container_dn, api.env.basedn) - new_dn = DN(staging_dn[0], self.obj.stage_container_dn, api.env.basedn) - # Check that this value is a Active user - try: - entry_attrs = self._exc_wrapper(keys, options, ldap.get_entry)(delete_dn, ['dn']) - except errors.NotFound: - self.obj.handle_not_found(*keys) - - self._exc_wrapper(keys, options, ldap.move_entry)( - delete_dn, new_dn) - entry_attrs = entry_to_dict(entry_attrs, **options) - entry_attrs['dn'] = new_dn - - if self.obj.primary_key and keys[-1] is not None: - return dict(result=entry_attrs, value=keys[-1]) - return dict(result=entry_attrs, value=u'') - else: - return super(stageuser_add, self).execute(*keys, **options) - def post_callback(self, ldap, dn, entry_attrs, *keys, **options): assert isinstance(dn, DN) config = ldap.get_ipa_config() diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py index 418c51b..d7cf966 100644 --- a/ipalib/plugins/user.py +++ b/ipalib/plugins/user.py @@ -859,6 +859,57 @@ class user_undel(LDAPQuery): value=pkey_to_value(keys[0], options), ) + +@register() +class user_stage(LDAPMultiQuery): + __doc__ = _('Move deleted user into staged area') + + has_output = output.standard_multi_delete + msg_summary = _('Staged user account "%(value)s"') + + def execute(self, *keys, **options): + staged = [] + failed = [] + + for key in keys[-1]: + single_keys = keys[:-1] + (key,) + multi_keys = keys[:-1] + ((key,),) + + user = self.api.Command.user_show(*single_keys, all=True)['result'] + new_options = {} + for param in self.api.Command.stageuser_add.options(): + try: + value = user[param.name] + except KeyError: + continue + if param.multivalue and not isinstance(value, (list, tuple)): + value = [value] + elif not param.multivalue and isinstance(value, (list, tuple)): + value = value[0] + new_options[param.name] = value + + try: + self.api.Command.stageuser_add(*single_keys, **new_options) + try: + self.api.Command.user_del(*multi_keys, preserve=False) + except errors.ExecutionError: + self.api.Command.stageuser_del(*multi_keys) + raise + except errors.ExecutionError: + if not options['continue']: + raise + failed.append(key) + else: + staged.append(key) + + return dict( + result=dict( + failed=pkey_to_value(failed, options), + ), + value=pkey_to_value(staged, options), + ) + + @register() class user_disable(LDAPQuery): __doc__ = _('Disable a user account.')