Projet

Général

Profil

0004-manager-display-inheritance-info-excerpt-in-table-on.patch

Valentin Deniaud, 03 août 2021 18:13

Télécharger (13 ko)

Voir les différences:

Subject: [PATCH 4/4] manager: display inheritance info excerpt in table on
 role page (#53481)

 src/authentic2/manager/role_views.py          | 21 +++--
 .../static/authentic2/manager/css/style.css   |  4 +
 .../authentic2/manager/role_members.html      | 84 +++++++++++++------
 tests/test_ldap.py                            |  2 +-
 tests/test_manager.py                         | 50 -----------
 tests/test_role_manager.py                    | 64 ++++++++++++++
 6 files changed, 141 insertions(+), 84 deletions(-)
src/authentic2/manager/role_views.py
242 242

  
243 243
    def get_context_data(self, **kwargs):
244 244
        ctx = super().get_context_data(**kwargs)
245
        ctx['children'] = views.filter_view(
246
            self.request, self.object.children(include_self=False, annotate=True)
245
        ctx['children'] = list(
246
            views.filter_view(
247
                self.request,
248
                self.object.children(include_self=False, annotate=True).order_by(
249
                    F('ou').asc(nulls_first=True), 'name'
250
                ),
251
            )[:11]
247 252
        )
248
        ctx['parents'] = views.filter_view(
249
            self.request,
250
            self.object.parents(include_self=False, annotate=True).order_by(
251
                F('ou').asc(nulls_first=True), 'name'
252
            ),
253
        ctx['parents'] = list(
254
            views.filter_view(
255
                self.request,
256
                self.object.parents(include_self=False, annotate=True).order_by(
257
                    F('ou').asc(nulls_first=True), 'name'
258
                ),
259
            )[:11]
253 260
        )
254 261
        ctx['has_multiple_ou'] = OU.objects.count() > 1
255 262
        ctx['admin_roles'] = views.filter_view(
src/authentic2/manager/static/authentic2/manager/css/style.css
273 273
table.main.plaintable tr:hover td {
274 274
	cursor: default;
275 275
}
276

  
277
a.role-inheritance-view-all {
278
    font-style: italic;
279
}
src/authentic2/manager/templates/authentic2/manager/role_members.html
71 71
           <button>{% trans "Add" %}</button>
72 72
   </form>
73 73
 {% endif %}
74

  
75
 <div class="section">
76
   <h3>{% trans "Child roles" %}
77
     {% if view.can_manage_members %}
78
     <a href="{% url "a2-manager-role-children" pk=object.pk %}" class="button">{% trans "Edit" %}</a>
79
     {% else %}
80
     <a title="{% trans "Permission denied" %}" class="button disabled">{% trans "Edit" %}</a>
81
     {% endif %}
82
   </h3>
83
   <div>
84
     {% if children %}
85
     <ul class="objects-list single-links">
86
       {% for child in children|slice:":10" %}
87
       <li>
88
         <a  class="role-inheritance-child" href="{% url "a2-manager-role-members" pk=child.pk %}">{% if child.ou and has_multiple_ou %}{{ child.ou }} - {% endif %}{{ child }}</a>
89
         {% if not child.direct %}
90
         <span class="badge">{% trans "Indirect" %}</span>
91
         {% endif %}
92
       </li>
93
       {% endfor %}
94
       {% if children|length > 10 %}
95
       <li><a class="role-inheritance-view-all" href="{% url "a2-manager-role-children" pk=object.pk %}">({% trans "view all roles" %})</a></li>
96
       {% endif %}
97
     </ul>
98
     {% else %}
99
     <p>{% trans "This role has no children." %}</p>
100
     {% endif %}
101
   </div>
102
 </div>
103
 <div class="section">
104
   <h3>{% trans "Parent roles" %}
105
     {% if not object.is_internal %}
106
     <a href="{% url "a2-manager-role-parents" pk=object.pk %}" class="button">{% trans "Edit" %}</a>
107
     {% else %}
108
     <a title="{% trans "This role is technical, you cannot modify its permissions." %}" class="button disabled">{% trans "Edit" %}</a>
109
     {% endif %}
110
   </h3>
111
   <div>
112
     {% if parents %}
113
     <ul class="objects-list single-links">
114
       {% for parent in parents|slice:":10" %}
115
       <li>
116
         <a class="role-inheritance-parent" href="{% url "a2-manager-role-members" pk=parent.pk %}">{% if parent.ou and has_multiple_ou %}{{ parent.ou }} - {% endif %}{{ parent }}</a>
117
         {% if not parent.direct %}
118
         <span class="badge">{% trans "Indirect" %}</span>
119
         {% endif %}
120
       </li>
121
       {% endfor %}
122
       {% if parents|length > 10 %}
123
       <li><a class="role-inheritance-view-all" href="{% url "a2-manager-role-parents" pk=object.pk %}">({% trans "view all roles" %})</a></li>
124
       {% endif %}
125
     </ul>
126
     {% else %}
127
     <p>{% trans "This role has no parents." %}</p>
128
     {% endif %}
129
   </div>
130
 </div>
131

  
74 132
 <fieldset class="gadjo-foldable gadjo-folded" id="other-properties">
75 133
 <legend class="gadjo-foldable-widget">{% trans "Advanced parameters" %}</legend>
76 134
 <div class="role-inheritance gadjo-folding">
......
105 163
    <a title="{% trans "Permission denied" %}" class="disabled role-add icon-add-sign"></a>
106 164
  {% endif %}
107 165
 </div>
108
 <div class="role-inheritance gadjo-folding">
109
   {% trans "Child roles:" %}
110
   {% for child in children %}
111
     <a href="{% url "a2-manager-role-members" pk=child.pk %}">{{ child }}</a>
112
     {% if not forloop.last %} − {% endif %}
113
   {% endfor %}
114
  {% if view.can_manage_members %}
115
    <a href="{% url "a2-manager-role-children" pk=object.pk %}" class="role-add icon-add-sign"></a>
116
  {% else %}
117
    <a title="{% trans "Permission denied" %}" class="disabled role-add icon-add-sign"></a>
118
  {% endif %}
119
 </div>
120
 <div class="role-inheritance gadjo-folding">
121
   {% trans "Parent roles:" %}
122
   {% for parent in parents %}
123
     <a class="role" href="{% url "a2-manager-role-members" pk=parent.pk %}">
124
       {% if parent.ou and has_multiple_ou %}{{ parent.ou }} - {% endif %}{{ parent }}
125
     </a>
126
    {% if not forloop.last %} − {% endif %}
127
   {% endfor %}
128
   {% if not object.is_internal %}
129
     <a href="{% url "a2-manager-role-parents" pk=object.pk %}" class="role-add icon-add-sign"></a>
130
   {% else %}
131
     <a title="{% trans "This role is technical, you cannot modify its permissions." %}" class="disabled role-add icon-add-sign"></a>
132
   {% endif %}
133
 </div>
134 166
 </fieldset>
135 167
{% endblock %}
tests/test_ldap.py
652 652
    assert 'synchronised from LDAP' in response.text
653 653
    q = response.pyquery.remove_namespaces()
654 654
    assert not q('form.manager-m2m-add-form')
655
    assert q('div.role-inheritance .role-add.disabled')
655
    assert q('div.section h3 a.button.disabled')
656 656
    assert not q('table tbody td a.icon-remove-sign js-remove-object')
657 657

  
658 658

  
tests/test_manager.py
1161 1161
    assert {e.text_content() for e in q('table tbody td.name')} == {simple_role.name}
1162 1162

  
1163 1163

  
1164
def test_display_parent_roles_on_role_page(app, superuser, settings):
1165
    ou1 = get_default_ou()
1166
    ou1.name = 'ou1'
1167
    ou1.save()
1168

  
1169
    child = Role.objects.create(name='child', slug='role', ou=ou1)
1170
    parent1 = Role.objects.create(name='parent1', slug='role1', ou=None)
1171
    parent2 = Role.objects.create(name='parent2', slug='role2', ou=ou1)
1172
    child.add_parent(parent1)
1173
    child.add_parent(parent2)
1174
    child.save()
1175

  
1176
    # do not display roles if we have a single OU
1177
    url = reverse('a2-manager-role-members', kwargs={'pk': child.pk})
1178
    login(app, superuser)
1179
    response = app.get(url, status=200)
1180
    parent_roles_html = response.html.find_all('div', {'class': 'role-inheritance'})[3]
1181
    assert 'Parent roles:' in parent_roles_html.text
1182
    assert [x.text.strip() for x in parent_roles_html.find_all('a', {'class': 'role'})] == [
1183
        'parent1',
1184
        'parent2',
1185
    ]
1186

  
1187
    # display parent roles if we have multiple OUs
1188
    ou2 = OU.objects.create(name='ou2')
1189
    response = app.get(url, status=200)
1190
    parent_roles_html = response.html.find_all('div', {'class': 'role-inheritance'})[3]
1191
    assert 'Parent roles:' in parent_roles_html.text
1192
    assert [x.text.strip() for x in parent_roles_html.find_all('a', {'class': 'role'})] == [
1193
        'parent1',
1194
        'ou1 - parent2',
1195
    ]
1196

  
1197
    # display parent roles sorted by OU
1198
    parent3 = Role.objects.create(name='parent3', slug='role3', ou=ou2)
1199
    child.add_parent(parent3)
1200
    parent4 = Role.objects.create(name='parent4', slug='role4', ou=ou1)
1201
    child.add_parent(parent4)
1202
    child.save()
1203
    response = app.get(url, status=200)
1204
    parent_roles_html = response.html.find_all('div', {'class': 'role-inheritance'})[3]
1205
    assert 'Parent roles:' in parent_roles_html.text
1206
    assert [x.text.strip() for x in parent_roles_html.find_all('a', {'class': 'role'})] == [
1207
        'parent1',
1208
        'ou1 - parent2',
1209
        'ou1 - parent4',
1210
        'ou2 - parent3',
1211
    ]
1212

  
1213

  
1214 1164
def test_manager_service_search(app, admin, ou1):
1215 1165
    Service.objects.create(ou=ou1, slug='test', name='Test Service')
1216 1166
    Service.objects.create(ou=get_default_ou(), slug='example', name='Example Service')
tests/test_role_manager.py
16 16

  
17 17
import json
18 18

  
19
import pytest
20
from django.urls import reverse
19 21
from django.utils.encoding import force_bytes, force_text
20 22
from webtest import Upload
21 23

  
22 24
from authentic2.a2_rbac.models import OrganizationalUnit, Role
23 25
from authentic2.a2_rbac.utils import get_default_ou
24 26
from authentic2.custom_user.models import User
27
from django_rbac.utils import get_ou_model, get_role_model
25 28

  
26 29
from .utils import login, text_content
27 30

  
31
OU = get_ou_model()
32
Role = get_role_model()
33

  
28 34

  
29 35
def test_manager_role_export(app, admin, ou1, role_ou1, ou2, role_ou2):
30 36
    import csv
......
336 342
    resp = app.get('/manage/roles/csv-import/')
337 343
    resp = resp.click('Download sample')
338 344
    assert 'name,slug,ou' in resp.text
345

  
346

  
347
@pytest.mark.parametrize('relation', ['child', 'parent'])
348
def test_role_members_display_inheritance_info(app, superuser, settings, simple_role, relation):
349
    url = reverse('a2-manager-role-members', kwargs={'pk': simple_role.pk})
350

  
351
    resp = login(app, superuser, url)
352
    assert 'This role has no children.' in resp.text
353
    assert 'This role has no parents.' in resp.text
354

  
355
    for i in range(10):
356
        role = Role.objects.create(name=f'Role {i}', ou=get_default_ou())
357
        getattr(simple_role, 'add_%s' % relation)(role)
358

  
359
    resp = app.get(url)
360
    if relation == 'child':
361
        assert 'This role has no children.' not in resp.text
362
        assert 'This role has no parents.' in resp.text
363
    elif relation == 'parent':
364
        assert 'This role has no children.' in resp.text
365
        assert 'This role has no parents.' not in resp.text
366

  
367
    for i, el in enumerate(resp.pyquery.find('a.role-inheritance-%s' % relation)):
368
        assert el.text == f'Role {i}'
369
    assert '(view all roles)' not in resp.text
370

  
371
    role = Role.objects.create(name=f'Role a', ou=get_default_ou())
372
    getattr(simple_role, 'add_%s' % relation)(role)
373
    resp = app.get(url)
374
    assert 'Role a' not in resp.text
375
    assert '(view all roles)' in resp.text
376

  
377
    resp = resp.click('(view all roles)', href=relation)
378
    assert 'Role a' in resp.text
379

  
380
    # display OU if there are more than one
381
    ou1 = OU.objects.create(name='ou1')
382
    resp = app.get(url)
383
    for i, el in enumerate(resp.pyquery.find('a.role-inheritance-%s' % relation)):
384
        assert el.text == f'Default organizational unit - Role {i}'
385

  
386
    # sort by OU, then name
387
    Role.objects.filter(name__in=['Role 2', 'Role 3', 'Role 4']).update(ou=ou1)
388
    Role.objects.filter(name__in=['Role 5', 'Role 6']).update(ou=None)
389

  
390
    resp = app.get(url)
391
    assert [el.text for el in resp.pyquery.find('a.role-inheritance-%s' % relation)] == [
392
        'Role 5',
393
        'Role 6',
394
        'Default organizational unit - Role 0',
395
        'Default organizational unit - Role 1',
396
        'Default organizational unit - Role 7',
397
        'Default organizational unit - Role 8',
398
        'Default organizational unit - Role 9',
399
        'Default organizational unit - Role a',
400
        'ou1 - Role 2',
401
        'ou1 - Role 3',
402
    ]
339
-