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:
parent
c0a692ea21
commit
b5c6330f54
4 changed files with 96 additions and 70 deletions
|
@ -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
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
69
machines/templates/machines/edit_portlist.html
Normal file
69
machines/templates/machines/edit_portlist.html
Normal 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 %}
|
|
@ -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')
|
||||||
|
|
Loading…
Reference in a new issue