stages/email: add wrapper view to accept queryargs and redirects to flow if

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-03-23 19:41:20 +01:00
parent fa5f379a53
commit 62d0e020db
5 changed files with 43 additions and 9 deletions

View File

@ -16,6 +16,7 @@ class AuthentikStageEmailConfig(AppConfig):
name = "authentik.stages.email" name = "authentik.stages.email"
label = "authentik_stages_email" label = "authentik_stages_email"
verbose_name = "authentik Stages.Email" verbose_name = "authentik Stages.Email"
mountpoint = "stages/email/"
def ready(self): def ready(self):
import_module("authentik.stages.email.tasks") import_module("authentik.stages.email.tasks")

View File

@ -45,7 +45,7 @@ class EmailStageView(ChallengeStageView):
def get_full_url(self, **kwargs) -> str: def get_full_url(self, **kwargs) -> str:
"""Get full URL to be used in template""" """Get full URL to be used in template"""
base_url = reverse( base_url = reverse(
"authentik_core:if-flow", "authentik_stages_email:from-email",
kwargs={"flow_slug": self.executor.flow.slug}, kwargs={"flow_slug": self.executor.flow.slug},
) )
relative_url = f"{base_url}?{urlencode(kwargs)}" relative_url = f"{base_url}?{urlencode(kwargs)}"

View File

@ -7,7 +7,6 @@ from django.urls import reverse
from django.utils.encoding import force_str from django.utils.encoding import force_str
from authentik.core.models import Token, User from authentik.core.models import Token, User
from authentik.flows.challenge import ChallengeTypes
from authentik.flows.markers import StageMarker from authentik.flows.markers import StageMarker
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
@ -110,7 +109,7 @@ class TestEmailStage(TestCase):
with patch("authentik.flows.views.FlowExecutorView.cancel", MagicMock()): with patch("authentik.flows.views.FlowExecutorView.cancel", MagicMock()):
# Call the executor shell to preseed the session # Call the executor shell to preseed the session
url = reverse( url = reverse(
"authentik_core:if-flow", "authentik_stages_email:from-email",
kwargs={"flow_slug": self.flow.slug}, kwargs={"flow_slug": self.flow.slug},
) )
token = Token.objects.get(user=self.user) token = Token.objects.get(user=self.user)
@ -127,12 +126,7 @@ class TestEmailStage(TestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertJSONEqual( self.assertJSONEqual(
force_str(response.content), force_str(response.content),
{ {"to": reverse("authentik_core:root-redirect"), "type": "redirect"},
"component": "ak-stage-access-denied",
"error_message": None,
"title": "",
"type": ChallengeTypes.native.value,
},
) )
session = self.client.session session = self.client.session

View File

@ -0,0 +1,8 @@
"""Email stage url patterns"""
from django.urls import path
from authentik.stages.email.views import FromEmailView
urlpatterns = [
path("from-email/<slug:flow_slug>/", FromEmailView.as_view(), name="from-email"),
]

View File

@ -0,0 +1,31 @@
"""Email stage views"""
from django.http.request import HttpRequest
from django.http.response import HttpResponse, HttpResponseBadRequest
from django.shortcuts import get_object_or_404, redirect
from django.views import View
from structlog.stdlib import get_logger
from authentik.core.models import Token
from authentik.flows.views import SESSION_KEY_GET
from authentik.stages.email.stage import QS_KEY_TOKEN
LOGGER = get_logger()
class FromEmailView(View):
"""FromEmailView, this view is linked in the email confirmation link.
It is required because the flow executor does not pass query args to the API,
so this view gets called, checks for a Querystring and updates the plan
if everything is valid."""
def get(self, request: HttpRequest, flow_slug: str) -> HttpResponse:
"""Check for ?token param and validate it."""
if QS_KEY_TOKEN not in request.GET:
LOGGER.debug("No token set")
return HttpResponseBadRequest()
# Lookup token here to quickly fail for invalid input
get_object_or_404(Token, pk=request.GET[QS_KEY_TOKEN])
if SESSION_KEY_GET not in request.session:
request.session[SESSION_KEY_GET] = {}
request.session[SESSION_KEY_GET][QS_KEY_TOKEN] = request.GET[QS_KEY_TOKEN]
return redirect("authentik_core:if-flow", flow_slug=flow_slug)