show cache on admin overview, add modal to clear cache, re-add logging to policy
This commit is contained in:
parent
f576985cc9
commit
e0d597eeac
|
@ -152,10 +152,8 @@
|
||||||
<div class="col-xs-6 col-sm-2 col-md-2">
|
<div class="col-xs-6 col-sm-2 col-md-2">
|
||||||
<div class="card-pf card-pf-accented card-pf-aggregate-status">
|
<div class="card-pf card-pf-accented card-pf-aggregate-status">
|
||||||
<h2 class="card-pf-title">
|
<h2 class="card-pf-title">
|
||||||
<a href="#">
|
|
||||||
<span class="pficon-bundle"></span>
|
<span class="pficon-bundle"></span>
|
||||||
<span class="card-pf-aggregate-status-count"></span> {% trans 'Version' %}
|
<span class="card-pf-aggregate-status-count"></span> {% trans 'Version' %}
|
||||||
</a>
|
|
||||||
</h2>
|
</h2>
|
||||||
<div class="card-pf-body">
|
<div class="card-pf-body">
|
||||||
<p class="card-pf-aggregate-status-notifications">
|
<p class="card-pf-aggregate-status-notifications">
|
||||||
|
@ -192,5 +190,59 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-xs-6 col-sm-2 col-md-2">
|
||||||
|
<div class="card-pf card-pf-accented card-pf-aggregate-status">
|
||||||
|
<h2 class="card-pf-title">
|
||||||
|
<span class="pficon-server"></span>
|
||||||
|
<span class="card-pf-aggregate-status-count"></span> {% trans 'Cached Policies' %}
|
||||||
|
</h2>
|
||||||
|
<div class="card-pf-body">
|
||||||
|
<p class="card-pf-aggregate-status-notifications">
|
||||||
|
<span class="card-pf-aggregate-status-notification">
|
||||||
|
<a href="#" data-toggle="modal" data-target="#clearCacheMOdal">
|
||||||
|
{% if cached_policies < 1 %}
|
||||||
|
<span class="pficon-warning-triangle-o" data-toggle="tooltip" data-placement="right"
|
||||||
|
title="{% trans 'No policies cached. Users may experience slow response times.' %}"></span> {{ cached_policies }}
|
||||||
|
{% else %}
|
||||||
|
<span class="pficon pficon-ok"></span>{{ cached_policies }}
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal fade" id="clearCacheMOdal" tabindex="-1" role="dialog" aria-labelledby="clearCacheMOdalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
|
||||||
|
<span class="pficon pficon-close"></span>
|
||||||
|
</button>
|
||||||
|
<h4 class="modal-title" id="clearCacheMOdalLabel">{% trans 'Clear Cache' %}</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form method="post" id="clearForm">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="clear">
|
||||||
|
<p>
|
||||||
|
{% blocktrans %}
|
||||||
|
Are you sure you want to clear the cache? This includes all user sessions and all cached Policy results.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
<h3>
|
||||||
|
{% blocktrans %}
|
||||||
|
This will also log you out.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</h3>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||||
|
<button form="clearForm" type="submit" type="button" class="btn btn-danger">{% trans 'Clear' %}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
"""passbook administration overview"""
|
"""passbook administration overview"""
|
||||||
|
from django.core.cache import cache
|
||||||
|
from django.shortcuts import redirect, reverse
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
from passbook.admin.mixins import AdminRequiredMixin
|
from passbook.admin.mixins import AdminRequiredMixin
|
||||||
|
@ -13,6 +15,12 @@ class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
|
||||||
|
|
||||||
template_name = 'administration/overview.html'
|
template_name = 'administration/overview.html'
|
||||||
|
|
||||||
|
def post(self, *args, **kwargs):
|
||||||
|
if 'clear' in self.request.POST:
|
||||||
|
cache.clear()
|
||||||
|
return redirect(reverse('passbook_core:auth-login'))
|
||||||
|
return self.get(*args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs['application_count'] = len(Application.objects.all())
|
kwargs['application_count'] = len(Application.objects.all())
|
||||||
kwargs['policy_count'] = len(Policy.objects.all())
|
kwargs['policy_count'] = len(Policy.objects.all())
|
||||||
|
@ -25,4 +33,6 @@ class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
|
||||||
kwargs['worker_count'] = len(CELERY_APP.control.ping(timeout=0.5))
|
kwargs['worker_count'] = len(CELERY_APP.control.ping(timeout=0.5))
|
||||||
kwargs['providers_without_application'] = Provider.objects.filter(application=None)
|
kwargs['providers_without_application'] = Provider.objects.filter(application=None)
|
||||||
kwargs['policies_without_attachment'] = len(Policy.objects.filter(policymodel__isnull=True))
|
kwargs['policies_without_attachment'] = len(Policy.objects.filter(policymodel__isnull=True))
|
||||||
|
kwargs['cached_policies'] = len(cache.keys('policy_*'))
|
||||||
|
print(cache.keys('*'))
|
||||||
return super().get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
"""passbook core policy engine"""
|
"""passbook core policy engine"""
|
||||||
# from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from amqp.exceptions import UnexpectedFrame
|
from amqp.exceptions import UnexpectedFrame
|
||||||
from celery import group
|
from celery import group
|
||||||
from celery.exceptions import TimeoutError as CeleryTimeoutError
|
from celery.exceptions import TimeoutError as CeleryTimeoutError
|
||||||
|
@ -9,10 +10,10 @@ from ipware import get_client_ip
|
||||||
from passbook.core.celery import CELERY_APP
|
from passbook.core.celery import CELERY_APP
|
||||||
from passbook.core.models import Policy, User
|
from passbook.core.models import Policy, User
|
||||||
|
|
||||||
# LOGGER = getLogger(__name__)
|
LOGGER = getLogger(__name__)
|
||||||
|
|
||||||
def _cache_key(policy, user):
|
def _cache_key(policy, user):
|
||||||
return "%s#%s" % (policy.uuid, user.pk)
|
return "policy_%s#%s" % (policy.uuid, user.pk)
|
||||||
|
|
||||||
@CELERY_APP.task()
|
@CELERY_APP.task()
|
||||||
def _policy_engine_task(user_pk, policy_pk, **kwargs):
|
def _policy_engine_task(user_pk, policy_pk, **kwargs):
|
||||||
|
@ -23,8 +24,8 @@ def _policy_engine_task(user_pk, policy_pk, **kwargs):
|
||||||
user_obj = User.objects.get(pk=user_pk)
|
user_obj = User.objects.get(pk=user_pk)
|
||||||
for key, value in kwargs.items():
|
for key, value in kwargs.items():
|
||||||
setattr(user_obj, key, value)
|
setattr(user_obj, key, value)
|
||||||
# LOGGER.debug("Running policy `%s`#%s for user %s...", policy_obj.name,
|
LOGGER.debug("Running policy `%s`#%s for user %s...", policy_obj.name,
|
||||||
# policy_obj.pk.hex, user_obj)
|
policy_obj.pk.hex, user_obj)
|
||||||
policy_result = policy_obj.passes(user_obj)
|
policy_result = policy_obj.passes(user_obj)
|
||||||
# Handle policy result correctly if result, message or just result
|
# Handle policy result correctly if result, message or just result
|
||||||
message = None
|
message = None
|
||||||
|
@ -33,10 +34,10 @@ def _policy_engine_task(user_pk, policy_pk, **kwargs):
|
||||||
# Invert result if policy.negate is set
|
# Invert result if policy.negate is set
|
||||||
if policy_obj.negate:
|
if policy_obj.negate:
|
||||||
policy_result = not policy_result
|
policy_result = not policy_result
|
||||||
# LOGGER.debug("Policy %r#%s got %s", policy_obj.name, policy_obj.pk.hex, policy_result)
|
LOGGER.debug("Policy %r#%s got %s", policy_obj.name, policy_obj.pk.hex, policy_result)
|
||||||
cache_key = _cache_key(policy_obj, user_obj)
|
cache_key = _cache_key(policy_obj, user_obj)
|
||||||
cache.set(cache_key, (policy_obj.action, policy_result, message))
|
cache.set(cache_key, (policy_obj.action, policy_result, message))
|
||||||
# LOGGER.debug("Cached entry as %s", cache_key)
|
LOGGER.debug("Cached entry as %s", cache_key)
|
||||||
return policy_obj.action, policy_result, message
|
return policy_obj.action, policy_result, message
|
||||||
|
|
||||||
class PolicyEngine:
|
class PolicyEngine:
|
||||||
|
@ -81,16 +82,16 @@ class PolicyEngine:
|
||||||
for policy in self.policies:
|
for policy in self.policies:
|
||||||
cached_policy = cache.get(_cache_key(policy, self.__user), None)
|
cached_policy = cache.get(_cache_key(policy, self.__user), None)
|
||||||
if cached_policy:
|
if cached_policy:
|
||||||
# LOGGER.debug("Taking result from cache for %s", policy.pk.hex)
|
LOGGER.debug("Taking result from cache for %s", policy.pk.hex)
|
||||||
cached_policies.append(cached_policy)
|
cached_policies.append(cached_policy)
|
||||||
else:
|
else:
|
||||||
# LOGGER.debug("Evaluating policy %s", policy.pk.hex)
|
LOGGER.debug("Evaluating policy %s", policy.pk.hex)
|
||||||
signatures.append(_policy_engine_task.signature(
|
signatures.append(_policy_engine_task.signature(
|
||||||
args=(self.__user.pk, policy.pk.hex),
|
args=(self.__user.pk, policy.pk.hex),
|
||||||
kwargs=kwargs,
|
kwargs=kwargs,
|
||||||
time_limit=policy.timeout))
|
time_limit=policy.timeout))
|
||||||
self.__get_timeout += policy.timeout
|
self.__get_timeout += policy.timeout
|
||||||
# LOGGER.debug("Set total policy timeout to %r", self.__get_timeout)
|
LOGGER.debug("Set total policy timeout to %r", self.__get_timeout)
|
||||||
# If all policies are cached, we have an empty list here.
|
# If all policies are cached, we have an empty list here.
|
||||||
if signatures:
|
if signatures:
|
||||||
self.__group = group(signatures)()
|
self.__group = group(signatures)()
|
||||||
|
@ -119,7 +120,7 @@ class PolicyEngine:
|
||||||
for policy_action, policy_result, policy_message in result:
|
for policy_action, policy_result, policy_message in result:
|
||||||
passing = (policy_action == Policy.ACTION_ALLOW and policy_result) or \
|
passing = (policy_action == Policy.ACTION_ALLOW and policy_result) or \
|
||||||
(policy_action == Policy.ACTION_DENY and not policy_result)
|
(policy_action == Policy.ACTION_DENY and not policy_result)
|
||||||
# LOGGER.debug('Action=%s, Result=%r => %r', policy_action, policy_result, passing)
|
LOGGER.debug('Action=%s, Result=%r => %r', policy_action, policy_result, passing)
|
||||||
if policy_message:
|
if policy_message:
|
||||||
messages.append(policy_message)
|
messages.append(policy_message)
|
||||||
if not passing:
|
if not passing:
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
from passbook.core.models import Application
|
from passbook.core.models import Application
|
||||||
from passbook.core.policies import PolicyEngine
|
from passbook.core.policies import PolicyEngine
|
||||||
|
|
||||||
|
|
Reference in a new issue