Projet

Général

Profil

0004-manager-use-new-manage_members-permission-20513.patch

Valentin Deniaud, 20 avril 2020 17:33

Télécharger (11,9 ko)

Voir les différences:

Subject: [PATCH 4/4] manager: use new manage_members permission (#20513)

 src/authentic2/manager/role_views.py          |  8 +-
 .../authentic2/manager/role_members.html      |  6 +-
 .../manager/role_members_table.html           |  2 +-
 src/authentic2/manager/user_views.py          |  4 +-
 src/authentic2/manager/views.py               | 13 ++-
 tests/test_manager.py                         | 84 ++++++++++++++++++-
 6 files changed, 98 insertions(+), 19 deletions(-)
src/authentic2/manager/role_views.py
155 155
    def form_valid(self, form):
156 156
        user = form.cleaned_data['user']
157 157
        action = form.cleaned_data['action']
158
        if self.can_change:
158
        if self.can_manage_members:
159 159
            if action == 'add':
160 160
                if self.object.members.filter(pk=user.pk).exists():
161 161
                    messages.warning(self.request, _('User already in this role.'))
......
277 277
    form_class = forms.RolesForm
278 278
    success_url = '..'
279 279
    template_name = 'authentic2/manager/form.html'
280
    permissions = ['a2_rbac.change_role']
280
    permissions = ['a2_rbac.manage_members_role']
281 281

  
282 282
    def dispatch(self, request, *args, **kwargs):
283 283
        self.object = self.get_object()
......
325 325
    model = get_role_model()
326 326
    success_url = '../..'
327 327
    template_name = 'authentic2/manager/role_remove_child.html'
328
    permissions = ['a2_rbac.change_role']
328
    permissions = ['a2_rbac.manage_members_role']
329 329

  
330 330
    def dispatch(self, request, *args, **kwargs):
331 331
        self.object = self.get_object()
......
366 366
        return ctx
367 367

  
368 368
    def post(self, request, *args, **kwargs):
369
        if not self.request.user.has_perm('a2_rbac.change_role', self.parent):
369
        if not self.request.user.has_perm('a2_rbac.manage_members_role', self.parent):
370 370
            raise PermissionDenied
371 371
        self.object.remove_parent(self.parent)
372 372
        hooks.call_hooks('event', name='manager-remove-child-role', user=self.request.user,
src/authentic2/manager/templates/authentic2/manager/role_members.html
52 52

  
53 53
 {% include "authentic2/manager/export_include.html" with export_view_name="a2-manager-role-members-export" %}
54 54

  
55
 {% if view.can_change %}
56
   <form method="post" class="manager-m2m-add-form">
55
 {% if view.can_manage_members %}
56
   <form method="post" class="manager-m2m-add-form" id="add-user">
57 57
           {% csrf_token %}
58 58
           {{ form }}
59 59
           <button>{% trans "Add" %}</button>
......
103 103
       <a title="{% trans "Indirect child role" %}" class="disabled role-remove icon-minus-sign"></a>
104 104
     {% endif %}
105 105
   {% endfor %}
106
  {% if view.can_change %}
106
  {% if view.can_manage_members %}
107 107
    <a rel="popup" href="{% url "a2-manager-role-add-child" pk=object.pk %}" class="role-add icon-add-sign"></a>
108 108
  {% else %}
109 109
    <a title="{% trans "Permission denied" %}" class="disabled role-add icon-add-sign"></a>
src/authentic2/manager/templates/authentic2/manager/role_members_table.html
7 7
    <th></th>
8 8
  {% endblock %}
9 9
  {% block table.tbody.last.column %}
10
  <td>{% if table.context.view.can_change and row.record.direct %}<a class="icon-remove-sign js-remove-object" data-confirm="{% blocktrans with username=row.record.get_full_name role=table.context.object %}Do you really want to remove user &quot;{{ username }}&quot; from role &quot;{{ role }}&quot;&nbsp;?{% endblocktrans %}" href="#" data-pk-arg="user"></a>{% endif %}</td>
10
  <td>{% if table.context.view.can_manage_members and row.record.direct %}<a class="icon-remove-sign js-remove-object" data-confirm="{% blocktrans with username=row.record.get_full_name role=table.context.object %}Do you really want to remove user &quot;{{ username }}&quot; from role &quot;{{ role }}&quot;&nbsp;?{% endblocktrans %}" href="#" data-pk-arg="user"></a>{% endif %}</td>
11 11
  {% endblock %}
12 12
{% endif %}
src/authentic2/manager/user_views.py
554 554
            qs = qs.prefetch_related(models.Prefetch(
555 555
                'members', queryset=User.objects.filter(pk=self.object.pk),
556 556
                to_attr='member'))
557
            qs2 = self.request.user.filter_by_perm('a2_rbac.change_role', qs)
557
            qs2 = self.request.user.filter_by_perm('a2_rbac.manage_members_role', qs)
558 558
            managable_ids = map(str, qs2.values_list('pk', flat=True))
559 559
            qs = qs.extra(select={'has_perm': 'a2_rbac_role.id in (%s)' % ', '.join(managable_ids)})
560 560
            qs = qs.exclude(slug__startswith='_a2-managers-of-role')
......
579 579
        user = self.object
580 580
        role = form.cleaned_data['role']
581 581
        action = form.cleaned_data['action']
582
        if self.request.user.has_perm('a2_rbac.change_role', role):
582
        if self.request.user.has_perm('a2_rbac.manage_members_role', role):
583 583
            if action == 'add':
584 584
                if user.roles.filter(pk=role.pk):
585 585
                    messages.warning(
src/authentic2/manager/views.py
115 115
                         or (hasattr(self, 'slug_url_kwarg')
116 116
                             and self.slug_url_kwarg in self.kwargs)):
117 117
                self.object = self.get_object()
118
                view_perm = '%s.view_%s' % (app_label, model_name)
119
                change_perm = '%s.change_%s' % (app_label, model_name)
120
                delete_perm = '%s.delete_%s' % (app_label, model_name)
121
                self.can_view = request.user.has_perm(view_perm, self.object)
122
                self.can_change = request.user.has_perm(change_perm,
123
                                                        self.object)
124
                self.can_delete = request.user.has_perm(delete_perm,
125
                                                        self.object)
118
                permissions = ('view', 'change', 'delete', 'manage_members')
119
                for permission in permissions:
120
                    perm = '%s.%s_%s' % (app_label, permission, model_name)
121
                    setattr(self, 'can_' + permission,
122
                            request.user.has_perm(perm, self.object))
126 123
                if self.permissions \
127 124
                        and not request.user.has_perms(
128 125
                            self.permissions, self.object):
tests/test_manager.py
26 26
from authentic2.a2_rbac.utils import get_default_ou
27 27
from authentic2.validators import EmailValidator
28 28

  
29
from django_rbac.utils import get_ou_model, get_role_model
29
from django_rbac.utils import (get_ou_model, get_role_model,
30
                               get_permission_model, get_operation)
31
from django_rbac.models import VIEW_OP
30 32
from django.contrib.auth import get_user_model
33
from django.contrib.contenttypes.models import ContentType
31 34
from django.utils.encoding import force_bytes
32 35
from django.utils.six.moves.urllib.parse import urlparse
33 36
from utils import login, get_link_from_mail
......
935 938
    resp = app.get('/manage/roles/add/', xhr=True, status=200)
936 939
    assert resp.content_type == 'application/json'
937 940
    assert resp.json['content']
941

  
942

  
943
def test_manager_role_admin_permissions(app, simple_user, admin, simple_role):
944
    admin_role = simple_role.get_admin_role()
945
    simple_user.roles.add(admin_role)
946
    login(app, simple_user, '/manage/')
947

  
948
    # user can view users
949
    response = app.get('/manage/users/')
950
    q = response.pyquery.remove_namespaces()
951
    assert len(q('table tbody tr')) == 2
952
    assert set([e.text for e in q('table tbody td.username')]) == {'admin', 'user'}
953

  
954
    # user can view administered roles
955
    response = app.get('/manage/roles/')
956
    q = response.pyquery.remove_namespaces()
957
    assert len(q('table tbody tr')) == 1
958
    assert q('table tbody td.name').text() == 'simple role'
959

  
960
    # user can add members
961
    response = app.get('/manage/roles/%s/' % simple_role.pk)
962
    form = response.forms['add-user']
963
    form['user'].force_value(admin.pk)
964
    response = form.submit().follow()
965
    assert simple_role in admin.roles.all()
966

  
967
    # user can delete members
968
    q = response.pyquery.remove_namespaces()
969
    assert q('table tbody tr td .icon-remove-sign')
970
    token = str(response.context['csrf_token'])
971
    params = {'action': 'remove', 'user': admin.pk, 'csrfmiddlewaretoken': token}
972
    app.post('/manage/roles/%s/' % simple_role.pk, params=params)
973
    assert simple_role not in admin.roles.all()
974

  
975
    # user can act on role inheritance
976
    role = Role.objects.create(name='test_role')
977
    view_role_perm = get_permission_model().objects.create(
978
        operation=get_operation(VIEW_OP), ou=role.ou,
979
        target_ct=ContentType.objects.get_for_model(Role),
980
        target_id=role.pk)
981
    simple_role.permissions.add(view_role_perm)
982
    simple_user.roles.add(simple_role)
983
    admin.roles.add(role)
984
    response = app.get('/manage/roles/%s/add-child/' % simple_role.pk)
985
    form = response.form
986
    form['roles'].force_value(role.pk)
987
    form.submit().follow()
988
    assert role in simple_role.children()
989

  
990
    url = '/manage/roles/%s/remove-child/%s/' % (simple_role.pk, role.pk)
991
    token = str(response.context['csrf_token'])
992
    app.post(url, params={'csrfmiddlewaretoken': token})
993
    assert not role in simple_role.children()
994

  
995
    response = app.get('/manage/roles/%s/add-parent/' % role.pk)
996
    form = response.form
997
    form['roles'].force_value(simple_role.pk)
998
    form.submit().follow()
999
    assert simple_role in role.parents()
1000

  
1001
    url = '/manage/roles/%s/remove-parent/%s/' % (role.pk, simple_role.pk)
1002
    token = str(response.context['csrf_token'])
1003
    app.post(url, params={'csrfmiddlewaretoken': token})
1004
    assert not simple_role in role.parents()
1005

  
1006
    # user roles view works
1007
    response = app.get('/manage/users/%s/roles/' % admin.pk)
1008
    q = response.pyquery.remove_namespaces()
1009
    assert len(q('table tbody tr')) == 1
1010
    assert q('table tbody td.name').text() == 'simple role'
1011

  
1012
    token = str(response.context['csrf_token'])
1013
    params = {'action': 'add', 'role': simple_role.pk, 'csrfmiddlewaretoken': token}
1014
    response = app.post('/manage/users/%s/roles/' % admin.pk, params=params)
1015
    assert simple_role in admin.roles.all()
1016

  
1017
    app.get('/manage/roles/add/', status=403)
1018
    app.get('/manage/roles/%s/edit/' % simple_role.pk, status=403)
1019
    app.get('/manage/roles/%s/delete/' % simple_role.pk, status=403)
938
-