Projet

Général

Profil

0001-manager-prevent-changing-ldap-sychronised-role-affec.patch

Valentin Deniaud, 18 novembre 2019 16:56

Télécharger (6,96 ko)

Voir les différences:

Subject: [PATCH] manager: prevent changing ldap-sychronised role affectations
 (#37187)

 src/authentic2/manager/role_views.py          |  5 ++++
 src/authentic2/manager/tables.py              |  4 ++-
 .../authentic2/manager/user_roles_table.html  |  6 ++++-
 src/authentic2/manager/user_views.py          | 15 +++++++++--
 tests/test_ldap.py                            | 26 +++++++++++++++++++
 5 files changed, 52 insertions(+), 4 deletions(-)
src/authentic2/manager/role_views.py
16 16

  
17 17
import json
18 18

  
19
from django.conf import settings
19 20
from django.core.exceptions import PermissionDenied
20 21
from django.utils.translation import ugettext_lazy as _
21 22
from django.views.generic import FormView, TemplateView
......
194 195
        ctx['admin_roles'] = views.filter_view(self.request,
195 196
                                               self.object.get_admin_role().children(include_self=False,
196 197
                                                                                     annotate=True))
198
        mappings = getattr(settings, 'LDAP_AUTH_SETTINGS', [{}])[0].get('group_to_role_mapping', [])
199
        if mappings:
200
            ctx['from_ldap'] = any(role for mapping in mappings for role in mapping[1]
201
                                   if role == self.object.name)
197 202
        return ctx
198 203

  
199 204
members = RoleMembersView.as_view()
src/authentic2/manager/tables.py
122 122
        'indeterminate{%% endif %%}"'
123 123
        ' name="role-{{ record.pk }}" type="checkbox" {%% if record.member %%}checked{%% endif %%} '
124 124
        '{%% if not record.has_perm %%}disabled '
125
        'title="{%% trans "%s" %%}"{%% endif %%}/>' % ugettext_noop('You are not authorized to manage this role'),
125
        'title="{%% trans "%s" %%}"{%% endif %%} '
126
        '{%% if record.from_ldap %%}disabled '
127
        'title="{%% trans "%s" %%}"{%% endif %%}/>' % (ugettext_noop('You are not authorized to manage this role'), ugettext_noop('This role is synchronised from LDAP, modification is not allowed.')),
126 128
        verbose_name=_('Member'),
127 129
        order_by=('member', 'via', 'name'))
128 130

  
src/authentic2/manager/templates/authentic2/manager/user_roles_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.member %}<a class="icon-remove-sign js-remove-object" data-confirm="{% blocktrans with name=row.record.name username=table.context.object.get_full_name %}Do you really want to remove role &quot;{{ name }}&quot; from user &quot;{{ username }}&quot;&nbsp;?{% endblocktrans %}" href="#" data-pk-arg="role"></a>{% endif %}</td>
10
  <td>
11
    {% if table.context.view.can_change and row.record.member %}
12
      <a class="icon-remove-sign {% if row.record.from_ldap %} disabled {% else %} js-remove-object {% endif %}" data-confirm="{% blocktrans with name=row.record.name username=table.context.object.get_full_name %}Do you really want to remove role &quot;{{ name }}&quot; from user &quot;{{ username }}&quot;&nbsp;?{% endblocktrans %}" href="#" data-pk-arg="role" title="{% if row.record.from_ldap %}{% trans "This role is synchronised from LDAP, modification is not allowed." %}{% endif %}"></a>
13
    {% endif %}
14
  </td>
11 15
  {% endblock %}
12 16
{% endif %}
src/authentic2/manager/user_views.py
19 19
import collections
20 20
import operator
21 21

  
22
from django.conf import settings
22 23
from django.db import models
23 24
from django.utils.translation import ugettext_lazy as _, ugettext
24 25
from django.utils.html import format_html
......
557 558
            manageable_ids = map(str, qs2.values_list('pk', flat=True))
558 559
            qs = qs.extra(select={'has_perm': 'a2_rbac_role.id in (%s)' % ', '.join(manageable_ids)})
559 560
            qs = qs.exclude(slug__startswith='_a2-managers-of-role')
560
            return qs
561 561
        else:
562
            return self.object.roles_and_parents()
562
            qs = self.object.roles_and_parents()
563
        qs = self.indicate_ldap_roles(qs)
564
        return qs
565

  
566
    def indicate_ldap_roles(self, qs):
567
        mappings = getattr(settings, 'LDAP_AUTH_SETTINGS', [{}])[0].get('group_to_role_mapping', [])
568
        if mappings:
569
            role_names = [role for mapping in mappings for role in mapping[1]]
570
            roles = qs.filter(name__in=role_names)
571
            role_ids = map(str, roles.values_list('pk', flat=True))
572
            qs = qs.extra(select={'from_ldap': 'a2_rbac_role.id in (%s)' % ', '.join(role_ids)})
573
        return qs
563 574

  
564 575
    def get_table_data(self):
565 576
        qs = super(UserRolesView, self).get_table_data()
tests/test_ldap.py
345 345
    assert response.context['user'].roles.count() == 1
346 346

  
347 347

  
348
def test_group_to_role_mapping_modify_disabled(slapd, settings, db, app, admin, simple_user):
349
    from authentic2.a2_rbac.models import Role
350

  
351
    role = Role.objects.get_or_create(name='Role2', ou=simple_user.ou)[0]
352
    simple_user.roles.add(role)
353
    settings.LDAP_AUTH_SETTINGS = [{
354
        'url': [slapd.ldap_url],
355
        'basedn': u'o=ôrga',
356
        'use_tls': False,
357
        'group_to_role_mapping': [
358
            ['cn=group2,o=ôrga', ['Role2']],
359
        ],
360
    }]
361
    utils.login(app, admin, '/manage/')
362

  
363
    response = app.get('/manage/users/%s/roles/?search-ou=all' % simple_user.pk)
364
    q = response.pyquery.remove_namespaces()
365
    assert q('table tbody td.name').text() == 'Role2'
366
    assert q('table tbody td .disabled')
367

  
368
    response = app.get('/manage/users/%s/roles/?search-ou=%s' % (simple_user.pk, simple_user.ou.pk))
369
    q = response.pyquery.remove_namespaces()
370
    assert q('table tbody td.name').text() == 'Role2'
371
    assert q('table tbody td.member input').attr('disabled')
372

  
373

  
348 374
def test_group_su(slapd, settings, client, db):
349 375
    from django.contrib.auth.models import Group
350 376

  
351
-