Skip to content

Commit 0a61e84

Browse files
jerioxjb-sap
authored andcommitted
rework consequence queryset filtering
1 parent 314f81c commit 0a61e84

File tree

3 files changed

+33
-31
lines changed

3 files changed

+33
-31
lines changed

ephios/core/consequences.py

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,14 @@ def consequence_handler_from_slug(slug):
4040

4141
def editable_consequences(user):
4242
handlers = list(installed_consequence_handlers())
43-
# qs = LocalConsequence.objects.all().select_related("user")
44-
# for handler in handlers:
45-
# qs = handler.filter_queryset(qs, user)
46-
qs = AbstractConsequence.objects.all()
47-
return qs.filter(slug__in=map(operator.attrgetter("slug"), handlers)).distinct()
43+
consequence_classes = AbstractConsequence.__subclasses__()
44+
45+
qs = AbstractConsequence.objects.filter(slug__in=map(operator.attrgetter("slug"), handlers)).distinct()
46+
q_obj = Q()
47+
for handler in handlers:
48+
for ConcreteConsequence in consequence_classes:
49+
q_obj = q_obj | ConcreteConsequence.filter_editable_by_user(handler, user)
50+
return qs.filter(q_obj)
4851

4952

5053
def pending_consequences(user):
@@ -81,10 +84,9 @@ def render(cls, consequence):
8184
raise NotImplementedError
8285

8386
@classmethod
84-
def filter_queryset(cls, qs, user: UserProfile):
87+
def filter_editable_by_user(cls, user: UserProfile) -> Q:
8588
"""
86-
Return a filtered that excludes consequences with the slug of this class that the user is not allowed to edit.
87-
Consequences should also be annotated with values needed for rendering.
89+
Return a Q object that include consequences with the slug of this class that the user is allowed to edit.
8890
"""
8991
raise NotImplementedError
9092

@@ -126,15 +128,12 @@ def render(cls, consequence):
126128
)
127129

128130
@classmethod
129-
def filter_queryset(cls, qs, user: UserProfile):
130-
return qs.filter(
131-
~Q(slug=cls.slug)
132-
| Q(
133-
user__groups__in=get_objects_for_user(
131+
def filter_editable_by_user(cls, user: UserProfile):
132+
return Q(slug=cls.slug,
133+
localconsequence__user__groups__in=get_objects_for_user(
134134
user, "decide_workinghours_for_group", klass=Group
135135
)
136136
)
137-
)
138137

139138

140139
class QualificationConsequenceHandler(BaseConsequenceHandler):
@@ -215,25 +214,14 @@ def render(cls, consequence):
215214
return s
216215

217216
@classmethod
218-
def filter_queryset(cls, qs, user: UserProfile):
219-
qs = qs.annotate(
220-
qualification_id=Cast(KeyTransform("qualification_id", "data"), IntegerField()),
221-
event_id=Cast(KeyTransform("event_id", "data"), IntegerField()),
222-
).annotate(
223-
qualification_title=Subquery(
224-
Qualification.objects.filter(id=OuterRef("qualification_id")).values("title")[:1]
225-
),
226-
event_title=Subquery(Event.objects.filter(id=OuterRef("event_id")).values("title")[:1]),
227-
)
228-
229-
return qs.filter(
230-
~Q(slug=cls.slug)
217+
def filter_editable_by_user(cls, user: UserProfile):
218+
return Q(slug=cls.slug) & Q(
231219
# Qualifications can be granted by people who...
232-
| Q( # are responsible for the event the consequence originated from, if applicable
233-
event_id__in=get_objects_for_user(user, perms="change_event", klass=Event),
220+
Q( # are responsible for the event the consequence originated from, if applicable
221+
data__event_id__in=get_objects_for_user(user, perms="change_event", klass=Event),
234222
)
235223
| Q( # can edit the affected user anyway
236-
user__in=get_objects_for_user(
224+
localconsequence__user__in=get_objects_for_user(
237225
user, perms="change_userprofile", klass=get_user_model()
238226
)
239227
)

ephios/core/models/users.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,10 @@ class Meta:
416416
verbose_name = _("Abstract consequence")
417417
verbose_name_plural = _("Abstract consequences")
418418

419+
@classmethod
420+
def filter_editable_by_user(cls, handler, user):
421+
raise NotImplementedError
422+
419423
@property
420424
def handler(self):
421425
from ephios.core import consequences
@@ -491,6 +495,10 @@ class Meta:
491495
verbose_name = _("Local consequence")
492496
verbose_name_plural = _("Local consequences")
493497

498+
@classmethod
499+
def filter_editable_by_user(cls, handler, user):
500+
return handler.filter_editable_by_user(user)
501+
494502
def participant_display_name(self):
495503
return self.user.display_name
496504

ephios/plugins/federation/models.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import json
55
from secrets import token_hex
66

7+
from django.contrib.contenttypes.models import ContentType
78
from django.db import models
9+
from django.db.models import Q
810
from django.urls import reverse
911
from django.utils import timezone
1012
from django.utils.safestring import mark_safe
@@ -172,6 +174,10 @@ class Meta:
172174
verbose_name = _("Federated consequence")
173175
verbose_name_plural = _("Federated consequences")
174176

177+
@classmethod
178+
def filter_editable_by_user(cls, handler, user):
179+
return Q(polymorphic_ctype=ContentType.objects.get_for_model(cls))
180+
175181
def participant_display_name(self):
176182
return f"{self.federated_user.display_name} ({self.federated_user.federated_instance.name})"
177183

@@ -199,7 +205,7 @@ def all_participations(self):
199205
return FederatedParticipation.objects.filter(federated_user=self.federated_user)
200206

201207
def new_consequence(self) -> AbstractConsequence:
202-
return FederatedConsequence()
208+
return FederatedConsequence(federated_user=self.federated_user)
203209

204210
def reverse_signup_action(self, shift):
205211
return reverse(

0 commit comments

Comments
 (0)