0001-a2_rbac-do-not-break-unicity-when-get-or-creating-ad.patch
src/authentic2/a2_rbac/management.py | ||
---|---|---|
20 | 20 |
from django.contrib.contenttypes.models import ContentType |
21 | 21 | |
22 | 22 |
from django_rbac.models import ADMIN_OP |
23 |
from django_rbac.utils import get_role_model, get_ou_model |
|
23 |
from django_rbac.utils import get_ou_model |
|
24 |
from django_rbac.utils import get_permission_model |
|
25 |
from django_rbac.utils import get_role_model |
|
24 | 26 | |
25 | 27 |
from ..utils import get_fk_model |
26 | 28 |
from . import utils, app_settings |
... | ... | |
138 | 140 |
continue |
139 | 141 |
ct_admin_role = Role.objects.get_admin_role(instance=ct, name=name, |
140 | 142 |
slug=slug, |
141 |
update_name=True) |
|
143 |
update_name=True, |
|
144 |
update_slug=True, |
|
145 |
create=True) |
|
142 | 146 |
if MANAGED_CT[ct_tuple].get('must_view_user'): |
143 | 147 |
ct_admin_role.permissions.add(view_user_perm) |
144 | 148 |
ct_admin_role.permissions.add(search_ou_perm) |
... | ... | |
146 | 150 | |
147 | 151 | |
148 | 152 |
def update_user_admin_roles_permission(): |
149 |
roles = get_role_model().objects.filter(slug__startswith='_a2-managers-of-role',
|
|
150 |
permissions__operation__slug=ADMIN_OP.slug)
|
|
151 |
for role in roles:
|
|
152 |
old_perm = role.permissions.get(operation__slug=ADMIN_OP.slug)
|
|
153 |
administered_role = old_perm.target
|
|
153 |
role_ct = ContentType.objects.get_for_model(get_role_model())
|
|
154 |
permissions = get_permission_model().objects.filter(target_ct=role_ct,
|
|
155 |
operation__slug=ADMIN_OP.slug)
|
|
156 |
for perm in permissions:
|
|
157 |
administered_role = perm.target |
|
154 | 158 |
admin_role = administered_role.get_admin_role() |
155 |
new_perm = admin_role.permissions.get(operation__slug=MANAGE_MEMBERS_OP.slug) |
|
159 |
assert admin_role.slug.startswith('_a2-managers-of-role') |
|
160 |
new_perm = admin_role.permissions.get( |
|
161 |
operation__slug=MANAGE_MEMBERS_OP.slug) |
|
162 |
assert new_perm.ou is None |
|
163 | ||
156 | 164 |
admin_role.delete() |
165 |
assert len(perm.roles.all()) == 1 |
|
166 |
role = perm.roles.first() |
|
157 | 167 |
role.admin_scope_id = new_perm.pk |
158 |
role.save() |
|
159 |
role.permissions.remove(old_perm)
|
|
168 |
role.save(update_fields=['admin_scope_id'])
|
|
169 |
role.permissions.remove(perm) |
|
160 | 170 |
role.permissions.add(new_perm) |
161 |
assert role.pk == administered_role.get_admin_role().pk |
|
171 |
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 |
- |