Add missing --pkey-only option for selfservice and delegation

pkey-only functionality has to be implemented separately for these
modules as they are based on crud.Search instead of standard
LDAPSearch.

Delegation moduled was also fixed to support new format of ACI's
memberof attribute introduced in patch "Display the value of
memberOf ACIs in permission plugin."

https://fedorahosted.org/freeipa/ticket/2092
This commit is contained in:
Martin Kosek 2012-01-16 11:14:59 +01:00
parent f7753bf55c
commit 7f6c9ac04c
9 changed files with 106 additions and 68 deletions

View File

@ -27,7 +27,7 @@ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: Output('result', <type 'bool'>, None) output: Output('result', <type 'bool'>, None)
output: Output('value', <type 'unicode'>, None) output: Output('value', <type 'unicode'>, None)
command: aci_find command: aci_find
args: 1,15,4 args: 1,16,4
arg: Str('criteria?') arg: Str('criteria?')
option: Str('aciname', attribute=False, autofill=False, cli_name='name', multivalue=False, primary_key=True, query=True, required=False) option: Str('aciname', attribute=False, autofill=False, cli_name='name', multivalue=False, primary_key=True, query=True, required=False)
option: Str('permission', attribute=False, autofill=False, cli_name='permission', multivalue=False, query=True, required=False) option: Str('permission', attribute=False, autofill=False, cli_name='permission', multivalue=False, query=True, required=False)
@ -41,6 +41,7 @@ option: Str('subtree', attribute=False, autofill=False, cli_name='subtree', mult
option: Str('targetgroup', attribute=False, autofill=False, cli_name='targetgroup', multivalue=False, query=True, required=False) option: Str('targetgroup', attribute=False, autofill=False, cli_name='targetgroup', multivalue=False, query=True, required=False)
option: Bool('selfaci', attribute=False, autofill=False, cli_name='self', default=False, multivalue=False, query=True, required=False) option: Bool('selfaci', attribute=False, autofill=False, cli_name='self', default=False, multivalue=False, query=True, required=False)
option: StrEnum('aciprefix?', cli_name='prefix', multivalue=False, required=False, values=(u'permission', u'delegation', u'selfservice', u'none')) option: StrEnum('aciprefix?', cli_name='prefix', multivalue=False, required=False, values=(u'permission', u'delegation', u'selfservice', u'none'))
option: Flag('pkey_only?', autofill=True, default=False)
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Str('version?', exclude='webui') option: Str('version?', exclude='webui')
@ -560,13 +561,14 @@ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: Output('result', <type 'bool'>, None) output: Output('result', <type 'bool'>, None)
output: Output('value', <type 'unicode'>, None) output: Output('value', <type 'unicode'>, None)
command: delegation_find command: delegation_find
args: 1,8,4 args: 1,9,4
arg: Str('criteria?') arg: Str('criteria?')
option: Str('aciname', attribute=True, autofill=False, cli_name='name', multivalue=False, primary_key=True, query=True, required=False) option: Str('aciname', attribute=True, autofill=False, cli_name='name', multivalue=False, primary_key=True, query=True, required=False)
option: Str('permissions', attribute=True, autofill=False, cli_name='permissions', csv=True, multivalue=True, query=True, required=False) option: Str('permissions', attribute=True, autofill=False, cli_name='permissions', csv=True, multivalue=True, query=True, required=False)
option: Str('attrs', attribute=True, autofill=False, cli_name='attrs', csv=True, multivalue=True, query=True, required=False) option: Str('attrs', attribute=True, autofill=False, cli_name='attrs', csv=True, multivalue=True, query=True, required=False)
option: Str('memberof', attribute=True, autofill=False, cli_name='membergroup', multivalue=False, query=True, required=False) option: Str('memberof', attribute=True, autofill=False, cli_name='membergroup', multivalue=False, query=True, required=False)
option: Str('group', attribute=True, autofill=False, cli_name='group', multivalue=False, query=True, required=False) option: Str('group', attribute=True, autofill=False, cli_name='group', multivalue=False, query=True, required=False)
option: Flag('pkey_only?', autofill=True, default=False)
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Str('version?', exclude='webui') option: Str('version?', exclude='webui')
@ -2465,11 +2467,12 @@ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: Output('result', <type 'bool'>, None) output: Output('result', <type 'bool'>, None)
output: Output('value', <type 'unicode'>, None) output: Output('value', <type 'unicode'>, None)
command: selfservice_find command: selfservice_find
args: 1,6,4 args: 1,7,4
arg: Str('criteria?') arg: Str('criteria?')
option: Str('aciname', attribute=True, autofill=False, cli_name='name', multivalue=False, primary_key=True, query=True, required=False) option: Str('aciname', attribute=True, autofill=False, cli_name='name', multivalue=False, primary_key=True, query=True, required=False)
option: Str('permissions', attribute=True, autofill=False, cli_name='permissions', csv=True, multivalue=True, query=True, required=False) option: Str('permissions', attribute=True, autofill=False, cli_name='permissions', csv=True, multivalue=True, query=True, required=False)
option: Str('attrs', attribute=True, autofill=False, cli_name='attrs', csv=True, multivalue=True, query=True, required=False) option: Str('attrs', attribute=True, autofill=False, cli_name='attrs', csv=True, multivalue=True, query=True, required=False)
option: Flag('pkey_only?', autofill=True, default=False)
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
option: Str('version?', exclude='webui') option: Str('version?', exclude='webui')

View File

@ -79,4 +79,4 @@ IPA_DATA_VERSION=20100614120000
# # # #
######################################################## ########################################################
IPA_API_VERSION_MAJOR=2 IPA_API_VERSION_MAJOR=2
IPA_API_VERSION_MINOR=20 IPA_API_VERSION_MINOR=21

View File

@ -126,6 +126,7 @@ from ipalib.aci import ACI
from ipalib.dn import DN from ipalib.dn import DN
from ipalib import output from ipalib import output
from ipalib import _, ngettext from ipalib import _, ngettext
from ipalib.plugins.baseldap import gen_pkey_only_option
if api.env.in_server and api.env.context in ['lite', 'server']: if api.env.in_server and api.env.context in ['lite', 'server']:
from ldap import explode_dn from ldap import explode_dn
from ipapython.ipa_log_manager import * from ipapython.ipa_log_manager import *
@ -297,7 +298,7 @@ def _make_aci(ldap, current, aciname, kw):
return a return a
def _aci_to_kw(ldap, a, test=False): def _aci_to_kw(ldap, a, test=False, pkey_only=False):
"""Convert an ACI into its equivalent keywords. """Convert an ACI into its equivalent keywords.
This is used for the modify operation so we can merge the This is used for the modify operation so we can merge the
@ -306,6 +307,8 @@ def _aci_to_kw(ldap, a, test=False):
""" """
kw = {} kw = {}
kw['aciprefix'], kw['aciname'] = _parse_aci_name(a.name) kw['aciprefix'], kw['aciname'] = _parse_aci_name(a.name)
if pkey_only:
return kw
kw['permissions'] = tuple(a.permissions) kw['permissions'] = tuple(a.permissions)
if 'targetattr' in a.target: if 'targetattr' in a.target:
kw['attrs'] = list(a.target['targetattr']['expression']) kw['attrs'] = list(a.target['targetattr']['expression'])
@ -682,7 +685,8 @@ class aci_find(crud.Search):
NO_CLI = True NO_CLI = True
msg_summary = ngettext('%(count)d ACI matched', '%(count)d ACIs matched', 0) msg_summary = ngettext('%(count)d ACI matched', '%(count)d ACIs matched', 0)
takes_options = (_prefix_option.clone_rename("aciprefix?", required=False),) takes_options = (_prefix_option.clone_rename("aciprefix?", required=False),
gen_pkey_only_option("name"),)
def execute(self, term, **kw): def execute(self, term, **kw):
ldap = self.api.Backend.ldap2 ldap = self.api.Backend.ldap2
@ -837,7 +841,8 @@ class aci_find(crud.Search):
if kw.get('raw', False): if kw.get('raw', False):
aci = dict(aci=unicode(result)) aci = dict(aci=unicode(result))
else: else:
aci = _aci_to_kw(ldap, result) aci = _aci_to_kw(ldap, result,
pkey_only=kw.get('pkey_only', False))
acis.append(aci) acis.append(aci)
return dict( return dict(

View File

@ -1552,6 +1552,12 @@ class LDAPRemoveMember(LDAPModMember):
return return
def gen_pkey_only_option(cli_name):
return Flag('pkey_only?',
label=_('Primary key only'),
doc=_('Results should contain primary key attribute only ("%s")') \
% to_cli(cli_name),)
class LDAPSearch(BaseLDAPCommand, crud.Search): class LDAPSearch(BaseLDAPCommand, crud.Search):
""" """
Retrieve all LDAP entries matching the given criteria. Retrieve all LDAP entries matching the given criteria.
@ -1594,11 +1600,7 @@ class LDAPSearch(BaseLDAPCommand, crud.Search):
yield option yield option
if self.obj.primary_key and \ if self.obj.primary_key and \
'no_output' not in self.obj.primary_key.flags: 'no_output' not in self.obj.primary_key.flags:
yield Flag('pkey_only?', yield gen_pkey_only_option(self.obj.primary_key.cli_name)
label=_('Primary key only'),
doc=_('Results should contain primary key attribute only ("%s")') \
% to_cli(self.obj.primary_key.cli_name),
)
for attr in self.member_attributes: for attr in self.member_attributes:
for ldap_obj_name in self.obj.attribute_members[attr]: for ldap_obj_name in self.obj.attribute_members[attr]:
ldap_obj = self.api.Object[ldap_obj_name] ldap_obj = self.api.Object[ldap_obj_name]

View File

@ -1,5 +1,6 @@
# Authors: # Authors:
# Rob Crittenden <rcritten@redhat.com> # Rob Crittenden <rcritten@redhat.com>
# Martin Kosek <mkosek@redhat.com>
# #
# Copyright (C) 2010 Red Hat # Copyright (C) 2010 Red Hat
# see file 'COPYING' for use and warranty information # see file 'COPYING' for use and warranty information
@ -24,6 +25,7 @@ from ipalib.request import context
from ipalib import api, crud, errors from ipalib import api, crud, errors
from ipalib import output from ipalib import output
from ipalib import Object, Command from ipalib import Object, Command
from ipalib.plugins.baseldap import gen_pkey_only_option
__doc__ = _(""" __doc__ = _("""
Group to Group Delegation Group to Group Delegation
@ -53,45 +55,6 @@ EXAMPLES:
ACI_PREFIX=u"delegation" ACI_PREFIX=u"delegation"
def convert_delegation(ldap, aci):
"""
memberOf is in filter but we want to pull out the group for easier
displaying.
"""
filter = aci['memberof']
st = filter.find('memberOf=')
if st == -1:
raise errors.NotFound(reason=_('Delegation \'%(permission)s\' not found') % dict(permission=aci['aciname']))
en = filter.find(')', st)
membergroup = filter[st+9:en]
try:
(dn, entry_attrs) = ldap.get_entry(membergroup, ['cn'])
except Exception, e:
# Uh oh, the group we're granting access to has an error
msg = _('Error retrieving member group %(group)s: %(error)s') % (membergroup, str(e))
raise errors.NonFatalError(reason=msg)
aci['memberof'] = entry_attrs['cn'][0]
del aci['aciprefix'] # do not include prefix in result
return aci
def is_delegation(ldap, aciname):
"""
Determine if the ACI is a Delegation ACI and raise an exception if it
isn't.
Return the result if it is a delegation ACI, adding a new attribute
membergroup.
"""
result = api.Command['aci_show'](aciname, aciprefix=ACI_PREFIX)['result']
if 'memberof' in result:
result = convert_delegation(ldap, result)
else:
raise errors.NotFound(reason=_('Delegation \'%(permission)s\' not found') % dict(permission=aciname))
return result
class delegation(Object): class delegation(Object):
""" """
Delegation object. Delegation object.
@ -163,8 +126,12 @@ class delegation_add(crud.Create):
kw['permissions'] = (u'write',) kw['permissions'] = (u'write',)
kw['aciprefix'] = ACI_PREFIX kw['aciprefix'] = ACI_PREFIX
result = api.Command['aci_add'](aciname, **kw)['result'] result = api.Command['aci_add'](aciname, **kw)['result']
if 'memberof' in result:
result = convert_delegation(ldap, result) # do not include prefix in result
try:
del result['aciprefix']
except KeyError:
pass
return dict( return dict(
result=result, result=result,
@ -181,8 +148,6 @@ class delegation_del(crud.Delete):
msg_summary = _('Deleted delegation "%(value)s"') msg_summary = _('Deleted delegation "%(value)s"')
def execute(self, aciname, **kw): def execute(self, aciname, **kw):
ldap = self.api.Backend.ldap2
is_delegation(ldap, aciname)
kw['aciprefix'] = ACI_PREFIX kw['aciprefix'] = ACI_PREFIX
result = api.Command['aci_del'](aciname, **kw) result = api.Command['aci_del'](aciname, **kw)
return dict( return dict(
@ -199,12 +164,15 @@ class delegation_mod(crud.Update):
msg_summary = _('Modified delegation "%(value)s"') msg_summary = _('Modified delegation "%(value)s"')
def execute(self, aciname, **kw): def execute(self, aciname, **kw):
ldap = self.api.Backend.ldap2
is_delegation(ldap, aciname)
kw['aciprefix'] = ACI_PREFIX kw['aciprefix'] = ACI_PREFIX
result = api.Command['aci_mod'](aciname, **kw)['result'] result = api.Command['aci_mod'](aciname, **kw)['result']
if 'memberof' in result:
result = convert_delegation(ldap, result) # do not include prefix in result
try:
del result['aciprefix']
except KeyError:
pass
return dict( return dict(
result=result, result=result,
value=aciname, value=aciname,
@ -220,17 +188,18 @@ class delegation_find(crud.Search):
'%(count)d delegation matched', '%(count)d delegations matched', 0 '%(count)d delegation matched', '%(count)d delegations matched', 0
) )
takes_options = (gen_pkey_only_option("name"),)
def execute(self, term, **kw): def execute(self, term, **kw):
ldap = self.api.Backend.ldap2 ldap = self.api.Backend.ldap2
kw['aciprefix'] = ACI_PREFIX kw['aciprefix'] = ACI_PREFIX
acis = api.Command['aci_find'](term, **kw)['result'] results = api.Command['aci_find'](term, **kw)['result']
results = []
for aci in acis: for aci in results:
# do not include prefix in result
try: try:
if 'memberof' in aci: del aci['aciprefix']
aci = convert_delegation(ldap, aci) except KeyError:
results.append(aci)
except errors.NotFound:
pass pass
return dict( return dict(
@ -252,8 +221,12 @@ class delegation_show(crud.Retrieve):
) )
def execute(self, aciname, **kw): def execute(self, aciname, **kw):
ldap = self.api.Backend.ldap2 result = api.Command['aci_show'](aciname, aciprefix=ACI_PREFIX)['result']
result = is_delegation(ldap, aciname) # do not include prefix in result
try:
del result['aciprefix']
except KeyError:
pass
return dict( return dict(
result=result, result=result,
value=aciname, value=aciname,

View File

@ -24,6 +24,7 @@ from ipalib.request import context
from ipalib import api, crud, errors from ipalib import api, crud, errors
from ipalib import output from ipalib import output
from ipalib import Object, Command from ipalib import Object, Command
from ipalib.plugins.baseldap import gen_pkey_only_option
__doc__ = _(""" __doc__ = _("""
Self-service Permissions Self-service Permissions
@ -182,6 +183,8 @@ class selfservice_find(crud.Search):
'%(count)d selfservice matched', '%(count)d selfservices matched', 0 '%(count)d selfservice matched', '%(count)d selfservices matched', 0
) )
takes_options = (gen_pkey_only_option("name"),)
def execute(self, term, **kw): def execute(self, term, **kw):
kw['selfaci'] = True kw['selfaci'] = True
kw['aciprefix'] = ACI_PREFIX kw['aciprefix'] = ACI_PREFIX

View File

@ -146,6 +146,22 @@ class test_delegation(Declarative):
), ),
dict(
desc='Search for %r with --pkey-only' % delegation1,
command=('delegation_find', [delegation1], {'pkey_only' : True}),
expected=dict(
count=1,
truncated=False,
summary=u'1 delegation matched',
result=[
{
'aciname': delegation1,
},
],
),
),
dict( dict(
desc='Update %r' % delegation1, desc='Update %r' % delegation1,
command=( command=(

View File

@ -268,6 +268,27 @@ class test_permission(Declarative):
), ),
dict(
desc='Search for %r with --pkey-only' % permission1,
command=('permission_find', [permission1], {'pkey_only' : True}),
expected=dict(
count=2,
truncated=False,
summary=u'2 permissions matched',
result=[
{
'dn': lambda x: DN(x) == permission1_dn,
'cn': [permission1],
},
{
'dn': lambda x: DN(x) == permission2_dn,
'cn': [permission2],
},
],
),
),
dict( dict(
desc='Search for %r' % privilege1, desc='Search for %r' % privilege1,
command=('privilege_find', [privilege1], {}), command=('privilege_find', [privilege1], {}),

View File

@ -137,6 +137,21 @@ class test_selfservice(Declarative):
), ),
), ),
dict(
desc='Search for %r with --pkey-only' % selfservice1,
command=('selfservice_find', [selfservice1], {'pkey_only' : True}),
expected=dict(
count=1,
truncated=False,
summary=u'1 selfservice matched',
result=[
{
'aciname': selfservice1,
},
],
),
),
dict( dict(
desc='Update %r' % selfservice1, desc='Update %r' % selfservice1,