diff options
author | Martin Basti <mbasti@redhat.com> | 2015-11-05 17:11:23 +0100 |
---|---|---|
committer | Martin Basti <mbasti@redhat.com> | 2015-11-20 15:35:14 +0100 |
commit | 457c9746709042e6f4f8f37a85ca8ad562962405 (patch) | |
tree | 5c4dd4456a6bfa5cd031310950bca1f2c0ff60a8 | |
parent | c56d45bc382a6e72c0439452994e998798b22b57 (diff) | |
download | freeipa-457c9746709042e6f4f8f37a85ca8ad562962405.tar.gz freeipa-457c9746709042e6f4f8f37a85ca8ad562962405.tar.xz freeipa-457c9746709042e6f4f8f37a85ca8ad562962405.zip |
Allow multiple managers per user - CLI part
Added commands:
* user-add-manager
* user-remove-manager
* stageuser-add-manager
* stageuser-remove-manager
Commit contains override of convert_attribute_members method in baseuser
class that ensures the managers will be returned in 'manager' attribute
due to backward compatibility instead of 'manager_user' as would be
expected.
https://fedorahosted.org/freeipa/ticket/5344
This patch also fixes: https://fedorahosted.org/freeipa/ticket/5387
Reviewed-By: David Kupka <dkupka@redhat.com>
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
-rw-r--r-- | API.txt | 44 | ||||
-rw-r--r-- | VERSION | 4 | ||||
-rw-r--r-- | ipalib/plugins/baseuser.py | 50 | ||||
-rw-r--r-- | ipalib/plugins/stageuser.py | 22 | ||||
-rw-r--r-- | ipalib/plugins/user.py | 24 |
5 files changed, 113 insertions, 31 deletions
@@ -4248,6 +4248,17 @@ 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_add_manager +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: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('version?', exclude='webui') +output: Output('completed', <type 'int'>, None) +output: Output('failed', <type 'dict'>, None) +output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=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) @@ -4367,6 +4378,17 @@ 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_remove_manager +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: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('version?', exclude='webui') +output: Output('completed', <type 'int'>, None) +output: Output('failed', <type 'dict'>, None) +output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=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) @@ -5208,6 +5230,17 @@ 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_add_manager +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: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('version?', exclude='webui') +output: Output('completed', <type 'int'>, None) +output: Output('failed', <type 'dict'>, None) +output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) command: user_del args: 1,4,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) @@ -5358,6 +5391,17 @@ 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_remove_manager +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: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('version?', exclude='webui') +output: Output('completed', <type 'int'>, None) +output: Output('failed', <type 'dict'>, None) +output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) command: user_show args: 1,6,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) @@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 # # ######################################################## IPA_API_VERSION_MAJOR=2 -IPA_API_VERSION_MINOR=157 -# Last change: mbabinsk - hide segment direction from topology commands +IPA_API_VERSION_MINOR=158 +# Last change: mbasti - allow multiple managers: (stage)user-{add|remove}-manager commands diff --git a/ipalib/plugins/baseuser.py b/ipalib/plugins/baseuser.py index cf0fd88d9..e2572930e 100644 --- a/ipalib/plugins/baseuser.py +++ b/ipalib/plugins/baseuser.py @@ -27,8 +27,9 @@ import six from ipalib import api, errors from ipalib import Flag, Int, Password, Str, Bool, StrEnum, DateTime, Bytes from ipalib.plugable import Registry -from ipalib.plugins.baseldap import DN, LDAPObject, \ - LDAPCreate, LDAPUpdate, LDAPSearch, LDAPDelete, LDAPRetrieve +from ipalib.plugins.baseldap import ( + DN, LDAPObject, LDAPCreate, LDAPUpdate, LDAPSearch, LDAPDelete, + LDAPRetrieve, LDAPAddMember, LDAPRemoveMember) from ipalib.plugins.service import validate_certificate from ipalib.plugins import baseldap from ipalib.request import context @@ -201,6 +202,7 @@ class baseuser(LDAPObject): ] uuid_attribute = 'ipauniqueid' attribute_members = { + 'manager': ['user'], 'memberof': ['group', 'netgroup', 'role', 'hbacrule', 'sudorule'], 'memberofindirect': ['group', 'netgroup', 'role', 'hbacrule', 'sudorule'], } @@ -338,6 +340,7 @@ class baseuser(LDAPObject): Str('title?', label=_('Job Title'), ), + # keep backward compatibility using single value manager option Str('manager?', label=_('Manager'), ), @@ -428,6 +431,7 @@ class baseuser(LDAPObject): if not isinstance(manager, list): manager = [manager] + try: container_dn = DN(container, api.env.basedn) for i, mgr in enumerate(manager): @@ -443,17 +447,6 @@ class baseuser(LDAPObject): return manager - def convert_manager(self, entry_attrs, **options): - """ - Convert a manager dn into a userid - """ - if options.get('raw', False): - return - - if 'manager' in entry_attrs: - for i, mgr in enumerate(entry_attrs['manager']): - entry_attrs['manager'][i] = self.get_primary_key_from_dn(mgr) - def _user_status(self, user, container): assert isinstance(user, DN) return user.endswith(container) @@ -480,6 +473,26 @@ class baseuser(LDAPObject): entry_attrs['usercertificate'] = entry_attrs.pop( 'usercertificate;binary') + def convert_attribute_members(self, entry_attrs, *keys, **options): + super(baseuser, self).convert_attribute_members( + entry_attrs, *keys, **options) + + if options.get("raw", False): + return + + # due the backward compatibility, managers have to be returned in + # 'manager' attribute instead of 'manager_user' + try: + entry_attrs['failed_manager'] = entry_attrs.pop('manager') + except KeyError: + pass + + try: + entry_attrs['manager'] = entry_attrs.pop('manager_user') + except KeyError: + pass + + class baseuser_add(LDAPCreate): """ Prototype command plugin to be implemented by real plugin @@ -578,7 +591,6 @@ class baseuser_mod(LDAPUpdate): # if both randompassword and userpassword options were used pass convert_nsaccountlock(entry_attrs) - self.obj.convert_manager(entry_attrs, **options) self.obj.get_password_attributes(ldap, dn, entry_attrs) self.obj.convert_usercertificate_post(entry_attrs, **options) convert_sshpubkey_post(ldap, dn, entry_attrs) @@ -609,7 +621,6 @@ class baseuser_find(LDAPSearch): def post_common_callback(self, ldap, entries, lockout=False, **options): for attrs in entries: - self.obj.convert_manager(attrs, **options) self.obj.get_password_attributes(ldap, attrs.dn, attrs) self.obj.convert_usercertificate_post(attrs, **options) if (lockout): @@ -624,8 +635,15 @@ class baseuser_show(LDAPRetrieve): """ def post_common_callback(self, ldap, dn, entry_attrs, **options): assert isinstance(dn, DN) - self.obj.convert_manager(entry_attrs, **options) self.obj.get_password_attributes(ldap, dn, entry_attrs) self.obj.convert_usercertificate_post(entry_attrs, **options) convert_sshpubkey_post(ldap, dn, entry_attrs) radius_dn2pk(self.api, entry_attrs) + + +class baseuser_add_manager(LDAPAddMember): + member_attributes = ['manager'] + + +class baseuser_remove_manager(LDAPRemoveMember): + member_attributes = ['manager'] diff --git a/ipalib/plugins/stageuser.py b/ipalib/plugins/stageuser.py index 47c96bb71..995f67923 100644 --- a/ipalib/plugins/stageuser.py +++ b/ipalib/plugins/stageuser.py @@ -31,12 +31,12 @@ from ipalib import (Flag, Int, Password, Str, Bool, StrEnum, DateTime, 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 -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 - +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, + baseuser_add_manager, baseuser_remove_manager) from ipalib.request import context from ipalib import _, ngettext from ipalib import output @@ -716,3 +716,13 @@ class stageuser_activate(LDAPQuery): return dict(result=result_entry, summary=unicode(_('Stage user %s activated' % staging_dn[0].value)), value=pkey_to_value(args[-1], options)) + + +@register() +class stageuser_add_manager(baseuser_add_manager): + __doc__ = _("Add a manager to the stage user entry") + + +@register() +class stageuser_remove_manager(baseuser_remove_manager): + __doc__ = _("Remove a manager to the stage user entry") diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py index 81a707035..2b792af62 100644 --- a/ipalib/plugins/user.py +++ b/ipalib/plugins/user.py @@ -27,12 +27,13 @@ import six from ipalib import api, errors, util from ipalib import Flag, Int, Password, Str, Bool, StrEnum, DateTime -from ipalib.plugins.baseuser import baseuser, baseuser_add, baseuser_del, \ - baseuser_mod, baseuser_find, baseuser_show, \ - NO_UPG_MAGIC, UPG_DEFINITION_DN, baseuser_output_params, \ - status_baseuser_output_params, baseuser_pwdchars, \ - validate_nsaccountlock, radius_dn2pk, convert_nsaccountlock, split_principal, validate_principal, \ - normalize_principal, fix_addressbook_permission_bindrule +from ipalib.plugins.baseuser import ( + baseuser, baseuser_add, baseuser_del, baseuser_mod, baseuser_find, + baseuser_show, NO_UPG_MAGIC, UPG_DEFINITION_DN, baseuser_output_params, + status_baseuser_output_params, baseuser_pwdchars, validate_nsaccountlock, + radius_dn2pk, convert_nsaccountlock, split_principal, validate_principal, + normalize_principal, fix_addressbook_permission_bindrule, + baseuser_add_manager, baseuser_remove_manager) from ipalib.plugins.idviews import remove_ipaobject_overrides from ipalib.plugable import Registry from ipalib.plugins.baseldap import * @@ -542,7 +543,6 @@ class user_add(baseuser_add): except errors.AlreadyGroupMember: pass - self.obj.convert_manager(entry_attrs, **options) # delete description attribute NO_UPG_MAGIC if present if options.get('noprivate', False): if not options.get('all', False): @@ -1157,3 +1157,13 @@ class user_remove_cert(LDAPRemoveAttribute): self.obj.convert_usercertificate_post(entry_attrs, **options) return dn + + +@register() +class user_add_manager(baseuser_add_manager): + __doc__ = _("Add a manager to the user entry") + + +@register() +class user_remove_manager(baseuser_remove_manager): + __doc__ = _("Remove a manager to the user entry") |