diff --git a/machines/admin.py b/machines/admin.py index 0122d746..02424537 100644 --- a/machines/admin.py +++ b/machines/admin.py @@ -1,12 +1,15 @@ from django.contrib import admin -from .models import Machine, MachineType, IpList, Interface +from .models import Machine, MachineType, IpList, Interface, Extension class MachineAdmin(admin.ModelAdmin): list_display = ('user','name','type','active') class MachineTypeAdmin(admin.ModelAdmin): - list_display = ('type',) + list_display = ('type','extension') + +class ExtensionAdmin(admin.ModelAdmin): + list_display = ('name',) class IpListAdmin(admin.ModelAdmin): list_display = ('ipv4',) @@ -16,5 +19,6 @@ class InterfaceAdmin(admin.ModelAdmin): admin.site.register(Machine, MachineAdmin) admin.site.register(MachineType, MachineTypeAdmin) +admin.site.register(Extension, ExtensionAdmin) admin.site.register(IpList, IpListAdmin) admin.site.register(Interface, InterfaceAdmin) diff --git a/machines/forms.py b/machines/forms.py index 57478ad4..cf62788e 100644 --- a/machines/forms.py +++ b/machines/forms.py @@ -1,6 +1,6 @@ from django.forms import ModelForm, Form, ValidationError from django import forms -from .models import Machine, Interface, MachineType +from .models import Machine, Interface, MachineType, Extension class EditMachineForm(ModelForm): class Meta: @@ -42,7 +42,7 @@ class NewInterfaceForm(EditInterfaceForm): class MachineTypeForm(ModelForm): class Meta: model = MachineType - fields = ['type'] + fields = ['type','extension'] def __init__(self, *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) class Meta: - exclude = ['type'] + exclude = ['type','extension'] 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 diff --git a/machines/migrations/0016_auto_20160708_1633.py b/machines/migrations/0016_auto_20160708_1633.py new file mode 100644 index 00000000..dddc1f09 --- /dev/null +++ b/machines/migrations/0016_auto_20160708_1633.py @@ -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'), + ), + ] diff --git a/machines/migrations/0017_auto_20160708_1645.py b/machines/migrations/0017_auto_20160708_1645.py new file mode 100644 index 00000000..d0d88915 --- /dev/null +++ b/machines/migrations/0017_auto_20160708_1645.py @@ -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, + ), + ] diff --git a/machines/models.py b/machines/models.py index 3d0c47d1..8475b45a 100644 --- a/machines/models.py +++ b/machines/models.py @@ -2,31 +2,30 @@ from django.db import models from django.forms import ValidationError from macaddress.fields import MACAddressField -from django.conf import settings import re -def full_domain_validator(hostname): - """ Validation du nom de domaine, extensions dans settings, prefixe pas plus long que 63 caractères """ +def full_domain_validator(interface): + """ 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-]+(? 63: + dns_short=re.sub('%s$' % allowed_extension, '', dns) + if len(dns_short) > 63: raise ValidationError( - ", le nom de domaine '%(label)s' est trop long (maximum de 63 caractères).", - params={'label': hostname}, + "Le nom de domaine '%(label)s' est trop long (maximum de 63 caractères).", + params={'label': dns}, ) - if not HOSTNAME_LABEL_PATTERN.match(hostname): + if not HOSTNAME_LABEL_PATTERN.match(dns_short): raise ValidationError( - ", ce nom de domaine '%(label)s' contient des carractères interdits.", - params={'label': hostname}, + "Ce nom de domaine '%(label)s' contient des carractères interdits.", + params={'label': dns}, ) + return dns class Machine(models.Model): user = models.ForeignKey('users.User', on_delete=models.PROTECT) @@ -39,10 +38,16 @@ class Machine(models.Model): class MachineType(models.Model): type = models.CharField(max_length=255) + extension = models.ForeignKey('Extension', on_delete=models.PROTECT) def __str__(self): return self.type +class Extension(models.Model): + name = models.CharField(max_length=255) + + def __str__(self): + return self.name class Interface(models.Model): 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) machine = models.ForeignKey('Machine', on_delete=models.PROTECT) 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): return self.dns def clean(self): - self.dns=self.dns.lower() + self.dns=full_domain_validator(self) class IpList(models.Model): ipv4 = models.GenericIPAddressField(protocol='IPv4', unique=True) diff --git a/machines/templates/machines/aff_extension.html b/machines/templates/machines/aff_extension.html new file mode 100644 index 00000000..b00972a3 --- /dev/null +++ b/machines/templates/machines/aff_extension.html @@ -0,0 +1,15 @@ + + + + + + + + {% for extension in extension_list %} + + + + + {% endfor %} +
Extension
{{ extension.name }} Editer
+ diff --git a/machines/templates/machines/aff_machinetype.html b/machines/templates/machines/aff_machinetype.html index 981d1b48..d951b329 100644 --- a/machines/templates/machines/aff_machinetype.html +++ b/machines/templates/machines/aff_machinetype.html @@ -2,12 +2,14 @@ Type de machine + Extension {% for type in machinetype_list %} {{ type.type }} + {{ type.extension }} Editer {% endfor %} diff --git a/machines/templates/machines/index_extension.html b/machines/templates/machines/index_extension.html new file mode 100644 index 00000000..1c867e26 --- /dev/null +++ b/machines/templates/machines/index_extension.html @@ -0,0 +1,15 @@ +{% extends "machines/sidebar.html" %} +{% load bootstrap3 %} + +{% block title %}Machines{% endblock %} + +{% block content %} +

