From 5d553027155d3243913cfcb96455c6e02de27abd Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Thu, 28 Sep 2017 17:19:33 +0200 Subject: [PATCH 01/37] =?UTF-8?q?Cr=C3=A9e=20un=20mod=C3=A8le=20pour=20une?= =?UTF-8?q?=20liste=20de=20ports=20et=20un=20autre=20pour=20repr=C3=A9sent?= =?UTF-8?q?er=20un=20port=20ou=20une=20plage=20de=20ports.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0058_auto_20170928_1711.py | 37 +++++++++++++++++++ machines/migrations/0059_port_protocole.py | 20 ++++++++++ machines/models.py | 37 +++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 machines/migrations/0058_auto_20170928_1711.py create mode 100644 machines/migrations/0059_port_protocole.py diff --git a/machines/migrations/0058_auto_20170928_1711.py b/machines/migrations/0058_auto_20170928_1711.py new file mode 100644 index 00000000..41224de1 --- /dev/null +++ b/machines/migrations/0058_auto_20170928_1711.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-09-28 15:11 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('machines', '0057_nas_autocapture_mac'), + ] + + operations = [ + migrations.CreateModel( + name='Port', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('begin', models.IntegerField()), + ('end', models.IntegerField()), + ], + ), + migrations.CreateModel( + name='PortList', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(help_text='Nom de la configuration des ports.', max_length=255)), + ('interfaces', models.ManyToManyField(to='machines.Interface')), + ], + ), + migrations.AddField( + model_name='port', + name='port_list', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='machines.PortList'), + ), + ] diff --git a/machines/migrations/0059_port_protocole.py b/machines/migrations/0059_port_protocole.py new file mode 100644 index 00000000..fc43bdb0 --- /dev/null +++ b/machines/migrations/0059_port_protocole.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-09-28 16:03 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('machines', '0058_auto_20170928_1711'), + ] + + operations = [ + migrations.AddField( + model_name='port', + name='protocole', + field=models.CharField(choices=[('T', 'TCP'), ('U', 'UDP')], default='T', max_length=1), + ), + ] diff --git a/machines/models.py b/machines/models.py index 8eff89fc..4dc0e3ad 100644 --- a/machines/models.py +++ b/machines/models.py @@ -406,6 +406,43 @@ class Service_link(models.Model): def __str__(self): return str(self.server) + " " + str(self.service) + +class PortList(models.Model): + """Liste des ports ouverts sur une interface.""" + interfaces = models.ManyToManyField('Interface') + name = models.CharField(help_text="Nom de la configuration des ports.", max_length=255) + + def __str__(self): + return ', '.join(map(str, self.port_set.all())) + +class Port(models.Model): + """ + Représente un simple port ou une plage de ports. + + Les ports de la plage sont compris entre begin et en inclus. + Si begin == end alors on ne représente qu'un seul port. + """ + TCP = 'T' + UDP = 'U' + begin = models.IntegerField() + end = models.IntegerField() + port_list = models.ForeignKey('PortList', on_delete=models.CASCADE) + protocole = models.CharField( + max_length=1, + choices=( + (TCP, 'TCP'), + (UDP, 'UDP'), + ), + default=TCP, + ) + + def __str__(self): + beg = self.protocole + ' : ' + if self.begin == self.end : + return beg + str(self.begin) + return beg + '-'.join([str(self.begin), str(self.end)]) + + @receiver(post_save, sender=Machine) def machine_post_save(sender, **kwargs): user = kwargs['instance'].user From d8dbf46d6ac9af1850cf5cf221d7cab701f23fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Kervella?= Date: Fri, 29 Sep 2017 08:40:41 +0000 Subject: [PATCH 02/37] Fonction pour proposer un nom non-existant pour une nouvelle interface --- machines/forms.py | 6 +++--- machines/views.py | 2 +- users/models.py | 21 +++++++++++++++++++-- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/machines/forms.py b/machines/forms.py index cd4ac87d..f1a9566d 100644 --- a/machines/forms.py +++ b/machines/forms.py @@ -107,11 +107,11 @@ class DomainForm(AliasForm): fields = ['name'] def __init__(self, *args, **kwargs): - if 'name_user' in kwargs: - name_user = kwargs.pop('name_user') + if 'user' in kwargs: + user = kwargs.pop('user') nb_machine = kwargs.pop('nb_machine') initial = kwargs.get('initial', {}) - initial['name'] = name_user.lower()+str(nb_machine) + initial['name'] = user.get_next_domain_name() kwargs['initial'] = initial super(DomainForm, self).__init__(*args, **kwargs) diff --git a/machines/views.py b/machines/views.py index 4268519b..9fc64236 100644 --- a/machines/views.py +++ b/machines/views.py @@ -93,7 +93,7 @@ def new_machine(request, userid): machine = NewMachineForm(request.POST or None) 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, name_user=user.pseudo.replace('_','-'), nb_machine=nb_machine) + domain = DomainForm(request.POST or None, user=user, nb_machine=nb_machine) if machine.is_valid() and interface.is_valid(): new_machine = machine.save(commit=False) new_machine.user = user diff --git a/users/models.py b/users/models.py index a69493ae..61c39aad 100644 --- a/users/models.py +++ b/users/models.py @@ -50,7 +50,7 @@ from django.contrib.auth.models import AbstractBaseUser, BaseUserManager from django.core.validators import MinLengthValidator from topologie.models import Room from cotisations.models import Cotisation, Facture, Paiement, Vente -from machines.models import Domain, Interface, MachineType, Machine, Nas, MachineType, regen +from machines.models import Domain, Interface, MachineType, Machine, Nas, MachineType, Extension, regen from preferences.models import GeneralOption, AssoOption, OptionalUser, OptionalMachine, MailMessageOption now = timezone.now() @@ -473,7 +473,7 @@ class User(AbstractBaseUser): interface_cible.clean() machine_parent.clean() domain = Domain() - domain.name = self.pseudo.replace('_','-').lower() + str(all_machines.count()) + domain.name = self.get_next_domain_name() domain.interface_parent = interface_cible domain.clean() machine_parent.save() @@ -494,6 +494,23 @@ class User(AbstractBaseUser): self.pwd_ntlm = hashNT(password) return + def get_next_domain_name(self): + """Look for an available name for a new interface for + this user by trying "pseudo0", "pseudo1", "pseudo2", ... + """ + + def simple_pseudo(): + return self.pseudo.replace('_', '-').lower() + + def composed_pseudo( n ): + return simple_pseudo() + str(n) + + num = 0 + while Domain.objects.filter(name=composed_pseudo(num)) : + num += 1 + return composed_pseudo(num) + + def __str__(self): return self.pseudo From 80ac47b4e241776077692bcef0c6951357299a03 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Fri, 29 Sep 2017 22:28:48 +0200 Subject: [PATCH 03/37] Affichage basique des configurations de ports disponibles. --- machines/models.py | 11 ++++-- .../templates/machines/index_portlist.html | 37 +++++++++++++++++++ machines/templates/machines/sidebar.html | 6 +++ machines/urls.py | 1 + machines/views.py | 8 +++- 5 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 machines/templates/machines/index_portlist.html diff --git a/machines/models.py b/machines/models.py index 4dc0e3ad..ff5dd1e9 100644 --- a/machines/models.py +++ b/machines/models.py @@ -415,6 +415,12 @@ class PortList(models.Model): def __str__(self): return ', '.join(map(str, self.port_set.all())) + def tcp_ports(self): + return self.port_set.filter(protocole=Port.TCP) + + def udp_ports(self): + return self.port_set.filter(protocole=Port.UDP) + class Port(models.Model): """ Représente un simple port ou une plage de ports. @@ -437,10 +443,9 @@ class Port(models.Model): ) def __str__(self): - beg = self.protocole + ' : ' if self.begin == self.end : - return beg + str(self.begin) - return beg + '-'.join([str(self.begin), str(self.end)]) + return str(self.begin) + return '-'.join([str(self.begin), str(self.end)]) @receiver(post_save, sender=Machine) diff --git a/machines/templates/machines/index_portlist.html b/machines/templates/machines/index_portlist.html new file mode 100644 index 00000000..1ba3a61f --- /dev/null +++ b/machines/templates/machines/index_portlist.html @@ -0,0 +1,37 @@ +{% extends "machines/sidebar.html" %} + +{% load bootstrap3 %} + +{% block title %}Configuration de ports{% endblock %} + +{% block content %} +

Liste des configurations de ports

+ Ajouter une configuration + + + + + + + + + + {% for pl in port_list %} + + + + + + + {%endfor%} +
NomTCPUDP
{{pl.name}}{{pl.tcp_ports}}{{pl.udp_ports}} + {%comment%} + {% include 'buttons/suppr.html' href='machines:del-portlist' id=pl.id %} + {% include 'buttons/edit.html' href='machines:edit-portlist' id=pl.id %} + {%endcomment%} +
+
+
+
+ +{% endblock %} diff --git a/machines/templates/machines/sidebar.html b/machines/templates/machines/sidebar.html index 7334f628..a0d6948a 100644 --- a/machines/templates/machines/sidebar.html +++ b/machines/templates/machines/sidebar.html @@ -55,4 +55,10 @@ with this program; if not, write to the Free Software Foundation, Inc., Services (dhcp, dns...) {% endif %} + {% if is_bureau %} + + + Configuration de ports + + {%endif%} {% endblock %} diff --git a/machines/urls.py b/machines/urls.py index cdf3d5fb..4962609e 100644 --- a/machines/urls.py +++ b/machines/urls.py @@ -92,4 +92,5 @@ urlpatterns = [ url(r'^rest/text/$', views.text, name='text'), url(r'^rest/zones/$', views.zones, name='zones'), url(r'^rest/service_servers/$', views.service_servers, name='service-servers'), + url(r'index_portlist/$', views.index_portlist, name='index-portlist'), ] diff --git a/machines/views.py b/machines/views.py index 4268519b..4cb1149f 100644 --- a/machines/views.py +++ b/machines/views.py @@ -48,7 +48,7 @@ from reversion.models import Version import re from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm, BaseEditInterfaceForm, BaseEditMachineForm from .forms import EditIpTypeForm, IpTypeForm, DelIpTypeForm, DomainForm, AliasForm, DelAliasForm, NsForm, DelNsForm, TextForm, DelTextForm, MxForm, DelMxForm, VlanForm, DelVlanForm, ServiceForm, DelServiceForm, NasForm, DelNasForm -from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain, Service, Service_link, Vlan, Nas, Text +from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain, Service, Service_link, Vlan, Nas, Text, PortList from users.models import User from users.models import all_has_access from preferences.models import GeneralOption, OptionalMachine @@ -912,6 +912,12 @@ def history(request, object, id): return render(request, 're2o/history.html', {'reversions': reversions, 'object': object_instance}) +@login_required +@permission_required('bureau') +def index_portlist(request): + port_list = PortList.objects.all().order_by('name') + return render(request, "machines/index_portlist.html", {'port_list':port_list}) + """ Framework Rest """ class JSONResponse(HttpResponse): From 4716d7f34322834df30997f2041abcdfa3be19e4 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Sat, 30 Sep 2017 10:04:18 +0200 Subject: [PATCH 04/37] =?UTF-8?q?Affichage=20de=20la=20page=20d'=C3=A9diti?= =?UTF-8?q?on=20d'une=20liste=20de=20ports.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/forms.py | 9 ++++++++- machines/models.py | 5 +++++ machines/templates/machines/index_portlist.html | 6 +++--- machines/urls.py | 1 + machines/views.py | 12 +++++++++++- 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/machines/forms.py b/machines/forms.py index cd4ac87d..afe781f1 100644 --- a/machines/forms.py +++ b/machines/forms.py @@ -24,7 +24,7 @@ from __future__ import unicode_literals from django.forms import ModelForm, Form, ValidationError from django import forms -from .models import Domain, Machine, Interface, IpList, MachineType, Extension, Mx, Text, Ns, Service, Vlan, Nas, IpType +from .models import Domain, Machine, Interface, IpList, MachineType, Extension, Mx, Text, Ns, Service, Vlan, Nas, IpType, PortList from django.db.models import Q from django.core.validators import validate_email @@ -229,5 +229,12 @@ class VlanForm(ModelForm): class DelVlanForm(Form): vlan = forms.ModelMultipleChoiceField(queryset=Vlan.objects.all(), label="Vlan actuels", widget=forms.CheckboxSelectMultiple) +class EditPortListForm(ModelForm): + tcp_ports = forms.CharField(required=False, label="Ports TCP") + udp_ports = forms.CharField(required=False, label="Ports UDP") + # interfaces = forms.ModelMultipleChoiceField(queryset=Interface.objects.filter(Q(has_public_ip=True)), label="Interface", widget=forms.CheckboxSelectMultiple) + class Meta: + model = PortList + fields = ['name'] diff --git a/machines/models.py b/machines/models.py index ff5dd1e9..91e16ab9 100644 --- a/machines/models.py +++ b/machines/models.py @@ -223,6 +223,7 @@ class Interface(models.Model): machine = models.ForeignKey('Machine', on_delete=models.CASCADE) type = models.ForeignKey('MachineType', on_delete=models.PROTECT) details = models.CharField(max_length=255, blank=True) + has_public_ip = False @cached_property def is_active(self): @@ -278,6 +279,7 @@ class Interface(models.Model): domain = None return str(domain) + class Domain(models.Model): PRETTY_NAME = "Domaine dns" @@ -447,6 +449,9 @@ class Port(models.Model): return str(self.begin) return '-'.join([str(self.begin), str(self.end)]) + def show_port(self): + return str(self) + @receiver(post_save, sender=Machine) def machine_post_save(sender, **kwargs): diff --git a/machines/templates/machines/index_portlist.html b/machines/templates/machines/index_portlist.html index 1ba3a61f..ce48e249 100644 --- a/machines/templates/machines/index_portlist.html +++ b/machines/templates/machines/index_portlist.html @@ -19,13 +19,13 @@ {% for pl in port_list %} {{pl.name}} - {{pl.tcp_ports}} - {{pl.udp_ports}} + {% for p in pl.tcp_ports%}{{p.show_port}}, {%endfor%} + {% for p in pl.udp_ports%}{{p.show_port}}, {%endfor%} {%comment%} {% include 'buttons/suppr.html' href='machines:del-portlist' id=pl.id %} - {% include 'buttons/edit.html' href='machines:edit-portlist' id=pl.id %} {%endcomment%} + {% include 'buttons/edit.html' with href='machines:edit-portlist' id=pl.id %} {%endfor%} diff --git a/machines/urls.py b/machines/urls.py index 4962609e..29f7668f 100644 --- a/machines/urls.py +++ b/machines/urls.py @@ -93,4 +93,5 @@ urlpatterns = [ url(r'^rest/zones/$', views.zones, name='zones'), url(r'^rest/service_servers/$', views.service_servers, name='service-servers'), url(r'index_portlist/$', views.index_portlist, name='index-portlist'), + url(r'^edit_portlist/(?P[0-9]+)$', views.edit_portlist, name='edit-portlist'), ] diff --git a/machines/views.py b/machines/views.py index 4cb1149f..32b04c2e 100644 --- a/machines/views.py +++ b/machines/views.py @@ -48,6 +48,7 @@ from reversion.models import Version import re from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm, BaseEditInterfaceForm, BaseEditMachineForm from .forms import EditIpTypeForm, IpTypeForm, DelIpTypeForm, DomainForm, AliasForm, DelAliasForm, NsForm, DelNsForm, TextForm, DelTextForm, MxForm, DelMxForm, VlanForm, DelVlanForm, ServiceForm, DelServiceForm, NasForm, DelNasForm +from .forms import EditPortListForm from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain, Service, Service_link, Vlan, Nas, Text, PortList from users.models import User from users.models import all_has_access @@ -913,11 +914,20 @@ def history(request, object, id): @login_required -@permission_required('bureau') +@permission_required('cableur') def index_portlist(request): port_list = PortList.objects.all().order_by('name') return render(request, "machines/index_portlist.html", {'port_list':port_list}) +@login_required +@permission_required('bureau') +def edit_portlist(request, pk): + port_list_instance = get_object_or_404(PortList, pk=pk) + port_list = EditPortListForm(request.POST or None, instance=port_list_instance) + if port_list.is_valid(): + return redirect("/machines/index_portlist/") + return form({'machineform' : port_list}, 'machines/machine.html', request) + """ Framework Rest """ class JSONResponse(HttpResponse): From cf9db8f1d1fbf751f63020628b67e087bef14066 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Sun, 1 Oct 2017 11:39:39 +0200 Subject: [PATCH 05/37] =?UTF-8?q?Gestion=20de=20l'ouverture=20en=20entr?= =?UTF-8?q?=C3=A9e=20et=20en=20sortie.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/forms.py | 7 +++--- machines/migrations/0060_port_io.py | 20 +++++++++++++++ machines/models.py | 25 ++++++++++++++++--- .../templates/machines/index_portlist.html | 12 ++++++--- 4 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 machines/migrations/0060_port_io.py diff --git a/machines/forms.py b/machines/forms.py index afe781f1..a611fa98 100644 --- a/machines/forms.py +++ b/machines/forms.py @@ -230,9 +230,10 @@ class DelVlanForm(Form): vlan = forms.ModelMultipleChoiceField(queryset=Vlan.objects.all(), label="Vlan actuels", widget=forms.CheckboxSelectMultiple) class EditPortListForm(ModelForm): - tcp_ports = forms.CharField(required=False, label="Ports TCP") - udp_ports = forms.CharField(required=False, label="Ports UDP") - # interfaces = forms.ModelMultipleChoiceField(queryset=Interface.objects.filter(Q(has_public_ip=True)), label="Interface", widget=forms.CheckboxSelectMultiple) + tcp_ports_in = forms.CharField(required=False, label="Ports TCP (entrée)") + udp_ports_in = forms.CharField(required=False, label="Ports UDP (entrée)") + tcp_ports_out = forms.CharField(required=False, label="Ports TCP (sortie)") + udp_ports_out = forms.CharField(required=False, label="Ports UDP (sortie)") class Meta: model = PortList fields = ['name'] diff --git a/machines/migrations/0060_port_io.py b/machines/migrations/0060_port_io.py new file mode 100644 index 00000000..0d890b56 --- /dev/null +++ b/machines/migrations/0060_port_io.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-10-01 09:30 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('machines', '0059_port_protocole'), + ] + + operations = [ + migrations.AddField( + model_name='port', + name='io', + field=models.CharField(choices=[('I', 'IN'), ('O', 'OUT')], default='O', max_length=1), + ), + ] diff --git a/machines/models.py b/machines/models.py index 91e16ab9..949d9608 100644 --- a/machines/models.py +++ b/machines/models.py @@ -417,11 +417,18 @@ class PortList(models.Model): def __str__(self): return ', '.join(map(str, self.port_set.all())) - def tcp_ports(self): - return self.port_set.filter(protocole=Port.TCP) + def tcp_ports_in(self): + return self.port_set.filter(protocole=Port.TCP, io=Port.IN) - def udp_ports(self): - return self.port_set.filter(protocole=Port.UDP) + def udp_ports_in(self): + return self.port_set.filter(protocole=Port.UDP, io=Port.IN) + + def tcp_ports_out(self): + return self.port_set.filter(protocole=Port.TCP, io=Port.OUT) + + def udp_ports_out(self): + return self.port_set.filter(protocole=Port.UDP, io=Port.OUT) + class Port(models.Model): """ @@ -432,6 +439,8 @@ class Port(models.Model): """ TCP = 'T' UDP = 'U' + IN = 'I' + OUT = 'O' begin = models.IntegerField() end = models.IntegerField() port_list = models.ForeignKey('PortList', on_delete=models.CASCADE) @@ -443,6 +452,14 @@ class Port(models.Model): ), default=TCP, ) + io = models.CharField( + max_length=1, + choices=( + (IN, 'IN'), + (OUT, 'OUT'), + ), + default=OUT, + ) def __str__(self): if self.begin == self.end : diff --git a/machines/templates/machines/index_portlist.html b/machines/templates/machines/index_portlist.html index ce48e249..81847af1 100644 --- a/machines/templates/machines/index_portlist.html +++ b/machines/templates/machines/index_portlist.html @@ -11,16 +11,20 @@ Nom - TCP - UDP + TCP (entrée) + TCP (sortie) + UDP (entrée) + UDP (sortie) {% for pl in port_list %} {{pl.name}} - {% for p in pl.tcp_ports%}{{p.show_port}}, {%endfor%} - {% for p in pl.udp_ports%}{{p.show_port}}, {%endfor%} + {% for p in pl.tcp_ports_in %}{{p.show_port}}, {%endfor%} + {% for p in pl.tcp_ports_out %}{{p.show_port}}, {%endfor%} + {% for p in pl.udp_ports_in %}{{p.show_port}}, {%endfor%} + {% for p in pl.udp_ports_out %}{{p.show_port}}, {%endfor%} {%comment%} {% include 'buttons/suppr.html' href='machines:del-portlist' id=pl.id %} From 60e42d699338002c4b93bef503364865bdad7d07 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Sun, 1 Oct 2017 16:42:55 +0200 Subject: [PATCH 06/37] =?UTF-8?q?=C3=89dition=20des=20listes=20de=20ports.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/forms.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++- machines/views.py | 5 +++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/machines/forms.py b/machines/forms.py index a611fa98..dec2cad2 100644 --- a/machines/forms.py +++ b/machines/forms.py @@ -22,9 +22,11 @@ from __future__ import unicode_literals +import re + from django.forms import ModelForm, Form, ValidationError from django import forms -from .models import Domain, Machine, Interface, IpList, MachineType, Extension, Mx, Text, Ns, Service, Vlan, Nas, IpType, PortList +from .models import Domain, Machine, Interface, IpList, MachineType, Extension, Mx, Text, Ns, Service, Vlan, Nas, IpType, PortList, Port from django.db.models import Q from django.core.validators import validate_email @@ -238,4 +240,57 @@ class EditPortListForm(ModelForm): model = PortList fields = ['name'] + def __init__(self, *args, **kwargs): + super(EditPortListForm, self).__init__(*args, **kwargs) + self.fields['name'].label = "Nom de la liste" + if 'instance' in kwargs.keys(): + p = kwargs['instance'] + self.fields['tcp_ports_in'].initial = ', '.join(map(str, p.tcp_ports_in())) + self.fields['tcp_ports_out'].initial = ', '.join(map(str, p.tcp_ports_out())) + self.fields['udp_ports_in'].initial = ', '.join(map(str, p.udp_ports_in())) + self.fields['udp_ports_out'].initial = ', '.join(map(str, p.udp_ports_out())) + + def save(self, commit=False): + """ + Sauvegarde l'instance. Le commit est obligatoire à cause des ForeignKey. + """ + instance = super(EditPortListForm, self).save(commit=False) + + # Suppression des anciens ports. + for port in instance.port_set.all(): + port.delete() + + split = r',\s+' + ip_range = r'\d+-\d+' + def add_port(string, protocole, mode): + for p in re.split(split, string): + if not p: + continue + if re.match(ip_range, p): + a,b = p.split('-') + a,b = int(a), int(b) + begin,end = min(a,b),max(a,b) + else: + begin = end = int(p.strip()) + port = Port() + port.begin = begin + port.end = end + port.port_list = instance + port.protocole = protocole + port.io = mode + port.save() + + # Ajout des ports TCP en entrée + add_port(self.cleaned_data['tcp_ports_in'], Port.TCP, Port.IN) + # Ajout des ports TCP en sortie + add_port(self.cleaned_data['tcp_ports_out'], Port.TCP, Port.OUT) + # Ajout des ports UDP en entrée + add_port(self.cleaned_data['tcp_ports_in'], Port.UDP, Port.IN) + # Ajout des ports UDP en sortie + add_port(self.cleaned_data['tcp_ports_in'], Port.UDP, Port.OUT) + + if commit: + instance.save() + + return instance diff --git a/machines/views.py b/machines/views.py index 32b04c2e..a35ad79d 100644 --- a/machines/views.py +++ b/machines/views.py @@ -925,6 +925,11 @@ def edit_portlist(request, pk): port_list_instance = get_object_or_404(PortList, pk=pk) port_list = EditPortListForm(request.POST or None, instance=port_list_instance) if port_list.is_valid(): + with transaction.atomic(), reversion.create_revision(): + port_list.save() + reversion.set_user(request.user) + reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in port_list.changed_data)) + messages.success(request, "Liste de ports modifiée") return redirect("/machines/index_portlist/") return form({'machineform' : port_list}, 'machines/machine.html', request) From 9ae9a840be1355808d60c80191c45a75db09b7e7 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Sun, 1 Oct 2017 16:57:51 +0200 Subject: [PATCH 07/37] =?UTF-8?q?Enl=C3=A8ve=20les=20log=20inutilisables.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/views.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/machines/views.py b/machines/views.py index a35ad79d..31e9545f 100644 --- a/machines/views.py +++ b/machines/views.py @@ -927,8 +927,6 @@ def edit_portlist(request, pk): if port_list.is_valid(): with transaction.atomic(), reversion.create_revision(): port_list.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in port_list.changed_data)) messages.success(request, "Liste de ports modifiée") return redirect("/machines/index_portlist/") return form({'machineform' : port_list}, 'machines/machine.html', request) From 4e2f795e77d4761a3240682b4bfe1c2c1a288f54 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Sun, 1 Oct 2017 17:09:00 +0200 Subject: [PATCH 08/37] Suppression de liste de ports. --- .../templates/machines/index_portlist.html | 4 +--- machines/urls.py | 1 + machines/views.py | 23 ++++++++++++++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/machines/templates/machines/index_portlist.html b/machines/templates/machines/index_portlist.html index 81847af1..b7a9d00d 100644 --- a/machines/templates/machines/index_portlist.html +++ b/machines/templates/machines/index_portlist.html @@ -26,9 +26,7 @@ {% for p in pl.udp_ports_in %}{{p.show_port}}, {%endfor%} {% for p in pl.udp_ports_out %}{{p.show_port}}, {%endfor%} - {%comment%} - {% include 'buttons/suppr.html' href='machines:del-portlist' id=pl.id %} - {%endcomment%} + {% include 'buttons/suppr.html' with href='machines:del-portlist' id=pl.id %} {% include 'buttons/edit.html' with href='machines:edit-portlist' id=pl.id %} diff --git a/machines/urls.py b/machines/urls.py index 29f7668f..bae9535f 100644 --- a/machines/urls.py +++ b/machines/urls.py @@ -94,4 +94,5 @@ urlpatterns = [ url(r'^rest/service_servers/$', views.service_servers, name='service-servers'), url(r'index_portlist/$', views.index_portlist, name='index-portlist'), url(r'^edit_portlist/(?P[0-9]+)$', views.edit_portlist, name='edit-portlist'), + url(r'^del_portlist/(?P[0-9]+)$', views.del_portlist, name='del-portlist'), ] diff --git a/machines/views.py b/machines/views.py index 31e9545f..e394fdc1 100644 --- a/machines/views.py +++ b/machines/views.py @@ -922,7 +922,11 @@ def index_portlist(request): @login_required @permission_required('bureau') def edit_portlist(request, pk): - port_list_instance = get_object_or_404(PortList, pk=pk) + try: + port_list_instance = PortList.objects.get(pk=pk) + except PortList.DoesNotExist: + messages.error(request, "Liste de ports inexistante") + return redirect("/machines/index_portlist/") port_list = EditPortListForm(request.POST or None, instance=port_list_instance) if port_list.is_valid(): with transaction.atomic(), reversion.create_revision(): @@ -931,6 +935,23 @@ def edit_portlist(request, pk): return redirect("/machines/index_portlist/") return form({'machineform' : port_list}, 'machines/machine.html', request) +@login_required +@permission_required('bureau') +def del_portlist(request, pk): + try: + port_list_instance = PortList.objects.get(pk=pk) + except PortList.DoesNotExist: + messages.error(request, "Liste de ports inexistante") + return redirect("/machines/index_portlist/") + if port_list_instance.interfaces.all(): + messages.error(request, "Cette liste de ports est utilisée") + return redirect("/machines/index_portlist/") + port_list_instance.delete() + messages.success(request, "La liste de ports a été supprimée") + return redirect("/machines/index_portlist/") + + + """ Framework Rest """ class JSONResponse(HttpResponse): From 71d9f1c382cb63a2435b6c9498b30ff62aff2d61 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Sun, 1 Oct 2017 17:11:07 +0200 Subject: [PATCH 09/37] Les cableurs peuvent voir les configurations de ports. --- machines/templates/machines/sidebar.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/templates/machines/sidebar.html b/machines/templates/machines/sidebar.html index a0d6948a..e635d69a 100644 --- a/machines/templates/machines/sidebar.html +++ b/machines/templates/machines/sidebar.html @@ -55,7 +55,7 @@ with this program; if not, write to the Free Software Foundation, Inc., Services (dhcp, dns...) {% endif %} - {% if is_bureau %} + {% if is_cableur %} Configuration de ports From 779c2be2de928f1353761087c411331b76e72af5 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Sun, 1 Oct 2017 17:19:42 +0200 Subject: [PATCH 10/37] =?UTF-8?q?Cr=C3=A9ation=20de=20liste=20de=20ports.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/forms.py | 2 ++ machines/templates/machines/index_portlist.html | 2 +- machines/urls.py | 1 + machines/views.py | 12 ++++++++++-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/machines/forms.py b/machines/forms.py index dec2cad2..ee84adfc 100644 --- a/machines/forms.py +++ b/machines/forms.py @@ -262,6 +262,8 @@ class EditPortListForm(ModelForm): split = r',\s+' ip_range = r'\d+-\d+' + if instance.pk == None: # On ne peut pas créer de ForeignKey sur des objets sans pk + instance.save() def add_port(string, protocole, mode): for p in re.split(split, string): if not p: diff --git a/machines/templates/machines/index_portlist.html b/machines/templates/machines/index_portlist.html index b7a9d00d..c21ea30e 100644 --- a/machines/templates/machines/index_portlist.html +++ b/machines/templates/machines/index_portlist.html @@ -6,7 +6,7 @@ {% block content %}

