admin: improve overview, re-add links

closes #270
This commit is contained in:
Jens Langhammer 2020-10-16 20:00:17 +02:00
parent 897f64600a
commit dfedd4a7f1
3 changed files with 86 additions and 38 deletions

View File

@ -11,7 +11,7 @@
</section> </section>
<section class="pf-c-page__main-section"> <section class="pf-c-page__main-section">
<div class="pf-l-gallery pf-m-gutter"> <div class="pf-l-gallery pf-m-gutter">
<div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-4-col" style="grid-column-end: span 3;grid-row-end: span 2;"> <div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-4-col" style="grid-column-end: span 3;grid-row-end: span 5;">
<div class="pf-c-card__header"> <div class="pf-c-card__header">
<div class="pf-c-card__header-main"> <div class="pf-c-card__header-main">
<i class="pf-icon pf-icon-server"></i> {% trans 'Logins over the last 24 hours' %} <i class="pf-icon pf-icon-server"></i> {% trans 'Logins over the last 24 hours' %}
@ -56,19 +56,22 @@
</div> </div>
<div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-compact"> <div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-compact">
<div class="pf-c-card__header"> <div class="pf-c-card__header pf-l-flex pf-m-justify-content-space-between">
<div class="pf-c-card__header-main"> <div class="pf-c-card__header-main">
<i class="pf-icon pf-icon-plugged"></i> {% trans 'Providers' %} <i class="pf-icon pf-icon-plugged"></i> {% trans 'Providers' %}
</div> </div>
<a href="{% url 'passbook_admin:providers' %}">
<i class="fa fa-external-link-alt"> </i>
</a>
</div> </div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
{% if providers_without_application.exists %} {% if providers_without_application.exists %}
<p class="aggregate-status"> <p class="pb-aggregate-card">
<i class="fa fa-exclamation-triangle"></i> {{ provider_count }} <i class="fa fa-exclamation-triangle"></i> {{ provider_count }}
</p> </p>
<p>{% trans 'Warning: At least one Provider has no application assigned.' %}</p> <p>{% trans 'Warning: At least one Provider has no application assigned.' %}</p>
{% else %} {% else %}
<p class="aggregate-status"> <p class="pb-aggregate-card">
<i class="fa fa-check-circle"></i> {{ provider_count }} <i class="fa fa-check-circle"></i> {{ provider_count }}
</p> </p>
{% endif %} {% endif %}
@ -76,19 +79,22 @@
</div> </div>
<div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-compact"> <div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-compact">
<div class="pf-c-card__header"> <div class="pf-c-card__header pf-l-flex pf-m-justify-content-space-between">
<div class="pf-c-card__header-main"> <div class="pf-c-card__header-main">
<i class="pf-icon pf-icon-infrastructure"></i> {% trans 'Policies' %} <i class="pf-icon pf-icon-infrastructure"></i> {% trans 'Policies' %}
</div> </div>
<a href="{% url 'passbook_admin:policies' %}">
<i class="fa fa-external-link-alt"> </i>
</a>
</div> </div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
{% if policies_without_binding %} {% if policies_without_binding %}
<p class="aggregate-status"> <p class="pb-aggregate-card">
<i class="fa fa-exclamation-triangle"></i> {{ policy_count }} <i class="fa fa-exclamation-triangle"></i> {{ policy_count }}
</p> </p>
<p>{% trans 'Policies without binding exist.' %}</p> <p>{% trans 'Policies without binding exist.' %}</p>
{% else %} {% else %}
<p class="aggregate-status"> <p class="pb-aggregate-card">
<i class="fa fa-check-circle"></i> {{ policy_count }} <i class="fa fa-check-circle"></i> {{ policy_count }}
</p> </p>
{% endif %} {% endif %}
@ -96,26 +102,32 @@
</div> </div>
<div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-compact"> <div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-compact">
<div class="pf-c-card__header"> <div class="pf-c-card__header pf-l-flex pf-m-justify-content-space-between">
<div class="pf-c-card__header-main"> <div class="pf-c-card__header-main">
<i class="pf-icon pf-icon-user"></i> {% trans 'Users' %} <i class="pf-icon pf-icon-user"></i> {% trans 'Users' %}
</div> </div>
<a href="{% url 'passbook_admin:users' %}">
<i class="fa fa-external-link-alt"> </i>
</a>
</div> </div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<p class="aggregate-status"> <p class="pb-aggregate-card">
<i class="fa fa-check-circle"></i> {{ user_count }} <i class="fa fa-check-circle"></i> {{ user_count }}
</p> </p>
</div> </div>
</div> </div>
<div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-compact"> <div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-compact">
<div class="pf-c-card__header"> <div class="pf-c-card__header pf-l-flex pf-m-justify-content-space-between">
<div class="pf-c-card__header-main"> <div class="pf-c-card__header-main">
<i class="pf-icon pf-icon-bundle"></i> {% trans 'Version' %} <i class="pf-icon pf-icon-bundle"></i> {% trans 'Version' %}
</div> </div>
<a href="https://github.com/BeryJu/passbook/releases" target="_blank">
<i class="fa fa-external-link-alt"> </i>
</a>
</div> </div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<p class="aggregate-status"> <p class="pb-aggregate-card">
{% if version >= version_latest %} {% if version >= version_latest %}
<i class="fa fa-check-circle"></i> {{ version }} <i class="fa fa-check-circle"></i> {{ version }}
{% else %} {% else %}
@ -142,13 +154,13 @@
</div> </div>
<fetch-fill-slot class="pf-c-card__body" url="{% url 'passbook_api:admin_overview-list' %}" key="worker_count"> <fetch-fill-slot class="pf-c-card__body" url="{% url 'passbook_api:admin_overview-list' %}" key="worker_count">
<div slot="value < 1"> <div slot="value < 1">
<p class="aggregate-status"> <p class="pb-aggregate-card">
<i class="fa fa-exclamation-triangle"></i> <span data-value></span> <i class="fa fa-exclamation-triangle"></i> <span data-value></span>
</p> </p>
<p>{% trans 'No workers connected.' %}</p> <p>{% trans 'No workers connected.' %}</p>
</div> </div>
<div slot="value >= 1"> <div slot="value >= 1">
<p class="aggregate-status"> <p class="pb-aggregate-card">
<i class="fa fa-check-circle"></i> <span data-value></span> <i class="fa fa-check-circle"></i> <span data-value></span>
</p> </p>
</div> </div>
@ -162,40 +174,46 @@
</fetch-fill-slot> </fetch-fill-slot>
</div> </div>
<a class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-hoverable pf-m-compact" data-target="modal" data-modal="clearCacheModalRoot"> <div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-compact">
<div class="pf-c-card__header"> <div class="pf-c-card__header pf-l-flex pf-m-justify-content-space-between">
<div class="pf-c-card__header-main"> <div class="pf-c-card__header-main">
<i class="pf-icon pf-icon-server"></i> {% trans 'Cached Policies' %} <i class="pf-icon pf-icon-server"></i> {% trans 'Cached Policies' %}
</div> </div>
<a data-target="modal" data-modal="clearPolicyCache">
<i class="fa fa-trash"> </i>
</a>
</div> </div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
{% if cached_policies < 1 %} {% if cached_policies < 1 %}
<p class="aggregate-status"> <p class="pb-aggregate-card">
<i class="fa fa-exclamation-triangle"></i> {{ cached_policies }} <i class="fa fa-exclamation-triangle"></i> {{ cached_policies }}
</p> </p>
<p>{% trans 'No policies cached. Users may experience slow response times.' %}</p> <p>{% trans 'No policies cached. Users may experience slow response times.' %}</p>
{% else %} {% else %}
<p class="aggregate-status"> <p class="pb-aggregate-card">
<i class="fa fa-check-circle"></i> {{ cached_policies }} <i class="fa fa-check-circle"></i> {{ cached_policies }}
</p> </p>
{% endif %} {% endif %}
</div> </div>
</a> </div>
<div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-compact"> <div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-compact">
<div class="pf-c-card__header"> <div class="pf-c-card__header pf-l-flex pf-m-justify-content-space-between">
<div class="pf-c-card__header-main"> <div class="pf-c-card__header-main">
<i class="pf-icon pf-icon-server"></i> {% trans 'Cached Flows' %} <i class="pf-icon pf-icon-server"></i> {% trans 'Cached Flows' %}
</div> </div>
<a data-target="modal" data-modal="clearFlowCache">
<i class="fa fa-trash"> </i>
</a>
</div> </div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
{% if cached_flows < 1 %} {% if cached_flows < 1 %}
<p class="aggregate-status"> <p class="pb-aggregate-card">
<span class="fa fa-exclamation-triangle"></span> {{ cached_flows }} <span class="fa fa-exclamation-triangle"></span> {{ cached_flows }}
</p> </p>
<p>{% trans 'No flows cached.' %}</p> <p>{% trans 'No flows cached.' %}</p>
{% else %} {% else %}
<p class="aggregate-status"> <p class="pb-aggregate-card">
<i class="fa fa-check-circle"></i> {{ cached_flows }} <i class="fa fa-check-circle"></i> {{ cached_flows }}
</p> </p>
{% endif %} {% endif %}
@ -203,33 +221,57 @@
</div> </div>
</section> </section>
</div> </div>
<div class="pf-c-backdrop" id="clearCacheModalRoot" hidden>
<div class="pf-c-backdrop" id="clearPolicyCache" hidden>
<div class="pf-l-bullseye"> <div class="pf-l-bullseye">
<div class="pf-c-modal-box pf-m-sm" role="dialog"> <div class="pf-c-modal-box pf-m-sm" role="dialog">
<button data-modal-close class="pf-c-button pf-m-plain" type="button" aria-label="Close dialog"> <button data-modal-close class="pf-c-button pf-m-plain" type="button" aria-label="Close dialog">
<i class="fas fa-times" aria-hidden="true"></i> <i class="fas fa-times" aria-hidden="true"></i>
</button> </button>
<div class="pf-c-modal-box__header"> <div class="pf-c-modal-box__header">
<h1 class="pf-c-title pf-m-2xl" id="modal-title">{% trans 'Clear Cache' %}?</h1> <h1 class="pf-c-title pf-m-2xl" id="modal-title">{% trans 'Clear Policy Cache' %}?</h1>
</div> </div>
<div class="pf-c-modal-box__body" id="modal-description"> <div class="pf-c-modal-box__body" id="modal-description">
<form method="post" id="clearForm"> <form method="post" id="clear_policies">
{% csrf_token %} {% csrf_token %}
<input type="hidden" name="clear"> <input type="hidden" name="clear_policies">
<p> <p>
{% blocktrans %} {% blocktrans %}
Are you sure you want to clear the cache? This includes all user sessions and all cached Policy results. Are you sure you want to clear the policy cache? This will cause all policies to be re-evaluated on their next usage.
{% endblocktrans %} {% endblocktrans %}
</p> </p>
<h3>
{% blocktrans %}
This will also log you out.
{% endblocktrans %}
</h3>
</form> </form>
</div> </div>
<footer class="pf-c-modal-box__footer pf-m-align-left"> <footer class="pf-c-modal-box__footer pf-m-align-left">
<button form="clearForm" class="pf-c-button pf-m-primary" type="submit">{% trans 'Clear' %}</button> <button form="clear_policies" class="pf-c-button pf-m-primary" type="submit">{% trans 'Clear' %}</button>
<button data-modal-close class="pf-c-button pf-m-link" type="button">{% trans 'Cancel' %}</button>
</footer>
</div>
</div>
</div>
<div class="pf-c-backdrop" id="clearFlowCache" hidden>
<div class="pf-l-bullseye">
<div class="pf-c-modal-box pf-m-sm" role="dialog">
<button data-modal-close class="pf-c-button pf-m-plain" type="button" aria-label="Close dialog">
<i class="fas fa-times" aria-hidden="true"></i>
</button>
<div class="pf-c-modal-box__header">
<h1 class="pf-c-title pf-m-2xl" id="modal-title">{% trans 'Clear Flow Cache' %}?</h1>
</div>
<div class="pf-c-modal-box__body" id="modal-description">
<form method="post" id="clear_flows">
{% csrf_token %}
<input type="hidden" name="clear_flows">
<p>
{% blocktrans %}
Are you sure you want to clear the flow cache? This will cause all flows to be re-evaluated on their next usage.
{% endblocktrans %}
</p>
</form>
</div>
<footer class="pf-c-modal-box__footer pf-m-align-left">
<button form="clear_flows" class="pf-c-button pf-m-primary" type="submit">{% trans 'Clear' %}</button>
<button data-modal-close class="pf-c-button pf-m-link" type="button">{% trans 'Cancel' %}</button> <button data-modal-close class="pf-c-button pf-m-link" type="button">{% trans 'Cancel' %}</button>
</footer> </footer>
</div> </div>
@ -274,7 +316,6 @@ fetch("{% url 'passbook_api:admin_metrics-list' %}").then(r => r.json()).then(r
const date = new Date(); const date = new Date();
const delta = (date - values[index].value); const delta = (date - values[index].value);
const ago = Math.round(delta / 1000 / 3600); const ago = Math.round(delta / 1000 / 3600);
console.log(ago);
return `${ago} Hours ago`; return `${ago} Hours ago`;
}, },
autoSkip: true, autoSkip: true,

