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:
parent
22ff664d94
commit
bd4f0fafe3
13 changed files with 186 additions and 27 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
33
machines/migrations/0016_auto_20160708_1633.py
Normal file
33
machines/migrations/0016_auto_20160708_1633.py
Normal 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'),
|
||||||
|
),
|
||||||
|
]
|
21
machines/migrations/0017_auto_20160708_1645.py
Normal file
21
machines/migrations/0017_auto_20160708_1645.py
Normal 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,
|
||||||
|
),
|
||||||
|
]
|
|
@ -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)
|
||||||
|
|
15
machines/templates/machines/aff_extension.html
Normal file
15
machines/templates/machines/aff_extension.html
Normal 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>
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
15
machines/templates/machines/index_extension.html
Normal file
15
machines/templates/machines/index_extension.html
Normal 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 %}
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
|
@ -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'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -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})
|
||||||
|
|
|
@ -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/'
|
||||||
|
|
|
@ -17,4 +17,3 @@ DATABASES = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ALLOWED_EXTENSIONS = ['.example']
|
|
||||||
|
|
Loading…
Reference in a new issue