8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-30 00:22:25 +00:00

Gestion des extensions avec un modèle

This commit is contained in:
Gabriel Detraz 2016-07-08 17:54:06 +02:00
parent 22ff664d94
commit bd4f0fafe3
13 changed files with 186 additions and 27 deletions

View file

@ -1,12 +1,15 @@
from django.contrib import admin from django.contrib import admin
from .models import Machine, MachineType, IpList, Interface from .models import Machine, MachineType, IpList, Interface, Extension
class MachineAdmin(admin.ModelAdmin): class MachineAdmin(admin.ModelAdmin):
list_display = ('user','name','type','active') list_display = ('user','name','type','active')
class MachineTypeAdmin(admin.ModelAdmin): class MachineTypeAdmin(admin.ModelAdmin):
list_display = ('type',) list_display = ('type','extension')
class ExtensionAdmin(admin.ModelAdmin):
list_display = ('name',)
class IpListAdmin(admin.ModelAdmin): class IpListAdmin(admin.ModelAdmin):
list_display = ('ipv4',) list_display = ('ipv4',)
@ -16,5 +19,6 @@ class InterfaceAdmin(admin.ModelAdmin):
admin.site.register(Machine, MachineAdmin) admin.site.register(Machine, MachineAdmin)
admin.site.register(MachineType, MachineTypeAdmin) admin.site.register(MachineType, MachineTypeAdmin)
admin.site.register(Extension, ExtensionAdmin)
admin.site.register(IpList, IpListAdmin) admin.site.register(IpList, IpListAdmin)
admin.site.register(Interface, InterfaceAdmin) admin.site.register(Interface, InterfaceAdmin)

View file

@ -1,6 +1,6 @@
from django.forms import ModelForm, Form, ValidationError from django.forms import ModelForm, Form, ValidationError
from django import forms from django import forms
from .models import Machine, Interface, MachineType from .models import Machine, Interface, MachineType, Extension
class EditMachineForm(ModelForm): class EditMachineForm(ModelForm):
class Meta: class Meta:
@ -42,7 +42,7 @@ class NewInterfaceForm(EditInterfaceForm):
class MachineTypeForm(ModelForm): class MachineTypeForm(ModelForm):
class Meta: class Meta:
model = MachineType model = MachineType
fields = ['type'] fields = ['type','extension']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(MachineTypeForm, self).__init__(*args, **kwargs) super(MachineTypeForm, self).__init__(*args, **kwargs)
@ -52,5 +52,21 @@ class DelMachineTypeForm(ModelForm):
machinetypes = forms.ModelMultipleChoiceField(queryset=MachineType.objects.all(), label="Types de machines actuelles", widget=forms.CheckboxSelectMultiple) machinetypes = forms.ModelMultipleChoiceField(queryset=MachineType.objects.all(), label="Types de machines actuelles", widget=forms.CheckboxSelectMultiple)
class Meta: class Meta:
exclude = ['type'] exclude = ['type','extension']
model = MachineType model = MachineType
class ExtensionForm(ModelForm):
class Meta:
model = Extension
fields = ['name']
def __init__(self, *args, **kwargs):
super(ExtensionForm, self).__init__(*args, **kwargs)
self.fields['name'].label = 'Exstension à ajouter'
class DelExtensionForm(ModelForm):
extensions = forms.ModelMultipleChoiceField(queryset=Extension.objects.all(), label="Extensions actuelles", widget=forms.CheckboxSelectMultiple)
class Meta:
exclude = ['name']
model = Extension

View file

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import machines.models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('machines', '0015_auto_20160707_0105'),
]
operations = [
migrations.CreateModel(
name='Extension',
fields=[
('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=False, auto_created=True)),
('name', models.CharField(max_length=255)),
],
),
migrations.AlterField(
model_name='interface',
name='dns',
field=models.CharField(unique=True, max_length=255, validators=[machines.models.full_domain_validator], help_text="Obligatoire et unique, doit se terminer en .rez et ne pas comporter d'autres points"),
),
migrations.AddField(
model_name='machinetype',
name='extension',
field=models.ForeignKey(null=True, blank=True, on_delete=django.db.models.deletion.PROTECT, to='machines.Extension'),
),
]

View file

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('machines', '0016_auto_20160708_1633'),
]
operations = [
migrations.AlterField(
model_name='machinetype',
name='extension',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, default=1, to='machines.Extension'),
preserve_default=False,
),
]

View file

