Projet

Général

Profil

0001-a2_rbac-do-not-break-unicity-when-get-or-creating-ad.patch

Paul Marillonnet, 09 juin 2020 10:17

Télécharger (7,03 ko)

Voir les différences:

Subject: [PATCH] a2_rbac: do not break unicity when get-or-creating admin role
 (#42178)

 src/authentic2/a2_rbac/management.py |  9 +++++---
 src/authentic2/a2_rbac/managers.py   | 34 +++++++++++++---------------
 src/authentic2/a2_rbac/models.py     |  2 +-
 tests/test_a2_rbac.py                |  6 ++---
 4 files changed, 26 insertions(+), 25 deletions(-)
src/authentic2/a2_rbac/management.py
138 138
            continue
139 139
        ct_admin_role = Role.objects.get_admin_role(instance=ct, name=name,
140 140
                                                    slug=slug,
141
                                                    update_name=True)
141
                                                    update_name=True,
142
                                                    update_slug=True,
143
                                                    create=True)
142 144
        if MANAGED_CT[ct_tuple].get('must_view_user'):
143 145
            ct_admin_role.permissions.add(view_user_perm)
144 146
        ct_admin_role.permissions.add(search_ou_perm)
......
153 155
        administered_role = old_perm.target
154 156
        admin_role = administered_role.get_admin_role()
155 157
        new_perm = admin_role.permissions.get(operation__slug=MANAGE_MEMBERS_OP.slug)
158
        assert new_perm.ou is None
156 159
        admin_role.delete()
157 160
        role.admin_scope_id = new_perm.pk
158
        role.save()
161
        role.save(update_fields=['admin_scope_id'])
159 162
        role.permissions.remove(old_perm)
160 163
        role.permissions.add(new_perm)
161
        assert role.pk == administered_role.get_admin_role().pk
164
        assert role.pk == administered_role.get_admin_role(create=False).pk
src/authentic2/a2_rbac/managers.py
41 41
        op = get_operation(operation)
42 42
        Permission = rbac_utils.get_permission_model()
43 43
        if create:
44
            perm, created = Permission.objects.get_or_create(
44
            perm, _ = Permission.objects.get_or_create(
45 45
                operation=op,
46 46
                target_ct=ContentType.objects.get_for_model(instance),
47 47
                target_id=instance.pk,
......
55 55
                    **kwargs)
56 56
            except Permission.DoesNotExist:
57 57
                return None
58
            created = False
59 58

  
60 59
        admin_role = self.get_mirror_role(perm, name, slug, ou=ou,
61 60
                                          update_name=update_name,
......
76 75

  
77 76
    def get_mirror_role(self, instance, name, slug, ou=None,
78 77
                        update_name=False, update_slug=False, create=True):
79
        '''Get or create a role which mirror another model, for example a
78
        '''Get or create a role which mirrors another model, for example a
80 79
           permission.
81 80
        '''
82 81
        ct = ContentType.objects.get_for_model(instance)
82
        update_fields = {}
83 83
        kwargs = {}
84
        if ou or getattr(instance, 'ou', None):
85
            kwargs['ou'] = ou or instance.ou
84
        ou = ou or getattr(instance, 'ou', None)
85
        if ou:
86
            update_fields['ou'] = ou
86 87
        else:
87 88
            kwargs['ou__isnull'] = True
89
        if update_name:
90
            update_fields['name'] = name
91
        if update_slug:
92
            update_fields['slug'] = slug
93

  
88 94
        if create:
89
            role, created = self.prefetch_related('permissions').get_or_create(
95
            role, _ = self.prefetch_related('permissions').update_or_create(
90 96
                admin_scope_ct=ct,
91 97
                admin_scope_id=instance.pk,
92
                defaults={
93
                    'name': name,
94
                    'slug': slug,
95
                },
98
                defaults=update_fields,
96 99
                **kwargs)
97 100
        else:
98 101
            try:
......
102 105
                    **kwargs)
103 106
            except self.model.DoesNotExist:
104 107
                return None
105
            created = False
106

  
107
        if update_name and not created and role.name != name:
108
            role.name = name
109
            role.save()
110
        if update_slug and not created and role.slug != slug:
111
            role.slug = slug
112
            role.save()
108
            for field, value in update_fields.items():
109
                setattr(role, field, value)
110
            role.save(update_fields=update_fields)
113 111
        return role
114 112

  
115 113
    def get_by_natural_key(self, slug, ou_natural_key, service_natural_key):
src/authentic2/a2_rbac/models.py
151 151
        slug = '_a2-managers-of-{ou.slug}'.format(ou=self)
152 152
        return Role.objects.get_admin_role(
153 153
            instance=self, name=name, slug=slug, operation=VIEW_OP,
154
            update_name=True, update_slug=True)
154
            update_name=True, update_slug=True, create=True)
155 155

  
156 156
    def delete(self, *args, **kwargs):
157 157
        Permission.objects.filter(ou=self).delete()
tests/test_a2_rbac.py
108 108
    user = User.objects.create(username='john.doe')
109 109
    name1 = 'Can manage john.doe'
110 110
    slug1 = 'can-manage-john-doe'
111
    admin_role1 = Role.objects.get_admin_role(user, name1, slug1)
111
    admin_role1 = Role.objects.get_admin_role(user, name1, slug1, update_name=True, update_slug=True)
112 112
    assert admin_role1.name == name1
113 113
    assert admin_role1.slug == slug1
114 114
    name2 = 'Should manage john.doe'
......
403 403
    assert ar1.slug == '_a2-managers-of-role-r1ter'
404 404

  
405 405

  
406
def test_admin_role_user_view(settings, app, admin, simple_user, ou1, user_ou1, role_ou1):
406
def test_admin_role_user_view(db, settings, app, admin, simple_user, ou1, user_ou1, role_ou1):
407 407
    role_ou1.get_admin_role().members.add(simple_user)
408 408

  
409 409
    # Default: all users are visible
......
493 493
@pytest.mark.parametrize(
494 494
    'alert,deletion', [(-1, 31), (31, -1), (0, 31), (31, 0), (None, 31), (31, None), (32, 31)]
495 495
)
496
def test_unused_account_settings_validation(ou1, alert, deletion):
496
def test_unused_account_settings_validation(db, ou1, alert, deletion):
497 497
    ou1.clean_unused_accounts_alert = alert
498 498
    ou1.clean_unused_accounts_deletion = deletion
499 499
    with pytest.raises(ValidationError):
500
-