From 3a6bbb874e54ee3ecd6894ed00594fac1afde18e Mon Sep 17 00:00:00 2001
From: magicfelix <felix@felix-zauberer.de>
Date: Mon, 3 Feb 2025 08:19:39 +0100
Subject: [PATCH] [DAV] Replace get_dav_objects with get_objects

---
 aleksis/core/mixins.py                   | 59 ++++++++++++------------
 aleksis/core/models.py                   | 40 +---------------
 aleksis/core/util/dav_handler/base.py    |  2 +-
 aleksis/core/util/dav_handler/generic.py |  9 ++--
 aleksis/core/views.py                    | 16 +++----
 5 files changed, 44 insertions(+), 82 deletions(-)

diff --git a/aleksis/core/mixins.py b/aleksis/core/mixins.py
index b37e8e40e..437b962f9 100644
--- a/aleksis/core/mixins.py
+++ b/aleksis/core/mixins.py
@@ -2,7 +2,7 @@
 
 import os
 import warnings
-from collections.abc import Iterable
+from collections.abc import Iterable, Sequence
 from datetime import datetime
 from hashlib import sha256
 from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, Union
@@ -12,7 +12,7 @@ from django.conf import settings
 from django.contrib import messages
 from django.contrib.auth.views import LoginView, RedirectURLMixin
 from django.db import models
-from django.db.models import JSONField, QuerySet
+from django.db.models import JSONField, Q, QuerySet
 from django.db.models.fields import CharField, TextField
 from django.forms.forms import BaseForm
 from django.forms.models import ModelForm, ModelFormMetaclass, fields_for_model
@@ -607,21 +607,6 @@ class DAVResource(RegistryObject):
         for ns, propname in cls.dav_live_props:
             ElementTree.SubElement(prop, f"{{{ns}}}{propname}")
 
-    @classmethod
-    def get_dav_objects(
-        cls, request: HttpRequest, objects: Optional[Iterable | QuerySet] = None
-    ) -> Iterable | QuerySet:
-        if objects is None:
-            return []
-        return objects
-
-    @classmethod
-    def get_dav_objects_by_id(cls, id, request: HttpRequest):  # noqa: A002
-        objects = cls.get_dav_objects(request)
-        if isinstance(objects, QuerySet):
-            return objects.filter(id=id)
-        return list(filter(lambda x: x.id == id, objects))
-
     @classmethod
     def get_dav_absolute_url(cls, reference_object, request: HttpRequest) -> str:
         raise NotImplementedError