Liste des extensions

+ Ajouter une extension + Supprimer une ou plusieurs extensions + {% include "machines/aff_extension.html" with extension_list=extension_list %} +
+
+
+{% endblock %} + diff --git a/machines/templates/machines/sidebar.html b/machines/templates/machines/sidebar.html index 117b8770..a321147b 100644 --- a/machines/templates/machines/sidebar.html +++ b/machines/templates/machines/sidebar.html @@ -2,4 +2,5 @@ {% block sidebar %}

Liste des types de machine

+

Liste des types des extensions

{% endblock %} diff --git a/machines/urls.py b/machines/urls.py index ff4bef8e..c80c3da6 100644 --- a/machines/urls.py +++ b/machines/urls.py @@ -10,5 +10,9 @@ urlpatterns = [ url(r'^edit_machinetype/(?P[0-9]+)$', views.edit_machinetype, name='edit-machinetype'), url(r'^del_machinetype/$', views.del_machinetype, name='del-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[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'), ] diff --git a/machines/views.py b/machines/views.py index 029baa10..dbfc217b 100644 --- a/machines/views.py +++ b/machines/views.py @@ -9,8 +9,8 @@ from django.contrib import messages from django.contrib.auth.decorators import login_required from django.db.models import ProtectedError -from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, NewInterfaceForm, MachineTypeForm, DelMachineTypeForm -from .models import Machine, Interface, IpList, MachineType +from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, NewInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm +from .models import Machine, Interface, IpList, MachineType, Extension from users.models import User def unassign_ips(user): @@ -147,6 +147,43 @@ def del_machinetype(request): return redirect("/machines/index_machinetype") 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 def index(request): interfaces_list = Interface.objects.order_by('pk') @@ -156,3 +193,8 @@ def index(request): def index_machinetype(request): machinetype_list = MachineType.objects.order_by('type') 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}) diff --git a/re2o/settings.py b/re2o/settings.py index fbd6c1d3..86b6547f 100644 --- a/re2o/settings.py +++ b/re2o/settings.py @@ -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, ...) 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__))) @@ -117,3 +117,5 @@ STATICFILES_DIRS = ( ) STATIC_URL = '/static/' + +LOGIN_URL = '/admin/' diff --git a/re2o/settings_local.example.py b/re2o/settings_local.example.py index 3da70fb2..fae7b8c8 100644 --- a/re2o/settings_local.example.py +++ b/re2o/settings_local.example.py @@ -17,4 +17,3 @@ DATABASES = { } } -ALLOWED_EXTENSIONS = ['.example']