Projet

Général

Profil

0001-support-organizational-unit-automatic-roles-20690.patch

Paul Marillonnet, 02 août 2018 17:58

Télécharger (9,55 ko)

Voir les différences:

Subject: [PATCH] support organizational unit automatic roles (#20690)

 src/authentic2/a2_rbac/models.py     | 20 +++++++++++
 src/authentic2/custom_user/models.py |  4 ++-
 src/authentic2/manager/user_views.py | 17 +++++++---
 src/django_rbac/managers.py          | 11 ++++--
 tests/conftest.py                    | 16 +++++++++
 tests/test_a2_rbac.py                | 51 +++++++++++++++++++++++++++-
 6 files changed, 109 insertions(+), 10 deletions(-)
src/authentic2/a2_rbac/models.py
23 23
from . import managers, fields
24 24

  
25 25

  
26
class OUAutomaticRoles(models.Model):
27
    ou = models.ForeignKey('OrganizationalUnit')
28
    role = models.ForeignKey('Role')
29

  
30

  
26 31
class OrganizationalUnit(OrganizationalUnitAbstractBase):
27 32
    username_is_unique = models.BooleanField(
28 33
        blank=True,
......
40 45
        default=False,
41 46
        verbose_name=_('Validate emails'))
42 47

  
48
    automatic_roles = models.ManyToManyField('Role', through=OUAutomaticRoles)
49

  
43 50
    admin_perms = GenericRelation(rbac_utils.get_permission_model_name(),
44 51
                                  content_type_field='target_ct',
45 52
                                  object_id_field='target_id')
......
55 62
            ('slug',),
56 63
        )
57 64

  
65
    def add_automatic_role(self, role):
66
        if not OUAutomaticRoles.objects.filter(ou=self, role=role):
67
            role = OUAutomaticRoles.objects.create(ou=self, role=role)
68
            role.save()
69

  
70
    def delete_automatic_role(self, role):
71
        for role in OUAutomaticRoles.objects.filter(ou=self, role=role):
72
            role.delete()
73

  
74
    def clear_automatic_roles(self):
75
        for role in OUAutomaticRoles.objects.filter(ou=self):
76
            role.delete()
77

  
58 78
    def clean(self):
59 79
        # if we set this ou as the default one, we must unset the other one if
60 80
        # there is
src/authentic2/custom_user/models.py
150 150
    def roles_and_parents(self):
151 151
        qs1 = self.roles.all()
152 152
        qs2 = qs1.model.objects.filter(child_relation__child=qs1)
153
        qs = (qs1 | qs2).order_by('name').distinct()
153
        qs3 = qs1.model.objects.for_user(user=self)
154
        qs = (qs1 | qs2).distinct()
155
        qs = (qs | qs3).order_by('name').distinct()
154 156
        RoleParenting = get_role_parenting_model()
155 157
        rp_qs = RoleParenting.objects.filter(child=qs1)
