start fixing tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens Langhammer 2023-02-21 21:52:30 +01:00
parent 1889e82309
commit ff996f798f
No known key found for this signature in database
10 changed files with 88 additions and 41 deletions

View File

@ -10,7 +10,6 @@ from django.db.models.functions import ExtractHour
from django.db.models.query import QuerySet
from django.db.transaction import atomic
from django.db.utils import IntegrityError
from django.urls import reverse_lazy
from django.utils.http import urlencode
from django.utils.text import slugify
from django.utils.timezone import now
@ -72,6 +71,8 @@ from authentik.flows.exceptions import FlowNonApplicableException
from authentik.flows.models import FlowToken
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlanner
from authentik.flows.views.executor import QS_KEY_TOKEN
from authentik.interfaces.models import InterfaceType
from authentik.interfaces.views import reverse_interface
from authentik.stages.email.models import EmailStage
from authentik.stages.email.tasks import send_mails
from authentik.stages.email.utils import TemplateEmailMessage
@ -350,8 +351,12 @@ class UserViewSet(UsedByMixin, ModelViewSet):
)
querystring = urlencode({QS_KEY_TOKEN: token.key})
link = self.request.build_absolute_uri(
reverse_lazy("authentik_core:if-flow", kwargs={"flow_slug": flow.slug})
+ f"?{querystring}"
reverse_interface(
self.request,
InterfaceType.FLOW,
flow_slug=flow.slug,
),
+f"?{querystring}",
)
return link, token

View File

@ -60,5 +60,5 @@ class TestImpersonation(TestCase):
response = self.client.get(reverse("authentik_core:impersonate-end"))
self.assertRedirects(
response, reverse("authentik_interfaces:if", kwargs={"if_name", "user"})
response, reverse("authentik_interfaces:if", kwargs={"if_name": "user"})
)

View File

@ -25,6 +25,8 @@ from authentik.flows.exceptions import FlowNonApplicableException
from authentik.flows.models import Flow
from authentik.flows.planner import CACHE_PREFIX, PLAN_CONTEXT_PENDING_USER, FlowPlanner, cache_key
from authentik.flows.views.executor import SESSION_KEY_HISTORY, SESSION_KEY_PLAN
from authentik.interfaces.models import InterfaceType
from authentik.interfaces.views import reverse_interface
from authentik.lib.utils.file import (
FilePathSerializer,
FileUploadSerializer,
@ -294,7 +296,10 @@ class FlowViewSet(UsedByMixin, ModelViewSet):
return Response(
{
"link": request._request.build_absolute_uri(
reverse("authentik_core:if-flow", kwargs={"flow_slug": flow.slug})
reverse_interface(
InterfaceType.FLOW,
flow_slug=flow.slug,
),
)
}
)

View File

@ -7,6 +7,8 @@ from authentik.core.tests.utils import create_test_flow
from authentik.flows.models import Flow, FlowDesignation
from authentik.flows.planner import FlowPlan
from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE, SESSION_KEY_PLAN
from authentik.interfaces.models import InterfaceType
from authentik.interfaces.tests import reverse_interface
from authentik.lib.generators import generate_id
from authentik.providers.oauth2.models import OAuth2Provider
@ -21,7 +23,10 @@ class TestHelperView(TestCase):
response = self.client.get(
reverse("authentik_flows:default-invalidation"),
)
expected_url = reverse("authentik_core:if-flow", kwargs={"flow_slug": flow.slug})
expected_url = reverse_interface(
InterfaceType.FLOW,
flow_slug=flow.slug,
)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, expected_url)
@ -72,6 +77,9 @@ class TestHelperView(TestCase):
response = self.client.get(
reverse("authentik_flows:default-invalidation"),
)
expected_url = reverse("authentik_core:if-flow", kwargs={"flow_slug": flow.slug})
expected_url = reverse_interface(
InterfaceType.FLOW,
flow_slug=flow.slug,
)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, expected_url)

View File

@ -25,3 +25,4 @@ class InterfaceViewSet(UsedByMixin, ModelViewSet):
queryset = Interface.objects.all()
serializer_class = InterfaceSerializer
filterset_fields = ["url_name", "type", "template"]
search_fields = ["url_name", "type", "template"]

View File

@ -0,0 +1,12 @@
"""Interface tests"""
from django.test import RequestFactory
from authentik.interfaces.models import InterfaceType
from authentik.interfaces.views import reverse_interface as full_reverse_interface
def reverse_interface(interface_type: InterfaceType, **kwargs):
"""reverse_interface wrapper for tests"""
factory = RequestFactory()
request = factory.get("/")
return full_reverse_interface(request, interface_type, **kwargs)

View File

