Projet

Général

Profil

0002-manager-use-new-select2-widget-to-manage-role-s-admi.patch

Benjamin Dauvergne, 27 janvier 2022 23:26

Télécharger (26,8 ko)

Voir les différences:

Subject: [PATCH 2/2] manager: use new select2 widget to manage role's
 administrators (#61196)

Also remove now unused RolesForm, UsersForm, roles' administrators views,
and ChooseManageableMemberRolesWidget
 src/authentic2/manager/forms.py               |  22 +-
 src/authentic2/manager/role_views.py          | 264 +++++++-----------
 .../static/authentic2/manager/js/manager.js   |   6 +-
 .../authentic2/manager/role_members.html      |  58 ++--
 src/authentic2/manager/urls.py                |  20 --
 src/authentic2/manager/widgets.py             |  14 -
 tests/test_manager.py                         |  33 +--
 tests/test_role_manager.py                    |  14 +-
 8 files changed, 160 insertions(+), 271 deletions(-)
src/authentic2/manager/forms.py
115 115
    action = forms.CharField(initial='add', widget=forms.HiddenInput)
116 116

  
117 117

  
118
class UsersForm(LimitQuerysetFormMixin, CssClass, forms.Form):
119

  
120
    users = fields.ChooseUsersField(label=_('Add some users'))
121

  
122

  
123
class RolesForm(LimitQuerysetFormMixin, CssClass, forms.Form):
124
    roles = fields.ChooseRolesField(label=_('Add some roles'))
125

  
126

  
127 118
class RoleParentForm(LimitQuerysetFormMixin, CssClass, forms.Form):
128 119
    role = fields.ChooseManageableMemberRoleField(label=_('Add some roles'))
129 120
    action = forms.CharField(initial='add', widget=forms.HiddenInput)
......
861 852
    )
862 853

  
863 854

  
864
class ChooseUserOrRoleForm(FormWithRequest, forms.Form):
855
class RoleAdminForm(FormWithRequest, forms.Form):
856
    TARGETS = [
857
        ('members', 'members'),
858
        ('admin', 'admin'),
859
    ]
860
    ACTIONS = [
861
        ('add', 'add'),
862
        ('remove', 'remove'),
863
    ]
865 864
    user_or_roles = UserOrRoleField(label=_('Add to role'))
866
    action = forms.CharField(initial='add', widget=forms.HiddenInput)
865
    target = forms.ChoiceField(choices=TARGETS, initial='members', widget=forms.HiddenInput)
866
    action = forms.ChoiceField(choices=ACTIONS, initial='add', widget=forms.HiddenInput)
867 867

  
868 868
    def __init__(self, *args, **kwargs):
869 869
        self.role = kwargs.pop('role', None)
src/authentic2/manager/role_views.py
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17 17
import json
18
import operator
18 19
from functools import reduce
19 20

  
20 21
from django.contrib import messages
......
32 33
from django.utils.functional import cached_property
33 34
from django.utils.translation import ugettext_lazy as _
34 35
from django.views.generic import DetailView, FormView, TemplateView
35
from django.views.generic.detail import SingleObjectMixin
36 36

  
37 37
from authentic2 import data_transfer, hooks
38 38
from authentic2.a2_rbac.models import OrganizationalUnit, Permission, Role, RoleParenting
39 39
from authentic2.a2_rbac.utils import get_default_ou
40 40
from authentic2.apps.journal.views import JournalViewWithContext
41 41
from authentic2.forms.profile import modelform_factory
42
from authentic2.utils.misc import redirect
43 42

  
44 43
from . import forms, resources, tables, views
45 44
from .journal_views import BaseJournalView
......
174 173

  
175 174
class RoleMembersView(views.HideOUColumnMixin, RoleViewMixin, views.BaseSubTableView):
176 175
    template_name = 'authentic2/manager/role_members.html'
177
    form_class = forms.ChooseUserOrRoleForm
176
    form_class = forms.RoleAdminForm
178 177
    success_url = '.'
179 178
    search_form_class = forms.RoleMembersSearchForm
180 179
    permissions = ['a2_rbac.view_role']
......
221 220

  
222 221
    def form_valid(self, form):
223 222
        action = form.cleaned_data['action']
224
        if not self.can_manage_members:
223
        target = form.cleaned_data['target']
224
        if target == 'members' and not self.can_manage_members:
225 225
            messages.warning(self.request, _('You are not authorized'))
226
        if action == 'add':
227
            user_action = self.add_user
228
            role_action = self.add_role
229
        elif action == 'remove':
230
            user_action = self.remove_user
231
            role_action = self.remove_role
226
            return super().form_valid(form)
227
        if target == 'admin' and not self.can_change:
228
            messages.warning(self.request, _('You are not authorized'))
229
            return super().form_valid(form)
230
        user_action = getattr(self, '%s_%s_user' % (action, target))
231
        role_action = getattr(self, '%s_%s_role' % (action, target))
232 232
        for user in form.cleaned_data.get('users', []):
233 233
            user_action(user)
234 234
        for role in form.cleaned_data.get('roles', []):
235 235
            role_action(role)
236 236
        return super().form_valid(form)
237 237

  
238
    def add_user(self, user):
238
    def add_members_user(self, user):
239 239
        if self.object.members.filter(pk=user.pk).exists():
240 240
            messages.warning(self.request, _('User already in this role.'))
241 241
        else:
......
245 245
            )
246 246
            self.request.journal.record('manager.role.membership.grant', role=self.object, member=user)
247 247

  
248
    def remove_user(self, user):
248
    def remove_members_user(self, user):
249 249
        if not self.object.members.filter(pk=user.pk).exists():
250 250
            messages.warning(self.request, _('User was not in this role.'))
251 251
        else:
......
259 259
            )
260 260
            self.request.journal.record('manager.role.membership.removal', role=self.object, member=user)
261 261

  
262
    def add_role(self, role):
262
    def add_members_role(self, role):
263 263
        self.object.add_child(role)
264 264
        hooks.call_hooks(
265 265
            'event', name='manager-add-child-role', user=self.request.user, parent=self.object, child=role
266 266
        )
267 267
        self.request.journal.record('manager.role.inheritance.addition', parent=self.object, child=role)
268 268

  
269
    def remove_role(self, role):
269
    def remove_members_role(self, role):
270 270
        self.object.remove_child(role)
271 271
        hooks.call_hooks(
272 272
            'event', name='manager-remove-child-role', user=self.request.user, parent=self.object, child=role
273 273
        )
274 274
        self.request.journal.record('manager.role.inheritance.removal', parent=self.object, child=role)
275 275

  
276
    def add_admin_user(self, user):
277
        admin_role = self.object.get_admin_role()
278
        if admin_role.members.filter(id=user.id).exists():
279
            return
280
        admin_role.members.add(user)
281
        hooks.call_hooks(
282
            'event',
283
            name='manager-add-admin-role-user',
284
            user=self.request.user,
285
            role=self.object,
286
            admin=user,
287
        )
288
        self.request.journal.record(
289
            'manager.role.administrator.user.addition', role=self.object, admin_user=user
290
        )
291

  
292
    def remove_admin_user(self, user):
293
        admin_role = self.object.get_admin_role()
294
        if not admin_role.members.filter(id=user.id).exists():
295
            return
296
        admin_role.members.remove(user)
297
        hooks.call_hooks(
298
            'event',
299
            name='remove-remove-admin-role-user',
300
            user=self.request.user,
301
            role=self.object,
302
            admin=user,
303
        )
304
        self.request.journal.record(
305
            'manager.role.administrator.user.removal', role=self.object, admin_user=user
306
        )
307

  
308
    def add_admin_role(self, role):
309
        admin_role = self.object.get_admin_role()
310
        if admin_role.child_relation.filter(child=role).exists():
311
            return
312
        admin_role.add_child(role)
