diff --git a/allianceauth/services/modules/mumble/models.py b/allianceauth/services/modules/mumble/models.py index 72ab63fc..8c7d0ead 100644 --- a/allianceauth/services/modules/mumble/models.py +++ b/allianceauth/services/modules/mumble/models.py @@ -90,7 +90,7 @@ class MumbleUser(AbstractServiceModel): blank=True, null=True, editable=False, - help_text="The Mumble Release the user last authenticated with" + help_text="Client release. For official releases, this equals the version. For snapshots and git compiles, this will be something else." ) version = models.IntegerField( verbose_name="Mumble Version", @@ -159,4 +159,5 @@ class MumbleUser(AbstractServiceModel): class Meta: permissions = ( ("access_mumble", "Can access the Mumble service"), + ("view_connection_history", "Can access the connection history of the Mumble service"), ) diff --git a/allianceauth/services/modules/mumble/templates/services/mumble/mumble_connection_history.html b/allianceauth/services/modules/mumble/templates/services/mumble/mumble_connection_history.html new file mode 100644 index 00000000..536e3d39 --- /dev/null +++ b/allianceauth/services/modules/mumble/templates/services/mumble/mumble_connection_history.html @@ -0,0 +1,205 @@ +{% extends "allianceauth/base-bs5.html" %} + +{% load i18n %} + +{% block page_title %} + {% translate "Mumble" %} +{% endblock page_title %} + +{% block header_nav_brand %} + {% trans "Mumble History" %} - {{ mumble_url }} +{% endblock header_nav_brand %} + +{% block header_nav_collapse_left %} +{% endblock header_nav_collapse_left %} + +{% block header_nav_collapse_right %} +{% endblock header_nav_collapse_right %} + +{% block content %} +
+
+ {% translate "Server Connection History" %} +
+ +
+
+ + + + + + + + + + + +
{% translate "User" %}{% translate "Displayed Name" %}{% translate "Release" %}{% translate "Version" %}{% translate "Last Connect" %}{% translate "Last Disconnect" %}
+
+
+
+ +
+
+
+
+ {% translate "Server Connection Breakdown" %} +
+ +
+ +
+
+
+ +
+
+
+ {% translate "Server Connection Breakdown" %} +
+ +
+
+ + + + + + + +
{% translate "Version" %}{% translate "Number" %}
+
+
+
+
+
+{% endblock content %} + +{% block extra_javascript %} + {% include "bundles/datatables-js-bs5.html" %} + {% include "bundles/filterdropdown-js.html" %} + {% include "bundles/chart-js.html" %} + {% include "bundles/moment-js.html" with locale=True %} + + +{% endblock extra_javascript %} + +{% block extra_css %} + {% include "bundles/datatables-css-bs5.html" %} +{% endblock extra_css %} diff --git a/allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html b/allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html index e140ee7c..cf122157 100644 --- a/allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html +++ b/allianceauth/services/modules/mumble/templates/services/mumble/mumble_service_ctrl.html @@ -48,4 +48,9 @@ {% endif %} {% endif %} + {% if request.user.is_superuser %} + + History + +{% endif %} {% endblock %} diff --git a/allianceauth/services/modules/mumble/urls.py b/allianceauth/services/modules/mumble/urls.py index ef7ff699..d3276e0b 100644 --- a/allianceauth/services/modules/mumble/urls.py +++ b/allianceauth/services/modules/mumble/urls.py @@ -10,6 +10,10 @@ module_urls = [ path('deactivate/', views.DeleteMumbleView.as_view(), name='deactivate'), path('reset_password/', views.ResetPasswordMumbleView.as_view(), name='reset_password'), path('set_password/', views.SetPasswordMumbleView.as_view(), name='set_password'), + path('connection_history/', views.connection_history, name="connection_history"), + path('ajax/connection_history_data', views.connection_history_data, name="connection_history_data"), + path('ajax/release_counts_data', views.release_counts_data, name="release_counts_data"), + path('ajax/release_pie_chart_data', views.release_pie_chart_data, name="release_pie_chart_data"), ] urlpatterns = [ diff --git a/allianceauth/services/modules/mumble/views.py b/allianceauth/services/modules/mumble/views.py index ba8904fd..7dd07c82 100644 --- a/allianceauth/services/modules/mumble/views.py +++ b/allianceauth/services/modules/mumble/views.py @@ -3,6 +3,11 @@ import logging from allianceauth.services.forms import ServicePasswordModelForm from allianceauth.services.abstract import BaseCreatePasswordServiceAccountView, BaseDeactivateServiceAccountView, \ BaseResetPasswordServiceAccountView, BaseSetPasswordServiceAccountView +from django.conf import settings +from django.contrib.auth.decorators import login_required, permission_required +from django.db.models import Count +from django.http import HttpResponse, JsonResponse +from django.shortcuts import render from .models import MumbleUser @@ -35,3 +40,51 @@ class ResetPasswordMumbleView(MumbleViewMixin, BaseResetPasswordServiceAccountVi class SetPasswordMumbleView(MumbleViewMixin, BaseSetPasswordServiceAccountView): form_class = MumblePasswordForm + + +@login_required +@permission_required('mumble.view_connection_history') +def connection_history(request) -> HttpResponse: + + context = { + "mumble_url": settings.MUMBLE_URL, + } + + return render(request, 'services/mumble/mumble_connection_history.html', context) + + +@login_required +@permission_required("mumble.view_connection_history") +def connection_history_data(request) -> JsonResponse: + connection_history_data = MumbleUser.objects.all( + ).values( + 'user', + 'display_name', + 'release', + 'version', + 'last_connect', + 'last_disconnect', + ) + + return JsonResponse({"connection_history_data": list(connection_history_data)}) + + +@login_required +@permission_required("mumble.view_connection_history") +def release_counts_data(request) -> JsonResponse: + release_counts_data = MumbleUser.objects.values('release').annotate(user_count=Count('user_id')).order_by('release') + + return JsonResponse({ + "release_counts_data": list(release_counts_data), + }) + + +@login_required +@permission_required("mumble.view_connection_history") +def release_pie_chart_data(request) -> JsonResponse: + release_counts = MumbleUser.objects.values('release').annotate(user_count=Count('user_id')).order_by('release') + + return JsonResponse({ + "labels": list(release_counts.values_list("release", flat=True)), + "values": list(release_counts.values_list("user_count", flat=True)), + }) diff --git a/allianceauth/templates/bundles/chart-js.html b/allianceauth/templates/bundles/chart-js.html new file mode 100644 index 00000000..9747b5ed --- /dev/null +++ b/allianceauth/templates/bundles/chart-js.html @@ -0,0 +1,3 @@ + + +