Only use no_create/no_update for things we really don't want the user to change (even through setattr). This is stuff like ipacertificatesubjectbase.
Make --{set,add,del}attr refuse to modify these params.

For things we just don't advertise in the because there's a different way to do change them, there is the "no_option" flag (undocumented before this patch). This only causes the option to be hidden from the CLI; XML-RPC will still happily take it (and it will appear in API.txt).
Use this for ipaenabledflag, nsacconuntlock, and externalhost.


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

--
PetrĀ³
From 6602ed9cce34d313922670085550a6bdd5852606 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Mon, 21 May 2012 05:03:21 -0400
Subject: [PATCH] Disallow setattr on no_update/no_create params

Make --{set,add,del}attr fail on parameters with the no_update/no_create
flag for the respective command.

For attributes that can be modified, but we just don't want to display
in the CLI, use the 'no_option' flag. These are "locking" attributes
(ipaenabledflag, nsaccountlock) and externalhost.

Document the 'no_option' flag. Add some tests.

https://fedorahosted.org/freeipa/ticket/2580
---
 API.txt                               |   51 +++++++++++++++++--------
 VERSION                               |    2 +-
 ipalib/parameters.py                  |    3 ++
 ipalib/plugable.py                    |    2 +-
 ipalib/plugins/baseldap.py            |   18 ++++-----
 ipalib/plugins/hbacrule.py            |    6 +--
 ipalib/plugins/selinuxusermap.py      |    6 +--
 ipalib/plugins/sudorule.py            |    6 +--
 ipalib/plugins/user.py                |    2 +-
 tests/test_xmlrpc/test_attr.py        |    3 +-
 tests/test_xmlrpc/test_user_plugin.py |   67 +++++++++++++++++++++++++++++++++
 11 files changed, 128 insertions(+), 38 deletions(-)

diff --git a/API.txt b/API.txt
index 82a6bc65c1e1936f94f4c29b58a34972237f4eb3..3cc25b24ef0e6896a70ab75e4ba717381d89b8c9 100644
--- a/API.txt
+++ b/API.txt
@@ -1302,14 +1302,16 @@ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
 output: Output('value', <type 'unicode'>, None)
 command: hbacrule_add
