permission plugin: Write support for extratargetfilter

Extend the permission-add and permission-mod commands to process
extratargetfilter.

Part of the work for: https://fedorahosted.org/freeipa/ticket/4216

Reviewed-By: Martin Kosek <mkosek@redhat.com>
This commit is contained in:
Petr Viktorin 2014-03-04 16:59:33 +01:00 committed by Martin Kosek
parent 3120a6833e
commit f58ffe176c

View File

@ -285,23 +285,19 @@ class permission(baseldap.LDAPObject):
raise errors.ACIError( raise errors.ACIError(
info=_('A SYSTEM permission may not be modified or removed')) info=_('A SYSTEM permission may not be modified or removed'))
def postprocess_result(self, entry, options): def _get_filter_attr_info(self, entry):
"""Update a permission entry for output (in place) """Get information on filter-related virtual attributes
:param entry: The entry to update Returns a dict with this information:
:param options: 'implicit_targetfilters': targetfilters implied by memberof and type
Command options. Contains keys such as ``raw``, ``all``, 'memberof': list of names of groups from memberof
``pkey_only``, ``version``. 'type': the type
""" """
old_client = not client_has_capability(
options['version'], 'permissions2')
if not options.get('raw') and not options.get('pkey_only'):
ipapermtargetfilter = entry.get('ipapermtargetfilter', []) ipapermtargetfilter = entry.get('ipapermtargetfilter', [])
ipapermtarget = entry.single_value.get('ipapermtarget')
ipapermlocation = entry.single_value.get('ipapermlocation') ipapermlocation = entry.single_value.get('ipapermlocation')
implicit_targetfilters = set() implicit_targetfilters = set()
result = {'implicit_targetfilters': implicit_targetfilters}
# memberof # memberof
memberof = [] memberof = []
@ -315,15 +311,7 @@ class permission(baseldap.LDAPObject):
memberof.append(dn[0].value) memberof.append(dn[0].value)
implicit_targetfilters.add(match.group(0)) implicit_targetfilters.add(match.group(0))
if memberof: if memberof:
entry['memberof'] = memberof result['memberof'] = memberof
# targetgroup
if ipapermtarget:
dn = DN(ipapermtarget)
if (dn[1:] == DN(self.api.Object.group.container_dn,
self.api.env.basedn)[:] and
dn[0].attr == 'cn' and dn[0].value != '*'):
entry.single_value['targetgroup'] = dn[0].value
# type # type
if ipapermtargetfilter and ipapermlocation: if ipapermtargetfilter and ipapermlocation:
@ -346,13 +334,44 @@ class permission(baseldap.LDAPObject):
else: else:
break break
else: else:
entry.single_value['type'] = unicode(obj.name) result['type'] = [unicode(obj.name)]
implicit_targetfilters |= objectclass_targetfilters implicit_targetfilters |= objectclass_targetfilters
break break
if ipapermtargetfilter: return result
def postprocess_result(self, entry, options):
"""Update a permission entry for output (in place)
:param entry: The entry to update
:param options:
Command options. Contains keys such as ``raw``, ``all``,
``pkey_only``, ``version``.
"""
old_client = not client_has_capability(
options['version'], 'permissions2')
if not options.get('raw') and not options.get('pkey_only'):
ipapermtargetfilter = entry.get('ipapermtargetfilter', [])
ipapermtarget = entry.single_value.get('ipapermtarget')
# targetgroup
if ipapermtarget:
dn = DN(ipapermtarget)
if (dn[1:] == DN(self.api.Object.group.container_dn,
self.api.env.basedn)[:] and
dn[0].attr == 'cn' and dn[0].value != '*'):
entry.single_value['targetgroup'] = dn[0].value
filter_attr_info = self._get_filter_attr_info(entry)
if 'type' in filter_attr_info:
entry['type'] = filter_attr_info['type']
if 'memberof' in filter_attr_info:
entry['memberof'] = filter_attr_info['memberof']
if 'implicit_targetfilters' in filter_attr_info:
extratargetfilter = sorted( extratargetfilter = sorted(
set(ipapermtargetfilter) - implicit_targetfilters) set(ipapermtargetfilter) -
filter_attr_info['implicit_targetfilters'])
if extratargetfilter: if extratargetfilter:
entry['extratargetfilter'] = extratargetfilter entry['extratargetfilter'] = extratargetfilter
@ -652,7 +671,9 @@ class permission(baseldap.LDAPObject):
raise ValueError('Cannot convert ACI, %r != %r' % (new_acistring, raise ValueError('Cannot convert ACI, %r != %r' % (new_acistring,
acistring)) acistring))
def preprocess_options(self, options, return_filter_ops=False): def preprocess_options(self, options,
return_filter_ops=False,
merge_targetfilter=False):
"""Preprocess options (in-place) """Preprocess options (in-place)
:param options: A dictionary of options :param options: A dictionary of options
@ -667,8 +688,19 @@ class permission(baseldap.LDAPObject):
- remove: list of regular expression objects; values that match - remove: list of regular expression objects; values that match
any of them sould be removed any of them sould be removed
- add: list of values to be added, after any removals - add: list of values to be added, after any removals
:merge_targetfilter:
If true, the extratargetfilter is copied into ipapermtargetfilter.
""" """
if 'extratargetfilter' in options:
if 'ipapermtargetfilter' in options:
raise errors.ValidationError(
name='ipapermtargetfilter',
error=_('cannot specify full target filter '
'and extra target filter simultaneously'))
if merge_targetfilter:
options['ipapermtargetfilter'] = options['extratargetfilter']
filter_ops = {'add': [], 'remove': []} filter_ops = {'add': [], 'remove': []}
if options.get('subtree'): if options.get('subtree'):
@ -836,7 +868,7 @@ class permission_add(baseldap.LDAPCreate):
# Need to override execute so that processed options apply to # Need to override execute so that processed options apply to
# the whole command, not just the callbacks # the whole command, not just the callbacks
def execute(self, *keys, **options): def execute(self, *keys, **options):
self.obj.preprocess_options(options) self.obj.preprocess_options(options, merge_targetfilter=True)
return super(permission_add, self).execute(*keys, **options) return super(permission_add, self).execute(*keys, **options)
def pre_callback(self, ldap, dn, entry, attrs_list, *keys, **options): def pre_callback(self, ldap, dn, entry, attrs_list, *keys, **options):
@ -950,7 +982,8 @@ class permission_mod(baseldap.LDAPUpdate):
error=_('cannot rename managed permissions')) error=_('cannot rename managed permissions'))
option = self.options[option_name] option = self.options[option_name]
allow_mod = 'allow_mod_for_managed_permission' in option.flags allow_mod = 'allow_mod_for_managed_permission' in option.flags
if option.attribute and not allow_mod: if (option.attribute and not allow_mod or
option_name == 'extratargetfilter'):
raise errors.ValidationError( raise errors.ValidationError(
name=option_name, name=option_name,
error=_('not modifiable on managed permissions')) error=_('not modifiable on managed permissions'))
@ -994,6 +1027,14 @@ class permission_mod(baseldap.LDAPUpdate):
key not in self.obj.attribute_members): key not in self.obj.attribute_members):
entry.setdefault(key, value) entry.setdefault(key, value)
# For extratargetfilter, add it to the implicit filters
# to get the full target filter
if 'extratargetfilter' in options:
filter_attr_info = self.obj._get_filter_attr_info(entry)
entry['ipapermtargetfilter'] = (
list(options['extratargetfilter'] or []) +
list(filter_attr_info['implicit_targetfilters']))
filter_ops = context.filter_ops filter_ops = context.filter_ops
removes = filter_ops.get('remove', []) removes = filter_ops.get('remove', [])
new_filters = set( new_filters = set(