8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-12-26 08:53:46 +00:00

Mise en cache des attributs user (@proprety) + reecriture de methodes directes SQl pour la collecte des set users (has_access, etc)

This commit is contained in:
Gabriel Detraz 2017-05-27 00:43:51 +02:00 committed by root
parent 6935a2013b
commit 67ac11f8f9
11 changed files with 131 additions and 30 deletions

View file

@ -58,7 +58,7 @@ def create_cotis(vente, user, duration, date_start=False):
if date_start:
end_adhesion = Cotisation.objects.filter(vente__in=Vente.objects.filter(facture__in=Facture.objects.filter(user=user).exclude(valid=False))).filter(date_start__lt=date_start).aggregate(Max('date_end'))['date_end__max']
else:
end_adhesion = user.end_adhesion()
end_adhesion = user.end_adhesion
date_start = date_start or timezone.now()
end_adhesion = end_adhesion or date_start
date_max = max(end_adhesion, date_start)
@ -102,7 +102,7 @@ def new_facture(request, userid):
if art_item.cleaned_data['article'].iscotisation:
create_cotis(new_vente, user, art_item.cleaned_data['article'].duration*art_item.cleaned_data['quantity'])
if any(art_item.cleaned_data['article'].iscotisation for art_item in articles if art_item.cleaned_data):
messages.success(request, "La cotisation a été prolongée pour l'adhérent %s jusqu'au %s" % (user.name, user.end_adhesion()) )
messages.success(request, "La cotisation a été prolongée pour l'adhérent %s jusqu'au %s" % (user.name, user.end_adhesion) )
else:
messages.success(request, "La facture a été crée")
return redirect("/users/profil/" + userid)

View file

@ -73,7 +73,7 @@ def decide_vlan(switch_id, port_number, mac_address):
room_user = User.objects.filter(room=Room.objects.filter(name=port.room))
if not room_user:
return (sw_name, 'Chambre non cotisante', VLAN_NOK)
elif not room_user[0].has_access():
elif not room_user[0].has_access:
return (sw_name, 'Chambre resident desactive', VLAN_NOK)
# else: user OK, on passe à la verif MAC
@ -82,7 +82,7 @@ def decide_vlan(switch_id, port_number, mac_address):
interface = Interface.objects.filter(mac_address=mac_address)
if not interface:
return (sw_name, 'Machine inconnue', VLAN_NOK)
elif not interface[0].is_active():
elif not interface[0].is_active:
return (sw_name, 'Machine non active / adherent non cotisant', VLAN_NOK)
else:
return (sw_name, 'Machine OK', VLAN_OK)

View file

@ -0,0 +1,42 @@
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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.
{% endcomment %}
{% for stats in stats_list %}
<table class="table table-striped">
<thead>
<tr>
{% for element in stats.0 %}
<th>{{ element }}</th>
{% endfor %}
</tr>
</thead>
{% for key, stat in stats.1.items %}
<tr>
{% for item in stat %}
<td>{{ item }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endfor %}

View file

@ -0,0 +1,36 @@
{% extends "logs/sidebar.html" %}
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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.
{% endcomment %}
{% load bootstrap3 %}
{% block title %}Statistiques générales{% endblock %}
{% block content %}
<h2>Statistiques générales</h2>
{% include "logs/aff_stats_general.html" with stats_list=stats_list %}
<br />
<br />
<br />
{% endblock %}

View file

@ -40,6 +40,7 @@ from reversion.models import Revision
from reversion.models import Version
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 topologie.models import Switch, Port, Room
@ -107,10 +108,10 @@ def stats_general(request):
'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", len([user for user in all_active_users if user.is_adherent()])],
'connexion_users' : ["Utilisateurs bénéficiant d'une connexion", len([user for user in all_active_users if user.has_access()])],
'ban_users' : ["Utilisateurs bannis", len([user for user in all_active_users if user.is_ban()])],
'whitelisted_user' : ["Utilisateurs bénéficiant d'une connexion gracieuse", len([user for user in all_active_users if user.is_whitelisted()])],
'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()],
}],
[["Range d'ip", "Nombre d'ip totales", "Nombre d'ip utilisées", "Nombre d'ip libres"] ,ip]
]

View file

