mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-30 08:32:26 +00:00
422 lines
19 KiB
Python
422 lines
19 KiB
Python
# App de gestion des machines pour re2o
|
|
# Gabriel Détraz
|
|
# Gplv2
|
|
from django.http import HttpResponse
|
|
from django.shortcuts import render, redirect
|
|
from django.shortcuts import render_to_response, get_object_or_404
|
|
from django.core.context_processors import csrf
|
|
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
|
from django.template import Context, RequestContext, loader
|
|
from django.contrib import messages
|
|
from django.contrib.auth.decorators import login_required, permission_required
|
|
from django.db.models import ProtectedError
|
|
from django.forms import ValidationError
|
|
from django.db import transaction
|
|
|
|
from rest_framework.renderers import JSONRenderer
|
|
from machines.serializers import InterfaceSerializer
|
|
from reversion import revisions as reversion
|
|
|
|
|
|
import re
|
|
from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm, BaseEditInterfaceForm, BaseEditMachineForm
|
|
from .models import Machine, Interface, IpList, MachineType, Extension
|
|
from users.models import User
|
|
from re2o.settings import PAGINATION_NUMBER, PAGINATION_LARGE_NUMBER
|
|
|
|
def full_domain_validator(request, 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-]+(?<!-)$", re.IGNORECASE)
|
|
dns = interface.dns.lower()
|
|
allowed_extension = interface.type.extension.name
|
|
if not dns.endswith(allowed_extension):
|
|
messages.error(request,
|
|
"Le nom de domaine %s doit comporter une extension valide en %s" % (dns, allowed_extension) )
|
|
return False
|
|
dns_short=re.sub('%s$' % allowed_extension, '', dns)
|
|
if len(dns_short) > 63:
|
|
messages.error(request,
|
|
"Le nom de domaine %s est trop long (maximum de 63 caractères)." % dns)
|
|
return False
|
|
if not HOSTNAME_LABEL_PATTERN.match(dns_short):
|
|
messages.error(request,
|
|
"Ce nom de domaine %s contient des carractères interdits." % dns)
|
|
return False
|
|
return True
|
|
|
|
def unassign_ips(user):
|
|
machines = Interface.objects.filter(machine=Machine.objects.filter(user=user))
|
|
for machine in machines:
|
|
unassign_ipv4(machine)
|
|
return
|
|
|
|
def assign_ips(user):
|
|
""" Assign une ipv4 aux machines d'un user """
|
|
machines = Interface.objects.filter(machine=Machine.objects.filter(user=user))
|
|
for machine in machines:
|
|
if not machine.ipv4:
|
|
interface = assign_ipv4(machine)
|
|
with transaction.atomic(), reversion.create_revision():
|
|
reversion.set_comment("Assignation ipv4")
|
|
interface.save()
|
|
return
|
|
|
|
def free_ip():
|
|
""" Renvoie la liste des ip disponibles """
|
|
return IpList.objects.filter(interface__isnull=True)
|
|
|
|
def assign_ipv4(interface):
|
|
""" Assigne une ip à l'interface """
|
|
free_ips = free_ip()
|
|
if free_ips:
|
|
interface.ipv4 = free_ips[0]
|
|
return interface
|
|
|
|
def unassign_ipv4(interface):
|
|
interface.ipv4 = None
|
|
with transaction.atomic(), reversion.create_revision():
|
|
reversion.set_comment("Désassignation ipv4")
|
|
interface.save()
|
|
|
|
def form(ctx, template, request):
|
|
c = ctx
|
|
c.update(csrf(request))
|
|
return render_to_response(template, c, context_instance=RequestContext(request))
|
|
|
|
@login_required
|
|
def new_machine(request, userid):
|
|
try:
|
|
user = User.objects.get(pk=userid)
|
|
except User.DoesNotExist:
|
|
messages.error(request, u"Utilisateur inexistant" )
|
|
return redirect("/machines/")
|
|
if not request.user.has_perms(('cableur',)) and user != request.user:
|
|
messages.error(request, "Vous ne pouvez pas ajouter une machine à un autre user que vous sans droit")
|
|
return redirect("/users/profil/" + str(request.user.id))
|
|
machine = NewMachineForm(request.POST or None)
|
|
interface = AddInterfaceForm(request.POST or None)
|
|
if machine.is_valid() and interface.is_valid():
|
|
new_machine = machine.save(commit=False)
|
|
new_machine.user = user
|
|
new_interface = interface.save(commit=False)
|
|
if full_domain_validator(request, new_interface):
|
|
with transaction.atomic(), reversion.create_revision():
|
|
new_machine.save()
|
|
reversion.set_user(request.user)
|
|
reversion.set_comment("Création")
|
|
new_interface.machine = new_machine
|
|
if free_ip() and not new_interface.ipv4:
|
|
new_interface = assign_ipv4(new_interface)
|
|
elif not new_interface.ipv4:
|
|
messages.error(request, u"Il n'y a plus d'ip disponibles")
|
|
with transaction.atomic(), reversion.create_revision():
|
|
new_interface.save()
|
|
reversion.set_user(request.user)
|
|
reversion.set_comment("Création")
|
|
messages.success(request, "La machine a été crée")
|
|
return redirect("/users/profil/" + userid)
|
|
return form({'machineform': machine, 'interfaceform': interface}, 'machines/machine.html', request)
|
|
|
|
@login_required
|
|
def edit_interface(request, interfaceid):
|
|
try:
|
|
interface = Interface.objects.get(pk=interfaceid)
|
|
except Interface.DoesNotExist:
|
|
messages.error(request, u"Interface inexistante" )
|
|
return redirect("/machines")
|
|
if not request.user.has_perms(('cableur',)):
|
|
if interface.machine.user != request.user:
|
|
messages.error(request, "Vous ne pouvez pas éditer une machine d'un autre user que vous sans droit")
|
|
return redirect("/users/profil/" + str(request.user.id))
|
|
machine_form = BaseEditMachineForm(request.POST or None, instance=interface.machine)
|
|
interface_form = BaseEditInterfaceForm(request.POST or None, instance=interface)
|
|
else:
|
|
machine_form = EditMachineForm(request.POST or None, instance=interface.machine)
|
|
interface_form = EditInterfaceForm(request.POST or None, instance=interface)
|
|
if machine_form.is_valid() and interface_form.is_valid():
|
|
new_interface = interface_form.save(commit=False)
|
|
new_machine = machine_form.save(commit=False)
|
|
if full_domain_validator(request, new_interface):
|
|
with transaction.atomic(), reversion.create_revision():
|
|
new_machine.save()
|
|
reversion.set_user(request.user)
|
|
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in machine_form.changed_data))
|
|
with transaction.atomic(), reversion.create_revision():
|
|
new_interface.save()
|
|
reversion.set_user(request.user)
|
|
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in interface_form.changed_data))
|
|
messages.success(request, "La machine a été modifiée")
|
|
return redirect("/users/profil/" + str(interface.machine.user.id))
|
|
return form({'machineform': machine_form, 'interfaceform': interface_form}, 'machines/machine.html', request)
|
|
|
|
@login_required
|
|
def del_machine(request, machineid):
|
|
try:
|
|
machine = Machine.objects.get(pk=machineid)
|
|
except Machine.DoesNotExist:
|
|
messages.error(request, u"Machine inexistante" )
|
|
return redirect("/machines")
|
|
if not request.user.has_perms(('cableur',)):
|
|
if machine.user != request.user:
|
|
messages.error(request, "Vous ne pouvez pas éditer une machine d'un autre user que vous sans droit")
|
|
return redirect("/users/profil/" + str(request.user.id))
|
|
if request.method == "POST":
|
|
with transaction.atomic(), reversion.create_revision():
|
|
machine.delete()
|
|
reversion.set_user(request.user)
|
|
messages.success(request, "La machine a été détruite")
|
|
return redirect("/users/profil/" + str(request.user.id))
|
|
return form({'objet': machine, 'objet_name': 'machine'}, 'machines/delete.html', request)
|
|
|
|
@login_required
|
|
def new_interface(request, machineid):
|
|
try:
|
|
machine = Machine.objects.get(pk=machineid)
|
|
except Machine.DoesNotExist:
|
|
messages.error(request, u"Machine inexistante" )
|
|
return redirect("/machines")
|
|
if not request.user.has_perms(('cableur',)):
|
|
if machine.user != request.user:
|
|
messages.error(request, "Vous ne pouvez pas ajouter une interface à une machine d'un autre user que vous sans droit")
|
|
return redirect("/users/profil/" + str(request.user.id))
|
|
interface_form = AddInterfaceForm(request.POST or None)
|
|
if interface_form.is_valid():
|
|
new_interface = interface_form.save(commit=False)
|
|
new_interface.machine = machine
|
|
if full_domain_validator(request, new_interface):
|
|
if free_ip() and not new_interface.ipv4:
|
|
new_interface = assign_ipv4(new_interface)
|
|
elif not new_interface.ipv4:
|
|
messages.error(request, u"Il n'y a plus d'ip disponibles")
|
|
with transaction.atomic(), reversion.create_revision():
|
|
new_interface.save()
|
|
reversion.set_user(request.user)
|
|
reversion.set_comment("Création")
|
|
messages.success(request, "L'interface a été ajoutée")
|
|
return redirect("/users/profil/" + str(request.user.id))
|
|
return form({'interfaceform': interface_form}, 'machines/machine.html', request)
|
|
|
|
@login_required
|
|
def del_interface(request, interfaceid):
|
|
try:
|
|
interface = Interface.objects.get(pk=interfaceid)
|
|
except Interface.DoesNotExist:
|
|
messages.error(request, u"Interface inexistante" )
|
|
return redirect("/machines")
|
|
if not request.user.has_perms(('cableur',)):
|
|
if interface.machine.user != request.user:
|
|
messages.error(request, "Vous ne pouvez pas éditer une machine d'un autre user que vous sans droit")
|
|
return redirect("/users/profil/" + str(request.user.id))
|
|
if request.method == "POST":
|
|
with transaction.atomic(), reversion.create_revision():
|
|
interface.delete()
|
|
reversion.set_user(request.user)
|
|
messages.success(request, "L'interface a été détruite")
|
|
return redirect("/users/profil/" + str(request.user.id))
|
|
return form({'objet': interface, 'objet_name': 'interface'}, 'machines/delete.html', request)
|
|
|
|
@login_required
|
|
@permission_required('infra')
|
|
def add_machinetype(request):
|
|
machinetype = MachineTypeForm(request.POST or None)
|
|
if machinetype.is_valid():
|
|
with transaction.atomic(), reversion.create_revision():
|
|
machinetype.save()
|
|
reversion.set_user(request.user)
|
|
reversion.set_comment("Création")
|
|
messages.success(request, "Ce type de machine a été ajouté")
|
|
return redirect("/machines/index_machinetype")
|
|
return form({'machineform': machinetype, 'interfaceform': None}, 'machines/machine.html', request)
|
|
|
|
@login_required
|
|
@permission_required('infra')
|
|
def edit_machinetype(request, machinetypeid):
|
|
try:
|
|
machinetype_instance = MachineType.objects.get(pk=machinetypeid)
|
|
except MachineType.DoesNotExist:
|
|
messages.error(request, u"Entrée inexistante" )
|
|
return redirect("/machines/index_machinetype/")
|
|
machinetype = MachineTypeForm(request.POST or None, instance=machinetype_instance)
|
|
if machinetype.is_valid():
|
|
with transaction.atomic(), reversion.create_revision():
|
|
machinetype.save()
|
|
reversion.set_user(request.user)
|
|
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in machinetype.changed_data))
|
|
messages.success(request, "Type de machine modifié")
|
|
return redirect("/machines/index_machinetype/")
|
|
return form({'machineform': machinetype}, 'machines/machine.html', request)
|
|
|
|
@login_required
|
|
@permission_required('infra')
|
|
def del_machinetype(request):
|
|
machinetype = DelMachineTypeForm(request.POST or None)
|
|
if machinetype.is_valid():
|
|
machinetype_dels = machinetype.cleaned_data['machinetypes']
|
|
for machinetype_del in machinetype_dels:
|
|
try:
|
|
with transaction.atomic(), reversion.create_revision():
|
|
machinetype_del.delete()
|
|
reversion.set_user(request.user)
|
|
messages.success(request, "Le type de machine a été supprimé")
|
|
except ProtectedError:
|
|
messages.error(request, "Le type de machine %s est affectée à au moins une machine, vous ne pouvez pas le supprimer" % machinetype_del)
|
|
return redirect("/machines/index_machinetype")
|
|
return form({'machineform': machinetype, 'interfaceform': None}, 'machines/machine.html', request)
|
|
|
|
@login_required
|
|
@permission_required('infra')
|
|
def add_extension(request):
|
|
extension = ExtensionForm(request.POST or None)
|
|
if extension.is_valid():
|
|
with transaction.atomic(), reversion.create_revision():
|
|
extension.save()
|
|
reversion.set_user(request.user)
|
|
reversion.set_comment("Création")
|
|
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
|
|
@permission_required('infra')
|
|
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():
|
|
with transaction.atomic(), reversion.create_revision():
|
|
extension.save()
|
|
reversion.set_user(request.user)
|
|
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in extension.changed_data))
|
|
messages.success(request, "Extension modifiée")
|
|
return redirect("/machines/index_extension/")
|
|
return form({'machineform': extension}, 'machines/machine.html', request)
|
|
|
|
@login_required
|
|
@permission_required('infra')
|
|
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:
|
|
with transaction.atomic(), reversion.create_revision():
|
|
extension_del.delete()
|
|
reversion.set_user(request.user)
|
|
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
|
|
@permission_required('cableur')
|
|
def index(request):
|
|
machines_list = Machine.objects.order_by('pk')
|
|
paginator = Paginator(machines_list, PAGINATION_LARGE_NUMBER)
|
|
page = request.GET.get('page')
|
|
try:
|
|
machines_list = paginator.page(page)
|
|
except PageNotAnInteger:
|
|
# If page is not an integer, deliver first page.
|
|
machines_list = paginator.page(1)
|
|
except EmptyPage:
|
|
# If page is out of range (e.g. 9999), deliver last page of results.
|
|
machines_list = paginator.page(paginator.num_pages)
|
|
return render(request, 'machines/index.html', {'machines_list': machines_list})
|
|
|
|
@login_required
|
|
@permission_required('cableur')
|
|
def index_machinetype(request):
|
|
machinetype_list = MachineType.objects.order_by('type')
|
|
return render(request, 'machines/index_machinetype.html', {'machinetype_list':machinetype_list})
|
|
|
|
@login_required
|
|
@permission_required('cableur')
|
|
def index_extension(request):
|
|
extension_list = Extension.objects.order_by('name')
|
|
return render(request, 'machines/index_extension.html', {'extension_list':extension_list})
|
|
|
|
@login_required
|
|
def history(request, object, id):
|
|
if object == 'machine':
|
|
try:
|
|
object_instance = Machine.objects.get(pk=id)
|
|
except Machine.DoesNotExist:
|
|
messages.error(request, "Machine inexistante")
|
|
return redirect("/machines/")
|
|
if not request.user.has_perms(('cableur',)) and object_instance.user != request.user:
|
|
messages.error(request, "Vous ne pouvez pas afficher l'historique d'une machine d'un autre user que vous sans droit cableur")
|
|
return redirect("/users/profil/" + str(request.user.id))
|
|
elif object == 'interface':
|
|
try:
|
|
object_instance = Interface.objects.get(pk=id)
|
|
except Interface.DoesNotExist:
|
|
messages.error(request, "Interface inexistante")
|
|
return redirect("/machines/")
|
|
if not request.user.has_perms(('cableur',)) and object_instance.machine.user != request.user:
|
|
messages.error(request, "Vous ne pouvez pas afficher l'historique d'une interface d'un autre user que vous sans droit cableur")
|
|
return redirect("/users/profil/" + str(request.user.id))
|
|
elif object == 'machinetype' and request.user.has_perms(('cableur',)):
|
|
try:
|
|
object_instance = MachineType.objects.get(pk=id)
|
|
except MachineType.DoesNotExist:
|
|
messages.error(request, "Type de machine inexistant")
|
|
return redirect("/machines/")
|
|
elif object == 'extension' and request.user.has_perms(('cableur',)):
|
|
try:
|
|
object_instance = Extension.objects.get(pk=id)
|
|
except Extension.DoesNotExist:
|
|
messages.error(request, "Extension inexistante")
|
|
return redirect("/machines/")
|
|
else:
|
|
messages.error(request, "Objet inconnu")
|
|
return redirect("/machines/")
|
|
reversions = reversion.get_for_object(object_instance)
|
|
paginator = Paginator(reversions, PAGINATION_NUMBER)
|
|
page = request.GET.get('page')
|
|
try:
|
|
reversions = paginator.page(page)
|
|
except PageNotAnInteger:
|
|
# If page is not an integer, deliver first page.
|
|
reversions = paginator.page(1)
|
|
except EmptyPage:
|
|
# If page is out of range (e.g. 9999), deliver last page of results.
|
|
reversions = paginator.page(paginator.num_pages)
|
|
return render(request, 're2o/history.html', {'reversions': reversions, 'object': object_instance})
|
|
|
|
|
|
""" Framework Rest """
|
|
|
|
class JSONResponse(HttpResponse):
|
|
def __init__(self, data, **kwargs):
|
|
for d in data:
|
|
if d["ipv4"]:
|
|
d["ipv4"]= IpList.objects.get(pk=d["ipv4"]).__str__()
|
|
content = JSONRenderer().render(data)
|
|
kwargs['content_type'] = 'application/json'
|
|
super(JSONResponse, self).__init__(content, **kwargs)
|
|
|
|
|
|
def interface_list(request):
|
|
interfaces = Interface.objects.all()
|
|
interface = []
|
|
for i in interfaces :
|
|
if i.ipv4 and i.is_active():
|
|
interface.append(i)
|
|
seria = InterfaceSerializer(interface, many=True)
|
|
return seria.data
|
|
|
|
def mac_ip(request):
|
|
seria = interface_list(request)
|
|
for s in seria:
|
|
s.pop('dns')
|
|
return JSONResponse(seria)
|
|
|
|
def dns_ip(request):
|
|
seria = interface_list(request)
|
|
for s in seria:
|
|
s.pop('mac_address')
|
|
return JSONResponse(seria)
|