@ -2,31 +2,30 @@ from django.db import models
from django.forms import ValidationError from django.forms import ValidationError
from macaddress.fields import MACAddressField from macaddress.fields import MACAddressField
from django.conf import settings
import re import re
def full_domain_validator(hostname): def full_domain_validator(interface):
""" Validation du nom de domaine, extensions dans settings, prefixe pas plus long que 63 caractères """ """ Validation du nom de domaine, extensions dans type de machine, prefixe pas plus long que 63 caractères """
HOSTNAME_LABEL_PATTERN = re.compile("(?!-)[A-Z\d-]+(?<!-)$", re.IGNORECASE) HOSTNAME_LABEL_PATTERN = re.compile("(?!-)[A-Z\d-]+(?<!-)$", re.IGNORECASE)
if not any(ext in hostname for ext in settings.ALLOWED_EXTENSIONS): dns = interface.dns.lower()
allowed_extension = interface.machine.type.extension.name
if not dns.endswith(allowed_extension):
raise ValidationError( raise ValidationError(
", le nom de domaine '%(label)s' doit comporter une extension valide", "Le nom de domaine '%(label)s' doit comporter une extension valide en '%(extension)s'",
params={'label': hostname}, params={'label': dns, 'extension': allowed_extension},
) )
for extension in settings.ALLOWED_EXTENSIONS: dns_short=re.sub('%s$' % allowed_extension, '', dns)
if hostname.endswith(extension): if len(dns_short) > 63:
hostname=re.sub('%s$' % extension, '', hostname)
break
if len(hostname) > 63:
raise ValidationError( raise ValidationError(
", le nom de domaine '%(label)s' est trop long (maximum de 63 caractères).", "Le nom de domaine '%(label)s' est trop long (maximum de 63 caractères).",
params={'label': hostname}, params={'label': dns},
) )
if not HOSTNAME_LABEL_PATTERN.match(hostname): if not HOSTNAME_LABEL_PATTERN.match(dns_short):
raise ValidationError( raise ValidationError(
", ce nom de domaine '%(label)s' contient des carractères interdits.", "Ce nom de domaine '%(label)s' contient des carractères interdits.",
params={'label': hostname}, params={'label': dns},
) )
return dns
class Machine(models.Model): class Machine(models.Model):
user = models.ForeignKey('users.User', on_delete=models.PROTECT) user = models.ForeignKey('users.User', on_delete=models.PROTECT)
@ -39,10 +38,16 @@ class Machine(models.Model):
class MachineType(models.Model): class MachineType(models.Model):
type = models.CharField(max_length=255) type = models.CharField(max_length=255)
extension = models.ForeignKey('Extension', on_delete=models.PROTECT)
def __str__(self): def __str__(self):
return self.type return self.type
class Extension(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Interface(models.Model): class Interface(models.Model):
ipv4 = models.OneToOneField('IpList', on_delete=models.PROTECT, blank=True, null=True) ipv4 = models.OneToOneField('IpList', on_delete=models.PROTECT, blank=True, null=True)
@ -50,13 +55,13 @@ class Interface(models.Model):
mac_address = MACAddressField(integer=False, unique=True) mac_address = MACAddressField(integer=False, unique=True)
machine = models.ForeignKey('Machine', on_delete=models.PROTECT) machine = models.ForeignKey('Machine', on_delete=models.PROTECT)
details = models.CharField(max_length=255, blank=True) details = models.CharField(max_length=255, blank=True)
dns = models.CharField(help_text="Obligatoire et unique, doit se terminer en %s et ne pas comporter d'autres points" % ", ".join(settings.ALLOWED_EXTENSIONS), max_length=255, unique=True, validators=[full_domain_validator]) dns = models.CharField(help_text="Obligatoire et unique, doit se terminer en %s et ne pas comporter d'autres points" % ", ".join(Extension.objects.values_list('name', flat=True)), max_length=255, unique=True)
def __str__(self): def __str__(self):
return self.dns return self.dns
def clean(self): def clean(self):
self.dns=self.dns.lower() self.dns=full_domain_validator(self)
class IpList(models.Model): class IpList(models.Model):
ipv4 = models.GenericIPAddressField(protocol='IPv4', unique=True) ipv4 = models.GenericIPAddressField(protocol='IPv4', unique=True)

View file

@ -0,0 +1,15 @@
<table class="table table-striped">
<thead>
<tr>
<th>Extension</th>
<th></th>
</tr>
</thead>
{% for extension in extension_list %}
<tr>
<td>{{ extension.name }}</td>
<td><a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:edit-extension' extension.id %}"><i class="glyphicon glyphicon-pushpin"></i> Editer</a></td>
</tr>
{% endfor %}
</table>

View file

@ -2,12 +2,14 @@
<thead> <thead>
<tr> <tr>
<th>Type de machine</th> <th>Type de machine</th>
<th>Extension</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
{% for type in machinetype_list %} {% for type in machinetype_list %}
<tr> <tr>
<td>{{ type.type }}</td> <td>{{ type.type }}</td>
<td>{{ type.extension }}</td>
<td><a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:edit-machinetype' type.id %}"><i class="glyphicon glyphicon-pushpin"></i> Editer</a></td> <td><a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:edit-machinetype' type.id %}"><i class="glyphicon glyphicon-pushpin"></i> Editer</a></td>
</tr> </tr>
{% endfor %} {% endfor %}

View file

@ -0,0 +1,15 @@
{% extends "machines/sidebar.html" %}
{% load bootstrap3 %}
{% block title %}Machines{% endblock %}
{% block content %}
<h2>Liste des extensions</h2>
<a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:add-extension' %}"><i class="glyphicon glyphicon-plus"></i> Ajouter une extension</a>
<a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:del-extension' %}"><i class="glyphicon glyphicon-trash"></i> Supprimer une ou plusieurs extensions</a>
{% include "machines/aff_extension.html" with extension_list=extension_list %}
<br />
<br />
<br />
{% endblock %}

