mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-16 00:13:12 +00:00
Merge branch 'master' into massive_use_bft_tag
This commit is contained in:
commit
2ccf8f4729
34 changed files with 1094 additions and 233 deletions
26
cotisations/migrations/0024_auto_20171015_2033.py
Normal file
26
cotisations/migrations/0024_auto_20171015_2033.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-15 18:33
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('cotisations', '0023_auto_20170902_1303'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='article',
|
||||||
|
name='duration',
|
||||||
|
field=models.PositiveIntegerField(blank=True, help_text='Durée exprimée en mois entiers', null=True, validators=[django.core.validators.MinValueValidator(0)]),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='vente',
|
||||||
|
name='duration',
|
||||||
|
field=models.PositiveIntegerField(blank=True, help_text='Durée exprimée en mois entiers', null=True),
|
||||||
|
),
|
||||||
|
]
|
|
@ -132,7 +132,7 @@ class Vente(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
prix = models.DecimalField(max_digits=5, decimal_places=2)
|
prix = models.DecimalField(max_digits=5, decimal_places=2)
|
||||||
iscotisation = models.BooleanField()
|
iscotisation = models.BooleanField()
|
||||||
duration = models.IntegerField(
|
duration = models.PositiveIntegerField(
|
||||||
help_text="Durée exprimée en mois entiers",
|
help_text="Durée exprimée en mois entiers",
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True)
|
null=True)
|
||||||
|
@ -222,7 +222,7 @@ class Article(models.Model):
|
||||||
name = models.CharField(max_length=255, unique=True)
|
name = models.CharField(max_length=255, unique=True)
|
||||||
prix = models.DecimalField(max_digits=5, decimal_places=2)
|
prix = models.DecimalField(max_digits=5, decimal_places=2)
|
||||||
iscotisation = models.BooleanField()
|
iscotisation = models.BooleanField()
|
||||||
duration = models.IntegerField(
|
duration = models.PositiveIntegerField(
|
||||||
help_text="Durée exprimée en mois entiers",
|
help_text="Durée exprimée en mois entiers",
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
|
|
|
@ -99,18 +99,18 @@ urlpatterns = [
|
||||||
views.index_paiement,
|
views.index_paiement,
|
||||||
name='index-paiement'
|
name='index-paiement'
|
||||||
),
|
),
|
||||||
url(r'^history/(?P<object>facture)/(?P<id>[0-9]+)$',
|
url(r'^history/(?P<object_name>facture)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'
|
name='history'
|
||||||
),
|
),
|
||||||
url(r'^history/(?P<object>article)/(?P<id>[0-9]+)$',
|
url(r'^history/(?P<object_name>article)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'
|
name='history'
|
||||||
),
|
),
|
||||||
url(r'^history/(?P<object>paiement)/(?P<id>[0-9]+)$',
|
url(r'^history/(?P<object_name>paiement)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'),
|
name='history'),
|
||||||
url(r'^history/(?P<object>banque)/(?P<id>[0-9]+)$',
|
url(r'^history/(?P<object_name>banque)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'
|
name='history'
|
||||||
),
|
),
|
||||||
|
|
|
@ -533,7 +533,8 @@ def control(request):
|
||||||
facture_list = paginator.page(1)
|
facture_list = paginator.page(1)
|
||||||
except EmptyPage:
|
except EmptyPage:
|
||||||
facture_list = paginator.page(paginator.num.pages)
|
facture_list = paginator.page(paginator.num.pages)
|
||||||
page_query = Facture.objects.order_by('date').reverse().filter(
|
page_query = Facture.objects.order_by('date').select_related('user')\
|
||||||
|
.select_related('paiement').reverse().filter(
|
||||||
id__in=[facture.id for facture in facture_list]
|
id__in=[facture.id for facture in facture_list]
|
||||||
)
|
)
|
||||||
controlform = controlform_set(request.POST or None, queryset=page_query)
|
controlform = controlform_set(request.POST or None, queryset=page_query)
|
||||||
|
@ -603,9 +604,9 @@ def index(request):
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def history(request, object, object_id):
|
def history(request, object_name, object_id):
|
||||||
"""Affiche l'historique de chaque objet"""
|
"""Affiche l'historique de chaque objet"""
|
||||||
if object == 'facture':
|
if object_name == 'facture':
|
||||||
try:
|
try:
|
||||||
object_instance = Facture.objects.get(pk=object_id)
|
object_instance = Facture.objects.get(pk=object_id)
|
||||||
except Facture.DoesNotExist:
|
except Facture.DoesNotExist:
|
||||||
|
@ -616,19 +617,19 @@ def history(request, object, object_id):
|
||||||
messages.error(request, "Vous ne pouvez pas afficher l'historique\
|
messages.error(request, "Vous ne pouvez pas afficher l'historique\
|
||||||
d'une facture d'un autre user que vous sans droit cableur")
|
d'une facture d'un autre user que vous sans droit cableur")
|
||||||
return redirect("/users/profil/" + str(request.user.id))
|
return redirect("/users/profil/" + str(request.user.id))
|
||||||
elif object == 'paiement' and request.user.has_perms(('cableur',)):
|
elif object_name == 'paiement' and request.user.has_perms(('cableur',)):
|
||||||
try:
|
try:
|
||||||
object_instance = Paiement.objects.get(pk=object_id)
|
object_instance = Paiement.objects.get(pk=object_id)
|
||||||
except Paiement.DoesNotExist:
|
except Paiement.DoesNotExist:
|
||||||
messages.error(request, "Paiement inexistant")
|
messages.error(request, "Paiement inexistant")
|
||||||
return redirect("/cotisations/")
|
return redirect("/cotisations/")
|
||||||
elif object == 'article' and request.user.has_perms(('cableur',)):
|
elif object_name == 'article' and request.user.has_perms(('cableur',)):
|
||||||
try:
|
try:
|
||||||
object_instance = Article.objects.get(pk=object_id)
|
object_instance = Article.objects.get(pk=object_id)
|
||||||
except Article.DoesNotExist:
|
except Article.DoesNotExist:
|
||||||
messages.error(request, "Article inexistante")
|
messages.error(request, "Article inexistante")
|
||||||
return redirect("/cotisations/")
|
return redirect("/cotisations/")
|
||||||
elif object == 'banque' and request.user.has_perms(('cableur',)):
|
elif object_name == 'banque' and request.user.has_perms(('cableur',)):
|
||||||
try:
|
try:
|
||||||
object_instance = Banque.objects.get(pk=object_id)
|
object_instance = Banque.objects.get(pk=object_id)
|
||||||
except Banque.DoesNotExist:
|
except Banque.DoesNotExist:
|
||||||
|
|
BIN
docs_utils/re2o-archi.dia
Normal file
BIN
docs_utils/re2o-archi.dia
Normal file
Binary file not shown.
|
@ -292,7 +292,7 @@ def decide_vlan_and_register_switch(nas, nas_type, port_number, mac_address):
|
||||||
if not port.room:
|
if not port.room:
|
||||||
return (sw_name, u'Chambre inconnue', VLAN_NOK)
|
return (sw_name, u'Chambre inconnue', VLAN_NOK)
|
||||||
|
|
||||||
room_user = User.objects.filter(room=Room.objects.filter(name=port.room))
|
room_user = User.objects.filter(room=port.room)
|
||||||
if not room_user:
|
if not room_user:
|
||||||
return (sw_name, u'Chambre non cotisante', VLAN_NOK)
|
return (sw_name, u'Chambre non cotisante', VLAN_NOK)
|
||||||
elif not room_user.first().has_access():
|
elif not room_user.first().has_access():
|
||||||
|
|
|
@ -30,51 +30,67 @@ from .models import IpType, Machine, MachineType, Domain, IpList, Interface
|
||||||
from .models import Extension, Mx, Ns, Vlan, Text, Nas, Service, OuverturePort
|
from .models import Extension, Mx, Ns, Vlan, Text, Nas, Service, OuverturePort
|
||||||
from .models import OuverturePortList
|
from .models import OuverturePortList
|
||||||
|
|
||||||
|
|
||||||
class MachineAdmin(VersionAdmin):
|
class MachineAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class IpTypeAdmin(VersionAdmin):
|
class IpTypeAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MachineTypeAdmin(VersionAdmin):
|
class MachineTypeAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class VlanAdmin(VersionAdmin):
|
class VlanAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ExtensionAdmin(VersionAdmin):
|
class ExtensionAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MxAdmin(VersionAdmin):
|
class MxAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NsAdmin(VersionAdmin):
|
class NsAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TextAdmin(VersionAdmin):
|
class TextAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NasAdmin(VersionAdmin):
|
class NasAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class IpListAdmin(VersionAdmin):
|
class IpListAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class OuverturePortAdmin(VersionAdmin):
|
class OuverturePortAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class OuverturePortListAdmin(VersionAdmin):
|
class OuverturePortListAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class InterfaceAdmin(VersionAdmin):
|
class InterfaceAdmin(VersionAdmin):
|
||||||
list_display = ('machine','type','mac_address','ipv4','details')
|
list_display = ('machine','type','mac_address','ipv4','details')
|
||||||
|
|
||||||
|
|
||||||
class DomainAdmin(VersionAdmin):
|
class DomainAdmin(VersionAdmin):
|
||||||
list_display = ('interface_parent', 'name', 'extension', 'cname')
|
list_display = ('interface_parent', 'name', 'extension', 'cname')
|
||||||
|
|
||||||
|
|
||||||
class ServiceAdmin(VersionAdmin):
|
class ServiceAdmin(VersionAdmin):
|
||||||
list_display = ('service_type', 'min_time_regen', 'regular_time_regen')
|
list_display = ('service_type', 'min_time_regen', 'regular_time_regen')
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(Machine, MachineAdmin)
|
admin.site.register(Machine, MachineAdmin)
|
||||||
admin.site.register(MachineType, MachineTypeAdmin)
|
admin.site.register(MachineType, MachineTypeAdmin)
|
||||||
admin.site.register(IpType, IpTypeAdmin)
|
admin.site.register(IpType, IpTypeAdmin)
|
||||||
|
|
|
@ -21,20 +21,43 @@
|
||||||
# You should have received a copy of the GNU General Public License along
|
# 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.,
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
"""
|
||||||
|
Formulaires d'ajout, edition et suppressions de :
|
||||||
|
- machines
|
||||||
|
- interfaces
|
||||||
|
- domain (noms de machine)
|
||||||
|
- alias (cname)
|
||||||
|
- service (dhcp, dns..)
|
||||||
|
- ns (serveur dns)
|
||||||
|
- mx (serveur mail)
|
||||||
|
- ports ouverts et profils d'ouverture par interface
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import re
|
from django.forms import ModelForm, Form
|
||||||
|
|
||||||
from django.forms import ModelForm, Form, ValidationError
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from .models import Domain, Machine, Interface, IpList, MachineType, Extension, Mx, Text, Ns, Service, Vlan, Nas, IpType, OuverturePortList, OuverturePort
|
|
||||||
from django.db.models import Q
|
|
||||||
from django.core.validators import validate_email
|
|
||||||
|
|
||||||
from users.models import User
|
from .models import (
|
||||||
|
Domain,
|
||||||
|
Machine,
|
||||||
|
Interface,
|
||||||
|
IpList,
|
||||||
|
MachineType,
|
||||||
|
Extension,
|
||||||
|
Mx,
|
||||||
|
Text,
|
||||||
|
Ns,
|
||||||
|
Service,
|
||||||
|
Vlan,
|
||||||
|
Nas,
|
||||||
|
IpType,
|
||||||
|
OuverturePortList,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class EditMachineForm(ModelForm):
|
class EditMachineForm(ModelForm):
|
||||||
|
"""Formulaire d'édition d'une machine"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Machine
|
model = Machine
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
@ -44,15 +67,22 @@ class EditMachineForm(ModelForm):
|
||||||
super(EditMachineForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(EditMachineForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
self.fields['name'].label = 'Nom de la machine'
|
self.fields['name'].label = 'Nom de la machine'
|
||||||
|
|
||||||
|
|
||||||
class NewMachineForm(EditMachineForm):
|
class NewMachineForm(EditMachineForm):
|
||||||
|
"""Creation d'une machine, ne renseigne que le nom"""
|
||||||
class Meta(EditMachineForm.Meta):
|
class Meta(EditMachineForm.Meta):
|
||||||
fields = ['name']
|
fields = ['name']
|
||||||
|
|
||||||
|
|
||||||
class BaseEditMachineForm(EditMachineForm):
|
class BaseEditMachineForm(EditMachineForm):
|
||||||
|
"""Edition basique, ne permet que de changer le nom et le statut.
|
||||||
|
Réservé aux users sans droits spécifiques"""
|
||||||
class Meta(EditMachineForm.Meta):
|
class Meta(EditMachineForm.Meta):
|
||||||
fields = ['name','active']
|
fields = ['name', 'active']
|
||||||
|
|
||||||
|
|
||||||
class EditInterfaceForm(ModelForm):
|
class EditInterfaceForm(ModelForm):
|
||||||
|
"""Edition d'une interface. Edition complète"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Interface
|
model = Interface
|
||||||
fields = ['machine', 'type', 'ipv4', 'mac_address', 'details']
|
fields = ['machine', 'type', 'ipv4', 'mac_address', 'details']
|
||||||
|
@ -64,85 +94,126 @@ class EditInterfaceForm(ModelForm):
|
||||||
self.fields['type'].label = 'Type de machine'
|
self.fields['type'].label = 'Type de machine'
|
||||||
self.fields['type'].empty_label = "Séléctionner un type de machine"
|
self.fields['type'].empty_label = "Séléctionner un type de machine"
|
||||||
if "ipv4" in self.fields:
|
if "ipv4" in self.fields:
|
||||||
self.fields['ipv4'].empty_label = "Assignation automatique de l'ipv4"
|
self.fields['ipv4'].empty_label = "Assignation automatique\
|
||||||
self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True)
|
de l'ipv4"
|
||||||
|
self.fields['ipv4'].queryset = IpList.objects.filter(
|
||||||
|
interface__isnull=True
|
||||||
|
)
|
||||||
# Add it's own address
|
# Add it's own address
|
||||||
self.fields['ipv4'].queryset |= IpList.objects.filter(interface=self.instance)
|
self.fields['ipv4'].queryset |= IpList.objects.filter(
|
||||||
|
interface=self.instance
|
||||||
|
)
|
||||||
if "machine" in self.fields:
|
if "machine" in self.fields:
|
||||||
self.fields['machine'].queryset = Machine.objects.all().select_related('user')
|
self.fields['machine'].queryset = Machine.objects.all()\
|
||||||
|
.select_related('user')
|
||||||
|
|
||||||
|
|
||||||
class AddInterfaceForm(EditInterfaceForm):
|
class AddInterfaceForm(EditInterfaceForm):
|
||||||
|
"""Ajout d'une interface à une machine. En fonction des droits,
|
||||||
|
affiche ou non l'ensemble des ip disponibles"""
|
||||||
class Meta(EditInterfaceForm.Meta):
|
class Meta(EditInterfaceForm.Meta):
|
||||||
fields = ['type','ipv4','mac_address','details']
|
fields = ['type', 'ipv4', 'mac_address', 'details']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
infra = kwargs.pop('infra')
|
infra = kwargs.pop('infra')
|
||||||
super(AddInterfaceForm, self).__init__(*args, **kwargs)
|
super(AddInterfaceForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['ipv4'].empty_label = "Assignation automatique de l'ipv4"
|
self.fields['ipv4'].empty_label = "Assignation automatique de l'ipv4"
|
||||||
if not infra:
|
if not infra:
|
||||||
self.fields['type'].queryset = MachineType.objects.filter(ip_type__in=IpType.objects.filter(need_infra=False))
|
self.fields['type'].queryset = MachineType.objects.filter(
|
||||||
self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True).filter(ip_type__in=IpType.objects.filter(need_infra=False))
|
ip_type__in=IpType.objects.filter(need_infra=False)
|
||||||
|
)
|
||||||
|
self.fields['ipv4'].queryset = IpList.objects.filter(
|
||||||
|
interface__isnull=True
|
||||||
|
).filter(ip_type__in=IpType.objects.filter(need_infra=False))
|
||||||
else:
|
else:
|
||||||
self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True)
|
self.fields['ipv4'].queryset = IpList.objects.filter(
|
||||||
|
interface__isnull=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class NewInterfaceForm(EditInterfaceForm):
|
class NewInterfaceForm(EditInterfaceForm):
|
||||||
|
"""Formulaire light, sans choix de l'ipv4; d'ajout d'une interface"""
|
||||||
class Meta(EditInterfaceForm.Meta):
|
class Meta(EditInterfaceForm.Meta):
|
||||||
fields = ['type','mac_address','details']
|
fields = ['type', 'mac_address', 'details']
|
||||||
|
|
||||||
|
|
||||||
class BaseEditInterfaceForm(EditInterfaceForm):
|
class BaseEditInterfaceForm(EditInterfaceForm):
|
||||||
|
"""Edition basique d'une interface. En fonction des droits,
|
||||||
|
ajoute ou non l'ensemble des ipv4 disponibles (infra)"""
|
||||||
class Meta(EditInterfaceForm.Meta):
|
class Meta(EditInterfaceForm.Meta):
|
||||||
fields = ['type','ipv4','mac_address','details']
|
fields = ['type', 'ipv4', 'mac_address', 'details']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
infra = kwargs.pop('infra')
|
infra = kwargs.pop('infra')
|
||||||
super(BaseEditInterfaceForm, self).__init__(*args, **kwargs)
|
super(BaseEditInterfaceForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['ipv4'].empty_label = "Assignation automatique de l'ipv4"
|
self.fields['ipv4'].empty_label = "Assignation automatique de l'ipv4"
|
||||||
if not infra:
|
if not infra:
|
||||||
self.fields['type'].queryset = MachineType.objects.filter(ip_type__in=IpType.objects.filter(need_infra=False))
|
self.fields['type'].queryset = MachineType.objects.filter(
|
||||||
self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True).filter(ip_type__in=IpType.objects.filter(need_infra=False))
|
ip_type__in=IpType.objects.filter(need_infra=False)
|
||||||
|
)
|
||||||
|
self.fields['ipv4'].queryset = IpList.objects.filter(
|
||||||
|
interface__isnull=True
|
||||||
|
).filter(ip_type__in=IpType.objects.filter(need_infra=False))
|
||||||
# Add it's own address
|
# Add it's own address
|
||||||
self.fields['ipv4'].queryset |= IpList.objects.filter(interface=self.instance)
|
self.fields['ipv4'].queryset |= IpList.objects.filter(
|
||||||
|
interface=self.instance
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.fields['ipv4'].queryset = IpList.objects.filter(interface__isnull=True)
|
self.fields['ipv4'].queryset = IpList.objects.filter(
|
||||||
self.fields['ipv4'].queryset |= IpList.objects.filter(interface=self.instance)
|
interface__isnull=True
|
||||||
|
)
|
||||||
|
self.fields['ipv4'].queryset |= IpList.objects.filter(
|
||||||
|
interface=self.instance
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class AliasForm(ModelForm):
|
class AliasForm(ModelForm):
|
||||||
|
"""Ajout d'un alias (et edition), CNAME, contenant nom et extension"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Domain
|
model = Domain
|
||||||
fields = ['name','extension']
|
fields = ['name', 'extension']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
if 'infra' in kwargs:
|
|
||||||
infra = kwargs.pop('infra')
|
|
||||||
super(AliasForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(AliasForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class DomainForm(AliasForm):
|
class DomainForm(AliasForm):
|
||||||
|
"""Ajout et edition d'un enregistrement de nom, relié à interface"""
|
||||||
class Meta(AliasForm.Meta):
|
class Meta(AliasForm.Meta):
|
||||||
fields = ['name']
|
fields = ['name']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if 'user' in kwargs:
|
if 'user' in kwargs:
|
||||||
user = kwargs.pop('user')
|
user = kwargs.pop('user')
|
||||||
nb_machine = kwargs.pop('nb_machine')
|
|
||||||
initial = kwargs.get('initial', {})
|
initial = kwargs.get('initial', {})
|
||||||
initial['name'] = user.get_next_domain_name()
|
initial['name'] = user.get_next_domain_name()
|
||||||
kwargs['initial'] = initial
|
kwargs['initial'] = initial
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(DomainForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(DomainForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class DelAliasForm(Form):
|
class DelAliasForm(Form):
|
||||||
alias = forms.ModelMultipleChoiceField(queryset=Domain.objects.all(), label="Alias actuels", widget=forms.CheckboxSelectMultiple)
|
"""Suppression d'un ou plusieurs objets alias"""
|
||||||
|
alias = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=Domain.objects.all(),
|
||||||
|
label="Alias actuels",
|
||||||
|
widget=forms.CheckboxSelectMultiple
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
interface = kwargs.pop('interface')
|
interface = kwargs.pop('interface')
|
||||||
super(DelAliasForm, self).__init__(*args, **kwargs)
|
super(DelAliasForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['alias'].queryset = Domain.objects.filter(cname__in=Domain.objects.filter(interface_parent=interface))
|
self.fields['alias'].queryset = Domain.objects.filter(
|
||||||
|
cname__in=Domain.objects.filter(interface_parent=interface)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MachineTypeForm(ModelForm):
|
class MachineTypeForm(ModelForm):
|
||||||
|
"""Ajout et edition d'un machinetype, relié à un iptype"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = MachineType
|
model = MachineType
|
||||||
fields = ['type','ip_type']
|
fields = ['type', 'ip_type']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
|
@ -150,41 +221,72 @@ class MachineTypeForm(ModelForm):
|
||||||
self.fields['type'].label = 'Type de machine à ajouter'
|
self.fields['type'].label = 'Type de machine à ajouter'
|
||||||
self.fields['ip_type'].label = "Type d'ip relié"
|
self.fields['ip_type'].label = "Type d'ip relié"
|
||||||
|
|
||||||
|
|
||||||
class DelMachineTypeForm(Form):
|
class DelMachineTypeForm(Form):
|
||||||
machinetypes = forms.ModelMultipleChoiceField(queryset=MachineType.objects.all(), label="Types de machines actuelles", widget=forms.CheckboxSelectMultiple)
|
"""Suppression d'un ou plusieurs machinetype"""
|
||||||
|
machinetypes = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=MachineType.objects.all(),
|
||||||
|
label="Types de machines actuelles",
|
||||||
|
widget=forms.CheckboxSelectMultiple
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class IpTypeForm(ModelForm):
|
class IpTypeForm(ModelForm):
|
||||||
|
"""Formulaire d'ajout d'un iptype. Pas d'edition de l'ip de start et de
|
||||||
|
stop après creation"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = IpType
|
model = IpType
|
||||||
fields = ['type','extension','need_infra','domaine_ip_start','domaine_ip_stop', 'prefix_v6', 'vlan']
|
fields = ['type', 'extension', 'need_infra', 'domaine_ip_start',
|
||||||
|
'domaine_ip_stop', 'prefix_v6', 'vlan', 'ouverture_ports']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(IpTypeForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(IpTypeForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
self.fields['type'].label = 'Type ip à ajouter'
|
self.fields['type'].label = 'Type ip à ajouter'
|
||||||
|
|
||||||
|
|
||||||
class EditIpTypeForm(IpTypeForm):
|
class EditIpTypeForm(IpTypeForm):
|
||||||
|
"""Edition d'un iptype. Pas d'edition du rangev4 possible, car il faudrait
|
||||||
|
synchroniser les objets iplist"""
|
||||||
class Meta(IpTypeForm.Meta):
|
class Meta(IpTypeForm.Meta):
|
||||||
fields = ['extension','type','need_infra', 'prefix_v6', 'vlan']
|
fields = ['extension', 'type', 'need_infra', 'prefix_v6', 'vlan',
|
||||||
|
'ouverture_ports']
|
||||||
|
|
||||||
|
|
||||||
class DelIpTypeForm(Form):
|
class DelIpTypeForm(Form):
|
||||||
iptypes = forms.ModelMultipleChoiceField(queryset=IpType.objects.all(), label="Types d'ip actuelles", widget=forms.CheckboxSelectMultiple)
|
"""Suppression d'un ou plusieurs iptype"""
|
||||||
|
iptypes = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=IpType.objects.all(),
|
||||||
|
label="Types d'ip actuelles",
|
||||||
|
widget=forms.CheckboxSelectMultiple
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ExtensionForm(ModelForm):
|
class ExtensionForm(ModelForm):
|
||||||
|
"""Formulaire d'ajout et edition d'une extension"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Extension
|
model = Extension
|
||||||
fields = ['name', 'need_infra', 'origin']
|
fields = '__all__'
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(ExtensionForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(ExtensionForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
self.fields['name'].label = 'Extension à ajouter'
|
self.fields['name'].label = 'Extension à ajouter'
|
||||||
self.fields['origin'].label = 'Enregistrement A origin'
|
self.fields['origin'].label = 'Enregistrement A origin'
|
||||||
|
self.fields['origin_v6'].label = 'Enregistrement AAAA origin'
|
||||||
|
|
||||||
|
|
||||||
class DelExtensionForm(Form):
|
class DelExtensionForm(Form):
|
||||||
extensions = forms.ModelMultipleChoiceField(queryset=Extension.objects.all(), label="Extensions actuelles", widget=forms.CheckboxSelectMultiple)
|
"""Suppression d'une ou plusieurs extensions"""
|
||||||
|
extensions = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=Extension.objects.all(),
|
||||||
|
label="Extensions actuelles",
|
||||||
|
widget=forms.CheckboxSelectMultiple
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MxForm(ModelForm):
|
class MxForm(ModelForm):
|
||||||
|
"""Ajout et edition d'un MX"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Mx
|
model = Mx
|
||||||
fields = ['zone', 'priority', 'name']
|
fields = ['zone', 'priority', 'name']
|
||||||
|
@ -192,12 +294,24 @@ class MxForm(ModelForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(MxForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(MxForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
self.fields['name'].queryset = Domain.objects.exclude(interface_parent=None)
|
self.fields['name'].queryset = Domain.objects.exclude(
|
||||||
|
interface_parent=None
|
||||||
|
).select_related('extension')
|
||||||
|
|
||||||
|
|
||||||
class DelMxForm(Form):
|
class DelMxForm(Form):
|
||||||
mx = forms.ModelMultipleChoiceField(queryset=Mx.objects.all(), label="MX actuels", widget=forms.CheckboxSelectMultiple)
|
"""Suppression d'un ou plusieurs MX"""
|
||||||
|
mx = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=Mx.objects.all(),
|
||||||
|
label="MX actuels",
|
||||||
|
widget=forms.CheckboxSelectMultiple
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class NsForm(ModelForm):
|
class NsForm(ModelForm):
|
||||||
|
"""Ajout d'un NS pour une zone
|
||||||
|
On exclue les CNAME dans les objets domain (interdit par la rfc)
|
||||||
|
donc on prend uniquemet """
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Ns
|
model = Ns
|
||||||
fields = ['zone', 'ns']
|
fields = ['zone', 'ns']
|
||||||
|
@ -205,12 +319,22 @@ class NsForm(ModelForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(NsForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(NsForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
self.fields['ns'].queryset = Domain.objects.exclude(interface_parent=None)
|
self.fields['ns'].queryset = Domain.objects.exclude(
|
||||||
|
interface_parent=None
|
||||||
|
).select_related('extension')
|
||||||
|
|
||||||
|
|
||||||
class DelNsForm(Form):
|
class DelNsForm(Form):
|
||||||
ns = forms.ModelMultipleChoiceField(queryset=Ns.objects.all(), label="Enregistrements NS actuels", widget=forms.CheckboxSelectMultiple)
|
"""Suppresion d'un ou plusieurs NS"""
|
||||||
|
ns = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=Ns.objects.all(),
|
||||||
|
label="Enregistrements NS actuels",
|
||||||
|
widget=forms.CheckboxSelectMultiple
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TxtForm(ModelForm):
|
class TxtForm(ModelForm):
|
||||||
|
"""Ajout d'un txt pour une zone"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Text
|
model = Text
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
@ -219,10 +343,19 @@ class TxtForm(ModelForm):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(TxtForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(TxtForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class DelTxtForm(Form):
|
class DelTxtForm(Form):
|
||||||
txt = forms.ModelMultipleChoiceField(queryset=Text.objects.all(), label="Enregistrements Txt actuels", widget=forms.CheckboxSelectMultiple)
|
"""Suppression d'un ou plusieurs TXT"""
|
||||||
|
txt = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=Text.objects.all(),
|
||||||
|
label="Enregistrements Txt actuels",
|
||||||
|
widget=forms.CheckboxSelectMultiple
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class NasForm(ModelForm):
|
class NasForm(ModelForm):
|
||||||
|
"""Ajout d'un type de nas (machine d'authentification,
|
||||||
|
swicths, bornes...)"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Nas
|
model = Nas
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
@ -231,10 +364,18 @@ class NasForm(ModelForm):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(NasForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(NasForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class DelNasForm(Form):
|
class DelNasForm(Form):
|
||||||
nas = forms.ModelMultipleChoiceField(queryset=Nas.objects.all(), label="Enregistrements Nas actuels", widget=forms.CheckboxSelectMultiple)
|
"""Suppression d'un ou plusieurs nas"""
|
||||||
|
nas = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=Nas.objects.all(),
|
||||||
|
label="Enregistrements Nas actuels",
|
||||||
|
widget=forms.CheckboxSelectMultiple
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ServiceForm(ModelForm):
|
class ServiceForm(ModelForm):
|
||||||
|
"""Ajout et edition d'une classe de service : dns, dhcp, etc"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Service
|
model = Service
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
@ -242,6 +383,8 @@ class ServiceForm(ModelForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(ServiceForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(ServiceForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
|
self.fields['servers'].queryset = Interface.objects.all()\
|
||||||
|
.select_related('domain__extension')
|
||||||
|
|
||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
instance = super(ServiceForm, self).save(commit=False)
|
instance = super(ServiceForm, self).save(commit=False)
|
||||||
|
@ -250,10 +393,18 @@ class ServiceForm(ModelForm):
|
||||||
instance.process_link(self.cleaned_data.get('servers'))
|
instance.process_link(self.cleaned_data.get('servers'))
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
|
||||||
class DelServiceForm(Form):
|
class DelServiceForm(Form):
|
||||||
service = forms.ModelMultipleChoiceField(queryset=Service.objects.all(), label="Services actuels", widget=forms.CheckboxSelectMultiple)
|
"""Suppression d'un ou plusieurs service"""
|
||||||
|
service = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=Service.objects.all(),
|
||||||
|
label="Services actuels",
|
||||||
|
widget=forms.CheckboxSelectMultiple
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class VlanForm(ModelForm):
|
class VlanForm(ModelForm):
|
||||||
|
"""Ajout d'un vlan : id, nom"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Vlan
|
model = Vlan
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
@ -262,24 +413,43 @@ class VlanForm(ModelForm):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(VlanForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(VlanForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class DelVlanForm(Form):
|
class DelVlanForm(Form):
|
||||||
vlan = forms.ModelMultipleChoiceField(queryset=Vlan.objects.all(), label="Vlan actuels", widget=forms.CheckboxSelectMultiple)
|
"""Suppression d'un ou plusieurs vlans"""
|
||||||
|
vlan = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=Vlan.objects.all(),
|
||||||
|
label="Vlan actuels",
|
||||||
|
widget=forms.CheckboxSelectMultiple
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class EditOuverturePortConfigForm(ModelForm):
|
class EditOuverturePortConfigForm(ModelForm):
|
||||||
|
"""Edition de la liste des profils d'ouverture de ports
|
||||||
|
pour l'interface"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Interface
|
model = Interface
|
||||||
fields = ['port_lists']
|
fields = ['port_lists']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(EditOuverturePortConfigForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(EditOuverturePortConfigForm, self).__init__(
|
||||||
|
*args,
|
||||||
|
prefix=prefix,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class EditOuverturePortListForm(ModelForm):
|
class EditOuverturePortListForm(ModelForm):
|
||||||
|
"""Edition de la liste des ports et profils d'ouverture
|
||||||
|
des ports"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = OuverturePortList
|
model = OuverturePortList
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(EditOuverturePortListForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(EditOuverturePortListForm, self).__init__(
|
||||||
|
*args,
|
||||||
|
prefix=prefix,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
21
machines/migrations/0060_iptype_ouverture_ports.py
Normal file
21
machines/migrations/0060_iptype_ouverture_ports.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-03 16:08
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('machines', '0059_iptype_prefix_v6'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='iptype',
|
||||||
|
name='ouverture_ports',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='machines.OuverturePortList'),
|
||||||
|
),
|
||||||
|
]
|
36
machines/migrations/0061_auto_20171015_2033.py
Normal file
36
machines/migrations/0061_auto_20171015_2033.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-15 18:33
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('machines', '0060_iptype_ouverture_ports'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mx',
|
||||||
|
name='priority',
|
||||||
|
field=models.PositiveIntegerField(unique=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='ouvertureport',
|
||||||
|
name='begin',
|
||||||
|
field=models.PositiveIntegerField(validators=[django.core.validators.MaxValueValidator(65535)]),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='ouvertureport',
|
||||||
|
name='end',
|
||||||
|
field=models.PositiveIntegerField(validators=[django.core.validators.MaxValueValidator(65535)]),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='vlan',
|
||||||
|
name='vlan_id',
|
||||||
|
field=models.PositiveIntegerField(validators=[django.core.validators.MaxValueValidator(4095)]),
|
||||||
|
),
|
||||||
|
]
|
20
machines/migrations/0062_extension_origin_v6.py
Normal file
20
machines/migrations/0062_extension_origin_v6.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-18 14:08
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('machines', '0061_auto_20171015_2033'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='extension',
|
||||||
|
name='origin_v6',
|
||||||
|
field=models.GenericIPAddressField(blank=True, null=True, protocol='IPv6'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -23,44 +23,59 @@
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from datetime import timedelta
|
||||||
|
import re
|
||||||
|
from netaddr import mac_bare, EUI, IPSet, IPRange, IPNetwork, IPAddress
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.signals import post_save, pre_delete, post_delete
|
from django.db.models.signals import post_save, post_delete
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.forms import ValidationError
|
from django.forms import ValidationError
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.core.validators import MaxValueValidator
|
||||||
|
|
||||||
from macaddress.fields import MACAddressField
|
from macaddress.fields import MACAddressField
|
||||||
from netaddr import mac_bare, EUI, IPSet, IPRange, IPNetwork, IPAddress
|
|
||||||
from django.core.validators import MinValueValidator,MaxValueValidator
|
|
||||||
import re
|
|
||||||
from reversion import revisions as reversion
|
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
|
|
||||||
class Machine(models.Model):
|
class Machine(models.Model):
|
||||||
""" Class définissant une machine, object parent user, objets fils interfaces"""
|
""" Class définissant une machine, object parent user, objets fils
|
||||||
|
interfaces"""
|
||||||
PRETTY_NAME = "Machine"
|
PRETTY_NAME = "Machine"
|
||||||
|
|
||||||
user = models.ForeignKey('users.User', on_delete=models.PROTECT)
|
user = models.ForeignKey('users.User', on_delete=models.PROTECT)
|
||||||
name = models.CharField(max_length=255, help_text="Optionnel", blank=True, null=True)
|
name = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
help_text="Optionnel",
|
||||||
|
blank=True,
|
||||||
|
null=True
|
||||||
|
)
|
||||||
active = models.BooleanField(default=True)
|
active = models.BooleanField(default=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.user) + ' - ' + str(self.id) + ' - ' + str(self.name)
|
return str(self.user) + ' - ' + str(self.id) + ' - ' + str(self.name)
|
||||||
|
|
||||||
|
|
||||||
class MachineType(models.Model):
|
class MachineType(models.Model):
|
||||||
""" Type de machine, relié à un type d'ip, affecté aux interfaces"""
|
""" Type de machine, relié à un type d'ip, affecté aux interfaces"""
|
||||||
PRETTY_NAME = "Type de machine"
|
PRETTY_NAME = "Type de machine"
|
||||||
|
|
||||||
type = models.CharField(max_length=255)
|
type = models.CharField(max_length=255)
|
||||||
ip_type = models.ForeignKey('IpType', on_delete=models.PROTECT, blank=True, null=True)
|
ip_type = models.ForeignKey(
|
||||||
|
'IpType',
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
blank=True,
|
||||||
|
null=True
|
||||||
|
)
|
||||||
|
|
||||||
def all_interfaces(self):
|
def all_interfaces(self):
|
||||||
""" Renvoie toutes les interfaces (cartes réseaux) de type machinetype"""
|
""" Renvoie toutes les interfaces (cartes réseaux) de type
|
||||||
|
machinetype"""
|
||||||
return Interface.objects.filter(type=self)
|
return Interface.objects.filter(type=self)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.type
|
return self.type
|
||||||
|
|
||||||
|
|
||||||
class IpType(models.Model):
|
class IpType(models.Model):
|
||||||
""" Type d'ip, définissant un range d'ip, affecté aux machine types"""
|
""" Type d'ip, définissant un range d'ip, affecté aux machine types"""
|
||||||
|
@ -71,13 +86,27 @@ class IpType(models.Model):
|
||||||
need_infra = models.BooleanField(default=False)
|
need_infra = models.BooleanField(default=False)
|
||||||
domaine_ip_start = models.GenericIPAddressField(protocol='IPv4')
|
domaine_ip_start = models.GenericIPAddressField(protocol='IPv4')
|
||||||
domaine_ip_stop = models.GenericIPAddressField(protocol='IPv4')
|
domaine_ip_stop = models.GenericIPAddressField(protocol='IPv4')
|
||||||
prefix_v6 = models.GenericIPAddressField(protocol='IPv6', null=True, blank=True)
|
prefix_v6 = models.GenericIPAddressField(
|
||||||
vlan = models.ForeignKey('Vlan', on_delete=models.PROTECT, blank=True, null=True)
|
protocol='IPv6',
|
||||||
|
null=True,
|
||||||
|
blank=True
|
||||||
|
)
|
||||||
|
vlan = models.ForeignKey(
|
||||||
|
'Vlan',
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
blank=True,
|
||||||
|
null=True
|
||||||
|
)
|
||||||
|
ouverture_ports = models.ForeignKey(
|
||||||
|
'OuverturePortList',
|
||||||
|
blank=True,
|
||||||
|
null=True
|
||||||
|
)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def ip_range(self):
|
def ip_range(self):
|
||||||
""" Renvoie un objet IPRange à partir de l'objet IpType"""
|
""" Renvoie un objet IPRange à partir de l'objet IpType"""
|
||||||
return IPRange(self.domaine_ip_start, end=self.domaine_ip_stop)
|
return IPRange(self.domaine_ip_start, end=self.domaine_ip_stop)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def ip_set(self):
|
def ip_set(self):
|
||||||
|
@ -95,18 +124,22 @@ class IpType(models.Model):
|
||||||
|
|
||||||
def free_ip(self):
|
def free_ip(self):
|
||||||
""" Renvoie toutes les ip libres associées au type donné (self)"""
|
""" Renvoie toutes les ip libres associées au type donné (self)"""
|
||||||
return IpList.objects.filter(interface__isnull=True).filter(ip_type=self)
|
return IpList.objects.filter(
|
||||||
|
interface__isnull=True
|
||||||
|
).filter(ip_type=self)
|
||||||
|
|
||||||
def gen_ip_range(self):
|
def gen_ip_range(self):
|
||||||
""" Cree les IpList associées au type self. Parcours pédestrement et crée
|
""" Cree les IpList associées au type self. Parcours pédestrement et
|
||||||
les ip une par une. Si elles existent déjà, met à jour le type associé
|
crée les ip une par une. Si elles existent déjà, met à jour le type
|
||||||
à l'ip"""
|
associé à l'ip"""
|
||||||
# Creation du range d'ip dans les objets iplist
|
# Creation du range d'ip dans les objets iplist
|
||||||
networks = []
|
networks = []
|
||||||
for net in self.ip_range.cidrs():
|
for net in self.ip_range.cidrs():
|
||||||
networks += net.iter_hosts()
|
networks += net.iter_hosts()
|
||||||
ip_obj = [IpList(ip_type=self, ipv4=str(ip)) for ip in networks]
|
ip_obj = [IpList(ip_type=self, ipv4=str(ip)) for ip in networks]
|
||||||
listes_ip = IpList.objects.filter(ipv4__in=[str(ip) for ip in networks])
|
listes_ip = IpList.objects.filter(
|
||||||
|
ipv4__in=[str(ip) for ip in networks]
|
||||||
|
)
|
||||||
# Si il n'y a pas d'ip, on les crée
|
# Si il n'y a pas d'ip, on les crée
|
||||||
if not listes_ip:
|
if not listes_ip:
|
||||||
IpList.objects.bulk_create(ip_obj)
|
IpList.objects.bulk_create(ip_obj)
|
||||||
|
@ -116,9 +149,11 @@ class IpType(models.Model):
|
||||||
return
|
return
|
||||||
|
|
||||||
def del_ip_range(self):
|
def del_ip_range(self):
|
||||||
""" Methode dépréciée, IpList est en mode cascade et supprimé automatiquement"""
|
""" Methode dépréciée, IpList est en mode cascade et supprimé
|
||||||
|
automatiquement"""
|
||||||
if Interface.objects.filter(ipv4__in=self.ip_objects()):
|
if Interface.objects.filter(ipv4__in=self.ip_objects()):
|
||||||
raise ValidationError("Une ou plusieurs ip du range sont affectées, impossible de supprimer le range")
|
raise ValidationError("Une ou plusieurs ip du range sont\
|
||||||
|
affectées, impossible de supprimer le range")
|
||||||
for ip in self.ip_objects():
|
for ip in self.ip_objects():
|
||||||
ip.delete()
|
ip.delete()
|
||||||
|
|
||||||
|
@ -132,11 +167,13 @@ class IpType(models.Model):
|
||||||
raise ValidationError("Domaine end doit être après start...")
|
raise ValidationError("Domaine end doit être après start...")
|
||||||
# On ne crée pas plus grand qu'un /16
|
# On ne crée pas plus grand qu'un /16
|
||||||
if self.ip_range.size > 65536:
|
if self.ip_range.size > 65536:
|
||||||
raise ValidationError("Le range est trop gros, vous ne devez pas créer plus grand qu'un /16")
|
raise ValidationError("Le range est trop gros, vous ne devez\
|
||||||
|
pas créer plus grand qu'un /16")
|
||||||
# On check que les / ne se recoupent pas
|
# On check que les / ne se recoupent pas
|
||||||
for element in IpType.objects.all().exclude(pk=self.pk):
|
for element in IpType.objects.all().exclude(pk=self.pk):
|
||||||
if not self.ip_set.isdisjoint(element.ip_set):
|
if not self.ip_set.isdisjoint(element.ip_set):
|
||||||
raise ValidationError("Le range indiqué n'est pas disjoint des ranges existants")
|
raise ValidationError("Le range indiqué n'est pas disjoint\
|
||||||
|
des ranges existants")
|
||||||
# On formate le prefix v6
|
# On formate le prefix v6
|
||||||
if self.prefix_v6:
|
if self.prefix_v6:
|
||||||
self.prefix_v6 = str(IPNetwork(self.prefix_v6 + '/64').network)
|
self.prefix_v6 = str(IPNetwork(self.prefix_v6 + '/64').network)
|
||||||
|
@ -149,17 +186,20 @@ class IpType(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.type
|
return self.type
|
||||||
|
|
||||||
|
|
||||||
class Vlan(models.Model):
|
class Vlan(models.Model):
|
||||||
""" Un vlan : vlan_id et nom"""
|
""" Un vlan : vlan_id et nom
|
||||||
|
On limite le vlan id entre 0 et 4096, comme défini par la norme"""
|
||||||
PRETTY_NAME = "Vlans"
|
PRETTY_NAME = "Vlans"
|
||||||
|
|
||||||
vlan_id = models.IntegerField()
|
vlan_id = models.PositiveIntegerField(validators=[MaxValueValidator(4095)])
|
||||||
name = models.CharField(max_length=256)
|
name = models.CharField(max_length=256)
|
||||||
comment = models.CharField(max_length=256, blank=True)
|
comment = models.CharField(max_length=256, blank=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class Nas(models.Model):
|
class Nas(models.Model):
|
||||||
""" Les nas. Associé à un machine_type.
|
""" Les nas. Associé à un machine_type.
|
||||||
Permet aussi de régler le port_access_mode (802.1X ou mac-address) pour
|
Permet aussi de régler le port_access_mode (802.1X ou mac-address) pour
|
||||||
|
@ -173,48 +213,84 @@ class Nas(models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
name = models.CharField(max_length=255, unique=True)
|
name = models.CharField(max_length=255, unique=True)
|
||||||
nas_type = models.ForeignKey('MachineType', on_delete=models.PROTECT, related_name='nas_type')
|
nas_type = models.ForeignKey(
|
||||||
machine_type = models.ForeignKey('MachineType', on_delete=models.PROTECT, related_name='machinetype_on_nas')
|
'MachineType',
|
||||||
port_access_mode = models.CharField(choices=AUTH, default=default_mode, max_length=32)
|
on_delete=models.PROTECT,
|
||||||
|
related_name='nas_type'
|
||||||
|
)
|
||||||
|
machine_type = models.ForeignKey(
|
||||||
|
'MachineType',
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
related_name='machinetype_on_nas'
|
||||||
|
)
|
||||||
|
port_access_mode = models.CharField(
|
||||||
|
choices=AUTH,
|
||||||
|
default=default_mode,
|
||||||
|
max_length=32
|
||||||
|
)
|
||||||
autocapture_mac = models.BooleanField(default=False)
|
autocapture_mac = models.BooleanField(default=False)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class Extension(models.Model):
|
class Extension(models.Model):
|
||||||
""" Extension dns type example.org. Précise si tout le monde peut l'utiliser,
|
""" Extension dns type example.org. Précise si tout le monde peut
|
||||||
associé à un origin (ip d'origine)"""
|
l'utiliser, associé à un origin (ip d'origine)"""
|
||||||
PRETTY_NAME = "Extensions dns"
|
PRETTY_NAME = "Extensions dns"
|
||||||
|
|
||||||
name = models.CharField(max_length=255, unique=True)
|
name = models.CharField(max_length=255, unique=True)
|
||||||
need_infra = models.BooleanField(default=False)
|
need_infra = models.BooleanField(default=False)
|
||||||
origin = models.OneToOneField('IpList', on_delete=models.PROTECT, blank=True, null=True)
|
origin = models.OneToOneField(
|
||||||
|
'IpList',
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
blank=True,
|
||||||
|
null=True
|
||||||
|
)
|
||||||
|
origin_v6 = models.GenericIPAddressField(
|
||||||
|
protocol='IPv6',
|
||||||
|
null=True,
|
||||||
|
blank=True
|
||||||
|
)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
""" Une entrée DNS A"""
|
""" Une entrée DNS A et AAAA sur origin (zone self)"""
|
||||||
return "@ IN A " + str(self.origin)
|
entry = ""
|
||||||
|
if self.origin:
|
||||||
|
entry += "@ IN A " + str(self.origin)
|
||||||
|
if self.origin_v6:
|
||||||
|
if entry:
|
||||||
|
entry += "\n"
|
||||||
|
entry += "@ IN AAAA " + str(self.origin_v6)
|
||||||
|
return entry
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class Mx(models.Model):
|
class Mx(models.Model):
|
||||||
""" Entrées des MX. Enregistre la zone (extension) associée et la priorité
|
""" Entrées des MX. Enregistre la zone (extension) associée et la
|
||||||
|
priorité
|
||||||
Todo : pouvoir associer un MX à une interface """
|
Todo : pouvoir associer un MX à une interface """
|
||||||
PRETTY_NAME = "Enregistrements MX"
|
PRETTY_NAME = "Enregistrements MX"
|
||||||
|
|
||||||
zone = models.ForeignKey('Extension', on_delete=models.PROTECT)
|
zone = models.ForeignKey('Extension', on_delete=models.PROTECT)
|
||||||
priority = models.IntegerField(unique=True)
|
priority = models.PositiveIntegerField(unique=True)
|
||||||
name = models.OneToOneField('Domain', on_delete=models.PROTECT)
|
name = models.OneToOneField('Domain', on_delete=models.PROTECT)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
return "@ IN MX " + str(self.priority) + " " + str(self.name)
|
"""Renvoie l'entrée DNS complète pour un MX à mettre dans les
|
||||||
|
fichiers de zones"""
|
||||||
|
return "@ IN MX " + str(self.priority) + " " + str(self.name)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.zone) + ' ' + str(self.priority) + ' ' + str(self.name)
|
return str(self.zone) + ' ' + str(self.priority) + ' ' + str(self.name)
|
||||||
|
|
||||||
|
|
||||||
class Ns(models.Model):
|
class Ns(models.Model):
|
||||||
|
"""Liste des enregistrements name servers par zone considéérée"""
|
||||||
PRETTY_NAME = "Enregistrements NS"
|
PRETTY_NAME = "Enregistrements NS"
|
||||||
|
|
||||||
zone = models.ForeignKey('Extension', on_delete=models.PROTECT)
|
zone = models.ForeignKey('Extension', on_delete=models.PROTECT)
|
||||||
|
@ -222,11 +298,13 @@ class Ns(models.Model):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
return "@ IN NS " + str(self.ns)
|
"""Renvoie un enregistrement NS complet pour les filezones"""
|
||||||
|
return "@ IN NS " + str(self.ns)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.zone) + ' ' + str(self.ns)
|
return str(self.zone) + ' ' + str(self.ns)
|
||||||
|
|
||||||
|
|
||||||
class Text(models.Model):
|
class Text(models.Model):
|
||||||
""" Un enregistrement TXT associé à une extension"""
|
""" Un enregistrement TXT associé à une extension"""
|
||||||
PRETTY_NAME = "Enregistrement text"
|
PRETTY_NAME = "Enregistrement text"
|
||||||
|
@ -236,22 +314,31 @@ class Text(models.Model):
|
||||||
field2 = models.CharField(max_length=255)
|
field2 = models.CharField(max_length=255)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.zone) + " : " + str(self.field1) + " " + str(self.field2)
|
return str(self.zone) + " : " + str(self.field1) + " " +\
|
||||||
|
str(self.field2)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
|
"""Renvoie l'enregistrement TXT complet pour le fichier de zone"""
|
||||||
return str(self.field1) + " IN TXT " + str(self.field2)
|
return str(self.field1) + " IN TXT " + str(self.field2)
|
||||||
|
|
||||||
|
|
||||||
class Interface(models.Model):
|
class Interface(models.Model):
|
||||||
""" Une interface. Objet clef de l'application machine :
|
""" Une interface. Objet clef de l'application machine :
|
||||||
- une address mac unique. Possibilité de la rendre unique avec le typemachine
|
- une address mac unique. Possibilité de la rendre unique avec le
|
||||||
|
typemachine
|
||||||
- une onetoone vers IpList pour attribution ipv4
|
- une onetoone vers IpList pour attribution ipv4
|
||||||
- le type parent associé au range ip et à l'extension
|
- le type parent associé au range ip et à l'extension
|
||||||
- un objet domain associé contenant son nom
|
- un objet domain associé contenant son nom
|
||||||
- la liste des ports oiuvert"""
|
- la liste des ports oiuvert"""
|
||||||
PRETTY_NAME = "Interface"
|
PRETTY_NAME = "Interface"
|
||||||
|
|
||||||
ipv4 = models.OneToOneField('IpList', on_delete=models.PROTECT, blank=True, null=True)
|
ipv4 = models.OneToOneField(
|
||||||
|
'IpList',
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
blank=True,
|
||||||
|
null=True
|
||||||
|
)
|
||||||
mac_address = MACAddressField(integer=False, unique=True)
|
mac_address = MACAddressField(integer=False, unique=True)
|
||||||
machine = models.ForeignKey('Machine', on_delete=models.CASCADE)
|
machine = models.ForeignKey('Machine', on_delete=models.CASCADE)
|
||||||
type = models.ForeignKey('MachineType', on_delete=models.PROTECT)
|
type = models.ForeignKey('MachineType', on_delete=models.PROTECT)
|
||||||
|
@ -265,12 +352,14 @@ class Interface(models.Model):
|
||||||
user = self.machine.user
|
user = self.machine.user
|
||||||
return machine.active and user.has_access()
|
return machine.active and user.has_access()
|
||||||
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def ipv6_object(self):
|
def ipv6_object(self):
|
||||||
""" Renvoie un objet type ipv6 à partir du prefix associé à l'iptype parent"""
|
""" Renvoie un objet type ipv6 à partir du prefix associé à
|
||||||
|
l'iptype parent"""
|
||||||
if self.type.ip_type.prefix_v6:
|
if self.type.ip_type.prefix_v6:
|
||||||
return EUI(self.mac_address).ipv6(IPNetwork(self.type.ip_type.prefix_v6).network)
|
return EUI(self.mac_address).ipv6(
|
||||||
|
IPNetwork(self.type.ip_type.prefix_v6).network
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -284,10 +373,11 @@ class Interface(models.Model):
|
||||||
return str(EUI(self.mac_address, dialect=mac_bare)).lower()
|
return str(EUI(self.mac_address, dialect=mac_bare)).lower()
|
||||||
|
|
||||||
def filter_macaddress(self):
|
def filter_macaddress(self):
|
||||||
""" Tente un formatage mac_bare, si échoue, lève une erreur de validation"""
|
""" Tente un formatage mac_bare, si échoue, lève une erreur de
|
||||||
|
validation"""
|
||||||
try:
|
try:
|
||||||
self.mac_address = str(EUI(self.mac_address))
|
self.mac_address = str(EUI(self.mac_address))
|
||||||
except :
|
except:
|
||||||
raise ValidationError("La mac donnée est invalide")
|
raise ValidationError("La mac donnée est invalide")
|
||||||
|
|
||||||
def clean(self, *args, **kwargs):
|
def clean(self, *args, **kwargs):
|
||||||
|
@ -305,7 +395,8 @@ class Interface(models.Model):
|
||||||
if free_ips:
|
if free_ips:
|
||||||
self.ipv4 = free_ips[0]
|
self.ipv4 = free_ips[0]
|
||||||
else:
|
else:
|
||||||
raise ValidationError("Il n'y a plus d'ip disponibles dans le slash")
|
raise ValidationError("Il n'y a plus d'ip disponibles\
|
||||||
|
dans le slash")
|
||||||
return
|
return
|
||||||
|
|
||||||
def unassign_ipv4(self):
|
def unassign_ipv4(self):
|
||||||
|
@ -320,8 +411,10 @@ class Interface(models.Model):
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
self.filter_macaddress()
|
self.filter_macaddress()
|
||||||
# On verifie la cohérence en forçant l'extension par la méthode
|
# On verifie la cohérence en forçant l'extension par la méthode
|
||||||
if self.type.ip_type != self.ipv4.ip_type:
|
if self.ipv4:
|
||||||
raise ValidationError("L'ipv4 et le type de la machine ne correspondent pas")
|
if self.type.ip_type != self.ipv4.ip_type:
|
||||||
|
raise ValidationError("L'ipv4 et le type de la machine ne\
|
||||||
|
correspondent pas")
|
||||||
super(Interface, self).save(*args, **kwargs)
|
super(Interface, self).save(*args, **kwargs)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -340,18 +433,34 @@ class Interface(models.Model):
|
||||||
|
|
||||||
def may_have_port_open(self):
|
def may_have_port_open(self):
|
||||||
""" True si l'interface a une ip et une ip publique.
|
""" True si l'interface a une ip et une ip publique.
|
||||||
Permet de ne pas exporter des ouvertures sur des ip privées (useless)"""
|
Permet de ne pas exporter des ouvertures sur des ip privées
|
||||||
|
(useless)"""
|
||||||
return self.ipv4 and not self.has_private_ip()
|
return self.ipv4 and not self.has_private_ip()
|
||||||
|
|
||||||
|
|
||||||
class Domain(models.Model):
|
class Domain(models.Model):
|
||||||
""" Objet domain. Enregistrement A et CNAME en même temps : permet de stocker les
|
""" Objet domain. Enregistrement A et CNAME en même temps : permet de
|
||||||
alias et les nom de machines, suivant si interface_parent ou cname sont remplis"""
|
stocker les alias et les nom de machines, suivant si interface_parent
|
||||||
|
ou cname sont remplis"""
|
||||||
PRETTY_NAME = "Domaine dns"
|
PRETTY_NAME = "Domaine dns"
|
||||||
|
|
||||||
interface_parent = models.OneToOneField('Interface', on_delete=models.CASCADE, blank=True, null=True)
|
interface_parent = models.OneToOneField(
|
||||||
name = models.CharField(help_text="Obligatoire et unique, ne doit pas comporter de points", max_length=255)
|
'Interface',
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
blank=True,
|
||||||
|
null=True
|
||||||
|
)
|
||||||
|
name = models.CharField(
|
||||||
|
help_text="Obligatoire et unique, ne doit pas comporter de points",
|
||||||
|
max_length=255
|
||||||
|
)
|
||||||
extension = models.ForeignKey('Extension', on_delete=models.PROTECT)
|
extension = models.ForeignKey('Extension', on_delete=models.PROTECT)
|
||||||
cname = models.ForeignKey('self', null=True, blank=True, related_name='related_domain')
|
cname = models.ForeignKey(
|
||||||
|
'self',
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
related_name='related_domain'
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = (("name", "extension"),)
|
unique_together = (("name", "extension"),)
|
||||||
|
@ -361,7 +470,7 @@ class Domain(models.Model):
|
||||||
Retourne l'extension propre si c'est un cname, renvoie None sinon"""
|
Retourne l'extension propre si c'est un cname, renvoie None sinon"""
|
||||||
if self.interface_parent:
|
if self.interface_parent:
|
||||||
return self.interface_parent.type.ip_type.extension
|
return self.interface_parent.type.ip_type.extension
|
||||||
elif hasattr(self,'extension'):
|
elif hasattr(self, 'extension'):
|
||||||
return self.extension
|
return self.extension
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
@ -370,21 +479,26 @@ class Domain(models.Model):
|
||||||
""" Validation :
|
""" Validation :
|
||||||
- l'objet est bien soit A soit CNAME
|
- l'objet est bien soit A soit CNAME
|
||||||
- le cname est pas pointé sur lui-même
|
- le cname est pas pointé sur lui-même
|
||||||
- le nom contient bien les caractères autorisés par la norme dns et moins de 63 caractères au total
|
- le nom contient bien les caractères autorisés par la norme
|
||||||
|
dns et moins de 63 caractères au total
|
||||||
- le couple nom/extension est bien unique"""
|
- le couple nom/extension est bien unique"""
|
||||||
if self.get_extension():
|
if self.get_extension():
|
||||||
self.extension=self.get_extension()
|
self.extension = self.get_extension()
|
||||||
""" Validation du nom de domaine, extensions dans type de machine, prefixe pas plus long que 63 caractères """
|
|
||||||
if self.interface_parent and self.cname:
|
if self.interface_parent and self.cname:
|
||||||
raise ValidationError("On ne peut créer à la fois A et CNAME")
|
raise ValidationError("On ne peut créer à la fois A et CNAME")
|
||||||
if self.cname==self:
|
if self.cname == self:
|
||||||
raise ValidationError("On ne peut créer un cname sur lui même")
|
raise ValidationError("On ne peut créer un cname sur lui même")
|
||||||
HOSTNAME_LABEL_PATTERN = re.compile("(?!-)[A-Z\d-]+(?<!-)$", re.IGNORECASE)
|
HOSTNAME_LABEL_PATTERN = re.compile(
|
||||||
|
"(?!-)[A-Z\d-]+(?<!-)$",
|
||||||
|
re.IGNORECASE
|
||||||
|
)
|
||||||
dns = self.name.lower()
|
dns = self.name.lower()
|
||||||
if len(dns) > 63:
|
if len(dns) > 63:
|
||||||
raise ValidationError("Le nom de domaine %s est trop long (maximum de 63 caractères)." % dns)
|
raise ValidationError("Le nom de domaine %s est trop long\
|
||||||
|
(maximum de 63 caractères)." % dns)
|
||||||
if not HOSTNAME_LABEL_PATTERN.match(dns):
|
if not HOSTNAME_LABEL_PATTERN.match(dns):
|
||||||
raise ValidationError("Ce nom de domaine %s contient des carractères interdits." % dns)
|
raise ValidationError("Ce nom de domaine %s contient des\
|
||||||
|
carractères interdits." % dns)
|
||||||
self.validate_unique()
|
self.validate_unique()
|
||||||
super(Domain, self).clean()
|
super(Domain, self).clean()
|
||||||
|
|
||||||
|
@ -392,10 +506,11 @@ class Domain(models.Model):
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
""" Une entrée DNS"""
|
""" Une entrée DNS"""
|
||||||
if self.cname:
|
if self.cname:
|
||||||
return str(self.name) + " IN CNAME " + str(self.cname) + "."
|
return str(self.name) + " IN CNAME " + str(self.cname) + "."
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
""" Empèche le save sans extension valide. Force à avoir appellé clean avant"""
|
""" Empèche le save sans extension valide.
|
||||||
|
Force à avoir appellé clean avant"""
|
||||||
if not self.get_extension():
|
if not self.get_extension():
|
||||||
raise ValidationError("Extension invalide")
|
raise ValidationError("Extension invalide")
|
||||||
self.full_clean()
|
self.full_clean()
|
||||||
|
@ -404,6 +519,7 @@ class Domain(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.name) + str(self.extension)
|
return str(self.name) + str(self.extension)
|
||||||
|
|
||||||
|
|
||||||
class IpList(models.Model):
|
class IpList(models.Model):
|
||||||
PRETTY_NAME = "Addresses ipv4"
|
PRETTY_NAME = "Addresses ipv4"
|
||||||
|
|
||||||
|
@ -412,13 +528,15 @@ class IpList(models.Model):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def need_infra(self):
|
def need_infra(self):
|
||||||
""" Permet de savoir si un user basique peut assigner cette ip ou non"""
|
""" Permet de savoir si un user basique peut assigner cette ip ou
|
||||||
|
non"""
|
||||||
return self.ip_type.need_infra
|
return self.ip_type.need_infra
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
""" Erreur si l'ip_type est incorrect"""
|
""" Erreur si l'ip_type est incorrect"""
|
||||||
if not str(self.ipv4) in self.ip_type.ip_set_as_str:
|
if not str(self.ipv4) in self.ip_type.ip_set_as_str:
|
||||||
raise ValidationError("L'ipv4 et le range de l'iptype ne correspondent pas!")
|
raise ValidationError("L'ipv4 et le range de l'iptype ne\
|
||||||
|
correspondent pas!")
|
||||||
return
|
return
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
|
@ -428,24 +546,36 @@ class IpList(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.ipv4
|
return self.ipv4
|
||||||
|
|
||||||
|
|
||||||
class Service(models.Model):
|
class Service(models.Model):
|
||||||
""" Definition d'un service (dhcp, dns, etc)"""
|
""" Definition d'un service (dhcp, dns, etc)"""
|
||||||
service_type = models.CharField(max_length=255, blank=True, unique=True)
|
service_type = models.CharField(max_length=255, blank=True, unique=True)
|
||||||
min_time_regen = models.DurationField(default=timedelta(minutes=1), help_text="Temps minimal avant nouvelle génération du service")
|
min_time_regen = models.DurationField(
|
||||||
regular_time_regen = models.DurationField(default=timedelta(hours=1), help_text="Temps maximal avant nouvelle génération du service")
|
default=timedelta(minutes=1),
|
||||||
|
help_text="Temps minimal avant nouvelle génération du service"
|
||||||
|
)
|
||||||
|
regular_time_regen = models.DurationField(
|
||||||
|
default=timedelta(hours=1),
|
||||||
|
help_text="Temps maximal avant nouvelle génération du service"
|
||||||
|
)
|
||||||
servers = models.ManyToManyField('Interface', through='Service_link')
|
servers = models.ManyToManyField('Interface', through='Service_link')
|
||||||
|
|
||||||
def ask_regen(self):
|
def ask_regen(self):
|
||||||
""" Marque à True la demande de régénération pour un service x """
|
""" Marque à True la demande de régénération pour un service x """
|
||||||
Service_link.objects.filter(service=self).exclude(asked_regen=True).update(asked_regen=True)
|
Service_link.objects.filter(service=self).exclude(asked_regen=True)\
|
||||||
|
.update(asked_regen=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
def process_link(self, servers):
|
def process_link(self, servers):
|
||||||
""" Django ne peut créer lui meme les relations manytomany avec table intermediaire explicite"""
|
""" Django ne peut créer lui meme les relations manytomany avec table
|
||||||
for serv in servers.exclude(pk__in=Interface.objects.filter(service=self)):
|
intermediaire explicite"""
|
||||||
|
for serv in servers.exclude(
|
||||||
|
pk__in=Interface.objects.filter(service=self)
|
||||||
|
):
|
||||||
link = Service_link(service=self, server=serv)
|
link = Service_link(service=self, server=serv)
|
||||||
link.save()
|
link.save()
|
||||||
Service_link.objects.filter(service=self).exclude(server__in=servers).delete()
|
Service_link.objects.filter(service=self).exclude(server__in=servers)\
|
||||||
|
.delete()
|
||||||
return
|
return
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
|
@ -454,13 +584,16 @@ class Service(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.service_type)
|
return str(self.service_type)
|
||||||
|
|
||||||
|
|
||||||
def regen(service):
|
def regen(service):
|
||||||
""" Fonction externe pour régérération d'un service, prend un objet service en arg"""
|
""" Fonction externe pour régérération d'un service, prend un objet service
|
||||||
|
en arg"""
|
||||||
obj = Service.objects.filter(service_type=service)
|
obj = Service.objects.filter(service_type=service)
|
||||||
if obj:
|
if obj:
|
||||||
obj[0].ask_regen()
|
obj[0].ask_regen()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
class Service_link(models.Model):
|
class Service_link(models.Model):
|
||||||
""" Definition du lien entre serveurs et services"""
|
""" Definition du lien entre serveurs et services"""
|
||||||
service = models.ForeignKey('Service', on_delete=models.CASCADE)
|
service = models.ForeignKey('Service', on_delete=models.CASCADE)
|
||||||
|
@ -475,11 +608,16 @@ class Service_link(models.Model):
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
def need_regen(self):
|
def need_regen(self):
|
||||||
""" Décide si le temps minimal écoulé est suffisant pour provoquer une régénération de service"""
|
""" Décide si le temps minimal écoulé est suffisant pour provoquer une
|
||||||
if (self.asked_regen and (self.last_regen + self.service.min_time_regen) < timezone.now()) or (self.last_regen + self.service.regular_time_regen) < timezone.now():
|
régénération de service"""
|
||||||
return True
|
return bool(
|
||||||
else:
|
(self.asked_regen and (
|
||||||
return False
|
self.last_regen + self.service.min_time_regen
|
||||||
|
) < timezone.now()
|
||||||
|
) or (
|
||||||
|
self.last_regen + self.service.regular_time_regen
|
||||||
|
) < timezone.now()
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.server) + " " + str(self.service)
|
return str(self.server) + " " + str(self.service)
|
||||||
|
@ -487,22 +625,41 @@ class Service_link(models.Model):
|
||||||
|
|
||||||
class OuverturePortList(models.Model):
|
class OuverturePortList(models.Model):
|
||||||
"""Liste des ports ouverts sur une interface."""
|
"""Liste des ports ouverts sur une interface."""
|
||||||
name = models.CharField(help_text="Nom de la configuration des ports.", max_length=255)
|
name = models.CharField(
|
||||||
|
help_text="Nom de la configuration des ports.",
|
||||||
|
max_length=255
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def tcp_ports_in(self):
|
def tcp_ports_in(self):
|
||||||
return self.ouvertureport_set.filter(protocole=OuverturePort.TCP, io=OuverturePort.IN)
|
"""Renvoie la liste des ports ouverts en TCP IN pour ce profil"""
|
||||||
|
return self.ouvertureport_set.filter(
|
||||||
|
protocole=OuverturePort.TCP,
|
||||||
|
io=OuverturePort.IN
|
||||||
|
)
|
||||||
|
|
||||||
def udp_ports_in(self):
|
def udp_ports_in(self):
|
||||||
return self.ouvertureport_set.filter(protocole=OuverturePort.UDP, io=OuverturePort.IN)
|
"""Renvoie la liste des ports ouverts en UDP IN pour ce profil"""
|
||||||
|
return self.ouvertureport_set.filter(
|
||||||
|
protocole=OuverturePort.UDP,
|
||||||
|
io=OuverturePort.IN
|
||||||
|
)
|
||||||
|
|
||||||
def tcp_ports_out(self):
|
def tcp_ports_out(self):
|
||||||
return self.ouvertureport_set.filter(protocole=OuverturePort.TCP, io=OuverturePort.OUT)
|
"""Renvoie la liste des ports ouverts en TCP OUT pour ce profil"""
|
||||||
|
return self.ouvertureport_set.filter(
|
||||||
|
protocole=OuverturePort.TCP,
|
||||||
|
io=OuverturePort.OUT
|
||||||
|
)
|
||||||
|
|
||||||
def udp_ports_out(self):
|
def udp_ports_out(self):
|
||||||
return self.ouvertureport_set.filter(protocole=OuverturePort.UDP, io=OuverturePort.OUT)
|
"""Renvoie la liste des ports ouverts en UDP OUT pour ce profil"""
|
||||||
|
return self.ouvertureport_set.filter(
|
||||||
|
protocole=OuverturePort.UDP,
|
||||||
|
io=OuverturePort.OUT
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class OuverturePort(models.Model):
|
class OuverturePort(models.Model):
|
||||||
|
@ -511,119 +668,159 @@ class OuverturePort(models.Model):
|
||||||
|
|
||||||
Les ports de la plage sont compris entre begin et en inclus.
|
Les ports de la plage sont compris entre begin et en inclus.
|
||||||
Si begin == end alors on ne représente qu'un seul port.
|
Si begin == end alors on ne représente qu'un seul port.
|
||||||
|
|
||||||
|
On limite les ports entre 0 et 65535, tels que défini par la RFC
|
||||||
"""
|
"""
|
||||||
TCP = 'T'
|
TCP = 'T'
|
||||||
UDP = 'U'
|
UDP = 'U'
|
||||||
IN = 'I'
|
IN = 'I'
|
||||||
OUT = 'O'
|
OUT = 'O'
|
||||||
begin = models.IntegerField()
|
begin = models.PositiveIntegerField(validators=[MaxValueValidator(65535)])
|
||||||
end = models.IntegerField()
|
end = models.PositiveIntegerField(validators=[MaxValueValidator(65535)])
|
||||||
port_list = models.ForeignKey('OuverturePortList', on_delete=models.CASCADE)
|
port_list = models.ForeignKey(
|
||||||
|
'OuverturePortList',
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
protocole = models.CharField(
|
protocole = models.CharField(
|
||||||
max_length=1,
|
max_length=1,
|
||||||
choices=(
|
choices=(
|
||||||
(TCP, 'TCP'),
|
(TCP, 'TCP'),
|
||||||
(UDP, 'UDP'),
|
(UDP, 'UDP'),
|
||||||
),
|
),
|
||||||
default=TCP,
|
default=TCP,
|
||||||
)
|
)
|
||||||
io = models.CharField(
|
io = models.CharField(
|
||||||
max_length=1,
|
max_length=1,
|
||||||
choices=(
|
choices=(
|
||||||
(IN, 'IN'),
|
(IN, 'IN'),
|
||||||
(OUT, 'OUT'),
|
(OUT, 'OUT'),
|
||||||
),
|
),
|
||||||
default=OUT,
|
default=OUT,
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self.begin == self.end :
|
if self.begin == self.end:
|
||||||
return str(self.begin)
|
return str(self.begin)
|
||||||
return '-'.join([str(self.begin), str(self.end)])
|
return '-'.join([str(self.begin), str(self.end)])
|
||||||
|
|
||||||
def show_port(self):
|
def show_port(self):
|
||||||
|
"""Formatage plus joli, alias pour str"""
|
||||||
return str(self)
|
return str(self)
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Machine)
|
@receiver(post_save, sender=Machine)
|
||||||
def machine_post_save(sender, **kwargs):
|
def machine_post_save(sender, **kwargs):
|
||||||
|
"""Synchronisation ldap et régen parefeu/dhcp lors de la modification
|
||||||
|
d'une machine"""
|
||||||
user = kwargs['instance'].user
|
user = kwargs['instance'].user
|
||||||
user.ldap_sync(base=False, access_refresh=False, mac_refresh=True)
|
user.ldap_sync(base=False, access_refresh=False, mac_refresh=True)
|
||||||
regen('dhcp')
|
regen('dhcp')
|
||||||
regen('mac_ip_list')
|
regen('mac_ip_list')
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_delete, sender=Machine)
|
@receiver(post_delete, sender=Machine)
|
||||||
def machine_post_delete(sender, **kwargs):
|
def machine_post_delete(sender, **kwargs):
|
||||||
|
"""Synchronisation ldap et régen parefeu/dhcp lors de la suppression
|
||||||
|
d'une machine"""
|
||||||
machine = kwargs['instance']
|
machine = kwargs['instance']
|
||||||
user = machine.user
|
user = machine.user
|
||||||
user.ldap_sync(base=False, access_refresh=False, mac_refresh=True)
|
user.ldap_sync(base=False, access_refresh=False, mac_refresh=True)
|
||||||
regen('dhcp')
|
regen('dhcp')
|
||||||
regen('mac_ip_list')
|
regen('mac_ip_list')
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Interface)
|
@receiver(post_save, sender=Interface)
|
||||||
def interface_post_save(sender, **kwargs):
|
def interface_post_save(sender, **kwargs):
|
||||||
|
"""Synchronisation ldap et régen parefeu/dhcp lors de la modification
|
||||||
|
d'une interface"""
|
||||||
interface = kwargs['instance']
|
interface = kwargs['instance']
|
||||||
user = interface.machine.user
|
user = interface.machine.user
|
||||||
user.ldap_sync(base=False, access_refresh=False, mac_refresh=True)
|
user.ldap_sync(base=False, access_refresh=False, mac_refresh=True)
|
||||||
if not interface.may_have_port_open() and interface.port_lists.all():
|
|
||||||
interface.port_lists.clear()
|
|
||||||
# Regen services
|
# Regen services
|
||||||
regen('dhcp')
|
regen('dhcp')
|
||||||
regen('mac_ip_list')
|
regen('mac_ip_list')
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_delete, sender=Interface)
|
@receiver(post_delete, sender=Interface)
|
||||||
def interface_post_delete(sender, **kwargs):
|
def interface_post_delete(sender, **kwargs):
|
||||||
|
"""Synchronisation ldap et régen parefeu/dhcp lors de la suppression
|
||||||
|
d'une interface"""
|
||||||
interface = kwargs['instance']
|
interface = kwargs['instance']
|
||||||
user = interface.machine.user
|
user = interface.machine.user
|
||||||
user.ldap_sync(base=False, access_refresh=False, mac_refresh=True)
|
user.ldap_sync(base=False, access_refresh=False, mac_refresh=True)
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=IpType)
|
@receiver(post_save, sender=IpType)
|
||||||
def iptype_post_save(sender, **kwargs):
|
def iptype_post_save(sender, **kwargs):
|
||||||
|
"""Generation des objets ip après modification d'un range ip"""
|
||||||
iptype = kwargs['instance']
|
iptype = kwargs['instance']
|
||||||
iptype.gen_ip_range()
|
iptype.gen_ip_range()
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=MachineType)
|
@receiver(post_save, sender=MachineType)
|
||||||
def machine_post_save(sender, **kwargs):
|
def machine_post_save(sender, **kwargs):
|
||||||
|
"""Mise à jour des interfaces lorsque changement d'attribution
|
||||||
|
d'une machinetype (changement iptype parent)"""
|
||||||
machinetype = kwargs['instance']
|
machinetype = kwargs['instance']
|
||||||
for interface in machinetype.all_interfaces():
|
for interface in machinetype.all_interfaces():
|
||||||
interface.update_type()
|
interface.update_type()
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Domain)
|
@receiver(post_save, sender=Domain)
|
||||||
def domain_post_save(sender, **kwargs):
|
def domain_post_save(sender, **kwargs):
|
||||||
|
"""Regeneration dns après modification d'un domain object"""
|
||||||
regen('dns')
|
regen('dns')
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_delete, sender=Domain)
|
@receiver(post_delete, sender=Domain)
|
||||||
def domain_post_delete(sender, **kwargs):
|
def domain_post_delete(sender, **kwargs):
|
||||||
|
"""Regeneration dns après suppression d'un domain object"""
|
||||||
regen('dns')
|
regen('dns')
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Extension)
|
@receiver(post_save, sender=Extension)
|
||||||
def extension_post_save(sender, **kwargs):
|
def extension_post_save(sender, **kwargs):
|
||||||
|
"""Regeneration dns après modification d'une extension"""
|
||||||
regen('dns')
|
regen('dns')
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_delete, sender=Extension)
|
@receiver(post_delete, sender=Extension)
|
||||||
def extension_post_selete(sender, **kwargs):
|
def extension_post_selete(sender, **kwargs):
|
||||||
|
"""Regeneration dns après suppression d'une extension"""
|
||||||
regen('dns')
|
regen('dns')
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Mx)
|
@receiver(post_save, sender=Mx)
|
||||||
def mx_post_save(sender, **kwargs):
|
def mx_post_save(sender, **kwargs):
|
||||||
|
"""Regeneration dns après modification d'un MX"""
|
||||||
regen('dns')
|
regen('dns')
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_delete, sender=Mx)
|
@receiver(post_delete, sender=Mx)
|
||||||
def mx_post_delete(sender, **kwargs):
|
def mx_post_delete(sender, **kwargs):
|
||||||
|
"""Regeneration dns après suppresson d'un MX"""
|
||||||
regen('dns')
|
regen('dns')
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Ns)
|
@receiver(post_save, sender=Ns)
|
||||||
def ns_post_save(sender, **kwargs):
|
def ns_post_save(sender, **kwargs):
|
||||||
|
"""Regeneration dns après modification d'un NS"""
|
||||||
regen('dns')
|
regen('dns')
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_delete, sender=Ns)
|
@receiver(post_delete, sender=Ns)
|
||||||
def ns_post_delete(sender, **kwargs):
|
def ns_post_delete(sender, **kwargs):
|
||||||
|
"""Regeneration dns après modification d'un NS"""
|
||||||
regen('dns')
|
regen('dns')
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Text)
|
@receiver(post_save, sender=Text)
|
||||||
def text_post_save(sender, **kwargs):
|
def text_post_save(sender, **kwargs):
|
||||||
|
"""Regeneration dns après modification d'un TXT"""
|
||||||
regen('dns')
|
regen('dns')
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_delete, sender=Text)
|
@receiver(post_delete, sender=Text)
|
||||||
def text_post_delete(sender, **kwargs):
|
def text_post_delete(sender, **kwargs):
|
||||||
|
"""Regeneration dns après modification d'un TX"""
|
||||||
regen('dns')
|
regen('dns')
|
||||||
|
|
|
@ -24,20 +24,42 @@
|
||||||
#Augustin Lemesle
|
#Augustin Lemesle
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from machines.models import Interface, IpType, Extension, IpList, MachineType, Domain, Text, Mx, Service_link, Ns
|
from machines.models import (
|
||||||
|
Interface,
|
||||||
|
IpType,
|
||||||
|
Extension,
|
||||||
|
IpList,
|
||||||
|
MachineType,
|
||||||
|
Domain,
|
||||||
|
Text,
|
||||||
|
Mx,
|
||||||
|
Service_link,
|
||||||
|
Ns,
|
||||||
|
OuverturePortList,
|
||||||
|
OuverturePort
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class IpTypeField(serializers.RelatedField):
|
class IpTypeField(serializers.RelatedField):
|
||||||
|
"""Serialisation d'une iptype, renvoie son evaluation str"""
|
||||||
def to_representation(self, value):
|
def to_representation(self, value):
|
||||||
return value.type
|
return value.type
|
||||||
|
|
||||||
|
|
||||||
class IpListSerializer(serializers.ModelSerializer):
|
class IpListSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialisation d'une iplist, ip_type etant une foreign_key,
|
||||||
|
on evalue sa methode str"""
|
||||||
ip_type = IpTypeField(read_only=True)
|
ip_type = IpTypeField(read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = IpList
|
model = IpList
|
||||||
fields = ('ipv4', 'ip_type')
|
fields = ('ipv4', 'ip_type')
|
||||||
|
|
||||||
|
|
||||||
class InterfaceSerializer(serializers.ModelSerializer):
|
class InterfaceSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialisation d'une interface, ipv4, domain et extension sont
|
||||||
|
des foreign_key, on les override et on les evalue avec des fonctions
|
||||||
|
get_..."""
|
||||||
ipv4 = IpListSerializer(read_only=True)
|
ipv4 = IpListSerializer(read_only=True)
|
||||||
mac_address = serializers.SerializerMethodField('get_macaddress')
|
mac_address = serializers.SerializerMethodField('get_macaddress')
|
||||||
domain = serializers.SerializerMethodField('get_dns')
|
domain = serializers.SerializerMethodField('get_dns')
|
||||||
|
@ -56,7 +78,9 @@ class InterfaceSerializer(serializers.ModelSerializer):
|
||||||
def get_macaddress(self, obj):
|
def get_macaddress(self, obj):
|
||||||
return str(obj.mac_address)
|
return str(obj.mac_address)
|
||||||
|
|
||||||
|
|
||||||
class FullInterfaceSerializer(serializers.ModelSerializer):
|
class FullInterfaceSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialisation complete d'une interface avec l'ipv6 en plus"""
|
||||||
ipv4 = IpListSerializer(read_only=True)
|
ipv4 = IpListSerializer(read_only=True)
|
||||||
mac_address = serializers.SerializerMethodField('get_macaddress')
|
mac_address = serializers.SerializerMethodField('get_macaddress')
|
||||||
domain = serializers.SerializerMethodField('get_dns')
|
domain = serializers.SerializerMethodField('get_dns')
|
||||||
|
@ -75,24 +99,69 @@ class FullInterfaceSerializer(serializers.ModelSerializer):
|
||||||
def get_macaddress(self, obj):
|
def get_macaddress(self, obj):
|
||||||
return str(obj.mac_address)
|
return str(obj.mac_address)
|
||||||
|
|
||||||
|
|
||||||
class ExtensionNameField(serializers.RelatedField):
|
class ExtensionNameField(serializers.RelatedField):
|
||||||
|
"""Evaluation str d'un objet extension (.example.org)"""
|
||||||
def to_representation(self, value):
|
def to_representation(self, value):
|
||||||
return value.name
|
return value.name
|
||||||
|
|
||||||
|
|
||||||
class TypeSerializer(serializers.ModelSerializer):
|
class TypeSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialisation d'un iptype : extension et la liste des
|
||||||
|
ouvertures de port son evalués en get_... etant des
|
||||||
|
foreign_key ou des relations manytomany"""
|
||||||
extension = ExtensionNameField(read_only=True)
|
extension = ExtensionNameField(read_only=True)
|
||||||
|
ouverture_ports_tcp_in = serializers\
|
||||||
|
.SerializerMethodField('get_port_policy_input_tcp')
|
||||||
|
ouverture_ports_tcp_out = serializers\
|
||||||
|
.SerializerMethodField('get_port_policy_output_tcp')
|
||||||
|
ouverture_ports_udp_in = serializers\
|
||||||
|
.SerializerMethodField('get_port_policy_input_udp')
|
||||||
|
ouverture_ports_udp_out = serializers\
|
||||||
|
.SerializerMethodField('get_port_policy_output_udp')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = IpType
|
model = IpType
|
||||||
fields = ('type', 'extension', 'domaine_ip_start', 'domaine_ip_stop')
|
fields = ('type', 'extension', 'domaine_ip_start', 'domaine_ip_stop',
|
||||||
|
'ouverture_ports_tcp_in', 'ouverture_ports_tcp_out',
|
||||||
|
'ouverture_ports_udp_in', 'ouverture_ports_udp_out',)
|
||||||
|
|
||||||
|
def get_port_policy(self, obj, protocole, io):
|
||||||
|
if obj.ouverture_ports is None:
|
||||||
|
return []
|
||||||
|
return map(
|
||||||
|
str,
|
||||||
|
obj.ouverture_ports.ouvertureport_set.filter(
|
||||||
|
protocole=protocole
|
||||||
|
).filter(io=io)
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_port_policy_input_tcp(self, obj):
|
||||||
|
"""Renvoie la liste des ports ouverts en entrée tcp"""
|
||||||
|
return self.get_port_policy(obj, OuverturePort.TCP, OuverturePort.IN)
|
||||||
|
|
||||||
|
def get_port_policy_output_tcp(self, obj):
|
||||||
|
"""Renvoie la liste des ports ouverts en sortie tcp"""
|
||||||
|
return self.get_port_policy(obj, OuverturePort.TCP, OuverturePort.OUT)
|
||||||
|
|
||||||
|
def get_port_policy_input_udp(self, obj):
|
||||||
|
"""Renvoie la liste des ports ouverts en entrée udp"""
|
||||||
|
return self.get_port_policy(obj, OuverturePort.UDP, OuverturePort.IN)
|
||||||
|
|
||||||
|
def get_port_policy_output_udp(self, obj):
|
||||||
|
"""Renvoie la liste des ports ouverts en sortie udp"""
|
||||||
|
return self.get_port_policy(obj, OuverturePort.UDP, OuverturePort.OUT)
|
||||||
|
|
||||||
|
|
||||||
class ExtensionSerializer(serializers.ModelSerializer):
|
class ExtensionSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialisation d'une extension : origin_ip et la zone sont
|
||||||
|
des foreign_key donc evalués en get_..."""
|
||||||
origin = serializers.SerializerMethodField('get_origin_ip')
|
origin = serializers.SerializerMethodField('get_origin_ip')
|
||||||
zone_entry = serializers.SerializerMethodField('get_zone_name')
|
zone_entry = serializers.SerializerMethodField('get_zone_name')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Extension
|
model = Extension
|
||||||
fields = ('name', 'origin', 'zone_entry')
|
fields = ('name', 'origin', 'origin_v6', 'zone_entry')
|
||||||
|
|
||||||
def get_origin_ip(self, obj):
|
def get_origin_ip(self, obj):
|
||||||
return obj.origin.ipv4
|
return obj.origin.ipv4
|
||||||
|
@ -100,7 +169,10 @@ class ExtensionSerializer(serializers.ModelSerializer):
|
||||||
def get_zone_name(self, obj):
|
def get_zone_name(self, obj):
|
||||||
return str(obj.dns_entry)
|
return str(obj.dns_entry)
|
||||||
|
|
||||||
|
|
||||||
class MxSerializer(serializers.ModelSerializer):
|
class MxSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialisation d'un MX, evaluation du nom, de la zone
|
||||||
|
et du serveur cible, etant des foreign_key"""
|
||||||
name = serializers.SerializerMethodField('get_entry_name')
|
name = serializers.SerializerMethodField('get_entry_name')
|
||||||
zone = serializers.SerializerMethodField('get_zone_name')
|
zone = serializers.SerializerMethodField('get_zone_name')
|
||||||
mx_entry = serializers.SerializerMethodField('get_mx_name')
|
mx_entry = serializers.SerializerMethodField('get_mx_name')
|
||||||
|
@ -118,13 +190,16 @@ class MxSerializer(serializers.ModelSerializer):
|
||||||
def get_mx_name(self, obj):
|
def get_mx_name(self, obj):
|
||||||
return str(obj.dns_entry)
|
return str(obj.dns_entry)
|
||||||
|
|
||||||
|
|
||||||
class TextSerializer(serializers.ModelSerializer):
|
class TextSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialisation d'un txt : zone cible et l'entrée txt
|
||||||
|
sont evaluées à part"""
|
||||||
zone = serializers.SerializerMethodField('get_zone_name')
|
zone = serializers.SerializerMethodField('get_zone_name')
|
||||||
text_entry = serializers.SerializerMethodField('get_text_name')
|
text_entry = serializers.SerializerMethodField('get_text_name')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Text
|
model = Text
|
||||||
fields = ('zone','text_entry','field1', 'field2')
|
fields = ('zone', 'text_entry', 'field1', 'field2')
|
||||||
|
|
||||||
def get_zone_name(self, obj):
|
def get_zone_name(self, obj):
|
||||||
return str(obj.zone.name)
|
return str(obj.zone.name)
|
||||||
|
@ -132,7 +207,10 @@ class TextSerializer(serializers.ModelSerializer):
|
||||||
def get_text_name(self, obj):
|
def get_text_name(self, obj):
|
||||||
return str(obj.dns_entry)
|
return str(obj.dns_entry)
|
||||||
|
|
||||||
|
|
||||||
class NsSerializer(serializers.ModelSerializer):
|
class NsSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialisation d'un NS : la zone, l'entrée ns complète et le serveur
|
||||||
|
ns sont évalués à part"""
|
||||||
zone = serializers.SerializerMethodField('get_zone_name')
|
zone = serializers.SerializerMethodField('get_zone_name')
|
||||||
ns = serializers.SerializerMethodField('get_domain_name')
|
ns = serializers.SerializerMethodField('get_domain_name')
|
||||||
ns_entry = serializers.SerializerMethodField('get_text_name')
|
ns_entry = serializers.SerializerMethodField('get_text_name')
|
||||||
|
@ -150,7 +228,10 @@ class NsSerializer(serializers.ModelSerializer):
|
||||||
def get_text_name(self, obj):
|
def get_text_name(self, obj):
|
||||||
return str(obj.dns_entry)
|
return str(obj.dns_entry)
|
||||||
|
|
||||||
|
|
||||||
class DomainSerializer(serializers.ModelSerializer):
|
class DomainSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialisation d'un domain, extension, cname sont des foreign_key,
|
||||||
|
et l'entrée complète, sont évalués à part"""
|
||||||
extension = serializers.SerializerMethodField('get_zone_name')
|
extension = serializers.SerializerMethodField('get_zone_name')
|
||||||
cname = serializers.SerializerMethodField('get_alias_name')
|
cname = serializers.SerializerMethodField('get_alias_name')
|
||||||
cname_entry = serializers.SerializerMethodField('get_cname_name')
|
cname_entry = serializers.SerializerMethodField('get_cname_name')
|
||||||
|
@ -168,7 +249,9 @@ class DomainSerializer(serializers.ModelSerializer):
|
||||||
def get_cname_name(self, obj):
|
def get_cname_name(self, obj):
|
||||||
return str(obj.dns_entry)
|
return str(obj.dns_entry)
|
||||||
|
|
||||||
|
|
||||||
class ServiceServersSerializer(serializers.ModelSerializer):
|
class ServiceServersSerializer(serializers.ModelSerializer):
|
||||||
|
"""Evaluation d'un Service, et serialisation"""
|
||||||
server = serializers.SerializerMethodField('get_server_name')
|
server = serializers.SerializerMethodField('get_server_name')
|
||||||
service = serializers.SerializerMethodField('get_service_name')
|
service = serializers.SerializerMethodField('get_service_name')
|
||||||
need_regen = serializers.SerializerMethodField('get_regen_status')
|
need_regen = serializers.SerializerMethodField('get_regen_status')
|
||||||
|
@ -185,3 +268,31 @@ class ServiceServersSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
def get_regen_status(self, obj):
|
def get_regen_status(self, obj):
|
||||||
return obj.need_regen()
|
return obj.need_regen()
|
||||||
|
|
||||||
|
|
||||||
|
class OuverturePortsSerializer(serializers.Serializer):
|
||||||
|
"""Serialisation de l'ouverture des ports"""
|
||||||
|
ipv4 = serializers.SerializerMethodField()
|
||||||
|
ipv6 = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
def get_ipv4():
|
||||||
|
return {i.ipv4.ipv4:
|
||||||
|
{
|
||||||
|
"tcp_in":[j.tcp_ports_in() for j in i.port_lists.all()],
|
||||||
|
"tcp_out":[j.tcp_ports_out()for j in i.port_lists.all()],
|
||||||
|
"udp_in":[j.udp_ports_in() for j in i.port_lists.all()],
|
||||||
|
"udp_out":[j.udp_ports_out() for j in i.port_lists.all()],
|
||||||
|
}
|
||||||
|
for i in Interface.objects.all() if i.ipv4
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_ipv6():
|
||||||
|
return {i.ipv6:
|
||||||
|
{
|
||||||
|
"tcp_in":[j.tcp_ports_in() for j in i.port_lists.all()],
|
||||||
|
"tcp_out":[j.tcp_ports_out()for j in i.port_lists.all()],
|
||||||
|
"udp_in":[j.udp_ports_in() for j in i.port_lists.all()],
|
||||||
|
"udp_out":[j.udp_ports_out() for j in i.port_lists.all()],
|
||||||
|
}
|
||||||
|
for i in Interface.objects.all() if i.ipv6
|
||||||
|
}
|
||||||
|
|
|
@ -28,7 +28,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
<th>Extension</th>
|
<th>Extension</th>
|
||||||
<th>Autorisation infra pour utiliser l'extension</th>
|
<th>Autorisation infra pour utiliser l'extension</th>
|
||||||
<th>Enregistrement A origin</th>
|
<th>Enregistrement A origin</th>
|
||||||
<th></th>
|
<th>Enregistrement AAAA origin</th>
|
||||||
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
{% for extension in extension_list %}
|
{% for extension in extension_list %}
|
||||||
|
@ -36,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
<td>{{ extension.name }}</td>
|
<td>{{ extension.name }}</td>
|
||||||
<td>{{ extension.need_infra }}</td>
|
<td>{{ extension.need_infra }}</td>
|
||||||
<td>{{ extension.origin }}</td>
|
<td>{{ extension.origin }}</td>
|
||||||
|
<td>{{ extension.origin_v6 }}</td>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
{% if is_infra %}
|
{% if is_infra %}
|
||||||
{% include 'buttons/edit.html' with href='machines:edit-extension' id=extension.id %}
|
{% include 'buttons/edit.html' with href='machines:edit-extension' id=extension.id %}
|
||||||
|
|
|
@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
<th>Fin</th>
|
<th>Fin</th>
|
||||||
<th>Préfixe v6</th>
|
<th>Préfixe v6</th>
|
||||||
<th>Sur vlan</th>
|
<th>Sur vlan</th>
|
||||||
|
<th>Ouverture ports par défault</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -45,6 +46,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
<td>{{ type.domaine_ip_stop }}</td>
|
<td>{{ type.domaine_ip_stop }}</td>
|
||||||
<td>{{ type.prefix_v6 }}</td>
|
<td>{{ type.prefix_v6 }}</td>
|
||||||
<td>{{ type.vlan }}</td>
|
<td>{{ type.vlan }}</td>
|
||||||
|
<td>{{ type.ouverture_ports }}</td>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
{% if is_infra %}
|
{% if is_infra %}
|
||||||
{% include 'buttons/edit.html' with href='machines:edit-iptype' id=type.id %}
|
{% include 'buttons/edit.html' with href='machines:edit-iptype' id=type.id %}
|
||||||
|
|
|
@ -58,7 +58,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
{% if is_cableur %}
|
{% if is_cableur %}
|
||||||
<a class="list-group-item list-group-item-info" href="{% url "machines:index-portlist" %}">
|
<a class="list-group-item list-group-item-info" href="{% url "machines:index-portlist" %}">
|
||||||
<i class="glyphicon glyphicon-list"></i>
|
<i class="glyphicon glyphicon-list"></i>
|
||||||
Configuration de ports
|
Ouverture de ports
|
||||||
</a>
|
</a>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -93,6 +93,7 @@ urlpatterns = [
|
||||||
url(r'^rest/text/$', views.text, name='text'),
|
url(r'^rest/text/$', views.text, name='text'),
|
||||||
url(r'^rest/zones/$', views.zones, name='zones'),
|
url(r'^rest/zones/$', views.zones, name='zones'),
|
||||||
url(r'^rest/service_servers/$', views.service_servers, name='service-servers'),
|
url(r'^rest/service_servers/$', views.service_servers, name='service-servers'),
|
||||||
|
url(r'^rest/ouverture_ports/$', views.ouverture_ports, name='ouverture-ports'),
|
||||||
url(r'index_portlist/$', views.index_portlist, name='index-portlist'),
|
url(r'index_portlist/$', views.index_portlist, name='index-portlist'),
|
||||||
url(r'^edit_portlist/(?P<pk>[0-9]+)$', views.edit_portlist, name='edit-portlist'),
|
url(r'^edit_portlist/(?P<pk>[0-9]+)$', views.edit_portlist, name='edit-portlist'),
|
||||||
url(r'^del_portlist/(?P<pk>[0-9]+)$', views.del_portlist, name='del-portlist'),
|
url(r'^del_portlist/(?P<pk>[0-9]+)$', views.del_portlist, name='del-portlist'),
|
||||||
|
|
|
@ -43,18 +43,79 @@ from django.contrib.auth import authenticate, login
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
|
||||||
from rest_framework.renderers import JSONRenderer
|
from rest_framework.renderers import JSONRenderer
|
||||||
from machines.serializers import FullInterfaceSerializer, InterfaceSerializer, TypeSerializer, DomainSerializer, TextSerializer, MxSerializer, ExtensionSerializer, ServiceServersSerializer, NsSerializer
|
from machines.serializers import ( FullInterfaceSerializer,
|
||||||
|
InterfaceSerializer,
|
||||||
|
TypeSerializer,
|
||||||
|
DomainSerializer,
|
||||||
|
TextSerializer,
|
||||||
|
MxSerializer,
|
||||||
|
ExtensionSerializer,
|
||||||
|
ServiceServersSerializer,
|
||||||
|
NsSerializer,
|
||||||
|
OuverturePortsSerializer
|
||||||
|
)
|
||||||
from reversion import revisions as reversion
|
from reversion import revisions as reversion
|
||||||
from reversion.models import Version
|
from reversion.models import Version
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm, BaseEditInterfaceForm, BaseEditMachineForm
|
from .forms import (
|
||||||
from .forms import EditIpTypeForm, IpTypeForm, DelIpTypeForm, DomainForm, AliasForm, DelAliasForm, NsForm, DelNsForm, TxtForm, DelTxtForm, MxForm, DelMxForm, VlanForm, DelVlanForm, ServiceForm, DelServiceForm, NasForm, DelNasForm
|
NewMachineForm,
|
||||||
|
EditMachineForm,
|
||||||
|
EditInterfaceForm,
|
||||||
|
AddInterfaceForm,
|
||||||
|
MachineTypeForm,
|
||||||
|
DelMachineTypeForm,
|
||||||
|
ExtensionForm,
|
||||||
|
DelExtensionForm,
|
||||||
|
BaseEditInterfaceForm,
|
||||||
|
BaseEditMachineForm
|
||||||
|
)
|
||||||
|
from .forms import (
|
||||||
|
EditIpTypeForm,
|
||||||
|
IpTypeForm,
|
||||||
|
DelIpTypeForm,
|
||||||
|
DomainForm,
|
||||||
|
AliasForm,
|
||||||
|
DelAliasForm,
|
||||||
|
NsForm,
|
||||||
|
DelNsForm,
|
||||||
|
TxtForm,
|
||||||
|
DelTxtForm,
|
||||||
|
MxForm,
|
||||||
|
DelMxForm,
|
||||||
|
VlanForm,
|
||||||
|
DelVlanForm,
|
||||||
|
ServiceForm,
|
||||||
|
DelServiceForm,
|
||||||
|
NasForm,
|
||||||
|
DelNasForm
|
||||||
|
)
|
||||||
from .forms import EditOuverturePortListForm, EditOuverturePortConfigForm
|
from .forms import EditOuverturePortListForm, EditOuverturePortConfigForm
|
||||||
from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain, Service, Service_link, Vlan, Nas, Text, OuverturePortList, OuverturePort
|
from .models import (
|
||||||
|
IpType,
|
||||||
|
Machine,
|
||||||
|
Interface,
|
||||||
|
IpList,
|
||||||
|
MachineType,
|
||||||
|
Extension,
|
||||||
|
Mx,
|
||||||
|
Ns,
|
||||||
|
Domain,
|
||||||
|
Service,
|
||||||
|
Service_link,
|
||||||
|
Vlan,
|
||||||
|
Nas,
|
||||||
|
Text,
|
||||||
|
OuverturePortList,
|
||||||
|
OuverturePort
|
||||||
|
)
|
||||||
from users.models import User
|
from users.models import User
|
||||||
from preferences.models import GeneralOption, OptionalMachine
|
from preferences.models import GeneralOption, OptionalMachine
|
||||||
from re2o.utils import all_active_assigned_interfaces, all_has_access
|
from re2o.utils import (
|
||||||
|
all_active_assigned_interfaces,
|
||||||
|
all_has_access,
|
||||||
|
filter_active_interfaces
|
||||||
|
)
|
||||||
from re2o.views import form
|
from re2o.views import form
|
||||||
|
|
||||||
def f_type_id( is_type_tt ):
|
def f_type_id( is_type_tt ):
|
||||||
|
@ -71,7 +132,8 @@ def generate_ipv4_choices( form ) :
|
||||||
choices = '{"":[{key:"",value:"Choisissez d\'abord un type de machine"},'
|
choices = '{"":[{key:"",value:"Choisissez d\'abord un type de machine"},'
|
||||||
mtype_id = -1
|
mtype_id = -1
|
||||||
|
|
||||||
for ip in f_ipv4.queryset.annotate(mtype_id=F('ip_type__machinetype__id')).order_by('mtype_id', 'id') :
|
for ip in f_ipv4.queryset.annotate(mtype_id=F('ip_type__machinetype__id'))\
|
||||||
|
.order_by('mtype_id', 'id') :
|
||||||
if mtype_id != ip.mtype_id :
|
if mtype_id != ip.mtype_id :
|
||||||
mtype_id = ip.mtype_id
|
mtype_id = ip.mtype_id
|
||||||
used_mtype_id.append(mtype_id)
|
used_mtype_id.append(mtype_id)
|
||||||
|
@ -140,8 +202,8 @@ def generate_ipv4_mbf_param( form, is_type_tt ):
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def new_machine(request, userid):
|
def new_machine(request, userid):
|
||||||
""" Fonction de creation d'une machine. Cree l'objet machine, le sous objet interface et l'objet domain
|
""" Fonction de creation d'une machine. Cree l'objet machine,
|
||||||
à partir de model forms.
|
le sous objet interface et l'objet domain à partir de model forms.
|
||||||
Trop complexe, devrait être simplifié"""
|
Trop complexe, devrait être simplifié"""
|
||||||
try:
|
try:
|
||||||
user = User.objects.get(pk=userid)
|
user = User.objects.get(pk=userid)
|
||||||
|
@ -152,15 +214,16 @@ def new_machine(request, userid):
|
||||||
max_lambdauser_interfaces = options.max_lambdauser_interfaces
|
max_lambdauser_interfaces = options.max_lambdauser_interfaces
|
||||||
if not request.user.has_perms(('cableur',)):
|
if not request.user.has_perms(('cableur',)):
|
||||||
if user != request.user:
|
if user != request.user:
|
||||||
messages.error(request, "Vous ne pouvez pas ajouter une machine à un autre user que vous sans droit")
|
messages.error(
|
||||||
|
request,
|
||||||
|
"Vous ne pouvez pas ajouter une machine à un autre user que vous sans droit")
|
||||||
return redirect("/users/profil/" + str(request.user.id))
|
return redirect("/users/profil/" + str(request.user.id))
|
||||||
if user.user_interfaces().count() >= max_lambdauser_interfaces:
|
if user.user_interfaces().count() >= max_lambdauser_interfaces:
|
||||||
messages.error(request, "Vous avez atteint le maximum d'interfaces autorisées que vous pouvez créer vous même (%s) " % max_lambdauser_interfaces)
|
messages.error(request, "Vous avez atteint le maximum d'interfaces autorisées que vous pouvez créer vous même (%s) " % max_lambdauser_interfaces)
|
||||||
return redirect("/users/profil/" + str(request.user.id))
|
return redirect("/users/profil/" + str(request.user.id))
|
||||||
machine = NewMachineForm(request.POST or None)
|
machine = NewMachineForm(request.POST or None)
|
||||||
interface = AddInterfaceForm(request.POST or None, infra=request.user.has_perms(('infra',)))
|
interface = AddInterfaceForm(request.POST or None, infra=request.user.has_perms(('infra',)))
|
||||||
nb_machine = Interface.objects.filter(machine__user=userid).count()
|
domain = DomainForm(request.POST or None, user=user)
|
||||||
domain = DomainForm(request.POST or None, user=user, nb_machine=nb_machine)
|
|
||||||
if machine.is_valid() and interface.is_valid():
|
if machine.is_valid() and interface.is_valid():
|
||||||
new_machine = machine.save(commit=False)
|
new_machine = machine.save(commit=False)
|
||||||
new_machine.user = user
|
new_machine.user = user
|
||||||
|
@ -993,7 +1056,9 @@ def history(request, object, id):
|
||||||
@login_required
|
@login_required
|
||||||
@permission_required('cableur')
|
@permission_required('cableur')
|
||||||
def index_portlist(request):
|
def index_portlist(request):
|
||||||
port_list = OuverturePortList.objects.prefetch_related('ouvertureport_set').prefetch_related('interface_set').order_by('name')
|
port_list = OuverturePortList.objects.prefetch_related('ouvertureport_set')\
|
||||||
|
.prefetch_related('interface_set__domain__extension')\
|
||||||
|
.prefetch_related('interface_set__machine__user').order_by('name')
|
||||||
return render(request, "machines/index_portlist.html", {'port_list':port_list})
|
return render(request, "machines/index_portlist.html", {'port_list':port_list})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -1184,6 +1249,34 @@ def service_servers(request):
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
@login_required
|
@login_required
|
||||||
@permission_required('serveur')
|
@permission_required('serveur')
|
||||||
|
def ouverture_ports(request):
|
||||||
|
r = {'ipv4':{}, 'ipv6':{}}
|
||||||
|
for o in OuverturePortList.objects.all().prefetch_related('ouvertureport_set').prefetch_related('interface_set', 'interface_set__ipv4'):
|
||||||
|
pl = {
|
||||||
|
"tcp_in":set(map(str,o.ouvertureport_set.filter(protocole=OuverturePort.TCP, io=OuverturePort.IN))),
|
||||||
|
"tcp_out":set(map(str,o.ouvertureport_set.filter(protocole=OuverturePort.TCP, io=OuverturePort.OUT))),
|
||||||
|
"udp_in":set(map(str,o.ouvertureport_set.filter(protocole=OuverturePort.UDP, io=OuverturePort.IN))),
|
||||||
|
"udp_out":set(map(str,o.ouvertureport_set.filter(protocole=OuverturePort.UDP, io=OuverturePort.OUT))),
|
||||||
|
}
|
||||||
|
for i in filter_active_interfaces(o.interface_set):
|
||||||
|
if i.may_have_port_open():
|
||||||
|
d = r['ipv4'].get(i.ipv4.ipv4, {})
|
||||||
|
d["tcp_in"] = d.get("tcp_in",set()).union(pl["tcp_in"])
|
||||||
|
d["tcp_out"] = d.get("tcp_out",set()).union(pl["tcp_out"])
|
||||||
|
d["udp_in"] = d.get("udp_in",set()).union(pl["udp_in"])
|
||||||
|
d["udp_out"] = d.get("udp_out",set()).union(pl["udp_out"])
|
||||||
|
r['ipv4'][i.ipv4.ipv4] = d
|
||||||
|
if i.ipv6_object:
|
||||||
|
d = r['ipv6'].get(i.ipv6, {})
|
||||||
|
d["tcp_in"] = d.get("tcp_in",set()).union(pl["tcp_in"])
|
||||||
|
d["tcp_out"] = d.get("tcp_out",set()).union(pl["tcp_out"])
|
||||||
|
d["udp_in"] = d.get("udp_in",set()).union(pl["udp_in"])
|
||||||
|
d["udp_out"] = d.get("udp_out",set()).union(pl["udp_out"])
|
||||||
|
r['ipv6'][i.ipv6] = d
|
||||||
|
return JSONResponse(r)
|
||||||
|
@csrf_exempt
|
||||||
|
@login_required
|
||||||
|
@permission_required('serveur')
|
||||||
def regen_achieved(request):
|
def regen_achieved(request):
|
||||||
obj = Service_link.objects.filter(service__in=Service.objects.filter(service_type=request.POST['service']), server__in=Interface.objects.filter(domain__in=Domain.objects.filter(name=request.POST['server'])))
|
obj = Service_link.objects.filter(service__in=Service.objects.filter(service_type=request.POST['service']), server__in=Interface.objects.filter(domain__in=Domain.objects.filter(name=request.POST['server'])))
|
||||||
if obj:
|
if obj:
|
||||||
|
|
20
preferences/migrations/0021_auto_20171015_1741.py
Normal file
20
preferences/migrations/0021_auto_20171015_1741.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-15 15:41
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('preferences', '0020_optionalmachine_ipv6'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='optionaltopologie',
|
||||||
|
name='radius_general_policy',
|
||||||
|
field=models.CharField(choices=[('MACHINE', 'Sur le vlan de la plage ip machine'), ('DEFINED', 'Prédéfini dans "Vlan où placer les machines après acceptation RADIUS"')], default='DEFINED', max_length=32),
|
||||||
|
),
|
||||||
|
]
|
20
preferences/migrations/0022_auto_20171015_1758.py
Normal file
20
preferences/migrations/0022_auto_20171015_1758.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-15 15:58
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('preferences', '0021_auto_20171015_1741'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='optionaltopologie',
|
||||||
|
name='radius_general_policy',
|
||||||
|
field=models.CharField(choices=[('MACHINE', 'Sur le vlan de la plage ip machine'), ('DEFINED', 'Prédéfini dans "Vlan où placer les machines après acceptation RADIUS"')], default='DEFINED', max_length=32),
|
||||||
|
),
|
||||||
|
]
|
20
preferences/migrations/0023_auto_20171015_2033.py
Normal file
20
preferences/migrations/0023_auto_20171015_2033.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-15 18:33
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('preferences', '0022_auto_20171015_1758'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='optionaltopologie',
|
||||||
|
name='radius_general_policy',
|
||||||
|
field=models.CharField(choices=[('MACHINE', 'Sur le vlan de la plage ip machine'), ('DEFINED', 'Prédéfini dans "Vlan où placer les machines après acceptation RADIUS"')], default='DEFINED', max_length=32),
|
||||||
|
),
|
||||||
|
]
|
|
@ -69,7 +69,7 @@ urlpatterns = [
|
||||||
),
|
),
|
||||||
url(r'^del_services/$', views.del_services, name='del-services'),
|
url(r'^del_services/$', views.del_services, name='del-services'),
|
||||||
url(
|
url(
|
||||||
r'^history/(?P<object>service)/(?P<id>[0-9]+)$',
|
r'^history/(?P<object_name>service)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'
|
name='history'
|
||||||
),
|
),
|
||||||
|
|
|
@ -104,9 +104,9 @@ def all_has_access(search_time=DT_NOW):
|
||||||
).distinct()
|
).distinct()
|
||||||
|
|
||||||
|
|
||||||
def all_active_interfaces():
|
def filter_active_interfaces(interface_set):
|
||||||
"""Renvoie l'ensemble des machines autorisées à sortir sur internet """
|
"""Filtre les machines autorisées à sortir sur internet dans une requête"""
|
||||||
return Interface.objects.filter(
|
return interface_set.filter(
|
||||||
machine__in=Machine.objects.filter(
|
machine__in=Machine.objects.filter(
|
||||||
user__in=all_has_access()
|
user__in=all_has_access()
|
||||||
).filter(active=True)
|
).filter(active=True)
|
||||||
|
@ -116,6 +116,11 @@ def all_active_interfaces():
|
||||||
.distinct()
|
.distinct()
|
||||||
|
|
||||||
|
|
||||||
|
def all_active_interfaces():
|
||||||
|
"""Renvoie l'ensemble des machines autorisées à sortir sur internet """
|
||||||
|
return filter_active_interfaces(Interface.objects)
|
||||||
|
|
||||||
|
|
||||||
def all_active_assigned_interfaces():
|
def all_active_assigned_interfaces():
|
||||||
""" Renvoie l'ensemble des machines qui ont une ipv4 assignées et
|
""" Renvoie l'ensemble des machines qui ont une ipv4 assignées et
|
||||||
disposant de l'accès internet"""
|
disposant de l'accès internet"""
|
||||||
|
|
|
@ -82,6 +82,11 @@ class AddPortForm(ModelForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(AddPortForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(AddPortForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
|
self.fields['machine_interface'].queryset = Interface.objects.all()\
|
||||||
|
.select_related('domain__extension')
|
||||||
|
self.fields['related'].queryset = Port.objects.all()\
|
||||||
|
.select_related('switch__switch_interface__domain__extension')\
|
||||||
|
.order_by('switch', 'port')
|
||||||
|
|
||||||
|
|
||||||
class StackForm(ModelForm):
|
class StackForm(ModelForm):
|
||||||
|
@ -105,6 +110,8 @@ class EditSwitchForm(ModelForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
super(EditSwitchForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(EditSwitchForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
|
self.fields['switch_interface'].queryset = Interface.objects.all()\
|
||||||
|
.select_related('domain__extension')
|
||||||
self.fields['location'].label = 'Localisation'
|
self.fields['location'].label = 'Localisation'
|
||||||
self.fields['number'].label = 'Nombre de ports'
|
self.fields['number'].label = 'Nombre de ports'
|
||||||
|
|
||||||
|
|
40
topologie/migrations/0031_auto_20171015_2033.py
Normal file
40
topologie/migrations/0031_auto_20171015_2033.py
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-15 18:33
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('topologie', '0030_auto_20171004_0235'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='port',
|
||||||
|
name='port',
|
||||||
|
field=models.PositiveIntegerField(),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='stack',
|
||||||
|
name='member_id_max',
|
||||||
|
field=models.PositiveIntegerField(),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='stack',
|
||||||
|
name='member_id_min',
|
||||||
|
field=models.PositiveIntegerField(),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='switch',
|
||||||
|
name='number',
|
||||||
|
field=models.PositiveIntegerField(),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='switch',
|
||||||
|
name='stack_member_id',
|
||||||
|
field=models.PositiveIntegerField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
]
|
|
@ -52,8 +52,8 @@ class Stack(models.Model):
|
||||||
name = models.CharField(max_length=32, blank=True, null=True)
|
name = models.CharField(max_length=32, blank=True, null=True)
|
||||||
stack_id = models.CharField(max_length=32, unique=True)
|
stack_id = models.CharField(max_length=32, unique=True)
|
||||||
details = models.CharField(max_length=255, blank=True, null=True)
|
details = models.CharField(max_length=255, blank=True, null=True)
|
||||||
member_id_min = models.IntegerField()
|
member_id_min = models.PositiveIntegerField()
|
||||||
member_id_max = models.IntegerField()
|
member_id_max = models.PositiveIntegerField()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return " ".join([self.name, self.stack_id])
|
return " ".join([self.name, self.stack_id])
|
||||||
|
@ -90,7 +90,7 @@ class Switch(models.Model):
|
||||||
on_delete=models.CASCADE
|
on_delete=models.CASCADE
|
||||||
)
|
)
|
||||||
location = models.CharField(max_length=255)
|
location = models.CharField(max_length=255)
|
||||||
number = models.IntegerField()
|
number = models.PositiveIntegerField()
|
||||||
details = models.CharField(max_length=255, blank=True)
|
details = models.CharField(max_length=255, blank=True)
|
||||||
stack = models.ForeignKey(
|
stack = models.ForeignKey(
|
||||||
Stack,
|
Stack,
|
||||||
|
@ -98,7 +98,7 @@ class Switch(models.Model):
|
||||||
null=True,
|
null=True,
|
||||||
on_delete=models.SET_NULL
|
on_delete=models.SET_NULL
|
||||||
)
|
)
|
||||||
stack_member_id = models.IntegerField(blank=True, null=True)
|
stack_member_id = models.PositiveIntegerField(blank=True, null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ('stack', 'stack_member_id')
|
unique_together = ('stack', 'stack_member_id')
|
||||||
|
@ -145,8 +145,12 @@ class Port(models.Model):
|
||||||
('COMMON', 'COMMON'),
|
('COMMON', 'COMMON'),
|
||||||
)
|
)
|
||||||
|
|
||||||
switch = models.ForeignKey('Switch', related_name="ports")
|
switch = models.ForeignKey(
|
||||||
port = models.IntegerField()
|
'Switch',
|
||||||
|
related_name="ports",
|
||||||
|
on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
port = models.PositiveIntegerField()
|
||||||
room = models.ForeignKey(
|
room = models.ForeignKey(
|
||||||
'Room',
|
'Room',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
|
|
|
@ -52,6 +52,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
<a class="btn btn-info btn-sm" role="button" title="Historique" href="{% url 'topologie:history' 'switch' switch.pk %}">
|
<a class="btn btn-info btn-sm" role="button" title="Historique" href="{% url 'topologie:history' 'switch' switch.pk %}">
|
||||||
<i class="glyphicon glyphicon-time"></i>
|
<i class="glyphicon glyphicon-time"></i>
|
||||||
</a>
|
</a>
|
||||||
|
{% include 'buttons/edit.html' with href='topologie:edit-switch' id=switch.pk %}
|
||||||
|
{% include 'buttons/suppr.html' with href='machines:del-interface' id=switch.switch_interface.id %}
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -42,16 +42,16 @@ urlpatterns = [
|
||||||
url(r'^switch/(?P<switch_id>[0-9]+)$',
|
url(r'^switch/(?P<switch_id>[0-9]+)$',
|
||||||
views.index_port,
|
views.index_port,
|
||||||
name='index-port'),
|
name='index-port'),
|
||||||
url(r'^history/(?P<object>switch)/(?P<id>[0-9]+)$',
|
url(r'^history/(?P<object_name>switch)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'),
|
name='history'),
|
||||||
url(r'^history/(?P<object>port)/(?P<id>[0-9]+)$',
|
url(r'^history/(?P<object_name>port)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'),
|
name='history'),
|
||||||
url(r'^history/(?P<object>room)/(?P<id>[0-9]+)$',
|
url(r'^history/(?P<object_name>room)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'),
|
name='history'),
|
||||||
url(r'^history/(?P<object>stack)/(?P<id>[0-9]+)$',
|
url(r'^history/(?P<object_name>stack)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'),
|
name='history'),
|
||||||
url(r'^edit_port/(?P<port_id>[0-9]+)$', views.edit_port, name='edit-port'),
|
url(r'^edit_port/(?P<port_id>[0-9]+)$', views.edit_port, name='edit-port'),
|
||||||
|
|
|
@ -50,7 +50,7 @@ from topologie.forms import EditPortForm, NewSwitchForm, EditSwitchForm
|
||||||
from topologie.forms import AddPortForm, EditRoomForm, StackForm
|
from topologie.forms import AddPortForm, EditRoomForm, StackForm
|
||||||
from users.views import form
|
from users.views import form
|
||||||
|
|
||||||
from machines.forms import AliasForm, NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm
|
from machines.forms import DomainForm, NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm
|
||||||
from machines.views import generate_ipv4_mbf_param
|
from machines.views import generate_ipv4_mbf_param
|
||||||
from preferences.models import AssoOption, GeneralOption
|
from preferences.models import AssoOption, GeneralOption
|
||||||
|
|
||||||
|
@ -135,7 +135,8 @@ def index_port(request, switch_id):
|
||||||
port_list = Port.objects.filter(switch=switch)\
|
port_list = Port.objects.filter(switch=switch)\
|
||||||
.select_related('room')\
|
.select_related('room')\
|
||||||
.select_related('machine_interface__domain__extension')\
|
.select_related('machine_interface__domain__extension')\
|
||||||
.select_related('related')\
|
.select_related('machine_interface__machine__user')\
|
||||||
|
.select_related('related__switch__switch_interface__domain__extension')\
|
||||||
.select_related('switch')\
|
.select_related('switch')\
|
||||||
.order_by('port')
|
.order_by('port')
|
||||||
return render(request, 'topologie/index_p.html', {
|
return render(request, 'topologie/index_p.html', {
|
||||||
|
@ -344,9 +345,8 @@ def new_switch(request):
|
||||||
request.POST or None,
|
request.POST or None,
|
||||||
infra=request.user.has_perms(('infra',))
|
infra=request.user.has_perms(('infra',))
|
||||||
)
|
)
|
||||||
domain = AliasForm(
|
domain = DomainForm(
|
||||||
request.POST or None,
|
request.POST or None,
|
||||||
infra=request.user.has_perms(('infra',))
|
|
||||||
)
|
)
|
||||||
if switch.is_valid() and machine.is_valid() and interface.is_valid():
|
if switch.is_valid() and machine.is_valid() and interface.is_valid():
|
||||||
options, _created = AssoOption.objects.get_or_create()
|
options, _created = AssoOption.objects.get_or_create()
|
||||||
|
@ -410,9 +410,8 @@ def edit_switch(request, switch_id):
|
||||||
request.POST or None,
|
request.POST or None,
|
||||||
instance=switch.switch_interface
|
instance=switch.switch_interface
|
||||||
)
|
)
|
||||||
domain_form = AliasForm(
|
domain_form = DomainForm(
|
||||||
request.POST or None,
|
request.POST or None,
|
||||||
infra=request.user.has_perms(('infra',)),
|
|
||||||
instance=switch.switch_interface.domain
|
instance=switch.switch_interface.domain
|
||||||
)
|
)
|
||||||
if switch_form.is_valid() and machine_form.is_valid()\
|
if switch_form.is_valid() and machine_form.is_valid()\
|
||||||
|
|
|
@ -452,13 +452,14 @@ class RightForm(ModelForm):
|
||||||
class DelRightForm(Form):
|
class DelRightForm(Form):
|
||||||
"""Suppression d'un droit d'un user"""
|
"""Suppression d'un droit d'un user"""
|
||||||
rights = forms.ModelMultipleChoiceField(
|
rights = forms.ModelMultipleChoiceField(
|
||||||
queryset=Right.objects.all(),
|
queryset=Right.objects.select_related('user'),
|
||||||
widget=forms.CheckboxSelectMultiple
|
widget=forms.CheckboxSelectMultiple
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, right, *args, **kwargs):
|
def __init__(self, right, *args, **kwargs):
|
||||||
super(DelRightForm, self).__init__(*args, **kwargs)
|
super(DelRightForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['rights'].queryset = Right.objects.filter(right=right)
|
self.fields['rights'].queryset = Right.objects.select_related('user')\
|
||||||
|
.select_related('right').filter(right=right)
|
||||||
|
|
||||||
|
|
||||||
class BanForm(ModelForm):
|
class BanForm(ModelForm):
|
||||||
|
|
37
users/migrations/0056_auto_20171015_2033.py
Normal file
37
users/migrations/0056_auto_20171015_2033.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-15 18:33
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
import users.models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('users', '0055_auto_20171003_0556'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='listright',
|
||||||
|
name='gid',
|
||||||
|
field=models.PositiveIntegerField(null=True, unique=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='listright',
|
||||||
|
name='listright',
|
||||||
|
field=models.CharField(max_length=255, unique=True, validators=[django.core.validators.RegexValidator('^[a-z]+$', message='Les groupes unix ne peuvent contenir que des lettres minuscules')]),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='user',
|
||||||
|
name='rezo_rez_uid',
|
||||||
|
field=models.PositiveIntegerField(blank=True, null=True, unique=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='user',
|
||||||
|
name='uid_number',
|
||||||
|
field=models.PositiveIntegerField(default=users.models.User.auto_uid, unique=True),
|
||||||
|
),
|
||||||
|
]
|
|
@ -243,8 +243,8 @@ class User(AbstractBaseUser):
|
||||||
state = models.IntegerField(choices=STATES, default=STATE_ACTIVE)
|
state = models.IntegerField(choices=STATES, default=STATE_ACTIVE)
|
||||||
registered = models.DateTimeField(auto_now_add=True)
|
registered = models.DateTimeField(auto_now_add=True)
|
||||||
telephone = models.CharField(max_length=15, blank=True, null=True)
|
telephone = models.CharField(max_length=15, blank=True, null=True)
|
||||||
uid_number = models.IntegerField(default=auto_uid, unique=True)
|
uid_number = models.PositiveIntegerField(default=auto_uid, unique=True)
|
||||||
rezo_rez_uid = models.IntegerField(unique=True, blank=True, null=True)
|
rezo_rez_uid = models.PositiveIntegerField(unique=True, blank=True, null=True)
|
||||||
|
|
||||||
USERNAME_FIELD = 'pseudo'
|
USERNAME_FIELD = 'pseudo'
|
||||||
REQUIRED_FIELDS = ['name', 'surname', 'email']
|
REQUIRED_FIELDS = ['name', 'surname', 'email']
|
||||||
|
@ -840,7 +840,7 @@ class ListRight(models.Model):
|
||||||
que des lettres minuscules"
|
que des lettres minuscules"
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
gid = models.IntegerField(unique=True, null=True)
|
gid = models.PositiveIntegerField(unique=True, null=True)
|
||||||
details = models.CharField(
|
details = models.CharField(
|
||||||
help_text="Description",
|
help_text="Description",
|
||||||
max_length=255,
|
max_length=255,
|
||||||
|
|
|
@ -34,19 +34,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
<form class="form" method="post">
|
<form class="form" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<table class="table table-striped">
|
<table id="delRights_table" class="table table-striped">
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for key, values in userform.items %}
|
{% for key, values in userform.items %}
|
||||||
<tr class="active">
|
<tr class="active">
|
||||||
<td>
|
<td>
|
||||||
<a data-toggle="collapse" href="#collapseRight_{{key}}" aria-expanded="false" aria-controls="collapseRights_{{key}}">
|
<a data-toggle="collapse" href="#collapseRight_{{key}}" aria-expanded="true" aria-controls="collapseRights_{{key}}">
|
||||||
<b>{{ key }}</b> ( {{values.rights|length }} users )
|
<b>{{ key }}</b> ( {{values.rights|length }} users )
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="collapse" id="collapseRight_{{key}}">
|
<div class="collapse in" id="collapseRight_{{key}}">
|
||||||
<ul class="list-group" style="margin-bottom: 0px">
|
<ul class="list-group" style="margin-bottom: 0px">
|
||||||
{% for user in values.rights %}
|
{% for user in values.rights %}
|
||||||
<li class="list-group-item col-xs-6 col-sm-4 col-md-3" style="border: none;">{{ user }}</li>
|
<li class="list-group-item col-xs-6 col-sm-4 col-md-3" style="border: none;">{{ user }}</li>
|
||||||
|
@ -58,9 +58,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% bootstrap_button "Modifier" button_type="submit" icon="star" %}
|
{% bootstrap_button "Supprimer" button_type="submit" icon="star" %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$("#delRights_table").ready( function () {
|
||||||
|
var rights_div = [{% for k in userform.keys %}$("#collapseRight_{{k}}"), {% endfor %}];
|
||||||
|
for (var i=0 ; i<rights_div.length ; i++) {
|
||||||
|
rights_div[i].collapse('hide');
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
</script>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
|
|
@ -88,32 +88,32 @@ urlpatterns = [
|
||||||
url(r'^reset_password/$', views.reset_password, name='reset-password'),
|
url(r'^reset_password/$', views.reset_password, name='reset-password'),
|
||||||
url(r'^mass_archive/$', views.mass_archive, name='mass-archive'),
|
url(r'^mass_archive/$', views.mass_archive, name='mass-archive'),
|
||||||
url(
|
url(
|
||||||
r'^history/(?P<object>user)/(?P<id>[0-9]+)$',
|
r'^history/(?P<object_name>user)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'
|
name='history'
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
r'^history/(?P<object>ban)/(?P<id>[0-9]+)$',
|
r'^history/(?P<object_name>ban)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'
|
name='history'
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
r'^history/(?P<object>whitelist)/(?P<id>[0-9]+)$',
|
r'^history/(?P<object_name>whitelist)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'
|
name='history'
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
r'^history/(?P<object>school)/(?P<id>[0-9]+)$',
|
r'^history/(?P<object_name>school)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'
|
name='history'
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
r'^history/(?P<object>listright)/(?P<id>[0-9]+)$',
|
r'^history/(?P<object_name>listright)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'
|
name='history'
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
r'^history/(?P<object>serviceuser)/(?P<id>[0-9]+)$',
|
r'^history/(?P<object_name>serviceuser)/(?P<object_id>[0-9]+)$',
|
||||||
views.history,
|
views.history,
|
||||||
name='history'
|
name='history'
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue