This repository has been archived on 2024-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
authentik/authentik/flows/markers.py
Jens Langhammer 2b1356bb91 flows: add invalid_response_action to configure how the FlowExecutor should handle invalid responses
closes #1079

Default value of `retry` behaves like previous version.

`restart` and `restart_with_context` restart the flow upon an invalid response. `restart_with_context` keeps the same context of the Flow, allowing users to bind policies that maybe aren't valid on the first execution, but are after a retry, like a reputation policy with a deny stage.

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-06-28 00:22:09 +02:00

70 lines
2.1 KiB
Python

"""Stage Markers"""
from dataclasses import dataclass
from typing import TYPE_CHECKING, Optional
from django.http.request import HttpRequest
from structlog.stdlib import get_logger
from authentik.flows.models import FlowStageBinding
from authentik.policies.engine import PolicyEngine
from authentik.policies.models import PolicyBinding
if TYPE_CHECKING:
from authentik.flows.planner import FlowPlan
LOGGER = get_logger()
@dataclass
class StageMarker:
"""Base stage marker class, no extra attributes, and has no special handler."""
# pylint: disable=unused-argument
def process(
self,
plan: "FlowPlan",
binding: FlowStageBinding,
http_request: HttpRequest,
) -> Optional[FlowStageBinding]:
"""Process callback for this marker. This should be overridden by sub-classes.
If a stage should be removed, return None."""
return binding
@dataclass
class ReevaluateMarker(StageMarker):
"""Reevaluate Marker, forces stage's policies to be evaluated again."""
binding: PolicyBinding
def process(
self,
plan: "FlowPlan",
binding: FlowStageBinding,
http_request: HttpRequest,
) -> Optional[FlowStageBinding]:
"""Re-evaluate policies bound to stage, and if they fail, remove from plan"""
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
LOGGER.debug(
"f(plan_inst)[re-eval marker]: running re-evaluation",
binding=binding,
policy_binding=self.binding,
)
engine = PolicyEngine(
self.binding, plan.context.get(PLAN_CONTEXT_PENDING_USER, http_request.user)
)
engine.use_cache = False
engine.request.set_http_request(http_request)
engine.request.context = plan.context
engine.build()
result = engine.result
if result.passing:
return binding
LOGGER.warning(
"f(plan_inst)[re-eval marker]: binding failed re-evaluation",
binding=binding,
messages=result.messages,
)
return None