Liste des configurations de ports

-
Ajouter une configuration + Ajouter une configuration diff --git a/machines/urls.py b/machines/urls.py index bae9535f..51cf962e 100644 --- a/machines/urls.py +++ b/machines/urls.py @@ -95,4 +95,5 @@ urlpatterns = [ url(r'index_portlist/$', views.index_portlist, name='index-portlist'), url(r'^edit_portlist/(?P[0-9]+)$', views.edit_portlist, name='edit-portlist'), url(r'^del_portlist/(?P[0-9]+)$', views.del_portlist, name='del-portlist'), + url(r'^add_portlist/$', views.add_portlist, name='add-portlist'), ] diff --git a/machines/views.py b/machines/views.py index e394fdc1..9c1ad718 100644 --- a/machines/views.py +++ b/machines/views.py @@ -929,8 +929,7 @@ def edit_portlist(request, pk): return redirect("/machines/index_portlist/") port_list = EditPortListForm(request.POST or None, instance=port_list_instance) if port_list.is_valid(): - with transaction.atomic(), reversion.create_revision(): - port_list.save() + port_list.save() messages.success(request, "Liste de ports modifiée") return redirect("/machines/index_portlist/") return form({'machineform' : port_list}, 'machines/machine.html', request) @@ -950,6 +949,15 @@ def del_portlist(request, pk): messages.success(request, "La liste de ports a été supprimée") return redirect("/machines/index_portlist/") +@login_required +@permission_required('bureau') +def add_portlist(request): + port_list = EditPortListForm(request.POST or None) + if port_list.is_valid(): + port_list.save() + messages.success(request, "Liste de ports créée") + return redirect("/machines/index_portlist/") + return form({'machineform' : port_list}, 'machines/machine.html', request) """ Framework Rest """ From a00ad6c5908d9722a654ec79f518522c41b9ed40 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Sun, 1 Oct 2017 18:02:51 +0200 Subject: [PATCH 11/37] =?UTF-8?q?Nommage=20coh=C3=A9rent.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/views.py b/machines/views.py index 9c1ad718..eed0e4c8 100644 --- a/machines/views.py +++ b/machines/views.py @@ -942,7 +942,7 @@ def del_portlist(request, pk): except PortList.DoesNotExist: messages.error(request, "Liste de ports inexistante") return redirect("/machines/index_portlist/") - if port_list_instance.interfaces.all(): + if port_list_instance.interface_set.all(): messages.error(request, "Cette liste de ports est utilisée") return redirect("/machines/index_portlist/") port_list_instance.delete() From 2b08be8931812dc8aa8e36ca5c442554bc91c270 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Sun, 1 Oct 2017 21:57:10 +0200 Subject: [PATCH 12/37] =?UTF-8?q?Utilisation=20de=20formset=20pour=20?= =?UTF-8?q?=C3=A9diter=20une=20liste=20de=20ports.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/forms.py | 68 ++---------------- machines/models.py | 5 +- .../templates/machines/edit_portlist.html | 69 +++++++++++++++++++ machines/views.py | 24 +++++-- 4 files changed, 96 insertions(+), 70 deletions(-) create mode 100644 machines/templates/machines/edit_portlist.html diff --git a/machines/forms.py b/machines/forms.py index ee84adfc..863a4d6f 100644 --- a/machines/forms.py +++ b/machines/forms.py @@ -59,6 +59,7 @@ class EditInterfaceForm(ModelForm): self.fields['mac_address'].label = 'Adresse mac' self.fields['type'].label = 'Type de machine' self.fields['type'].empty_label = "Séléctionner un type de machine" + self.fields['port_lists'].label = "Configuration des ports" if "machine" in self.fields: self.fields['machine'].queryset = Machine.objects.all().select_related('user') @@ -231,68 +232,13 @@ class VlanForm(ModelForm): class DelVlanForm(Form): vlan = forms.ModelMultipleChoiceField(queryset=Vlan.objects.all(), label="Vlan actuels", widget=forms.CheckboxSelectMultiple) +class EditPortForm(ModelForm): + class Meta: + model = Port + fields = '__all__' + class EditPortListForm(ModelForm): - tcp_ports_in = forms.CharField(required=False, label="Ports TCP (entrée)") - udp_ports_in = forms.CharField(required=False, label="Ports UDP (entrée)") - tcp_ports_out = forms.CharField(required=False, label="Ports TCP (sortie)") - udp_ports_out = forms.CharField(required=False, label="Ports UDP (sortie)") class Meta: model = PortList - fields = ['name'] - - def __init__(self, *args, **kwargs): - super(EditPortListForm, self).__init__(*args, **kwargs) - self.fields['name'].label = "Nom de la liste" - if 'instance' in kwargs.keys(): - p = kwargs['instance'] - self.fields['tcp_ports_in'].initial = ', '.join(map(str, p.tcp_ports_in())) - self.fields['tcp_ports_out'].initial = ', '.join(map(str, p.tcp_ports_out())) - self.fields['udp_ports_in'].initial = ', '.join(map(str, p.udp_ports_in())) - self.fields['udp_ports_out'].initial = ', '.join(map(str, p.udp_ports_out())) - - def save(self, commit=False): - """ - Sauvegarde l'instance. Le commit est obligatoire à cause des ForeignKey. - """ - instance = super(EditPortListForm, self).save(commit=False) - - # Suppression des anciens ports. - for port in instance.port_set.all(): - port.delete() - - split = r',\s+' - ip_range = r'\d+-\d+' - if instance.pk == None: # On ne peut pas créer de ForeignKey sur des objets sans pk - instance.save() - def add_port(string, protocole, mode): - for p in re.split(split, string): - if not p: - continue - if re.match(ip_range, p): - a,b = p.split('-') - a,b = int(a), int(b) - begin,end = min(a,b),max(a,b) - else: - begin = end = int(p.strip()) - port = Port() - port.begin = begin - port.end = end - port.port_list = instance - port.protocole = protocole - port.io = mode - port.save() - - # Ajout des ports TCP en entrée - add_port(self.cleaned_data['tcp_ports_in'], Port.TCP, Port.IN) - # Ajout des ports TCP en sortie - add_port(self.cleaned_data['tcp_ports_out'], Port.TCP, Port.OUT) - # Ajout des ports UDP en entrée - add_port(self.cleaned_data['tcp_ports_in'], Port.UDP, Port.IN) - # Ajout des ports UDP en sortie - add_port(self.cleaned_data['tcp_ports_in'], Port.UDP, Port.OUT) - - if commit: - instance.save() - - return instance + fields = '__all__' diff --git a/machines/models.py b/machines/models.py index 949d9608..7c13e8eb 100644 --- a/machines/models.py +++ b/machines/models.py @@ -223,7 +223,7 @@ class Interface(models.Model): machine = models.ForeignKey('Machine', on_delete=models.CASCADE) type = models.ForeignKey('MachineType', on_delete=models.PROTECT) details = models.CharField(max_length=255, blank=True) - has_public_ip = False + port_lists = models.ManyToManyField('PortList', blank=True) @cached_property def is_active(self): @@ -411,11 +411,10 @@ class Service_link(models.Model): class PortList(models.Model): """Liste des ports ouverts sur une interface.""" - interfaces = models.ManyToManyField('Interface') name = models.CharField(help_text="Nom de la configuration des ports.", max_length=255) def __str__(self): - return ', '.join(map(str, self.port_set.all())) + return self.name def tcp_ports_in(self): return self.port_set.filter(protocole=Port.TCP, io=Port.IN) diff --git a/machines/templates/machines/edit_portlist.html b/machines/templates/machines/edit_portlist.html new file mode 100644 index 00000000..21cc46f2 --- /dev/null +++ b/machines/templates/machines/edit_portlist.html @@ -0,0 +1,69 @@ +{% extends "machines/sidebar.html" %} +{% comment %} +Re2o est un logiciel d'administration développé initiallement au rezometz. Il +se veut agnostique au réseau considéré, de manière à être installable en +quelques clics. + +Copyright © 2017 Gabriel Détraz +Copyright © 2017 Goulven Kermarec +Copyright © 2017 Augustin Lemesle + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +{% endcomment %} + +{% load bootstrap3 %} + +{% block title %}Création et modification de machines{% endblock %} + +{% block content %} +{% bootstrap_form_errors port_list %} + + +
+ {% csrf_token %} + {% bootstrap_form port_list %} + {{ ports.management_form }} +
+ {% for form in ports.forms %} +
+