@ -27,6 +27,7 @@ from django.forms import ValidationError
from macaddress.fields import MACAddressField
from netaddr import mac_bare, EUI
from django.core.validators import MinValueValidator,MaxValueValidator
from django.utils.functional import cached_property
from re2o.settings import MAIN_EXTENSION
@ -101,11 +102,12 @@ class Interface(models.Model):
type = models.ForeignKey('MachineType', on_delete=models.PROTECT)
details = models.CharField(max_length=255, blank=True)
@cached_property
def is_active(self):
""" Renvoie si une interface doit avoir accès ou non """
machine = self.machine
user = self.machine.user
return machine.active and user.has_access()
return machine.active and user.has_access
def mac_bare(self):
return str(EUI(self.mac_address, dialect=mac_bare)).lower()

View file

@ -728,7 +728,7 @@ class JSONResponse(HttpResponse):
def mac_ip_list(request):
interf = Interface.objects.select_related('ipv4').select_related('domain__extension').all()
interfaces = list(filter(
lambda interface: interface.ipv4 and interface.is_active(),
lambda interface: interface.ipv4 and interface.is_active,
interf
))
seria = InterfaceSerializer(interfaces, many=True)

View file

@ -30,11 +30,11 @@ class PortForm(ModelForm):
class EditPortForm(ModelForm):
class Meta(PortForm.Meta):
fields = ['room', 'machine_interface', 'related', 'radius', 'details']
fields = ['room', 'related', 'radius', 'details']
def __init__(self, *args, **kwargs):
super(EditPortForm, self).__init__(*args, **kwargs)
self.fields['related'].queryset = Port.objects.all().order_by('switch', 'port')
# def __init__(self, *args, **kwargs):
# super(EditPortForm, self).__init__(*args, **kwargs)
# self.fields['related'].queryset = Port.objects.all().order_by('switch', 'port')
class AddPortForm(ModelForm):
class Meta(PortForm.Meta):

View file

@ -126,7 +126,7 @@ def new_port(request, switch_id):
@permission_required('infra')
def edit_port(request, port_id):
try:
port_object = Port.objects.get(pk=port_id)
port_object = Port.objects.select_related('switch__switch_interface__domain__extension').select_related('machine_interface').select_related('room').select_related('related').get(pk=port_id)
except Port.DoesNotExist:
messages.error(request, u"Port inexistant")
return redirect("/topologie/")

View file