313
        hooks.call_hooks(
314
            'event',
315
            name='manager-add-admin-role',
316
            user=self.request.user,
317
            role=self.object,
318
            admin_role=role,
319
        )
320
        self.request.journal.record(
321
            'manager.role.administrator.role.addition', role=self.object, admin_role=role
322
        )
323

  
324
    def remove_admin_role(self, role):
325
        admin_role = self.object.get_admin_role()
326
        if not admin_role.child_relation.filter(child=role).exists():
327
            return
328
        admin_role.remove_child(role)
329
        hooks.call_hooks(
330
            'event',
331
            name='manager-remove-admin-role',
332
            user=self.request.user,
333
            role=self.object,
334
            admin_role=role,
335
        )
336
        self.request.journal.record(
337
            'manager.role.administrator.role.removal', role=self.object, admin_role=role
338
        )
339

  
276 340
    def get_form_kwargs(self):
277 341
        kwargs = super().get_form_kwargs()
278 342
        kwargs['role'] = self.object
......
296 360
            )[:11]
297 361
        )
298 362
        ctx['has_multiple_ou'] = OrganizationalUnit.objects.count() > 1
299
        ctx['admin_roles'] = views.filter_view(
300
            self.request, self.object.get_admin_role().children(include_self=False, annotate=True)
301
        )
302 363
        ctx['from_ldap'] = self._can_manage_members and not self.can_manage_members
364
        admin_form = self.get_form()
365
        admin_form.fields['target'].initial = 'admin'
366
        ctx['admin_form'] = admin_form
367
        administrators = []
368
        for user in self.object.get_admin_role().all_members():
369
            user.ref = 'user-%s' % user.id
370
            user.type = _('User')
371
            administrators.append(user)
372
        for role in views.filter_view(
373
            self.request, self.object.get_admin_role().children(include_self=False, annotate=True)
374
        ):
375
            role.ref = 'role-%s' % role.id
376
            role.type = _('Role')
377
            administrators.append(role)
378
        ctx['administrators'] = sorted(administrators, key=str)
303 379
        return ctx
304 380

  
305 381
    def is_ou_specified(self):
......
473 549
parents = RoleParentsView.as_view()
474 550

  
475 551

  
476
class RoleAddAdminRoleView(
477
    views.AjaxFormViewMixin,
478
    views.TitleMixin,
479
    views.PermissionMixin,
480
    views.FormNeedsRequest,
481
    SingleObjectMixin,
482
    FormView,
483
):
484
    title = _('Add admin role')
485
    model = Role
486
    form_class = forms.RolesForm
487
    success_url = '..'
488
    template_name = 'authentic2/manager/form.html'
489
    permissions = ['a2_rbac.change_role']
490

  
491
    def dispatch(self, request, *args, **kwargs):
492
        self.object = self.get_object()
493
        return super().dispatch(request, *args, **kwargs)
494

  
495
    def form_valid(self, form):
496
        administered_role = self.get_object()
497
        for role in form.cleaned_data['roles']:
498
            administered_role.get_admin_role().add_child(role)
499
            hooks.call_hooks(
500
                'event',
501
                name='manager-add-admin-role',
502
                user=self.request.user,
503
                role=administered_role,
504
                admin_role=role,
505
            )
506
            self.request.journal.record(
507
                'manager.role.administrator.role.addition', role=administered_role, admin_role=role
508
            )
509
        return super().form_valid(form)
510

  
511

  
512
add_admin_role = RoleAddAdminRoleView.as_view()
513

  
514

  
515
class RoleRemoveAdminRoleView(
516
    views.TitleMixin, views.AjaxFormViewMixin, SingleObjectMixin, views.PermissionMixin, TemplateView
517
):
518
    title = _('Remove admin role')
519
    model = Role
520
    success_url = '../..'
521
    template_name = 'authentic2/manager/role_remove_admin_role.html'
522
    permissions = ['a2_rbac.change_role']
523

  
524
    def dispatch(self, request, *args, **kwargs):
525
        self.object = self.get_object()