+ {{ form }} +

+
+ {% endfor %} +
+ +

+ +

+ + {% bootstrap_button "Créer ou modifier" button_type="submit" icon="star" %} + + +{% endblock %} diff --git a/machines/views.py b/machines/views.py index eed0e4c8..b02d2198 100644 --- a/machines/views.py +++ b/machines/views.py @@ -35,7 +35,7 @@ from django.template import Context, RequestContext, loader from django.contrib import messages from django.contrib.auth.decorators import login_required, permission_required from django.db.models import ProtectedError -from django.forms import ValidationError +from django.forms import ValidationError, formset_factory, modelformset_factory from django.db import transaction from django.contrib.auth import authenticate, login from django.views.decorators.csrf import csrf_exempt @@ -48,8 +48,8 @@ from reversion.models import Version import re from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm, BaseEditInterfaceForm, BaseEditMachineForm from .forms import EditIpTypeForm, IpTypeForm, DelIpTypeForm, DomainForm, AliasForm, DelAliasForm, NsForm, DelNsForm, TextForm, DelTextForm, MxForm, DelMxForm, VlanForm, DelVlanForm, ServiceForm, DelServiceForm, NasForm, DelNasForm -from .forms import EditPortListForm -from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain, Service, Service_link, Vlan, Nas, Text, PortList +from .forms import EditPortListForm, EditPortForm +from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain, Service, Service_link, Vlan, Nas, Text, PortList, Port from users.models import User from users.models import all_has_access from preferences.models import GeneralOption, OptionalMachine @@ -928,11 +928,23 @@ def edit_portlist(request, pk): messages.error(request, "Liste de ports inexistante") return redirect("/machines/index_portlist/") port_list = EditPortListForm(request.POST or None, instance=port_list_instance) - if port_list.is_valid(): - port_list.save() + port_formset = modelformset_factory( + Port, + fields=('begin','end','protocole','io'), + extra=0, + can_delete=True + )(request.POST or None, queryset=port_list_instance.port_set.all()) + if port_list.is_valid() and port_formset.is_valid(): + pl = port_list.save() + instances = port_formset.save(commit=False) + for to_delete in port_formset.deleted_objects: + to_delete.delete() + for port in instances: + port.port_list = pl + port.save() messages.success(request, "Liste de ports modifiée") return redirect("/machines/index_portlist/") - return form({'machineform' : port_list}, 'machines/machine.html', request) + return form({'port_list' : port_list, 'ports' : port_formset}, 'machines/edit_portlist.html', request) @login_required @permission_required('bureau') From 9f3e9b5509e3a3eea2cd4a36cea5c59511cc3ca7 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Sun, 1 Oct 2017 22:04:37 +0200 Subject: [PATCH 13/37] =?UTF-8?q?Cr=C3=A9ation=20de=20liste=20de=20ports?= =?UTF-8?q?=20via=20formset.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/views.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/machines/views.py b/machines/views.py index b02d2198..36db72cd 100644 --- a/machines/views.py +++ b/machines/views.py @@ -35,7 +35,7 @@ from django.template import Context, RequestContext, loader from django.contrib import messages from django.contrib.auth.decorators import login_required, permission_required from django.db.models import ProtectedError -from django.forms import ValidationError, formset_factory, modelformset_factory +from django.forms import ValidationError, modelformset_factory from django.db import transaction from django.contrib.auth import authenticate, login from django.views.decorators.csrf import csrf_exempt @@ -964,6 +964,24 @@ def del_portlist(request, pk): @login_required @permission_required('bureau') def add_portlist(request): + port_list = EditPortListForm(request.POST or None) + port_formset = modelformset_factory( + Port, + fields=('begin','end','protocole','io'), + extra=1, + can_delete=True + )(request.POST or None, queryset=Port.objects.none()) + if port_list.is_valid() and port_formset.is_valid(): + pl = port_list.save() + instances = port_formset.save(commit=False) + for to_delete in port_formset.deleted_objects: + to_delete.delete() + for port in instances: + port.port_list = pl + port.save() + messages.success(request, "Liste de ports créée") + return redirect("/machines/index_portlist/") + return form({'port_list' : port_list, 'ports' : port_formset}, 'machines/edit_portlist.html', request) port_list = EditPortListForm(request.POST or None) if port_list.is_valid(): port_list.save() From ad67b9cbd60e4179e5f1566d1cb92fa04c29f642 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Sun, 1 Oct 2017 23:13:10 +0200 Subject: [PATCH 14/37] Ne permet pas de sauvegarder de liste de ports vides. --- machines/views.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/machines/views.py b/machines/views.py index 36db72cd..54828999 100644 --- a/machines/views.py +++ b/machines/views.py @@ -932,7 +932,9 @@ def edit_portlist(request, pk): Port, fields=('begin','end','protocole','io'), extra=0, - can_delete=True + can_delete=True, + min_num=1, + validate_min=True, )(request.POST or None, queryset=port_list_instance.port_set.all()) if port_list.is_valid() and port_formset.is_valid(): pl = port_list.save() @@ -968,8 +970,10 @@ def add_portlist(request): port_formset = modelformset_factory( Port, fields=('begin','end','protocole','io'), - extra=1, - can_delete=True + extra=0, + can_delete=True, + min_num=1, + validate_min=True, )(request.POST or None, queryset=Port.objects.none()) if port_list.is_valid() and port_formset.is_valid(): pl = port_list.save() From b57fed742318bfa76abacd6bcb58670401441cd8 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Mon, 2 Oct 2017 00:08:07 +0200 Subject: [PATCH 15/37] =?UTF-8?q?Affectation=20de=20configuration=20de=20p?= =?UTF-8?q?orts=20=C3=A0=20une=20interface.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/forms.py | 10 ++++---- .../migrations/0061_auto_20171001_1727.py | 24 +++++++++++++++++++ machines/models.py | 3 +++ machines/templates/machines/aff_machines.html | 5 ++++ machines/urls.py | 2 ++ machines/views.py | 16 ++++++++++++- 6 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 machines/migrations/0061_auto_20171001_1727.py diff --git a/machines/forms.py b/machines/forms.py index 863a4d6f..34d9652f 100644 --- a/machines/forms.py +++ b/machines/forms.py @@ -52,14 +52,14 @@ class BaseEditMachineForm(EditMachineForm): class EditInterfaceForm(ModelForm): class Meta: model = Interface - fields = '__all__' + # fields = '__all__' + exclude = ['port_lists'] def __init__(self, *args, **kwargs): super(EditInterfaceForm, self).__init__(*args, **kwargs) self.fields['mac_address'].label = 'Adresse mac' self.fields['type'].label = 'Type de machine' self.fields['type'].empty_label = "Séléctionner un type de machine" - self.fields['port_lists'].label = "Configuration des ports" if "machine" in self.fields: self.fields['machine'].queryset = Machine.objects.all().select_related('user') @@ -232,10 +232,10 @@ class VlanForm(ModelForm): class DelVlanForm(Form): vlan = forms.ModelMultipleChoiceField(queryset=Vlan.objects.all(), label="Vlan actuels", widget=forms.CheckboxSelectMultiple) -class EditPortForm(ModelForm): +class EditPortConfigForm(ModelForm): class Meta: - model = Port - fields = '__all__' + model = Interface + fields = ['port_lists'] class EditPortListForm(ModelForm): class Meta: diff --git a/machines/migrations/0061_auto_20171001_1727.py b/machines/migrations/0061_auto_20171001_1727.py new file mode 100644 index 00000000..661f9fd3 --- /dev/null +++ b/machines/migrations/0061_auto_20171001_1727.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-10-01 15:27 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('machines', '0060_port_io'), + ] + + operations = [ + migrations.RemoveField( + model_name='portlist', + name='interfaces', + ), + migrations.AddField( + model_name='interface', + name='port_lists', + field=models.ManyToManyField(to='machines.PortList'), + ), + ] diff --git a/machines/models.py b/machines/models.py index 7c13e8eb..bf5a774d 100644 --- a/machines/models.py +++ b/machines/models.py @@ -279,6 +279,9 @@ class Interface(models.Model): domain = None return str(domain) + def has_private_ip(self): + return IPAddress(str(self.ipv4)).is_private() + class Domain(models.Model): PRETTY_NAME = "Domaine dns" diff --git a/machines/templates/machines/aff_machines.html b/machines/templates/machines/aff_machines.html index a09d8868..c4a2dd56 100644 --- a/machines/templates/machines/aff_machines.html +++ b/machines/templates/machines/aff_machines.html @@ -91,6 +91,11 @@ with this program; if not, write to the Free Software Foundation, Inc., Gerer les alias +
  • + + Gerer la configuration des ports + +
  • Historique diff --git a/machines/urls.py b/machines/urls.py index 51cf962e..62576a4e 100644 --- a/machines/urls.py +++ b/machines/urls.py @@ -96,4 +96,6 @@ urlpatterns = [ url(r'^edit_portlist/(?P[0-9]+)$', views.edit_portlist, name='edit-portlist'), url(r'^del_portlist/(?P[0-9]+)$', views.del_portlist, name='del-portlist'), url(r'^add_portlist/$', views.add_portlist, name='add-portlist'), + url(r'^port_config/(?P[0-9]+)$', views.configure_ports, name='port-config'), + ] diff --git a/machines/views.py b/machines/views.py index 54828999..9aaf90e7 100644 --- a/machines/views.py +++ b/machines/views.py @@ -48,7 +48,7 @@ from reversion.models import Version import re from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm, BaseEditInterfaceForm, BaseEditMachineForm from .forms import EditIpTypeForm, IpTypeForm, DelIpTypeForm, DomainForm, AliasForm, DelAliasForm, NsForm, DelNsForm, TextForm, DelTextForm, MxForm, DelMxForm, VlanForm, DelVlanForm, ServiceForm, DelServiceForm, NasForm, DelNasForm -from .forms import EditPortListForm, EditPortForm +from .forms import EditPortListForm, EditPortConfigForm from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain, Service, Service_link, Vlan, Nas, Text, PortList, Port from users.models import User from users.models import all_has_access @@ -993,6 +993,20 @@ def add_portlist(request): return redirect("/machines/index_portlist/") return form({'machineform' : port_list}, 'machines/machine.html', request) +@login_required +@permission_required('cableur') +def configure_ports(request, pk): + try: + interface_instance = Interface.objects.get(pk=pk) + except Interface.DoesNotExist: + messages.error(request, u"Interface inexistante" ) + return redirect("/machines") + interface = EditPortConfigForm(request.POST or None, instance=interface_instance) + if interface.is_valid(): + interface.save() + messages.success(request, "Configuration des ports mise à jour.") + return redirect("/machines/") + return form({'interfaceform' : interface}, 'machines/machine.html', request) """ Framework Rest """ From 5f511eaf3fca4991738a53fd964b2a67c36fe79e Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Mon, 2 Oct 2017 01:52:14 +0200 Subject: [PATCH 16/37] Affichage des machines par profil de port --- .../templates/machines/index_portlist.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/machines/templates/machines/index_portlist.html b/machines/templates/machines/index_portlist.html index c21ea30e..04ac66d4 100644 --- a/machines/templates/machines/index_portlist.html +++ b/machines/templates/machines/index_portlist.html @@ -15,6 +15,7 @@
  • + @@ -25,6 +26,23 @@ + + @@ -42,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc., + - + @@ -74,7 +74,9 @@ with this program; if not, write to the Free Software Foundation, Inc., - + - + + +
    TCP (sortie) UDP (entrée) UDP (sortie)Machines
    {% for p in pl.tcp_ports_out %}{{p.show_port}}, {%endfor%} {% for p in pl.udp_ports_in %}{{p.show_port}}, {%endfor%} {% for p in pl.udp_ports_out %}{{p.show_port}}, {%endfor%} + {% if pl.interface_set.all %} + + {% endif %} {% include 'buttons/suppr.html' with href='machines:del-portlist' id=pl.id %} {% include 'buttons/edit.html' with href='machines:edit-portlist' id=pl.id %} From c459d3f45c5d2fc4dc02b9f18883e0d997a842d7 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Mon, 2 Oct 2017 04:19:07 +0200 Subject: [PATCH 17/37] Renomage des tables, ecriture des admin et fioritures --- machines/admin.py | 14 +++++++++- machines/forms.py | 8 +++--- ...928_1711.py => 0058_auto_20171002_0350.py} | 18 ++++++++---- machines/migrations/0059_port_protocole.py | 20 ------------- machines/migrations/0060_port_io.py | 20 ------------- .../migrations/0061_auto_20171001_1727.py | 24 ---------------- machines/models.py | 26 +++++++++++------ machines/views.py | 28 +++++++++---------- 8 files changed, 60 insertions(+), 98 deletions(-) rename machines/migrations/{0058_auto_20170928_1711.py => 0058_auto_20171002_0350.py} (61%) delete mode 100644 machines/migrations/0059_port_protocole.py delete mode 100644 machines/migrations/0060_port_io.py delete mode 100644 machines/migrations/0061_auto_20171001_1727.py diff --git a/machines/admin.py b/machines/admin.py index 5fe4c49b..49b02a7e 100644 --- a/machines/admin.py +++ b/machines/admin.py @@ -26,7 +26,9 @@ from __future__ import unicode_literals from django.contrib import admin from reversion.admin import VersionAdmin -from .models import IpType, Machine, MachineType, Domain, IpList, Interface, Extension, Mx, Ns, Vlan, Text, Nas, Service +from .models import IpType, Machine, MachineType, Domain, IpList, Interface +from .models import Extension, Mx, Ns, Vlan, Text, Nas, Service, OuverturePort +from .models import OuverturePortList class MachineAdmin(VersionAdmin): pass @@ -58,6 +60,12 @@ class NasAdmin(VersionAdmin): class IpListAdmin(VersionAdmin): pass +class OuverturePortAdmin(VersionAdmin): + pass + +class OuverturePortListAdmin(VersionAdmin): + pass + class InterfaceAdmin(VersionAdmin): list_display = ('machine','type','mac_address','ipv4','details') @@ -80,3 +88,7 @@ admin.site.register(Domain, DomainAdmin) admin.site.register(Service, ServiceAdmin) admin.site.register(Vlan, VlanAdmin) admin.site.register(Nas, NasAdmin) +admin.site.register(OuverturePort, OuverturePortAdmin) +admin.site.register(OuverturePortList, OuverturePortListAdmin) + + diff --git a/machines/forms.py b/machines/forms.py index 34d9652f..c29af9dd 100644 --- a/machines/forms.py +++ b/machines/forms.py @@ -26,7 +26,7 @@ import re from django.forms import ModelForm, Form, ValidationError from django import forms -from .models import Domain, Machine, Interface, IpList, MachineType, Extension, Mx, Text, Ns, Service, Vlan, Nas, IpType, PortList, Port +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 @@ -232,13 +232,13 @@ class VlanForm(ModelForm): class DelVlanForm(Form): vlan = forms.ModelMultipleChoiceField(queryset=Vlan.objects.all(), label="Vlan actuels", widget=forms.CheckboxSelectMultiple) -class EditPortConfigForm(ModelForm): +class EditOuverturePortConfigForm(ModelForm): class Meta: model = Interface fields = ['port_lists'] -class EditPortListForm(ModelForm): +class EditOuverturePortListForm(ModelForm): class Meta: - model = PortList + model = OuverturePortList fields = '__all__' diff --git a/machines/migrations/0058_auto_20170928_1711.py b/machines/migrations/0058_auto_20171002_0350.py similarity index 61% rename from machines/migrations/0058_auto_20170928_1711.py rename to machines/migrations/0058_auto_20171002_0350.py index 41224de1..bc6b2508 100644 --- a/machines/migrations/0058_auto_20170928_1711.py +++ b/machines/migrations/0058_auto_20171002_0350.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-09-28 15:11 +# Generated by Django 1.10.7 on 2017-10-02 01:50 from __future__ import unicode_literals from django.db import migrations, models @@ -14,24 +14,30 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Port', + name='OuverturePort', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('begin', models.IntegerField()), ('end', models.IntegerField()), + ('protocole', models.CharField(choices=[('T', 'TCP'), ('U', 'UDP')], default='T', max_length=1)), + ('io', models.CharField(choices=[('I', 'IN'), ('O', 'OUT')], default='O', max_length=1)), ], ), migrations.CreateModel( - name='PortList', + name='OuverturePortList', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(help_text='Nom de la configuration des ports.', max_length=255)), - ('interfaces', models.ManyToManyField(to='machines.Interface')), ], ), migrations.AddField( - model_name='port', + model_name='ouvertureport', name='port_list', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='machines.PortList'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='machines.OuverturePortList'), + ), + migrations.AddField( + model_name='interface', + name='port_lists', + field=models.ManyToManyField(blank=True, to='machines.OuverturePortList'), ), ] diff --git a/machines/migrations/0059_port_protocole.py b/machines/migrations/0059_port_protocole.py deleted file mode 100644 index fc43bdb0..00000000 --- a/machines/migrations/0059_port_protocole.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-09-28 16:03 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('machines', '0058_auto_20170928_1711'), - ] - - operations = [ - migrations.AddField( - model_name='port', - name='protocole', - field=models.CharField(choices=[('T', 'TCP'), ('U', 'UDP')], default='T', max_length=1), - ), - ] diff --git a/machines/migrations/0060_port_io.py b/machines/migrations/0060_port_io.py deleted file mode 100644 index 0d890b56..00000000 --- a/machines/migrations/0060_port_io.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-10-01 09:30 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('machines', '0059_port_protocole'), - ] - - operations = [ - migrations.AddField( - model_name='port', - name='io', - field=models.CharField(choices=[('I', 'IN'), ('O', 'OUT')], default='O', max_length=1), - ), - ] diff --git a/machines/migrations/0061_auto_20171001_1727.py b/machines/migrations/0061_auto_20171001_1727.py deleted file mode 100644 index 661f9fd3..00000000 --- a/machines/migrations/0061_auto_20171001_1727.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-10-01 15:27 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('machines', '0060_port_io'), - ] - - operations = [ - migrations.RemoveField( - model_name='portlist', - name='interfaces', - ), - migrations.AddField( - model_name='interface', - name='port_lists', - field=models.ManyToManyField(to='machines.PortList'), - ), - ] diff --git a/machines/models.py b/machines/models.py index bf5a774d..0313470d 100644 --- a/machines/models.py +++ b/machines/models.py @@ -223,7 +223,7 @@ class Interface(models.Model): machine = models.ForeignKey('Machine', on_delete=models.CASCADE) type = models.ForeignKey('MachineType', on_delete=models.PROTECT) details = models.CharField(max_length=255, blank=True) - port_lists = models.ManyToManyField('PortList', blank=True) + port_lists = models.ManyToManyField('OuverturePortList', blank=True) @cached_property def is_active(self): @@ -280,8 +280,13 @@ class Interface(models.Model): return str(domain) def has_private_ip(self): - return IPAddress(str(self.ipv4)).is_private() + if hasattr(self, 'ipv4'): + return IPAddress(str(self.ipv4)).is_private() + else: + return False + def may_have_port_open(self): + return hasattr(self, 'ipv4') and self.has_private_ip() class Domain(models.Model): PRETTY_NAME = "Domaine dns" @@ -412,7 +417,7 @@ class Service_link(models.Model): return str(self.server) + " " + str(self.service) -class PortList(models.Model): +class OuverturePortList(models.Model): """Liste des ports ouverts sur une interface.""" name = models.CharField(help_text="Nom de la configuration des ports.", max_length=255) @@ -420,19 +425,19 @@ class PortList(models.Model): return self.name def tcp_ports_in(self): - return self.port_set.filter(protocole=Port.TCP, io=Port.IN) + return self.ouvertureport_set.filter(protocole=OuverturePort.TCP, io=OuverturePort.IN) def udp_ports_in(self): - return self.port_set.filter(protocole=Port.UDP, io=Port.IN) + return self.ouvertureport_set.filter(protocole=OuverturePort.UDP, io=OuverturePort.IN) def tcp_ports_out(self): - return self.port_set.filter(protocole=Port.TCP, io=Port.OUT) + return self.ouvertureport_set.filter(protocole=OuverturePort.TCP, io=OuverturePort.OUT) def udp_ports_out(self): - return self.port_set.filter(protocole=Port.UDP, io=Port.OUT) + return self.ouvertureport_set.filter(protocole=OuverturePort.UDP, io=OuverturePort.OUT) -class Port(models.Model): +class OuverturePort(models.Model): """ Représente un simple port ou une plage de ports. @@ -445,7 +450,7 @@ class Port(models.Model): OUT = 'O' begin = models.IntegerField() end = models.IntegerField() - port_list = models.ForeignKey('PortList', on_delete=models.CASCADE) + port_list = models.ForeignKey('OuverturePortList', on_delete=models.CASCADE) protocole = models.CharField( max_length=1, choices=( @@ -492,6 +497,9 @@ def interface_post_save(sender, **kwargs): interface = kwargs['instance'] user = interface.machine.user user.ldap_sync(base=False, access_refresh=False, mac_refresh=True) + if interface.may_have_port_open() and interface.port_lists.all(): + interface.port_lists.clear() + # Regen services regen('dhcp') regen('mac_ip_list') diff --git a/machines/views.py b/machines/views.py index 9aaf90e7..8a01d813 100644 --- a/machines/views.py +++ b/machines/views.py @@ -48,8 +48,8 @@ from reversion.models import Version import re from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm, BaseEditInterfaceForm, BaseEditMachineForm from .forms import EditIpTypeForm, IpTypeForm, DelIpTypeForm, DomainForm, AliasForm, DelAliasForm, NsForm, DelNsForm, TextForm, DelTextForm, MxForm, DelMxForm, VlanForm, DelVlanForm, ServiceForm, DelServiceForm, NasForm, DelNasForm -from .forms import EditPortListForm, EditPortConfigForm -from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain, Service, Service_link, Vlan, Nas, Text, PortList, Port +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 users.models import User from users.models import all_has_access from preferences.models import GeneralOption, OptionalMachine @@ -916,20 +916,20 @@ def history(request, object, id): @login_required @permission_required('cableur') def index_portlist(request): - port_list = PortList.objects.all().order_by('name') + port_list = OuverturePortList.objects.all().order_by('name') return render(request, "machines/index_portlist.html", {'port_list':port_list}) @login_required @permission_required('bureau') def edit_portlist(request, pk): try: - port_list_instance = PortList.objects.get(pk=pk) - except PortList.DoesNotExist: + port_list_instance = OuverturePortList.objects.get(pk=pk) + except OuverturePortList.DoesNotExist: messages.error(request, "Liste de ports inexistante") return redirect("/machines/index_portlist/") - port_list = EditPortListForm(request.POST or None, instance=port_list_instance) + port_list = EditOuverturePortListForm(request.POST or None, instance=port_list_instance) port_formset = modelformset_factory( - Port, + OuverturePort, fields=('begin','end','protocole','io'), extra=0, can_delete=True, @@ -952,8 +952,8 @@ def edit_portlist(request, pk): @permission_required('bureau') def del_portlist(request, pk): try: - port_list_instance = PortList.objects.get(pk=pk) - except PortList.DoesNotExist: + port_list_instance = OuverturePortList.objects.get(pk=pk) + except OuverturePortList.DoesNotExist: messages.error(request, "Liste de ports inexistante") return redirect("/machines/index_portlist/") if port_list_instance.interface_set.all(): @@ -966,15 +966,15 @@ def del_portlist(request, pk): @login_required @permission_required('bureau') def add_portlist(request): - port_list = EditPortListForm(request.POST or None) + port_list = EditOuverturePortListForm(request.POST or None) port_formset = modelformset_factory( - Port, + OuverturePort, fields=('begin','end','protocole','io'), extra=0, can_delete=True, min_num=1, validate_min=True, - )(request.POST or None, queryset=Port.objects.none()) + )(request.POST or None, queryset=OuverturePort.objects.none()) if port_list.is_valid() and port_formset.is_valid(): pl = port_list.save() instances = port_formset.save(commit=False) @@ -986,7 +986,7 @@ def add_portlist(request): messages.success(request, "Liste de ports créée") return redirect("/machines/index_portlist/") return form({'port_list' : port_list, 'ports' : port_formset}, 'machines/edit_portlist.html', request) - port_list = EditPortListForm(request.POST or None) + port_list = EditOuverturePortListForm(request.POST or None) if port_list.is_valid(): port_list.save() messages.success(request, "Liste de ports créée") @@ -1001,7 +1001,7 @@ def configure_ports(request, pk): except Interface.DoesNotExist: messages.error(request, u"Interface inexistante" ) return redirect("/machines") - interface = EditPortConfigForm(request.POST or None, instance=interface_instance) + interface = EditOuverturePortConfigForm(request.POST or None, instance=interface_instance) if interface.is_valid(): interface.save() messages.success(request, "Configuration des ports mise à jour.") From 28a29df0549ec3c85f8c55487f7964086ff5c434 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 2 Oct 2017 04:54:40 +0200 Subject: [PATCH 18/37] =?UTF-8?q?L'affichage=20et=20l'acc=C3=A8s=20au=20me?= =?UTF-8?q?nu=20port=20sont=20possible=20que=20si=20ip=20publique?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/models.py | 6 +++--- machines/templates/machines/aff_machines.html | 2 ++ machines/views.py | 3 +++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/machines/models.py b/machines/models.py index 0313470d..cb859141 100644 --- a/machines/models.py +++ b/machines/models.py @@ -280,13 +280,13 @@ class Interface(models.Model): return str(domain) def has_private_ip(self): - if hasattr(self, 'ipv4'): + if self.ipv4: return IPAddress(str(self.ipv4)).is_private() else: return False def may_have_port_open(self): - return hasattr(self, 'ipv4') and self.has_private_ip() + return self.ipv4 and not self.has_private_ip() class Domain(models.Model): PRETTY_NAME = "Domaine dns" @@ -497,7 +497,7 @@ def interface_post_save(sender, **kwargs): interface = kwargs['instance'] user = interface.machine.user user.ldap_sync(base=False, access_refresh=False, mac_refresh=True) - if interface.may_have_port_open() and interface.port_lists.all(): + if not interface.may_have_port_open() and interface.port_lists.all(): interface.port_lists.clear() # Regen services regen('dhcp') diff --git a/machines/templates/machines/aff_machines.html b/machines/templates/machines/aff_machines.html index c4a2dd56..6cf306f7 100644 --- a/machines/templates/machines/aff_machines.html +++ b/machines/templates/machines/aff_machines.html @@ -91,11 +91,13 @@ with this program; if not, write to the Free Software Foundation, Inc., Gerer les alias + {% if interface.may_have_port_open %}
  • Gerer la configuration des ports
  • + {% endif %}
  • Historique diff --git a/machines/views.py b/machines/views.py index 8a01d813..8200843c 100644 --- a/machines/views.py +++ b/machines/views.py @@ -1001,6 +1001,9 @@ def configure_ports(request, pk): except Interface.DoesNotExist: messages.error(request, u"Interface inexistante" ) return redirect("/machines") + if not interface_instance.may_have_port_open(): + messages.error(request, "L'ip de cette interface n'est pas publique ou non assignée") + return redirect("/machines") interface = EditOuverturePortConfigForm(request.POST or None, instance=interface_instance) if interface.is_valid(): interface.save() From 12fe768754ceba0f8595d85addf6526176721de9 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Mon, 2 Oct 2017 05:11:50 +0200 Subject: [PATCH 19/37] Bug fix --- machines/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/views.py b/machines/views.py index 8200843c..7dc4a3ca 100644 --- a/machines/views.py +++ b/machines/views.py @@ -935,7 +935,7 @@ def edit_portlist(request, pk): can_delete=True, min_num=1, validate_min=True, - )(request.POST or None, queryset=port_list_instance.port_set.all()) + )(request.POST or None, queryset=port_list_instance.ouvertureport_set.all()) if port_list.is_valid() and port_formset.is_valid(): pl = port_list.save() instances = port_formset.save(commit=False) From b7a5e3eeeb0f0101055245b0c1946b4560ae1d78 Mon Sep 17 00:00:00 2001 From: Chirac Date: Tue, 3 Oct 2017 00:47:56 +0200 Subject: [PATCH 20/37] Update README.md --- README.md | 123 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 88 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index ac5edbfe..44e7a5d0 100644 --- a/README.md +++ b/README.md @@ -4,17 +4,28 @@ Gnu public license v2.0 ## Avant propos -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. +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. -Il utilise le framework django avec python3. Il permet de gérer les adhérents, les machines, les factures, les droits d'accès, les switchs et la topologie du réseau. -De cette manière, il est possible de pluguer très facilement des services dessus, qui accèdent à la base de donnée en passant par django (ex : dhcp), en chargeant la liste de toutes les mac-ip, ou la liste des mac-ip autorisées sur le réseau (adhérent à jour de cotisation). +Il utilise le framework django avec python3. Il permet de gérer les adhérents, +les machines, les factures, les droits d'accès, les switchs et la topologie du +réseau. +De cette manière, il est possible de pluguer très facilement des services +dessus, qui accèdent à la base de donnée en passant par django (ex : dhcp), en +chargeant la liste de toutes les mac-ip, ou la liste des mac-ip autorisées sur +le réseau (adhérent à jour de cotisation). #Installation ## Installation des dépendances -L'installation comporte 3 partie : le serveur web où se trouve le depot re2o ainsi que toutes ses dépendances, le serveur bdd (mysql ou pgsql) et le serveur ldap. Ces 3 serveurs peuvent en réalité être la même machine, ou séparés (recommandé en production). -Le serveur web sera nommé serveur A, le serveur bdd serveur B et le serveur ldap serveur C. +L'installation comporte 3 partie : le serveur web où se trouve le depot re2o +ainsi que toutes ses dépendances, le serveur bdd (mysql ou pgsql) et le +serveur ldap. Ces 3 serveurs peuvent en réalité être la même machine, ou séparés +(recommandé en production). +Le serveur web sera nommé serveur A, le serveur bdd serveur B et le serveur ldap +serveur C. ### Prérequis sur le serveur A @@ -66,13 +77,20 @@ Sur le serveur C (ldap), avec apt : ### Installation sur le serveur principal A Cloner le dépot re2o à partir du gitlab, par exemple dans /var/www/re2o. -Ensuite, il faut créer le fichier settings_local.py dans le sous dossier re2o, un settings_local.example.py est présent. Les options sont commentées, et des options par défaut existent. +Ensuite, il faut créer le fichier settings_local.py dans le sous dossier re2o, +un settings_local.example.py est présent. Les options sont commentées, et des +options par défaut existent. -En particulier, il est nécessaire de générer un login/mdp admin pour le ldap et un login/mdp pour l'utilisateur sql (cf ci-dessous), à mettre dans settings_local.py +En particulier, il est nécessaire de générer un login/mdp admin pour le ldap et +un login/mdp pour l'utilisateur sql (cf ci-dessous), à mettre dans +settings_local.py ### Installation du serveur mysql/postgresql sur B -Sur le serveur mysql ou postgresl, il est nécessaire de créer une base de donnée re2o, ainsi qu'un user re2o et un mot de passe associé. Ne pas oublier de faire écouter le serveur mysql ou postgresql avec les acl nécessaire pour que A puisse l'utiliser. +Sur le serveur mysql ou postgresl, il est nécessaire de créer une base de +donnée re2o, ainsi qu'un user re2o et un mot de passe associé. +Ne pas oublier de faire écouter le serveur mysql ou postgresql avec les acl +nécessaire pour que A puisse l'utiliser. Voici les étapes à éxecuter pour mysql : * CREATE DATABASE re2o collate='utf8_general_ci'; @@ -80,35 +98,54 @@ Voici les étapes à éxecuter pour mysql : * GRANT ALL PRIVILEGES ON re2o.* TO 'newuser'@'localhost'; * FLUSH PRIVILEGES; -Si les serveurs A et B ne sont pas la même machine, il est nécessaire de remplacer localhost par l'ip avec laquelle A contacte B dans les commandes du dessus. -Une fois ces commandes effectuées, ne pas oublier de vérifier que newuser et password sont présents dans settings_local.py +Si les serveurs A et B ne sont pas la même machine, il est nécessaire de +remplacer localhost par l'ip avec laquelle A contacte B dans les commandes +du dessus. +Une fois ces commandes effectuées, ne pas oublier de vérifier que newuser et +password sont présents dans settings_local.py ### Installation du serveur ldap sur le serveur C Ceci se fait en plusieurs étapes : * générer un login/mdp administrateur (par example mkpasswd sous debian) - * Copier depuis re2o/install_utils (dans le dépot re2o) les fichiers db.ldiff et schema.ldiff (normalement sur le serveur A) sur le serveur C (par ex dans /tmp) - * Hasher le mot de passe généré en utilisant la commande slappasswd (installée par slapd) - * Remplacer toutes les sections FILL_IN par le hash dans schema.ldiff et db.ldiff - * Remplacer dans schema.ldiff et db.ldiff 'dc=example,dc=org' par le suffixe de l'organisation + * Copier depuis re2o/install_utils (dans le dépot re2o) les fichiers db.ldiff +et schema.ldiff (normalement sur le serveur A) sur le serveur C +(par ex dans /tmp) + * Hasher le mot de passe généré en utilisant la commande slappasswd +(installée par slapd) + * Remplacer toutes les sections FILL_IN par le hash dans schema.ldiff et +db.ldiff + * Remplacer dans schema.ldiff et db.ldiff 'dc=example,dc=org' par le +suffixe de l'organisation * Arréter slapd - * Supprimer les données existantes : '''rm -rf /etc/ldap/slapd.d/*''' et '''rm -rf /var/lib/ldap/*''' - * Injecter le nouveau schéma : '''slapadd -n 0 -l schema.ldiff -F /etc/ldap/slapd.d/''' et '''slapadd -n 1 -l db.ldiff''' - * Réparer les permissions (chown -R openldap:openldap /etc/ldap/slapd.d et chown -R openldap:openldap /var/lib/ldap) puis relancer slapd + * Supprimer les données existantes : '''rm -rf /etc/ldap/slapd.d/*''' et +'''rm -rf /var/lib/ldap/*''' + * Injecter le nouveau schéma : +'''slapadd -n 0 -l schema.ldiff -F /etc/ldap/slapd.d/''' et +'''slapadd -n 1 -l db.ldiff''' + * Réparer les permissions (chown -R openldap:openldap /etc/ldap/slapd.d et +chown -R openldap:openldap /var/lib/ldap) puis relancer slapd -Normalement le serveur ldap démare et est fonctionnel. Par défaut tls n'est pas activé, il faut pour cela modifier le schéma pour indiquer l'emplacement du certificat. -Pour visualiser et éditer le ldap, l'utilisation de shelldap est fortement recommandée, en utilisant en binddn cn=admin,dc=ldap,dc=example,dc=org et binddpw le mot de passe admin. +Normalement le serveur ldap démare et est fonctionnel. +Par défaut tls n'est pas activé, il faut pour cela modifier le schéma pour +indiquer l'emplacement du certificat. +Pour visualiser et éditer le ldap, l'utilisation de shelldap est fortement +recommandée, en utilisant en binddn cn=admin,dc=ldap,dc=example,dc=org et +binddpw le mot de passe admin. ## Configuration initiale Normalement à cette étape, le ldap et la bdd sql sont configurées correctement. -Il faut alors lancer dans le dépot re2o '''python3 manage.py migrate''' qui va structurer initialement la base de données. -Les migrations sont normalement comitées au fur et à mesure, néanmoins cette étape peut crasher, merci de reporter les bugs. +Il faut alors lancer dans le dépot re2o '''python3 manage.py migrate''' qui +va structurer initialement la base de données. +Les migrations sont normalement comitées au fur et à mesure, néanmoins cette +étape peut crasher, merci de reporter les bugs. ## Démarer le site web -Il faut utiliser un moteur pour servir le site web. Nginx ou apache2 sont recommandés. +Il faut utiliser un moteur pour servir le site web. Nginx ou apache2 sont +recommandés. Pour apache2 : * apt install apache2 * apt install libapache2-mod-wsgi-py3 (pour le module wsgi) @@ -119,9 +156,12 @@ re2o/wsgi.py permet de fonctionner avec apache2 en production ## Configuration avancée Une fois démaré, le site web devrait être accessible. -Pour créer un premier user, faire '''python3 manage.py createsuperuser''' qui va alors créer un user admin. -Il est conseillé de créer alors les droits cableur, bureau, trésorier et infra, qui n'existent pas par défaut dans le menu adhérents. -Il est également conseillé de créer un user portant le nom de l'association/organisation, qui possedera l'ensemble des machines. +Pour créer un premier user, faire '''python3 manage.py createsuperuser''' +qui va alors créer un user admin. +Il est conseillé de créer alors les droits cableur, bureau, trésorier et infra, +qui n'existent pas par défaut dans le menu adhérents. +Il est également conseillé de créer un user portant le nom de +l'association/organisation, qui possedera l'ensemble des machines. ## Installations Optionnelles ### Générer le schéma des dépendances @@ -134,24 +174,37 @@ Pour cela : ## Fonctionnement général -Re2o est séparé entre les models, qui sont visible sur le schéma des dépendances. Il s'agit en réalité des tables sql, et les fields etant les colonnes. -Ceci dit il n'est jamais nécessaire de toucher directement au sql, django procédant automatiquement à tout cela. -On crée donc différents models (user, right pour les droits des users, interfaces, IpList pour l'ensemble des adresses ip, etc) +Re2o est séparé entre les models, qui sont visible sur le schéma des +dépendances. Il s'agit en réalité des tables sql, et les fields etant les +colonnes. +Ceci dit il n'est jamais nécessaire de toucher directement au sql, django +procédant automatiquement à tout cela. +On crée donc différents models (user, right pour les droits des users, +interfaces, IpList pour l'ensemble des adresses ip, etc) -Du coté des forms, il s'agit des formulaire d'édition des models. Il s'agit de ModelForms django, qui héritent des models très simplement, voir la documentation django models forms. +Du coté des forms, il s'agit des formulaire d'édition des models. Il +s'agit de ModelForms django, qui héritent des models très simplement, voir la +documentation django models forms. Enfin les views, générent les pages web à partir des forms et des templates. ## Fonctionnement avec les services Les services dhcp.py, dns.py etc accèdent aux données via des vues rest. -Celles-ci se trouvent dans machines/views.py. Elles sont générées via machines/serializers.py qui génère les vues. IL s'agit de vues en json utilisées par re2o-tools pour récupérer les données. -Il est nécessaire de créer un user dans re2o avec le droit serveur qui permet d'accéder à ces vues, utilisé par re2o-tools. +Celles-ci se trouvent dans machines/views.py. Elles sont générées via +machines/serializers.py qui génère les vues. IL s'agit de vues en json utilisées +par re2o-tools pour récupérer les données. +Il est nécessaire de créer un user dans re2o avec le droit serveur qui permet +d'accéder à ces vues, utilisé par re2o-tools. # Requète en base de donnée Pour avoir un shell, il suffit de lancer '''python3 manage.py shell''' -Pour charger des objets, example avec User, faire : ''' from users.models import User''' -Pour charger les objets django, il suffit de faire User.objects.all() pour tous les users par exemple. -Il est ensuite aisé de faire des requètes, par exemple User.objects.filter(pseudo='test') -Des exemples et la documentation complète sur les requètes django sont disponible sur le site officiel. +Pour charger des objets, example avec User, faire : +''' from users.models import User''' +Pour charger les objets django, il suffit de faire User.objects.all() +pour tous les users par exemple. +Il est ensuite aisé de faire des requètes, par exemple +User.objects.filter(pseudo='test') +Des exemples et la documentation complète sur les requètes django sont +disponible sur le site officiel. From 3f044a25f283c5e3faecf4b68ae7697e5eea0166 Mon Sep 17 00:00:00 2001 From: Chirac Date: Tue, 3 Oct 2017 00:51:26 +0200 Subject: [PATCH 21/37] Update README.md --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 44e7a5d0..78439a59 100644 --- a/README.md +++ b/README.md @@ -92,12 +92,19 @@ donnée re2o, ainsi qu'un user re2o et un mot de passe associé. Ne pas oublier de faire écouter le serveur mysql ou postgresql avec les acl nécessaire pour que A puisse l'utiliser. +#### Mysql Voici les étapes à éxecuter pour mysql : * CREATE DATABASE re2o collate='utf8_general_ci'; * CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'password'; * GRANT ALL PRIVILEGES ON re2o.* TO 'newuser'@'localhost'; * FLUSH PRIVILEGES; +#### Postgresql + * CREATE DATABASE re2o ENCODING 'UTF8' LC_COLLATE='fr_FR.UTF-8' +LC_CTYPE='fr_FR.UTF-8'; + * CREATE USER newuser with password 'password'; + * ALTER DATABASE re2o owner to newuser; + Si les serveurs A et B ne sont pas la même machine, il est nécessaire de remplacer localhost par l'ip avec laquelle A contacte B dans les commandes du dessus. @@ -130,7 +137,7 @@ Normalement le serveur ldap démare et est fonctionnel. Par défaut tls n'est pas activé, il faut pour cela modifier le schéma pour indiquer l'emplacement du certificat. Pour visualiser et éditer le ldap, l'utilisation de shelldap est fortement -recommandée, en utilisant en binddn cn=admin,dc=ldap,dc=example,dc=org et +recommandée, en utilisant en binddn cn=admin,dc=example,dc=org et binddpw le mot de passe admin. ## Configuration initiale From 27ff94202941b3faed3232f7d36c6a93d93bbf2b Mon Sep 17 00:00:00 2001 From: Daniel STAN Date: Tue, 3 Oct 2017 02:04:44 +0200 Subject: [PATCH 22/37] =?UTF-8?q?README:=20pr=C3=A9cision=20sur=20TLS=20ld?= =?UTF-8?q?ap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 ++++++++++---- re2o/settings_local.example.py | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 78439a59..023d186a 100644 --- a/README.md +++ b/README.md @@ -133,13 +133,19 @@ suffixe de l'organisation * Réparer les permissions (chown -R openldap:openldap /etc/ldap/slapd.d et chown -R openldap:openldap /var/lib/ldap) puis relancer slapd -Normalement le serveur ldap démare et est fonctionnel. -Par défaut tls n'est pas activé, il faut pour cela modifier le schéma pour -indiquer l'emplacement du certificat. Pour visualiser et éditer le ldap, l'utilisation de shelldap est fortement -recommandée, en utilisant en binddn cn=admin,dc=example,dc=org et +recommandée, en utilisant en binddn et basedn tous deux égaux à 'cn=config' et binddpw le mot de passe admin. +Rajouter (exemple de chemin de fichier avec un certif LE): +`olcTLSCertificateKeyFile: /etc/letsencrypt/live/HOSTNAME/privkey.pem +olcTLSCACertificateFile: /etc/letsencrypt/live/HOSTNAME/chain.pem +olcTLSCertificateFile: /etc/letsencrypt/live/HOSTNAME/cert.pem ` + +Mettre à jour la partie ldap du `settings_local.py` (mettre 'TLS' à True +si besoin, user cn=config,dc=example,dc=org et mot de passe +ldap choisi précédemment). + ## Configuration initiale Normalement à cette étape, le ldap et la bdd sql sont configurées correctement. diff --git a/re2o/settings_local.example.py b/re2o/settings_local.example.py index ef1797cf..967386bb 100644 --- a/re2o/settings_local.example.py +++ b/re2o/settings_local.example.py @@ -48,6 +48,7 @@ DATABASES = { 'ENGINE': 'ldapdb.backends.ldap', 'NAME': 'ldap://ldap_host_ip/', 'USER': 'ldap_dn', + # 'TLS': True, 'PASSWORD': 'SUPER_SECRET_LDAP', } } From 5c9c9c3a29ad1d872c1f644fb078183049da944a Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Tue, 3 Oct 2017 02:36:39 +0200 Subject: [PATCH 23/37] Attribut ipv6 sur les interfaces --- machines/forms.py | 4 ++-- machines/migrations/0059_iptype_prefix_v6.py | 20 +++++++++++++++++++ machines/models.py | 17 +++++++++++++++- machines/templates/machines/aff_iptype.html | 2 ++ machines/templates/machines/aff_machines.html | 6 ++++-- .../migrations/0020_optionalmachine_ipv6.py | 20 +++++++++++++++++++ preferences/models.py | 1 + .../preferences/display_preferences.html | 4 +++- re2o/context_processors.py | 4 +++- 9 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 machines/migrations/0059_iptype_prefix_v6.py create mode 100644 preferences/migrations/0020_optionalmachine_ipv6.py diff --git a/machines/forms.py b/machines/forms.py index c29af9dd..8321db8a 100644 --- a/machines/forms.py +++ b/machines/forms.py @@ -142,7 +142,7 @@ class DelMachineTypeForm(Form): class IpTypeForm(ModelForm): class Meta: model = IpType - fields = ['type','extension','need_infra','domaine_ip_start','domaine_ip_stop', 'vlan'] + fields = ['type','extension','need_infra','domaine_ip_start','domaine_ip_stop', 'prefix_v6', 'vlan'] def __init__(self, *args, **kwargs): @@ -151,7 +151,7 @@ class IpTypeForm(ModelForm): class EditIpTypeForm(IpTypeForm): class Meta(IpTypeForm.Meta): - fields = ['extension','type','need_infra', 'vlan'] + fields = ['extension','type','need_infra', 'prefix_v6', 'vlan'] class DelIpTypeForm(Form): iptypes = forms.ModelMultipleChoiceField(queryset=IpType.objects.all(), label="Types d'ip actuelles", widget=forms.CheckboxSelectMultiple) diff --git a/machines/migrations/0059_iptype_prefix_v6.py b/machines/migrations/0059_iptype_prefix_v6.py new file mode 100644 index 00000000..464fc5e6 --- /dev/null +++ b/machines/migrations/0059_iptype_prefix_v6.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-10-02 16:33 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('machines', '0058_auto_20171002_0350'), + ] + + operations = [ + migrations.AddField( + model_name='iptype', + name='prefix_v6', + field=models.GenericIPAddressField(blank=True, null=True, protocol='IPv6'), + ), + ] diff --git a/machines/models.py b/machines/models.py index cb859141..8e7b1c3c 100644 --- a/machines/models.py +++ b/machines/models.py @@ -70,6 +70,7 @@ class IpType(models.Model): need_infra = models.BooleanField(default=False) domaine_ip_start = models.GenericIPAddressField(protocol='IPv4') domaine_ip_stop = models.GenericIPAddressField(protocol='IPv4') + prefix_v6 = models.GenericIPAddressField(protocol='IPv6', null=True, blank=True) vlan = models.ForeignKey('Vlan', on_delete=models.PROTECT, blank=True, null=True) @cached_property @@ -122,6 +123,9 @@ class IpType(models.Model): for element in IpType.objects.all().exclude(pk=self.pk): if not self.ip_set.isdisjoint(element.ip_set): raise ValidationError("Le range indiqué n'est pas disjoint des ranges existants") + # On formate le prefix v6 + if self.prefix_v6: + self.prefix_v6 = str(IPNetwork(self.prefix_v6 + '/64').network) return def save(self, *args, **kwargs): @@ -218,7 +222,6 @@ class Interface(models.Model): PRETTY_NAME = "Interface" ipv4 = models.OneToOneField('IpList', on_delete=models.PROTECT, blank=True, null=True) - #ipv6 = models.GenericIPAddressField(protocol='IPv6', null=True) mac_address = MACAddressField(integer=False, unique=True) machine = models.ForeignKey('Machine', on_delete=models.CASCADE) type = models.ForeignKey('MachineType', on_delete=models.PROTECT) @@ -232,6 +235,18 @@ class Interface(models.Model): user = self.machine.user return machine.active and user.has_access() + + @cached_property + def ipv6_object(self): + if self.type.ip_type.prefix_v6: + return EUI(self.mac_address).ipv6(IPNetwork(self.type.ip_type.prefix_v6).network) + else: + return None + + @cached_property + def ipv6(self): + return str(self.ipv6_object) + def mac_bare(self): return str(EUI(self.mac_address, dialect=mac_bare)).lower() diff --git a/machines/templates/machines/aff_iptype.html b/machines/templates/machines/aff_iptype.html index 46318c83..aafc4c1d 100644 --- a/machines/templates/machines/aff_iptype.html +++ b/machines/templates/machines/aff_iptype.html @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
  • Nécessite l'autorisation infra Début FinPréfixe v6 Sur vlan {{ type.need_infra }} {{ type.domaine_ip_start }} {{ type.domaine_ip_stop }}{{ type.prefix_v6 }} {{ type.vlan }} {% if is_infra %} diff --git a/machines/templates/machines/aff_machines.html b/machines/templates/machines/aff_machines.html index 6cf306f7..b9c8c9e9 100644 --- a/machines/templates/machines/aff_machines.html +++ b/machines/templates/machines/aff_machines.html @@ -34,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., Nom dns Type MacIpv4IP
    {{ interface.type }} {{ interface.mac_address }}{{ interface.ipv4 }}{{ interface.ipv4 }} + {{ interface.ipv6 }} +
    Alias dns autorisé par utilisateur {{ machineoptions.max_lambdauser_aliases }}
    Support de l'ipv6{{ machineoptions.ipv6 }}

    Préférences topologie

    {% if is_bureau %} diff --git a/re2o/context_processors.py b/re2o/context_processors.py index dd39b04b..ed4769b5 100644 --- a/re2o/context_processors.py +++ b/re2o/context_processors.py @@ -23,10 +23,11 @@ from __future__ import unicode_literals from machines.models import Interface, Machine -from preferences.models import GeneralOption +from preferences.models import GeneralOption, OptionalMachine def context_user(request): general_options, created = GeneralOption.objects.get_or_create() + machine_options, created = OptionalMachine.objects.get_or_create() user = request.user if user.is_authenticated(): interfaces = user.user_interfaces() @@ -54,4 +55,5 @@ def context_user(request): 'is_admin' : is_admin, 'interfaces': interfaces, 'site_name': general_options.site_name, + 'ipv6_enabled' : machine_options.ipv6, } From abbceb6abc5b65e831f54d11aa67e71ec8963fde Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Tue, 3 Oct 2017 04:13:48 +0200 Subject: [PATCH 24/37] =?UTF-8?q?Affichage=20que=20si=20ipv6=20activ=C3=A9?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- machines/templates/machines/aff_machines.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/machines/templates/machines/aff_machines.html b/machines/templates/machines/aff_machines.html index b9c8c9e9..c22de7c9 100644 --- a/machines/templates/machines/aff_machines.html +++ b/machines/templates/machines/aff_machines.html @@ -75,7 +75,9 @@ with this program; if not, write to the Free Software Foundation, Inc., {{ interface.type }} {{ interface.mac_address }} {{ interface.ipv4 }} + {% if ipv6_enabled %} {{ interface.ipv6 }} + {% endif %}