156 158
        qs = qs.prefetch_related(models.Prefetch(
src/authentic2/manager/user_views.py
415 415

  
416 416
    def get_table_queryset(self):
417 417
        if self.is_ou_specified():
418
            roles = self.object.roles.all()
419
            User = get_user_model()
420 418
            Role = get_role_model()
419
            roles = Role.objects.for_user(self.object)
420
            User = get_user_model()
421 421
            RoleParenting = get_role_parenting_model()
422 422
            rp_qs = RoleParenting.objects.filter(child=roles)
423 423
            qs = Role.objects.all()
......
448 448
            return redirect(request, 'a2-manager-user-detail', kwargs={'pk': self.object.pk})
449 449

  
450 450
    def form_valid(self, form):
451
        Role = get_role_model()
451 452
        user = self.object
452 453
        role = form.cleaned_data['role']
453 454
        action = form.cleaned_data['action']
......
463 464
                    hooks.call_hooks('event', name='manager-add-role-member',
464 465
                                     user=self.request.user, role=role, member=user)
465 466
            elif action == 'remove':
466
                user.roles.remove(role)
467
                hooks.call_hooks('event', name='manager-remove-role-member', user=self.request.user,
468
                                 role=role, member=user)
467
                if user.roles.filter(pk=role.pk):
468
                    user.roles.remove(role)
469
                    hooks.call_hooks('event', name='manager-remove-role-member', user=self.request.user,
470
                                     role=role, member=user)
471
                elif role in Role.objects.for_user(user):
472
                    messages.warning(
473
                        self.request,
474
                        _('User {user} has role {role} automatically obtained from OU {ou}.')
475
                        .format(user=user, role=role, ou=user.ou))
469 476
        else:
470 477
            messages.warning(self.request, _('You are not authorized'))
471 478
        return super(UserRolesView, self).form_valid(form)
src/django_rbac/managers.py
78 78
        return self.by_target_ct(target).filter(target_id=target.pk)
79 79

  
80 80
    def for_user(self, user):
81
        '''Retrieve all permissions hold by an user through its role and
81
        '''Retrieve all permissions held by a user through its role and
82 82
           inherited roles.
83 83
        '''
84 84
        Role = utils.get_role_model()
85 85
        roles = Role.objects.for_user(user=user)
86
        return self.filter(roles=roles)
86
        if user.ou:
87
            roles = (roles | user.ou.automatic_roles.all().distinct())
88
        return self.filter(roles=roles.distinct())
87 89

  
88 90
    def cleanup(self):
89 91
        count = 0
......
103 105

  
104 106
class RoleQuerySet(query.QuerySet):
105 107
    def for_user(self, user):
106
        return self.filter(members=user).parents().distinct()
108
        roles = self.filter(members=user).parents().distinct()
109
        if user.ou:
110
            roles = (roles | user.ou.automatic_roles.all().distinct())
111
        return roles.distinct()
107 112

  
108 113
    def parents(self, include_self=True, annotate=False):
109 114
        qs = self.model.objects.filter(child_relation__child=self)
tests/conftest.py
97 97
                       email='john.doe@example.net', ou=ou2)
98 98

  
99 99

  
100
@pytest.fixture
101
def agent_ou1(db, ou1, role_ou1):
102
    user = create_user(username='john.doe', first_name=u'Jôhn', last_name=u'Dôe',
103
                       email='john.doe@example.net', ou=ou1)
104
    user.roles.add(role_ou1)
105
    return user
106

  
107

  
108
@pytest.fixture
109
def agent_ou2(db, ou2, role_ou2):
110
    user =  create_user(username='john.doe', first_name=u'Jôhn', last_name=u'Dôe',
111
                       email='john.doe@example.net', ou=ou2)
112
    user.roles.add(role_ou2)
113
    return user
114

  
115

  
100 116
@pytest.fixture
101 117
def admin_ou1(db, ou1):
102 118
    user = create_user(username='admin.ou1', first_name=u'Admin', last_name=u'OU1',
tests/test_a2_rbac.py
1 1
import pytest
2 2

  
3 3
from django.contrib.contenttypes.models import ContentType
4
from django_rbac.utils import get_permission_model
4
from django_rbac.utils import get_permission_model, get_role_model
5 5
from django_rbac.models import Operation
6 6
from authentic2.a2_rbac.models import Role, OrganizationalUnit as OU, RoleAttribute
7 7
from authentic2.models import Service
......
180 180
    assert ou_dict['email_is_unique'] == ou.email_is_unique
181 181
    assert ou_dict['default'] == ou.default
182 182
    assert ou_dict['validate_emails'] == ou.validate_emails
183

  
184

  
185
def test_ou_automatic_roles_m2m_changed(db, ou_rando, role_ou1, role_ou2, simple_user):
186
    Role = get_role_model()
187

  
188
    simple_user.ou = ou_rando
189
    simple_user.save()
190

  
191
    assert role_ou1 not in Role.objects.for_user(simple_user)
192
    assert role_ou2 not in Role.objects.for_user(simple_user)
193

  
194
    ou_rando.add_automatic_role(role_ou1)
195
    ou_rando.add_automatic_role(role_ou2)
196

  
197
    assert role_ou1 in Role.objects.for_user(simple_user)
198
    assert role_ou2 in Role.objects.for_user(simple_user)
199

  
200
    ou_rando.delete_automatic_role(role_ou1)
201

  
202
    assert role_ou1 not in Role.objects.for_user(simple_user)
203

  
204
    ou_rando.clear_automatic_roles()
205

  
206
    assert role_ou2 not in Role.objects.for_user(simple_user)
207

  
208
def test_ou_automatic_roles_user_changed(db, user_ou1, user_ou2, role_ou1, role_ou2, ou1, ou2):
209
    Role = get_role_model()
210

  
211
    for auto_role in ou1.automatic_roles.all():
212
        assert auto_role in Role.objects.for_user(user_ou1)
213

  
214
    user_ou1.ou = ou2
215
    user_ou1.save()
216

  
217
    for auto_role in ou2.automatic_roles.all():
218
        assert auto_role in Role.objects.for_user(user_ou1)
219

  
220

  
221
def test_ou_automatic_roles_no_sidefx(db, agent_ou1, role_ou1, ou1):
222
    Role = get_role_model()
223

  
224
    assert role_ou1 in agent_ou1.roles.all()
225

  
226
    ou1.add_automatic_role(role_ou1)
227
    ou1.save()
228
    ou1.delete_automatic_role(role_ou1)
229
    ou1.save()
230

  
231
    assert role_ou1 in agent_ou1.roles.all()
183
-