526
        self.child = self.get_queryset().get(pk=kwargs['role_pk'])
527
        return super().dispatch(request, *args, **kwargs)
528

  
529
    def get_context_data(self, **kwargs):
530
        ctx = super().get_context_data(**kwargs)
531
        ctx['child'] = self.child
532
        return ctx
533

  
534
    def post(self, request, *args, **kwargs):
535
        self.object.get_admin_role().remove_child(self.child)
536
        hooks.call_hooks(
537
            'event',
538
            name='manager-remove-admin-role',
539
            user=self.request.user,
540
            role=self.object,
541
            admin_role=self.child,
542
        )
543
        self.request.journal.record(
544
            'manager.role.administrator.role.removal', role=self.object, admin_role=self.child
545
        )
546
        return redirect(self.request, self.success_url)
547

  
548

  
549
remove_admin_role = RoleRemoveAdminRoleView.as_view()
550

  
551

  
552
class RoleAddAdminUserView(
553
    views.AjaxFormViewMixin,
554
    views.TitleMixin,
555
    views.PermissionMixin,
556
    views.FormNeedsRequest,
557
    SingleObjectMixin,
558
    FormView,
559
):
560
    title = _('Add admin user')
561
    model = Role
562
    form_class = forms.UsersForm
563
    success_url = '..'
564
    template_name = 'authentic2/manager/form.html'
565
    permissions = ['a2_rbac.change_role']
566

  
567
    def dispatch(self, request, *args, **kwargs):
568
        self.object = self.get_object()
569
        return super().dispatch(request, *args, **kwargs)
570

  
571
    def form_valid(self, form):
572
        administered_role = self.get_object()
573
        for user in form.cleaned_data['users']:
574
            administered_role.get_admin_role().members.add(user)
575
            hooks.call_hooks(
576
                'event',
577
                name='manager-add-admin-role-user',
578
                user=self.request.user,
579
                role=administered_role,
580
                admin=user,
581
            )
582
            self.request.journal.record(
583
                'manager.role.administrator.user.addition', role=administered_role, admin_user=user
584
            )
585
        return super().form_valid(form)
586

  
587

  
588
add_admin_user = RoleAddAdminUserView.as_view()
589

  
590

  
591
class RoleRemoveAdminUserView(
592
    views.TitleMixin, views.AjaxFormViewMixin, SingleObjectMixin, views.PermissionMixin, TemplateView
593
):
594
    title = _('Remove admin user')
595
    model = Role
596
    success_url = '../..'
597
    template_name = 'authentic2/manager/role_remove_admin_user.html'
598
    permissions = ['a2_rbac.change_role']
599

  
600
    def dispatch(self, request, *args, **kwargs):
601
        self.object = self.get_object()
602
        self.user = get_user_model().objects.get(pk=kwargs['user_pk'])
603
        return super().dispatch(request, *args, **kwargs)
604

  
605
    def get_context_data(self, **kwargs):
606
        ctx = super().get_context_data(**kwargs)
607
        ctx['user'] = self.user
608
        return ctx
609

  
610
    def post(self, request, *args, **kwargs):
611
        self.object.get_admin_role().members.remove(self.user)
612
        hooks.call_hooks(
613
            'event',
614
            name='remove-remove-admin-role-user',
615
            user=self.request.user,
616
            role=self.object,
617
            admin=self.user,
618
        )
619
        self.request.journal.record(
620
            'manager.role.administrator.user.removal', role=self.object, admin_user=self.user
621
        )
622
        return redirect(self.request, self.success_url)
623

  
624

  
625
remove_admin_user = RoleRemoveAdminUserView.as_view()
626

  
627

  
628 552
class RolesImportView(
629 553
    views.PermissionMixin, views.TitleMixin, views.MediaMixin, views.FormNeedsRequest, FormView
630 554
):
......
752 676

  
753 677

  
754 678
class UserOrRoleSelect2View(DetailView):
755
    form_class = forms.ChooseUserOrRoleForm
679
    form_class = forms.RoleAdminForm
