2020-06-18 20:43:51 +00:00
|
|
|
"""Stage Markers"""
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from typing import TYPE_CHECKING, Optional
|
|
|
|
|
2020-10-20 13:06:36 +00:00
|
|
|
from django.http.request import HttpRequest
|
2020-06-18 20:43:51 +00:00
|
|
|
from structlog import get_logger
|
|
|
|
|
|
|
|
from passbook.core.models import User
|
|
|
|
from passbook.flows.models import Stage
|
|
|
|
from passbook.policies.engine import PolicyEngine
|
|
|
|
from passbook.policies.models import PolicyBinding
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
from passbook.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
|
2020-10-20 13:06:36 +00:00
|
|
|
def process(
|
|
|
|
self, plan: "FlowPlan", stage: Stage, http_request: Optional[HttpRequest]
|
|
|
|
) -> Optional[Stage]:
|
2020-06-18 20:43:51 +00:00
|
|
|
"""Process callback for this marker. This should be overridden by sub-classes.
|
|
|
|
If a stage should be removed, return None."""
|
|
|
|
return stage
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class ReevaluateMarker(StageMarker):
|
|
|
|
"""Reevaluate Marker, forces stage's policies to be evaluated again."""
|
|
|
|
|
|
|
|
binding: PolicyBinding
|
|
|
|
user: User
|
|
|
|
|
2020-10-20 13:06:36 +00:00
|
|
|
def process(
|
|
|
|
self, plan: "FlowPlan", stage: Stage, http_request: Optional[HttpRequest]
|
|
|
|
) -> Optional[Stage]:
|
2020-06-18 20:43:51 +00:00
|
|
|
"""Re-evaluate policies bound to stage, and if they fail, remove from plan"""
|
|
|
|
engine = PolicyEngine(self.binding, self.user)
|
2020-06-18 20:54:09 +00:00
|
|
|
engine.use_cache = False
|
2020-10-20 13:06:36 +00:00
|
|
|
if http_request:
|
|
|
|
engine.request.http_request = http_request
|
2020-06-18 20:43:51 +00:00
|
|
|
engine.request.context = plan.context
|
|
|
|
engine.build()
|
|
|
|
result = engine.result
|
|
|
|
if result.passing:
|
|
|
|
return stage
|
|
|
|
LOGGER.warning(
|
|
|
|
"f(plan_inst)[re-eval marker]: stage failed re-evaluation",
|
|
|
|
stage=stage,
|
|
|
|
messages=result.messages,
|
|
|
|
)
|
|
|
|
return None
|