@ -26,6 +26,7 @@ from django.forms import ModelForm, Form
from django import forms
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django.utils.functional import cached_property
import ldapdb.models
import ldapdb.models.fields
@ -88,6 +89,17 @@ def get_admin_right():
admin_right.save()
return admin_right
def all_adherent():
return User.objects.filter(facture__in=Facture.objects.filter(vente__in=Vente.objects.filter(cotisation__in=Cotisation.objects.filter(vente__in=Vente.objects.filter(facture__in=Facture.objects.all().exclude(valid=False))).filter(date_end__gt=timezone.now())))).distinct()
def all_baned():
return User.objects.filter(ban__in=Ban.objects.filter(date_end__gt=timezone.now())).distinct()
def all_whitelisted():
return User.objects.filter(whitelist__in=Whitelist.objects.filter(date_end__gt=timezone.now())).distinct()
def all_has_access():
return User.objects.filter(Q(state=User.STATE_ACTIVE) & ~Q(ban__in=Ban.objects.filter(date_end__gt=timezone.now())) & (Q(whitelist__in=Whitelist.objects.filter(date_end__gt=timezone.now())) | Q(facture__in=Facture.objects.filter(vente__in=Vente.objects.filter(cotisation__in=Cotisation.objects.filter(vente__in=Vente.objects.filter(facture__in=Facture.objects.all().exclude(valid=False))).filter(date_end__gt=timezone.now())))))).distinct()
class UserManager(BaseUserManager):
def _create_user(self, pseudo, name, surname, email, password=None, su=False):
@ -204,12 +216,14 @@ class User(AbstractBaseUser):
def has_perm(self, perm, obj=None):
return True
@cached_property
def end_adhesion(self):
date_max = Cotisation.objects.filter(vente__in=Vente.objects.filter(facture__in=Facture.objects.filter(user=self).exclude(valid=False))).aggregate(models.Max('date_end'))['date_end__max']
return date_max
@cached_property
def is_adherent(self):
end = self.end_adhesion()
end = self.end_adhesion
if not end:
return False
elif end < timezone.now():
@ -217,19 +231,22 @@ class User(AbstractBaseUser):
else:
return True
@cached_property
def end_ban(self):
""" Renvoie la date de fin de ban d'un user, False sinon """
date_max = Ban.objects.filter(user=self).aggregate(models.Max('date_end'))['date_end__max']
return date_max
@cached_property
def end_whitelist(self):
""" Renvoie la date de fin de whitelist d'un user, False sinon """
date_max = Whitelist.objects.filter(user=self).aggregate(models.Max('date_end'))['date_end__max']
return date_max
@cached_property
def is_ban(self):
""" Renvoie si un user est banni ou non """
end = self.end_ban()
end = self.end_ban
if not end:
return False
elif end < timezone.now():
@ -237,9 +254,10 @@ class User(AbstractBaseUser):
else:
return True
@cached_property
def is_whitelisted(self):
""" Renvoie si un user est whitelisté ou non """
end = self.end_whitelist()
end = self.end_whitelist
if not end:
return False
elif end < timezone.now():
@ -247,23 +265,25 @@ class User(AbstractBaseUser):
else:
return True
@cached_property
def has_access(self):
""" Renvoie si un utilisateur a accès à internet """
return self.state == User.STATE_ACTIVE \
and not self.is_ban() and (self.is_adherent() or self.is_whitelisted())
and not self.is_ban and (self.is_adherent or self.is_whitelisted)
@cached_property
def end_access(self):
""" Renvoie la date de fin normale d'accès (adhésion ou whiteliste)"""
if not self.end_adhesion():
if not self.end_whitelist():
if not self.end_adhesion:
if not self.end_whitelist:
return None
else:
return self.end_whitelist()
return self.end_whitelist
else:
if not self.end_whitelist():
return self.end_adhesion()
if not self.end_whitelist:
return self.end_adhesion
else:
return max(self.end_adhesion(), self.end_whitelist())
return max(self.end_adhesion, self.end_whitelist)
def user_interfaces(self):
return Interface.objects.filter(machine__in=Machine.objects.filter(user=self, active=True))
@ -293,7 +313,7 @@ class User(AbstractBaseUser):
if base:
user_ldap.name = self.pseudo
user_ldap.sn = self.pseudo
user_ldap.dialupAccess = str(self.has_access())
user_ldap.dialupAccess = str(self.has_access)
user_ldap.home_directory = '/home/' + self.pseudo
user_ldap.mail = self.email
user_ldap.given_name = str(self.surname).lower() + '_' + str(self.name).lower()[:3]
@ -303,7 +323,7 @@ class User(AbstractBaseUser):
if self.shell:
user_ldap.login_shell = self.shell.shell
if access_refresh:
user_ldap.dialupAccess = str(self.has_access())
user_ldap.dialupAccess = str(self.has_access)
if mac_refresh:
user_ldap.macs = [inter.mac_bare() for inter in Interface.objects.filter(machine__in=Machine.objects.filter(user=self))]
user_ldap.save()

View file

@ -272,7 +272,7 @@ def add_ban(request, userid):
reversion.set_comment("Création")
messages.success(request, "Bannissement ajouté")
return redirect("/users/profil/" + userid)
if user.is_ban():
if user.is_ban:
messages.error(
request,
"Attention, cet utilisateur a deja un bannissement actif"
@ -318,7 +318,7 @@ def add_whitelist(request, userid):
reversion.set_comment("Création")
messages.success(request, "Accès à titre gracieux accordé")
return redirect("/users/profil/" + userid)
if user.is_whitelisted():
if user.is_whitelisted:
messages.error(
request,
"Attention, cet utilisateur a deja un accès gracieux actif"
@ -463,7 +463,7 @@ def mass_archive(request):
to_archive_list = []
if to_archive_date.is_valid():
date = to_archive_date.cleaned_data['date']
to_archive_list = [user for user in User.objects.exclude(state=User.STATE_ARCHIVE) if not user.end_access() or user.end_access() < date]
to_archive_list = [user for user in User.objects.exclude(state=User.STATE_ARCHIVE) if not user.end_access or user.end_access < date]
if "valider" in request.POST:
for user in to_archive_list:
archive(user)