We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
User write stages do not trigger a Model Updated event when writing to an existing user
**Describe the bug**
User write stages do not trigger a "Model updated" event when the user is existing if the stage is after an email stage with "activate pending user on success".

**To Reproduce**
Steps to reproduce the behavior:
1. Create a new enrollment flow
2. Add a prompt stage to enter username email and name
3. Do a user write, make sure it always creates a new user and store the user as inactive
4. Add an email stage, and enable "Activate pending user on success"
5. Add a prompt stage to set the password
6. Do another user write, make sure it never creates a user
7. Do a log in

During this process there is no Model Updated event sent in the second user write.
However, when you remove the email stage, it will trigger this event.
It also triggers the correct event in the user-write on a user settings flow for example, so it seems to be related to the activation stage.

**Expected behavior**
A user write should trigger a Model Updated event when modifying an existing user, as it also triggers a Model Created event when a new user is written to.

**Version and Deployment (please complete the following information):**
 - authentik version: 2023.1.2


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `authentik/events/middleware.py`
Content:
```
1 """Events middleware"""
2 from functools import partial
3 from threading import Thread
4 from typing import Any, Callable, Optional
5 
6 from django.conf import settings
7 from django.contrib.sessions.models import Session
8 from django.core.exceptions import SuspiciousOperation
9 from django.db.models import Model
10 from django.db.models.signals import m2m_changed, post_save, pre_delete
11 from django.http import HttpRequest, HttpResponse
12 from guardian.models import UserObjectPermission
13 
14 from authentik.core.models import (
15     AuthenticatedSession,
16     Group,
17     PropertyMapping,
18     Provider,
19     Source,
20     User,
21     UserSourceConnection,
22 )
23 from authentik.events.models import Event, EventAction, Notification
24 from authentik.events.utils import model_to_dict
25 from authentik.flows.models import FlowToken, Stage
26 from authentik.lib.sentry import before_send
27 from authentik.lib.utils.errors import exception_to_string
28 from authentik.outposts.models import OutpostServiceConnection
29 from authentik.policies.models import Policy, PolicyBindingModel
30 from authentik.providers.oauth2.models import AccessToken, AuthorizationCode, RefreshToken
31 from authentik.providers.scim.models import SCIMGroup, SCIMUser
32 from authentik.stages.authenticator_static.models import StaticToken
33 
34 IGNORED_MODELS = (
35     Event,
36     Notification,
37     UserObjectPermission,
38     AuthenticatedSession,
39     StaticToken,
40     Session,
41     FlowToken,
42     Provider,
43     Source,
44     PropertyMapping,
45     UserSourceConnection,
46     Stage,
47     OutpostServiceConnection,
48     Policy,
49     PolicyBindingModel,
50     AuthorizationCode,
51     AccessToken,
52     RefreshToken,
53     SCIMUser,
54     SCIMGroup,
55 )
56 
57 
58 def should_log_model(model: Model) -> bool:
59     """Return true if operation on `model` should be logged"""
60     if model.__module__.startswith("silk"):
61         return False
62     return model.__class__ not in IGNORED_MODELS
63 
64 
65 def should_log_m2m(model: Model) -> bool:
66     """Return true if m2m operation should be logged"""
67     if model.__class__ in [User, Group]:
68         return True
69     return False
70 
71 
72 class EventNewThread(Thread):
73     """Create Event in background thread"""
74 
75     action: str
76     request: HttpRequest
77     kwargs: dict[str, Any]
78     user: Optional[User] = None
79 
80     def __init__(self, action: str, request: HttpRequest, user: Optional[User] = None, **kwargs):
81         super().__init__()
82         self.action = action
83         self.request = request
84         self.user = user
85         self.kwargs = kwargs
86 
87     def run(self):
88         Event.new(self.action, **self.kwargs).from_http(self.request, user=self.user)
89 
90 
91 class AuditMiddleware:
92     """Register handlers for duration of request-response that log creation/update/deletion
93     of models"""
94 
95     get_response: Callable[[HttpRequest], HttpResponse]
96 
97     def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]):
98         self.get_response = get_response
99 
100     def connect(self, request: HttpRequest):
101         """Connect signal for automatic logging"""
102         if not hasattr(request, "user"):
103             return
104         if not getattr(request.user, "is_authenticated", False):
105             return
106         if not hasattr(request, "request_id"):
107             return
108         post_save_handler = partial(self.post_save_handler, user=request.user, request=request)
109         pre_delete_handler = partial(self.pre_delete_handler, user=request.user, request=request)
110         m2m_changed_handler = partial(self.m2m_changed_handler, user=request.user, request=request)
111         post_save.connect(
112             post_save_handler,
113             dispatch_uid=request.request_id,
114             weak=False,
115         )
116         pre_delete.connect(
117             pre_delete_handler,
118             dispatch_uid=request.request_id,
119             weak=False,
120         )
121         m2m_changed.connect(
122             m2m_changed_handler,
123             dispatch_uid=request.request_id,
124             weak=False,
125         )
126 
127     def disconnect(self, request: HttpRequest):
128         """Disconnect signals"""
129         if not hasattr(request, "request_id"):
130             return
131         post_save.disconnect(dispatch_uid=request.request_id)
132         pre_delete.disconnect(dispatch_uid=request.request_id)
133         m2m_changed.disconnect(dispatch_uid=request.request_id)
134 
135     def __call__(self, request: HttpRequest) -> HttpResponse:
136         self.connect(request)
137 
138         response = self.get_response(request)
139 
140         self.disconnect(request)
141         return response
142 
143     def process_exception(self, request: HttpRequest, exception: Exception):
144         """Disconnect handlers in case of exception"""
145         self.disconnect(request)
146 
147         if settings.DEBUG:
148             return
149         # Special case for SuspiciousOperation, we have a special event action for that
150         if isinstance(exception, SuspiciousOperation):
151             thread = EventNewThread(
152                 EventAction.SUSPICIOUS_REQUEST,
153                 request,
154                 message=str(exception),
155             )
156             thread.run()
157         elif before_send({}, {"exc_info": (None, exception, None)}) is not None:
158             thread = EventNewThread(
159                 EventAction.SYSTEM_EXCEPTION,
160                 request,
161                 message=exception_to_string(exception),
162             )
163             thread.run()
164 
165     @staticmethod
166     def post_save_handler(
167         user: User, request: HttpRequest, sender, instance: Model, created: bool, **_
168     ):
169         """Signal handler for all object's post_save"""
170         if not should_log_model(instance):
171             return
172 
173         action = EventAction.MODEL_CREATED if created else EventAction.MODEL_UPDATED
174         EventNewThread(action, request, user=user, model=model_to_dict(instance)).run()
175 
176     @staticmethod
177     def pre_delete_handler(user: User, request: HttpRequest, sender, instance: Model, **_):
178         """Signal handler for all object's pre_delete"""
179         if not should_log_model(instance):  # pragma: no cover
180             return
181 
182         EventNewThread(
183             EventAction.MODEL_DELETED,
184             request,
185             user=user,
186             model=model_to_dict(instance),
187         ).run()
188 
189     @staticmethod
190     def m2m_changed_handler(
191         user: User, request: HttpRequest, sender, instance: Model, action: str, **_
192     ):
193         """Signal handler for all object's m2m_changed"""
194         if action not in ["pre_add", "pre_remove", "post_clear"]:
195             return
196         if not should_log_m2m(instance):
197             return
198 
199         EventNewThread(
200             EventAction.MODEL_UPDATED,
201             request,
202             user=user,
203             model=model_to_dict(instance),
204         ).run()
205
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/authentik/events/middleware.py b/authentik/events/middleware.py
--- a/authentik/events/middleware.py
+++ b/authentik/events/middleware.py
@@ -93,21 +93,30 @@
     of models"""
 
     get_response: Callable[[HttpRequest], HttpResponse]
+    anonymous_user: User = None
 
     def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]):
         self.get_response = get_response
 
+    def _ensure_fallback_user(self):
+        """Defer fetching anonymous user until we have to"""
+        if self.anonymous_user:
+            return
+        from guardian.shortcuts import get_anonymous_user
+
+        self.anonymous_user = get_anonymous_user()
+
     def connect(self, request: HttpRequest):
         """Connect signal for automatic logging"""
-        if not hasattr(request, "user"):
-            return
-        if not getattr(request.user, "is_authenticated", False):
-            return
+        self._ensure_fallback_user()
+        user = getattr(request, "user", self.anonymous_user)
+        if not user.is_authenticated:
+            user = self.anonymous_user
         if not hasattr(request, "request_id"):
             return
-        post_save_handler = partial(self.post_save_handler, user=request.user, request=request)
-        pre_delete_handler = partial(self.pre_delete_handler, user=request.user, request=request)
-        m2m_changed_handler = partial(self.m2m_changed_handler, user=request.user, request=request)
+        post_save_handler = partial(self.post_save_handler, user=user, request=request)
+        pre_delete_handler = partial(self.pre_delete_handler, user=user, request=request)
+        m2m_changed_handler = partial(self.m2m_changed_handler, user=user, request=request)
         post_save.connect(
             post_save_handler,
             dispatch_uid=request.request_id,

{"golden_diff": "diff --git a/authentik/events/middleware.py b/authentik/events/middleware.py\n--- a/authentik/events/middleware.py\n+++ b/authentik/events/middleware.py\n@@ -93,21 +93,30 @@\n     of models\"\"\"\n \n     get_response: Callable[[HttpRequest], HttpResponse]\n+    anonymous_user: User = None\n \n     def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]):\n         self.get_response = get_response\n \n+    def _ensure_fallback_user(self):\n+        \"\"\"Defer fetching anonymous user until we have to\"\"\"\n+        if self.anonymous_user:\n+            return\n+        from guardian.shortcuts import get_anonymous_user\n+\n+        self.anonymous_user = get_anonymous_user()\n+\n     def connect(self, request: HttpRequest):\n         \"\"\"Connect signal for automatic logging\"\"\"\n-        if not hasattr(request, \"user\"):\n-            return\n-        if not getattr(request.user, \"is_authenticated\", False):\n-            return\n+        self._ensure_fallback_user()\n+        user = getattr(request, \"user\", self.anonymous_user)\n+        if not user.is_authenticated:\n+            user = self.anonymous_user\n         if not hasattr(request, \"request_id\"):\n             return\n-        post_save_handler = partial(self.post_save_handler, user=request.user, request=request)\n-        pre_delete_handler = partial(self.pre_delete_handler, user=request.user, request=request)\n-        m2m_changed_handler = partial(self.m2m_changed_handler, user=request.user, request=request)\n+        post_save_handler = partial(self.post_save_handler, user=user, request=request)\n+        pre_delete_handler = partial(self.pre_delete_handler, user=user, request=request)\n+        m2m_changed_handler = partial(self.m2m_changed_handler, user=user, request=request)\n         post_save.connect(\n             post_save_handler,\n             dispatch_uid=request.request_id,\n", "issue": "User write stages do not trigger a Model Updated event when writing to an existing user\n**Describe the bug**\r\nUser write stages do not trigger a \"Model updated\" event when the user is existing if the stage is after an email stage with \"activate pending user on success\".\r\n\r\n**To Reproduce**\r\nSteps to reproduce the behavior:\r\n1. Create a new enrollment flow\r\n2. Add a prompt stage to enter username email and name\r\n3. Do a user write, make sure it always creates a new user and store the user as inactive\r\n4. Add an email stage, and enable \"Activate pending user on success\"\r\n5. Add a prompt stage to set the password\r\n6. Do another user write, make sure it never creates a user\r\n7. Do a log in\r\n\r\nDuring this process there is no Model Updated event sent in the second user write.\r\nHowever, when you remove the email stage, it will trigger this event.\r\nIt also triggers the correct event in the user-write on a user settings flow for example, so it seems to be related to the activation stage.\r\n\r\n**Expected behavior**\r\nA user write should trigger a Model Updated event when modifying an existing user, as it also triggers a Model Created event when a new user is written to.\r\n\r\n**Version and Deployment (please complete the following information):**\r\n - authentik version: 2023.1.2\r\n\n", "before_files": [{"content": "\"\"\"Events middleware\"\"\"\nfrom functools import partial\nfrom threading import Thread\nfrom typing import Any, Callable, Optional\n\nfrom django.conf import settings\nfrom django.contrib.sessions.models import Session\nfrom django.core.exceptions import SuspiciousOperation\nfrom django.db.models import Model\nfrom django.db.models.signals import m2m_changed, post_save, pre_delete\nfrom django.http import HttpRequest, HttpResponse\nfrom guardian.models import UserObjectPermission\n\nfrom authentik.core.models import (\n    AuthenticatedSession,\n    Group,\n    PropertyMapping,\n    Provider,\n    Source,\n    User,\n    UserSourceConnection,\n)\nfrom authentik.events.models import Event, EventAction, Notification\nfrom authentik.events.utils import model_to_dict\nfrom authentik.flows.models import FlowToken, Stage\nfrom authentik.lib.sentry import before_send\nfrom authentik.lib.utils.errors import exception_to_string\nfrom authentik.outposts.models import OutpostServiceConnection\nfrom authentik.policies.models import Policy, PolicyBindingModel\nfrom authentik.providers.oauth2.models import AccessToken, AuthorizationCode, RefreshToken\nfrom authentik.providers.scim.models import SCIMGroup, SCIMUser\nfrom authentik.stages.authenticator_static.models import StaticToken\n\nIGNORED_MODELS = (\n    Event,\n    Notification,\n    UserObjectPermission,\n    AuthenticatedSession,\n    StaticToken,\n    Session,\n    FlowToken,\n    Provider,\n    Source,\n    PropertyMapping,\n    UserSourceConnection,\n    Stage,\n    OutpostServiceConnection,\n    Policy,\n    PolicyBindingModel,\n    AuthorizationCode,\n    AccessToken,\n    RefreshToken,\n    SCIMUser,\n    SCIMGroup,\n)\n\n\ndef should_log_model(model: Model) -> bool:\n    \"\"\"Return true if operation on `model` should be logged\"\"\"\n    if model.__module__.startswith(\"silk\"):\n        return False\n    return model.__class__ not in IGNORED_MODELS\n\n\ndef should_log_m2m(model: Model) -> bool:\n    \"\"\"Return true if m2m operation should be logged\"\"\"\n    if model.__class__ in [User, Group]:\n        return True\n    return False\n\n\nclass EventNewThread(Thread):\n    \"\"\"Create Event in background thread\"\"\"\n\n    action: str\n    request: HttpRequest\n    kwargs: dict[str, Any]\n    user: Optional[User] = None\n\n    def __init__(self, action: str, request: HttpRequest, user: Optional[User] = None, **kwargs):\n        super().__init__()\n        self.action = action\n        self.request = request\n        self.user = user\n        self.kwargs = kwargs\n\n    def run(self):\n        Event.new(self.action, **self.kwargs).from_http(self.request, user=self.user)\n\n\nclass AuditMiddleware:\n    \"\"\"Register handlers for duration of request-response that log creation/update/deletion\n    of models\"\"\"\n\n    get_response: Callable[[HttpRequest], HttpResponse]\n\n    def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]):\n        self.get_response = get_response\n\n    def connect(self, request: HttpRequest):\n        \"\"\"Connect signal for automatic logging\"\"\"\n        if not hasattr(request, \"user\"):\n            return\n        if not getattr(request.user, \"is_authenticated\", False):\n            return\n        if not hasattr(request, \"request_id\"):\n            return\n        post_save_handler = partial(self.post_save_handler, user=request.user, request=request)\n        pre_delete_handler = partial(self.pre_delete_handler, user=request.user, request=request)\n        m2m_changed_handler = partial(self.m2m_changed_handler, user=request.user, request=request)\n        post_save.connect(\n            post_save_handler,\n            dispatch_uid=request.request_id,\n            weak=False,\n        )\n        pre_delete.connect(\n            pre_delete_handler,\n            dispatch_uid=request.request_id,\n            weak=False,\n        )\n        m2m_changed.connect(\n            m2m_changed_handler,\n            dispatch_uid=request.request_id,\n            weak=False,\n        )\n\n    def disconnect(self, request: HttpRequest):\n        \"\"\"Disconnect signals\"\"\"\n        if not hasattr(request, \"request_id\"):\n            return\n        post_save.disconnect(dispatch_uid=request.request_id)\n        pre_delete.disconnect(dispatch_uid=request.request_id)\n        m2m_changed.disconnect(dispatch_uid=request.request_id)\n\n    def __call__(self, request: HttpRequest) -> HttpResponse:\n        self.connect(request)\n\n        response = self.get_response(request)\n\n        self.disconnect(request)\n        return response\n\n    def process_exception(self, request: HttpRequest, exception: Exception):\n        \"\"\"Disconnect handlers in case of exception\"\"\"\n        self.disconnect(request)\n\n        if settings.DEBUG:\n            return\n        # Special case for SuspiciousOperation, we have a special event action for that\n        if isinstance(exception, SuspiciousOperation):\n            thread = EventNewThread(\n                EventAction.SUSPICIOUS_REQUEST,\n                request,\n                message=str(exception),\n            )\n            thread.run()\n        elif before_send({}, {\"exc_info\": (None, exception, None)}) is not None:\n            thread = EventNewThread(\n                EventAction.SYSTEM_EXCEPTION,\n                request,\n                message=exception_to_string(exception),\n            )\n            thread.run()\n\n    @staticmethod\n    def post_save_handler(\n        user: User, request: HttpRequest, sender, instance: Model, created: bool, **_\n    ):\n        \"\"\"Signal handler for all object's post_save\"\"\"\n        if not should_log_model(instance):\n            return\n\n        action = EventAction.MODEL_CREATED if created else EventAction.MODEL_UPDATED\n        EventNewThread(action, request, user=user, model=model_to_dict(instance)).run()\n\n    @staticmethod\n    def pre_delete_handler(user: User, request: HttpRequest, sender, instance: Model, **_):\n        \"\"\"Signal handler for all object's pre_delete\"\"\"\n        if not should_log_model(instance):  # pragma: no cover\n            return\n\n        EventNewThread(\n            EventAction.MODEL_DELETED,\n            request,\n            user=user,\n            model=model_to_dict(instance),\n        ).run()\n\n    @staticmethod\n    def m2m_changed_handler(\n        user: User, request: HttpRequest, sender, instance: Model, action: str, **_\n    ):\n        \"\"\"Signal handler for all object's m2m_changed\"\"\"\n        if action not in [\"pre_add\", \"pre_remove\", \"post_clear\"]:\n            return\n        if not should_log_m2m(instance):\n            return\n\n        EventNewThread(\n            EventAction.MODEL_UPDATED,\n            request,\n            user=user,\n            model=model_to_dict(instance),\n        ).run()\n", "path": "authentik/events/middleware.py"}], "after_files": [{"content": "\"\"\"Events middleware\"\"\"\nfrom functools import partial\nfrom threading import Thread\nfrom typing import Any, Callable, Optional\n\nfrom django.conf import settings\nfrom django.contrib.sessions.models import Session\nfrom django.core.exceptions import SuspiciousOperation\nfrom django.db.models import Model\nfrom django.db.models.signals import m2m_changed, post_save, pre_delete\nfrom django.http import HttpRequest, HttpResponse\nfrom guardian.models import UserObjectPermission\n\nfrom authentik.core.models import (\n    AuthenticatedSession,\n    Group,\n    PropertyMapping,\n    Provider,\n    Source,\n    User,\n    UserSourceConnection,\n)\nfrom authentik.events.models import Event, EventAction, Notification\nfrom authentik.events.utils import model_to_dict\nfrom authentik.flows.models import FlowToken, Stage\nfrom authentik.lib.sentry import before_send\nfrom authentik.lib.utils.errors import exception_to_string\nfrom authentik.outposts.models import OutpostServiceConnection\nfrom authentik.policies.models import Policy, PolicyBindingModel\nfrom authentik.providers.oauth2.models import AccessToken, AuthorizationCode, RefreshToken\nfrom authentik.providers.scim.models import SCIMGroup, SCIMUser\nfrom authentik.stages.authenticator_static.models import StaticToken\n\nIGNORED_MODELS = (\n    Event,\n    Notification,\n    UserObjectPermission,\n    AuthenticatedSession,\n    StaticToken,\n    Session,\n    FlowToken,\n    Provider,\n    Source,\n    PropertyMapping,\n    UserSourceConnection,\n    Stage,\n    OutpostServiceConnection,\n    Policy,\n    PolicyBindingModel,\n    AuthorizationCode,\n    AccessToken,\n    RefreshToken,\n    SCIMUser,\n    SCIMGroup,\n)\n\n\ndef should_log_model(model: Model) -> bool:\n    \"\"\"Return true if operation on `model` should be logged\"\"\"\n    if model.__module__.startswith(\"silk\"):\n        return False\n    return model.__class__ not in IGNORED_MODELS\n\n\ndef should_log_m2m(model: Model) -> bool:\n    \"\"\"Return true if m2m operation should be logged\"\"\"\n    if model.__class__ in [User, Group]:\n        return True\n    return False\n\n\nclass EventNewThread(Thread):\n    \"\"\"Create Event in background thread\"\"\"\n\n    action: str\n    request: HttpRequest\n    kwargs: dict[str, Any]\n    user: Optional[User] = None\n\n    def __init__(self, action: str, request: HttpRequest, user: Optional[User] = None, **kwargs):\n        super().__init__()\n        self.action = action\n        self.request = request\n        self.user = user\n        self.kwargs = kwargs\n\n    def run(self):\n        Event.new(self.action, **self.kwargs).from_http(self.request, user=self.user)\n\n\nclass AuditMiddleware:\n    \"\"\"Register handlers for duration of request-response that log creation/update/deletion\n    of models\"\"\"\n\n    get_response: Callable[[HttpRequest], HttpResponse]\n    anonymous_user: User = None\n\n    def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]):\n        self.get_response = get_response\n\n    def _ensure_fallback_user(self):\n        \"\"\"Defer fetching anonymous user until we have to\"\"\"\n        if self.anonymous_user:\n            return\n        from guardian.shortcuts import get_anonymous_user\n\n        self.anonymous_user = get_anonymous_user()\n\n    def connect(self, request: HttpRequest):\n        \"\"\"Connect signal for automatic logging\"\"\"\n        self._ensure_fallback_user()\n        user = getattr(request, \"user\", self.anonymous_user)\n        if not user.is_authenticated:\n            user = self.anonymous_user\n        if not hasattr(request, \"request_id\"):\n            return\n        post_save_handler = partial(self.post_save_handler, user=user, request=request)\n        pre_delete_handler = partial(self.pre_delete_handler, user=user, request=request)\n        m2m_changed_handler = partial(self.m2m_changed_handler, user=user, request=request)\n        post_save.connect(\n            post_save_handler,\n            dispatch_uid=request.request_id,\n            weak=False,\n        )\n        pre_delete.connect(\n            pre_delete_handler,\n            dispatch_uid=request.request_id,\n            weak=False,\n        )\n        m2m_changed.connect(\n            m2m_changed_handler,\n            dispatch_uid=request.request_id,\n            weak=False,\n        )\n\n    def disconnect(self, request: HttpRequest):\n        \"\"\"Disconnect signals\"\"\"\n        if not hasattr(request, \"request_id\"):\n            return\n        post_save.disconnect(dispatch_uid=request.request_id)\n        pre_delete.disconnect(dispatch_uid=request.request_id)\n        m2m_changed.disconnect(dispatch_uid=request.request_id)\n\n    def __call__(self, request: HttpRequest) -> HttpResponse:\n        self.connect(request)\n\n        response = self.get_response(request)\n\n        self.disconnect(request)\n        return response\n\n    def process_exception(self, request: HttpRequest, exception: Exception):\n        \"\"\"Disconnect handlers in case of exception\"\"\"\n        self.disconnect(request)\n\n        if settings.DEBUG:\n            return\n        # Special case for SuspiciousOperation, we have a special event action for that\n        if isinstance(exception, SuspiciousOperation):\n            thread = EventNewThread(\n                EventAction.SUSPICIOUS_REQUEST,\n                request,\n                message=str(exception),\n            )\n            thread.run()\n        elif before_send({}, {\"exc_info\": (None, exception, None)}) is not None:\n            thread = EventNewThread(\n                EventAction.SYSTEM_EXCEPTION,\n                request,\n                message=exception_to_string(exception),\n            )\n            thread.run()\n\n    @staticmethod\n    def post_save_handler(\n        user: User, request: HttpRequest, sender, instance: Model, created: bool, **_\n    ):\n        \"\"\"Signal handler for all object's post_save\"\"\"\n        if not should_log_model(instance):\n            return\n\n        action = EventAction.MODEL_CREATED if created else EventAction.MODEL_UPDATED\n        EventNewThread(action, request, user=user, model=model_to_dict(instance)).run()\n\n    @staticmethod\n    def pre_delete_handler(user: User, request: HttpRequest, sender, instance: Model, **_):\n        \"\"\"Signal handler for all object's pre_delete\"\"\"\n        if not should_log_model(instance):  # pragma: no cover\n            return\n\n        EventNewThread(\n            EventAction.MODEL_DELETED,\n            request,\n            user=user,\n            model=model_to_dict(instance),\n        ).run()\n\n    @staticmethod\n    def m2m_changed_handler(\n        user: User, request: HttpRequest, sender, instance: Model, action: str, **_\n    ):\n        \"\"\"Signal handler for all object's m2m_changed\"\"\"\n        if action not in [\"pre_add\", \"pre_remove\", \"post_clear\"]:\n            return\n        if not should_log_m2m(instance):\n            return\n\n        EventNewThread(\n            EventAction.MODEL_UPDATED,\n            request,\n            user=user,\n            model=model_to_dict(instance),\n        ).run()\n", "path": "authentik/events/middleware.py"}]}