policies: fix display of policy result source

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-04-04 14:04:41 +02:00
parent 5b5d7e4997
commit 37a14858ad
6 changed files with 61 additions and 50 deletions

View File

@ -39,8 +39,11 @@ class PolicySerializer(ModelSerializer, MetaNameSerializer):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self._resolve_inheritance = resolve_inheritance self._resolve_inheritance = resolve_inheritance
def get_component(self, obj: Policy) -> str: def get_component(self, obj: Policy) -> str: # pragma: no cover
"""Get object component so that we know how to edit the object""" """Get object component so that we know how to edit the object"""
# pyright: reportGeneralTypeIssues=false
if obj.__class__ == Policy:
return ""
return obj.component return obj.component
def get_bound_to(self, obj: Policy) -> int: def get_bound_to(self, obj: Policy) -> int:

View File

@ -149,6 +149,7 @@ class PolicyEngine:
if self.mode == PolicyEngineMode.MODE_ANY: if self.mode == PolicyEngineMode.MODE_ANY:
passing = any(x.passing for x in all_results) passing = any(x.passing for x in all_results)
result = PolicyResult(passing) result = PolicyResult(passing)
result.source_results = all_results
result.messages = tuple(y for x in all_results for y in x.messages) result.messages = tuple(y for x in all_results for y in x.messages)
return result return result

View File

@ -112,10 +112,17 @@ class PolicyBinding(SerializerModel):
return PolicyBindingSerializer return PolicyBindingSerializer
def __str__(self) -> str: def __str__(self) -> str:
suffix = ""
if self.policy:
suffix = f"Policy {self.policy.name}"
if self.group:
suffix = f"Group {self.group.name}"
if self.user:
suffix = f"User {self.user.name}"
try: try:
return f"Policy Binding {self.target} #{self.order} {self.policy}" return f"Binding from {self.target} #{self.order} to {suffix}"
except PolicyBinding.target.RelatedObjectDoesNotExist: # pylint: disable=no-member except PolicyBinding.target.RelatedObjectDoesNotExist: # pylint: disable=no-member
return f"Policy Binding - #{self.order} {self.policy}" return f"Binding - #{self.order} to {suffix}"
class Meta: class Meta:

View File

@ -100,7 +100,7 @@ class PolicyProcess(PROCESS_CLASS):
self.create_event(EventAction.POLICY_EXCEPTION, message=error_string) self.create_event(EventAction.POLICY_EXCEPTION, message=error_string)
LOGGER.debug("P_ENG(proc): error", exc=src_exc) LOGGER.debug("P_ENG(proc): error", exc=src_exc)
policy_result = PolicyResult(False, str(src_exc)) policy_result = PolicyResult(False, str(src_exc))
policy_result.source_policy = self.binding.policy policy_result.source_binding = self.binding
# Invert result if policy.negate is set # Invert result if policy.negate is set
if self.binding.negate: if self.binding.negate:
policy_result.passing = not policy_result.passing policy_result.passing = not policy_result.passing

View File

@ -3,58 +3,58 @@
{% load static %} {% load static %}
{% load i18n %} {% load i18n %}
{% block title %}
{% trans 'Permission denied - authentik' %}
{% endblock %}
{% block card_title %} {% block card_title %}
{% trans 'Permission denied' %} {% trans 'Permission denied' %}
{% endblock %} {% endblock %}
{% block title %}
{% trans 'Permission denied' %}
{% endblock %}
{% block card %} {% block card %}
<form method="POST" class="pf-c-form"> <form method="POST" class="pf-c-form">
{% csrf_token %} {% csrf_token %}
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<p> <p>
<i class="pf-icon pf-icon-error-circle-o"></i> <i class="pf-icon pf-icon-error-circle-o"></i>
{% trans 'Request has been denied.' %} {% trans 'Request has been denied.' %}
</p> </p>
{% if error %} {% if error %}
<hr> <hr>
<p> <p>
{{ error }} {{ error }}
</p> </p>
{% endif %} {% endif %}
{% if policy_result %} {% if policy_result %}
<hr> <hr>
<em>{% trans 'Messages:' %}</em> <em>{% trans 'Messages:' %}</em>
<ul class="pf-c-list">
{% for message in policy_result.messages %}
<li>
{{ message }}
</li>
{% endfor %}
</ul>
{% if policy_result.source_results %}
<em>{% trans 'Explanation:' %}</em>
<ul class="pf-c-list"> <ul class="pf-c-list">
{% for message in policy_result.messages %} {% for source_result in policy_result.source_results %}
<li> <li>
{{ message }} {% blocktrans with name=source_result.source_binding result=source_result.passing %}
Policy binding '{{ name }}' returned result '{{ result }}'
{% endblocktrans %}
{% if source_result.messages %}
<ul class="pf-c-list">
{% for message in source_result.messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>
{% if policy_result.source_results %}
<em>{% trans 'Explanation:' %}</em>
<ul class="pf-c-list">
{% for source_result in policy_result.source_results %}
<li>
{% blocktrans with name=source_result.source_policy.name result=source_result.passing %}
Policy '{{ name }}' returned result '{{ result }}'
{% endblocktrans %}
{% if source_result.messages %}
<ul class="pf-c-list">
{% for message in source_result.messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
{% endif %} {% endif %}
</div> {% endif %}
</form> </div>
</form>
{% endblock %} {% endblock %}

View File

@ -14,7 +14,7 @@ from authentik.lib.utils.http import get_client_ip
if TYPE_CHECKING: if TYPE_CHECKING:
from authentik.core.models import User from authentik.core.models import User
from authentik.policies.models import Policy from authentik.policies.models import PolicyBinding
LOGGER = get_logger() LOGGER = get_logger()
@ -61,14 +61,14 @@ class PolicyResult:
passing: bool passing: bool
messages: tuple[str, ...] messages: tuple[str, ...]
source_policy: Optional[Policy] source_binding: Optional["PolicyBinding"]
source_results: Optional[list["PolicyResult"]] source_results: Optional[list["PolicyResult"]]
def __init__(self, passing: bool, *messages: str): def __init__(self, passing: bool, *messages: str):
super().__init__() super().__init__()
self.passing = passing self.passing = passing
self.messages = messages self.messages = messages
self.source_policy = None self.source_binding = None
self.source_results = [] self.source_results = []
def __repr__(self): def __repr__(self):