flows: add get_pending_user() for WithUserInfoChallenge

This commit is contained in:
Jens Langhammer 2021-02-21 18:30:40 +01:00
parent 27cd10e072
commit 88e5b22d16
4 changed files with 38 additions and 27 deletions

View file

@ -1,6 +1,5 @@
"""authentik stage Base view""" """authentik stage Base view"""
from collections import namedtuple from typing import Any, Optional
from typing import Any
from django.http import HttpRequest from django.http import HttpRequest
from django.http.request import QueryDict from django.http.request import QueryDict
@ -9,6 +8,7 @@ from django.utils.translation import gettext_lazy as _
from django.views.generic import TemplateView from django.views.generic import TemplateView
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from authentik.core.models import User
from authentik.flows.challenge import ( from authentik.flows.challenge import (
Challenge, Challenge,
ChallengeResponse, ChallengeResponse,
@ -20,8 +20,6 @@ from authentik.flows.views import FlowExecutorView
PLAN_CONTEXT_PENDING_USER_IDENTIFIER = "pending_user_identifier" PLAN_CONTEXT_PENDING_USER_IDENTIFIER = "pending_user_identifier"
LOGGER = get_logger() LOGGER = get_logger()
FakeUser = namedtuple("User", ["username", "email"])
class StageView(TemplateView): class StageView(TemplateView):
"""Abstract Stage, inherits TemplateView but can be combined with FormView""" """Abstract Stage, inherits TemplateView but can be combined with FormView"""
@ -44,7 +42,7 @@ class StageView(TemplateView):
if PLAN_CONTEXT_PENDING_USER in self.executor.plan.context: if PLAN_CONTEXT_PENDING_USER in self.executor.plan.context:
kwargs["user"] = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] kwargs["user"] = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER]
if PLAN_CONTEXT_PENDING_USER_IDENTIFIER in self.executor.plan.context: if PLAN_CONTEXT_PENDING_USER_IDENTIFIER in self.executor.plan.context:
kwargs["user"] = FakeUser( kwargs["user"] = User(
username=self.executor.plan.context.get( username=self.executor.plan.context.get(
PLAN_CONTEXT_PENDING_USER_IDENTIFIER PLAN_CONTEXT_PENDING_USER_IDENTIFIER
), ),
@ -59,6 +57,22 @@ class ChallengeStageView(StageView):
response_class = ChallengeResponse response_class = ChallengeResponse
def get_pending_user(self) -> Optional[User]:
"""Either show the matched User object or show what the user entered,
based on what the earlier stage (mostly IdentificationStage) set.
_USER_IDENTIFIER overrides the first User, as PENDING_USER is used for
other things besides the form display"""
if PLAN_CONTEXT_PENDING_USER_IDENTIFIER in self.executor.plan.context:
return User(
username=self.executor.plan.context.get(
PLAN_CONTEXT_PENDING_USER_IDENTIFIER
),
email="",
)
if PLAN_CONTEXT_PENDING_USER in self.executor.plan.context:
return self.executor.plan.context[PLAN_CONTEXT_PENDING_USER]
return None
def get_response_instance(self, data: QueryDict) -> ChallengeResponse: def get_response_instance(self, data: QueryDict) -> ChallengeResponse:
"""Return the response class type""" """Return the response class type"""
return self.response_class(None, data=data, stage=self) return self.response_class(None, data=data, stage=self)

View file

@ -3,7 +3,6 @@ from django.http import HttpRequest, HttpResponse
from django.utils.timezone import now from django.utils.timezone import now
from rest_framework.fields import CharField from rest_framework.fields import CharField
from authentik.core.models import User
from authentik.flows.challenge import ( from authentik.flows.challenge import (
Challenge, Challenge,
ChallengeResponse, ChallengeResponse,
@ -55,10 +54,9 @@ class ConsentStageView(ChallengeStageView):
# If there's a pending user, update the `username` field # If there's a pending user, update the `username` field
# this field is only used by password managers. # this field is only used by password managers.
# If there's no user set, an error is raised later. # If there's no user set, an error is raised later.
if PLAN_CONTEXT_PENDING_USER in self.executor.plan.context: if user := self.get_pending_user():
pending_user: User = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] challenge.initial_data["pending_user"] = user.username
challenge.initial_data["pending_user"] = pending_user.username challenge.initial_data["pending_user_avatar"] = avatar(user)
challenge.initial_data["pending_user_avatar"] = avatar(pending_user)
return challenge return challenge
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:

View file

@ -86,10 +86,9 @@ class PasswordStageView(ChallengeStageView):
# If there's a pending user, update the `username` field # If there's a pending user, update the `username` field
# this field is only used by password managers. # this field is only used by password managers.
# If there's no user set, an error is raised later. # If there's no user set, an error is raised later.
if PLAN_CONTEXT_PENDING_USER in self.executor.plan.context: if user := self.get_pending_user():
pending_user: User = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] challenge.initial_data["pending_user"] = user.username
challenge.initial_data["pending_user"] = pending_user.username challenge.initial_data["pending_user_avatar"] = avatar(user)
challenge.initial_data["pending_user_avatar"] = avatar(pending_user)
recovery_flow = Flow.objects.filter(designation=FlowDesignation.RECOVERY) recovery_flow = Flow.objects.filter(designation=FlowDesignation.RECOVERY)
if recovery_flow.exists(): if recovery_flow.exists():

View file

@ -9657,22 +9657,22 @@ definitions:
- authentik.sources.ldap - authentik.sources.ldap
- authentik.sources.oauth - authentik.sources.oauth
- authentik.sources.saml - authentik.sources.saml
- authentik.stages.captcha
- authentik.stages.consent
- authentik.stages.dummy
- authentik.stages.email
- authentik.stages.prompt
- authentik.stages.identification
- authentik.stages.invitation
- authentik.stages.user_delete
- authentik.stages.user_login
- authentik.stages.user_logout
- authentik.stages.user_write
- authentik.stages.authenticator_static - authentik.stages.authenticator_static
- authentik.stages.authenticator_totp - authentik.stages.authenticator_totp
- authentik.stages.authenticator_validate - authentik.stages.authenticator_validate
- authentik.stages.authenticator_webauthn - authentik.stages.authenticator_webauthn
- authentik.stages.captcha
- authentik.stages.consent
- authentik.stages.dummy
- authentik.stages.email
- authentik.stages.identification
- authentik.stages.invitation
- authentik.stages.password - authentik.stages.password
- authentik.stages.prompt
- authentik.stages.user_delete
- authentik.stages.user_login
- authentik.stages.user_logout
- authentik.stages.user_write
- authentik.managed - authentik.managed
- authentik.core - authentik.core
ExpressionPolicy: ExpressionPolicy:
@ -11742,8 +11742,8 @@ definitions:
- password - password
- number - number
- checkbox - checkbox
- data - date
- data-time - date-time
- separator - separator
- hidden - hidden
- static - static