From 0013da3e12ce61f558f05303b2e4c0773637f9c4 Mon Sep 17 00:00:00 2001
From: Dominik George <dominik.george@teckids.org>
Date: Fri, 1 May 2020 13:19:54 +0200
Subject: [PATCH] Add middleware to inject a dummy person into a superuser that
 does not have one

---
 aleksis/core/models.py           | 14 ++++++++++++++
 aleksis/core/settings.py         |  1 +
 aleksis/core/util/middlewares.py | 33 ++++++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+)
 create mode 100644 aleksis/core/util/middlewares.py

diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index 109db7158..d076019ea 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -246,6 +246,20 @@ class Person(ExtensibleModel):
                 self.primary_group = self.member_of.filter(name__regex=pattern).first()
 
 
+class DummyPerson(Person):
+    """ A dummy person that is not stored into the database.
+
+    Used to temporarily inject a Person object into a User.
+    """
+
+    class Meta:
+        managed = False
+        proxy = True
+
+    def save(self, *args, **kwargs):
+        pass
+        
+
 class Group(ExtensibleModel):
     """Any kind of group of persons in a school, including, but not limited
     classes, clubs, and the like.
diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py
index 6fd8e1495..9d8cf2acf 100644
--- a/aleksis/core/settings.py
+++ b/aleksis/core/settings.py
@@ -117,6 +117,7 @@ MIDDLEWARE = [
     "django.middleware.common.CommonMiddleware",
     "django.middleware.csrf.CsrfViewMiddleware",
     "django.contrib.auth.middleware.AuthenticationMiddleware",
+    "aleksis.core.util.middlewares.EnsurePersonMiddleware",
     "debug_toolbar.middleware.DebugToolbarMiddleware",
     "django_otp.middleware.OTPMiddleware",
     "impersonate.middleware.ImpersonateMiddleware",
diff --git a/aleksis/core/util/middlewares.py b/aleksis/core/util/middlewares.py
new file mode 100644
index 000000000..49d5c2e3e
--- /dev/null
+++ b/aleksis/core/util/middlewares.py
@@ -0,0 +1,33 @@
+from typing import Callable
+
+from django.core.exceptions import PermissionDenied
+from django.http import HttpRequest, HttpResponse
+from django.util.translation import gettext_lazy as _
+
+from .core_helpers import has_person
+from .messages import warning
+from ..models import DummyPerson
+
+
+class EnsurePersonMiddleware:
+    """ Middleware that ensures that the logged-in user is linked to a person.
+
+    It is needed to inject a dummy person to a superuser that would otherwise
+    not have an associated person, in order they can get their account set up
+    without external help.
+    """
+
+    def __init__(self, get_response: Callable):
+        self.get_response = get_response
+
+    def __call__(self, request: HttpRequest) -> HttpResponse:
+        if not has_person(request):
+            if request.user.is_superuser:
+                # Super-users get a dummy person linked
+                dummy_person = DummyPerson(first_name=request.user.first_name, last_name=request.user.last_name)
+                request.user.person = dummy_person
+
+                warning(request, _("A dummy user has been linked to your user account."))
+
+        response = self.get_response(request)
+        return response
-- 
GitLab