From 17d33f4b191a9f4fdb164fb4e52b585e390ebf3c Mon Sep 17 00:00:00 2001 From: Jens L Date: Sat, 2 Jul 2022 17:37:57 +0200 Subject: [PATCH] flows: denied action (#3194) --- .vscode/tasks.json | 10 ++ authentik/core/tests/utils.py | 9 +- authentik/flows/api/flows.py | 5 +- .../migrations/0023_flow_denied_action.py | 26 +++ authentik/flows/models.py | 32 ++-- authentik/flows/tests/test_executor.py | 149 ++++++++++-------- authentik/flows/views/executor.py | 37 ++++- authentik/lib/utils/errors.py | 14 +- locale/en/LC_MESSAGES/django.po | 96 +++++------ schema.yml | 30 ++++ web/src/locales/de.po | 28 +++- web/src/locales/en.po | 28 +++- web/src/locales/es.po | 28 +++- web/src/locales/fr_FR.po | 28 +++- web/src/locales/pl.po | 28 +++- web/src/locales/pseudo-LOCALE.po | 28 +++- web/src/locales/tr.po | 28 +++- web/src/locales/zh-Hans.po | 28 +++- web/src/locales/zh-Hant.po | 28 +++- web/src/locales/zh_TW.po | 28 +++- web/src/pages/flows/FlowForm.ts | 34 ++++ web/src/pages/flows/StageBindingForm.ts | 2 +- website/docs/flow/index.md | 8 + 23 files changed, 564 insertions(+), 168 deletions(-) create mode 100644 authentik/flows/migrations/0023_flow_denied_action.py diff --git a/.vscode/tasks.json b/.vscode/tasks.json index fb2b880fe..cd705afff 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -46,6 +46,16 @@ "args": ["install"], "group": "build", }, + { + "label": "authentik: i18n-extract", + "command": "poetry", + "args": [ + "run", + "make", + "i18n-extract" + ], + "group": "build", + }, { "label": "authentik[website]: format", "command": "make", diff --git a/authentik/core/tests/utils.py b/authentik/core/tests/utils.py index 84ef0845e..7ce92e8d4 100644 --- a/authentik/core/tests/utils.py +++ b/authentik/core/tests/utils.py @@ -11,14 +11,13 @@ from authentik.lib.generators import generate_id from authentik.tenants.models import Tenant -def create_test_flow(designation: FlowDesignation = FlowDesignation.STAGE_CONFIGURATION) -> Flow: +def create_test_flow( + designation: FlowDesignation = FlowDesignation.STAGE_CONFIGURATION, **kwargs +) -> Flow: """Generate a flow that can be used for testing""" uid = generate_id(10) return Flow.objects.create( - name=uid, - title=uid, - slug=slugify(uid), - designation=designation, + name=uid, title=uid, slug=slugify(uid), designation=designation, **kwargs ) diff --git a/authentik/flows/api/flows.py b/authentik/flows/api/flows.py index 5d84f493c..bbb0e49c0 100644 --- a/authentik/flows/api/flows.py +++ b/authentik/flows/api/flows.py @@ -73,6 +73,7 @@ class FlowSerializer(ModelSerializer): "compatibility_mode", "export_url", "layout", + "denied_action", ] extra_kwargs = { "background": {"read_only": True}, @@ -110,8 +111,8 @@ class FlowViewSet(UsedByMixin, ModelViewSet): serializer_class = FlowSerializer lookup_field = "slug" ordering = ["slug", "name"] - search_fields = ["name", "slug", "designation", "title"] - filterset_fields = ["flow_uuid", "name", "slug", "designation"] + search_fields = ["name", "slug", "designation", "title", "denied_action"] + filterset_fields = ["flow_uuid", "name", "slug", "designation", "denied_action"] @permission_required(None, ["authentik_flows.view_flow_cache"]) @extend_schema(responses={200: CacheSerializer(many=False)}) diff --git a/authentik/flows/migrations/0023_flow_denied_action.py b/authentik/flows/migrations/0023_flow_denied_action.py new file mode 100644 index 000000000..580d2f00e --- /dev/null +++ b/authentik/flows/migrations/0023_flow_denied_action.py @@ -0,0 +1,26 @@ +# Generated by Django 4.0.5 on 2022-07-02 12:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_flows", "0022_flow_layout"), + ] + + operations = [ + migrations.AddField( + model_name="flow", + name="denied_action", + field=models.TextField( + choices=[ + ("message_continue", "Message Continue"), + ("message", "Message"), + ("continue", "Continue"), + ], + default="message_continue", + help_text="Configure what should happen when a flow denies access to a user.", + ), + ), + ] diff --git a/authentik/flows/models.py b/authentik/flows/models.py index b1645ce37..d7e5ba39d 100644 --- a/authentik/flows/models.py +++ b/authentik/flows/models.py @@ -5,7 +5,6 @@ from typing import TYPE_CHECKING, Optional from uuid import uuid4 from django.db import models -from django.http import HttpRequest from django.utils.translation import gettext_lazy as _ from model_utils.managers import InheritanceManager from rest_framework.serializers import BaseSerializer @@ -40,6 +39,14 @@ class InvalidResponseAction(models.TextChoices): RESTART_WITH_CONTEXT = "restart_with_context" +class FlowDeniedAction(models.TextChoices): + """Configure what response is given to denied flow executions""" + + MESSAGE_CONTINUE = "message_continue" + MESSAGE = "message" + CONTINUE = "continue" + + class FlowDesignation(models.TextChoices): """Designation of what a Flow should be used for. At a later point, this should be replaced by a database entry.""" @@ -139,6 +146,12 @@ class Flow(SerializerModel, PolicyBindingModel): ), ) + denied_action = models.TextField( + choices=FlowDeniedAction.choices, + default=FlowDeniedAction.MESSAGE_CONTINUE, + help_text=_("Configure what should happen when a flow denies access to a user."), + ) + @property def background_url(self) -> str: """Get the URL to the background image. If the name is /static or starts with http @@ -157,23 +170,6 @@ class Flow(SerializerModel, PolicyBindingModel): return FlowSerializer - @staticmethod - def with_policy(request: HttpRequest, **flow_filter) -> Optional["Flow"]: - """Get a Flow by `**flow_filter` and check if the request from `request` can access it.""" - from authentik.policies.engine import PolicyEngine - - flows = Flow.objects.filter(**flow_filter).order_by("slug") - for flow in flows: - engine = PolicyEngine(flow, request.user, request) - engine.build() - result = engine.result - if result.passing: - LOGGER.debug("with_policy: flow passing", flow=flow) - return flow - LOGGER.warning("with_policy: flow not passing", flow=flow, messages=result.messages) - LOGGER.debug("with_policy: no flow found", filters=flow_filter) - return None - def __str__(self) -> str: return f"Flow {self.name} ({self.slug})" diff --git a/authentik/flows/tests/test_executor.py b/authentik/flows/tests/test_executor.py index 1a017812c..4387e9d28 100644 --- a/authentik/flows/tests/test_executor.py +++ b/authentik/flows/tests/test_executor.py @@ -6,14 +6,21 @@ from django.test.client import RequestFactory from django.urls import reverse from authentik.core.models import User +from authentik.core.tests.utils import create_test_flow from authentik.flows.exceptions import FlowNonApplicableException from authentik.flows.markers import ReevaluateMarker, StageMarker -from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding, InvalidResponseAction +from authentik.flows.models import ( + FlowDeniedAction, + FlowDesignation, + FlowStageBinding, + InvalidResponseAction, +) from authentik.flows.planner import FlowPlan, FlowPlanner from authentik.flows.stage import PLAN_CONTEXT_PENDING_USER_IDENTIFIER, StageView from authentik.flows.tests import FlowTestCase from authentik.flows.views.executor import NEXT_ARG_NAME, SESSION_KEY_PLAN, FlowExecutorView from authentik.lib.config import CONFIG +from authentik.lib.generators import generate_id from authentik.policies.dummy.models import DummyPolicy from authentik.policies.models import PolicyBinding from authentik.policies.reputation.models import ReputationPolicy @@ -47,12 +54,10 @@ class TestFlowExecutor(FlowTestCase): ) def test_existing_plan_diff_flow(self): """Check that a plan for a different flow cancels the current plan""" - flow = Flow.objects.create( - name="test-existing-plan-diff", - slug="test-existing-plan-diff", - designation=FlowDesignation.AUTHENTICATION, + flow = create_test_flow( + FlowDesignation.AUTHENTICATION, ) - stage = DummyStage.objects.create(name="dummy") + stage = DummyStage.objects.create(name=generate_id()) binding = FlowStageBinding(target=flow, stage=stage, order=0) plan = FlowPlan(flow_pk=flow.pk.hex + "a", bindings=[binding], markers=[StageMarker()]) session = self.client.session @@ -77,10 +82,8 @@ class TestFlowExecutor(FlowTestCase): ) def test_invalid_non_applicable_flow(self): """Tests that a non-applicable flow returns the correct error message""" - flow = Flow.objects.create( - name="test-non-applicable", - slug="test-non-applicable", - designation=FlowDesignation.AUTHENTICATION, + flow = create_test_flow( + FlowDesignation.AUTHENTICATION, ) CONFIG.update_from_dict({"domain": "testserver"}) @@ -98,12 +101,15 @@ class TestFlowExecutor(FlowTestCase): "authentik.flows.views.executor.to_stage_response", TO_STAGE_RESPONSE_MOCK, ) - def test_invalid_empty_flow(self): - """Tests that an empty flow returns the correct error message""" - flow = Flow.objects.create( - name="test-empty", - slug="test-empty", - designation=FlowDesignation.AUTHENTICATION, + @patch( + "authentik.policies.engine.PolicyEngine.result", + POLICY_RETURN_FALSE, + ) + def test_invalid_non_applicable_flow_continue(self): + """Tests that a non-applicable flow that should redirect""" + flow = create_test_flow( + FlowDesignation.AUTHENTICATION, + denied_action=FlowDeniedAction.CONTINUE, ) CONFIG.update_from_dict({"domain": "testserver"}) @@ -119,10 +125,8 @@ class TestFlowExecutor(FlowTestCase): ) def test_invalid_flow_redirect(self): """Tests that an invalid flow still redirects""" - flow = Flow.objects.create( - name="test-empty", - slug="test-empty", - designation=FlowDesignation.AUTHENTICATION, + flow = create_test_flow( + FlowDesignation.AUTHENTICATION, ) CONFIG.update_from_dict({"domain": "testserver"}) @@ -132,18 +136,33 @@ class TestFlowExecutor(FlowTestCase): self.assertEqual(response.status_code, 302) self.assertEqual(response.url, reverse("authentik_core:root-redirect")) + @patch( + "authentik.flows.views.executor.to_stage_response", + TO_STAGE_RESPONSE_MOCK, + ) + def test_invalid_empty_flow(self): + """Tests that an empty flow returns the correct error message""" + flow = create_test_flow( + FlowDesignation.AUTHENTICATION, + ) + + CONFIG.update_from_dict({"domain": "testserver"}) + response = self.client.get( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), + ) + self.assertEqual(response.status_code, 302) + self.assertEqual(response.url, reverse("authentik_core:root-redirect")) + def test_multi_stage_flow(self): """Test a full flow with multiple stages""" - flow = Flow.objects.create( - name="test-full", - slug="test-full", - designation=FlowDesignation.AUTHENTICATION, + flow = create_test_flow( + FlowDesignation.AUTHENTICATION, ) FlowStageBinding.objects.create( - target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0 + target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0 ) FlowStageBinding.objects.create( - target=flow, stage=DummyStage.objects.create(name="dummy2"), order=1 + target=flow, stage=DummyStage.objects.create(name=generate_id()), order=1 ) exec_url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}) @@ -170,19 +189,19 @@ class TestFlowExecutor(FlowTestCase): ) def test_reevaluate_remove_last(self): """Test planner with re-evaluate (last stage is removed)""" - flow = Flow.objects.create( - name="test-default-context", - slug="test-default-context", - designation=FlowDesignation.AUTHENTICATION, + flow = create_test_flow( + FlowDesignation.AUTHENTICATION, + ) + false_policy = DummyPolicy.objects.create( + name=generate_id(), result=False, wait_min=1, wait_max=2 ) - false_policy = DummyPolicy.objects.create(result=False, wait_min=1, wait_max=2) binding = FlowStageBinding.objects.create( - target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0 + target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0 ) binding2 = FlowStageBinding.objects.create( target=flow, - stage=DummyStage.objects.create(name="dummy2"), + stage=DummyStage.objects.create(name=generate_id()), order=1, re_evaluate_policies=True, ) @@ -217,24 +236,24 @@ class TestFlowExecutor(FlowTestCase): def test_reevaluate_remove_middle(self): """Test planner with re-evaluate (middle stage is removed)""" - flow = Flow.objects.create( - name="test-default-context", - slug="test-default-context", - designation=FlowDesignation.AUTHENTICATION, + flow = create_test_flow( + FlowDesignation.AUTHENTICATION, + ) + false_policy = DummyPolicy.objects.create( + name=generate_id(), result=False, wait_min=1, wait_max=2 ) - false_policy = DummyPolicy.objects.create(result=False, wait_min=1, wait_max=2) binding = FlowStageBinding.objects.create( - target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0 + target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0 ) binding2 = FlowStageBinding.objects.create( target=flow, - stage=DummyStage.objects.create(name="dummy2"), + stage=DummyStage.objects.create(name=generate_id()), order=1, re_evaluate_policies=True, ) binding3 = FlowStageBinding.objects.create( - target=flow, stage=DummyStage.objects.create(name="dummy3"), order=2 + target=flow, stage=DummyStage.objects.create(name=generate_id()), order=2 ) PolicyBinding.objects.create(policy=false_policy, target=binding2, order=0) @@ -277,24 +296,24 @@ class TestFlowExecutor(FlowTestCase): def test_reevaluate_keep(self): """Test planner with re-evaluate (everything is kept)""" - flow = Flow.objects.create( - name="test-default-context", - slug="test-default-context", - designation=FlowDesignation.AUTHENTICATION, + flow = create_test_flow( + FlowDesignation.AUTHENTICATION, + ) + true_policy = DummyPolicy.objects.create( + name=generate_id(), result=True, wait_min=1, wait_max=2 ) - true_policy = DummyPolicy.objects.create(result=True, wait_min=1, wait_max=2) binding = FlowStageBinding.objects.create( - target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0 + target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0 ) binding2 = FlowStageBinding.objects.create( target=flow, - stage=DummyStage.objects.create(name="dummy2"), + stage=DummyStage.objects.create(name=generate_id()), order=1, re_evaluate_policies=True, ) binding3 = FlowStageBinding.objects.create( - target=flow, stage=DummyStage.objects.create(name="dummy3"), order=2 + target=flow, stage=DummyStage.objects.create(name=generate_id()), order=2 ) PolicyBinding.objects.create(policy=true_policy, target=binding2, order=0) @@ -347,30 +366,30 @@ class TestFlowExecutor(FlowTestCase): def test_reevaluate_remove_consecutive(self): """Test planner with re-evaluate (consecutive stages are removed)""" - flow = Flow.objects.create( - name="test-default-context", - slug="test-default-context", - designation=FlowDesignation.AUTHENTICATION, + flow = create_test_flow( + FlowDesignation.AUTHENTICATION, + ) + false_policy = DummyPolicy.objects.create( + name=generate_id(), result=False, wait_min=1, wait_max=2 ) - false_policy = DummyPolicy.objects.create(result=False, wait_min=1, wait_max=2) binding = FlowStageBinding.objects.create( - target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0 + target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0 ) binding2 = FlowStageBinding.objects.create( target=flow, - stage=DummyStage.objects.create(name="dummy2"), + stage=DummyStage.objects.create(name=generate_id()), order=1, re_evaluate_policies=True, ) binding3 = FlowStageBinding.objects.create( target=flow, - stage=DummyStage.objects.create(name="dummy3"), + stage=DummyStage.objects.create(name=generate_id()), order=2, re_evaluate_policies=True, ) binding4 = FlowStageBinding.objects.create( - target=flow, stage=DummyStage.objects.create(name="dummy4"), order=2 + target=flow, stage=DummyStage.objects.create(name=generate_id()), order=2 ) PolicyBinding.objects.create(policy=false_policy, target=binding2, order=0) @@ -415,13 +434,11 @@ class TestFlowExecutor(FlowTestCase): def test_stageview_user_identifier(self): """Test PLAN_CONTEXT_PENDING_USER_IDENTIFIER""" - flow = Flow.objects.create( - name="test-default-context", - slug="test-default-context", - designation=FlowDesignation.AUTHENTICATION, + flow = create_test_flow( + FlowDesignation.AUTHENTICATION, ) FlowStageBinding.objects.create( - target=flow, stage=DummyStage.objects.create(name="dummy"), order=0 + target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0 ) ident = "test-identifier" @@ -443,10 +460,8 @@ class TestFlowExecutor(FlowTestCase): def test_invalid_restart(self): """Test flow that restarts on invalid entry""" - flow = Flow.objects.create( - name="restart-on-invalid", - slug="restart-on-invalid", - designation=FlowDesignation.AUTHENTICATION, + flow = create_test_flow( + FlowDesignation.AUTHENTICATION, ) # Stage 0 is a deny stage that is added dynamically # when the reputation policy says so diff --git a/authentik/flows/views/executor.py b/authentik/flows/views/executor.py index 677b7bf23..a75568bae 100644 --- a/authentik/flows/views/executor.py +++ b/authentik/flows/views/executor.py @@ -10,6 +10,7 @@ from django.http import Http404, HttpRequest, HttpResponse, HttpResponseRedirect from django.http.request import QueryDict from django.shortcuts import get_object_or_404, redirect from django.template.response import TemplateResponse +from django.urls import reverse from django.utils.decorators import method_decorator from django.views.decorators.clickjacking import xframe_options_sameorigin from django.views.generic import View @@ -37,6 +38,7 @@ from authentik.flows.exceptions import EmptyFlowException, FlowNonApplicableExce from authentik.flows.models import ( ConfigurableStage, Flow, + FlowDeniedAction, FlowDesignation, FlowStageBinding, FlowToken, @@ -54,6 +56,7 @@ from authentik.lib.sentry import SentryIgnoredException from authentik.lib.utils.errors import exception_to_string from authentik.lib.utils.reflection import all_subclasses, class_to_path from authentik.lib.utils.urls import is_url_absolute, redirect_with_qs +from authentik.policies.engine import PolicyEngine from authentik.tenants.models import Tenant LOGGER = get_logger() @@ -131,12 +134,20 @@ class FlowExecutorView(APIView): def handle_invalid_flow(self, exc: BaseException) -> HttpResponse: """When a flow is non-applicable check if user is on the correct domain""" - if NEXT_ARG_NAME in self.request.GET: - if not is_url_absolute(self.request.GET.get(NEXT_ARG_NAME)): + if self.flow.denied_action in [ + FlowDeniedAction.CONTINUE, + FlowDeniedAction.MESSAGE_CONTINUE, + ]: + next_url = self.request.GET.get(NEXT_ARG_NAME) + if next_url and not is_url_absolute(next_url): self._logger.debug("f(exec): Redirecting to next on fail") - return redirect(self.request.GET.get(NEXT_ARG_NAME)) + return to_stage_response(self.request, redirect(next_url)) + if self.flow.denied_action == FlowDeniedAction.CONTINUE: + return to_stage_response( + self.request, redirect(reverse("authentik_core:root-redirect")) + ) message = exc.__doc__ if exc.__doc__ else str(exc) - return self.stage_invalid(error_message=message) + return to_stage_response(self.request, self.stage_invalid(error_message=message)) def _check_flow_token(self, key: str) -> Optional[FlowPlan]: """Check if the user is using a flow token to restore a plan""" @@ -187,7 +198,7 @@ class FlowExecutorView(APIView): self.plan = self._initiate_plan() except FlowNonApplicableException as exc: self._logger.warning("f(exec): Flow not applicable to current user", exc=exc) - return to_stage_response(self.request, self.handle_invalid_flow(exc)) + return self.handle_invalid_flow(exc) except EmptyFlowException as exc: self._logger.warning("f(exec): Flow is empty", exc=exc) # To match behaviour with loading an empty flow plan from cache, @@ -470,6 +481,20 @@ class ToDefaultFlow(View): designation: Optional[FlowDesignation] = None + def flow_by_policy(self, request: HttpRequest, **flow_filter) -> Optional[Flow]: + """Get a Flow by `**flow_filter` and check if the request from `request` can access it.""" + flows = Flow.objects.filter(**flow_filter).order_by("slug") + for flow in flows: + engine = PolicyEngine(flow, request.user, request) + engine.build() + result = engine.result + if result.passing: + LOGGER.debug("flow_by_policy: flow passing", flow=flow) + return flow + LOGGER.warning("flow_by_policy: flow not passing", flow=flow, messages=result.messages) + LOGGER.debug("flow_by_policy: no flow found", filters=flow_filter) + return None + def dispatch(self, request: HttpRequest) -> HttpResponse: tenant: Tenant = request.tenant flow = None @@ -480,7 +505,7 @@ class ToDefaultFlow(View): flow = tenant.flow_invalidation # If no flow was set, get the first based on slug and policy if not flow: - flow = Flow.with_policy(request, designation=self.designation) + flow = self.flow_by_policy(request, designation=self.designation) # If we still don't have a flow, 404 if not flow: raise Http404 diff --git a/authentik/lib/utils/errors.py b/authentik/lib/utils/errors.py index e2b210571..f1207c3ce 100644 --- a/authentik/lib/utils/errors.py +++ b/authentik/lib/utils/errors.py @@ -1,10 +1,18 @@ """error utils""" -from traceback import format_tb +from traceback import extract_tb -TRACEBACK_HEADER = "Traceback (most recent call last):\n" +from authentik.lib.utils.reflection import class_to_path + +TRACEBACK_HEADER = "Traceback (most recent call last):" def exception_to_string(exc: Exception) -> str: """Convert exception to string stackrace""" # Either use passed original exception or whatever we have - return TRACEBACK_HEADER + "".join(format_tb(exc.__traceback__)) + str(exc) + return "\n".join( + [ + TRACEBACK_HEADER, + *[x.rstrip() for x in extract_tb(exc.__traceback__).format()], + f"{class_to_path(exc.__class__)}: {str(exc)}", + ] + ) diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po index 1f75ef273..3eeb440d5 100644 --- a/locale/en/LC_MESSAGES/django.po +++ b/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-06-30 20:17+0000\n" +"POT-Creation-Date: 2022-07-02 15:10+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -217,7 +217,7 @@ msgid "Powered by authentik" msgstr "" #: authentik/core/views/apps.py:48 -#: authentik/providers/oauth2/views/authorize.py:356 +#: authentik/providers/oauth2/views/authorize.py:364 #: authentik/providers/saml/views/sso.py:69 #, python-format msgid "You're about to sign into %(application)s." @@ -336,56 +336,60 @@ msgstr "" msgid "Notification Webhook Mappings" msgstr "" -#: authentik/events/monitored_tasks.py:197 +#: authentik/events/monitored_tasks.py:191 msgid "Task has not been run yet." msgstr "" -#: authentik/flows/api/flows.py:227 authentik/flows/api/flows.py:249 +#: authentik/flows/api/flows.py:228 authentik/flows/api/flows.py:250 #, python-format msgid "Policy (%(type)s)" msgstr "" -#: authentik/flows/api/flows.py:258 +#: authentik/flows/api/flows.py:259 #, python-format msgid "Stage (%(type)s)" msgstr "" -#: authentik/flows/api/flows.py:373 +#: authentik/flows/api/flows.py:374 #, python-format msgid "Flow not applicable to current user/request: %(messages)s" msgstr "" -#: authentik/flows/models.py:108 +#: authentik/flows/models.py:117 msgid "Visible in the URL." msgstr "" -#: authentik/flows/models.py:110 +#: authentik/flows/models.py:119 msgid "Shown as the Title in Flow pages." msgstr "" -#: authentik/flows/models.py:128 +#: authentik/flows/models.py:137 msgid "Background shown during execution" msgstr "" -#: authentik/flows/models.py:135 +#: authentik/flows/models.py:144 msgid "" "Enable compatibility mode, increases compatibility with password managers on " "mobile devices." msgstr "" -#: authentik/flows/models.py:180 +#: authentik/flows/models.py:152 +msgid "Configure what should happen when a flow denies access to a user." +msgstr "" + +#: authentik/flows/models.py:178 msgid "Flow" msgstr "" -#: authentik/flows/models.py:181 +#: authentik/flows/models.py:179 msgid "Flows" msgstr "" -#: authentik/flows/models.py:211 +#: authentik/flows/models.py:209 msgid "Evaluate policies when the Stage is present to the user." msgstr "" -#: authentik/flows/models.py:218 +#: authentik/flows/models.py:216 msgid "" "Configure how the flow executor should handle an invalid response to a " "challenge. RETRY returns the error message and a similar challenge to the " @@ -393,19 +397,19 @@ msgid "" "RESTART_WITH_CONTEXT restarts the flow while keeping the current context." msgstr "" -#: authentik/flows/models.py:242 +#: authentik/flows/models.py:240 msgid "Flow Stage Binding" msgstr "" -#: authentik/flows/models.py:243 +#: authentik/flows/models.py:241 msgid "Flow Stage Bindings" msgstr "" -#: authentik/flows/models.py:293 +#: authentik/flows/models.py:291 msgid "Flow Token" msgstr "" -#: authentik/flows/models.py:294 +#: authentik/flows/models.py:292 msgid "Flow Tokens" msgstr "" @@ -833,7 +837,7 @@ msgstr "" msgid "OAuth2 Tokens" msgstr "" -#: authentik/providers/oauth2/views/authorize.py:410 +#: authentik/providers/oauth2/views/authorize.py:418 #: authentik/providers/saml/views/flows.py:86 #, python-format msgid "Redirecting to %(app)s..." @@ -856,42 +860,42 @@ msgstr "" msgid "authentik API Access on behalf of your user" msgstr "" -#: authentik/providers/proxy/models.py:52 +#: authentik/providers/proxy/models.py:47 msgid "Validate SSL Certificates of upstream servers" msgstr "" -#: authentik/providers/proxy/models.py:53 +#: authentik/providers/proxy/models.py:48 msgid "Internal host SSL Validation" msgstr "" -#: authentik/providers/proxy/models.py:59 +#: authentik/providers/proxy/models.py:54 msgid "" "Enable support for forwardAuth in traefik and nginx auth_request. Exclusive " "with internal_host." msgstr "" -#: authentik/providers/proxy/models.py:77 +#: authentik/providers/proxy/models.py:72 msgid "Set HTTP-Basic Authentication" msgstr "" -#: authentik/providers/proxy/models.py:79 +#: authentik/providers/proxy/models.py:74 msgid "" "Set a custom HTTP-Basic Authentication header based on values from authentik." msgstr "" -#: authentik/providers/proxy/models.py:84 +#: authentik/providers/proxy/models.py:79 msgid "HTTP-Basic Username Key" msgstr "" -#: authentik/providers/proxy/models.py:94 +#: authentik/providers/proxy/models.py:89 msgid "HTTP-Basic Password Key" msgstr "" -#: authentik/providers/proxy/models.py:149 +#: authentik/providers/proxy/models.py:144 msgid "Proxy Provider" msgstr "" -#: authentik/providers/proxy/models.py:150 +#: authentik/providers/proxy/models.py:145 msgid "Proxy Providers" msgstr "" @@ -996,77 +1000,77 @@ msgstr "" msgid "Used recovery-link to authenticate." msgstr "" -#: authentik/sources/ldap/models.py:32 +#: authentik/sources/ldap/models.py:33 msgid "Server URI" msgstr "" -#: authentik/sources/ldap/models.py:40 +#: authentik/sources/ldap/models.py:41 msgid "" "Optionally verify the LDAP Server's Certificate against the CA Chain in this " "keypair." msgstr "" -#: authentik/sources/ldap/models.py:45 +#: authentik/sources/ldap/models.py:46 msgid "Bind CN" msgstr "" -#: authentik/sources/ldap/models.py:47 +#: authentik/sources/ldap/models.py:48 msgid "Enable Start TLS" msgstr "" -#: authentik/sources/ldap/models.py:49 +#: authentik/sources/ldap/models.py:50 msgid "Base DN" msgstr "" -#: authentik/sources/ldap/models.py:51 +#: authentik/sources/ldap/models.py:52 msgid "Prepended to Base DN for User-queries." msgstr "" -#: authentik/sources/ldap/models.py:52 +#: authentik/sources/ldap/models.py:53 msgid "Addition User DN" msgstr "" -#: authentik/sources/ldap/models.py:56 +#: authentik/sources/ldap/models.py:57 msgid "Prepended to Base DN for Group-queries." msgstr "" -#: authentik/sources/ldap/models.py:57 +#: authentik/sources/ldap/models.py:58 msgid "Addition Group DN" msgstr "" -#: authentik/sources/ldap/models.py:63 +#: authentik/sources/ldap/models.py:64 msgid "Consider Objects matching this filter to be Users." msgstr "" -#: authentik/sources/ldap/models.py:66 +#: authentik/sources/ldap/models.py:67 msgid "Field which contains members of a group." msgstr "" -#: authentik/sources/ldap/models.py:70 +#: authentik/sources/ldap/models.py:71 msgid "Consider Objects matching this filter to be Groups." msgstr "" -#: authentik/sources/ldap/models.py:73 +#: authentik/sources/ldap/models.py:74 msgid "Field which contains a unique Identifier." msgstr "" -#: authentik/sources/ldap/models.py:80 +#: authentik/sources/ldap/models.py:81 msgid "Property mappings used for group creation/updating." msgstr "" -#: authentik/sources/ldap/models.py:145 +#: authentik/sources/ldap/models.py:149 msgid "LDAP Source" msgstr "" -#: authentik/sources/ldap/models.py:146 +#: authentik/sources/ldap/models.py:150 msgid "LDAP Sources" msgstr "" -#: authentik/sources/ldap/models.py:169 +#: authentik/sources/ldap/models.py:173 msgid "LDAP Property Mapping" msgstr "" -#: authentik/sources/ldap/models.py:170 +#: authentik/sources/ldap/models.py:174 msgid "LDAP Property Mappings" msgstr "" diff --git a/schema.yml b/schema.yml index 73aee7f94..2b5c9ae9f 100644 --- a/schema.yml +++ b/schema.yml @@ -5140,6 +5140,15 @@ paths: operationId: flows_instances_list description: Flow Viewset parameters: + - in: query + name: denied_action + schema: + type: string + enum: + - continue + - message + - message_continue + description: Configure what should happen when a flow denies access to a user. - in: query name: designation schema: @@ -20656,6 +20665,12 @@ components: - branding_title - matched_domain - ui_footer_links + DeniedActionEnum: + enum: + - message_continue + - message + - continue + type: string DenyStage: type: object description: DenyStage Serializer @@ -21571,6 +21586,11 @@ components: readOnly: true layout: $ref: '#/components/schemas/LayoutEnum' + denied_action: + allOf: + - $ref: '#/components/schemas/DeniedActionEnum' + description: Configure what should happen when a flow denies access to a + user. required: - background - cache_count @@ -21708,6 +21728,11 @@ components: managers on mobile devices. layout: $ref: '#/components/schemas/LayoutEnum' + denied_action: + allOf: + - $ref: '#/components/schemas/DeniedActionEnum' + description: Configure what should happen when a flow denies access to a + user. required: - designation - name @@ -27269,6 +27294,11 @@ components: managers on mobile devices. layout: $ref: '#/components/schemas/LayoutEnum' + denied_action: + allOf: + - $ref: '#/components/schemas/DeniedActionEnum' + description: Configure what should happen when a flow denies access to a + user. PatchedFlowStageBindingRequest: type: object description: FlowStageBinding Serializer diff --git a/web/src/locales/de.po b/web/src/locales/de.po index 263eb8d7c..17d39c98a 100644 --- a/web/src/locales/de.po +++ b/web/src/locales/de.po @@ -789,6 +789,10 @@ msgstr "Standardmäßig werden für Quellen nur Symbole angezeigt. Aktiviere die msgid "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." msgstr "CA, anhand derer das Zertifikat des Endpunkts überprüft wird. Kann leer gelassen werden, um keine Validierung durchzuführen." +#: src/pages/flows/FlowForm.ts +msgid "CONTINUE will either follow the ?next parameter or redirect to the default interface." +msgstr "" + #: src/pages/providers/ldap/LDAPProviderForm.ts msgid "Cached binding, flow is executed and session is cached in memory. Flow is executed when session expires." msgstr "" @@ -1530,6 +1534,10 @@ msgstr "Deaktivieren" msgid "Debug" msgstr "Debuggen" +#: src/pages/flows/FlowForm.ts +msgid "Decides the response when a policy denies access to this flow for a user." +msgstr "" + #: src/pages/flows/FlowForm.ts msgid "Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik." msgstr "Entscheidet, wofür dieser Flow verwendet wird. Beispielsweise wird der Authentifizierungsablauf umgeleitet, wenn ein nicht authentifizierter Benutzer authentik besucht." @@ -1627,6 +1635,10 @@ msgstr "" msgid "Delete {0}" msgstr "{0} löschen" +#: src/pages/flows/FlowForm.ts +msgid "Denied action" +msgstr "" + #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts msgid "Deny the user access" msgstr "Dem Benutzer den Zugang verweigern" @@ -3174,6 +3186,14 @@ msgstr "Logs" msgid "Long-running operations which authentik executes in the background." msgstr "Langlaufende Operationen, die Authentik im Hintergrund ausführt." +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE will notify the user the flow isn't applicable." +msgstr "" + +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE_CONTINUE will follow the ?next parameter if set, otherwise show a message." +msgstr "" + #: src/user/user-settings/UserSettingsPage.ts msgid "MFA Devices" msgstr "Multifaktor-Authentifzierungs Geräte" @@ -4262,13 +4282,17 @@ msgid "Quick actions" msgstr "Schnellaktionen" #: src/pages/flows/StageBindingForm.ts -msgid "RESTART restarts the flow from the beginning, while keeping the flow context." -msgstr "RESTART startet den Flow von Anfang an neu, während der Flow-Kontext beibehalten wird." +#~ msgid "RESTART restarts the flow from the beginning, while keeping the flow context." +#~ msgstr "RESTART startet den Flow von Anfang an neu, während der Flow-Kontext beibehalten wird." #: src/pages/flows/StageBindingForm.ts msgid "RESTART restarts the flow from the beginning." msgstr "RESTART startet den Flow von Anfang an neu." +#: src/pages/flows/StageBindingForm.ts +msgid "RESTART_WITH_CONTEXT restarts the flow from the beginning, while keeping the flow context." +msgstr "" + #: src/pages/flows/StageBindingForm.ts msgid "RETRY returns the error message and a similar challenge to the executor." msgstr "RETRY gibt die Fehlermeldung und eine ähnliche Aufforderung an den Executor zurück." diff --git a/web/src/locales/en.po b/web/src/locales/en.po index 438d1fca2..26a36f49b 100644 --- a/web/src/locales/en.po +++ b/web/src/locales/en.po @@ -786,6 +786,10 @@ msgstr "By default, only icons are shown for sources. Enable this to show their msgid "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." msgstr "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." +#: src/pages/flows/FlowForm.ts +msgid "CONTINUE will either follow the ?next parameter or redirect to the default interface." +msgstr "CONTINUE will either follow the ?next parameter or redirect to the default interface." + #: src/pages/providers/ldap/LDAPProviderForm.ts msgid "Cached binding, flow is executed and session is cached in memory. Flow is executed when session expires." msgstr "Cached binding, flow is executed and session is cached in memory. Flow is executed when session expires." @@ -1542,6 +1546,10 @@ msgstr "Deactivate" msgid "Debug" msgstr "Debug" +#: src/pages/flows/FlowForm.ts +msgid "Decides the response when a policy denies access to this flow for a user." +msgstr "Decides the response when a policy denies access to this flow for a user." + #: src/pages/flows/FlowForm.ts msgid "Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik." msgstr "Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik." @@ -1645,6 +1653,10 @@ msgstr "" msgid "Delete {0}" msgstr "Delete {0}" +#: src/pages/flows/FlowForm.ts +msgid "Denied action" +msgstr "Denied action" + #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts msgid "Deny the user access" msgstr "Deny the user access" @@ -3226,6 +3238,14 @@ msgstr "Logs" msgid "Long-running operations which authentik executes in the background." msgstr "Long-running operations which authentik executes in the background." +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE will notify the user the flow isn't applicable." +msgstr "MESSAGE will notify the user the flow isn't applicable." + +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE_CONTINUE will follow the ?next parameter if set, otherwise show a message." +msgstr "MESSAGE_CONTINUE will follow the ?next parameter if set, otherwise show a message." + #: src/user/user-settings/UserSettingsPage.ts msgid "MFA Devices" msgstr "MFA Devices" @@ -4332,13 +4352,17 @@ msgid "Quick actions" msgstr "Quick actions" #: src/pages/flows/StageBindingForm.ts -msgid "RESTART restarts the flow from the beginning, while keeping the flow context." -msgstr "RESTART restarts the flow from the beginning, while keeping the flow context." +#~ msgid "RESTART restarts the flow from the beginning, while keeping the flow context." +#~ msgstr "RESTART restarts the flow from the beginning, while keeping the flow context." #: src/pages/flows/StageBindingForm.ts msgid "RESTART restarts the flow from the beginning." msgstr "RESTART restarts the flow from the beginning." +#: src/pages/flows/StageBindingForm.ts +msgid "RESTART_WITH_CONTEXT restarts the flow from the beginning, while keeping the flow context." +msgstr "RESTART_WITH_CONTEXT restarts the flow from the beginning, while keeping the flow context." + #: src/pages/flows/StageBindingForm.ts msgid "RETRY returns the error message and a similar challenge to the executor." msgstr "RETRY returns the error message and a similar challenge to the executor." diff --git a/web/src/locales/es.po b/web/src/locales/es.po index 2edf801ca..937821520 100644 --- a/web/src/locales/es.po +++ b/web/src/locales/es.po @@ -779,6 +779,10 @@ msgstr "De forma predeterminada, solo se muestran los iconos de las fuentes. Act msgid "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." msgstr "CA con la que se verifica el certificado del punto final. Se puede dejar vacío para que no se valide." +#: src/pages/flows/FlowForm.ts +msgid "CONTINUE will either follow the ?next parameter or redirect to the default interface." +msgstr "" + #: src/pages/providers/ldap/LDAPProviderForm.ts msgid "Cached binding, flow is executed and session is cached in memory. Flow is executed when session expires." msgstr "" @@ -1521,6 +1525,10 @@ msgstr "Desactivar" msgid "Debug" msgstr "Depurar" +#: src/pages/flows/FlowForm.ts +msgid "Decides the response when a policy denies access to this flow for a user." +msgstr "" + #: src/pages/flows/FlowForm.ts msgid "Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik." msgstr "Decide para qué se utiliza este flujo. Por ejemplo, el flujo de autenticación se redirige a cuando un usuario no autenticado visita authentick." @@ -1618,6 +1626,10 @@ msgstr "" msgid "Delete {0}" msgstr "Eliminar {0}" +#: src/pages/flows/FlowForm.ts +msgid "Denied action" +msgstr "" + #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts msgid "Deny the user access" msgstr "Denegar el acceso al usuario" @@ -3167,6 +3179,14 @@ msgstr "troncos" msgid "Long-running operations which authentik executes in the background." msgstr "Operaciones de larga ejecución que authentik se ejecuta en segundo plano." +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE will notify the user the flow isn't applicable." +msgstr "" + +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE_CONTINUE will follow the ?next parameter if set, otherwise show a message." +msgstr "" + #: src/user/user-settings/UserSettingsPage.ts msgid "MFA Devices" msgstr "Dispositivos de MFA" @@ -4255,13 +4275,17 @@ msgid "Quick actions" msgstr "Acciones rápidas" #: src/pages/flows/StageBindingForm.ts -msgid "RESTART restarts the flow from the beginning, while keeping the flow context." -msgstr "RESTART reinicia el flujo desde el principio, a la vez que mantiene el contexto del flujo." +#~ msgid "RESTART restarts the flow from the beginning, while keeping the flow context." +#~ msgstr "RESTART reinicia el flujo desde el principio, a la vez que mantiene el contexto del flujo." #: src/pages/flows/StageBindingForm.ts msgid "RESTART restarts the flow from the beginning." msgstr "RESTART reinicia el flujo desde el principio." +#: src/pages/flows/StageBindingForm.ts +msgid "RESTART_WITH_CONTEXT restarts the flow from the beginning, while keeping the flow context." +msgstr "" + #: src/pages/flows/StageBindingForm.ts msgid "RETRY returns the error message and a similar challenge to the executor." msgstr "RETRY devuelve el mensaje de error y un desafío similar para el ejecutor." diff --git a/web/src/locales/fr_FR.po b/web/src/locales/fr_FR.po index 6f5b2bf8d..ba7bfdcc6 100644 --- a/web/src/locales/fr_FR.po +++ b/web/src/locales/fr_FR.po @@ -785,6 +785,10 @@ msgstr "" msgid "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." msgstr "AC auprès de laquelle le certificat du terminal est vérifié. Peut être laissé vide en l'absence de validation." +#: src/pages/flows/FlowForm.ts +msgid "CONTINUE will either follow the ?next parameter or redirect to the default interface." +msgstr "" + #: src/pages/providers/ldap/LDAPProviderForm.ts msgid "Cached binding, flow is executed and session is cached in memory. Flow is executed when session expires." msgstr "" @@ -1535,6 +1539,10 @@ msgstr "Désactiver" msgid "Debug" msgstr "" +#: src/pages/flows/FlowForm.ts +msgid "Decides the response when a policy denies access to this flow for a user." +msgstr "" + #: src/pages/flows/FlowForm.ts msgid "Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik." msgstr "Détermine l'usage de ce flux. Par exemple, un flux d'authentification est la destination d'un visiteur d'authentik non authentifié." @@ -1630,6 +1638,10 @@ msgstr "Supprimer l'utilisateur en attente. ATTENTION, cette étape ne demande a msgid "Delete {0}" msgstr "Supprimer {0}" +#: src/pages/flows/FlowForm.ts +msgid "Denied action" +msgstr "" + #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts msgid "Deny the user access" msgstr "Refuser l'accès à l'utilisateu" @@ -3198,6 +3210,14 @@ msgstr "Logs" msgid "Long-running operations which authentik executes in the background." msgstr "Opérations de longue durée qu'Authentik exécute en arrière-plan." +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE will notify the user the flow isn't applicable." +msgstr "" + +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE_CONTINUE will follow the ?next parameter if set, otherwise show a message." +msgstr "" + #: src/user/user-settings/UserSettingsPage.ts msgid "MFA Devices" msgstr "" @@ -4291,13 +4311,17 @@ msgid "Quick actions" msgstr "" #: src/pages/flows/StageBindingForm.ts -msgid "RESTART restarts the flow from the beginning, while keeping the flow context." -msgstr "REDÉMARRER redémarre le flux depuis le début, en gardant le contexte du flux." +#~ msgid "RESTART restarts the flow from the beginning, while keeping the flow context." +#~ msgstr "REDÉMARRER redémarre le flux depuis le début, en gardant le contexte du flux." #: src/pages/flows/StageBindingForm.ts msgid "RESTART restarts the flow from the beginning." msgstr "REDÉMARRER redémarre le flux depuis le début." +#: src/pages/flows/StageBindingForm.ts +msgid "RESTART_WITH_CONTEXT restarts the flow from the beginning, while keeping the flow context." +msgstr "" + #: src/pages/flows/StageBindingForm.ts msgid "RETRY returns the error message and a similar challenge to the executor." msgstr "RETRY indiquer le message d'erreur et présenter un challenge similaire à l'utilisateur" diff --git a/web/src/locales/pl.po b/web/src/locales/pl.po index 7bc4f513f..e8a81f41f 100644 --- a/web/src/locales/pl.po +++ b/web/src/locales/pl.po @@ -776,6 +776,10 @@ msgstr "Domyślnie dla źródeł wyświetlane są tylko ikony. Włącz tę opcj msgid "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." msgstr "CA względem którego weryfikowany jest certyfikat. Można pozostawić puste, aby nie sprawdzać poprawności." +#: src/pages/flows/FlowForm.ts +msgid "CONTINUE will either follow the ?next parameter or redirect to the default interface." +msgstr "" + #: src/pages/providers/ldap/LDAPProviderForm.ts msgid "Cached binding, flow is executed and session is cached in memory. Flow is executed when session expires." msgstr "" @@ -1518,6 +1522,10 @@ msgstr "Dezaktywuj" msgid "Debug" msgstr "Debug" +#: src/pages/flows/FlowForm.ts +msgid "Decides the response when a policy denies access to this flow for a user." +msgstr "" + #: src/pages/flows/FlowForm.ts msgid "Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik." msgstr "Decyduje, do czego służy ten przepływ. Na przykład przepływ uwierzytelniania służy do przekierowania nieuwierzytelnionego użytkownika który odwiedza authentik." @@ -1615,6 +1623,10 @@ msgstr "" msgid "Delete {0}" msgstr "Usuń {0}" +#: src/pages/flows/FlowForm.ts +msgid "Denied action" +msgstr "" + #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts msgid "Deny the user access" msgstr "Odmów użytkownikowi dostępu" @@ -3164,6 +3176,14 @@ msgstr "Logi" msgid "Long-running operations which authentik executes in the background." msgstr "Długotrwałe operacje, które authentik wykonuje w tle." +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE will notify the user the flow isn't applicable." +msgstr "" + +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE_CONTINUE will follow the ?next parameter if set, otherwise show a message." +msgstr "" + #: src/user/user-settings/UserSettingsPage.ts msgid "MFA Devices" msgstr "Urządzenia MFA" @@ -4252,13 +4272,17 @@ msgid "Quick actions" msgstr "Szybkie akcje" #: src/pages/flows/StageBindingForm.ts -msgid "RESTART restarts the flow from the beginning, while keeping the flow context." -msgstr "RESTART ponownie uruchamia przepływ od początku, zachowując kontekst przepływu." +#~ msgid "RESTART restarts the flow from the beginning, while keeping the flow context." +#~ msgstr "RESTART ponownie uruchamia przepływ od początku, zachowując kontekst przepływu." #: src/pages/flows/StageBindingForm.ts msgid "RESTART restarts the flow from the beginning." msgstr "RESTART ponownie uruchamia przepływ od początku." +#: src/pages/flows/StageBindingForm.ts +msgid "RESTART_WITH_CONTEXT restarts the flow from the beginning, while keeping the flow context." +msgstr "" + #: src/pages/flows/StageBindingForm.ts msgid "RETRY returns the error message and a similar challenge to the executor." msgstr "RETRY zwraca komunikat o błędzie i podobne wyzwanie do executora." diff --git a/web/src/locales/pseudo-LOCALE.po b/web/src/locales/pseudo-LOCALE.po index e3cd1b45a..6b89e2abf 100644 --- a/web/src/locales/pseudo-LOCALE.po +++ b/web/src/locales/pseudo-LOCALE.po @@ -778,6 +778,10 @@ msgstr "" msgid "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." msgstr "" +#: src/pages/flows/FlowForm.ts +msgid "CONTINUE will either follow the ?next parameter or redirect to the default interface." +msgstr "" + #: src/pages/providers/ldap/LDAPProviderForm.ts msgid "Cached binding, flow is executed and session is cached in memory. Flow is executed when session expires." msgstr "" @@ -1530,6 +1534,10 @@ msgstr "" msgid "Debug" msgstr "" +#: src/pages/flows/FlowForm.ts +msgid "Decides the response when a policy denies access to this flow for a user." +msgstr "" + #: src/pages/flows/FlowForm.ts msgid "Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik." msgstr "" @@ -1631,6 +1639,10 @@ msgstr "" msgid "Delete {0}" msgstr "" +#: src/pages/flows/FlowForm.ts +msgid "Denied action" +msgstr "" + #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts msgid "Deny the user access" msgstr "" @@ -3208,6 +3220,14 @@ msgstr "" msgid "Long-running operations which authentik executes in the background." msgstr "" +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE will notify the user the flow isn't applicable." +msgstr "" + +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE_CONTINUE will follow the ?next parameter if set, otherwise show a message." +msgstr "" + #: src/user/user-settings/UserSettingsPage.ts msgid "MFA Devices" msgstr "" @@ -4312,13 +4332,17 @@ msgid "Quick actions" msgstr "" #: src/pages/flows/StageBindingForm.ts -msgid "RESTART restarts the flow from the beginning, while keeping the flow context." -msgstr "" +#~ msgid "RESTART restarts the flow from the beginning, while keeping the flow context." +#~ msgstr "" #: src/pages/flows/StageBindingForm.ts msgid "RESTART restarts the flow from the beginning." msgstr "" +#: src/pages/flows/StageBindingForm.ts +msgid "RESTART_WITH_CONTEXT restarts the flow from the beginning, while keeping the flow context." +msgstr "" + #: src/pages/flows/StageBindingForm.ts msgid "RETRY returns the error message and a similar challenge to the executor." msgstr "" diff --git a/web/src/locales/tr.po b/web/src/locales/tr.po index 380cfe25d..02be4c4dc 100644 --- a/web/src/locales/tr.po +++ b/web/src/locales/tr.po @@ -779,6 +779,10 @@ msgstr "Varsayılan olarak, kaynaklar için yalnızca simgeler gösterilir. Tam msgid "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." msgstr "Uç noktanın Sertifikası karşı doğrulanan CA. Doğrulama yapılmadan boş bırakılabilir." +#: src/pages/flows/FlowForm.ts +msgid "CONTINUE will either follow the ?next parameter or redirect to the default interface." +msgstr "" + #: src/pages/providers/ldap/LDAPProviderForm.ts msgid "Cached binding, flow is executed and session is cached in memory. Flow is executed when session expires." msgstr "" @@ -1521,6 +1525,10 @@ msgstr "Devre dışı bırak" msgid "Debug" msgstr "Hata Ayıklama" +#: src/pages/flows/FlowForm.ts +msgid "Decides the response when a policy denies access to this flow for a user." +msgstr "" + #: src/pages/flows/FlowForm.ts msgid "Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik." msgstr "Bu Akış'ın ne için kullanıldığına karar verir. Örneğin, kimliği doğrulanmamış bir kullanıcı authentik ziyaret ettiğinde kimlik doğrulama akışı yönlendirir." @@ -1618,6 +1626,10 @@ msgstr "" msgid "Delete {0}" msgstr "{0} Sil" +#: src/pages/flows/FlowForm.ts +msgid "Denied action" +msgstr "" + #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts msgid "Deny the user access" msgstr "Kullanıcı erişimini engelle" @@ -3168,6 +3180,14 @@ msgstr "Günlükler" msgid "Long-running operations which authentik executes in the background." msgstr "authentik'in arka planda yürüttüğü uzun süreli işlemler." +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE will notify the user the flow isn't applicable." +msgstr "" + +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE_CONTINUE will follow the ?next parameter if set, otherwise show a message." +msgstr "" + #: src/user/user-settings/UserSettingsPage.ts msgid "MFA Devices" msgstr "MFA Cihazları" @@ -4257,13 +4277,17 @@ msgid "Quick actions" msgstr "Hızlı eylemler" #: src/pages/flows/StageBindingForm.ts -msgid "RESTART restarts the flow from the beginning, while keeping the flow context." -msgstr "RESTART, akış bağlamını korurken akışı baştan yeniden başlatır." +#~ msgid "RESTART restarts the flow from the beginning, while keeping the flow context." +#~ msgstr "RESTART, akış bağlamını korurken akışı baştan yeniden başlatır." #: src/pages/flows/StageBindingForm.ts msgid "RESTART restarts the flow from the beginning." msgstr "RESTART, akışı baştan yeniden başlatır." +#: src/pages/flows/StageBindingForm.ts +msgid "RESTART_WITH_CONTEXT restarts the flow from the beginning, while keeping the flow context." +msgstr "" + #: src/pages/flows/StageBindingForm.ts msgid "RETRY returns the error message and a similar challenge to the executor." msgstr "RETRY hata iletisi ve yürütücünün benzer bir meydan okuma döndürür." diff --git a/web/src/locales/zh-Hans.po b/web/src/locales/zh-Hans.po index f8389b4b9..ec8de56c7 100644 --- a/web/src/locales/zh-Hans.po +++ b/web/src/locales/zh-Hans.po @@ -774,6 +774,10 @@ msgstr "默认情况下,只为源显示图标。启用此选项可显示它们 msgid "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." msgstr "验证端点证书所依据的 CA。可以留空,表示不进行验证。" +#: src/pages/flows/FlowForm.ts +msgid "CONTINUE will either follow the ?next parameter or redirect to the default interface." +msgstr "" + #: src/pages/providers/ldap/LDAPProviderForm.ts msgid "Cached binding, flow is executed and session is cached in memory. Flow is executed when session expires." msgstr "缓存绑定,流程与会话会在内存中执行与缓存。会话过期时执行流程。" @@ -1516,6 +1520,10 @@ msgstr "停用" msgid "Debug" msgstr "调试" +#: src/pages/flows/FlowForm.ts +msgid "Decides the response when a policy denies access to this flow for a user." +msgstr "" + #: src/pages/flows/FlowForm.ts msgid "Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik." msgstr "决定此流程的用途。例如,当未经身份验证的用户访问 authentik 时,会重定向到身份验证流程。" @@ -1613,6 +1621,10 @@ msgstr "" msgid "Delete {0}" msgstr "删除 {0}" +#: src/pages/flows/FlowForm.ts +msgid "Denied action" +msgstr "" + #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts msgid "Deny the user access" msgstr "拒绝用户访问" @@ -3150,6 +3162,14 @@ msgstr "日志" msgid "Long-running operations which authentik executes in the background." msgstr "authentik 在后台执行的长时间运行的操作。" +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE will notify the user the flow isn't applicable." +msgstr "" + +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE_CONTINUE will follow the ?next parameter if set, otherwise show a message." +msgstr "" + #: src/user/user-settings/UserSettingsPage.ts msgid "MFA Devices" msgstr "MFA 设备" @@ -4228,13 +4248,17 @@ msgid "Quick actions" msgstr "快速操作" #: src/pages/flows/StageBindingForm.ts -msgid "RESTART restarts the flow from the beginning, while keeping the flow context." -msgstr "RESTART 从头开始重新启动流程,同时保留流程上下文。" +#~ msgid "RESTART restarts the flow from the beginning, while keeping the flow context." +#~ msgstr "RESTART 从头开始重新启动流程,同时保留流程上下文。" #: src/pages/flows/StageBindingForm.ts msgid "RESTART restarts the flow from the beginning." msgstr "RESTART 从头开始重新启动流程。" +#: src/pages/flows/StageBindingForm.ts +msgid "RESTART_WITH_CONTEXT restarts the flow from the beginning, while keeping the flow context." +msgstr "" + #: src/pages/flows/StageBindingForm.ts msgid "RETRY returns the error message and a similar challenge to the executor." msgstr "RETRY 向执行器返回错误消息和类似的质询。" diff --git a/web/src/locales/zh-Hant.po b/web/src/locales/zh-Hant.po index c4e484c1c..7e983f56f 100644 --- a/web/src/locales/zh-Hant.po +++ b/web/src/locales/zh-Hant.po @@ -776,6 +776,10 @@ msgstr "默认情况下,只为源显示图标。启用此选项可显示他们 msgid "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." msgstr "验证终端节点证书所依据的 CA。可以留空以表示不进行验证。" +#: src/pages/flows/FlowForm.ts +msgid "CONTINUE will either follow the ?next parameter or redirect to the default interface." +msgstr "" + #: src/pages/providers/ldap/LDAPProviderForm.ts msgid "Cached binding, flow is executed and session is cached in memory. Flow is executed when session expires." msgstr "" @@ -1518,6 +1522,10 @@ msgstr "停用" msgid "Debug" msgstr "调试" +#: src/pages/flows/FlowForm.ts +msgid "Decides the response when a policy denies access to this flow for a user." +msgstr "" + #: src/pages/flows/FlowForm.ts msgid "Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik." msgstr "决定此 Flow 的用途。例如,当未经身份验证的用户访问 authentik 时,身份验证流程将重定向到。" @@ -1615,6 +1623,10 @@ msgstr "" msgid "Delete {0}" msgstr "删除 {0}" +#: src/pages/flows/FlowForm.ts +msgid "Denied action" +msgstr "" + #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts msgid "Deny the user access" msgstr "拒绝用户访问" @@ -3154,6 +3166,14 @@ msgstr "日志" msgid "Long-running operations which authentik executes in the background." msgstr "authentik 在后台执行的长时间运行的操作。" +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE will notify the user the flow isn't applicable." +msgstr "" + +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE_CONTINUE will follow the ?next parameter if set, otherwise show a message." +msgstr "" + #: src/user/user-settings/UserSettingsPage.ts msgid "MFA Devices" msgstr "MFA 设备" @@ -4233,13 +4253,17 @@ msgid "Quick actions" msgstr "快速行动" #: src/pages/flows/StageBindingForm.ts -msgid "RESTART restarts the flow from the beginning, while keeping the flow context." -msgstr "RESTART 从头开始重新启动流程,同时保留流程上下文。" +#~ msgid "RESTART restarts the flow from the beginning, while keeping the flow context." +#~ msgstr "RESTART 从头开始重新启动流程,同时保留流程上下文。" #: src/pages/flows/StageBindingForm.ts msgid "RESTART restarts the flow from the beginning." msgstr "RESTART 从头开始重新启动流程。" +#: src/pages/flows/StageBindingForm.ts +msgid "RESTART_WITH_CONTEXT restarts the flow from the beginning, while keeping the flow context." +msgstr "" + #: src/pages/flows/StageBindingForm.ts msgid "RETRY returns the error message and a similar challenge to the executor." msgstr "RETRY 向执行器返回错误消息和类似的质询。" diff --git a/web/src/locales/zh_TW.po b/web/src/locales/zh_TW.po index c0baf5697..4e70ce85b 100644 --- a/web/src/locales/zh_TW.po +++ b/web/src/locales/zh_TW.po @@ -776,6 +776,10 @@ msgstr "默认情况下,只为源显示图标。启用此选项可显示他们 msgid "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." msgstr "验证终端节点证书所依据的 CA。可以留空以表示不进行验证。" +#: src/pages/flows/FlowForm.ts +msgid "CONTINUE will either follow the ?next parameter or redirect to the default interface." +msgstr "" + #: src/pages/providers/ldap/LDAPProviderForm.ts msgid "Cached binding, flow is executed and session is cached in memory. Flow is executed when session expires." msgstr "" @@ -1518,6 +1522,10 @@ msgstr "停用" msgid "Debug" msgstr "调试" +#: src/pages/flows/FlowForm.ts +msgid "Decides the response when a policy denies access to this flow for a user." +msgstr "" + #: src/pages/flows/FlowForm.ts msgid "Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik." msgstr "决定此 Flow 的用途。例如,当未经身份验证的用户访问 authentik 时,身份验证流程将重定向到。" @@ -1615,6 +1623,10 @@ msgstr "" msgid "Delete {0}" msgstr "删除 {0}" +#: src/pages/flows/FlowForm.ts +msgid "Denied action" +msgstr "" + #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts msgid "Deny the user access" msgstr "拒绝用户访问" @@ -3154,6 +3166,14 @@ msgstr "日志" msgid "Long-running operations which authentik executes in the background." msgstr "authentik 在后台执行的长时间运行的操作。" +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE will notify the user the flow isn't applicable." +msgstr "" + +#: src/pages/flows/FlowForm.ts +msgid "MESSAGE_CONTINUE will follow the ?next parameter if set, otherwise show a message." +msgstr "" + #: src/user/user-settings/UserSettingsPage.ts msgid "MFA Devices" msgstr "MFA 设备" @@ -4233,13 +4253,17 @@ msgid "Quick actions" msgstr "快速行动" #: src/pages/flows/StageBindingForm.ts -msgid "RESTART restarts the flow from the beginning, while keeping the flow context." -msgstr "RESTART 从头开始重新启动流程,同时保留流程上下文。" +#~ msgid "RESTART restarts the flow from the beginning, while keeping the flow context." +#~ msgstr "RESTART 从头开始重新启动流程,同时保留流程上下文。" #: src/pages/flows/StageBindingForm.ts msgid "RESTART restarts the flow from the beginning." msgstr "RESTART 从头开始重新启动流程。" +#: src/pages/flows/StageBindingForm.ts +msgid "RESTART_WITH_CONTEXT restarts the flow from the beginning, while keeping the flow context." +msgstr "" + #: src/pages/flows/StageBindingForm.ts msgid "RETRY returns the error message and a similar challenge to the executor." msgstr "RETRY 向执行器返回错误消息和类似的质询。" diff --git a/web/src/pages/flows/FlowForm.ts b/web/src/pages/flows/FlowForm.ts index ea0c18e35..9a3b952fc 100644 --- a/web/src/pages/flows/FlowForm.ts +++ b/web/src/pages/flows/FlowForm.ts @@ -1,3 +1,4 @@ +import { DeniedActionEnum } from "@goauthentik/api/dist/models/DeniedActionEnum.js"; import { DEFAULT_CONFIG, config } from "@goauthentik/web/api/Config"; import "@goauthentik/web/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/web/elements/forms/ModelForm"; @@ -120,6 +121,27 @@ export class FlowForm extends ModelForm { `; } + renderDeniedAction(): TemplateResult { + return html` + + `; + } + renderLayout(): TemplateResult { return html`