stages/identification: add show_matched_user to optionally hide user details
This commit is contained in:
parent
58497bb63f
commit
ff15514d5b
|
@ -1,4 +1,5 @@
|
||||||
"""authentik stage Base view"""
|
"""authentik stage Base view"""
|
||||||
|
from collections import namedtuple
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
|
@ -8,6 +9,10 @@ from django.views.generic import TemplateView
|
||||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||||
from authentik.flows.views import FlowExecutorView
|
from authentik.flows.views import FlowExecutorView
|
||||||
|
|
||||||
|
PLAN_CONTEXT_PENDING_USER_IDENTIFIER = "pending_user_identifier"
|
||||||
|
|
||||||
|
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"""
|
||||||
|
@ -21,9 +26,20 @@ class StageView(TemplateView):
|
||||||
def __init__(self, executor: FlowExecutorView):
|
def __init__(self, executor: FlowExecutorView):
|
||||||
self.executor = executor
|
self.executor = executor
|
||||||
|
|
||||||
def get_context_data(self, **kwargs: Dict[str, Any]) -> Dict[str, Any]:
|
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
|
||||||
kwargs["title"] = self.executor.flow.title
|
kwargs["title"] = self.executor.flow.title
|
||||||
|
# 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 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:
|
||||||
|
kwargs["user"] = FakeUser(
|
||||||
|
username=self.executor.plan.context.get(
|
||||||
|
PLAN_CONTEXT_PENDING_USER_IDENTIFIER
|
||||||
|
),
|
||||||
|
email="",
|
||||||
|
)
|
||||||
kwargs["primary_action"] = _("Continue")
|
kwargs["primary_action"] = _("Continue")
|
||||||
return super().get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
|
@ -18,6 +18,7 @@ register = template.Library()
|
||||||
LOGGER = get_logger()
|
LOGGER = get_logger()
|
||||||
|
|
||||||
GRAVATAR_URL = "https://secure.gravatar.com"
|
GRAVATAR_URL = "https://secure.gravatar.com"
|
||||||
|
DEFAULT_AVATAR = static("authentik/user_default.png")
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
|
@ -62,7 +63,7 @@ def avatar(user: User) -> str:
|
||||||
"""Get avatar, depending on authentik.avatar setting"""
|
"""Get avatar, depending on authentik.avatar setting"""
|
||||||
mode = CONFIG.raw.get("authentik").get("avatars")
|
mode = CONFIG.raw.get("authentik").get("avatars")
|
||||||
if mode == "none":
|
if mode == "none":
|
||||||
return static("authentik/user_default.png")
|
return DEFAULT_AVATAR
|
||||||
if mode == "gravatar":
|
if mode == "gravatar":
|
||||||
parameters = [
|
parameters = [
|
||||||
("s", "158"),
|
("s", "158"),
|
||||||
|
|
|
@ -16,6 +16,7 @@ class IdentificationStageSerializer(ModelSerializer):
|
||||||
"name",
|
"name",
|
||||||
"user_fields",
|
"user_fields",
|
||||||
"case_insensitive_matching",
|
"case_insensitive_matching",
|
||||||
|
"show_matched_user",
|
||||||
"template",
|
"template",
|
||||||
"enrollment_flow",
|
"enrollment_flow",
|
||||||
"recovery_flow",
|
"recovery_flow",
|
||||||
|
|
|
@ -31,6 +31,7 @@ class IdentificationStageForm(forms.ModelForm):
|
||||||
"name",
|
"name",
|
||||||
"user_fields",
|
"user_fields",
|
||||||
"case_insensitive_matching",
|
"case_insensitive_matching",
|
||||||
|
"show_matched_user",
|
||||||
"template",
|
"template",
|
||||||
"enrollment_flow",
|
"enrollment_flow",
|
||||||
"recovery_flow",
|
"recovery_flow",
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Generated by Django 3.1.4 on 2020-12-06 11:55
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("authentik_stages_identification", "0005_auto_20201003_1734"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="identificationstage",
|
||||||
|
name="show_matched_user",
|
||||||
|
field=models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
help_text="When a valid username/email has been entered, and this option is enabled, the user's username and avatar will be shown. Otherwise, the text that the user entered will be shown",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -45,6 +45,16 @@ class IdentificationStage(Stage):
|
||||||
"When enabled, user fields are matched regardless of their casing."
|
"When enabled, user fields are matched regardless of their casing."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
show_matched_user = models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
help_text=_(
|
||||||
|
(
|
||||||
|
"When a valid username/email has been entered, and this option is enabled, "
|
||||||
|
"the user's username and avatar will be shown. Otherwise, the text that the user "
|
||||||
|
"entered will be shown"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
enrollment_flow = models.ForeignKey(
|
enrollment_flow = models.ForeignKey(
|
||||||
Flow,
|
Flow,
|
||||||
|
|
|
@ -11,7 +11,7 @@ from structlog import get_logger
|
||||||
|
|
||||||
from authentik.core.models import Source, User
|
from authentik.core.models import Source, User
|
||||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||||
from authentik.flows.stage import StageView
|
from authentik.flows.stage import PLAN_CONTEXT_PENDING_USER_IDENTIFIER, StageView
|
||||||
from authentik.flows.views import SESSION_KEY_APPLICATION_PRE
|
from authentik.flows.views import SESSION_KEY_APPLICATION_PRE
|
||||||
from authentik.stages.identification.forms import IdentificationForm
|
from authentik.stages.identification.forms import IdentificationForm
|
||||||
from authentik.stages.identification.models import IdentificationStage
|
from authentik.stages.identification.models import IdentificationStage
|
||||||
|
@ -84,10 +84,18 @@ class IdentificationStageView(FormView, StageView):
|
||||||
|
|
||||||
def form_valid(self, form: IdentificationForm) -> HttpResponse:
|
def form_valid(self, form: IdentificationForm) -> HttpResponse:
|
||||||
"""Form data is valid"""
|
"""Form data is valid"""
|
||||||
pre_user = self.get_user(form.cleaned_data.get("uid_field"))
|
user_identifier = form.cleaned_data.get("uid_field")
|
||||||
|
pre_user = self.get_user(user_identifier)
|
||||||
if not pre_user:
|
if not pre_user:
|
||||||
LOGGER.debug("invalid_login")
|
LOGGER.debug("invalid_login")
|
||||||
messages.error(self.request, _("Failed to authenticate."))
|
messages.error(self.request, _("Failed to authenticate."))
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] = pre_user
|
self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] = pre_user
|
||||||
|
|
||||||
|
current_stage: IdentificationStage = self.executor.current_stage
|
||||||
|
if not current_stage.show_matched_user:
|
||||||
|
self.executor.plan.context[
|
||||||
|
PLAN_CONTEXT_PENDING_USER_IDENTIFIER
|
||||||
|
] = user_identifier
|
||||||
|
|
||||||
return self.executor.stage_ok()
|
return self.executor.stage_ok()
|
||||||
|
|
|
@ -8278,6 +8278,12 @@ definitions:
|
||||||
title: Case insensitive matching
|
title: Case insensitive matching
|
||||||
description: When enabled, user fields are matched regardless of their casing.
|
description: When enabled, user fields are matched regardless of their casing.
|
||||||
type: boolean
|
type: boolean
|
||||||
|
show_matched_user:
|
||||||
|
title: Show matched user
|
||||||
|
description: When a valid username/email has been entered, and this option
|
||||||
|
is enabled, the user's username and avatar will be shown. Otherwise, the
|
||||||
|
text that the user entered will be shown
|
||||||
|
type: boolean
|
||||||
template:
|
template:
|
||||||
title: Template
|
title: Template
|
||||||
type: string
|
type: string
|
||||||
|
|
Reference in New Issue