events: improve handling creation of events with non-pickleable objects
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
93fee5f0e5
commit
3251bdc220
|
@ -1,7 +1,6 @@
|
|||
"""authentik events models"""
|
||||
import time
|
||||
from collections import Counter
|
||||
from copy import deepcopy
|
||||
from datetime import timedelta
|
||||
from inspect import currentframe
|
||||
from smtplib import SMTPException
|
||||
|
@ -211,7 +210,7 @@ class Event(SerializerModel, ExpiringModel):
|
|||
current = currentframe()
|
||||
parent = current.f_back
|
||||
app = parent.f_globals["__name__"]
|
||||
cleaned_kwargs = cleanse_dict(sanitize_dict(deepcopy(kwargs)))
|
||||
cleaned_kwargs = cleanse_dict(sanitize_dict(kwargs))
|
||||
event = Event(action=action, app=app, context=cleaned_kwargs)
|
||||
return event
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
"""event utilities"""
|
||||
import re
|
||||
from copy import copy
|
||||
from dataclasses import asdict, is_dataclass
|
||||
from pathlib import Path
|
||||
from types import GeneratorType
|
||||
|
@ -87,9 +88,15 @@ def sanitize_item(value: Any) -> Any:
|
|||
"""Sanitize a single item, ensure it is JSON parsable"""
|
||||
if is_dataclass(value):
|
||||
# Because asdict calls `copy.deepcopy(obj)` on everything that's not tuple/dict,
|
||||
# and deepcopy doesn't work with HttpRequests (neither django nor rest_framework).
|
||||
# and deepcopy doesn't work with HttpRequest (neither django nor rest_framework).
|
||||
# (more specifically doesn't work with ResolverMatch)
|
||||
# rest_framework's custom Request class makes this more complicated as it also holds a
|
||||
# thread lock.
|
||||
# Since this class is mainly used for Events which already hold the http request context
|
||||
# we just remove the http_request from the shallow policy request
|
||||
# Currently, the only dataclass that actually holds an http request is a PolicyRequest
|
||||
if isinstance(value, PolicyRequest):
|
||||
if isinstance(value, PolicyRequest) and value.http_request is not None:
|
||||
value: PolicyRequest = copy(value)
|
||||
value.http_request = None
|
||||
value = asdict(value)
|
||||
if isinstance(value, dict):
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.core.cache import cache
|
||||
from django.test import RequestFactory, TestCase
|
||||
from django.urls import resolve, reverse
|
||||
from guardian.shortcuts import get_anonymous_user
|
||||
|
||||
from authentik.core.models import Application, Group, User
|
||||
|
@ -129,8 +130,9 @@ class TestPolicyProcess(TestCase):
|
|||
)
|
||||
binding = PolicyBinding(policy=policy, target=Application.objects.create(name="test"))
|
||||
|
||||
http_request = self.factory.get("/")
|
||||
http_request = self.factory.get(reverse("authentik_core:impersonate-end"))
|
||||
http_request.user = self.user
|
||||
http_request.resolver_match = resolve(reverse("authentik_core:impersonate-end"))
|
||||
|
||||
request = PolicyRequest(self.user)
|
||||
request.set_http_request(http_request)
|
||||
|
|
Reference in a new issue