8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-12-26 08:53:46 +00:00

Utilisation de formset pour éditer une liste de ports.

This commit is contained in:
Hugo LEVY-FALK 2017-10-01 21:57:10 +02:00
parent c0a692ea21
commit b5c6330f54
4 changed files with 96 additions and 70 deletions

View file

@ -59,6 +59,7 @@ class EditInterfaceForm(ModelForm):
self.fields['mac_address'].label = 'Adresse mac' self.fields['mac_address'].label = 'Adresse mac'
self.fields['type'].label = 'Type de machine' self.fields['type'].label = 'Type de machine'
self.fields['type'].empty_label = "Séléctionner un type de machine" self.fields['type'].empty_label = "Séléctionner un type de machine"
self.fields['port_lists'].label = "Configuration des ports"
if "machine" in self.fields: if "machine" in self.fields:
self.fields['machine'].queryset = Machine.objects.all().select_related('user') self.fields['machine'].queryset = Machine.objects.all().select_related('user')
@ -231,68 +232,13 @@ class VlanForm(ModelForm):
class DelVlanForm(Form): class DelVlanForm(Form):
vlan = forms.ModelMultipleChoiceField(queryset=Vlan.objects.all(), label="Vlan actuels", widget=forms.CheckboxSelectMultiple) 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): 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: class Meta:
model = PortList model = PortList
fields = ['name'] fields = '__all__'
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

View file

@ -223,7 +223,7 @@ class Interface(models.Model):
machine = models.ForeignKey('Machine', on_delete=models.CASCADE) machine = models.ForeignKey('Machine', on_delete=models.CASCADE)
type = models.ForeignKey('MachineType', on_delete=models.PROTECT) type = models.ForeignKey('MachineType', on_delete=models.PROTECT)
details = models.CharField(max_length=255, blank=True) details = models.CharField(max_length=255, blank=True)
has_public_ip = False port_lists = models.ManyToManyField('PortList', blank=True)
@cached_property @cached_property
def is_active(self): def is_active(self):
@ -411,11 +411,10 @@ class Service_link(models.Model):
class PortList(models.Model): class PortList(models.Model):
"""Liste des ports ouverts sur une interface.""" """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) name = models.CharField(help_text="Nom de la configuration des ports.", max_length=255)
def __str__(self): def __str__(self):
return ', '.join(map(str, self.port_set.all())) return self.name
def tcp_ports_in(self): def tcp_ports_in(self):
return self.port_set.filter(protocole=Port.TCP, io=Port.IN) return self.port_set.filter(protocole=Port.TCP, io=Port.IN)

View file

@ -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 %}
<form class="form" method="post">
{% csrf_token %}
{% bootstrap_form port_list %}
{{ ports.management_form }}
<div id="formset">
{% for form in ports.forms %}
<div class="port">
<p>
{{ form }}
</p>
</div>
{% endfor %}
</div>
<p>
<input class="btn btn-primary btn-sm" role="button" value="Ajouter un port" id="add_one">
</p>
{% bootstrap_button "Créer ou modifier" button_type="submit" icon="star" %}
</form>
<script type="text/javascript">
var template = `{{ports.empty_form}}`;
function add_port(){
var new_index = document.getElementsByClassName('port').length;
document.getElementById('id_form-TOTAL_FORMS').value =
parseInt(document.getElementById('id_form-TOTAL_FORMS').value) + 1;
var new_port = document.createElement('div');
new_port.className = 'port';
new_port.innerHTML = template.replace(/__prefix__/g, new_index);
document.getElementById('formset').appendChild(new_port);
}
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("add_one").addEventListener("click", add_port, true);});
</script>
{% endblock %}

View file

@ -35,7 +35,7 @@ from django.template import Context, RequestContext, loader
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
from django.db.models import ProtectedError 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.db import transaction
from django.contrib.auth import authenticate, login from django.contrib.auth import authenticate, login
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
@ -48,8 +48,8 @@ from reversion.models import Version
import re import re
from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm, BaseEditInterfaceForm, BaseEditMachineForm from .forms import 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 EditIpTypeForm, IpTypeForm, DelIpTypeForm, DomainForm, AliasForm, DelAliasForm, NsForm, DelNsForm, TextForm, DelTextForm, MxForm, DelMxForm, VlanForm, DelVlanForm, ServiceForm, DelServiceForm, NasForm, DelNasForm
from .forms import EditPortListForm from .forms import EditPortListForm, EditPortForm
from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain, Service, Service_link, Vlan, Nas, Text, PortList 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 User
from users.models import all_has_access from users.models import all_has_access
from preferences.models import GeneralOption, OptionalMachine from preferences.models import GeneralOption, OptionalMachine
@ -928,11 +928,23 @@ def edit_portlist(request, pk):
messages.error(request, "Liste de ports inexistante") messages.error(request, "Liste de ports inexistante")
return redirect("/machines/index_portlist/") return redirect("/machines/index_portlist/")
port_list = EditPortListForm(request.POST or None, instance=port_list_instance) port_list = EditPortListForm(request.POST or None, instance=port_list_instance)
if port_list.is_valid(): port_formset = modelformset_factory(
port_list.save() 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") messages.success(request, "Liste de ports modifiée")
return redirect("/machines/index_portlist/") 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 @login_required
@permission_required('bureau') @permission_required('bureau')