flows: denied action (#3194)
This commit is contained in:
		
							
								
								
									
										10
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							| @ -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", | ||||
|  | ||||
| @ -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 | ||||
|     ) | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -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)}) | ||||
|  | ||||
							
								
								
									
										26
									
								
								authentik/flows/migrations/0023_flow_denied_action.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								authentik/flows/migrations/0023_flow_denied_action.py
									
									
									
									
									
										Normal file
									
								
							| @ -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.", | ||||
|             ), | ||||
|         ), | ||||
|     ] | ||||
| @ -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})" | ||||
|  | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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)}", | ||||
|         ] | ||||
|     ) | ||||
|  | ||||
| @ -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 <EMAIL@ADDRESS>\n" | ||||
| "Language-Team: LANGUAGE <LL@li.org>\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 "" | ||||
|  | ||||
|  | ||||
							
								
								
									
										30
									
								
								schema.yml
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								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 | ||||
|  | ||||
| @ -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." | ||||
|  | ||||
| @ -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." | ||||
|  | ||||
| @ -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." | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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." | ||||
|  | ||||
| @ -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 "" | ||||
|  | ||||
| @ -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." | ||||
|  | ||||
| @ -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 向执行器返回错误消息和类似的质询。" | ||||
|  | ||||
| @ -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 向执行器返回错误消息和类似的质询。" | ||||
|  | ||||
| @ -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 向执行器返回错误消息和类似的质询。" | ||||
|  | ||||
| @ -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<Flow, string> { | ||||
|         `; | ||||
|     } | ||||
|  | ||||
|     renderDeniedAction(): TemplateResult { | ||||
|         return html` <option | ||||
|                 value=${DeniedActionEnum.MessageContinue} | ||||
|                 ?selected=${this.instance?.deniedAction === DeniedActionEnum.MessageContinue} | ||||
|             > | ||||
|                 ${t`MESSAGE_CONTINUE will follow the ?next parameter if set, otherwise show a message.`} | ||||
|             </option> | ||||
|             <option | ||||
|                 value=${DeniedActionEnum.Continue} | ||||
|                 ?selected=${this.instance?.deniedAction === DeniedActionEnum.Continue} | ||||
|             > | ||||
|                 ${t`CONTINUE will either follow the ?next parameter or redirect to the default interface.`} | ||||
|             </option> | ||||
|             <option | ||||
|                 value=${DeniedActionEnum.Message} | ||||
|                 ?selected=${this.instance?.deniedAction === DeniedActionEnum.Message} | ||||
|             > | ||||
|                 ${t`MESSAGE will notify the user the flow isn't applicable.`} | ||||
|             </option>`; | ||||
|     } | ||||
|  | ||||
|     renderLayout(): TemplateResult { | ||||
|         return html` | ||||
|             <option | ||||
| @ -218,6 +240,18 @@ export class FlowForm extends ModelForm<Flow, string> { | ||||
|                     ${t`Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik.`} | ||||
|                 </p> | ||||
|             </ak-form-element-horizontal> | ||||
|             <ak-form-element-horizontal | ||||
|                 label=${t`Denied action`} | ||||
|                 ?required=${true} | ||||
|                 name="deniedAction" | ||||
|             > | ||||
|                 <select class="pf-c-form-control"> | ||||
|                     ${this.renderDeniedAction()} | ||||
|                 </select> | ||||
|                 <p class="pf-c-form__helper-text"> | ||||
|                     ${t`Decides the response when a policy denies access to this flow for a user.`} | ||||
|                 </p> | ||||
|             </ak-form-element-horizontal> | ||||
|             <ak-form-element-horizontal label=${t`Layout`} ?required=${true} name="layout"> | ||||
|                 <select class="pf-c-form-control"> | ||||
|                     ${this.renderLayout()} | ||||
|  | ||||
| @ -193,7 +193,7 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> { | ||||
|                         ?selected=${this.instance?.invalidResponseAction === | ||||
|                         InvalidResponseActionEnum.RestartWithContext} | ||||
|                     > | ||||
|                         ${t`RESTART restarts the flow from the beginning, while keeping the flow context.`} | ||||
|                         ${t`RESTART_WITH_CONTEXT restarts the flow from the beginning, while keeping the flow context.`} | ||||
|                     </option> | ||||
|                 </select> | ||||
|                 <p class="pf-c-form__helper-text"> | ||||
|  | ||||
| @ -20,6 +20,14 @@ Flows can have policies assigned to them. These policies determine if the curren | ||||
|  | ||||
| Keep in mind that in certain circumstances, policies cannot match against users and groups as there is no authenticated user yet. | ||||
|  | ||||
| ### Denied action | ||||
|  | ||||
| Configure what happens when access to a flow is denied by a policy. By default, authentik will redirect to a `?next` parameter if set, and otherwise show an error message. | ||||
|  | ||||
| -   `MESSAGE_CONTINUE`: Show a message if no `?next` parameter is set, otherwise redirect. | ||||
| -   `MESSAGE`: Always show error message. | ||||
| -   `CONTINUE`: Always redirect, either to `?next` if set, otherwise to the default interface. | ||||
|  | ||||
| ## Designation | ||||
|  | ||||
| Flows are designated for a single purpose. This designation changes when a flow is used. The following designations are available: | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Jens L
					Jens L