0008-apply-soft-deletion-logic-when-retrieving-roleparent.patch
src/authentic2/custom_user/models.py | ||
---|---|---|
219 | 219 | |
220 | 220 |
def roles_and_parents(self): |
221 | 221 |
qs1 = self.roles.all() |
222 |
qs2 = qs1.model.objects.filter(child_relation__child__in=qs1) |
|
222 |
qs2 = qs1.model.objects.filter( |
|
223 |
child_relation__deleted__isnull=True, |
|
224 |
child_relation__child__in=qs1, |
|
225 |
) |
|
223 | 226 |
qs = (qs1 | qs2).order_by('name').distinct() |
224 | 227 |
RoleParenting = get_role_parenting_model() |
225 |
rp_qs = RoleParenting.objects.filter(child__in=qs1) |
|
228 |
rp_qs = RoleParenting.active_objects.filter(child__in=qs1)
|
|
226 | 229 |
qs = qs.prefetch_related(models.Prefetch('child_relation', queryset=rp_qs), 'child_relation__parent') |
227 | 230 |
qs = qs.prefetch_related( |
228 | 231 |
models.Prefetch('members', queryset=self.__class__.objects.filter(pk=self.pk), to_attr='member') |
src/authentic2/management/commands/check-and-repair.py | ||
---|---|---|
388 | 388 |
direct_members = manager_role.members.all() |
389 | 389 |
direct_members_count = direct_members.count() |
390 | 390 |
direct_children = Role.objects.filter( |
391 |
parent_relation__parent=manager_role, parent_relation__direct=True |
|
391 |
parent_relation__deleted__isnull=True, |
|
392 |
parent_relation__parent=manager_role, |
|
393 |
parent_relation__direct=True, |
|
392 | 394 |
) |
393 | 395 |
direct_children_count = direct_children.count() |
394 | 396 |
show = members_count or self.verbosity > 1 |
src/authentic2/manager/resources.py | ||
---|---|---|
40 | 40 |
for role in instance.roles.all(): |
41 | 41 |
result.add(role) |
42 | 42 |
for pr in role.parent_relation.all(): |
43 |
result.add(pr.parent) |
|
43 |
if pr.deleted is None: |
|
44 |
result.add(pr.parent) |
|
44 | 45 |
return ', '.join(str(x) for x in result) |
45 | 46 | |
46 | 47 |
class Meta: |
src/authentic2/manager/role_views.py | ||
---|---|---|
396 | 396 |
) |
397 | 397 |
) |
398 | 398 |
RoleParenting = get_role_parenting_model() |
399 |
rp_qs = RoleParenting.objects.filter(parent__in=children).annotate(name=F('parent__name')) |
|
399 |
rp_qs = RoleParenting.active_objects.filter(parent__in=children).annotate(name=F('parent__name'))
|
|
400 | 400 |
qs = qs.prefetch_related(Prefetch('parent_relation', queryset=rp_qs, to_attr='via')) |
401 | 401 |
return qs |
402 | 402 | |
... | ... | |
461 | 461 |
) |
462 | 462 |
) |
463 | 463 |
RoleParenting = get_role_parenting_model() |
464 |
rp_qs = RoleParenting.objects.filter(child__in=parents).annotate(name=F('child__name')) |
|
464 |
rp_qs = RoleParenting.active_objects.filter(child__in=parents).annotate(name=F('child__name'))
|
|
465 | 465 |
qs = qs.prefetch_related(Prefetch('child_relation', queryset=rp_qs, to_attr='via')) |
466 | 466 |
return qs |
467 | 467 |
src/authentic2/manager/tables.py | ||
---|---|---|
182 | 182 |
) |
183 | 183 |
ou = tables.Column() |
184 | 184 |
via = tables.TemplateColumn( |
185 |
'{% if not record.member %}{% for rel in record.child_relation.all %}{{ rel.child }} {% if not'
|
|
186 |
' forloop.last %}, {% endif %}{% endfor %}{% endif %}',
|
|
185 |
'{% if not record.member %}{% for rel in record.child_relation.all %}{% if not rel.deleted %}'
|
|
186 |
'{{ rel.child }} {% if not forloop.last %}, {% endif %}{% endif %}{% endfor %}{% endif %}',
|
|
187 | 187 |
verbose_name=_('Inherited from'), |
188 | 188 |
orderable=False, |
189 | 189 |
) |
src/authentic2/manager/user_views.py | ||
---|---|---|
643 | 643 |
User = get_user_model() |
644 | 644 |
Role = get_role_model() |
645 | 645 |
RoleParenting = get_role_parenting_model() |
646 |
rp_qs = RoleParenting.objects.filter(child__in=roles) |
|
646 |
rp_qs = RoleParenting.active_objects.filter(child__in=roles)
|
|
647 | 647 |
qs = Role.objects.all() |
648 | 648 |
qs = qs.prefetch_related(models.Prefetch('child_relation', queryset=rp_qs, to_attr='via')) |
649 | 649 |
qs = qs.prefetch_related( |
src/django_rbac/managers.py | ||
---|---|---|
109 | 109 |
return self.filter(members=user).parents().distinct() |
110 | 110 | |
111 | 111 |
def parents(self, include_self=True, annotate=False): |
112 |
qs = self.model.objects.filter(child_relation__child__in=self) |
|
112 |
qs = self.model.objects.filter( |
|
113 |
child_relation__deleted__isnull=True, |
|
114 |
child_relation__child__in=self, |
|
115 |
) |
|
113 | 116 |
if include_self: |
114 | 117 |
qs = self | qs |
115 | 118 |
qs = qs.distinct() |
... | ... | |
118 | 121 |
return qs |
119 | 122 | |
120 | 123 |
def children(self, include_self=True, annotate=False): |
121 |
qs = self.model.objects.filter(parent_relation__parent__in=self) |
|
124 |
qs = self.model.objects.filter( |
|
125 |
parent_relation__deleted__isnull=True, |
|
126 |
parent_relation__parent__in=self, |
|
127 |
) |
|
122 | 128 |
if include_self: |
123 | 129 |
qs = self | qs |
124 | 130 |
qs = qs.distinct() |
... | ... | |
130 | 136 |
User = get_user_model() |
131 | 137 |
prefetch = Prefetch('roles', queryset=self, to_attr='direct') |
132 | 138 |
return ( |
133 |
User.objects.filter(Q(roles__in=self) | Q(roles__parent_relation__parent__in=self)) |
|
139 |
User.objects.filter( |
|
140 |
Q(roles__in=self) |
|
141 |
| ( |
|
142 |
Q(roles__parent_relation__parent__in=self) |
|
143 |
& Q(roles__parent_relation__deleted__isnull=True) |
|
144 |
) |
|
145 |
) |
|
134 | 146 |
.distinct() |
135 | 147 |
.prefetch_related(prefetch) |
136 | 148 |
) |
src/django_rbac/models.py | ||
---|---|---|
217 | 217 |
def all_members(self): |
218 | 218 |
User = get_user_model() |
219 | 219 |
prefetch = Prefetch('roles', queryset=self.__class__.objects.filter(pk=self.pk), to_attr='direct') |
220 | ||
220 | 221 |
return ( |
221 |
User.objects.filter(Q(roles=self) | Q(roles__parent_relation__parent=self)) |
|
222 |
User.objects.filter( |
|
223 |
Q(roles=self) |
|
224 |
| Q(roles__parent_relation__parent=self) & Q(roles__parent_relation__deleted__isnull=True) |
|
225 |
) |
|
222 | 226 |
.distinct() |
223 | 227 |
.prefetch_related(prefetch) |
224 | 228 |
) |
tests_rbac/test_rbac.py | ||
---|---|---|
66 | 66 |
assert role.parents().count() == i + 1 |
67 | 67 |
assert role.children(False).count() == 6 - i - 1 |
68 | 68 |
assert role.parents(False).count() == i |
69 |
RoleParenting.objects.filter(parent=roles[2], child=roles[3], direct=True).delete() |
|
70 |
assert RoleParenting.objects.filter(direct=True).count() == 4 |
|
71 |
assert RoleParenting.objects.filter(direct=False).count() == 2 |
|
69 |
RoleParenting.objects.soft_delete(roles[2], roles[3], direct=True) |
|
70 |
assert ( |
|
71 |
RoleParenting.active_objects.filter( |
|
72 |
direct=True, |
|
73 |
).count() |
|
74 |
== 4 |
|
75 |
) |
|
76 |
assert ( |
|
77 |
RoleParenting.active_objects.filter( |
|
78 |
direct=False, |
|
79 |
).count() |
|
80 |
== 2 |
|
81 |
) |
|
72 | 82 |
# test that it works with cycles |
73 | 83 |
RoleParenting.objects.create(parent=roles[2], child=roles[3]) |
74 | 84 |
RoleParenting.objects.create(parent=roles[5], child=roles[0]) |
... | ... | |
77 | 87 |
assert role.parents().count() == 6 |
78 | 88 | |
79 | 89 | |
90 |
def test_role_parenting_soft_delete_children(db): |
|
91 |
OrganizationalUnit = utils.get_ou_model() |
|
92 |
Role = utils.get_role_model() |
|
93 |
RoleParenting = utils.get_role_parenting_model() |
|
94 | ||
95 |
ou = OrganizationalUnit.objects.create(name='ou') |
|
96 |
roles = [] |
|
97 |
for i in range(10): |
|
98 |
roles.append(Role.objects.create(name='r%d' % i, ou=ou)) |
|
99 |
assert not len(RoleParenting.objects.all()) |
|
100 | ||
101 |
rps = [] |
|
102 |
for i in range(5): |
|
103 |
rps.append(RoleParenting.objects.create(parent=roles[9 - i], child=roles[i])) |
|
104 |
assert len(RoleParenting.objects.all()) == 5 |
|
105 |
for i in range(5): |
|
106 |
roles[9 - i].remove_child(roles[i]) |
|
107 |
assert len(RoleParenting.objects.all()) == 5 |
|
108 |
assert len(RoleParenting.active_objects.all()) == 4 - i |
|
109 |
for i in range(5): |
|
110 |
roles[9 - i].add_child(roles[i]) |
|
111 |
assert len(RoleParenting.objects.all()) == 5 |
|
112 |
assert len(RoleParenting.active_objects.all()) == i + 1 |
|
113 | ||
114 | ||
115 |
def test_role_parenting_soft_delete_parents(db): |
|
116 |
OrganizationalUnit = utils.get_ou_model() |
|
117 |
Role = utils.get_role_model() |
|
118 |
RoleParenting = utils.get_role_parenting_model() |
|
119 | ||
120 |
ou = OrganizationalUnit.objects.create(name='ou') |
|
121 |
roles = [] |
|
122 |
for i in range(10): |
|
123 |
roles.append(Role.objects.create(name='r%d' % i, ou=ou)) |
|
124 |
assert not len(RoleParenting.objects.all()) |
|
125 | ||
126 |
rps = [] |
|
127 |
for i in range(5): |
|
128 |
rps.append(RoleParenting.objects.create(child=roles[9 - i], parent=roles[i])) |
|
129 |
assert len(RoleParenting.objects.all()) == 5 |
|
130 |
for i in range(5): |
|
131 |
roles[9 - i].remove_parent(roles[i]) |
|
132 |
assert len(RoleParenting.objects.all()) == 5 |
|
133 |
assert len(RoleParenting.active_objects.all()) == 4 - i |
|
134 |
for i in range(5): |
|
135 |
roles[9 - i].add_parent(roles[i]) |
|
136 |
assert len(RoleParenting.objects.all()) == 5 |
|
137 |
assert len(RoleParenting.active_objects.all()) == i + 1 |
|
138 | ||
139 | ||
80 | 140 |
SIZE = 1000 |
81 | 141 |
SPAN = 50 |
82 | 142 | |
83 |
- |