mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-27 07:02:26 +00:00
Docstrings et pep8 sur logs
This commit is contained in:
parent
77ce677c5b
commit
54fad989b3
2 changed files with 215 additions and 132 deletions
|
@ -19,7 +19,10 @@
|
|||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
"""
|
||||
Urls de l'application logs, pointe vers les fonctions de views.
|
||||
Inclu dans le re2o.urls
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf.urls import url
|
||||
|
@ -29,7 +32,9 @@ from . import views
|
|||
urlpatterns = [
|
||||
url(r'^$', views.index, name='index'),
|
||||
url(r'^stats_logs$', views.stats_logs, name='stats-logs'),
|
||||
url(r'^revert_action/(?P<revision_id>[0-9]+)$', views.revert_action, name='revert-action'),
|
||||
url(r'^revert_action/(?P<revision_id>[0-9]+)$',
|
||||
views.revert_action,
|
||||
name='revert-action'),
|
||||
url(r'^stats_general/$', views.stats_general, name='stats-general'),
|
||||
url(r'^stats_models/$', views.stats_models, name='stats-models'),
|
||||
url(r'^stats_users/$', views.stats_users, name='stats-users'),
|
||||
|
|
338
logs/views.py
338
logs/views.py
|
@ -23,62 +23,68 @@
|
|||
# App de gestion des statistiques pour re2o
|
||||
# Gabriel Détraz
|
||||
# Gplv2
|
||||
"""
|
||||
Vues des logs et statistiques générales.
|
||||
|
||||
La vue index générale affiche une selection des dernières actions,
|
||||
classées selon l'importance, avec date, et user formatés.
|
||||
|
||||
Stats_logs renvoie l'ensemble des logs.
|
||||
|
||||
Les autres vues sont thématiques, ensemble des statistiques et du
|
||||
nombre d'objets par models, nombre d'actions par user, etc
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import render, redirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.template.context_processors import csrf
|
||||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||
from django.template import Context, RequestContext, loader
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.db.models import ProtectedError
|
||||
from django.forms import ValidationError
|
||||
from django.db import transaction
|
||||
from django.db.models import Count
|
||||
|
||||
from reversion.models import Revision
|
||||
from reversion.models import Version, ContentType
|
||||
|
||||
from users.models import User, ServiceUser, Right, School, ListRight, ListShell, Ban, Whitelist
|
||||
from users.models import all_has_access, all_whitelisted, all_baned, all_adherent
|
||||
from cotisations.models import Facture, Vente, Article, Banque, Paiement, Cotisation
|
||||
from machines.models import Machine, MachineType, IpType, Extension, Interface, Domain, IpList
|
||||
from machines.views import all_active_assigned_interfaces_count, all_active_interfaces_count
|
||||
from users.models import User, ServiceUser, Right, School, ListRight, ListShell
|
||||
from users.models import Ban, Whitelist, all_has_access
|
||||
from users.models import all_whitelisted, all_baned, all_adherent
|
||||
from cotisations.models import Facture, Vente, Article, Banque, Paiement
|
||||
from cotisations.models import Cotisation
|
||||
from machines.models import Machine, MachineType, IpType, Extension, Interface
|
||||
from machines.models import Domain, IpList
|
||||
from machines.views import all_active_assigned_interfaces_count
|
||||
from machines.views import all_active_interfaces_count
|
||||
from topologie.models import Switch, Port, Room
|
||||
from preferences.models import GeneralOption
|
||||
from re2o.views import form
|
||||
|
||||
from django.utils import timezone
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
STATS_DICT = {
|
||||
0 : ["Tout", 36],
|
||||
1 : ["1 mois", 1],
|
||||
2 : ["2 mois", 2],
|
||||
3 : ["6 mois", 6],
|
||||
4 : ["1 an", 12],
|
||||
5 : ["2 an", 24],
|
||||
0: ["Tout", 36],
|
||||
1: ["1 mois", 1],
|
||||
2: ["2 mois", 2],
|
||||
3: ["6 mois", 6],
|
||||
4: ["1 an", 12],
|
||||
5: ["2 an", 24],
|
||||
}
|
||||
|
||||
def form(ctx, template, request):
|
||||
c = ctx
|
||||
c.update(csrf(request))
|
||||
return render(request, template, c)
|
||||
|
||||
@login_required
|
||||
@permission_required('cableur')
|
||||
def index(request):
|
||||
options, created = GeneralOption.objects.get_or_create()
|
||||
"""Affiche les logs affinés, date reformatées, selectionne
|
||||
les event importants (ajout de droits, ajout de ban/whitelist)"""
|
||||
options, _created = GeneralOption.objects.get_or_create()
|
||||
pagination_number = options.pagination_number
|
||||
|
||||
# The types of content kept for display
|
||||
content_type_filter = ['ban', 'whitelist', 'vente', 'interface', 'user']
|
||||
|
||||
content_type_filter = ['ban', 'whitelist', 'vente', 'interface', 'user']
|
||||
# Select only wanted versions
|
||||
versions = Version.objects.filter(content_type__in=ContentType.objects.filter(model__in=content_type_filter)).order_by('revision__date_created').reverse().select_related('revision')
|
||||
|
||||
versions = Version.objects.filter(
|
||||
content_type__in=ContentType.objects.filter(
|
||||
model__in=content_type_filter
|
||||
)
|
||||
).order_by('revision__date_created').reverse().select_related('revision')
|
||||
paginator = Paginator(versions, pagination_number)
|
||||
page = request.GET.get('page')
|
||||
try:
|
||||
|
@ -87,7 +93,7 @@ def index(request):
|
|||
# If page is not an integer, deliver first page.
|
||||
versions = paginator.page(1)
|
||||
except EmptyPage:
|
||||
# If page is out of range (e.g. 9999), deliver last page of results.
|
||||
# If page is out of range (e.g. 9999), deliver last page of results.
|
||||
versions = paginator.page(paginator.num_pages)
|
||||
|
||||
# Force to have a list instead of QuerySet
|
||||
|
@ -95,30 +101,38 @@ def index(request):
|
|||
# Items to remove later because invalid
|
||||
to_remove = []
|
||||
# Parse every item (max = pagination_number)
|
||||
for i in range( len( versions.object_list ) ):
|
||||
if versions.object_list[i].object :
|
||||
v = versions.object_list[i]
|
||||
for i in range(len(versions.object_list)):
|
||||
if versions.object_list[i].object:
|
||||
version = versions.object_list[i]
|
||||
versions.object_list[i] = {
|
||||
'rev_id' : v.revision.id,
|
||||
'comment': v.revision.comment,
|
||||
'datetime': v.revision.date_created.strftime('%d/%m/%y %H:%M:%S'),
|
||||
'username': v.revision.user.get_username() if v.revision.user else '?',
|
||||
'user_id': v.revision.user_id,
|
||||
'version': v }
|
||||
else :
|
||||
to_remove.insert(0,i)
|
||||
'rev_id': version.revision.id,
|
||||
'comment': version.revision.comment,
|
||||
'datetime': version.revision.date_created.strftime(
|
||||
'%d/%m/%y %H:%M:%S'
|
||||
),
|
||||
'username':
|
||||
version.revision.user.get_username()
|
||||
if version.revision.user else '?',
|
||||
'user_id': version.revision.user_id,
|
||||
'version': version}
|
||||
else:
|
||||
to_remove.insert(0, i)
|
||||
# Remove all tagged invalid items
|
||||
for i in to_remove :
|
||||
for i in to_remove:
|
||||
versions.object_list.pop(i)
|
||||
|
||||
return render(request, 'logs/index.html', {'versions_list': versions})
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required('cableur')
|
||||
def stats_logs(request):
|
||||
options, created = GeneralOption.objects.get_or_create()
|
||||
"""Affiche l'ensemble des logs et des modifications sur les objets,
|
||||
classés par date croissante, en vrac"""
|
||||
options, _created = GeneralOption.objects.get_or_create()
|
||||
pagination_number = options.pagination_number
|
||||
revisions = Revision.objects.all().order_by('date_created').reverse().select_related('user').prefetch_related('version_set__object')
|
||||
revisions = Revision.objects.all().order_by('date_created')\
|
||||
.reverse().select_related('user')\
|
||||
.prefetch_related('version_set__object')
|
||||
paginator = Paginator(revisions, pagination_number)
|
||||
page = request.GET.get('page')
|
||||
try:
|
||||
|
@ -127,9 +141,12 @@ def stats_logs(request):
|
|||
# If page is not an integer, deliver first page.
|
||||
revisions = paginator.page(1)
|
||||
except EmptyPage:
|
||||
# If page is out of range (e.g. 9999), deliver last page of results.
|
||||
# If page is out of range (e.g. 9999), deliver last page of results.
|
||||
revisions = paginator.page(paginator.num_pages)
|
||||
return render(request, 'logs/stats_logs.html', {'revisions_list': revisions})
|
||||
return render(request, 'logs/stats_logs.html', {
|
||||
'revisions_list': revisions
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required('bureau')
|
||||
|
@ -138,121 +155,182 @@ def revert_action(request, revision_id):
|
|||
try:
|
||||
revision = Revision.objects.get(id=revision_id)
|
||||
except Revision.DoesNotExist:
|
||||
messages.error(request, u"Revision inexistante" )
|
||||
messages.error(request, u"Revision inexistante")
|
||||
if request.method == "POST":
|
||||
revision.revert()
|
||||
messages.success(request, "L'action a été supprimée")
|
||||
return redirect("/logs/")
|
||||
return form({'objet': revision, 'objet_name': revision.__class__.__name__ }, 'logs/delete.html', request)
|
||||
return form({
|
||||
'objet': revision,
|
||||
'objet_name': revision.__class__.__name__
|
||||
}, 'logs/delete.html', request)
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required('cableur')
|
||||
def stats_general(request):
|
||||
all_active_users = User.objects.filter(state=User.STATE_ACTIVE)
|
||||
ip = dict()
|
||||
"""Statistiques générales affinées sur les ip, activées, utilisées par
|
||||
range, et les statistiques générales sur les users : users actifs,
|
||||
cotisants, activés, archivés, etc"""
|
||||
ip_dict = dict()
|
||||
for ip_range in IpType.objects.all():
|
||||
all_ip = IpList.objects.filter(ip_type=ip_range)
|
||||
used_ip = Interface.objects.filter(ipv4__in=all_ip).count()
|
||||
active_ip = all_active_assigned_interfaces_count().filter(ipv4__in=IpList.objects.filter(ip_type=ip_range)).count()
|
||||
ip[ip_range] = [ip_range, all_ip.count(), used_ip, active_ip, all_ip.count()-used_ip]
|
||||
active_ip = all_active_assigned_interfaces_count().filter(
|
||||
ipv4__in=IpList.objects.filter(ip_type=ip_range)
|
||||
).count()
|
||||
ip_dict[ip_range] = [ip_range, all_ip.count(),
|
||||
used_ip, active_ip, all_ip.count()-used_ip]
|
||||
stats = [
|
||||
[["Categorie", "Nombre d'utilisateurs"], {
|
||||
'active_users' : ["Users actifs", User.objects.filter(state=User.STATE_ACTIVE).count()],
|
||||
'inactive_users' : ["Users désactivés", User.objects.filter(state=User.STATE_DISABLED).count()],
|
||||
'archive_users' : ["Users archivés", User.objects.filter(state=User.STATE_ARCHIVE).count()],
|
||||
'adherent_users' : ["Adhérents à l'association", all_adherent().count()],
|
||||
'connexion_users' : ["Utilisateurs bénéficiant d'une connexion", all_has_access().count()],
|
||||
'ban_users' : ["Utilisateurs bannis", all_baned().count()],
|
||||
'whitelisted_user' : ["Utilisateurs bénéficiant d'une connexion gracieuse", all_whitelisted().count()],
|
||||
'actives_interfaces' : ["Interfaces actives (ayant accès au reseau)", all_active_interfaces_count().count()],
|
||||
'actives_assigned_interfaces' : ["Interfaces actives et assignées ipv4", all_active_assigned_interfaces_count().count()]
|
||||
}],
|
||||
[["Range d'ip", "Nombre d'ip totales", "Ip assignées", "Ip assignées à une machine active", "Ip non assignées"] ,ip]
|
||||
]
|
||||
[["Categorie", "Nombre d'utilisateurs"], {
|
||||
'active_users': [
|
||||
"Users actifs",
|
||||
User.objects.filter(state=User.STATE_ACTIVE).count()],
|
||||
'inactive_users': [
|
||||
"Users désactivés",
|
||||
User.objects.filter(state=User.STATE_DISABLED).count()],
|
||||
'archive_users': [
|
||||
"Users archivés",
|
||||
User.objects.filter(state=User.STATE_ARCHIVE).count()],
|
||||
'adherent_users': [
|
||||
"Adhérents à l'association",
|
||||
all_adherent().count()],
|
||||
'connexion_users': [
|
||||
"Utilisateurs bénéficiant d'une connexion",
|
||||
all_has_access().count()],
|
||||
'ban_users': [
|
||||
"Utilisateurs bannis",
|
||||
all_baned().count()],
|
||||
'whitelisted_user': [
|
||||
"Utilisateurs bénéficiant d'une connexion gracieuse",
|
||||
all_whitelisted().count()],
|
||||
'actives_interfaces': [
|
||||
"Interfaces actives (ayant accès au reseau)",
|
||||
all_active_interfaces_count().count()],
|
||||
'actives_assigned_interfaces': [
|
||||
"Interfaces actives et assignées ipv4",
|
||||
all_active_assigned_interfaces_count().count()]
|
||||
}],
|
||||
[["Range d'ip", "Nombre d'ip totales", "Ip assignées",
|
||||
"Ip assignées à une machine active", "Ip non assignées"], ip_dict]
|
||||
]
|
||||
return render(request, 'logs/stats_general.html', {'stats_list': stats})
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required('cableur')
|
||||
def stats_models(request):
|
||||
all_active_users = User.objects.filter(state=User.STATE_ACTIVE)
|
||||
"""Statistiques générales, affiche les comptages par models:
|
||||
nombre d'users, d'écoles, de droits, de bannissements,
|
||||
de factures, de ventes, de banque, de machines, etc"""
|
||||
stats = {
|
||||
'Users' : {
|
||||
'users' : [User.PRETTY_NAME, User.objects.count()],
|
||||
'serviceuser' : [ServiceUser.PRETTY_NAME, ServiceUser.objects.count()],
|
||||
'right' : [Right.PRETTY_NAME, Right.objects.count()],
|
||||
'school' : [School.PRETTY_NAME, School.objects.count()],
|
||||
'listright' : [ListRight.PRETTY_NAME, ListRight.objects.count()],
|
||||
'listshell' : [ListShell.PRETTY_NAME, ListShell.objects.count()],
|
||||
'ban' : [Ban.PRETTY_NAME, Ban.objects.count()],
|
||||
'whitelist' : [Whitelist.PRETTY_NAME, Whitelist.objects.count()]
|
||||
},
|
||||
'Cotisations' : {
|
||||
'factures' : [Facture.PRETTY_NAME, Facture.objects.count()],
|
||||
'vente' : [Vente.PRETTY_NAME, Vente.objects.count()],
|
||||
'cotisation' : [Cotisation.PRETTY_NAME, Cotisation.objects.count()],
|
||||
'article' : [Article.PRETTY_NAME, Article.objects.count()],
|
||||
'banque' : [Banque.PRETTY_NAME, Banque.objects.count()],
|
||||
'cotisation' : [Cotisation.PRETTY_NAME, Cotisation.objects.count()],
|
||||
},
|
||||
'Machines' : {
|
||||
'machine' : [Machine.PRETTY_NAME, Machine.objects.count()],
|
||||
'typemachine' : [MachineType.PRETTY_NAME, MachineType.objects.count()],
|
||||
'typeip' : [IpType.PRETTY_NAME, IpType.objects.count()],
|
||||
'extension' : [Extension.PRETTY_NAME, Extension.objects.count()],
|
||||
'interface' : [Interface.PRETTY_NAME, Interface.objects.count()],
|
||||
'alias' : [Domain.PRETTY_NAME, Domain.objects.exclude(cname=None).count()],
|
||||
'iplist' : [IpList.PRETTY_NAME, IpList.objects.count()],
|
||||
},
|
||||
'Topologie' : {
|
||||
'switch' : [Switch.PRETTY_NAME, Switch.objects.count()],
|
||||
'port' : [Port.PRETTY_NAME, Port.objects.count()],
|
||||
'chambre' : [Room.PRETTY_NAME, Room.objects.count()],
|
||||
},
|
||||
'Actions effectuées sur la base' :
|
||||
{
|
||||
'revision' : ["Nombre d'actions", Revision.objects.count()],
|
||||
},
|
||||
'Users': {
|
||||
'users': [User.PRETTY_NAME, User.objects.count()],
|
||||
'serviceuser': [ServiceUser.PRETTY_NAME,
|
||||
ServiceUser.objects.count()],
|
||||
'right': [Right.PRETTY_NAME, Right.objects.count()],
|
||||
'school': [School.PRETTY_NAME, School.objects.count()],
|
||||
'listright': [ListRight.PRETTY_NAME, ListRight.objects.count()],
|
||||
'listshell': [ListShell.PRETTY_NAME, ListShell.objects.count()],
|
||||
'ban': [Ban.PRETTY_NAME, Ban.objects.count()],
|
||||
'whitelist': [Whitelist.PRETTY_NAME, Whitelist.objects.count()]
|
||||
},
|
||||
'Cotisations': {
|
||||
'factures': [Facture.PRETTY_NAME, Facture.objects.count()],
|
||||
'vente': [Vente.PRETTY_NAME, Vente.objects.count()],
|
||||
'cotisation': [Cotisation.PRETTY_NAME, Cotisation.objects.count()],
|
||||
'article': [Article.PRETTY_NAME, Article.objects.count()],
|
||||
'banque': [Banque.PRETTY_NAME, Banque.objects.count()],
|
||||
},
|
||||
'Machines': {
|
||||
'machine': [Machine.PRETTY_NAME, Machine.objects.count()],
|
||||
'typemachine': [MachineType.PRETTY_NAME,
|
||||
MachineType.objects.count()],
|
||||
'typeip': [IpType.PRETTY_NAME, IpType.objects.count()],
|
||||
'extension': [Extension.PRETTY_NAME, Extension.objects.count()],
|
||||
'interface': [Interface.PRETTY_NAME, Interface.objects.count()],
|
||||
'alias': [Domain.PRETTY_NAME,
|
||||
Domain.objects.exclude(cname=None).count()],
|
||||
'iplist': [IpList.PRETTY_NAME, IpList.objects.count()],
|
||||
},
|
||||
'Topologie': {
|
||||
'switch': [Switch.PRETTY_NAME, Switch.objects.count()],
|
||||
'port': [Port.PRETTY_NAME, Port.objects.count()],
|
||||
'chambre': [Room.PRETTY_NAME, Room.objects.count()],
|
||||
},
|
||||
'Actions effectuées sur la base':
|
||||
{
|
||||
'revision': ["Nombre d'actions", Revision.objects.count()],
|
||||
},
|
||||
}
|
||||
return render(request, 'logs/stats_models.html', {'stats_list': stats})
|
||||
return render(request, 'logs/stats_models.html', {'stats_list': stats})
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required('cableur')
|
||||
def stats_users(request):
|
||||
"""Affiche les statistiques base de données aggrégées par user :
|
||||
nombre de machines par user, d'etablissements par user,
|
||||
de moyens de paiements par user, de banque par user,
|
||||
de bannissement par user, etc"""
|
||||
onglet = request.GET.get('onglet')
|
||||
try:
|
||||
search_field = STATS_DICT[onglet]
|
||||
except:
|
||||
search_field = STATS_DICT[0]
|
||||
_search_field = STATS_DICT[onglet]
|
||||
except KeyError:
|
||||
_search_field = STATS_DICT[0]
|
||||
onglet = 0
|
||||
start_date = timezone.now() + relativedelta(months=-search_field[1])
|
||||
stats = {
|
||||
'Utilisateur' : {
|
||||
'Machines' : User.objects.annotate(num=Count('machine')).order_by('-num')[:10],
|
||||
'Facture' : User.objects.annotate(num=Count('facture')).order_by('-num')[:10],
|
||||
'Bannissement' : User.objects.annotate(num=Count('ban')).order_by('-num')[:10],
|
||||
'Accès gracieux' : User.objects.annotate(num=Count('whitelist')).order_by('-num')[:10],
|
||||
'Droits' : User.objects.annotate(num=Count('right')).order_by('-num')[:10],
|
||||
},
|
||||
'Etablissement' : {
|
||||
'Utilisateur' : School.objects.annotate(num=Count('user')).order_by('-num')[:10],
|
||||
},
|
||||
'Moyen de paiement' : {
|
||||
'Utilisateur' : Paiement.objects.annotate(num=Count('facture')).order_by('-num')[:10],
|
||||
},
|
||||
'Banque' : {
|
||||
'Utilisateur' : Banque.objects.annotate(num=Count('facture')).order_by('-num')[:10],
|
||||
},
|
||||
'Utilisateur': {
|
||||
'Machines': User.objects.annotate(
|
||||
num=Count('machine')
|
||||
).order_by('-num')[:10],
|
||||
'Facture': User.objects.annotate(
|
||||
num=Count('facture')
|
||||
).order_by('-num')[:10],
|
||||
'Bannissement': User.objects.annotate(
|
||||
num=Count('ban')
|
||||
).order_by('-num')[:10],
|
||||
'Accès gracieux': User.objects.annotate(
|
||||
num=Count('whitelist')
|
||||
).order_by('-num')[:10],
|
||||
'Droits': User.objects.annotate(
|
||||
num=Count('right')
|
||||
).order_by('-num')[:10],
|
||||
},
|
||||
'Etablissement': {
|
||||
'Utilisateur': School.objects.annotate(
|
||||
num=Count('user')
|
||||
).order_by('-num')[:10],
|
||||
},
|
||||
'Moyen de paiement': {
|
||||
'Utilisateur': Paiement.objects.annotate(
|
||||
num=Count('facture')
|
||||
).order_by('-num')[:10],
|
||||
},
|
||||
'Banque': {
|
||||
'Utilisateur': Banque.objects.annotate(
|
||||
num=Count('facture')
|
||||
).order_by('-num')[:10],
|
||||
},
|
||||
}
|
||||
return render(request, 'logs/stats_users.html', {'stats_list': stats, 'stats_dict' : STATS_DICT, 'active_field': onglet})
|
||||
return render(request, 'logs/stats_users.html', {
|
||||
'stats_list': stats,
|
||||
'stats_dict': STATS_DICT,
|
||||
'active_field': onglet
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required('cableur')
|
||||
def stats_actions(request):
|
||||
onglet = request.GET.get('onglet')
|
||||
"""Vue qui affiche les statistiques de modifications d'objets par
|
||||
utilisateurs.
|
||||
Affiche le nombre de modifications aggrégées par utilisateurs"""
|
||||
stats = {
|
||||
'Utilisateur' : {
|
||||
'Action' : User.objects.annotate(num=Count('revision')).order_by('-num')[:40],
|
||||
},
|
||||
'Utilisateur': {
|
||||
'Action': User.objects.annotate(
|
||||
num=Count('revision')
|
||||
).order_by('-num')[:40],
|
||||
},
|
||||
}
|
||||
return render(request, 'logs/stats_users.html', {'stats_list': stats})
|
||||
|
|
Loading…
Reference in a new issue