0001-support-organizational-unit-automatic-roles-20690.patch
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 |
- |