diff --git a/cotisations/models.py b/cotisations/models.py
index 2db945b4..6be735f7 100644
--- a/cotisations/models.py
+++ b/cotisations/models.py
@@ -6,6 +6,8 @@ from dateutil.relativedelta import relativedelta
from django.core.validators import MinValueValidator
class Facture(models.Model):
+ PRETTY_NAME = "Factures émises"
+
user = models.ForeignKey('users.User', on_delete=models.PROTECT)
paiement = models.ForeignKey('Paiement', on_delete=models.PROTECT)
banque = models.ForeignKey('Banque', on_delete=models.PROTECT, blank=True, null=True)
@@ -40,6 +42,8 @@ def facture_post_delete(sender, **kwargs):
#user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
class Vente(models.Model):
+ PRETTY_NAME = "Ventes effectuées"
+
facture = models.ForeignKey('Facture', on_delete=models.CASCADE)
number = models.IntegerField(validators=[MinValueValidator(1)])
name = models.CharField(max_length=255)
@@ -74,6 +78,8 @@ def vente_post_delete(sender, **kwargs):
#user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
class Article(models.Model):
+ PRETTY_NAME = "Articles en vente"
+
name = models.CharField(max_length=255)
prix = models.DecimalField(max_digits=5, decimal_places=2)
iscotisation = models.BooleanField()
@@ -83,18 +89,24 @@ class Article(models.Model):
return self.name
class Banque(models.Model):
+ PRETTY_NAME = "Banques enregistrées"
+
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Paiement(models.Model):
+ PRETTY_NAME = "Moyens de paiement"
+
moyen = models.CharField(max_length=255)
def __str__(self):
return self.moyen
class Cotisation(models.Model):
+ PRETTY_NAME = "Cotisations"
+
vente = models.OneToOneField('Vente', on_delete=models.CASCADE, null=True)
date_start = models.DateTimeField()
date_end = models.DateTimeField()
diff --git a/logs/templates/logs/aff_actions.html b/logs/templates/logs/aff_actions.html
index e1ee5734..798f4224 100644
--- a/logs/templates/logs/aff_actions.html
+++ b/logs/templates/logs/aff_actions.html
@@ -12,6 +12,7 @@
Modification par |
Date de modification |
Commentaire |
+ |
{% for revision in revisions_list %}
@@ -21,6 +22,7 @@
{{ revision.user }} |
{{ revision.date_created }} |
{{ revision.comment }} |
-
+ {% if is_bureau %}Annuler | {% endif %}
+
{% endfor %}
diff --git a/logs/templates/logs/aff_stats_models.html b/logs/templates/logs/aff_stats_models.html
new file mode 100644
index 00000000..8d3e2b9d
--- /dev/null
+++ b/logs/templates/logs/aff_stats_models.html
@@ -0,0 +1,17 @@
+ {% for key, stats in stats_list.items %}
+
+ Statistiques de l'ensemble {{ key }}
+
+
+ Type d'objet |
+ Nombre d'entrée stockées |
+
+
+ {% for key, stat in stats.items %}
+
+ {{ stat.0 }} |
+ {{ stat.1 }} |
+
+ {% endfor %}
+
+ {% endfor %}
diff --git a/logs/templates/logs/delete.html b/logs/templates/logs/delete.html
new file mode 100644
index 00000000..1e2c8373
--- /dev/null
+++ b/logs/templates/logs/delete.html
@@ -0,0 +1,16 @@
+{% extends "logs/sidebar.html" %}
+{% load bootstrap3 %}
+
+{% block title %}Supression d'action{% endblock %}
+
+{% block content %}
+
+
+
+
+
+{% endblock %}
diff --git a/logs/templates/logs/sidebar.html b/logs/templates/logs/sidebar.html
index aa868933..fd1e35f3 100644
--- a/logs/templates/logs/sidebar.html
+++ b/logs/templates/logs/sidebar.html
@@ -2,5 +2,6 @@
{% block sidebar %}
{% if is_cableur %}
+ Statistiques base de donnée
{% endif %}
{% endblock %}
diff --git a/logs/templates/logs/stats_models.html b/logs/templates/logs/stats_models.html
new file mode 100644
index 00000000..0195fd48
--- /dev/null
+++ b/logs/templates/logs/stats_models.html
@@ -0,0 +1,12 @@
+{% extends "logs/sidebar.html" %}
+{% load bootstrap3 %}
+
+{% block title %}Statistiques des objets base de données{% endblock %}
+
+{% block content %}
+ Statistiques bdd
+ {% include "logs/aff_stats_models.html" with stats_list=stats_list %}
+
+
+
+ {% endblock %}
diff --git a/logs/urls.py b/logs/urls.py
index a3780aa2..8ed34e1d 100644
--- a/logs/urls.py
+++ b/logs/urls.py
@@ -4,4 +4,6 @@ from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
+ url(r'^revert_action/(?P[0-9]+)$', views.revert_action, name='revert-action'),
+ url(r'^stats_models/$', views.stats_models, name='stats-models'),
]
diff --git a/logs/views.py b/logs/views.py
index fd55a715..00e04af8 100644
--- a/logs/views.py
+++ b/logs/views.py
@@ -16,8 +16,18 @@ from django.db import transaction
from reversion.models import Revision
from reversion.models import Version
+from users.models import User, ServiceUser, Right, School, ListRight, ListShell, Ban, Whitelist
+from cotisations.models import Facture, Vente, Article, Banque, Paiement, Cotisation
+from machines.models import Machine, MachineType, IpType, Extension, Interface, Alias, IpList
+from topologie.models import Switch, Port, Room
+
from re2o.settings import PAGINATION_NUMBER, PAGINATION_LARGE_NUMBER
+def form(ctx, template, request):
+ c = ctx
+ c.update(csrf(request))
+ return render_to_response(template, c, context_instance=RequestContext(request))
+
@login_required
@permission_required('cableur')
def index(request):
@@ -34,3 +44,55 @@ def index(request):
revisions = paginator.page(paginator.num_pages)
return render(request, 'logs/index.html', {'revisions_list': revisions})
+@login_required
+@permission_required('bureau')
+def revert_action(request, revision_id):
+ """ Annule l'action en question """
+ try:
+ revision = Revision.objects.get(id=revision_id)
+ except Revision.DoesNotExist:
+ 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)
+
+@login_required
+@permission_required('cableur')
+def stats_models(request):
+ 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' : [Alias.PRETTY_NAME, Alias.objects.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()],
+ },
+ }
+ return render(request, 'logs/stats_models.html', {'stats_list': stats})
diff --git a/machines/admin.py b/machines/admin.py
index 7ee8cde1..6423e1c1 100644
--- a/machines/admin.py
+++ b/machines/admin.py
@@ -1,7 +1,7 @@
from django.contrib import admin
from reversion.admin import VersionAdmin
-from .models import IpType, Machine, MachineType, IpList, Interface, Extension
+from .models import IpType, Machine, MachineType, Alias, IpList, Interface, Extension
class MachineAdmin(VersionAdmin):
list_display = ('user','name','active')
@@ -22,9 +22,13 @@ class IpListAdmin(VersionAdmin):
class InterfaceAdmin(VersionAdmin):
list_display = ('machine','type','dns','mac_address','ipv4','details')
+class AliasAdmin(VersionAdmin):
+ list_display = ('interface_parent', 'alias')
+
admin.site.register(Machine, MachineAdmin)
admin.site.register(MachineType, MachineTypeAdmin)
admin.site.register(IpType, IpTypeAdmin)
admin.site.register(Extension, ExtensionAdmin)
admin.site.register(IpList, IpListAdmin)
admin.site.register(Interface, InterfaceAdmin)
+admin.site.register(Alias, AliasAdmin)
diff --git a/machines/forms.py b/machines/forms.py
index d2818b0d..5a9e3395 100644
--- a/machines/forms.py
+++ b/machines/forms.py
@@ -1,6 +1,6 @@
from django.forms import ModelForm, Form, ValidationError
from django import forms
-from .models import Machine, Interface, IpList, MachineType, Extension, IpType
+from .models import Alias, Machine, Interface, IpList, MachineType, Extension, IpType
class EditMachineForm(ModelForm):
class Meta:
@@ -59,6 +59,15 @@ class BaseEditInterfaceForm(EditInterfaceForm):
self.fields['type'].queryset = MachineType.objects.filter(ip_type=IpType.objects.filter(need_infra=False))
self.fields['ipv4'].queryset = IpList.objects.filter(ip_type=IpType.objects.filter(need_infra=False))
+class NewAliasForm(ModelForm):
+ class Meta:
+ model = Alias
+ fields = ['alias']
+
+class EditAliasFullForm(NewAliasForm):
+ class Meta(NewAliasForm.Meta):
+ fields = '__all__'
+
class MachineTypeForm(ModelForm):
class Meta:
model = MachineType
diff --git a/machines/migrations/0027_alias.py b/machines/migrations/0027_alias.py
new file mode 100644
index 00000000..fac2a108
--- /dev/null
+++ b/machines/migrations/0027_alias.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('machines', '0026_auto_20161026_1348'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Alias',
+ fields=[
+ ('id', models.AutoField(primary_key=True, serialize=False, auto_created=True, verbose_name='ID')),
+ ('alias', models.CharField(max_length=255, help_text='Obligatoire et unique, ne doit pas comporter de points', unique=True)),
+ ('interface_parent', models.ForeignKey(to='machines.Interface')),
+ ],
+ ),
+ ]
diff --git a/machines/models.py b/machines/models.py
index 31d1a406..7d083e09 100644
--- a/machines/models.py
+++ b/machines/models.py
@@ -8,6 +8,8 @@ from re2o.settings import MAIN_EXTENSION
class Machine(models.Model):
+ PRETTY_NAME = "Machine"
+
user = models.ForeignKey('users.User', on_delete=models.PROTECT)
name = models.CharField(max_length=255, help_text="Optionnel", blank=True, null=True)
active = models.BooleanField(default=True)
@@ -16,6 +18,8 @@ class Machine(models.Model):
return str(self.user) + ' - ' + str(self.id) + ' - ' + str(self.name)
class MachineType(models.Model):
+ PRETTY_NAME = "Type de machine"
+
type = models.CharField(max_length=255)
ip_type = models.ForeignKey('IpType', on_delete=models.PROTECT, blank=True, null=True)
@@ -23,6 +27,8 @@ class MachineType(models.Model):
return self.type
class IpType(models.Model):
+ PRETTY_NAME = "Type d'ip"
+
type = models.CharField(max_length=255)
extension = models.ForeignKey('Extension', on_delete=models.PROTECT)
need_infra = models.BooleanField(default=False)
@@ -31,12 +37,16 @@ class IpType(models.Model):
return self.type
class Extension(models.Model):
+ PRETTY_NAME = "Extensions dns"
+
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Interface(models.Model):
+ PRETTY_NAME = "Interface"
+
ipv4 = models.OneToOneField('IpList', on_delete=models.PROTECT, blank=True, null=True)
#ipv6 = models.GenericIPAddressField(protocol='IPv6', null=True)
mac_address = MACAddressField(integer=False, unique=True)
@@ -54,7 +64,18 @@ class Interface(models.Model):
def __str__(self):
return self.dns
+class Alias(models.Model):
+ PRETTY_NAME = "Alias dns"
+
+ interface_parent = models.ForeignKey('Interface', on_delete=models.CASCADE)
+ alias = models.CharField(help_text="Obligatoire et unique, ne doit pas comporter de points", max_length=255, unique=True)
+
+ def __str__(self):
+ return self.alias
+
class IpList(models.Model):
+ PRETTY_NAME = "Addresses ipv4"
+
ipv4 = models.GenericIPAddressField(protocol='IPv4', unique=True)
ip_type = models.ForeignKey('IpType', on_delete=models.PROTECT)
diff --git a/machines/views.py b/machines/views.py
index 5561c89e..91a250e1 100644
--- a/machines/views.py
+++ b/machines/views.py
@@ -20,7 +20,7 @@ from reversion import revisions as reversion
import re
from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm, BaseEditInterfaceForm, BaseEditMachineForm
-from .forms import IpTypeForm, DelIpTypeForm
+from .forms import IpTypeForm, DelIpTypeForm, NewAliasForm, EditAliasFullForm
from .models import IpType, Machine, Interface, IpList, MachineType, Extension
from users.models import User
from re2o.settings import PAGINATION_NUMBER, PAGINATION_LARGE_NUMBER
diff --git a/topologie/models.py b/topologie/models.py
index ceb06345..0e14fdf7 100644
--- a/topologie/models.py
+++ b/topologie/models.py
@@ -16,6 +16,8 @@ def clean_port_related(port):
related_port.save()
class Switch(models.Model):
+ PRETTY_NAME = "Switch / Commutateur"
+
switch_interface = models.OneToOneField('machines.Interface', on_delete=models.CASCADE)
location = models.CharField(max_length=255)
number = models.IntegerField()
@@ -25,6 +27,8 @@ class Switch(models.Model):
return str(self.location)
class Port(models.Model):
+ PRETTY_NAME = "Port de switch"
+
switch = models.ForeignKey('Switch', related_name="ports")
port = models.IntegerField()
room = models.ForeignKey('Room', on_delete=models.PROTECT, blank=True, null=True)
@@ -36,6 +40,8 @@ class Port(models.Model):
unique_together = ('switch', 'port')
def clean(self):
+ if self.port > self.switch.number:
+ raise ValidationError("Ce port ne peut exister, numero trop élevé")
if self.room and self.machine_interface or self.room and self.related or self.machine_interface and self.related:
raise ValidationError("Chambre, interface et related_port sont mutuellement exclusifs")
if self.related==self:
@@ -52,6 +58,8 @@ class Port(models.Model):
return str(self.switch) + " - " + str(self.port)
class Room(models.Model):
+ PRETTY_NAME = "Chambre/ Prise murale"
+
name = models.CharField(max_length=255, unique=True)
details = models.CharField(max_length=255, blank=True)
diff --git a/users/models.py b/users/models.py
index ea06fd37..d61c2091 100644
--- a/users/models.py
+++ b/users/models.py
@@ -101,6 +101,7 @@ class UserManager(BaseUserManager):
class User(AbstractBaseUser):
+ PRETTY_NAME = "Utilisateurs"
STATE_ACTIVE = 0
STATE_DISABLED = 1
STATE_ARCHIVE = 2
@@ -287,6 +288,7 @@ def user_post_delete(sender, **kwargs):
#user.ldap_del()
class ServiceUser(AbstractBaseUser):
+ PRETTY_NAME = "Utilisateurs de service"
pseudo = models.CharField(max_length=32, unique=True, help_text="Doit contenir uniquement des lettres, chiffres, ou tirets", validators=[linux_user_validator])
@@ -323,6 +325,8 @@ def service_user_post_delete(sender, **kwargs):
service_user.ldap_del()
class Right(models.Model):
+ PRETTY_NAME = "Droits affectés à des users"
+
user = models.ForeignKey('User', on_delete=models.PROTECT)
right = models.ForeignKey('ListRight', on_delete=models.PROTECT)
@@ -343,6 +347,8 @@ def right_post_delete(sender, **kwargs):
right.ldap_sync()
class School(models.Model):
+ PRETTY_NAME = "Etablissements enregistrés"
+
name = models.CharField(max_length=255)
def __str__(self):
@@ -350,6 +356,8 @@ class School(models.Model):
class ListRight(models.Model):
+ PRETTY_NAME = "Liste des droits existants"
+
listright = models.CharField(max_length=255, unique=True)
gid = models.IntegerField(unique=True, null=True)
@@ -383,12 +391,16 @@ def listright_post_delete(sender, **kwargs):
right.ldap_del()
class ListShell(models.Model):
+ PRETTY_NAME = "Liste des shells disponibles"
+
shell = models.CharField(max_length=255, unique=True)
def __str__(self):
return self.shell
class Ban(models.Model):
+ PRETTY_NAME = "Liste des bannissements"
+
user = models.ForeignKey('User', on_delete=models.PROTECT)
raison = models.CharField(max_length=255)
date_start = models.DateTimeField(auto_now_add=True)
@@ -399,6 +411,8 @@ class Ban(models.Model):
class Whitelist(models.Model):
+ PRETTY_NAME = "Liste des accès gracieux"
+
user = models.ForeignKey('User', on_delete=models.PROTECT)
raison = models.CharField(max_length=255)
date_start = models.DateTimeField(auto_now_add=True)