diff options
-rw-r--r-- | ipalib/plugins/aci.py | 37 | ||||
-rw-r--r-- | ipalib/plugins/permission.py | 3 | ||||
-rw-r--r-- | ipalib/plugins/selfservice.py | 192 | ||||
-rw-r--r-- | tests/test_xmlrpc/test_selfservice_plugin.py | 183 |
4 files changed, 400 insertions, 15 deletions
diff --git a/ipalib/plugins/aci.py b/ipalib/plugins/aci.py index 3636dddca..d5f7d996f 100644 --- a/ipalib/plugins/aci.py +++ b/ipalib/plugins/aci.py @@ -656,21 +656,30 @@ class aci_find(crud.Search): # acis = list(results) for a in acis: - if 'target' in a.target: - target = a.target['target']['expression'] - else: - results.remove(a) - continue - found = False - for k in _type_map.keys(): - if _type_map[k] == target and 'type' in kw and kw['type'] == k: - found = True - break; - if not found: - try: + if 'type' in kw: + if 'target' in a.target: + target = a.target['target']['expression'] + else: results.remove(a) - except ValueError: - pass + continue + found = False + for k in _type_map.keys(): + if _type_map[k] == target and kw['type'] == k: + found = True + break; + if not found: + try: + results.remove(a) + except ValueError: + pass + + if 'selfaci' in kw and kw['selfaci'] == True: + for a in acis: + if a.bindrule['expression'] != u'ldap:///self': + try: + results.remove(a) + except ValueError: + pass # TODO: searching by: filter, subtree diff --git a/ipalib/plugins/permission.py b/ipalib/plugins/permission.py index c2264aaf3..4ad53c749 100644 --- a/ipalib/plugins/permission.py +++ b/ipalib/plugins/permission.py @@ -310,7 +310,8 @@ class permission_find(LDAPSearch): found = False if 'permission' in aci: for entry in entries: - if aci['permission'] == entry['cn']: + (dn, attrs) = entry + if aci['permission'] == attrs['cn']: found = True break if not found in aci: diff --git a/ipalib/plugins/selfservice.py b/ipalib/plugins/selfservice.py new file mode 100644 index 000000000..6d34715ad --- /dev/null +++ b/ipalib/plugins/selfservice.py @@ -0,0 +1,192 @@ +# Authors: +# Rob Crittenden <rcritten@redhat.com> +# +# Copyright (C) 2010 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 only +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +""" +Self-Service Permissions + +A permission enables fine-grained delegation of permissions. Access Control +Rules, or instructions (ACIs), grant permission to permissions to perform +given tasks such as adding a user, modifying a group, etc. + +A Self-Service permission defines what an object can change in its own entry. + + +EXAMPLES: + + Add a self-service rule to allow users to manage their address: + ipa selfservice-add --permissions=write --attrs=street,postalCode,l,c,st "User's manage their own address" + + When managing the list of attributes you need to include all attributes + in the list, including existing ones. Add telephoneNumber to the list: + ipa selfservice-mod --attrs=street,postalCode,l,c,st,telephoneNumber "User's manage their own address" + + Display our updated rule: + ipa selfservice-show "User's manage their own address" + + Delete a rule: + ipa selfservice-del "User's manage their own address" +""" + +import copy +from ipalib import api, _, ngettext +from ipalib import Flag, Str, List +from ipalib.request import context +from ipalib import api, crud, errors +from ipalib import output +from ipalib import Object, Command + +def is_selfservice(aciname): + """ + Determine if the ACI is a Self-Service ACI and raise an exception if it + isn't. + + Return the result if it is a self-service ACI. + """ + result = api.Command['aci_show'](aciname)['result'] + if 'selfaci' not in result or result['selfaci'] == False: + raise errors.NotFound(reason=_('Self-service permission \'%(permission)s\' not found') % dict(permission=aciname)) + return result + +class selfservice(Object): + """ + Selfservice object. + """ + + label = _('Permissions') + + takes_params = ( + Str('aciname', + cli_name='name', + label=_('Self-Service name'), + doc=_('Self-Service name'), + primary_key=True, + ), + List('permissions?', + cli_name='permissions', + label=_('Permissions'), + doc=_('Comma-separated list of permissions to grant ' \ + '(read, write). Default is write.'), + ), + List('attrs', + cli_name='attrs', + label=_('Attributes'), + doc=_('Comma-separated list of attributes'), + ), + ) + +api.register(selfservice) + + +class selfservice_add(crud.Create): + """ + Add a new selfservice permission. + """ + + msg_summary = _('Added selfservice "%(value)s"') + + def execute(self, aciname, **kw): + if not 'permissions' in kw: + kw['permissions'] = (u'write',) + kw['selfaci'] = True + result = api.Command['aci_add'](aciname, **kw)['result'] + + return dict( + result=result, + value=aciname, + ) + +api.register(selfservice_add) + + +class selfservice_del(crud.Delete): + """ + Delete a selfservice. + """ + + has_output = output.standard_delete + msg_summary = _('Deleted selfservice "%(value)s"') + + def execute(self, aciname, **kw): + is_selfservice(aciname) + result = api.Command['aci_del'](aciname, **kw) + return dict( + result=True, + value=aciname, + ) + +api.register(selfservice_del) + + +class selfservice_mod(crud.Update): + """ + Modify a selfservice. + """ + + msg_summary = _('Modified selfservice "%(value)s"') + + def execute(self, aciname, **kw): + is_selfservice(aciname) + result = api.Command['aci_mod'](aciname, **kw)['result'] + return dict( + result=result, + value=aciname, + ) + +api.register(selfservice_mod) + + +class selfservice_find(crud.Search): + """ + Search for selfservices. + """ + + msg_summary = ngettext( + '%(count)d selfservice matched', '%(count)d selfservices matched' + ) + + def execute(self, term, **kw): + kw['selfaci'] = True + result = api.Command['aci_find'](term, **kw)['result'] + + return dict( + result=result, + count=len(result), + truncated=False, + ) + +api.register(selfservice_find) + + +class selfservice_show(crud.Retrieve): + """ + Display information about a selfservice. + """ + has_output_params = ( + Str('aci', + label=_('ACI'), + ), + ) + + def execute(self, aciname, **kw): + result = is_selfservice(aciname) + return dict( + result=result, + value=aciname, + ) + +api.register(selfservice_show) diff --git a/tests/test_xmlrpc/test_selfservice_plugin.py b/tests/test_xmlrpc/test_selfservice_plugin.py new file mode 100644 index 000000000..897bd0da4 --- /dev/null +++ b/tests/test_xmlrpc/test_selfservice_plugin.py @@ -0,0 +1,183 @@ +# Authors: +# Rob Crittenden <rcritten@redhat.com> +# +# Copyright (C) 2010 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 only +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +""" +Test the `ipalib/plugins/selfservice.py` module. +""" + +from ipalib import api, errors +from tests.test_xmlrpc import objectclasses +from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid + +selfservice1 = u'testself' + +class test_selfservice(Declarative): + + cleanup_commands = [ + ('selfservice_del', [selfservice1], {}), + ] + + tests = [ + + dict( + desc='Try to retrieve non-existent %r' % selfservice1, + command=('selfservice_show', [selfservice1], {}), + expected=errors.NotFound(reason='no such entry'), + ), + + + dict( + desc='Try to update non-existent %r' % selfservice1, + command=('selfservice_mod', [selfservice1], dict(description=u'Foo')), + expected=errors.NotFound(reason='no such entry'), + ), + + + dict( + desc='Try to delete non-existent %r' % selfservice1, + command=('selfservice_del', [selfservice1], {}), + expected=errors.NotFound(reason='no such entry'), + ), + + + dict( + desc='Search for non-existent %r' % selfservice1, + command=('selfservice_find', [selfservice1], {}), + expected=dict( + count=0, + truncated=False, + summary=u'0 selfservices matched', + result=[], + ), + ), + + + dict( + desc='Create %r' % selfservice1, + command=( + 'selfservice_add', [selfservice1], dict( + attrs=u'street,c,l,st,postalCode', + permissions=u'write', + ) + ), + expected=dict( + value=selfservice1, + summary=u'Added selfservice "%s"' % selfservice1, + result=dict( + attrs=[u'street', u'c', u'l', u'st', u'postalCode'], + permissions=[u'write'], + selfaci=True, + aciname=selfservice1, + ), + ), + ), + + + dict( + desc='Try to create duplicate %r' % selfservice1, + command=( + 'selfservice_add', [selfservice1], dict( + attrs=u'street,c,l,st,postalCode', + permissions=u'write', + ), + ), + expected=errors.DuplicateEntry(), + ), + + + dict( + desc='Retrieve %r' % selfservice1, + command=('selfservice_show', [selfservice1], {}), + expected=dict( + value=selfservice1, + summary=None, + result={ + 'attrs': [u'street', u'c', u'l', u'st', u'postalCode'], + 'permissions': [u'write'], + 'selfaci': True, + 'aciname': selfservice1, + }, + ), + ), + + + dict( + desc='Search for %r' % selfservice1, + command=('selfservice_find', [selfservice1], {}), + expected=dict( + count=1, + truncated=False, + summary=u'1 selfservice matched', + result=[ + { + 'attrs': [u'street', u'c', u'l', u'st', u'postalCode'], + 'permissions': [u'write'], + 'selfaci': True, + 'aciname': selfservice1, + }, + ], + ), + ), + + + dict( + desc='Update %r' % selfservice1, + command=( + 'selfservice_mod', [selfservice1], dict(permissions=u'read') + ), + expected=dict( + value=selfservice1, + summary=u'Modified selfservice "%s"' % selfservice1, + result=dict( + attrs=[u'street', u'c', u'l', u'st', u'postalCode'], + permissions=[u'read'], + selfaci=True, + aciname=selfservice1, + ), + ), + ), + + + dict( + desc='Retrieve %r to verify update' % selfservice1, + command=('selfservice_show', [selfservice1], {}), + expected=dict( + value=selfservice1, + summary=None, + result={ + 'attrs': [u'street', u'c', u'l', u'st', u'postalCode'], + 'permissions': [u'read'], + 'selfaci': True, + 'aciname': selfservice1, + }, + ), + ), + + + dict( + desc='Delete %r' % selfservice1, + command=('selfservice_del', [selfservice1], {}), + expected=dict( + result=True, + value=selfservice1, + summary=u'Deleted selfservice "%s"' % selfservice1, + ) + ), + + ] |