2b1356bb91
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>
70 lines
2.1 KiB
Python
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
|