0002-manage-remove-Add-a-role-as-member-menu-entry-61188-.patch
src/authentic2/manager/role_views.py | ||
---|---|---|
409 | 409 |
members_export = RoleMembersExportView.as_view() |
410 | 410 | |
411 | 411 | |
412 |
class RoleChildrenView(RoleViewMixin, views.HideOUColumnMixin, views.BaseSubTableView): |
|
413 |
title = _('Add child role') |
|
414 |
form_class = forms.ChooseRoleForm |
|
415 |
table_class = tables.InheritanceRolesTable |
|
416 |
search_form_class = forms.RoleSearchForm |
|
417 |
template_name = 'authentic2/manager/roles_inheritance.html' |
|
418 |
permissions = ['a2_rbac.manage_members_role'] |
|
419 |
success_url = '.' |
|
420 |
slug_field = 'uuid' |
|
421 | ||
422 |
def get_table_queryset(self): |
|
423 |
qs = super().get_table_queryset() |
|
424 |
qs = qs.exclude(pk=self.object.pk) |
|
425 |
children = self.object.children(annotate=True, include_self=False) |
|
426 |
children = children.annotate(is_direct=Cast('direct', output_field=BooleanField())) |
|
427 |
qs = qs.annotate( |
|
428 |
checked=ExpressionWrapper(Q(pk__in=children.filter(is_direct=True)), output_field=BooleanField()) |
|
429 |
) |
|
430 |
qs = qs.annotate( |
|
431 |
indeterminate=ExpressionWrapper( |
|
432 |
Q(pk__in=children.filter(is_direct=False)), output_field=BooleanField() |
|
433 |
) |
|
434 |
) |
|
435 |
rp_qs = RoleParenting.objects.filter(parent__in=children).annotate(name=F('parent__name')) |
|
436 |
qs = qs.prefetch_related(Prefetch('parent_relation', queryset=rp_qs, to_attr='via')) |
|
437 |
return qs |
|
438 | ||
439 |
def form_valid(self, form): |
|
440 |
role = form.cleaned_data['role'] |
|
441 |
action = form.cleaned_data['action'] |
|
442 |
if action == 'add': |
|
443 |
self.object.add_child(role) |
|
444 |
hooks.call_hooks( |
|
445 |
'event', name='manager-add-child-role', user=self.request.user, parent=self.object, child=role |
|
446 |
) |
|
447 |
self.request.journal.record('manager.role.inheritance.addition', parent=self.object, child=role) |
|
448 |
elif action == 'remove': |
|
449 |
self.object.remove_child(role) |
|
450 |
hooks.call_hooks( |
|
451 |
'event', |
|
452 |
name='manager-remove-child-role', |
|
453 |
user=self.request.user, |
|
454 |
parent=self.object, |
|
455 |
child=role, |
|
456 |
) |
|
457 |
self.request.journal.record('manager.role.inheritance.removal', parent=self.object, child=role) |
|
458 |
return super().form_valid(form) |
|
459 | ||
460 |
def get_search_form_kwargs(self): |
|
461 |
kwargs = super().get_search_form_kwargs() |
|
462 |
kwargs['queryset'] = self.request.user.filter_by_perm('a2_rbac.view_role', Role.objects.all()) |
|
463 |
return kwargs |
|
464 | ||
465 | ||
466 |
children = RoleChildrenView.as_view() |
|
467 | ||
468 | ||
469 | 412 |
class RoleParentsView(RoleViewMixin, views.HideOUColumnMixin, views.BaseSubTableView): |
470 | 413 |
title = _('Add parent role') |
471 | 414 |
form_class = forms.RoleParentForm |
src/authentic2/manager/static/authentic2/manager/css/style.css | ||
---|---|---|
243 | 243 |
/* Select2 styling */ |
244 | 244 | |
245 | 245 |
span.select2-container { |
246 |
width: auto !important; |
|
247 | 246 |
flex-grow: 1; |
248 | 247 |
margin-right: 1em; |
249 | 248 |
} |
src/authentic2/manager/templates/authentic2/manager/role_members.html | ||
---|---|---|
42 | 42 |
<li><a href="{% url "a2-manager-role-permissions" pk=object.pk %}">{% trans "Permissions" %}</a></li> |
43 | 43 |
{% endif %} |
44 | 44 |
<li><a href="{% url "a2-manager-role-journal" pk=object.pk %}">{% trans "Journal" %}</a></li> |
45 |
{% if view.can_manage_members %} |
|
46 |
<li><a href="{% url "a2-manager-role-children" pk=object.pk %}">{% trans "Add a role as a member" %}</a></li> |
|
47 |
{% endif %} |
|
48 | 45 |
</ul> |
49 | 46 |
</span> |
50 | 47 |
{% endblock %} |
src/authentic2/manager/urls.py | ||
---|---|---|
126 | 126 |
url(r'^roles/export/(?P<format>csv|json)/$', role_views.export, name='a2-manager-roles-export'), |
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 |
url(r'^roles/(?P<pk>\d+)/children/$', role_views.children, name='a2-manager-role-children'), |
|
130 | 129 |
url(r'^roles/(?P<pk>\d+)/parents/$', role_views.parents, name='a2-manager-role-parents'), |
131 | 130 |
url( |
132 | 131 |
r'^roles/(?P<pk>\d+)/add-admin-user/$', |
tests/test_manager.py | ||
---|---|---|
958 | 958 |
simple_user.roles.add(simple_role) |
959 | 959 |
admin.roles.add(role) |
960 | 960 | |
961 |
response = app.get('/manage/roles/%s/children/' % simple_role.pk) |
|
962 |
token = str(response.context['csrf_token']) |
|
963 |
params = {'action': 'add', 'role': role.pk, 'csrfmiddlewaretoken': token} |
|
964 |
response = app.post('/manage/roles/%s/children/' % simple_role.pk, params=params) |
|
965 |
assert role in simple_role.children() |
|
966 | ||
967 |
params = {'action': 'remove', 'role': role.pk, 'csrfmiddlewaretoken': token} |
|
968 |
response = app.post('/manage/roles/%s/children/' % simple_role.pk, params=params) |
|
969 |
assert role not in simple_role.children() |
|
970 | ||
971 | 961 |
response = app.get('/manage/roles/%s/parents/' % role.pk) |
972 | 962 |
token = str(response.context['csrf_token']) |
973 | 963 |
params = {'action': 'add', 'role': simple_role.pk, 'csrfmiddlewaretoken': token} |
... | ... | |
1096 | 1086 |
assert form.is_valid() |
1097 | 1087 | |
1098 | 1088 | |
1099 |
@pytest.mark.parametrize('relation', ['children', 'parents']) |
|
1100 |
def test_manager_role_inheritance_list(app, admin, simple_role, ou1, relation): |
|
1089 |
def test_manager_role_inheritance_list_parent(app, admin, simple_role, ou1): |
|
1101 | 1090 |
first_role = Role.objects.create(name='first_role', ou=simple_role.ou) |
1102 | 1091 |
second_role = Role.objects.create(name='second_role', ou=simple_role.ou) |
1103 | 1092 |
third_role = Role.objects.create(name='third_role', ou=ou1) |
1104 | 1093 | |
1105 |
if relation == 'children': |
|
1106 |
simple_role.add_child(first_role) |
|
1107 |
first_role.add_child(second_role) |
|
1108 |
elif relation == 'parents': |
|
1109 |
simple_role.add_parent(first_role) |
|
1110 |
first_role.add_parent(second_role) |
|
1094 |
simple_role.add_parent(first_role) |
|
1095 |
first_role.add_parent(second_role) |
|
1111 | 1096 | |
1112 | 1097 |
response = login(app, admin) |
1113 |
response = app.get('/manage/roles/%s/%s/' % (simple_role.pk, relation))
|
|
1098 |
response = app.get('/manage/roles/%s/parents/' % simple_role.pk)
|
|
1114 | 1099 |
q = response.pyquery.remove_namespaces() |
1115 | 1100 |
assert len(q('table tbody tr')) == 3 |
1116 | 1101 |
assert {e.text_content() for e in q('table tbody td.name')} == { |
... | ... | |
1165 | 1150 | |
1166 | 1151 |
response = login(app, simple_user, '/manage/roles/') |
1167 | 1152 | |
1168 |
# all visible roles are shown, except current role |
|
1169 |
response = app.get('/manage/roles/%s/children/' % simple_role.pk) |
|
1170 |
q = response.pyquery.remove_namespaces() |
|
1171 |
assert len(q('table tbody tr')) == 2 |
|
1172 |
assert {e.text_content() for e in q('table tbody td.name')} == {visible_role.name, visible_role_2.name} |
|
1173 | ||
1174 |
# filter by ou |
|
1175 |
response.form['search-ou'] = ou1.pk |
|
1176 |
response = response.form.submit() |
|
1177 |
q = response.pyquery.remove_namespaces() |
|
1178 |
assert len(q('table tbody tr')) == 1 |
|
1179 |
assert {e.text_content() for e in q('table tbody td.name')} == {visible_role_2.name} |
|
1180 | ||
1181 |
# filter by name |
|
1182 |
response.form['search-text'] = '2' |
|
1183 |
response.form['search-ou'] = 'all' |
|
1184 |
response = response.form.submit() |
|
1185 |
q = response.pyquery.remove_namespaces() |
|
1186 |
assert len(q('table tbody tr')) == 1 |
|
1187 |
assert {e.text_content() for e in q('table tbody td.name')} == {visible_role_2.name} |
|
1188 | ||
1189 | 1153 |
# all roles with manage_members permissions are shown |
1190 | 1154 |
response = app.get('/manage/roles/%s/parents/' % visible_role.pk) |
1191 | 1155 |
q = response.pyquery.remove_namespaces() |
tests/test_role_manager.py | ||
---|---|---|
473 | 473 |
rows = [text_content(el) for el in resp.pyquery('tr td.link')] |
474 | 474 |
assert rows == ['user1', 'Jôhn Dôe'] |
475 | 475 | |
476 |
resp = resp.click('Add a role as a member') |
|
477 |
assert 'Role a' in resp.text |
|
478 | ||
479 | 476 |
# add child role to child |
480 | 477 |
grandchild = Role.objects.create(name='grandchild') |
481 | 478 |
role.add_child(grandchild) |
482 |
- |