mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-25 22:22:26 +00:00
Merge branch 'master' into sort_columns
This commit is contained in:
commit
4026672297
13 changed files with 316 additions and 18 deletions
|
@ -27,8 +27,8 @@ from django.contrib import admin
|
||||||
from reversion.admin import VersionAdmin
|
from reversion.admin import VersionAdmin
|
||||||
|
|
||||||
from .models import IpType, Machine, MachineType, Domain, IpList, Interface
|
from .models import IpType, Machine, MachineType, Domain, IpList, Interface
|
||||||
from .models import Extension, Mx, Ns, Vlan, Text, Nas, Service, OuverturePort
|
from .models import Extension, SOA, Mx, Ns, Vlan, Text, Nas, Service
|
||||||
from .models import OuverturePortList
|
from .models import OuverturePort, OuverturePortList
|
||||||
|
|
||||||
|
|
||||||
class MachineAdmin(VersionAdmin):
|
class MachineAdmin(VersionAdmin):
|
||||||
|
@ -51,6 +51,10 @@ class ExtensionAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SOAAdmin(VersionAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MxAdmin(VersionAdmin):
|
class MxAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -95,6 +99,7 @@ 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)
|
||||||
admin.site.register(Extension, ExtensionAdmin)
|
admin.site.register(Extension, ExtensionAdmin)
|
||||||
|
admin.site.register(SOA, SOAAdmin)
|
||||||
admin.site.register(Mx, MxAdmin)
|
admin.site.register(Mx, MxAdmin)
|
||||||
admin.site.register(Ns, NsAdmin)
|
admin.site.register(Ns, NsAdmin)
|
||||||
admin.site.register(Text, TextAdmin)
|
admin.site.register(Text, TextAdmin)
|
||||||
|
|
|
@ -45,6 +45,7 @@ from .models import (
|
||||||
IpList,
|
IpList,
|
||||||
MachineType,
|
MachineType,
|
||||||
Extension,
|
Extension,
|
||||||
|
SOA,
|
||||||
Mx,
|
Mx,
|
||||||
Text,
|
Text,
|
||||||
Ns,
|
Ns,
|
||||||
|
@ -175,12 +176,18 @@ class AliasForm(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__)
|
||||||
|
infra = kwargs.pop('infra')
|
||||||
super(AliasForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(AliasForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
|
if not infra:
|
||||||
|
self.fields['extension'].queryset = Extension.objects.filter(
|
||||||
|
need_infra=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class DomainForm(AliasForm):
|
class DomainForm(ModelForm):
|
||||||
"""Ajout et edition d'un enregistrement de nom, relié à interface"""
|
"""Ajout et edition d'un enregistrement de nom, relié à interface"""
|
||||||
class Meta(AliasForm.Meta):
|
class Meta:
|
||||||
|
model = Domain
|
||||||
fields = ['name']
|
fields = ['name']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -274,6 +281,7 @@ class ExtensionForm(ModelForm):
|
||||||
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'
|
self.fields['origin_v6'].label = 'Enregistrement AAAA origin'
|
||||||
|
self.fields['soa'].label = 'En-tête SOA à utiliser'
|
||||||
|
|
||||||
|
|
||||||
class DelExtensionForm(Form):
|
class DelExtensionForm(Form):
|
||||||
|
@ -285,6 +293,26 @@ class DelExtensionForm(Form):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SOAForm(ModelForm):
|
||||||
|
"""Ajout et edition d'un SOA"""
|
||||||
|
class Meta:
|
||||||
|
model = SOA
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
|
super(SOAForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class DelSOAForm(Form):
|
||||||
|
"""Suppression d'un ou plusieurs SOA"""
|
||||||
|
soa = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=SOA.objects.all(),
|
||||||
|
label="SOA actuels",
|
||||||
|
widget=forms.CheckboxSelectMultiple
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MxForm(ModelForm):
|
class MxForm(ModelForm):
|
||||||
"""Ajout et edition d'un MX"""
|
"""Ajout et edition d'un MX"""
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
34
machines/migrations/0063_auto_20171020_0040.py
Normal file
34
machines/migrations/0063_auto_20171020_0040.py
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2017-10-19 22:40
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import machines.models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('machines', '0062_extension_origin_v6'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SOA',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255)),
|
||||||
|
('mail', models.EmailField(help_text='Email du contact pour la zone', max_length=254)),
|
||||||
|
('refresh', models.PositiveIntegerField(default=86400, help_text='Secondes avant que les DNS secondaires doivent demander le serial du DNS primaire pour détecter une modification')),
|
||||||
|
('retry', models.PositiveIntegerField(default=7200, help_text='Secondes avant que les DNS secondaires fassent une nouvelle demande de serial en cas de timeout du DNS primaire')),
|
||||||
|
('expire', models.PositiveIntegerField(default=3600000, help_text='Secondes après lesquelles les DNS secondaires arrêtent de de répondre aux requêtes en cas de timeout du DNS primaire')),
|
||||||
|
('ttl', models.PositiveIntegerField(default=172800, help_text='Time To Live')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='extension',
|
||||||
|
name='soa',
|
||||||
|
field=models.ForeignKey(default=machines.models.SOA.new_default_soa, on_delete=django.db.models.deletion.CASCADE, to='machines.SOA'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -234,6 +234,78 @@ class Nas(models.Model):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class SOA(models.Model):
|
||||||
|
"""
|
||||||
|
Un enregistrement SOA associé à une extension
|
||||||
|
Les valeurs par défault viennent des recommandations RIPE :
|
||||||
|
https://www.ripe.net/publications/docs/ripe-203
|
||||||
|
"""
|
||||||
|
PRETTY_NAME = "Enregistrement SOA"
|
||||||
|
|
||||||
|
name = models.CharField(max_length=255)
|
||||||
|
mail = models.EmailField(
|
||||||
|
help_text='Email du contact pour la zone'
|
||||||
|
)
|
||||||
|
refresh = models.PositiveIntegerField(
|
||||||
|
default=86400, # 24 hours
|
||||||
|
help_text='Secondes avant que les DNS secondaires doivent demander le\
|
||||||
|
serial du DNS primaire pour détecter une modification'
|
||||||
|
)
|
||||||
|
retry = models.PositiveIntegerField(
|
||||||
|
default=7200, # 2 hours
|
||||||
|
help_text='Secondes avant que les DNS secondaires fassent une nouvelle\
|
||||||
|
demande de serial en cas de timeout du DNS primaire'
|
||||||
|
)
|
||||||
|
expire = models.PositiveIntegerField(
|
||||||
|
default=3600000, # 1000 hours
|
||||||
|
help_text='Secondes après lesquelles les DNS secondaires arrêtent de\
|
||||||
|
de répondre aux requêtes en cas de timeout du DNS primaire'
|
||||||
|
)
|
||||||
|
ttl = models.PositiveIntegerField(
|
||||||
|
default=172800, # 2 days
|
||||||
|
help_text='Time To Live'
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.name)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def dns_soa_param(self):
|
||||||
|
"""
|
||||||
|
Renvoie la partie de l'enregistrement SOA correspondant aux champs :
|
||||||
|
<refresh> ; refresh
|
||||||
|
<retry> ; retry
|
||||||
|
<expire> ; expire
|
||||||
|
<ttl> ; TTL
|
||||||
|
"""
|
||||||
|
return (
|
||||||
|
' {refresh}; refresh\n'
|
||||||
|
' {retry}; retry\n'
|
||||||
|
' {expire}; expire\n'
|
||||||
|
' {ttl}; TTL'
|
||||||
|
).format(
|
||||||
|
refresh=str(self.refresh).ljust(12),
|
||||||
|
retry=str(self.retry).ljust(12),
|
||||||
|
expire=str(self.expire).ljust(12),
|
||||||
|
ttl=str(self.ttl).ljust(12)
|
||||||
|
)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def dns_soa_mail(self):
|
||||||
|
""" Renvoie le mail dans l'enregistrement SOA """
|
||||||
|
mail_fields = str(self.mail).split('@')
|
||||||
|
return mail_fields[0].replace('.', '\\.') + '.' + mail_fields[1] + '.'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def new_default_soa(cls):
|
||||||
|
""" Fonction pour créer un SOA par défaut, utile pour les nouvelles
|
||||||
|
extensions .
|
||||||
|
/!\ Ne jamais supprimer ou renommer cette fonction car elle est
|
||||||
|
utilisée dans les migrations de la BDD. """
|
||||||
|
return cls.objects.get_or_create(name="SOA to edit", mail="postmaser@example.com")[0].pk
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Extension(models.Model):
|
class Extension(models.Model):
|
||||||
""" Extension dns type example.org. Précise si tout le monde peut
|
""" Extension dns type example.org. Précise si tout le monde peut
|
||||||
l'utiliser, associé à un origin (ip d'origine)"""
|
l'utiliser, associé à un origin (ip d'origine)"""
|
||||||
|
@ -252,17 +324,22 @@ class Extension(models.Model):
|
||||||
null=True,
|
null=True,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
|
soa = models.ForeignKey(
|
||||||
|
'SOA',
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
default=SOA.new_default_soa
|
||||||
|
)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
""" Une entrée DNS A et AAAA sur origin (zone self)"""
|
""" Une entrée DNS A et AAAA sur origin (zone self)"""
|
||||||
entry = ""
|
entry = ""
|
||||||
if self.origin:
|
if self.origin:
|
||||||
entry += "@ IN A " + str(self.origin)
|
entry += "@ IN A " + str(self.origin)
|
||||||
if self.origin_v6:
|
if self.origin_v6:
|
||||||
if entry:
|
if entry:
|
||||||
entry += "\n"
|
entry += "\n"
|
||||||
entry += "@ IN AAAA " + str(self.origin_v6)
|
entry += "@ IN AAAA " + str(self.origin_v6)
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -283,7 +360,7 @@ class Mx(models.Model):
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
"""Renvoie l'entrée DNS complète pour un MX à mettre dans les
|
"""Renvoie l'entrée DNS complète pour un MX à mettre dans les
|
||||||
fichiers de zones"""
|
fichiers de zones"""
|
||||||
return "@ IN MX " + str(self.priority) + " " + str(self.name)
|
return "@ IN MX " + str(self.priority).ljust(3) + " " + 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)
|
||||||
|
@ -299,7 +376,7 @@ class Ns(models.Model):
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
"""Renvoie un enregistrement NS complet pour les filezones"""
|
"""Renvoie un enregistrement NS complet pour les filezones"""
|
||||||
return "@ IN NS " + str(self.ns)
|
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)
|
||||||
|
@ -307,7 +384,7 @@ class Ns(models.Model):
|
||||||
|
|
||||||
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 TXT"
|
||||||
|
|
||||||
zone = models.ForeignKey('Extension', on_delete=models.PROTECT)
|
zone = models.ForeignKey('Extension', on_delete=models.PROTECT)
|
||||||
field1 = models.CharField(max_length=255)
|
field1 = models.CharField(max_length=255)
|
||||||
|
@ -320,7 +397,7 @@ class Text(models.Model):
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
"""Renvoie l'enregistrement TXT complet pour le fichier de zone"""
|
"""Renvoie l'enregistrement TXT complet pour le fichier de zone"""
|
||||||
return str(self.field1) + " IN TXT " + str(self.field2)
|
return str(self.field1).ljust(15) + " IN TXT " + str(self.field2)
|
||||||
|
|
||||||
|
|
||||||
class Interface(models.Model):
|
class Interface(models.Model):
|
||||||
|
@ -506,7 +583,7 @@ 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).ljust(15) + " IN CNAME " + str(self.cname) + "."
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
""" Empèche le save sans extension valide.
|
""" Empèche le save sans extension valide.
|
||||||
|
@ -790,6 +867,18 @@ def extension_post_selete(sender, **kwargs):
|
||||||
regen('dns')
|
regen('dns')
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_save, sender=SOA)
|
||||||
|
def soa_post_save(sender, **kwargs):
|
||||||
|
"""Regeneration dns après modification d'un SOA"""
|
||||||
|
regen('dns')
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_delete, sender=SOA)
|
||||||
|
def soa_post_delete(sender, **kwargs):
|
||||||
|
"""Regeneration dns après suppresson d'un SOA"""
|
||||||
|
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"""
|
"""Regeneration dns après modification d'un MX"""
|
||||||
|
|
|
@ -158,10 +158,11 @@ class ExtensionSerializer(serializers.ModelSerializer):
|
||||||
des foreign_key donc evalués en get_..."""
|
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')
|
||||||
|
soa = serializers.SerializerMethodField('get_soa_data')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Extension
|
model = Extension
|
||||||
fields = ('name', 'origin', 'origin_v6', 'zone_entry')
|
fields = ('name', 'origin', 'origin_v6', 'zone_entry', 'soa')
|
||||||
|
|
||||||
def get_origin_ip(self, obj):
|
def get_origin_ip(self, obj):
|
||||||
return obj.origin.ipv4
|
return obj.origin.ipv4
|
||||||
|
@ -169,6 +170,9 @@ 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)
|
||||||
|
|
||||||
|
def get_soa_data(self, obj):
|
||||||
|
return { 'mail': obj.soa.dns_soa_mail, 'param': obj.soa.dns_soa_param }
|
||||||
|
|
||||||
|
|
||||||
class MxSerializer(serializers.ModelSerializer):
|
class MxSerializer(serializers.ModelSerializer):
|
||||||
"""Serialisation d'un MX, evaluation du nom, de la zone
|
"""Serialisation d'un MX, evaluation du nom, de la zone
|
||||||
|
|
|
@ -26,19 +26,25 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Extension</th>
|
<th>Extension</th>
|
||||||
<th>Autorisation infra pour utiliser l'extension</th>
|
<th>Droit infra pour utiliser ?</th>
|
||||||
|
<th>Enregistrement SOA</th>
|
||||||
<th>Enregistrement A origin</th>
|
<th>Enregistrement A origin</th>
|
||||||
|
{% if ipv6_enabled %}
|
||||||
<th>Enregistrement AAAA origin</th>
|
<th>Enregistrement AAAA origin</th>
|
||||||
|
{% endif %}
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
{% for extension in extension_list %}
|
{% for extension in extension_list %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ extension.name }}</td>
|
<td>{{ extension.name }}</td>
|
||||||
<td>{{ extension.need_infra }}</td>
|
<td>{{ extension.need_infra }}</td>
|
||||||
|
<td>{{ extension.soa}}</td>
|
||||||
<td>{{ extension.origin }}</td>
|
<td>{{ extension.origin }}</td>
|
||||||
<td>{{ extension.origin_v6 }}</td>
|
{% if ipv6_enabled %}
|
||||||
<td class="text-right">
|
<td>{{ extension.origin_v6 }}</td>
|
||||||
|
{% endif %}
|
||||||
|
<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 %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
56
machines/templates/machines/aff_soa.html
Normal file
56
machines/templates/machines/aff_soa.html
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
{% comment %}
|
||||||
|
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||||
|
se veut agnostique au réseau considéré, de manière à être installable en
|
||||||
|
quelques clics.
|
||||||
|
|
||||||
|
Copyright © 2017 Gabriel Détraz
|
||||||
|
Copyright © 2017 Goulven Kermarec
|
||||||
|
Copyright © 2017 Augustin Lemesle
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nom</th>
|
||||||
|
<th>Mail</th>
|
||||||
|
<th>Refresh</th>
|
||||||
|
<th>Retry</th>
|
||||||
|
<th>Expire</th>
|
||||||
|
<th>TTL</th>
|
||||||
|
<th></th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{% for soa in soa_list %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ soa.name }}</td>
|
||||||
|
<td>{{ soa.mail }}</td>
|
||||||
|
<td>{{ soa.refresh }}</td>
|
||||||
|
<td>{{ soa.retry }}</td>
|
||||||
|
<td>{{ soa.expire }}</td>
|
||||||
|
<td>{{ soa.ttl }}</td>
|
||||||
|
<td class="text-right">
|
||||||
|
{% if is_infra %}
|
||||||
|
{% include 'buttons/edit.html' with href='machines:edit-soa' id=soa.id %}
|
||||||
|
{% endif %}
|
||||||
|
{% include 'buttons/history.html' with href='machines:history' name='soa' id=soa.id %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% include "machines/aff_extension.html" with extension_list=extension_list %}
|
{% include "machines/aff_extension.html" with extension_list=extension_list %}
|
||||||
|
|
||||||
|
<h2>Liste des enregistrements SOA</h2>
|
||||||
|
{% if is_infra %}
|
||||||
|
<a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:add-soa' %}"><i class="glyphicon glyphicon-plus"></i> Ajouter un enregistrement SOA</a>
|
||||||
|
<a class="btn btn-danger btn-sm" role="button" href="{% url 'machines:del-soa' %}"><i class="glyphicon glyphicon-trash"></i> Supprimer un enregistrement SOA</a>
|
||||||
|
{% endif %}
|
||||||
|
{% include "machines/aff_soa.html" with soa_list=soa_list %}
|
||||||
<h2>Liste des enregistrements MX</h2>
|
<h2>Liste des enregistrements MX</h2>
|
||||||
{% if is_infra %}
|
{% if is_infra %}
|
||||||
<a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:add-mx' %}"><i class="glyphicon glyphicon-plus"></i> Ajouter un enregistrement MX</a>
|
<a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:add-mx' %}"><i class="glyphicon glyphicon-plus"></i> Ajouter un enregistrement MX</a>
|
||||||
|
|
|
@ -31,8 +31,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
<h2>Liste des nas</h2>
|
<h2>Liste des nas</h2>
|
||||||
<h5>La correpondance nas-machinetype relie le type de nas à un type de machine.
|
<h5>La correpondance nas-machinetype relie le type de nas à un type de machine.
|
||||||
Elle est utile pour l'autoenregistrement des macs par radius, et permet de choisir le type de machine à affecter aux machines en fonction du type de nas</h5>
|
Elle est utile pour l'autoenregistrement des macs par radius, et permet de choisir le type de machine à affecter aux machines en fonction du type de nas</h5>
|
||||||
|
{% if is_infra %}
|
||||||
<a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:add-nas' %}"><i class="glyphicon glyphicon-plus"></i> Ajouter un type de nas</a>
|
<a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:add-nas' %}"><i class="glyphicon glyphicon-plus"></i> Ajouter un type de nas</a>
|
||||||
<a class="btn btn-danger btn-sm" role="button" href="{% url 'machines:del-nas' %}"><i class="glyphicon glyphicon-trash"></i> Supprimer un ou plusieurs types nas</a>
|
<a class="btn btn-danger btn-sm" role="button" href="{% url 'machines:del-nas' %}"><i class="glyphicon glyphicon-trash"></i> Supprimer un ou plusieurs types nas</a>
|
||||||
|
{% endif %}
|
||||||
{% include "machines/aff_nas.html" with nas_list=nas_list %}
|
{% include "machines/aff_nas.html" with nas_list=nas_list %}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
|
|
@ -29,8 +29,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Liste des vlans</h2>
|
<h2>Liste des vlans</h2>
|
||||||
|
{% if is_infra %}
|
||||||
<a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:add-vlan' %}"><i class="glyphicon glyphicon-plus"></i> Ajouter un vlan</a>
|
<a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:add-vlan' %}"><i class="glyphicon glyphicon-plus"></i> Ajouter un vlan</a>
|
||||||
<a class="btn btn-danger btn-sm" role="button" href="{% url 'machines:del-vlan' %}"><i class="glyphicon glyphicon-trash"></i> Supprimer un ou plusieurs vlan</a>
|
<a class="btn btn-danger btn-sm" role="button" href="{% url 'machines:del-vlan' %}"><i class="glyphicon glyphicon-trash"></i> Supprimer un ou plusieurs vlan</a>
|
||||||
|
{% endif %}
|
||||||
{% include "machines/aff_vlan.html" with vlan_list=vlan_list %}
|
{% include "machines/aff_vlan.html" with vlan_list=vlan_list %}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
|
|
@ -100,6 +100,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
<h3>Extension</h3>
|
<h3>Extension</h3>
|
||||||
{% massive_bootstrap_form extensionform 'origin' %}
|
{% massive_bootstrap_form extensionform 'origin' %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if soaform %}
|
||||||
|
<h3>Enregistrement SOA</h3>
|
||||||
|
{% bootstrap_form soaform %}
|
||||||
|
{% endif %}
|
||||||
{% if mxform %}
|
{% if mxform %}
|
||||||
<h3>Enregistrement MX</h3>
|
<h3>Enregistrement MX</h3>
|
||||||
{% massive_bootstrap_form mxform 'name' %}
|
{% massive_bootstrap_form mxform 'name' %}
|
||||||
|
|
|
@ -44,6 +44,9 @@ urlpatterns = [
|
||||||
url(r'^add_extension/$', views.add_extension, name='add-extension'),
|
url(r'^add_extension/$', views.add_extension, name='add-extension'),
|
||||||
url(r'^edit_extension/(?P<extensionid>[0-9]+)$', views.edit_extension, name='edit-extension'),
|
url(r'^edit_extension/(?P<extensionid>[0-9]+)$', views.edit_extension, name='edit-extension'),
|
||||||
url(r'^del_extension/$', views.del_extension, name='del-extension'),
|
url(r'^del_extension/$', views.del_extension, name='del-extension'),
|
||||||
|
url(r'^add_soa/$', views.add_soa, name='add-soa'),
|
||||||
|
url(r'^edit_soa/(?P<soaid>[0-9]+)$', views.edit_soa, name='edit-soa'),
|
||||||
|
url(r'^del_soa/$', views.del_soa, name='del-soa'),
|
||||||
url(r'^add_mx/$', views.add_mx, name='add-mx'),
|
url(r'^add_mx/$', views.add_mx, name='add-mx'),
|
||||||
url(r'^edit_mx/(?P<mxid>[0-9]+)$', views.edit_mx, name='edit-mx'),
|
url(r'^edit_mx/(?P<mxid>[0-9]+)$', views.edit_mx, name='edit-mx'),
|
||||||
url(r'^del_mx/$', views.del_mx, name='del-mx'),
|
url(r'^del_mx/$', views.del_mx, name='del-mx'),
|
||||||
|
@ -74,6 +77,7 @@ urlpatterns = [
|
||||||
url(r'^history/(?P<object>interface)/(?P<id>[0-9]+)$', views.history, name='history'),
|
url(r'^history/(?P<object>interface)/(?P<id>[0-9]+)$', views.history, name='history'),
|
||||||
url(r'^history/(?P<object>machinetype)/(?P<id>[0-9]+)$', views.history, name='history'),
|
url(r'^history/(?P<object>machinetype)/(?P<id>[0-9]+)$', views.history, name='history'),
|
||||||
url(r'^history/(?P<object>extension)/(?P<id>[0-9]+)$', views.history, name='history'),
|
url(r'^history/(?P<object>extension)/(?P<id>[0-9]+)$', views.history, name='history'),
|
||||||
|
url(r'^history/(?P<object>soa)/(?P<id>[0-9]+)$', views.history, name='history'),
|
||||||
url(r'^history/(?P<object>mx)/(?P<id>[0-9]+)$', views.history, name='history'),
|
url(r'^history/(?P<object>mx)/(?P<id>[0-9]+)$', views.history, name='history'),
|
||||||
url(r'^history/(?P<object>ns)/(?P<id>[0-9]+)$', views.history, name='history'),
|
url(r'^history/(?P<object>ns)/(?P<id>[0-9]+)$', views.history, name='history'),
|
||||||
url(r'^history/(?P<object>txt)/(?P<id>[0-9]+)$', views.history, name='history'),
|
url(r'^history/(?P<object>txt)/(?P<id>[0-9]+)$', views.history, name='history'),
|
||||||
|
|
|
@ -77,6 +77,8 @@ from .forms import (
|
||||||
DomainForm,
|
DomainForm,
|
||||||
AliasForm,
|
AliasForm,
|
||||||
DelAliasForm,
|
DelAliasForm,
|
||||||
|
SOAForm,
|
||||||
|
DelSOAForm,
|
||||||
NsForm,
|
NsForm,
|
||||||
DelNsForm,
|
DelNsForm,
|
||||||
TxtForm,
|
TxtForm,
|
||||||
|
@ -98,6 +100,7 @@ from .models import (
|
||||||
IpList,
|
IpList,
|
||||||
MachineType,
|
MachineType,
|
||||||
Extension,
|
Extension,
|
||||||
|
SOA,
|
||||||
Mx,
|
Mx,
|
||||||
Ns,
|
Ns,
|
||||||
Domain,
|
Domain,
|
||||||
|
@ -520,6 +523,54 @@ def del_extension(request):
|
||||||
return redirect("/machines/index_extension")
|
return redirect("/machines/index_extension")
|
||||||
return form({'extensionform': extension}, 'machines/machine.html', request)
|
return form({'extensionform': extension}, 'machines/machine.html', request)
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@permission_required('infra')
|
||||||
|
def add_soa(request):
|
||||||
|
soa = SOAForm(request.POST or None)
|
||||||
|
if soa.is_valid():
|
||||||
|
with transaction.atomic(), reversion.create_revision():
|
||||||
|
soa.save()
|
||||||
|
reversion.set_user(request.user)
|
||||||
|
reversion.set_comment("Création")
|
||||||
|
messages.success(request, "Cet enregistrement SOA a été ajouté")
|
||||||
|
return redirect("/machines/index_extension")
|
||||||
|
return form({'soaform': soa}, 'machines/machine.html', request)
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@permission_required('infra')
|
||||||
|
def edit_soa(request, soaid):
|
||||||
|
try:
|
||||||
|
soa_instance = SOA.objects.get(pk=soaid)
|
||||||
|
except SOA.DoesNotExist:
|
||||||
|
messages.error(request, u"Entrée inexistante" )
|
||||||
|
return redirect("/machines/index_extension/")
|
||||||
|
soa = SOAForm(request.POST or None, instance=soa_instance)
|
||||||
|
if soa.is_valid():
|
||||||
|
with transaction.atomic(), reversion.create_revision():
|
||||||
|
soa.save()
|
||||||
|
reversion.set_user(request.user)
|
||||||
|
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in soa.changed_data))
|
||||||
|
messages.success(request, "SOA modifié")
|
||||||
|
return redirect("/machines/index_extension/")
|
||||||
|
return form({'soaform': soa}, 'machines/machine.html', request)
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@permission_required('infra')
|
||||||
|
def del_soa(request):
|
||||||
|
soa = DelSOAForm(request.POST or None)
|
||||||
|
if soa.is_valid():
|
||||||
|
soa_dels = soa.cleaned_data['soa']
|
||||||
|
for soa_del in soa_dels:
|
||||||
|
try:
|
||||||
|
with transaction.atomic(), reversion.create_revision():
|
||||||
|
soa_del.delete()
|
||||||
|
reversion.set_user(request.user)
|
||||||
|
messages.success(request, "Le SOA a été supprimée")
|
||||||
|
except ProtectedError:
|
||||||
|
messages.error(request, "Erreur le SOA suivant %s ne peut être supprimé" % soa_del)
|
||||||
|
return redirect("/machines/index_extension")
|
||||||
|
return form({'soaform': soa}, 'machines/machine.html', request)
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@permission_required('infra')
|
@permission_required('infra')
|
||||||
def add_mx(request):
|
def add_mx(request):
|
||||||
|
@ -932,11 +983,12 @@ def index_nas(request):
|
||||||
@login_required
|
@login_required
|
||||||
@permission_required('cableur')
|
@permission_required('cableur')
|
||||||
def index_extension(request):
|
def index_extension(request):
|
||||||
extension_list = Extension.objects.select_related('origin').order_by('name')
|
extension_list = Extension.objects.select_related('origin').select_related('soa').order_by('name')
|
||||||
|
soa_list = SOA.objects.order_by('name')
|
||||||
mx_list = Mx.objects.order_by('zone').select_related('zone').select_related('name__extension')
|
mx_list = Mx.objects.order_by('zone').select_related('zone').select_related('name__extension')
|
||||||
ns_list = Ns.objects.order_by('zone').select_related('zone').select_related('ns__extension')
|
ns_list = Ns.objects.order_by('zone').select_related('zone').select_related('ns__extension')
|
||||||
text_list = Text.objects.all().select_related('zone')
|
text_list = Text.objects.all().select_related('zone')
|
||||||
return render(request, 'machines/index_extension.html', {'extension_list':extension_list, 'mx_list': mx_list, 'ns_list': ns_list, 'text_list' : text_list})
|
return render(request, 'machines/index_extension.html', {'extension_list':extension_list, 'soa_list': soa_list, 'mx_list': mx_list, 'ns_list': ns_list, 'text_list' : text_list})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def index_alias(request, interfaceid):
|
def index_alias(request, interfaceid):
|
||||||
|
@ -1005,6 +1057,12 @@ def history(request, object, id):
|
||||||
except Extension.DoesNotExist:
|
except Extension.DoesNotExist:
|
||||||
messages.error(request, "Extension inexistante")
|
messages.error(request, "Extension inexistante")
|
||||||
return redirect("/machines/")
|
return redirect("/machines/")
|
||||||
|
elif object == 'soa' and request.user.has_perms(('cableur',)):
|
||||||
|
try:
|
||||||
|
object_instance = SOA.objects.get(pk=id)
|
||||||
|
except SOA.DoesNotExist:
|
||||||
|
messages.error(request, "SOA inexistant")
|
||||||
|
return redirect("/machines/")
|
||||||
elif object == 'mx' and request.user.has_perms(('cableur',)):
|
elif object == 'mx' and request.user.has_perms(('cableur',)):
|
||||||
try:
|
try:
|
||||||
object_instance = Mx.objects.get(pk=id)
|
object_instance = Mx.objects.get(pk=id)
|
||||||
|
|
Loading…
Reference in a new issue