mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Add support for setting/adding arbitrary attributes
This introduces 2 new params: --setattr and --addattr Both take a name/value pair, ala: ipa user-mod --setattr=postalcode=20601 jsmith --setattr replaces or sets the current attribute to the value --addattr adds the value to an attribute (or sets a new attribute) OptionsParser allows multiple versions of this, so you can have multiple setattr and addattr, either for the same attribute or for different attributes. ipa user-mod --addattr=postalcode=20601 --addattr=postalcode=30330 jsmith Values are silent dropped if either of these on an existing param: ipa user-mod --setattr=givenname=Jerry jsmith Is a no-op.
This commit is contained in:
parent
680bf7c548
commit
55c62ac79a
@ -473,6 +473,34 @@ class Command(HasParam):
|
|||||||
kw = self.args_options_2_params(*args, **options)
|
kw = self.args_options_2_params(*args, **options)
|
||||||
return dict(self.__attributes_2_entry(kw))
|
return dict(self.__attributes_2_entry(kw))
|
||||||
|
|
||||||
|
def __convert_2_dict(self, attrs, append=True):
|
||||||
|
"""
|
||||||
|
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 silently dropped.
|
||||||
|
|
||||||
|
append controls whether this returns a list of values or a single
|
||||||
|
value.
|
||||||
|
"""
|
||||||
|
newdict = {}
|
||||||
|
if not type(attrs) in (list, tuple):
|
||||||
|
attrs = [attrs]
|
||||||
|
for a in attrs:
|
||||||
|
m = re.match("\s*(.*?)\s*=\s*(.*?)\s*$", a)
|
||||||
|
attr = str(m.group(1)).lower()
|
||||||
|
value = m.group(2)
|
||||||
|
if len(value) == 0:
|
||||||
|
# None means "delete this attribute"
|
||||||
|
value = None
|
||||||
|
if attr not in self.params:
|
||||||
|
if append and attr in newdict:
|
||||||
|
newdict[attr].append(value)
|
||||||
|
else:
|
||||||
|
newdict[attr] = [value]
|
||||||
|
return newdict
|
||||||
|
|
||||||
def __attributes_2_entry(self, kw):
|
def __attributes_2_entry(self, kw):
|
||||||
for name in self.params:
|
for name in self.params:
|
||||||
if self.params[name].attribute and name in kw:
|
if self.params[name].attribute and name in kw:
|
||||||
@ -482,6 +510,23 @@ class Command(HasParam):
|
|||||||
else:
|
else:
|
||||||
yield (name, kw[name])
|
yield (name, kw[name])
|
||||||
|
|
||||||
|
adddict = {}
|
||||||
|
if 'setattr' in kw:
|
||||||
|
adddict = self.__convert_2_dict(kw['setattr'], append=False)
|
||||||
|
|
||||||
|
if 'addattr' in kw:
|
||||||
|
adddict.update(self.__convert_2_dict(kw['addattr']))
|
||||||
|
|
||||||
|
for name in adddict:
|
||||||
|
value = adddict[name]
|
||||||
|
if isinstance(value, list):
|
||||||
|
if len(value) == 1:
|
||||||
|
yield (name, value[0])
|
||||||
|
else:
|
||||||
|
yield (name, [v for v in value])
|
||||||
|
else:
|
||||||
|
yield (name, value)
|
||||||
|
|
||||||
def params_2_args_options(self, **params):
|
def params_2_args_options(self, **params):
|
||||||
"""
|
"""
|
||||||
Split params into (args, options).
|
Split params into (args, options).
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
Base classes for LDAP plugins.
|
Base classes for LDAP plugins.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
from ipalib import crud, errors, uuid
|
from ipalib import crud, errors, uuid
|
||||||
from ipalib import Command, Method, Object
|
from ipalib import Command, Method, Object
|
||||||
from ipalib import Flag, List, Str
|
from ipalib import Flag, List, Str
|
||||||
@ -27,6 +28,28 @@ from ipalib.base import NameSpace
|
|||||||
from ipalib.cli import to_cli, from_cli
|
from ipalib.cli import to_cli, from_cli
|
||||||
|
|
||||||
|
|
||||||
|
def validate_add_attribute(ugettext, attr):
|
||||||
|
validate_attribute(ugettext, 'addattr', attr)
|
||||||
|
|
||||||
|
def validate_set_attribute(ugettext, attr):
|
||||||
|
validate_attribute(ugettext, 'setattr', attr)
|
||||||
|
|
||||||
|
def validate_attribute(ugettext, name, attr):
|
||||||
|
m = re.match("\s*(.*?)\s*=\s*(.*?)\s*$", attr)
|
||||||
|
if not m or len(m.groups()) != 2:
|
||||||
|
raise errors.ValidationError(name=name, error='Invalid format. Should be name=value')
|
||||||
|
|
||||||
|
def get_attributes(attrs):
|
||||||
|
"""
|
||||||
|
Given a list of values in the form name=value, return a list of name.
|
||||||
|
"""
|
||||||
|
attrlist=[]
|
||||||
|
for attr in attrs:
|
||||||
|
m = re.match("\s*(.*?)\s*=\s*(.*?)\s*$", attr)
|
||||||
|
attrlist.append(str(m.group(1)).lower())
|
||||||
|
|
||||||
|
return attrlist
|
||||||
|
|
||||||
class LDAPObject(Object):
|
class LDAPObject(Object):
|
||||||
"""
|
"""
|
||||||
Object representing a LDAP entry.
|
Object representing a LDAP entry.
|
||||||
@ -111,6 +134,16 @@ class LDAPCreate(crud.Create):
|
|||||||
doc='print entries as they are stored in LDAP',
|
doc='print entries as they are stored in LDAP',
|
||||||
exclude='webui',
|
exclude='webui',
|
||||||
),
|
),
|
||||||
|
Str('addattr*', validate_add_attribute,
|
||||||
|
cli_name='addattr',
|
||||||
|
doc='Add an attribute/value pair. Format is attr=value',
|
||||||
|
exclude='webui',
|
||||||
|
),
|
||||||
|
Str('setattr*', validate_set_attribute,
|
||||||
|
cli_name='setattr',
|
||||||
|
doc='Set an attribute to an name/value pair. Format is attr=value',
|
||||||
|
exclude='webui',
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_args(self):
|
def get_args(self):
|
||||||
@ -241,6 +274,16 @@ class LDAPUpdate(LDAPQuery, crud.Update):
|
|||||||
cli_name='all',
|
cli_name='all',
|
||||||
doc='retrieve all attributes',
|
doc='retrieve all attributes',
|
||||||
),
|
),
|
||||||
|
Str('addattr*', validate_add_attribute,
|
||||||
|
cli_name='addattr',
|
||||||
|
doc='Add an attribute/value pair. Format is attr=value',
|
||||||
|
exclude='webui',
|
||||||
|
),
|
||||||
|
Str('setattr*', validate_set_attribute,
|
||||||
|
cli_name='setattr',
|
||||||
|
doc='Set an attribute to an name/value pair. Format is attr=value',
|
||||||
|
exclude='webui',
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def execute(self, *keys, **options):
|
def execute(self, *keys, **options):
|
||||||
@ -257,6 +300,24 @@ class LDAPUpdate(LDAPQuery, crud.Update):
|
|||||||
|
|
||||||
dn = self.pre_callback(ldap, dn, entry_attrs, attrs_list, *keys, **options)
|
dn = self.pre_callback(ldap, dn, entry_attrs, attrs_list, *keys, **options)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Some special handling is needed because we need to update the
|
||||||
|
values here rather than letting ldap.update_entry() do the work. We
|
||||||
|
have to do the work of adding new values to an existing attribute
|
||||||
|
because if we pass just what is addded only the new values get
|
||||||
|
set.
|
||||||
|
"""
|
||||||
|
if 'addattr' in options:
|
||||||
|
(dn, old_entry) = ldap.get_entry(dn, attrs_list)
|
||||||
|
attrlist = get_attributes(options['addattr'])
|
||||||
|
for attr in attrlist:
|
||||||
|
if attr in old_entry:
|
||||||
|
if type(entry_attrs[attr]) in (tuple,list):
|
||||||
|
entry_attrs[attr] = old_entry[attr] + entry_attrs[attr]
|
||||||
|
else:
|
||||||
|
old_entry[attr].append(entry_attrs[attr])
|
||||||
|
entry_attrs[attr] = old_entry[attr]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ldap.update_entry(dn, entry_attrs)
|
ldap.update_entry(dn, entry_attrs)
|
||||||
except errors.EmptyModlist:
|
except errors.EmptyModlist:
|
||||||
|
Loading…
Reference in New Issue
Block a user