-args: 1,11,3
+args: 1,13,3
 arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, required=True)
 option: StrEnum('accessruletype', attribute=True, autofill=True, cli_name='type', default=u'allow', exclude='webui', multivalue=False, required=True, values=(u'allow', u'deny'))
 option: StrEnum('usercategory', attribute=True, cli_name='usercat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, cli_name='hostcat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('sourcehostcategory', attribute=True, cli_name='srchostcat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('servicecategory', attribute=True, cli_name='servicecat', multivalue=False, required=False, values=(u'all',))
 option: Str('description', attribute=True, cli_name='desc', multivalue=False, required=False)
+option: Bool('ipaenabledflag', attribute=True, cli_name='ipaenabledflag', multivalue=False, required=False)
+option: Str('externalhost', attribute=True, cli_name='externalhost', multivalue=True, required=False)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@@ -1382,15 +1384,17 @@ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('result', <type 'bool'>, None)
 output: Output('value', <type 'unicode'>, None)
 command: hbacrule_find
-args: 1,13,4
+args: 1,15,4
 arg: Str('criteria?', noextrawhitespace=False)
 option: Str('cn', attribute=True, autofill=False, cli_name='name', multivalue=False, primary_key=True, query=True, required=False)
 option: StrEnum('accessruletype', attribute=True, autofill=False, cli_name='type', default=u'allow', exclude='webui', multivalue=False, query=True, required=False, values=(u'allow', u'deny'))
 option: StrEnum('usercategory', attribute=True, autofill=False, cli_name='usercat', multivalue=False, query=True, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, autofill=False, cli_name='hostcat', multivalue=False, query=True, required=False, values=(u'all',))
 option: StrEnum('sourcehostcategory', attribute=True, autofill=False, cli_name='srchostcat', multivalue=False, query=True, required=False, values=(u'all',))
 option: StrEnum('servicecategory', attribute=True, autofill=False, cli_name='servicecat', multivalue=False, query=True, required=False, values=(u'all',))
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, query=True, required=False)
+option: Bool('ipaenabledflag', attribute=True, autofill=False, cli_name='ipaenabledflag', multivalue=False, query=True, required=False)
+option: Str('externalhost', attribute=True, autofill=False, cli_name='externalhost', multivalue=True, query=True, required=False)
 option: Int('timelimit?', autofill=False, minvalue=0)
 option: Int('sizelimit?', autofill=False, minvalue=0)
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@@ -1402,14 +1406,16 @@ output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list
 output: Output('count', <type 'int'>, None)
 output: Output('truncated', <type 'bool'>, None)
 command: hbacrule_mod
-args: 1,13,3
+args: 1,15,3
 arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, query=True, required=True)
 option: StrEnum('accessruletype', attribute=True, autofill=False, cli_name='type', default=u'allow', exclude='webui', multivalue=False, required=False, values=(u'allow', u'deny'))
 option: StrEnum('usercategory', attribute=True, autofill=False, cli_name='usercat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, autofill=False, cli_name='hostcat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('sourcehostcategory', attribute=True, autofill=False, cli_name='srchostcat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('servicecategory', attribute=True, autofill=False, cli_name='servicecat', multivalue=False, required=False, values=(u'all',))
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, required=False)
+option: Bool('ipaenabledflag', attribute=True, autofill=False, cli_name='ipaenabledflag', multivalue=False, required=False)
+option: Str('externalhost', attribute=True, autofill=False, cli_name='externalhost', multivalue=True, required=False)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Str('delattr*', cli_name='delattr', exclude='webui')
@@ -1920,12 +1926,13 @@ output: Output('failed', <type 'dict'>, None)
 output: Output('enabled', <type 'bool'>, None)
 output: Output('compat', <type 'bool'>, None)
 command: netgroup_add
-args: 1,9,3
+args: 1,10,3
 arg: Str('cn', attribute=True, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, required=True)
 option: Str('description', attribute=True, cli_name='desc', multivalue=False, required=True)
 option: Str('nisdomainname', attribute=True, cli_name='nisdomain', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', required=False)
 option: StrEnum('usercategory', attribute=True, cli_name='usercat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, cli_name='hostcat', multivalue=False, required=False, values=(u'all',))
+option: Str('externalhost', attribute=True, cli_name='externalhost', multivalue=True, required=False)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@@ -1956,14 +1963,15 @@ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('result', <type 'dict'>, None)
 output: Output('value', <type 'unicode'>, None)
 command: netgroup_find
-args: 1,26,4
+args: 1,27,4
 arg: Str('criteria?', noextrawhitespace=False)
 option: Str('cn', attribute=True, autofill=False, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=False)
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, query=True, required=False)
 option: Str('nisdomainname', attribute=True, autofill=False, cli_name='nisdomain', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', query=True, required=False)
 option: Str('ipauniqueid', attribute=True, autofill=False, cli_name='uuid', multivalue=False, query=True, required=False)
 option: StrEnum('usercategory', attribute=True, autofill=False, cli_name='usercat', multivalue=False, query=True, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, autofill=False, cli_name='hostcat', multivalue=False, query=True, required=False, values=(u'all',))
+option: Str('externalhost', attribute=True, autofill=False, cli_name='externalhost', multivalue=True, query=True, required=False)
 option: Int('timelimit?', autofill=False, minvalue=0)
 option: Int('sizelimit?', autofill=False, minvalue=0)
 option: Flag('private', autofill=True, default=False, exclude='webui')
@@ -1989,12 +1997,13 @@ output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list
 output: Output('count', <type 'int'>, None)
 output: Output('truncated', <type 'bool'>, None)
 command: netgroup_mod
-args: 1,11,3
+args: 1,12,3
 arg: Str('cn', attribute=True, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=True)
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, required=False)
 option: Str('nisdomainname', attribute=True, autofill=False, cli_name='nisdomain', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', required=False)
 option: StrEnum('usercategory', attribute=True, autofill=False, cli_name='usercat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, autofill=False, cli_name='hostcat', multivalue=False, required=False, values=(u'all',))
+option: Str('externalhost', attribute=True, autofill=False, cli_name='externalhost', multivalue=True, required=False)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Str('delattr*', cli_name='delattr', exclude='webui')
@@ -2487,13 +2496,14 @@ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
 output: Output('value', <type 'unicode'>, None)
 command: selinuxusermap_add
-args: 1,10,3
+args: 1,11,3
 arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, required=True)
 option: Str('ipaselinuxuser', attribute=True, cli_name='selinuxuser', multivalue=False, required=True)
 option: Str('seealso', attribute=True, cli_name='hbacrule', multivalue=False, required=False)
 option: StrEnum('usercategory', attribute=True, cli_name='usercat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, cli_name='hostcat', multivalue=False, required=False, values=(u'all',))
 option: Str('description', attribute=True, cli_name='desc', multivalue=False, required=False)
+option: Bool('ipaenabledflag', attribute=True, cli_name='ipaenabledflag', multivalue=False, required=False)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@@ -2544,14 +2554,15 @@ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('result', <type 'bool'>, None)
 output: Output('value', <type 'unicode'>, None)
 command: selinuxusermap_find
-args: 1,12,4
+args: 1,13,4
 arg: Str('criteria?', noextrawhitespace=False)
 option: Str('cn', attribute=True, autofill=False, cli_name='name', multivalue=False, primary_key=True, query=True, required=False)
 option: Str('ipaselinuxuser', attribute=True, autofill=False, cli_name='selinuxuser', multivalue=False, query=True, required=False)
 option: Str('seealso', attribute=True, autofill=False, cli_name='hbacrule', multivalue=False, query=True, required=False)
 option: StrEnum('usercategory', attribute=True, autofill=False, cli_name='usercat', multivalue=False, query=True, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, autofill=False, cli_name='hostcat', multivalue=False, query=True, required=False, values=(u'all',))
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, query=True, required=False)
+option: Bool('ipaenabledflag', attribute=True, autofill=False, cli_name='ipaenabledflag', multivalue=False, query=True, required=False)
 option: Int('timelimit?', autofill=False, minvalue=0)
 option: Int('sizelimit?', autofill=False, minvalue=0)
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@@ -2563,13 +2574,14 @@ output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list
 output: Output('count', <type 'int'>, None)
 output: Output('truncated', <type 'bool'>, None)
 command: selinuxusermap_mod
-args: 1,12,3
+args: 1,13,3
 arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, query=True, required=True)
 option: Str('ipaselinuxuser', attribute=True, autofill=False, cli_name='selinuxuser', multivalue=False, required=False)
 option: Str('seealso', attribute=True, autofill=False, cli_name='hbacrule', multivalue=False, required=False)
 option: StrEnum('usercategory', attribute=True, autofill=False, cli_name='usercat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, autofill=False, cli_name='hostcat', multivalue=False, required=False, values=(u'all',))
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, required=False)
+option: Bool('ipaenabledflag', attribute=True, autofill=False, cli_name='ipaenabledflag', multivalue=False, required=False)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Str('delattr*', cli_name='delattr', exclude='webui')
@@ -2834,18 +2846,20 @@ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
 output: Output('value', <type 'unicode'>, None)
 command: sudorule_add
-args: 1,15,3
+args: 1,17,3
 arg: Str('cn', attribute=True, cli_name='sudorule_name', multivalue=False, primary_key=True, required=True)
 option: Str('description', attribute=True, cli_name='desc', multivalue=False, required=False)
+option: Bool('ipaenabledflag', attribute=True, cli_name='ipaenabledflag', multivalue=False, required=False)
 option: StrEnum('usercategory', attribute=True, cli_name='usercat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, cli_name='hostcat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('cmdcategory', attribute=True, cli_name='cmdcat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('ipasudorunasusercategory', attribute=True, cli_name='runasusercat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('ipasudorunasgroupcategory', attribute=True, cli_name='runasgroupcat', multivalue=False, required=False, values=(u'all',))
 option: Int('sudoorder', attribute=True, cli_name='order', default=0, minvalue=0, multivalue=False, required=False)
 option: Str('externaluser', attribute=True, cli_name='externaluser', multivalue=False, required=False)
 option: Str('ipasudorunasextuser', attribute=True, cli_name='runasexternaluser', multivalue=False, required=False)
 option: Str('ipasudorunasextgroup', attribute=True, cli_name='runasexternalgroup', multivalue=False, required=False)
+option: Str('externalhost', attribute=True, cli_name='externalhost', multivalue=True, required=False)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@@ -2940,19 +2954,21 @@ args: 1,0,1
 arg: Str('cn', attribute=True, cli_name='sudorule_name', multivalue=False, primary_key=True, query=True, required=True)
 output: Output('result', None, None)
 command: sudorule_find
-args: 1,17,4
+args: 1,19,4
 arg: Str('criteria?', noextrawhitespace=False)
 option: Str('cn', attribute=True, autofill=False, cli_name='sudorule_name', multivalue=False, primary_key=True, query=True, required=False)
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, query=True, required=False)
+option: Bool('ipaenabledflag', attribute=True, autofill=False, cli_name='ipaenabledflag', multivalue=False, query=True, required=False)
 option: StrEnum('usercategory', attribute=True, autofill=False, cli_name='usercat', multivalue=False, query=True, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, autofill=False, cli_name='hostcat', multivalue=False, query=True, required=False, values=(u'all',))
 option: StrEnum('cmdcategory', attribute=True, autofill=False, cli_name='cmdcat', multivalue=False, query=True, required=False, values=(u'all',))
 option: StrEnum('ipasudorunasusercategory', attribute=True, autofill=False, cli_name='runasusercat', multivalue=False, query=True, required=False, values=(u'all',))
 option: StrEnum('ipasudorunasgroupcategory', attribute=True, autofill=False, cli_name='runasgroupcat', multivalue=False, query=True, required=False, values=(u'all',))
 option: Int('sudoorder', attribute=True, autofill=False, cli_name='order', default=0, minvalue=0, multivalue=False, query=True, required=False)
 option: Str('externaluser', attribute=True, autofill=False, cli_name='externaluser', multivalue=False, query=True, required=False)
 option: Str('ipasudorunasextuser', attribute=True, autofill=False, cli_name='runasexternaluser', multivalue=False, query=True, required=False)
 option: Str('ipasudorunasextgroup', attribute=True, autofill=False, cli_name='runasexternalgroup', multivalue=False, query=True, required=False)
+option: Str('externalhost', attribute=True, autofill=False, cli_name='externalhost', multivalue=True, query=True, required=False)
 option: Int('timelimit?', autofill=False, minvalue=0)
 option: Int('sizelimit?', autofill=False, minvalue=0)
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@@ -2964,18 +2980,20 @@ output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list
 output: Output('count', <type 'int'>, None)
 output: Output('truncated', <type 'bool'>, None)
 command: sudorule_mod
-args: 1,17,3
+args: 1,19,3
 arg: Str('cn', attribute=True, cli_name='sudorule_name', multivalue=False, primary_key=True, query=True, required=True)
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, required=False)
+option: Bool('ipaenabledflag', attribute=True, autofill=False, cli_name='ipaenabledflag', multivalue=False, required=False)
 option: StrEnum('usercategory', attribute=True, autofill=False, cli_name='usercat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, autofill=False, cli_name='hostcat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('cmdcategory', attribute=True, autofill=False, cli_name='cmdcat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('ipasudorunasusercategory', attribute=True, autofill=False, cli_name='runasusercat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('ipasudorunasgroupcategory', attribute=True, autofill=False, cli_name='runasgroupcat', multivalue=False, required=False, values=(u'all',))
 option: Int('sudoorder', attribute=True, autofill=False, cli_name='order', default=0, minvalue=0, multivalue=False, required=False)
 option: Str('externaluser', attribute=True, autofill=False, cli_name='externaluser', multivalue=False, required=False)
 option: Str('ipasudorunasextuser', attribute=True, autofill=False, cli_name='runasexternaluser', multivalue=False, required=False)
 option: Str('ipasudorunasextgroup', attribute=True, autofill=False, cli_name='runasexternalgroup', multivalue=False, required=False)
+option: Str('externalhost', attribute=True, autofill=False, cli_name='externalhost', multivalue=True, required=False)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Str('delattr*', cli_name='delattr', exclude='webui')
@@ -3067,7 +3085,7 @@ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
 output: Output('value', <type 'unicode'>, None)
 command: user_add
-args: 1,33,3
+args: 1,34,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, required=True)
 option: Str('givenname', attribute=True, cli_name='first', multivalue=False, required=True)
 option: Str('sn', attribute=True, cli_name='last', multivalue=False, required=True)
@@ -3095,6 +3113,7 @@ option: Str('ou', attribute=True, cli_name='orgunit', multivalue=False, required
 option: Str('title', attribute=True, cli_name='title', multivalue=False, required=False)
 option: Str('manager', attribute=True, cli_name='manager', multivalue=False, required=False)
 option: Str('carlicense', attribute=True, cli_name='carlicense', multivalue=False, required=False)
+option: Bool('nsaccountlock', attribute=True, cli_name='nsaccountlock', multivalue=False, required=False)
 option: Bytes('ipasshpubkey', attribute=True, cli_name='sshpubkey', multivalue=True, required=False)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('addattr*', cli_name='addattr', exclude='webui')
@@ -3125,7 +3144,7 @@ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('result', <type 'bool'>, None)
 output: Output('value', <type 'unicode'>, None)
 command: user_find
-args: 1,43,4
+args: 1,44,4
 arg: Str('criteria?', noextrawhitespace=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: Str('givenname', attribute=True, autofill=False, cli_name='first', multivalue=False, query=True, required=False)
@@ -3153,6 +3172,7 @@ option: Str('ou', attribute=True, autofill=False, cli_name='orgunit', multivalue
 option: Str('title', attribute=True, autofill=False, cli_name='title', multivalue=False, query=True, required=False)
 option: Str('manager', attribute=True, autofill=False, cli_name='manager', multivalue=False, query=True, required=False)
 option: Str('carlicense', attribute=True, autofill=False, cli_name='carlicense', multivalue=False, query=True, required=False)
+option: Bool('nsaccountlock', attribute=True, autofill=False, cli_name='nsaccountlock', multivalue=False, query=True, required=False)
 option: Int('timelimit?', autofill=False, minvalue=0)
 option: Int('sizelimit?', autofill=False, minvalue=0)
 option: Flag('whoami', autofill=True, default=False)
@@ -3175,7 +3195,7 @@ output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list
 output: Output('count', <type 'int'>, None)
 output: Output('truncated', <type 'bool'>, None)
 command: user_mod
-args: 1,34,3
+args: 1,35,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('givenname', attribute=True, autofill=False, cli_name='first', multivalue=False, required=False)
 option: Str('sn', attribute=True, autofill=False, cli_name='last', multivalue=False, required=False)
@@ -3202,6 +3222,7 @@ option: Str('ou', attribute=True, autofill=False, cli_name='orgunit', multivalue
 option: Str('title', attribute=True, autofill=False, cli_name='title', multivalue=False, required=False)
 option: Str('manager', attribute=True, autofill=False, cli_name='manager', multivalue=False, required=False)
 option: Str('carlicense', attribute=True, autofill=False, cli_name='carlicense', multivalue=False, required=False)
+option: Bool('nsaccountlock', attribute=True, autofill=False, cli_name='nsaccountlock', multivalue=False, required=False)
 option: Bytes('ipasshpubkey', attribute=True, autofill=False, cli_name='sshpubkey', multivalue=True, required=False)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('addattr*', cli_name='addattr', exclude='webui')
diff --git a/VERSION b/VERSION
index f27fb473e65dd2db8e819d45e2dd84dc942bb41f..1ea26c1dfb0c9ce7b928324f528f1557cbc6ab68 100644
--- a/VERSION
+++ b/VERSION
@@ -79,4 +79,4 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=35
+IPA_API_VERSION_MINOR=36
diff --git a/ipalib/parameters.py b/ipalib/parameters.py
index 83a86544d5b66154944b9b279c042b638d3c57a5..529f15b3719ecb190dd7655abfaec9fb7c20b56c 100644
--- a/ipalib/parameters.py
+++ b/ipalib/parameters.py
@@ -330,6 +330,9 @@ class Param(ReadOnly):
               commands
             * no_update: do not include the parameter for crud.update based
               commands
+            * no_option: this attribute is not displayed in the CLI, usually
+              because there's a better way of setting it (for example, a
+              separate command)
             * virtual_attribute: the parameter is not stored physically in the
               LDAP and thus attribute `attribute` is not enabled
             * suppress_empty (Output parameters only): do not display parameter
diff --git a/ipalib/plugable.py b/ipalib/plugable.py
index 293db9241d55bc664268908bc75b7f67022259de..f3d185e14332f9f97937e2f1bc26069447eab855 100644
--- a/ipalib/plugable.py
+++ b/ipalib/plugable.py
@@ -646,7 +646,7 @@ def import_plugins(self, package):
                 if self.env.startup_traceback:
                     import traceback
                     self.log.error('could not load plugin module %r\n%s', pyfile, traceback.format_exc())
-                raise e
+                raise
 
     def finalize(self):
         """
diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py
index 2851f0f270d9e2bdba4780cc7bf308a76e180fd2..7664928beed250221af23137f0f1dbaf8b84e496 100644
--- a/ipalib/plugins/baseldap.py
+++ b/ipalib/plugins/baseldap.py
@@ -320,7 +320,7 @@ def validate_externalhost(ugettext, hostname):
 
 external_host_param = Str('externalhost*', validate_externalhost,
         label=_('External host'),
-        flags=['no_create', 'no_update', 'no_search'],
+        flags=['no_option'],
 )
 
 
@@ -819,6 +819,11 @@ def _convert_2_dict(self, attrs):
             m = re.match("\s*(.*?)\s*=\s*(.*?)\s*$", a)
             attr = str(m.group(1)).lower()
             value = m.group(2)
+            if attr in self.obj.params and attr not in self.params:
+                # The attribute is managed by IPA, but it didn't get cloned
+                # to the command. This happens with no_update/no_create attrs.
+                raise errors.ValidationError(
+                    name=attr, error=_('attribute is not configurable'))
             if len(value) == 0:
                 # None means "delete this attribute"
                 value = None
@@ -919,17 +924,10 @@ def process_attr_options(self, entry_attrs, dn, keys, options):
         # normalize all values
         changedattrs = setattrs | addattrs | delattrs
         for attr in changedattrs:
-            if attr in self.obj.params:
+            if attr in self.params and self.params[attr].attribute:
                 # convert single-value params to scalars
+                param = self.params[attr]
                 value = entry_attrs[attr]
-                try:
-                    param = self.params[attr]
-                except KeyError:
-                    # The CRUD classes filter their disallowed parameters out.
-                    # Yet {set,add,del}attr are powerful enough to change these
-                    # (e.g. Config's ipacertificatesubjectbase)
-                    # So, use the parent's attribute
-                    param = self.obj.params[attr]
                 if not param.multivalue:
                     if len(value) == 1:
                         value = value[0]
diff --git a/ipalib/plugins/hbacrule.py b/ipalib/plugins/hbacrule.py
index 33440ccde9ef63df7d087d17f0d5d224c75833fa..460083622ef3c8b29b2395b37615d2a996841eba 100644
--- a/ipalib/plugins/hbacrule.py
+++ b/ipalib/plugins/hbacrule.py
@@ -18,7 +18,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from ipalib import api, errors
-from ipalib import AccessTime, Password, Str, StrEnum
+from ipalib import AccessTime, Password, Str, StrEnum, Bool
 from ipalib.plugins.baseldap import *
 from ipalib import _, ngettext
 
@@ -183,9 +183,9 @@ class hbacrule(LDAPObject):
             cli_name='desc',
             label=_('Description'),
         ),
-        Flag('ipaenabledflag?',
+        Bool('ipaenabledflag?',
              label=_('Enabled'),
-             flags=['no_create', 'no_update', 'no_search'],
+             flags=['no_option'],
         ),
         Str('memberuser_user?',
             label=_('Users'),
diff --git a/ipalib/plugins/selinuxusermap.py b/ipalib/plugins/selinuxusermap.py
index e33e1016192d62312aa5f4f0dcdbafea23327216..e6179cee9006ac744e82df7cf11c3eca9aae7849 100644
--- a/ipalib/plugins/selinuxusermap.py
+++ b/ipalib/plugins/selinuxusermap.py
@@ -18,7 +18,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from ipalib import api, errors
-from ipalib import Str, StrEnum
+from ipalib import Str, StrEnum, Bool
 from ipalib.plugins.baseldap import *
 from ipalib import _, ngettext
 from ipalib.plugins.hbacrule import is_all
@@ -172,9 +172,9 @@ class selinuxusermap(LDAPObject):
             cli_name='desc',
             label=_('Description'),
         ),
-        Flag('ipaenabledflag?',
+        Bool('ipaenabledflag?',
              label=_('Enabled'),
-             flags=['no_create', 'no_update', 'no_search'],
+             flags=['no_option'],
         ),
         Str('memberuser_user?',
             label=_('Users'),
diff --git a/ipalib/plugins/sudorule.py b/ipalib/plugins/sudorule.py
index 2c0358e879fc203106731ce966ed697e85c4e84f..723cce2e416b562d520445996814498d17643a79 100644
--- a/ipalib/plugins/sudorule.py
+++ b/ipalib/plugins/sudorule.py
@@ -18,7 +18,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from ipalib import api, errors
-from ipalib import Str, StrEnum
+from ipalib import Str, StrEnum, Bool
 from ipalib.plugins.baseldap import *
 from ipalib.plugins.hbacrule import is_all
 from ipalib import _, ngettext
@@ -110,9 +110,9 @@ class sudorule(LDAPObject):
             cli_name='desc',
             label=_('Description'),
         ),
-        Flag('ipaenabledflag?',
+        Bool('ipaenabledflag?',
              label=_('Enabled'),
-             flags=['no_create', 'no_update', 'no_search'],
+             flags=['no_option'],
         ),
         StrEnum('usercategory?',
             cli_name='usercat',
diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index 3bea7af6f25bdab4f544922d9305b5474fcea7a8..2e069bde3ee338f3292594c11dc8627490233cb2 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -338,7 +338,7 @@ class user(LDAPObject):
         ),
         Bool('nsaccountlock?',
             label=_('Account disabled'),
-            flags=['no_create', 'no_update', 'no_search'],
+            flags=['no_option'],
         ),
         Bytes('ipasshpubkey*', validate_sshpubkey,
             cli_name='sshpubkey',
diff --git a/tests/test_xmlrpc/test_attr.py b/tests/test_xmlrpc/test_attr.py
index 5916ebd2d0f3b7bce8fc3160bce86d703145880d..248d21570a591696c781b2a530c6ca5c9576f341 100644
--- a/tests/test_xmlrpc/test_attr.py
+++ b/tests/test_xmlrpc/test_attr.py
@@ -471,7 +471,8 @@ class test_attr(Declarative):
             command=(
                 'config_mod', [], dict(addattr=u'ipacertificatesubjectbase=0=DOMAIN.COM')
             ),
-            expected=errors.OnlyOneValueAllowed(attr='ipacertificatesubjectbase'),
+            expected=errors.ValidationError(name='ipacertificatesubjectbase',
+                error='attribute is not configurable'),
         ),
 
         dict(
diff --git a/tests/test_xmlrpc/test_user_plugin.py b/tests/test_xmlrpc/test_user_plugin.py
index 5377681078319f57f4f059aeb9004639f11616c8..4b2be5c325ab8d5a73a62f9c979ca5f40f3498bb 100644
--- a/tests/test_xmlrpc/test_user_plugin.py
+++ b/tests/test_xmlrpc/test_user_plugin.py
@@ -344,6 +344,16 @@ class test_user(Declarative):
             ),
         ),
 
+        dict(
+            desc='Assert user is disabled',
+            command=('user_find', [user1], {}),
+            expected=dict(
+                result=[lambda d: d['nsaccountlock'] == True],
+                summary=u'1 user matched',
+                count=1,
+                truncated=False,
+            ),
+        ),
 
         dict(
             desc='Enable %r'  % user1,
@@ -357,6 +367,63 @@ class test_user(Declarative):
             ),
         ),
 
+        dict(
+            desc='Assert user is enabled',
+            command=('user_find', [user1], {}),
+            expected=dict(
+                result=[lambda d: d['nsaccountlock'] == False],
+                summary=u'1 user matched',
+                count=1,
+                truncated=False,
+            ),
+        ),
+
+        dict(
+            desc='Disable %r using setattr' % user1,
+            command=('user_mod', [user1], dict(setattr=u'nsaccountlock=True')),
+            expected=dict(
+                result=lambda d: d['nsaccountlock'] == True,
+                value=user1,
+                summary=u'Modified user "tuser1"',
+            ),
+        ),
+
+        dict(
+            desc='Enable %r using setattr' % user1,
+            command=('user_mod', [user1], dict(setattr=u'nsaccountlock=False')),
+            expected=dict(
+                result=lambda d: d['nsaccountlock'] == False,
+                value=user1,
+                summary=u'Modified user "tuser1"',
+            ),
+        ),
+
+        dict(
+            desc='Disable %r using user_mod' % user1,
+            command=('user_mod', [user1], dict(nsaccountlock=True)),
+            expected=dict(
+                result=lambda d: d['nsaccountlock'] == True,
+                value=user1,
+                summary=u'Modified user "tuser1"',
+            ),
+        ),
+
+        dict(
+            desc='Enable %r using user_mod' % user1,
+            command=('user_mod', [user1], dict(nsaccountlock=False)),
+            expected=dict(
+                result=lambda d: d['nsaccountlock'] == False,
+                value=user1,
+                summary=u'Modified user "tuser1"',
+            ),
+        ),
+
+        dict(
+            desc='Try setting virtual attribute on %r using setattr' % user1,
+            command=('user_mod', [user1], dict(setattr=u'random=xyz123')),
+            expected=errors.ObjectclassViolation(
+                info='attribute "random" not allowed'),
+        ),
 
         dict(
             desc='Update %r' % user1,
-- 
1.7.10.2

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to