diff options
-rw-r--r-- | ipalib/plugins/baseldap.py | 52 | ||||
-rw-r--r-- | tests/test_xmlrpc/test_attr.py | 113 |
2 files changed, 148 insertions, 17 deletions
diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py index 38f369a7..daf1b07f 100644 --- a/ipalib/plugins/baseldap.py +++ b/ipalib/plugins/baseldap.py @@ -794,8 +794,6 @@ last, after all sets and adds."""), Convert a string in the form of name/value pairs into a dictionary. The incoming attribute may be a string or a list. - Any attribute found that is also a param is validated. - :param attrs: A list of name/value pairs :param append: controls whether this returns a list of values or a single @@ -811,15 +809,6 @@ last, after all sets and adds."""), if len(value) == 0: # None means "delete this attribute" value = None - if attr in self.params: - try: - value = self.params[attr](value) - except errors.ValidationError, err: - raise errors.ValidationError(name=attr, error=err.error) - except errors.ConversionError, err: - raise errors.ValidationError(name=attr, error=err.error) - if self.api.env.in_server: - value = self.params[attr].encode(value) if append and attr in newdict: if type(value) in (tuple,): newdict[attr] += list(value) @@ -923,12 +912,41 @@ last, after all sets and adds."""), # normalize all values changedattrs = setattrs | addattrs | delattrs for attr in changedattrs: - # remove duplicite and invalid values - entry_attrs[attr] = list(set([val for val in entry_attrs[attr] if val])) - if not entry_attrs[attr]: - entry_attrs[attr] = None - elif isinstance(entry_attrs[attr], (tuple, list)) and len(entry_attrs[attr]) == 1: - entry_attrs[attr] = entry_attrs[attr][0] + if attr in self.obj.params: + # convert single-value params to scalars + 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] + elif not value: + value = None + else: + raise errors.OnlyOneValueAllowed(attr=attr) + # validate, convert and encode params + try: + value = param(value) + except errors.ValidationError, err: + raise errors.ValidationError(name=attr, error=err.error) + except errors.ConversionError, err: + raise errors.ConversionError(name=attr, error=err.error) + value = param.encode(value) + entry_attrs[attr] = value + else: + # unknown attribute: remove duplicite and invalid values + entry_attrs[attr] = list(set([val for val in entry_attrs[attr] if val])) + if not entry_attrs[attr]: + entry_attrs[attr] = None + elif isinstance(entry_attrs[attr], (tuple, list)) and len(entry_attrs[attr]) == 1: + entry_attrs[attr] = entry_attrs[attr][0] + class LDAPCreate(BaseLDAPCommand, crud.Create): """ diff --git a/tests/test_xmlrpc/test_attr.py b/tests/test_xmlrpc/test_attr.py index ef239709..e6872a67 100644 --- a/tests/test_xmlrpc/test_attr.py +++ b/tests/test_xmlrpc/test_attr.py @@ -402,4 +402,117 @@ class test_attr(Declarative): ), ), + dict( + desc='Lock %r using setattr' % user1, + command=( + 'user_mod', [user1], dict(setattr=u'nsaccountlock=TrUe') + ), + expected=dict( + result=dict( + givenname=[u'Finkle'], + homedirectory=[u'/home/tuser1'], + loginshell=[u'/bin/sh'], + sn=[u'User1'], + uid=[user1], + uidnumber=[fuzzy_digits], + gidnumber=[fuzzy_digits], + mail=[u'test@example.com', u'test2@example.com'], + memberof_group=[u'ipausers'], + telephonenumber=[u'202-888-9833'], + nsaccountlock=True, + has_keytab=False, + has_password=False, + ), + summary=u'Modified user "tuser1"', + value=user1, + ), + ), + + dict( + desc='Unlock %r using addattr&delattr' % user1, + command=( + 'user_mod', [user1], dict( + addattr=u'nsaccountlock=FaLsE', + delattr=u'nsaccountlock=True') + ), + expected=dict( + result=dict( + givenname=[u'Finkle'], + homedirectory=[u'/home/tuser1'], + loginshell=[u'/bin/sh'], + sn=[u'User1'], + uid=[user1], + uidnumber=[fuzzy_digits], + gidnumber=[fuzzy_digits], + mail=[u'test@example.com', u'test2@example.com'], + memberof_group=[u'ipausers'], + telephonenumber=[u'202-888-9833'], + nsaccountlock=False, + has_keytab=False, + has_password=False, + ), + summary=u'Modified user "tuser1"', + value=user1, + ), + ), + + dict( + desc='Try adding a new group search fields config entry', + command=( + 'config_mod', [], dict(addattr=u'ipagroupsearchfields=newattr') + ), + expected=errors.OnlyOneValueAllowed(attr='ipagroupsearchfields'), + ), + + dict( + desc='Try adding a new cert subject base config entry', + command=( + 'config_mod', [], dict(addattr=u'ipacertificatesubjectbase=0=DOMAIN.COM') + ), + expected=errors.OnlyOneValueAllowed(attr='ipacertificatesubjectbase'), + ), + + dict( + desc='Try deleting a required config entry', + command=( + 'config_mod', [], dict(delattr=u'ipasearchrecordslimit=100') + ), + expected=errors.RequirementError(name='ipasearchrecordslimit'), + ), + + dict( + desc='Try setting nonexistent attribute', + command=('config_mod', [], dict(setattr=u'invalid_attr=false')), + expected=errors.ObjectclassViolation( + info='attribute "invalid_attr" not allowed'), + ), + + dict( + desc='Try setting out-of-range krbpwdmaxfailure', + command=('pwpolicy_mod', [], dict(setattr=u'krbpwdmaxfailure=-1')), + expected=errors.ValidationError(name='krbpwdmaxfailure', + error='must be at least 0'), + ), + + dict( + desc='Try setting out-of-range maxfail', + command=('pwpolicy_mod', [], dict(krbpwdmaxfailure=u'-1')), + expected=errors.ValidationError(name='maxfail', + error='must be at least 0'), + ), + + dict( + desc='Try setting non-numeric krbpwdmaxfailure', + command=('pwpolicy_mod', [], dict(setattr=u'krbpwdmaxfailure=abc')), + expected=errors.ConversionError(name='krbpwdmaxfailure', + error='must be an integer'), + ), + + dict( + desc='Try setting non-numeric maxfail', + command=('pwpolicy_mod', [], dict(krbpwdmaxfailure=u'abc')), + expected=errors.ConversionError(name='maxfail', + error='must be an integer'), + ), + ] |