@ -1,11 +1,13 @@
"""Interface views"""
from json import dumps
from typing import Any, Optional
from urllib.parse import urlencode
from django.http import Http404, HttpRequest, HttpResponse
from django.shortcuts import get_object_or_404
from django.shortcuts import get_object_or_404, redirect
from django.template import Template, TemplateSyntaxError, engines
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.cache import cache_page
@ -40,30 +42,37 @@ def redirect_to_default_interface(request: HttpRequest, interface_type: Interfac
return RedirectToInterface.as_view(type=interface_type)(request, **kwargs)
def reverse_interface(request: HttpRequest, interface_type: InterfaceType, **kwargs):
"""Reverse URL to configured default interface"""
tenant: Tenant = request.tenant
interface: Interface = None
if interface_type == InterfaceType.USER:
interface = tenant.interface_user
if interface_type == InterfaceType.ADMIN:
interface = tenant.interface_admin
if interface_type == InterfaceType.FLOW:
interface = tenant.interface_flow
if not interface:
raise Http404()
kwargs["if_name"] = interface.url_name
return reverse(
"authentik_interfaces:if",
kwargs=kwargs,
)
class RedirectToInterface(View):
"""Redirect to tenant's configured view for specified type"""
type: Optional[InterfaceType] = None
def dispatch(self, request: HttpRequest, **kwargs: Any) -> HttpResponse:
tenant: Tenant = request.tenant
interface: Interface = None
if self.type == InterfaceType.USER:
interface = tenant.interface_user
if self.type == InterfaceType.ADMIN:
interface = tenant.interface_admin
if self.type == InterfaceType.FLOW:
interface = tenant.interface_flow
if not interface:
raise Http404()
return redirect_with_qs(
"authentik_interfaces:if",
self.request.GET,
if_name=interface.url_name,
**kwargs,
)
target = reverse_interface(request, self.type, **kwargs)
if self.request.GET:
target += "?" + urlencode(self.request.GET.items())
return redirect(target)
@method_decorator(ensure_csrf_cookie, name="dispatch")

View File

@ -16,6 +16,8 @@ from authentik.flows.models import FlowToken
from authentik.flows.planner import PLAN_CONTEXT_IS_RESTORED, PLAN_CONTEXT_PENDING_USER
from authentik.flows.stage import ChallengeStageView
from authentik.flows.views.executor import QS_KEY_TOKEN
from authentik.interfaces.models import InterfaceType
from authentik.interfaces.views import reverse_interface
from authentik.stages.email.models import EmailStage
from authentik.stages.email.tasks import send_mails
from authentik.stages.email.utils import TemplateEmailMessage
@ -47,9 +49,10 @@ class EmailStageView(ChallengeStageView):
def get_full_url(self, **kwargs) -> str:
"""Get full URL to be used in template"""
base_url = reverse(
"authentik_core:if-flow",
kwargs={"flow_slug": self.executor.flow.slug},
base_url = reverse_interface(
self.request,
InterfaceType.FLOW,
flow_slug=self.executor.flow.slug,
)
relative_url = f"{base_url}?{urlencode(kwargs)}"
return self.request.build_absolute_uri(relative_url)

View File

@ -5,6 +5,8 @@ from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.flows.challenge import ChallengeTypes
from authentik.flows.models import FlowDesignation, FlowStageBinding
from authentik.flows.tests import FlowTestCase
from authentik.interfaces.models import InterfaceType
from authentik.interfaces.tests import reverse_interface
from authentik.sources.oauth.models import OAuthSource
from authentik.stages.identification.models import IdentificationStage, UserFields
from authentik.stages.password import BACKEND_INBUILT
@ -166,9 +168,9 @@ class TestIdentificationStage(FlowTestCase):
component="ak-stage-identification",
user_fields=["email"],
password_fields=False,
enroll_url=reverse(
"authentik_core:if-flow",
kwargs={"flow_slug": flow.slug},
enroll_url=reverse_interface(
InterfaceType.FLOW,
flow_slug=flow.slug,
),
show_source_labels=False,
primary_action="Log in",
@ -204,9 +206,9 @@ class TestIdentificationStage(FlowTestCase):
component="ak-stage-identification",
user_fields=["email"],
password_fields=False,
recovery_url=reverse(
"authentik_core:if-flow",
kwargs={"flow_slug": flow.slug},
recovery_url=reverse_interface(
InterfaceType.FLOW,
flow_slug=flow.slug,
),
show_source_labels=False,
primary_action="Log in",

View File

@ -5,7 +5,6 @@ from django.contrib.auth import _clean_credentials
from django.contrib.auth.backends import BaseBackend
from django.core.exceptions import PermissionDenied
from django.http import HttpRequest, HttpResponse
from django.urls import reverse
from django.utils.translation import gettext as _
from rest_framework.exceptions import ErrorDetail, ValidationError
from rest_framework.fields import CharField
@ -23,6 +22,8 @@ from authentik.flows.challenge import (
from authentik.flows.models import Flow, FlowDesignation, Stage
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
from authentik.flows.stage import ChallengeStageView
from authentik.interfaces.models import InterfaceType
from authentik.interfaces.views import reverse_interface
from authentik.lib.utils.reflection import path_to_class
from authentik.stages.password.models import PasswordStage
@ -95,11 +96,12 @@ class PasswordStageView(ChallengeStageView):
"type": ChallengeTypes.NATIVE.value,
}
)
recovery_flow = Flow.objects.filter(designation=FlowDesignation.RECOVERY)
if recovery_flow.exists():
recover_url = reverse(
"authentik_core:if-flow",
kwargs={"flow_slug": recovery_flow.first().slug},
recovery_flow = Flow.objects.filter(designation=FlowDesignation.RECOVERY).first()
if recovery_flow:
recover_url = reverse_interface(
self.request,
InterfaceType.FLOW,
flow_slug=recovery_flow.slug,
)
challenge.initial_data["recovery_url"] = self.request.build_absolute_uri(recover_url)
return challenge