admin: expose info as API
This commit is contained in:
parent
c5a6b4961f
commit
189b0ec324
0
passbook/admin/api/__init__.py
Normal file
0
passbook/admin/api/__init__.py
Normal file
80
passbook/admin/api/overview.py
Normal file
80
passbook/admin/api/overview.py
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
"""passbook administration overview"""
|
||||||
|
from django.core.cache import cache
|
||||||
|
from django.http import response
|
||||||
|
from drf_yasg.utils import swagger_auto_schema
|
||||||
|
from rest_framework.fields import SerializerMethodField
|
||||||
|
from rest_framework.permissions import IsAdminUser
|
||||||
|
from rest_framework.request import Request
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.serializers import Serializer
|
||||||
|
from rest_framework.viewsets import ViewSet
|
||||||
|
|
||||||
|
from passbook import __version__
|
||||||
|
from passbook.admin.tasks import VERSION_CACHE_KEY, update_latest_version
|
||||||
|
from passbook.core.models import Provider
|
||||||
|
from passbook.policies.models import Policy
|
||||||
|
from passbook.root.celery import CELERY_APP
|
||||||
|
|
||||||
|
|
||||||
|
class AdministrationOverviewSerializer(Serializer):
|
||||||
|
"""Overview View"""
|
||||||
|
|
||||||
|
version = SerializerMethodField()
|
||||||
|
version_latest = SerializerMethodField()
|
||||||
|
worker_count = SerializerMethodField()
|
||||||
|
providers_without_application = SerializerMethodField()
|
||||||
|
policies_without_binding = SerializerMethodField()
|
||||||
|
cached_policies = SerializerMethodField()
|
||||||
|
cached_flows = SerializerMethodField()
|
||||||
|
|
||||||
|
def get_version(self, _) -> str:
|
||||||
|
"""Get current version"""
|
||||||
|
return __version__
|
||||||
|
|
||||||
|
def get_version_latest(self, _) -> str:
|
||||||
|
"""Get latest version from cache"""
|
||||||
|
version_in_cache = cache.get(VERSION_CACHE_KEY)
|
||||||
|
if not version_in_cache:
|
||||||
|
update_latest_version.delay()
|
||||||
|
return __version__
|
||||||
|
return version_in_cache
|
||||||
|
|
||||||
|
def get_worker_count(self, _) -> int:
|
||||||
|
"""Ping workers"""
|
||||||
|
return len(CELERY_APP.control.ping(timeout=0.5))
|
||||||
|
|
||||||
|
def get_providers_without_application(self, _) -> int:
|
||||||
|
"""Count of providers without application"""
|
||||||
|
return len(Provider.objects.filter(application=None))
|
||||||
|
|
||||||
|
def get_policies_without_binding(self, _) -> int:
|
||||||
|
"""Count of policies not bound or use in prompt stages"""
|
||||||
|
return len(
|
||||||
|
Policy.objects.filter(bindings__isnull=True, promptstage__isnull=True)
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_cached_policies(self, _) -> int:
|
||||||
|
"""Get cached policy count"""
|
||||||
|
return len(cache.keys("policy_*"))
|
||||||
|
|
||||||
|
def get_cached_flows(self, _) -> int:
|
||||||
|
"""Get cached flow count"""
|
||||||
|
return len(cache.keys("flow_*"))
|
||||||
|
|
||||||
|
def create(self, request: Request) -> response:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def update(self, request: Request) -> Response:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class AdministrationOverviewViewSet(ViewSet):
|
||||||
|
"""Return single instance of AdministrationOverviewSerializer"""
|
||||||
|
|
||||||
|
permission_classes = [IsAdminUser]
|
||||||
|
|
||||||
|
@swagger_auto_schema(responses={200: AdministrationOverviewSerializer(many=True)})
|
||||||
|
def list(self, request: Request) -> Response:
|
||||||
|
"""Return single instance of AdministrationOverviewSerializer"""
|
||||||
|
serializer = AdministrationOverviewSerializer(True)
|
||||||
|
return Response(serializer.data)
|
|
@ -25,7 +25,7 @@
|
||||||
<li class="pf-c-nav__item">
|
<li class="pf-c-nav__item">
|
||||||
<a href="{% url 'passbook_admin:overview' %}"
|
<a href="{% url 'passbook_admin:overview' %}"
|
||||||
class="pf-c-nav__link {% is_active 'passbook_admin:overview' %}">
|
class="pf-c-nav__link {% is_active 'passbook_admin:overview' %}">
|
||||||
{% trans 'System Status' %}
|
{% trans 'Overview' %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="pf-c-nav__item">
|
<li class="pf-c-nav__item">
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""passbook administration overview"""
|
"""passbook administration overview"""
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.shortcuts import redirect, reverse
|
from django.shortcuts import redirect, reverse
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
@ -32,6 +33,7 @@ class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
|
||||||
"""Get latest version from cache"""
|
"""Get latest version from cache"""
|
||||||
version_in_cache = cache.get(VERSION_CACHE_KEY)
|
version_in_cache = cache.get(VERSION_CACHE_KEY)
|
||||||
if not version_in_cache:
|
if not version_in_cache:
|
||||||
|
if not settings.DEBUG:
|
||||||
update_latest_version.delay()
|
update_latest_version.delay()
|
||||||
return parse(__version__)
|
return parse(__version__)
|
||||||
return parse(version_in_cache)
|
return parse(version_in_cache)
|
||||||
|
|
|
@ -4,6 +4,7 @@ from drf_yasg import openapi
|
||||||
from drf_yasg.views import get_schema_view
|
from drf_yasg.views import get_schema_view
|
||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
|
|
||||||
|
from passbook.admin.api.overview import AdministrationOverviewViewSet
|
||||||
from passbook.api.permissions import CustomObjectPermissions
|
from passbook.api.permissions import CustomObjectPermissions
|
||||||
from passbook.api.v2.messages import MessagesViewSet
|
from passbook.api.v2.messages import MessagesViewSet
|
||||||
from passbook.audit.api import EventViewSet
|
from passbook.audit.api import EventViewSet
|
||||||
|
@ -51,6 +52,10 @@ router = routers.DefaultRouter()
|
||||||
|
|
||||||
router.register("root/messages", MessagesViewSet, basename="messages")
|
router.register("root/messages", MessagesViewSet, basename="messages")
|
||||||
|
|
||||||
|
router.register(
|
||||||
|
"admin/overview", AdministrationOverviewViewSet, basename="admin_overview"
|
||||||
|
)
|
||||||
|
|
||||||
router.register("core/applications", ApplicationViewSet)
|
router.register("core/applications", ApplicationViewSet)
|
||||||
router.register("core/groups", GroupViewSet)
|
router.register("core/groups", GroupViewSet)
|
||||||
router.register("core/users", UserViewSet)
|
router.register("core/users", UserViewSet)
|
||||||
|
|
46
swagger.yaml
46
swagger.yaml
|
@ -19,6 +19,21 @@ securityDefinitions:
|
||||||
security:
|
security:
|
||||||
- token: []
|
- token: []
|
||||||
paths:
|
paths:
|
||||||
|
/admin/overview/:
|
||||||
|
get:
|
||||||
|
operationId: admin_overview_list
|
||||||
|
description: Return single instance of AdministrationOverviewSerializer
|
||||||
|
parameters: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: ''
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/AdministrationOverview'
|
||||||
|
tags:
|
||||||
|
- admin
|
||||||
|
parameters: []
|
||||||
/audit/events/:
|
/audit/events/:
|
||||||
get:
|
get:
|
||||||
operationId: audit_events_list
|
operationId: audit_events_list
|
||||||
|
@ -5943,6 +5958,37 @@ paths:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
definitions:
|
definitions:
|
||||||
|
AdministrationOverview:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
version:
|
||||||
|
title: Version
|
||||||
|
type: string
|
||||||
|
readOnly: true
|
||||||
|
version_latest:
|
||||||
|
title: Version latest
|
||||||
|
type: string
|
||||||
|
readOnly: true
|
||||||
|
worker_count:
|
||||||
|
title: Worker count
|
||||||
|
type: integer
|
||||||
|
readOnly: true
|
||||||
|
providers_without_application:
|
||||||
|
title: Providers without application
|
||||||
|
type: integer
|
||||||
|
readOnly: true
|
||||||
|
policies_without_binding:
|
||||||
|
title: Policies without binding
|
||||||
|
type: integer
|
||||||
|
readOnly: true
|
||||||
|
cached_policies:
|
||||||
|
title: Cached policies
|
||||||
|
type: integer
|
||||||
|
readOnly: true
|
||||||
|
cached_flows:
|
||||||
|
title: Cached flows
|
||||||
|
type: integer
|
||||||
|
readOnly: true
|
||||||
Event:
|
Event:
|
||||||
required:
|
required:
|
||||||
- action
|
- action
|
||||||
|
|
Reference in a new issue