diff --git a/authentik/flows/stage.py b/authentik/flows/stage.py index 970c4792c..bf26b7435 100644 --- a/authentik/flows/stage.py +++ b/authentik/flows/stage.py @@ -9,7 +9,7 @@ from django.urls import reverse from django.views.generic.base import View from rest_framework.request import Request from sentry_sdk.hub import Hub -from structlog.stdlib import get_logger +from structlog.stdlib import BoundLogger, get_logger from authentik.core.models import DEFAULT_AVATAR, User from authentik.flows.challenge import ( @@ -28,7 +28,6 @@ if TYPE_CHECKING: from authentik.flows.views.executor import FlowExecutorView PLAN_CONTEXT_PENDING_USER_IDENTIFIER = "pending_user_identifier" -LOGGER = get_logger() class StageView(View): @@ -38,8 +37,15 @@ class StageView(View): request: HttpRequest = None + logger: BoundLogger + def __init__(self, executor: "FlowExecutorView", **kwargs): self.executor = executor + current_stage = getattr(self.executor, "current_stage", None) + self.logger = get_logger().bind( + stage=getattr(current_stage, "name", None), + stage_view=self, + ) super().__init__(**kwargs) def get_pending_user(self, for_display=False) -> User: @@ -77,12 +83,9 @@ class ChallengeStageView(StageView): """Return a challenge for the frontend to solve""" challenge = self._get_challenge(*args, **kwargs) if not challenge.is_valid(): - LOGGER.warning( + self.logger.warning( "f(ch): Invalid challenge", - binding=self.executor.current_binding, errors=challenge.errors, - stage_view=self, - challenge=challenge, ) return HttpChallengeResponse(challenge) @@ -99,10 +102,8 @@ class ChallengeStageView(StageView): self.executor.current_binding.invalid_response_action == InvalidResponseAction.RESTART_WITH_CONTEXT ) - LOGGER.debug( + self.logger.debug( "f(ch): Invalid response, restarting flow", - binding=self.executor.current_binding, - stage_view=self, keep_context=keep_context, ) return self.executor.restart_flow(keep_context) @@ -128,7 +129,7 @@ class ChallengeStageView(StageView): } # pylint: disable=broad-except except Exception as exc: - LOGGER.warning("failed to template title", exc=exc) + self.logger.warning("failed to template title", exc=exc) return self.executor.flow.title def _get_challenge(self, *args, **kwargs) -> Challenge: @@ -188,11 +189,9 @@ class ChallengeStageView(StageView): ) challenge_response.initial_data["response_errors"] = full_errors if not challenge_response.is_valid(): - LOGGER.error( + self.logger.error( "f(ch): invalid challenge response", - binding=self.executor.current_binding, errors=challenge_response.errors, - stage_view=self, ) return HttpChallengeResponse(challenge_response) diff --git a/authentik/stages/authenticator_duo/stage.py b/authentik/stages/authenticator_duo/stage.py index 2c6d863da..433e811ab 100644 --- a/authentik/stages/authenticator_duo/stage.py +++ b/authentik/stages/authenticator_duo/stage.py @@ -2,7 +2,6 @@ from django.http import HttpRequest, HttpResponse from django.utils.timezone import now from rest_framework.fields import CharField -from structlog.stdlib import get_logger from authentik.events.models import Event, EventAction from authentik.flows.challenge import ( @@ -16,8 +15,6 @@ from authentik.flows.stage import ChallengeStageView from authentik.flows.views.executor import InvalidStageError from authentik.stages.authenticator_duo.models import AuthenticatorDuoStage, DuoDevice -LOGGER = get_logger() - SESSION_KEY_DUO_USER_ID = "authentik/stages/authenticator_duo/user_id" SESSION_KEY_DUO_ACTIVATION_CODE = "authentik/stages/authenticator_duo/activation_code" @@ -69,7 +66,7 @@ class AuthenticatorDuoStageView(ChallengeStageView): def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: user = self.executor.plan.context.get(PLAN_CONTEXT_PENDING_USER) if not user: - LOGGER.debug("No pending user, continuing") + self.logger.debug("No pending user, continuing") return self.executor.stage_ok() return super().get(request, *args, **kwargs) diff --git a/authentik/stages/authenticator_sms/stage.py b/authentik/stages/authenticator_sms/stage.py index 581522ce6..90ed24b63 100644 --- a/authentik/stages/authenticator_sms/stage.py +++ b/authentik/stages/authenticator_sms/stage.py @@ -6,7 +6,6 @@ from django.http.request import QueryDict from django.utils.translation import gettext_lazy as _ from rest_framework.exceptions import ValidationError from rest_framework.fields import BooleanField, CharField, IntegerField -from structlog.stdlib import get_logger from authentik.flows.challenge import ( Challenge, @@ -19,7 +18,6 @@ from authentik.flows.stage import ChallengeStageView from authentik.stages.authenticator_sms.models import AuthenticatorSMSStage, SMSDevice from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT -LOGGER = get_logger() SESSION_KEY_SMS_DEVICE = "authentik/stages/authenticator_sms/sms_device" @@ -64,10 +62,10 @@ class AuthenticatorSMSStageView(ChallengeStageView): def _has_phone_number(self) -> Optional[str]: context = self.executor.plan.context if "phone" in context.get(PLAN_CONTEXT_PROMPT, {}): - LOGGER.debug("got phone number from plan context") + self.logger.debug("got phone number from plan context") return context.get(PLAN_CONTEXT_PROMPT, {}).get("phone") if SESSION_KEY_SMS_DEVICE in self.request.session: - LOGGER.debug("got phone number from device in session") + self.logger.debug("got phone number from device in session") device: SMSDevice = self.request.session[SESSION_KEY_SMS_DEVICE] if device.phone_number == "": return None @@ -90,7 +88,7 @@ class AuthenticatorSMSStageView(ChallengeStageView): def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: user = self.executor.plan.context.get(PLAN_CONTEXT_PENDING_USER) if not user: - LOGGER.debug("No pending user, continuing") + self.logger.debug("No pending user, continuing") return self.executor.stage_ok() # Currently, this stage only supports one device per user. If the user already diff --git a/authentik/stages/authenticator_static/stage.py b/authentik/stages/authenticator_static/stage.py index 3cb082a28..841bb35ad 100644 --- a/authentik/stages/authenticator_static/stage.py +++ b/authentik/stages/authenticator_static/stage.py @@ -2,14 +2,11 @@ from django.http import HttpRequest, HttpResponse from django_otp.plugins.otp_static.models import StaticDevice, StaticToken from rest_framework.fields import CharField, ListField -from structlog.stdlib import get_logger from authentik.flows.challenge import ChallengeResponse, ChallengeTypes, WithUserInfoChallenge from authentik.flows.stage import ChallengeStageView from authentik.stages.authenticator_static.models import AuthenticatorStaticStage -LOGGER = get_logger() - class AuthenticatorStaticChallenge(WithUserInfoChallenge): """Static authenticator challenge""" @@ -42,7 +39,7 @@ class AuthenticatorStaticStageView(ChallengeStageView): def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: user = self.get_pending_user() if not user.is_authenticated: - LOGGER.debug("No pending user, continuing") + self.logger.debug("No pending user, continuing") return self.executor.stage_ok() stage: AuthenticatorStaticStage = self.executor.current_stage diff --git a/authentik/stages/authenticator_totp/stage.py b/authentik/stages/authenticator_totp/stage.py index 454ff013d..f431aa1b3 100644 --- a/authentik/stages/authenticator_totp/stage.py +++ b/authentik/stages/authenticator_totp/stage.py @@ -6,7 +6,6 @@ from django.utils.translation import gettext_lazy as _ from django_otp.plugins.otp_totp.models import TOTPDevice from rest_framework.fields import CharField, IntegerField from rest_framework.serializers import ValidationError -from structlog.stdlib import get_logger from authentik.flows.challenge import ( Challenge, @@ -18,8 +17,6 @@ from authentik.flows.stage import ChallengeStageView from authentik.stages.authenticator_totp.models import AuthenticatorTOTPStage from authentik.stages.authenticator_totp.settings import OTP_TOTP_ISSUER -LOGGER = get_logger() - class AuthenticatorTOTPChallenge(WithUserInfoChallenge): """TOTP Setup challenge""" @@ -72,7 +69,7 @@ class AuthenticatorTOTPStageView(ChallengeStageView): def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: user = self.get_pending_user() if not user.is_authenticated: - LOGGER.debug("No pending user, continuing") + self.logger.debug("No pending user, continuing") return self.executor.stage_ok() stage: AuthenticatorTOTPStage = self.executor.current_stage diff --git a/authentik/stages/authenticator_validate/stage.py b/authentik/stages/authenticator_validate/stage.py index 8abcb5d7f..4271d91f2 100644 --- a/authentik/stages/authenticator_validate/stage.py +++ b/authentik/stages/authenticator_validate/stage.py @@ -37,6 +37,7 @@ from authentik.stages.authenticator_webauthn.models import WebAuthnDevice from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS LOGGER = get_logger() + COOKIE_NAME_MFA = "authentik_mfa" SESSION_KEY_STAGES = "authentik/stages/authenticator_validate/stages" @@ -151,7 +152,7 @@ class AuthenticatorValidateStageView(ChallengeStageView): challenges = [] # Convert to a list to have usable log output instead of just user_devices = list(devices_for_user(self.get_pending_user())) - LOGGER.debug("Got devices for user", devices=user_devices) + self.logger.debug("Got devices for user", devices=user_devices) # static and totp are only shown once # since their challenges are device-independent @@ -165,7 +166,7 @@ class AuthenticatorValidateStageView(ChallengeStageView): for device in user_devices: device_class = device.__class__.__name__.lower().replace("device", "") if device_class not in stage.device_classes: - LOGGER.debug("device class not allowed", device_class=device_class) + self.logger.debug("device class not allowed", device_class=device_class) continue allowed_devices.append(device) # Ensure only one challenge per device class @@ -183,7 +184,7 @@ class AuthenticatorValidateStageView(ChallengeStageView): ) challenge.is_valid() challenges.append(challenge.data) - LOGGER.debug("adding challenge for device", challenge=challenge) + self.logger.debug("adding challenge for device", challenge=challenge) # check if we have an MFA cookie and if it's valid if threshold.total_seconds() > 0: self.check_mfa_cookie(allowed_devices) @@ -214,27 +215,27 @@ class AuthenticatorValidateStageView(ChallengeStageView): return self.executor.stage_ok() else: if self.executor.flow.designation != FlowDesignation.AUTHENTICATION: - LOGGER.debug("Refusing passwordless flow in non-authentication flow") + self.logger.debug("Refusing passwordless flow in non-authentication flow") return self.executor.stage_ok() # Passwordless auth, with just webauthn if DeviceClasses.WEBAUTHN in stage.device_classes: - LOGGER.debug("Flow without user, getting generic webauthn challenge") + self.logger.debug("Flow without user, getting generic webauthn challenge") challenges = self.get_webauthn_challenge_without_user() else: - LOGGER.debug("No pending user, continuing") + self.logger.debug("No pending user, continuing") return self.executor.stage_ok() self.request.session[SESSION_KEY_DEVICE_CHALLENGES] = challenges # No allowed devices if len(challenges) < 1: if stage.not_configured_action == NotConfiguredAction.SKIP: - LOGGER.debug("Authenticator not configured, skipping stage") + self.logger.debug("Authenticator not configured, skipping stage") return self.executor.stage_ok() if stage.not_configured_action == NotConfiguredAction.DENY: - LOGGER.debug("Authenticator not configured, denying") + self.logger.debug("Authenticator not configured, denying") return self.executor.stage_invalid() if stage.not_configured_action == NotConfiguredAction.CONFIGURE: - LOGGER.debug("Authenticator not configured, forcing configure") + self.logger.debug("Authenticator not configured, forcing configure") return self.prepare_stages(user) return super().get(request, *args, **kwargs) @@ -255,7 +256,7 @@ class AuthenticatorValidateStageView(ChallengeStageView): return self.executor.stage_invalid() if stage.configuration_stages.count() == 1: next_stage = Stage.objects.get_subclass(pk=stage.configuration_stages.first().pk) - LOGGER.debug("Single stage configured, auto-selecting", stage=next_stage) + self.logger.debug("Single stage configured, auto-selecting", stage=next_stage) self.request.session[SESSION_KEY_SELECTED_STAGE] = next_stage # Because that normal execution only happens on post, we directly inject it here and # return it @@ -271,7 +272,7 @@ class AuthenticatorValidateStageView(ChallengeStageView): SESSION_KEY_SELECTED_STAGE in self.request.session and self.executor.current_stage.not_configured_action == NotConfiguredAction.CONFIGURE ): - LOGGER.debug("Got selected stage in session, running that") + self.logger.debug("Got selected stage in session, running that") stage_pk = self.request.session.get(SESSION_KEY_SELECTED_STAGE) # Because the foreign key to stage.configuration_stage points to # a base stage class, we need to do another lookup @@ -326,18 +327,18 @@ class AuthenticatorValidateStageView(ChallengeStageView): try: payload = decode(self.request.COOKIES[COOKIE_NAME_MFA], self.cookie_jwt_key, ["HS256"]) if payload["stage"] != stage.pk.hex: - LOGGER.warning("Invalid stage PK") + self.logger.warning("Invalid stage PK") return if datetime.fromtimestamp(payload["exp"]) > latest_allowed: - LOGGER.warning("Expired MFA cookie") + self.logger.warning("Expired MFA cookie") return if not any(device.pk == payload["device"] for device in allowed_devices): - LOGGER.warning("Invalid device PK") + self.logger.warning("Invalid device PK") return - LOGGER.info("MFA has been used within threshold") + self.logger.info("MFA has been used within threshold") raise FlowSkipStageException() except (PyJWTError, ValueError, TypeError) as exc: - LOGGER.info("Invalid mfa cookie for device", exc=exc) + self.logger.info("Invalid mfa cookie for device", exc=exc) def set_valid_mfa_cookie(self, device: Device) -> HttpResponse: """Set an MFA cookie to allow users to skip MFA validation in this context (browser) @@ -346,7 +347,7 @@ class AuthenticatorValidateStageView(ChallengeStageView): stage: AuthenticatorValidateStage = self.executor.current_stage delta = timedelta_from_string(stage.last_auth_threshold) if delta.total_seconds() < 1: - LOGGER.info("Not setting MFA cookie since threshold is not set.") + self.logger.info("Not setting MFA cookie since threshold is not set.") return self.executor.stage_ok() expiry = datetime.now() + delta cookie_payload = { @@ -375,7 +376,7 @@ class AuthenticatorValidateStageView(ChallengeStageView): webauthn_device: WebAuthnDevice = response.data.get("webauthn", None) if not webauthn_device: return self.executor.stage_ok() - LOGGER.debug("Set user from user-less flow", user=webauthn_device.user) + self.logger.debug("Set user from user-less flow", user=webauthn_device.user) self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] = webauthn_device.user self.executor.plan.context[PLAN_CONTEXT_METHOD] = "auth_webauthn_pwl" self.executor.plan.context[PLAN_CONTEXT_METHOD_ARGS] = cleanse_dict( diff --git a/authentik/stages/authenticator_webauthn/stage.py b/authentik/stages/authenticator_webauthn/stage.py index 59ed3f32a..f8fba9ffe 100644 --- a/authentik/stages/authenticator_webauthn/stage.py +++ b/authentik/stages/authenticator_webauthn/stage.py @@ -29,7 +29,6 @@ from authentik.stages.authenticator_webauthn.models import AuthenticateWebAuthnS from authentik.stages.authenticator_webauthn.utils import get_origin, get_rp_id LOGGER = get_logger() - SESSION_KEY_WEBAUTHN_CHALLENGE = "authentik/stages/authenticator_webauthn/challenge" @@ -115,7 +114,7 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView): def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: user = self.executor.plan.context.get(PLAN_CONTEXT_PENDING_USER) if not user: - LOGGER.debug("No pending user, continuing") + self.logger.debug("No pending user, continuing") return self.executor.stage_ok() return super().get(request, *args, **kwargs) diff --git a/authentik/stages/deny/stage.py b/authentik/stages/deny/stage.py index 1620cee16..0513c269a 100644 --- a/authentik/stages/deny/stage.py +++ b/authentik/stages/deny/stage.py @@ -1,11 +1,8 @@ """Deny stage logic""" from django.http import HttpRequest, HttpResponse -from structlog.stdlib import get_logger from authentik.flows.stage import StageView -LOGGER = get_logger() - class DenyStageView(StageView): """Cancells the current flow""" diff --git a/authentik/stages/email/stage.py b/authentik/stages/email/stage.py index c9835cab6..8d35916b4 100644 --- a/authentik/stages/email/stage.py +++ b/authentik/stages/email/stage.py @@ -10,7 +10,6 @@ from django.utils.timezone import now from django.utils.translation import gettext as _ from rest_framework.fields import CharField from rest_framework.serializers import ValidationError -from structlog.stdlib import get_logger from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes from authentik.flows.models import FlowToken @@ -21,7 +20,6 @@ from authentik.stages.email.models import EmailStage from authentik.stages.email.tasks import send_mails from authentik.stages.email.utils import TemplateEmailMessage -LOGGER = get_logger() PLAN_CONTEXT_EMAIL_SENT = "email_sent" PLAN_CONTEXT_EMAIL_OVERRIDE = "email" @@ -113,7 +111,7 @@ class EmailStageView(ChallengeStageView): self.executor.plan.context[PLAN_CONTEXT_PENDING_USER].save() return self.executor.stage_ok() if PLAN_CONTEXT_PENDING_USER not in self.executor.plan.context: - LOGGER.debug("No pending user") + self.logger.debug("No pending user") messages.error(self.request, _("No pending user.")) return self.executor.stage_invalid() # Check if we've already sent the initial e-mail diff --git a/authentik/stages/identification/stage.py b/authentik/stages/identification/stage.py index 7243123fc..7656edbb4 100644 --- a/authentik/stages/identification/stage.py +++ b/authentik/stages/identification/stage.py @@ -159,11 +159,11 @@ class IdentificationStageView(ChallengeStageView): model_field += "__exact" query |= Q(**{model_field: uid_value}) if not query: - LOGGER.debug("Empty user query", query=query) + self.logger.debug("Empty user query", query=query) return None users = User.objects.filter(query, is_active=True) if users.exists(): - LOGGER.debug("Found user", user=users.first(), query=query) + self.logger.debug("Found user", user=users.first(), query=query) return users.first() return None diff --git a/authentik/stages/invitation/stage.py b/authentik/stages/invitation/stage.py index cea3f0054..c9d5883d7 100644 --- a/authentik/stages/invitation/stage.py +++ b/authentik/stages/invitation/stage.py @@ -4,7 +4,6 @@ from typing import Optional from deepmerge import always_merger from django.http import HttpRequest, HttpResponse from django.http.response import HttpResponseBadRequest -from structlog.stdlib import get_logger from authentik.flows.models import in_memory_stage from authentik.flows.stage import StageView @@ -13,7 +12,6 @@ from authentik.stages.invitation.models import Invitation, InvitationStage from authentik.stages.invitation.signals import invitation_used from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT -LOGGER = get_logger() INVITATION_TOKEN_KEY_CONTEXT = "token" # nosec INVITATION_TOKEN_KEY = "itoken" # nosec INVITATION_IN_EFFECT = "invitation_in_effect" @@ -51,7 +49,7 @@ class InvitationStageView(StageView): invite: Invitation = Invitation.objects.filter(pk=token).first() if not invite: - LOGGER.debug("invalid invitation", token=token) + self.logger.debug("invalid invitation", token=token) if stage.continue_flow_without_invitation: return self.executor.stage_ok() return self.executor.stage_invalid() @@ -81,11 +79,11 @@ class InvitationFinalStageView(StageView): """Delete invitation if single_use is active""" invitation: Invitation = self.executor.plan.context.get(INVITATION, None) if not invitation: - LOGGER.warning("InvitationFinalStageView stage called without invitation") + self.logger.warning("InvitationFinalStageView stage called without invitation") return HttpResponseBadRequest token = invitation.invite_uuid.hex if invitation.single_use: invitation.delete() - LOGGER.debug("Deleted invitation", token=token) + self.logger.debug("Deleted invitation", token=token) del self.executor.plan.context[INVITATION] return self.executor.stage_ok() diff --git a/authentik/stages/password/stage.py b/authentik/stages/password/stage.py index 508595a70..d6df90407 100644 --- a/authentik/stages/password/stage.py +++ b/authentik/stages/password/stage.py @@ -108,7 +108,7 @@ class PasswordStageView(ChallengeStageView): self.request.session[SESSION_KEY_INVALID_TRIES] > current_stage.failed_attempts_before_cancel ): - LOGGER.debug("User has exceeded maximum tries") + self.logger.debug("User has exceeded maximum tries") del self.request.session[SESSION_KEY_INVALID_TRIES] return self.executor.stage_invalid() return super().challenge_invalid(response) @@ -135,18 +135,18 @@ class PasswordStageView(ChallengeStageView): except PermissionDenied: del auth_kwargs["password"] # User was found, but permission was denied (i.e. user is not active) - LOGGER.debug("Denied access", **auth_kwargs) + self.logger.debug("Denied access", **auth_kwargs) return self.executor.stage_invalid() except ValidationError as exc: del auth_kwargs["password"] # User was found, authentication succeeded, but another signal raised an error # (most likely LDAP) - LOGGER.debug("Validation error from signal", exc=exc, **auth_kwargs) + self.logger.debug("Validation error from signal", exc=exc, **auth_kwargs) return self.executor.stage_invalid() else: if not user: # No user was found -> invalid credentials - LOGGER.debug("Invalid credentials") + self.logger.debug("Invalid credentials") # Manually inject error into form response._errors.setdefault("password", []) response._errors["password"].append(ErrorDetail(_("Invalid password"), "invalid")) diff --git a/authentik/stages/prompt/stage.py b/authentik/stages/prompt/stage.py index 665aec8bd..f68329c7a 100644 --- a/authentik/stages/prompt/stage.py +++ b/authentik/stages/prompt/stage.py @@ -10,7 +10,6 @@ from django.utils.translation import gettext_lazy as _ from guardian.shortcuts import get_anonymous_user from rest_framework.fields import BooleanField, CharField, ChoiceField, IntegerField, empty from rest_framework.serializers import ValidationError -from structlog.stdlib import get_logger from authentik.core.api.utils import PassiveSerializer from authentik.core.models import User @@ -22,7 +21,6 @@ from authentik.policies.models import PolicyBinding, PolicyBindingModel, PolicyE from authentik.stages.prompt.models import FieldTypes, Prompt, PromptStage from authentik.stages.prompt.signals import password_validate -LOGGER = get_logger() PLAN_CONTEXT_PROMPT = "prompt_data" diff --git a/authentik/stages/user_delete/stage.py b/authentik/stages/user_delete/stage.py index 4b68a0555..55a1a1711 100644 --- a/authentik/stages/user_delete/stage.py +++ b/authentik/stages/user_delete/stage.py @@ -3,13 +3,10 @@ from django.contrib import messages from django.contrib.auth import logout from django.http import HttpRequest, HttpResponse from django.utils.translation import gettext as _ -from structlog.stdlib import get_logger from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER from authentik.flows.stage import StageView -LOGGER = get_logger() - class UserDeleteStageView(StageView): """Finalise unenrollment flow by deleting the user object.""" @@ -24,11 +21,11 @@ class UserDeleteStageView(StageView): if not user.is_authenticated: message = _("No Pending User.") messages.error(request, message) - LOGGER.debug(message) + self.logger.debug(message) return self.executor.stage_invalid() logout(self.request) user.delete() - LOGGER.debug("Deleted user", user=user) + self.logger.debug("Deleted user", user=user) if PLAN_CONTEXT_PENDING_USER in self.executor.plan.context: del self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] return self.executor.stage_ok() diff --git a/authentik/stages/user_login/stage.py b/authentik/stages/user_login/stage.py index 4d4e184fd..00c9d9c70 100644 --- a/authentik/stages/user_login/stage.py +++ b/authentik/stages/user_login/stage.py @@ -3,7 +3,6 @@ from django.contrib import messages from django.contrib.auth import login from django.http import HttpRequest, HttpResponse from django.utils.translation import gettext as _ -from structlog.stdlib import get_logger from authentik.core.models import User from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER @@ -12,7 +11,6 @@ from authentik.lib.utils.time import timedelta_from_string from authentik.stages.password import BACKEND_INBUILT from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND -LOGGER = get_logger() USER_LOGIN_AUTHENTICATED = "user_login_authenticated" @@ -28,14 +26,14 @@ class UserLoginStageView(StageView): if PLAN_CONTEXT_PENDING_USER not in self.executor.plan.context: message = _("No Pending user to login.") messages.error(request, message) - LOGGER.debug(message) + self.logger.debug(message) return self.executor.stage_invalid() backend = self.executor.plan.context.get( PLAN_CONTEXT_AUTHENTICATION_BACKEND, BACKEND_INBUILT ) user: User = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] if not user.is_active: - LOGGER.warning("User is not active, login will not work.") + self.logger.warning("User is not active, login will not work.") login( self.request, user, @@ -46,7 +44,7 @@ class UserLoginStageView(StageView): self.request.session.set_expiry(0) else: self.request.session.set_expiry(delta) - LOGGER.debug( + self.logger.debug( "Logged in", backend=backend, user=user, diff --git a/authentik/stages/user_logout/stage.py b/authentik/stages/user_logout/stage.py index be1950035..e377c29f6 100644 --- a/authentik/stages/user_logout/stage.py +++ b/authentik/stages/user_logout/stage.py @@ -1,19 +1,16 @@ """Logout stage logic""" from django.contrib.auth import logout from django.http import HttpRequest, HttpResponse -from structlog.stdlib import get_logger from authentik.flows.stage import StageView -LOGGER = get_logger() - class UserLogoutStageView(StageView): """Finalise Authentication flow by logging the user in""" def get(self, request: HttpRequest) -> HttpResponse: """Remove the user from the current session""" - LOGGER.debug( + self.logger.debug( "Logged out", user=request.user, flow_slug=self.executor.flow.slug, diff --git a/authentik/stages/user_write/stage.py b/authentik/stages/user_write/stage.py index 63f22b133..6b5fd1af2 100644 --- a/authentik/stages/user_write/stage.py +++ b/authentik/stages/user_write/stage.py @@ -7,7 +7,6 @@ from django.db import transaction from django.db.utils import IntegrityError from django.http import HttpRequest, HttpResponse from django.utils.translation import gettext as _ -from structlog.stdlib import get_logger from authentik.core.middleware import SESSION_KEY_IMPERSONATE_USER from authentik.core.models import USER_ATTRIBUTE_SOURCES, User, UserSourceConnection @@ -19,7 +18,6 @@ from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT from authentik.stages.user_write.signals import user_write -LOGGER = get_logger() PLAN_CONTEXT_GROUPS = "groups" @@ -56,7 +54,7 @@ class UserWriteStageView(StageView): is_active=not self.executor.current_stage.create_users_as_inactive ) self.executor.plan.context[PLAN_CONTEXT_AUTHENTICATION_BACKEND] = BACKEND_INBUILT - LOGGER.debug( + self.logger.debug( "Created new user", flow_slug=self.executor.flow.slug, ) @@ -86,7 +84,7 @@ class UserWriteStageView(StageView): # `attribute_`, to prevent accidentally saving values else: if not key.startswith("attributes.") and not key.startswith("attributes_"): - LOGGER.debug("discarding key", key=key) + self.logger.debug("discarding key", key=key) continue UserWriteStageView.write_attribute(user, key, value) # Check if we're writing from a source, and save the source to the attributes @@ -106,7 +104,7 @@ class UserWriteStageView(StageView): if PLAN_CONTEXT_PROMPT not in self.executor.plan.context: message = _("No Pending data.") messages.error(request, message) - LOGGER.debug(message) + self.logger.debug(message) return self.executor.stage_invalid() data = self.executor.plan.context[PLAN_CONTEXT_PROMPT] user, user_created = self.ensure_user() @@ -123,7 +121,7 @@ class UserWriteStageView(StageView): self.update_user(user) # Extra check to prevent flows from saving a user with a blank username if user.username == "": - LOGGER.warning("Aborting write to empty username", user=user) + self.logger.warning("Aborting write to empty username", user=user) return self.executor.stage_invalid() try: with transaction.atomic(): @@ -133,14 +131,14 @@ class UserWriteStageView(StageView): if PLAN_CONTEXT_GROUPS in self.executor.plan.context: user.ak_groups.add(*self.executor.plan.context[PLAN_CONTEXT_GROUPS]) except (IntegrityError, ValueError, TypeError) as exc: - LOGGER.warning("Failed to save user", exc=exc) + self.logger.warning("Failed to save user", exc=exc) return self.executor.stage_invalid() user_write.send(sender=self, request=request, user=user, data=data, created=user_created) # Check if the password has been updated, and update the session auth hash if should_update_session: update_session_auth_hash(self.request, user) - LOGGER.debug("Updated session hash", user=user) - LOGGER.debug( + self.logger.debug("Updated session hash", user=user) + self.logger.debug( "Updated existing user", user=user, flow_slug=self.executor.flow.slug,