diff --git a/authentik/core/sources/stage.py b/authentik/core/sources/stage.py index bcc37adf0..3eb3b0a5c 100644 --- a/authentik/core/sources/stage.py +++ b/authentik/core/sources/stage.py @@ -28,3 +28,7 @@ class PostUserEnrollmentStage(StageView): source=connection.source, ).from_http(self.request) return self.executor.stage_ok() + + def post(self, request: HttpRequest) -> HttpResponse: + """Wrapper for post requests""" + return self.get(request) diff --git a/authentik/flows/tests/test_stage_views.py b/authentik/flows/tests/test_stage_views.py new file mode 100644 index 000000000..1b721fa65 --- /dev/null +++ b/authentik/flows/tests/test_stage_views.py @@ -0,0 +1,31 @@ +"""stage view tests""" +from typing import Callable, Type + +from django.test import RequestFactory, TestCase + +from authentik.flows.stage import StageView +from authentik.flows.views import FlowExecutorView +from authentik.lib.utils.reflection import all_subclasses + + +class TestViews(TestCase): + """Generic model properties tests""" + + def setUp(self) -> None: + self.factory = RequestFactory() + self.exec = FlowExecutorView(self.factory.request("/")) + + +def view_tester_factory(view: Type[StageView]) -> Callable: + """Test a form""" + + def tester(self: TestViews): + model_class = view(self.exec) + self.assertIsNotNone(model_class.post) + self.assertIsNotNone(model_class.get) + + return tester + + +for view in all_subclasses(StageView): + setattr(TestViews, f"test_view_{view.__name__}", view_tester_factory(view)) diff --git a/authentik/stages/deny/stage.py b/authentik/stages/deny/stage.py index 82c433058..1620cee16 100644 --- a/authentik/stages/deny/stage.py +++ b/authentik/stages/deny/stage.py @@ -13,3 +13,7 @@ class DenyStageView(StageView): def get(self, request: HttpRequest) -> HttpResponse: """Cancells the current flow""" return self.executor.stage_invalid() + + def post(self, request: HttpRequest) -> HttpResponse: + """Wrapper for post requests""" + return self.get(request) diff --git a/authentik/stages/invitation/stage.py b/authentik/stages/invitation/stage.py index 0042feb2a..364b77816 100644 --- a/authentik/stages/invitation/stage.py +++ b/authentik/stages/invitation/stage.py @@ -23,6 +23,10 @@ INVITATION = "invitation" class InvitationStageView(StageView): """Finalise Authentication flow by logging the user in""" + def post(self, request: HttpRequest) -> HttpResponse: + """Wrapper for post requests""" + return self.get(request) + def get_token(self) -> Optional[str]: """Get token from saved get-arguments or prompt_data""" if INVITATION_TOKEN_KEY in self.request.session.get(SESSION_KEY_GET, {}): diff --git a/authentik/stages/user_delete/stage.py b/authentik/stages/user_delete/stage.py index 15945dbe2..f57f8d659 100644 --- a/authentik/stages/user_delete/stage.py +++ b/authentik/stages/user_delete/stage.py @@ -14,6 +14,10 @@ LOGGER = get_logger() class UserDeleteStageView(StageView): """Finalise unenrollment flow by deleting the user object.""" + def post(self, request: HttpRequest) -> HttpResponse: + """Wrapper for post requests""" + return self.get(request) + def get(self, request: HttpRequest) -> HttpResponse: """Delete currently pending user""" if PLAN_CONTEXT_PENDING_USER not in self.executor.plan.context: diff --git a/authentik/stages/user_login/stage.py b/authentik/stages/user_login/stage.py index 568aa8885..d545d8559 100644 --- a/authentik/stages/user_login/stage.py +++ b/authentik/stages/user_login/stage.py @@ -18,6 +18,10 @@ USER_LOGIN_AUTHENTICATED = "user_login_authenticated" class UserLoginStageView(StageView): """Finalise Authentication flow by logging the user in""" + def post(self, request: HttpRequest) -> HttpResponse: + """Wrapper for post requests""" + return self.get(request) + def get(self, request: HttpRequest) -> HttpResponse: """Attach the currently pending user to the current session""" if PLAN_CONTEXT_PENDING_USER not in self.executor.plan.context: diff --git a/authentik/stages/user_logout/stage.py b/authentik/stages/user_logout/stage.py index 1302d2183..be1950035 100644 --- a/authentik/stages/user_logout/stage.py +++ b/authentik/stages/user_logout/stage.py @@ -20,3 +20,7 @@ class UserLogoutStageView(StageView): ) logout(self.request) return self.executor.stage_ok() + + def post(self, request: HttpRequest) -> HttpResponse: + """Wrapper for post requests""" + return self.get(request)