756 680
    model = Role
757 681

  
758 682
    def get(self, request, *args, **kwargs):
src/authentic2/manager/static/authentic2/manager/js/manager.js
133 133
          var pk = $tr.data('pk');
134 134
          var pk_arg = $anchor.data('pk-arg');
135 135
          var post_content = {
136
             'csrfmiddlewaretoken': window.csrf_token,
137
            'action': 'remove'}
136
            'csrfmiddlewaretoken': window.csrf_token,
137
            'target': 'members',
138
            'action': 'remove',
139
          }
138 140
          post_content[pk_arg] = pk
139 141
          $.post('', post_content, function () {
140 142
              update_content(window.location.href);
src/authentic2/manager/templates/authentic2/manager/role_members.html
103 103
   </div>
104 104
 </div>
105 105

  
106
 <fieldset class="gadjo-foldable gadjo-folded" id="other-properties">
107
 <legend class="gadjo-foldable-widget">{% trans "Advanced parameters" %}</legend>
108
 <div class="role-inheritance gadjo-folding">
109
   {% trans "Is administered by users" %}
110
   {% for user in object.get_admin_role.all_members %}
111
     <a href="{% url "a2-manager-user-edit" pk=user.pk %}">{{ user }}</a>
112
     {% if user.direct %}
113
       <a rel="popup" href="{% url "a2-manager-role-remove-admin-user" pk=object.pk user_pk=user.pk %}" class="role-remove icon-minus-sign"></a>
114
     {% else %}
115
       <a title="{% trans "Indirect child role" %}" class="disabled role-remove icon-minus-sign"></a>
106
{% if view.can_change %}
107
 <div class="section gadjo-foldable gadjo-folded" id="other-properties">
108
   <h3 class="gadjo-foldable-widget">{% trans "Administrators:" %}</h3>
109
   <div class="role-inheritance gadjo-folding section">
110
     {% if administrators %}
111
       <table class="main">
112
           <thead>
113
               <th>{% trans "Name" %}</th>
114
               <th>{% trans "Type" %}</th>
115
               <th></th>
116
           </thead>
117
           <tbody>{% for admin in administrators %}
118
               <tr>
119
                   <td><a href="{{ admin.get_absolute_url }}" title="{{ admin }}">{{ admin }}</a></td>
120
                   <td>{{ admin.type }}</td>
121
                   <td class="remove-admin-column">{% if admin.direct %}<form method="post">{% csrf_token %}<input type="hidden" name="target" value="admin"/><input type="hidden" name="action" value="remove"/><input type="hidden" name="user_or_roles" value="{{ admin.ref }}"/><button>{% trans "Remove" %}</button></form>{% endif %}</td>
122
               </tr>{% endfor %}
123
           </tbody>
124
       </table>
116 125
     {% endif %}
117
   {% endfor %}
118
  {% if view.can_change %}
119
    <a rel="popup" href="{% url "a2-manager-role-add-admin-user" pk=object.pk %}" class="role-add icon-add-sign"></a>
120
  {% else %}
121
    <a title="{% trans "Permission denied" %}" class="disabled role-add icon-add-sign"></a>
122
  {% endif %}
123
 </div>
124
 <div class="role-inheritance gadjo-folding">
125
   {% trans "Is administered by roles" %}
126
   {% for role in admin_roles %}
127
     <a href="{% url "a2-manager-role-members" pk=role.pk %}">{{ role }}</a>
128
     {% if role.direct %}
129
       <a rel="popup" href="{% url "a2-manager-role-remove-admin-role" pk=object.pk role_pk=role.pk %}" class="role-remove icon-minus-sign"></a>
130
     {% else %}
131
       <a title="{% trans "Indirect admin role" %}" class="disabled role-remove icon-minus-sign"></a>
132
     {% endif %}
133
   {% endfor %}
134
  {% if view.can_change %}
135
    <a rel="popup" href="{% url "a2-manager-role-add-admin-role" pk=object.pk %}" class="role-add icon-add-sign"></a>
136
  {% else %}
137
    <a title="{% trans "Permission denied" %}" class="disabled role-add icon-add-sign"></a>
138
  {% endif %}
126
     <form method="post" class="manager-m2m-add-form" id="add-admin">
127
       {% csrf_token %}
128
       {{ admin_form }}
129
       <button>{% trans "Add" %}</button>
130
     </form>
131
   </div>
139 132
 </div>
140 133
 </fieldset>
134
{% endif %}
141 135
{% endblock %}
src/authentic2/manager/urls.py
127 127
        url(r'^roles/journal/$', role_views.roles_journal, name='a2-manager-roles-journal'),
128 128
        url(r'^roles/(?P<pk>\d+)/$', role_views.members, name='a2-manager-role-members'),
129 129
        url(r'^roles/(?P<pk>\d+)/parents/$', role_views.parents, name='a2-manager-role-parents'),
130
        url(
131
            r'^roles/(?P<pk>\d+)/add-admin-user/$',
132
            role_views.add_admin_user,
133
            name='a2-manager-role-add-admin-user',
134
        ),
135
        url(
136
            r'^roles/(?P<pk>\d+)/remove-admin-user/(?P<user_pk>\d+)/$',
137
            role_views.remove_admin_user,
138
            name='a2-manager-role-remove-admin-user',
139
        ),
140
        url(
141
            r'^roles/(?P<pk>\d+)/add-admin-role/$',
142
            role_views.add_admin_role,
143
            name='a2-manager-role-add-admin-role',
144
        ),
145
        url(
146
            r'^roles/(?P<pk>\d+)/remove-admin-role/(?P<role_pk>\d+)/$',
147
            role_views.remove_admin_role,
148
            name='a2-manager-role-remove-admin-role',
149
        ),
150 130
        url(
151 131
            r'^roles/(?P<pk>\d+)/export/(?P<format>csv)/$',
152 132
            role_views.members_export,
src/authentic2/manager/widgets.py
86 86
        return utils.label_from_user(user)
87 87

  
88 88

  
89
class ChooseUsersWidget(SearchUserWidgetMixin, SimpleModelSelect2MultipleWidget):
90
    pass
91

  
92

  
93 89
class SearchRoleWidgetMixin(SplitTermMixin):
94 90
    model = Role
95 91
    split_term_operator = operator.__and__
......
112 108
        return cls.model.objects.exclude(slug__startswith='_')
113 109

  
114 110

  
115
class ChooseRolesWidget(SearchRoleWidgetMixin, SimpleModelSelect2MultipleWidget):
116
    @classmethod
117
    def get_initial_queryset(cls):
118
        return cls.model.objects.exclude(slug__startswith='_')
119

  
120

  
121
class ChooseManageableMemberRolesWidget(SearchRoleWidgetMixin, SimpleModelSelect2MultipleWidget):
122
    perm = 'manage_members'
123

  
124

  
125 111
class ChooseManageableMemberRoleWidget(SearchRoleWidgetMixin, SimpleModelSelect2Widget):
126 112
    perm = 'manage_members'
127 113

  
tests/test_manager.py
945 945
    q = response.pyquery.remove_namespaces()
946 946
    assert q('table tbody tr td .icon-remove-sign')
947 947
    token = str(response.context['csrf_token'])
948
    params = {'action': 'remove', 'user_or_roles': 'user-%s' % admin.pk, 'csrfmiddlewaretoken': token}
948
    params = {
949
        'action': 'remove',
950
        'target': 'members',
951
        'user_or_roles': 'user-%s' % admin.pk,
952
        'csrfmiddlewaretoken': token,
953
    }
949 954
    app.post('/manage/roles/%s/' % simple_role.pk, params=params)
950 955
    assert simple_role not in admin.roles.all()
951 956

  
......
979 984
    q = response.pyquery.remove_namespaces()
980 985
    assert q('table tbody tr td .icon-remove-sign')
981 986
    token = str(response.context['csrf_token'])
982
    params = {'action': 'remove', 'user_or_roles': 'role-%s' % role.pk, 'csrfmiddlewaretoken': token}
987
    params = {
988
        'action': 'remove',
989
        'target': 'members',
990
        'user_or_roles': 'role-%s' % role.pk,
991
        'csrfmiddlewaretoken': token,
992
    }
983 993
    app.post('/manage/roles/%s/' % simple_role.pk, params=params)
984 994
    assert role not in simple_role.children()
985 995

  
......
1009 1019

  
1010 1020
def test_manager_widget_fields_validation(app, simple_user, simple_role):
1011 1021
    '''Verify that fields corresponding to widget implement queryset restrictions.'''
1012
    from authentic2.manager.forms import (
1013
        ChooseRoleForm,
1014
        ChooseUserRoleForm,
1015
        RoleParentForm,
1016
        RolesForm,
1017
        UsersForm,
1018
    )
1022
    from authentic2.manager.forms import ChooseRoleForm, ChooseUserRoleForm, RoleParentForm
1019 1023

  
1020 1024
    error_message = 'Select a valid choice'
1021 1025

  
......
1027 1031
    visible_role = Role.objects.create(name='visible_role', ou=simple_user.ou)
1028 1032
    visible_user = User.objects.create(username='visible_user', ou=simple_user.ou)
1029 1033
    forbidden_role = Role.objects.create(name='forbidden_role', ou=simple_user.ou)
1030
    forbidden_user = User.objects.create(username='forbidden_user', ou=simple_user.ou)
1031 1034

  
1032 1035
    view_role_perm = Permission.objects.create(
1033 1036
        operation=get_operation(VIEW_OP),
......
1048 1051
    form = ChooseRoleForm(request=request, data={'role': forbidden_role.pk, 'action': 'add'})
1049 1052
    assert error_message in form.errors['role'][0]
1050 1053

  
1051
    form = UsersForm(request=request, data={'users': [visible_user.pk]})
1052
    assert form.is_valid()
1053
    form = UsersForm(request=request, data={'users': [forbidden_user.pk]})
1054
    assert error_message in form.errors['users'][0]
1055

  
1056
    form = RolesForm(request=request, data={'roles': [visible_role.pk]})
1057
    assert form.is_valid()
1058
    form = RolesForm(request=request, data={'roles': [forbidden_role.pk]})
1059
    assert error_message in form.errors['roles'][0]
1060

  
1061 1054
    # For those we need manage_members permission
1062 1055
    form = RoleParentForm(request=request, data={'role': visible_role.pk, 'action': 'add'})
1063 1056
    assert error_message in form.errors['role'][0]
tests/test_role_manager.py
589 589

  
590 590
    # simulate click on Jôhn Dôe delete icon
591 591
    token = str(resp.context['csrf_token'])
592
    params = {'action': 'remove', 'user_or_roles': 'user-%s' % simple_user.pk, 'csrfmiddlewaretoken': token}
592
    params = {
593
        'action': 'remove',
594
        'target': 'members',
595
        'user_or_roles': 'user-%s' % simple_user.pk,
596
        'csrfmiddlewaretoken': token,
597
    }
593 598
    resp = app.post('/manage/roles/%s/' % simple_role.pk, params=params).follow()
594 599
    assert 'Jôhn Dôe' not in resp.text
595 600

  
596 601
    # simulate click on role_ou1 delete icon
597 602
    token = str(resp.context['csrf_token'])
598
    params = {'action': 'remove', 'user_or_roles': 'role-%s' % role_ou1.pk, 'csrfmiddlewaretoken': token}
603
    params = {
604
        'action': 'remove',
605
        'target': 'members',
606
        'user_or_roles': 'role-%s' % role_ou1.pk,
607
        'csrfmiddlewaretoken': token,
608
    }
599 609
    resp = app.post('/manage/roles/%s/' % simple_role.pk, params=params).follow()
600 610
    assert 'role_ou1' not in resp.text
601 611

  
602
-