@@ -816,13 +801,35 @@ class CalendarEventMixin(DAVResource, RegistryObject, is_registry=True):
     @classmethod
     def get_objects(
         cls,
-        request: Optional[HttpRequest] = None,
-        params: Optional[dict[str, any]] = None,
+        request: HttpRequest | None = None,
+        params: dict[str, any] | None = None,
         start: Optional[datetime] = None,
         end: Optional[datetime] = None,
-    ) -> Iterable:
-        """Return the objects to create the calendar feed for."""
-        raise NotImplementedError
+        start_qs: QuerySet | None = None,
+        additional_filter: Q | None = None,
+        select_related: Sequence | None = None,
+        prefetch_related: Sequence | None = None,
+    ) -> QuerySet:
+        """Return all objects that should be included in the calendar."""
+        start_qs = cls.objects if start_qs is None else start_qs
+        start_qs = start_qs.instance_of(cls)
+        if not start or not end:
+            if additional_filter is not None:
+                qs = start_qs.filter(additional_filter)
+            if select_related is not None:
+                qs = start_qs.select_related(*select_related)
+            if prefetch_related is not None:
+                qs = start_qs.prefetch_related(*prefetch_related)
+        else:
+            qs = cls.objects.with_occurrences(
+                start,
+                end,
+                start_qs=start_qs,
+                additional_filter=additional_filter,
+                select_related=select_related,
+                prefetch_related=prefetch_related,
+            )
+        return qs
 
     @classmethod
     def create_feed(
@@ -955,14 +962,6 @@ class CalendarEventMixin(DAVResource, RegistryObject, is_registry=True):
     def get_dav_verbose_name(cls, request: Optional[HttpRequest] = None) -> str:
         return str(cls.get_verbose_name())
 
-    @classmethod
-    def get_dav_objects(
-        cls, request: HttpRequest, objects: Optional[Iterable | QuerySet] = None
-    ) -> Iterable | QuerySet:
-        if objects is None:
-            objects = cls.get_objects(request)
-        return super().get_dav_objects(request, objects)
-
     @classmethod
     def get_dav_file_content(
         cls,
diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index d6d1b1041..b05625a83 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -483,12 +483,6 @@ class Person(ContactMixin, ExtensibleModel):
             )
         return qs.filter(additional_filter) if additional_filter else qs
 
-    @classmethod
-    def get_dav_objects(
-        cls, request: HttpRequest, objects: Optional[QuerySet] = None
-    ) -> Iterable | QuerySet:
-        return [person for person in cls.get_objects(request=request, start_qs=objects)]
-
     @classmethod
     def get_dav_file_content(
         cls,
@@ -497,7 +491,7 @@ class Person(ContactMixin, ExtensibleModel):
         params: Optional[dict[str, any]] = None,
     ) -> str:
         if objects is None:
-            objects = cls.get_dav_objects(request)
+            objects = cls.get_objects(request)
         content = ""
         for person in objects:
             content += person.as_vcard(request, params)
@@ -1766,38 +1760,6 @@ class CalendarEvent(
             calendar_alarm.get_alarm(request) for calendar_alarm in reference_object.alarms.all()
         ]
 
-    @classmethod
-    def get_objects(
-        cls,
-        request: HttpRequest | None = None,
-        params: dict[str, any] | None = None,
-        start: Optional[datetime] = None,
-        end: Optional[datetime] = None,
-        start_qs: QuerySet | None = None,
-        additional_filter: Q | None = None,
-        select_related: Sequence | None = None,
-        prefetch_related: Sequence | None = None,
-    ) -> QuerySet:
-        """Return all objects that should be included in the calendar."""
-        start_qs = cls.objects if start_qs is None else start_qs
-        start_qs = start_qs.instance_of(cls)
-        if not start or not end:
-            start = timezone.now() - timedelta(days=50)
-            end = timezone.now() + timedelta(days=50)
-        qs = cls.objects.with_occurrences(
-            start,
-            end,
-            start_qs=start_qs,
-            additional_filter=additional_filter,
-            select_related=select_related,
-            prefetch_related=prefetch_related,
-        )
-        return qs
-
-    @classmethod
-    def get_dav_objects_by_id(cls, id, request):  # noqa: A002
-        return cls.get_objects(request).filter(Q(id=id) | Q(amends__pk=id))
-
     def save(self, *args, **kwargs):
         if (
             self.datetime_start
diff --git a/aleksis/core/util/dav_handler/base.py b/aleksis/core/util/dav_handler/base.py
index 87d8ee491..5d97e4c05 100644
--- a/aleksis/core/util/dav_handler/base.py
+++ b/aleksis/core/util/dav_handler/base.py
@@ -150,7 +150,7 @@ class DAVRequest(ElementHandler, ContentHandler):
                         lambda r: not getattr(r, "_is_registry", False), self.resources
                     ):
                         try:
-                            objs = resource.get_dav_objects(self._request)
+                            objs = resource.get_objects(self._request)
                         except NotImplementedError:
                             objs = []
 
diff --git a/aleksis/core/util/dav_handler/generic.py b/aleksis/core/util/dav_handler/generic.py
index d47ddbf0c..1f57d0b67 100644
--- a/aleksis/core/util/dav_handler/generic.py
+++ b/aleksis/core/util/dav_handler/generic.py
@@ -120,10 +120,11 @@ class DAVHref(ElementHandler):
         pk = res.kwargs.get("id")
 
         resource = DAVResource.registered_objects_dict[name]
-        objs = resource.get_dav_objects_by_id(pk, self.request._request)
-        if len(objs) == 0:
-            objs = [NotFoundObject(self.content)]
-        self.request.objects += objs
+        try:
+            obj = resource.get_objects(self.request._request).get(pk=pk)
+        except resource.DoesNotExist:
+            obj = NotFoundObject(self.content)
+        self.request.objects = list(self.request.objects).append(obj)
 
 
 class DAVProp(ElementHandler):
diff --git a/aleksis/core/views.py b/aleksis/core/views.py
index 9cd1719d0..908c12a51 100644
--- a/aleksis/core/views.py
+++ b/aleksis/core/views.py
@@ -1485,10 +1485,10 @@ class DAVSingleResourceView(DAVResourceView):
 
     def propfind(self, request, id, *args, **kwargs):  # noqa: A002
         resource = self.get_object()
-        objects = resource.get_dav_objects_by_id(id, request)
-
-        if len(objects) == 0:
-            raise Http404
+        try:
+            objects = resource.get_objects(request).get(pk=id)
+        except resource.DoesNotExist as exc:
+            raise Http404 from exc
 
         self._dav_request = DAVRequest(request, resource, objects[0])
 
@@ -1507,10 +1507,10 @@ class DAVSingleResourceView(DAVResourceView):
 
     def get(self, request, name, id, *args, **kwargs):  # noqa: A002
         resource: DAVResource = self.get_object()
-        objects = resource.get_dav_objects_by_id(id, request)
-
-        if len(objects) == 0:
-            raise Http404
+        try:
+            objects = resource.get_objects(request).get(pk=id)
+        except resource.DoesNotExist as exc:
+            raise Http404 from exc
 
         response = HttpResponse(content_type=resource.get_dav_content_type())
         response.write(resource.get_dav_file_content(request, objects=objects))
-- 
GitLab