events: save login event in session after login
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> #4070
This commit is contained in:
parent
f22f1ebcde
commit
5019346ab6
|
@ -196,9 +196,9 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet):
|
|||
if not should_cache:
|
||||
allowed_applications = self._get_allowed_applications(queryset)
|
||||
if should_cache:
|
||||
LOGGER.debug("Caching allowed application list")
|
||||
allowed_applications = cache.get(user_app_cache_key(self.request.user.pk))
|
||||
if not allowed_applications:
|
||||
LOGGER.debug("Caching allowed application list")
|
||||
allowed_applications = self._get_allowed_applications(queryset)
|
||||
cache.set(
|
||||
user_app_cache_key(self.request.user.pk),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""Events middleware"""
|
||||
from functools import partial
|
||||
from typing import Callable
|
||||
from threading import Thread
|
||||
from typing import Any, Callable, Optional
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.sessions.models import Session
|
||||
|
@ -13,7 +14,6 @@ from guardian.models import UserObjectPermission
|
|||
|
||||
from authentik.core.models import AuthenticatedSession, User
|
||||
from authentik.events.models import Event, EventAction, Notification
|
||||
from authentik.events.signals import EventNewThread
|
||||
from authentik.events.utils import model_to_dict
|
||||
from authentik.flows.models import FlowToken
|
||||
from authentik.lib.sentry import before_send
|
||||
|
@ -37,6 +37,25 @@ def should_log_model(model: Model) -> bool:
|
|||
return not isinstance(model, IGNORED_MODELS)
|
||||
|
||||
|
||||
class EventNewThread(Thread):
|
||||
"""Create Event in background thread"""
|
||||
|
||||
action: str
|
||||
request: HttpRequest
|
||||
kwargs: dict[str, Any]
|
||||
user: Optional[User] = None
|
||||
|
||||
def __init__(self, action: str, request: HttpRequest, user: Optional[User] = None, **kwargs):
|
||||
super().__init__()
|
||||
self.action = action
|
||||
self.request = request
|
||||
self.user = user
|
||||
self.kwargs = kwargs
|
||||
|
||||
def run(self):
|
||||
Event.new(self.action, **self.kwargs).from_http(self.request, user=self.user)
|
||||
|
||||
|
||||
class AuditMiddleware:
|
||||
"""Register handlers for duration of request-response that log creation/update/deletion
|
||||
of models"""
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
"""authentik events signal listener"""
|
||||
from threading import Thread
|
||||
from typing import Any, Optional
|
||||
|
||||
from django.contrib.auth.signals import user_logged_in, user_logged_out
|
||||
|
@ -19,63 +18,40 @@ from authentik.stages.invitation.signals import invitation_used
|
|||
from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS
|
||||
from authentik.stages.user_write.signals import user_write
|
||||
|
||||
|
||||
class EventNewThread(Thread):
|
||||
"""Create Event in background thread"""
|
||||
|
||||
action: str
|
||||
request: HttpRequest
|
||||
kwargs: dict[str, Any]
|
||||
user: Optional[User] = None
|
||||
|
||||
def __init__(self, action: str, request: HttpRequest, user: Optional[User] = None, **kwargs):
|
||||
super().__init__()
|
||||
self.action = action
|
||||
self.request = request
|
||||
self.user = user
|
||||
self.kwargs = kwargs
|
||||
|
||||
def run(self):
|
||||
Event.new(self.action, **self.kwargs).from_http(self.request, user=self.user)
|
||||
SESSION_LOGIN_EVENT = "login_event"
|
||||
|
||||
|
||||
@receiver(user_logged_in)
|
||||
# pylint: disable=unused-argument
|
||||
def on_user_logged_in(sender, request: HttpRequest, user: User, **_):
|
||||
"""Log successful login"""
|
||||
thread = EventNewThread(EventAction.LOGIN, request)
|
||||
kwargs = {}
|
||||
if SESSION_KEY_PLAN in request.session:
|
||||
flow_plan: FlowPlan = request.session[SESSION_KEY_PLAN]
|
||||
if PLAN_CONTEXT_SOURCE in flow_plan.context:
|
||||
# Login request came from an external source, save it in the context
|
||||
thread.kwargs[PLAN_CONTEXT_SOURCE] = flow_plan.context[PLAN_CONTEXT_SOURCE]
|
||||
kwargs[PLAN_CONTEXT_SOURCE] = flow_plan.context[PLAN_CONTEXT_SOURCE]
|
||||
if PLAN_CONTEXT_METHOD in flow_plan.context:
|
||||
thread.kwargs[PLAN_CONTEXT_METHOD] = flow_plan.context[PLAN_CONTEXT_METHOD]
|
||||
# Save the login method used
|
||||
thread.kwargs[PLAN_CONTEXT_METHOD_ARGS] = flow_plan.context.get(
|
||||
PLAN_CONTEXT_METHOD_ARGS, {}
|
||||
)
|
||||
thread.user = user
|
||||
thread.run()
|
||||
kwargs[PLAN_CONTEXT_METHOD] = flow_plan.context[PLAN_CONTEXT_METHOD]
|
||||
kwargs[PLAN_CONTEXT_METHOD_ARGS] = flow_plan.context.get(PLAN_CONTEXT_METHOD_ARGS, {})
|
||||
event = Event.new(EventAction.LOGIN, **kwargs).from_http(request, user=user)
|
||||
request.session[SESSION_LOGIN_EVENT] = event
|
||||
|
||||
|
||||
@receiver(user_logged_out)
|
||||
# pylint: disable=unused-argument
|
||||
def on_user_logged_out(sender, request: HttpRequest, user: User, **_):
|
||||
"""Log successfully logout"""
|
||||
thread = EventNewThread(EventAction.LOGOUT, request)
|
||||
thread.user = user
|
||||
thread.run()
|
||||
Event.new(EventAction.LOGOUT).from_http(request, user=user)
|
||||
|
||||
|
||||
@receiver(user_write)
|
||||
# pylint: disable=unused-argument
|
||||
def on_user_write(sender, request: HttpRequest, user: User, data: dict[str, Any], **kwargs):
|
||||
"""Log User write"""
|
||||
thread = EventNewThread(EventAction.USER_WRITE, request, **data)
|
||||
thread.kwargs["created"] = kwargs.get("created", False)
|
||||
thread.user = user
|
||||
thread.run()
|
||||
data["created"] = kwargs.get("created", False)
|
||||
Event.new(EventAction.USER_WRITE, **data).from_http(request, user=user)
|
||||
|
||||
|
||||
@receiver(login_failed)
|
||||
|
@ -89,26 +65,23 @@ def on_login_failed(
|
|||
**kwargs,
|
||||
):
|
||||
"""Failed Login, authentik custom event"""
|
||||
thread = EventNewThread(EventAction.LOGIN_FAILED, request, **credentials, stage=stage, **kwargs)
|
||||
thread.run()
|
||||
Event.new(EventAction.USER_WRITE, **credentials, stage=stage, **kwargs).from_http(request)
|
||||
|
||||
|
||||
@receiver(invitation_used)
|
||||
# pylint: disable=unused-argument
|
||||
def on_invitation_used(sender, request: HttpRequest, invitation: Invitation, **_):
|
||||
"""Log Invitation usage"""
|
||||
thread = EventNewThread(
|
||||
EventAction.INVITE_USED, request, invitation_uuid=invitation.invite_uuid.hex
|
||||
Event.new(EventAction.INVITE_USED, invitation_uuid=invitation.invite_uuid.hex).from_http(
|
||||
request
|
||||
)
|
||||
thread.run()
|
||||
|
||||
|
||||
@receiver(password_changed)
|
||||
# pylint: disable=unused-argument
|
||||
def on_password_changed(sender, user: User, password: str, **_):
|
||||
"""Log password change"""
|
||||
thread = EventNewThread(EventAction.PASSWORD_SET, None, user=user)
|
||||
thread.run()
|
||||
Event.new(EventAction.PASSWORD_SET).from_http(None, user=user)
|
||||
|
||||
|
||||
@receiver(post_save, sender=Event)
|
||||
|
|
Reference in a new issue