From 778faf5d4c2ed7e97a28954c8e49dca49ae8fc69 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Thu, 26 Oct 2017 21:47:54 +0200 Subject: [PATCH 01/19] Fix bug merge --- topologie/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/topologie/forms.py b/topologie/forms.py index 0119435d..562b87e2 100644 --- a/topologie/forms.py +++ b/topologie/forms.py @@ -140,7 +140,7 @@ class EditRoomForm(ModelForm): super(EditRoomForm, self).__init__(*args, prefix=prefix, **kwargs) -class CreatePortsForm(Form): +class CreatePortsForm(forms.Form): """Permet de créer une liste de ports pour un switch.""" begin = forms.IntegerField(label="Début :", min_value=0) end = forms.IntegerField(label="Fin :", min_value=0) From c7fa36efbad4accfdcdd935e4e8359e97cf88d6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Kervella?= Date: Thu, 26 Oct 2017 21:36:09 +0000 Subject: [PATCH 02/19] =?UTF-8?q?Fix=20#14=20:=20V=C3=A9rifie=20ipType=20c?= =?UTF-8?q?orrect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/models.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/machines/models.py b/machines/models.py index 102289d5..020b7f0d 100644 --- a/machines/models.py +++ b/machines/models.py @@ -460,6 +460,15 @@ class Interface(models.Model): def clean(self, *args, **kwargs): """ Formate l'addresse mac en mac_bare (fonction filter_mac) et assigne une ipv4 dans le bon range si inexistante ou incohérente""" + # If type was an invalid value, django won't create an attribute type + # but try clean() as we may be able to create it from another value + # so even if the error as yet been detected at this point, django + # continues because the error might not prevent us from creating the + # instance. + # But in our case, it's impossible to create a type value so we raise + # the error. + if not hasattr(self, 'type') : + raise ValidationError("Le type d'ip choisi n'est pas valide") self.filter_macaddress() self.mac_address = str(EUI(self.mac_address)) or None if not self.ipv4 or self.type.ip_type != self.ipv4.ip_type: From be6a06ea8164b001e19ef10164f036f0cf902281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Kervella?= Date: Thu, 26 Oct 2017 22:37:16 +0000 Subject: [PATCH 03/19] =?UTF-8?q?Fix=20:=20cr=C3=A9ation=20du=20user=20dan?= =?UTF-8?q?s=20le=20ldap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- users/models.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/users/models.py b/users/models.py index 2a403129..e6f477b7 100644 --- a/users/models.py +++ b/users/models.py @@ -750,7 +750,8 @@ class Club(User): pass -@receiver(post_save, sender=User) +@receiver(post_save, sender=Adherent) +@receiver(post_save, sender=Club) def user_post_save(sender, **kwargs): """ Synchronisation post_save : envoie le mail de bienvenue si creation Synchronise le ldap""" @@ -762,7 +763,8 @@ def user_post_save(sender, **kwargs): regen('mailing') -@receiver(post_delete, sender=User) +@receiver(post_delete, sender=Adherent) +@receiver(post_delete, sender=Club) def user_post_delete(sender, **kwargs): """Post delete d'un user, on supprime son instance ldap""" user = kwargs['instance'] From fd0cce6f9ed2775620659e81ab9c8927ac844673 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Fri, 27 Oct 2017 01:34:28 +0200 Subject: [PATCH 04/19] Post-user et post_del avec model User aussi --- users/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/users/models.py b/users/models.py index e6f477b7..68b80b25 100644 --- a/users/models.py +++ b/users/models.py @@ -752,6 +752,7 @@ class Club(User): @receiver(post_save, sender=Adherent) @receiver(post_save, sender=Club) +@receiver(post_save, sender=User) def user_post_save(sender, **kwargs): """ Synchronisation post_save : envoie le mail de bienvenue si creation Synchronise le ldap""" @@ -765,6 +766,7 @@ def user_post_save(sender, **kwargs): @receiver(post_delete, sender=Adherent) @receiver(post_delete, sender=Club) +@receiver(post_delete, sender=User) def user_post_delete(sender, **kwargs): """Post delete d'un user, on supprime son instance ldap""" user = kwargs['instance'] From 241d2462c32a889482a54a1a7a24cb8c091c796a Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Fri, 27 Oct 2017 01:46:43 +0200 Subject: [PATCH 05/19] Si l'instance ldap_user existe pas on l'ajoute sans bruit --- users/models.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/users/models.py b/users/models.py index 68b80b25..81fd4aa8 100644 --- a/users/models.py +++ b/users/models.py @@ -545,12 +545,16 @@ class User(AbstractBaseUser): mail, password, shell, home access_refresh : synchronise le dialup_access notant si l'user a accès aux services - mac_refresh : synchronise les machines de l'user""" + mac_refresh : synchronise les machines de l'user + Si l'instance n'existe pas, on crée le ldapuser correspondant""" self.refresh_from_db() try: user_ldap = LdapUser.objects.get(uidNumber=self.uid_number) except LdapUser.DoesNotExist: user_ldap = LdapUser(uidNumber=self.uid_number) + base = True + access_refresh = True + mac_refresh = True if base: user_ldap.name = self.pseudo user_ldap.sn = self.pseudo @@ -574,7 +578,6 @@ class User(AbstractBaseUser): user_ldap.macs = [str(mac) for mac in Interface.objects.filter( machine__user=self ).values_list('mac_address', flat=True).distinct()] - user_ldap.save() def ldap_del(self): From 31234e7178c5f60b9c9c3a96a80fb0dd844ad9bb Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Fri, 27 Oct 2017 02:44:19 +0200 Subject: [PATCH 06/19] =?UTF-8?q?Rajoute=20des=20donn=C3=A9es=20en=20stati?= =?UTF-8?q?stiques?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- logs/views.py | 134 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 112 insertions(+), 22 deletions(-) diff --git a/logs/views.py b/logs/views.py index d14dac68..df5ca681 100644 --- a/logs/views.py +++ b/logs/views.py @@ -46,13 +46,50 @@ 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 -from users.models import Ban, Whitelist -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 topologie.models import Switch, Port, Room +from users.models import ( + User, + ServiceUser, + Right, + School, + ListRight, + ListShell, + Ban, + Whitelist, + Adherent, + Club +) +from cotisations.models import ( + Facture, + Vente, + Article, + Banque, + Paiement, + Cotisation +) +from machines.models import ( + Machine, + MachineType, + IpType, + Extension, + Interface, + Domain, + IpList, + OuverturePortList, + Service, + Vlan, + Nas, + SOA, + Mx, + Ns +) +from topologie.models import ( + Switch, + Port, + Room, + Stack, + ModelSwitch, + ConstructorSwitch +) from preferences.models import GeneralOption from re2o.views import form from re2o.utils import all_whitelisted, all_baned, all_has_access, all_adherent @@ -183,45 +220,77 @@ def stats_general(request): 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(): + for ip_range in IpType.objects.select_related('vlan').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_dict[ip_range] = [ip_range, all_ip.count(), + ip_dict[ip_range] = [ip_range, ip_range.vlan, all_ip.count(), used_ip, active_ip, all_ip.count()-used_ip] + _all_adherent = all_adherent() + _all_has_access = all_has_access() + _all_baned = all_baned() + _all_whitelisted = all_whitelisted() + _all_active_interfaces_count = all_active_interfaces_count() + _all_active_assigned_interfaces_count = all_active_assigned_interfaces_count() stats = [ - [["Categorie", "Nombre d'utilisateurs"], { + [["Categorie", "Nombre d'utilisateurs (total club et adhérents)", "Nombre d'adhérents", "Nombre de clubs"], { 'active_users': [ "Users actifs", - User.objects.filter(state=User.STATE_ACTIVE).count()], - 'inactive_users': [ + User.objects.filter(state=User.STATE_ACTIVE).count(), + Adherent.objects.filter(state=Adherent.STATE_ACTIVE).count(), + Club.objects.filter(state=Club.STATE_ACTIVE).count()], + 'inactive_users': [ "Users désactivés", - User.objects.filter(state=User.STATE_DISABLED).count()], + User.objects.filter(state=User.STATE_DISABLED).count(), + Adherent.objects.filter(state=Adherent.STATE_DISABLED).count(), + Club.objects.filter(state=Club.STATE_DISABLED).count()], 'archive_users': [ "Users archivés", - User.objects.filter(state=User.STATE_ARCHIVE).count()], + User.objects.filter(state=User.STATE_ARCHIVE).count(), + Adherent.objects.filter(state=Adherent.STATE_ARCHIVE).count(), + Club.objects.filter(state=Club.STATE_ARCHIVE).count()], 'adherent_users': [ - "Adhérents à l'association", - all_adherent().count()], + "Cotisant à l'association", + _all_adherent.count(), + _all_adherent.exclude(adherent__isnull=True).count(), + _all_adherent.exclude(club__isnull=True).count()], 'connexion_users': [ "Utilisateurs bénéficiant d'une connexion", - all_has_access().count()], + _all_has_access.count(), + _all_has_access.exclude(adherent__isnull=True).count(), + _all_has_access.exclude(club__isnull=True).count()], 'ban_users': [ "Utilisateurs bannis", - all_baned().count()], + _all_baned.count(), + _all_baned.exclude(adherent__isnull=True).count(), + _all_baned.exclude(club__isnull=True).count()], 'whitelisted_user': [ "Utilisateurs bénéficiant d'une connexion gracieuse", - all_whitelisted().count()], + _all_whitelisted.count(), + _all_whitelisted.exclude(adherent__isnull=True).count(), + _all_whitelisted.exclude(club__isnull=True).count()], 'actives_interfaces': [ "Interfaces actives (ayant accès au reseau)", - all_active_interfaces_count().count()], + _all_active_interfaces_count.count(), + _all_active_interfaces_count.exclude( + machine__user__adherent__isnull=True + ).count(), + _all_active_interfaces_count.exclude( + machine__user__club__isnull=True + ).count()], 'actives_assigned_interfaces': [ "Interfaces actives et assignées ipv4", - all_active_assigned_interfaces_count().count()] + _all_active_assigned_interfaces_count.count(), + _all_active_assigned_interfaces_count.exclude( + machine__user__adherent__isnull=True + ).count(), + _all_active_assigned_interfaces_count.exclude( + machine__user__club__isnull=True + ).count()] }], - [["Range d'ip", "Nombre d'ip totales", "Ip assignées", + [["Range d'ip", "Vlan", "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}) @@ -236,6 +305,8 @@ def stats_models(request): stats = { 'Users': { 'users': [User.PRETTY_NAME, User.objects.count()], + 'adherents': [Adherent.PRETTY_NAME, Adherent.objects.count()], + 'clubs': [Club.PRETTY_NAME, Club.objects.count()], 'serviceuser': [ServiceUser.PRETTY_NAME, ServiceUser.objects.count()], 'right': [Right.PRETTY_NAME, Right.objects.count()], @@ -262,11 +333,30 @@ def stats_models(request): 'alias': [Domain.PRETTY_NAME, Domain.objects.exclude(cname=None).count()], 'iplist': [IpList.PRETTY_NAME, IpList.objects.count()], + 'service': [Service.PRETTY_NAME, Service.objects.count()], + 'ouvertureportlist': [ + OuverturePortList.PRETTY_NAME, + OuverturePortList.objects.count() + ], + 'vlan': [Vlan.PRETTY_NAME, Vlan.objects.count()], + 'SOA': [Mx.PRETTY_NAME, Mx.objects.count()], + 'Mx': [Mx.PRETTY_NAME, Mx.objects.count()], + 'Ns': [Ns.PRETTY_NAME, Ns.objects.count()], + 'nas': [Nas.PRETTY_NAME, Nas.objects.count()], }, 'Topologie': { 'switch': [Switch.PRETTY_NAME, Switch.objects.count()], 'port': [Port.PRETTY_NAME, Port.objects.count()], 'chambre': [Room.PRETTY_NAME, Room.objects.count()], + 'stack': [Stack.PRETTY_NAME, Stack.objects.count()], + 'modelswitch': [ + ModelSwitch.PRETTY_NAME, + ModelSwitch.objects.count() + ], + 'constructorswitch': [ + ConstructorSwitch.PRETTY_NAME, + ConstructorSwitch.objects.count() + ], }, 'Actions effectuées sur la base': { From d0239a1613cb1e1ec7deb2b67fe871f73e68904d Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Fri, 27 Oct 2017 22:08:53 +0200 Subject: [PATCH 07/19] Affiche les id factures et id user --- .../templates/cotisations/aff_cotisations.html | 13 +++++-------- cotisations/templates/cotisations/control.html | 8 ++++++-- re2o/utils.py | 5 ++++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/cotisations/templates/cotisations/aff_cotisations.html b/cotisations/templates/cotisations/aff_cotisations.html index 59d558bf..81feb0bf 100644 --- a/cotisations/templates/cotisations/aff_cotisations.html +++ b/cotisations/templates/cotisations/aff_cotisations.html @@ -34,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., Prix total {% include "buttons/sort.html" with prefix='cotis' col='paiement' text='Moyen de paiement' %} {% include "buttons/sort.html" with prefix='cotis' col='date' text='Date' %} - + {% include "buttons/sort.html" with prefix='cotis' col='id' text='Id facture' %} @@ -46,17 +46,19 @@ with this program; if not, write to the Free Software Foundation, Inc., {{ facture.prix_total }} {{ facture.paiement }} {{ facture.date }} + {{ facture.id }} {% if is_cableur %}