View file

@ -2,4 +2,5 @@
{% block sidebar %} {% block sidebar %}
<p><a href="{% url "machines:index-machinetype" %}">Liste des types de machine</a></p> <p><a href="{% url "machines:index-machinetype" %}">Liste des types de machine</a></p>
<p><a href="{% url "machines:index-extension" %}">Liste des types des extensions</a></p>
{% endblock %} {% endblock %}

View file

@ -10,5 +10,9 @@ urlpatterns = [
url(r'^edit_machinetype/(?P<machinetypeid>[0-9]+)$', views.edit_machinetype, name='edit-machinetype'), url(r'^edit_machinetype/(?P<machinetypeid>[0-9]+)$', views.edit_machinetype, name='edit-machinetype'),
url(r'^del_machinetype/$', views.del_machinetype, name='del-machinetype'), url(r'^del_machinetype/$', views.del_machinetype, name='del-machinetype'),
url(r'^index_machinetype/$', views.index_machinetype, name='index-machinetype'), url(r'^index_machinetype/$', views.index_machinetype, name='index-machinetype'),
url(r'^add_extension/$', views.add_extension, name='add-extension'),
url(r'^edit_extension/(?P<extensionid>[0-9]+)$', views.edit_extension, name='edit-extension'),
url(r'^del_extension/$', views.del_extension, name='del-extension'),
url(r'^index_extension/$', views.index_extension, name='index-extension'),
url(r'^$', views.index, name='index'), url(r'^$', views.index, name='index'),
] ]

View file

@ -9,8 +9,8 @@ from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.db.models import ProtectedError from django.db.models import ProtectedError
from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, NewInterfaceForm, MachineTypeForm, DelMachineTypeForm from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, NewInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm
from .models import Machine, Interface, IpList, MachineType from .models import Machine, Interface, IpList, MachineType, Extension
from users.models import User from users.models import User
def unassign_ips(user): def unassign_ips(user):
@ -147,6 +147,43 @@ def del_machinetype(request):
return redirect("/machines/index_machinetype") return redirect("/machines/index_machinetype")
return form({'machineform': machinetype, 'interfaceform': None}, 'machines/machine.html', request) return form({'machineform': machinetype, 'interfaceform': None}, 'machines/machine.html', request)
@login_required
def add_extension(request):
extension = ExtensionForm(request.POST or None)
if extension.is_valid():
extension.save()
messages.success(request, "Cette extension a été ajoutée")
return redirect("/machines/index_extension")
return form({'machineform': extension, 'interfaceform': None}, 'machines/machine.html', request)
@login_required
def edit_extension(request, extensionid):
try:
extension_instance = Extension.objects.get(pk=extensionid)
except Extension.DoesNotExist:
messages.error(request, u"Entrée inexistante" )
return redirect("/machines/index_extension/")
extension = ExtensionForm(request.POST or None, instance=extension_instance)
if extension.is_valid():
extension.save()
messages.success(request, "Extension modifiée")
return redirect("/machines/index_extension/")
return form({'machineform': extension}, 'machines/machine.html', request)
@login_required
def del_extension(request):
extension = DelExtensionForm(request.POST or None)
if extension.is_valid():
extension_dels = extension.cleaned_data['extensions']
for extension_del in extension_dels:
try:
extension_del.delete()
messages.success(request, "L'extension a été supprimée")
except ProtectedError:
messages.error(request, "L'extension %s est affectée à au moins un type de machine, vous ne pouvez pas la supprimer" % extension_del)
return redirect("/machines/index_extension")
return form({'machineform': extension, 'interfaceform': None}, 'machines/machine.html', request)
@login_required @login_required
def index(request): def index(request):
interfaces_list = Interface.objects.order_by('pk') interfaces_list = Interface.objects.order_by('pk')
@ -156,3 +193,8 @@ def index(request):
def index_machinetype(request): def index_machinetype(request):
machinetype_list = MachineType.objects.order_by('type') machinetype_list = MachineType.objects.order_by('type')
return render(request, 'machines/index_machinetype.html', {'machinetype_list':machinetype_list}) return render(request, 'machines/index_machinetype.html', {'machinetype_list':machinetype_list})
@login_required
def index_extension(request):
extension_list = Extension.objects.order_by('name')
return render(request, 'machines/index_extension.html', {'extension_list':extension_list})

View file

@ -12,7 +12,7 @@ https://docs.djangoproject.com/en/1.8/ref/settings/
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os import os
from .settings_local import SECRET_KEY, DATABASES, DEBUG, ALLOWED_HOSTS, ALLOWED_EXTENSIONS from .settings_local import SECRET_KEY, DATABASES, DEBUG, ALLOWED_HOSTS
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@ -117,3 +117,5 @@ STATICFILES_DIRS = (
) )
STATIC_URL = '/static/' STATIC_URL = '/static/'
LOGIN_URL = '/admin/'

View file

@ -17,4 +17,3 @@ DATABASES = {
} }
} }
ALLOWED_EXTENSIONS = ['.example']