View File

@ -5,9 +5,9 @@ from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.db.models import Count from django.db.models import Count
from django.db.models.fields.json import KeyTextTransform from django.db.models.fields.json import KeyTextTransform
from django.shortcuts import redirect, reverse
from django.views.generic import TemplateView from django.views.generic import TemplateView
from packaging.version import LegacyVersion, Version, parse from packaging.version import LegacyVersion, Version, parse
from structlog import get_logger
from passbook import __version__ from passbook import __version__
from passbook.admin.mixins import AdminRequiredMixin from passbook.admin.mixins import AdminRequiredMixin
@ -16,6 +16,8 @@ from passbook.audit.models import Event, EventAction
from passbook.core.models import Provider, User from passbook.core.models import Provider, User
from passbook.policies.models import Policy from passbook.policies.models import Policy
LOGGER = get_logger()
class AdministrationOverviewView(AdminRequiredMixin, TemplateView): class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
"""Overview View""" """Overview View"""
@ -24,9 +26,14 @@ class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
def post(self, *args, **kwargs): def post(self, *args, **kwargs):
"""Handle post (clear cache from modal)""" """Handle post (clear cache from modal)"""
if "clear" in self.request.POST: if "clear_policies" in self.request.POST:
cache.clear() keys = cache.keys("policy_*")
return redirect(reverse("passbook_flows:default-authentication")) cache.delete_many(keys)
LOGGER.debug("Cleared Policy cache", keys=len(keys))
if "clear_flows" in self.request.POST:
keys = cache.keys("flow_*")
cache.delete_many(keys)
LOGGER.debug("Cleared flow cache", keys=len(keys))
return self.get(*args, **kwargs) return self.get(*args, **kwargs)
def get_latest_version(self) -> Union[LegacyVersion, Version]: def get_latest_version(self) -> Union[LegacyVersion, Version]:

View File

@ -291,7 +291,7 @@ input[data-is-monospace] {
} }
/* Aggregate Cards */ /* Aggregate Cards */
.pf-c-card.pf-c-card-aggregate > .pf-c-card__body .aggregate-status { .pb-aggregate-card {
font-size: var(--pf-global--icon--FontSize--lg); font-size: var(--pf-global--icon--FontSize--lg);
text-align: center; text-align: center;
} }