diff --git a/passbook/policies/engine.py b/passbook/policies/engine.py index 3d2d4afe1..7547e341c 100644 --- a/passbook/policies/engine.py +++ b/passbook/policies/engine.py @@ -109,19 +109,23 @@ class PolicyEngine: @property def result(self) -> PolicyResult: """Get policy-checking result""" - messages: List[str] = [] process_results: List[PolicyResult] = [ x.result for x in self.__processes if x.result ] + final_result = PolicyResult(False) + final_result.messages = [] + final_result.source_results = list(process_results + self.__cached_policies) for result in process_results + self.__cached_policies: LOGGER.debug( "P_ENG: result", passing=result.passing, messages=result.messages ) if result.messages: - messages += result.messages + final_result.messages.extend(result.messages) if not result.passing: - return PolicyResult(False, *messages) - return PolicyResult(True, *messages) + final_result.passing = False + return final_result + final_result.passing = True + return final_result @property def passing(self) -> bool: diff --git a/passbook/policies/expression/templates/policy/expression/form.html b/passbook/policies/expression/templates/policy/expression/form.html index 95b3a8fb9..5a1f354db 100644 --- a/passbook/policies/expression/templates/policy/expression/form.html +++ b/passbook/policies/expression/templates/policy/expression/form.html @@ -7,7 +7,7 @@

- Expression using Python. See here for a list of all variables. + Expression using Python. See here for a list of all variables.

diff --git a/passbook/policies/mixins.py b/passbook/policies/mixins.py index 4712b0df0..712f00cee 100644 --- a/passbook/policies/mixins.py +++ b/passbook/policies/mixins.py @@ -10,7 +10,11 @@ from django.utils.translation import gettext as _ from structlog import get_logger from passbook.core.models import Application, Provider, User -from passbook.flows.views import SESSION_KEY_APPLICATION_PRE +from passbook.flows.views import ( + SESSION_KEY_APPLICATION_PRE, + SESSION_KEY_DENIED_ERROR, + SESSION_KEY_DENIED_POLICY_RESULT, +) from passbook.policies.engine import PolicyEngine from passbook.policies.types import PolicyResult @@ -36,8 +40,12 @@ class PolicyAccessMixin(BaseMixin, AccessMixin): self.get_redirect_field_name(), ) - def handle_no_permission_authorized(self) -> HttpResponse: - """Function called when user has no permissions but is authorized""" + def handle_no_permission_authenticated( + self, result: Optional[PolicyResult] = None + ) -> HttpResponse: + """Function called when user has no permissions but is authenticated""" + if result: + self.request.session[SESSION_KEY_DENIED_POLICY_RESULT] = result # TODO: Remove this URL and render the view instead return redirect("passbook_flows:denied") diff --git a/passbook/policies/process.py b/passbook/policies/process.py index a578a4b2a..137eb99b8 100644 --- a/passbook/policies/process.py +++ b/passbook/policies/process.py @@ -9,7 +9,7 @@ from sentry_sdk.tracing import Span from structlog import get_logger from passbook.policies.exceptions import PolicyException -from passbook.policies.models import PolicyBinding +from passbook.policies.models import Policy, PolicyBinding from passbook.policies.types import PolicyRequest, PolicyResult LOGGER = get_logger() @@ -63,6 +63,7 @@ class PolicyProcess(Process): except PolicyException as exc: LOGGER.debug("P_ENG(proc): error", exc=exc) policy_result = PolicyResult(False, str(exc)) + policy_result.source_policy = self.binding.policy # Invert result if policy.negate is set if self.binding.negate: policy_result.passing = not policy_result.passing diff --git a/passbook/policies/types.py b/passbook/policies/types.py index da956c75e..1b759b802 100644 --- a/passbook/policies/types.py +++ b/passbook/policies/types.py @@ -1,13 +1,15 @@ """policy structures""" from __future__ import annotations -from typing import TYPE_CHECKING, Dict, Optional, Tuple +from dataclasses import field +from typing import TYPE_CHECKING, Dict, List, Optional, Tuple from django.db.models import Model from django.http import HttpRequest if TYPE_CHECKING: from passbook.core.models import User + from passbook.policies.models import Policy class PolicyRequest: @@ -34,9 +36,14 @@ class PolicyResult: passing: bool messages: Tuple[str, ...] + source_policy: Optional[Policy] + source_results: Optional[List["PolicyResult"]] + def __init__(self, passing: bool, *messages: str): self.passing = passing self.messages = messages + self.source_policy = None + self.source_results = [] def __repr__(self): return self.__str__()