Ce serveur Gitlab sera éteint le 30 juin 2020, pensez à migrer vos projets vers les serveurs gitlab-research.centralesupelec.fr et gitlab-student.centralesupelec.fr !

views.py 44.2 KB
Newer Older
1
# -*- mode: python; coding: utf-8 -*-
2 3 4 5 6 7 8
# 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
9
# Copyright © 2017  Maël Kervella
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
#
# 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.

25
# App de gestion des machines pour re2o
Dalahro's avatar
Dalahro committed
26
# Gabriel Détraz, Augustin Lemesle
27
# Gplv2
28 29 30

from __future__ import unicode_literals

31
from django.urls import reverse
Dalahro's avatar
Dalahro committed
32
from django.http import HttpResponse
33
from django.shortcuts import render, redirect
34 35
from django.shortcuts import get_object_or_404
from django.template.context_processors import csrf
36
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
37 38
from django.template import Context, RequestContext, loader
from django.contrib import messages
39
from django.contrib.auth.decorators import login_required, permission_required
40
from django.db.models import ProtectedError, F
41
from django.forms import ValidationError, modelformset_factory
Dalahro's avatar
Dalahro committed
42 43
from django.contrib.auth import authenticate, login
from django.views.decorators.csrf import csrf_exempt
44

Dalahro's avatar
Dalahro committed
45
from rest_framework.renderers import JSONRenderer
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
46 47 48 49
from machines.serializers import ( FullInterfaceSerializer,
    InterfaceSerializer,
    TypeSerializer,
    DomainSerializer,
Gabriel Detraz's avatar
Gabriel Detraz committed
50
    TxtSerializer,
Gabriel Detraz's avatar
Gabriel Detraz committed
51
    SrvSerializer,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
52 53 54 55 56 57
    MxSerializer,
    ExtensionSerializer,
    ServiceServersSerializer,
    NsSerializer,
    OuverturePortsSerializer
)
58
from reversion import revisions as reversion
root's avatar
root committed
59
from reversion.models import Version
Dalahro's avatar
Dalahro committed
60

61
import re
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
from .forms import (
    NewMachineForm,
    EditMachineForm,
    EditInterfaceForm,
    AddInterfaceForm,
    MachineTypeForm,
    DelMachineTypeForm,
    ExtensionForm,
    DelExtensionForm,
)
from .forms import (
    EditIpTypeForm,
    IpTypeForm,
    DelIpTypeForm,
    DomainForm,
    AliasForm,
    DelAliasForm,
79 80
    SOAForm,
    DelSOAForm,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
81 82
    NsForm,
    DelNsForm,
83 84
    TxtForm,
    DelTxtForm,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
85 86 87 88 89 90 91
    MxForm,
    DelMxForm,
    VlanForm,
    DelVlanForm,
    ServiceForm,
    DelServiceForm,
    NasForm,
Gabriel Detraz's avatar
Gabriel Detraz committed
92 93 94
    DelNasForm,
    SrvForm,
    DelSrvForm,
95
    Ipv6ListForm,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
96
)
97
from .forms import EditOuverturePortListForm, EditOuverturePortConfigForm
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
98 99 100 101 102 103 104
from .models import (
    IpType,
    Machine,
    Interface,
    IpList,
    MachineType,
    Extension,
105
    SOA,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
106 107 108 109 110 111 112
    Mx,
    Ns,
    Domain,
    Service,
    Service_link,
    Vlan,
    Nas,
Gabriel Detraz's avatar
Gabriel Detraz committed
113
    Txt,
Gabriel Detraz's avatar
Gabriel Detraz committed
114
    Srv,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
115
    OuverturePortList,
Gabriel Detraz's avatar
Gabriel Detraz committed
116
    OuverturePort,
117
    Ipv6List,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
118
)
119
from users.models import User
120
from preferences.models import GeneralOption, OptionalMachine
121 122 123
from re2o.utils import (
    all_active_assigned_interfaces,
    all_has_access,
124
    filter_active_interfaces,
125
    SortTable,
126 127
)
from re2o.acl import (
128
    can_create,
129 130
    can_edit,
    can_delete,
131
    can_view,
132
    can_view_all,
133
    can_delete_set,
134
)
chirac's avatar
chirac committed
135
from re2o.views import form
136

137 138 139 140
def f_type_id( is_type_tt ):
    """ The id that will be used in HTML to store the value of the field
    type. Depends on the fact that type is generate using typeahead or not
    """
141
    return 'id_Interface-type_hidden' if is_type_tt else 'id_Interface-type'
142

143
def generate_ipv4_choices( form ) :
144
    """ Generate the parameter choices for the massive_bootstrap_form tag
145 146 147
    """
    f_ipv4 = form.fields['ipv4']
    used_mtype_id = []
148
    choices = '{"":[{key:"",value:"Choisissez d\'abord un type de machine"},'
149 150
    mtype_id = -1

Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
151 152
    for ip in f_ipv4.queryset.annotate(mtype_id=F('ip_type__machinetype__id'))\
            .order_by('mtype_id', 'id') :
153 154 155
        if mtype_id != ip.mtype_id :
            mtype_id = ip.mtype_id
            used_mtype_id.append(mtype_id)
156 157 158 159 160 161 162 163
            choices += '],"{t}":[{{key:"",value:"{v}"}},'.format(
                    t = mtype_id,
                    v = f_ipv4.empty_label or '""'
            )
        choices += '{{key:{k},value:"{v}"}},'.format(
                k = ip.id,
                v = ip.ipv4
        )
164 165 166 167 168 169 170 171

    for t in form.fields['type'].queryset.exclude(id__in=used_mtype_id) :
        choices += '], "'+str(t.id)+'": ['
        choices += '{key: "", value: "' + str(f_ipv4.empty_label) + '"},'
    choices += ']}'
    return choices

def generate_ipv4_engine( is_type_tt ) :
172
    """ Generate the parameter engine for the massive_bootstrap_form tag
173
    """
174 175 176 177 178 179 180 181 182 183
    return (
        'new Bloodhound( {{'
            'datumTokenizer: Bloodhound.tokenizers.obj.whitespace( "value" ),'
            'queryTokenizer: Bloodhound.tokenizers.whitespace,'
            'local: choices_ipv4[ $( "#{type_id}" ).val() ],'
            'identify: function( obj ) {{ return obj.key; }}'
        '}} )'
        ).format(
                type_id = f_type_id( is_type_tt )
        )
184 185

def generate_ipv4_match_func( is_type_tt ) :
186
    """ Generate the parameter match_func for the massive_bootstrap_form tag
187
    """
188 189 190 191 192 193 194 195 196 197 198 199 200
    return (
        'function(q, sync) {{'
            'if (q === "") {{'
                'var first = choices_ipv4[$("#{type_id}").val()].slice(0, 5);'
                'first = first.map( function (obj) {{ return obj.key; }} );'
                'sync(engine_ipv4.get(first));'
            '}} else {{'
                'engine_ipv4.search(q, sync);'
            '}}'
        '}}'
        ).format(
                type_id = f_type_id( is_type_tt )
        )
201

202 203
def generate_ipv4_mbf_param( form, is_type_tt ):
    """ Generate all the parameters to use with the massive_bootstrap_form
204 205 206 207 208
    tag """
    i_choices = { 'ipv4': generate_ipv4_choices( form ) }
    i_engine = { 'ipv4': generate_ipv4_engine( is_type_tt ) }
    i_match_func = { 'ipv4': generate_ipv4_match_func( is_type_tt ) }
    i_update_on = { 'ipv4': [f_type_id( is_type_tt )] }
Maël Kervella's avatar
Maël Kervella committed
209
    i_gen_select = { 'ipv4': False }
210
    i_mbf_param = {
211 212 213
        'choices': i_choices,
        'engine': i_engine,
        'match_func': i_match_func,
Maël Kervella's avatar
Maël Kervella committed
214 215
        'update_on': i_update_on,
        'gen_select': i_gen_select
216
    }
217
    return i_mbf_param
218

chirac's avatar
chirac committed
219
@login_required
220
@can_create(Machine)
221 222
@can_edit(User)
def new_machine(request, user, userid):
223
    """ Fonction de creation d'une machine. Cree l'objet machine,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
224
    le sous objet interface et l'objet domain à partir de model forms.
Gabriel Detraz's avatar
Gabriel Detraz committed
225
    Trop complexe, devrait être simplifié"""
Maël Kervella's avatar
Maël Kervella committed
226

227
    machine = NewMachineForm(request.POST or None, user=request.user)
Maël Kervella's avatar
Maël Kervella committed
228 229
    interface = AddInterfaceForm(
        request.POST or None,
230
        user=request.user
Maël Kervella's avatar
Maël Kervella committed
231
    )
232
    domain = DomainForm(request.POST or None, user=user)
233 234 235 236 237 238
    if machine.is_valid() and interface.is_valid():
        new_machine = machine.save(commit=False)
        new_machine.user = user
        new_interface = interface.save(commit=False)
        domain.instance.interface_parent = new_interface
        if domain.is_valid():
239
            new_domain = domain.save(commit=False)
240
            new_machine.save()
241
            new_interface.machine = new_machine
242
            new_interface.save()
243
            new_domain.interface_parent = new_interface
244
            new_domain.save()
guimoz's avatar
guimoz committed
245
            messages.success(request, "La machine a été créée")
246 247 248
            return redirect(reverse(
                'users:profil',
                kwargs={'userid':str(user.id)}
Maël Kervella's avatar
Maël Kervella committed
249 250 251 252 253 254 255
            ))
    i_mbf_param = generate_ipv4_mbf_param(interface, False)
    return form(
        {
            'machineform': machine,
            'interfaceform': interface,
            'domainform': domain,
256 257
            'i_mbf_param': i_mbf_param,
            'action_name' : 'Créer une machine'
Maël Kervella's avatar
Maël Kervella committed
258 259 260 261
        },
        'machines/machine.html',
        request
    )
262

chirac's avatar
chirac committed
263
@login_required
264 265
@can_edit(Interface)
def edit_interface(request, interface_instance, interfaceid):
Gabriel Detraz's avatar
Gabriel Detraz committed
266 267
    """ Edition d'une interface. Distingue suivant les droits les valeurs de interfaces et machines que l'user peut modifier
    infra permet de modifier le propriétaire"""
268

269 270 271 272 273
    machine_form = EditMachineForm(
        request.POST or None,
        instance=interface_instance.machine,
        user=request.user
    )
274
    interface_form = EditInterfaceForm(request.POST or None, instance=interface_instance, user=request.user)
275
    domain_form = DomainForm(request.POST or None, instance=interface_instance.domain)
276 277 278 279
    if machine_form.is_valid() and interface_form.is_valid() and domain_form.is_valid():
        new_machine = machine_form.save(commit=False)
        new_interface = interface_form.save(commit=False)
        new_domain = domain_form.save(commit=False)
280 281 282
        new_machine.save()
        new_interface.save()
        new_domain.save()
283
        messages.success(request, "La machine a été modifiée")
284 285
        return redirect(reverse(
            'users:profil',
286
            kwargs={'userid':str(interface_instance.machine.user.id)}
287
            ))
288
    i_mbf_param = generate_ipv4_mbf_param( interface_form, False )
289 290 291 292 293 294 295
    return form({
        'machineform': machine_form,
        'interfaceform': interface_form,
        'domainform': domain_form,
        'i_mbf_param': i_mbf_param,
        'action_name' : 'Editer une interface'
    }, 'machines/machine.html', request)
296

297
@login_required
298 299
@can_delete(Machine)
def del_machine(request, machine, machineid):
Gabriel Detraz's avatar
Gabriel Detraz committed
300
    """ Supprime une machine, interfaces en mode cascade"""
301
    if request.method == "POST":
302
        machine.delete()
303
        messages.success(request, "La machine a été détruite")
304 305 306 307
        return redirect(reverse(
            'users:profil',
            kwargs={'userid':str(machine.user.id)}
            ))
308
    return form({'objet': machine, 'objet_name': 'machine'}, 'machines/delete.html', request)
309

chirac's avatar
chirac committed
310
@login_required
311
@can_create(Interface)
312 313
@can_edit(Machine)
def new_interface(request, machine, machineid):
Gabriel Detraz's avatar
Gabriel Detraz committed
314
    """ Ajoute une interface et son domain associé à une machine existante"""
315

316
    interface_form = AddInterfaceForm(request.POST or None, user=request.user)
317
    domain_form = DomainForm(request.POST or None)
318 319 320 321 322
    if interface_form.is_valid():
        new_interface = interface_form.save(commit=False)
        domain_form.instance.interface_parent = new_interface
        new_interface.machine = machine
        if domain_form.is_valid():
323
            new_domain = domain_form.save(commit=False)
324
            new_interface.save()
325
            new_domain.interface_parent = new_interface
326
            new_domain.save()
327
            messages.success(request, "L'interface a été ajoutée")
328 329 330 331
            return redirect(reverse(
                'users:profil',
                kwargs={'userid':str(machine.user.id)}
                ))
332
    i_mbf_param = generate_ipv4_mbf_param( interface_form, False )
333 334 335 336 337 338
    return form({
        'interfaceform': interface_form,
        'domainform': domain_form,
        'i_mbf_param': i_mbf_param,
        'action_name' : 'Créer une interface' 
    }, 'machines/machine.html', request)
339

340
@login_required
341 342
@can_delete(Interface)
def del_interface(request, interface, interfaceid):
Gabriel Detraz's avatar
Gabriel Detraz committed
343
    """ Supprime une interface. Domain objet en mode cascade"""
344
    if request.method == "POST":
345
        machine = interface.machine
346 347 348
        interface.delete()
        if not machine.interface_set.all():
            machine.delete()
349
        messages.success(request, "L'interface a été détruite")
350 351 352 353
        return redirect(reverse(
            'users:profil',
            kwargs={'userid':str(request.user.id)}
            ))
354
    return form({'objet': interface, 'objet_name': 'interface'}, 'machines/delete.html', request)
355

356 357 358 359 360
@login_required
@can_create(Ipv6List)
@can_edit(Interface)
def new_ipv6list(request, interface, interfaceid):
    """Nouvelle ipv6"""
361 362
    ipv6list_instance = Ipv6List(interface=interface)
    ipv6 = Ipv6ListForm(request.POST or None, instance=ipv6list_instance, user=request.user)
363
    if ipv6.is_valid():
364
        ipv6.save()
365 366 367 368 369
        messages.success(request, "Ipv6 ajoutée")
        return redirect(reverse(
            'machines:index-ipv6',
            kwargs={'interfaceid':str(interface.id)}
            ))
370
    return form({'ipv6form': ipv6, 'action_name' : 'Créer'}, 'machines/machine.html', request)
371 372 373 374 375 376 377

@login_required
@can_edit(Ipv6List)
def edit_ipv6list(request, ipv6list_instance, ipv6listid):
    """Edition d'une ipv6"""
    ipv6 = Ipv6ListForm(request.POST or None, instance=ipv6list_instance, user=request.user)
    if ipv6.is_valid():
378
        ipv6.save()
379 380 381 382 383
        messages.success(request, "Ipv6 modifiée")
        return redirect(reverse(
            'machines:index-ipv6',
            kwargs={'interfaceid':str(ipv6list_instance.interface.id)}
            ))
384
    return form({'ipv6form': ipv6, 'action_name' : 'Editer'}, 'machines/machine.html', request)
385 386 387 388 389 390 391

@login_required
@can_delete(Ipv6List)
def del_ipv6list(request, ipv6list, ipv6listid):
    """ Supprime une ipv6"""
    if request.method == "POST":
        interfaceid = ipv6list.interface.id
392
        ipv6list.delete()
393 394 395 396 397 398 399
        messages.success(request, "L'ipv6 a été détruite")
        return redirect(reverse(
            'machines:index-ipv6',
            kwargs={'interfaceid':str(interfaceid)}
            ))
    return form({'objet': ipv6list, 'objet_name': 'ipv6'}, 'machines/delete.html', request)

400
@login_required
401
@can_create(IpType)
402
def add_iptype(request):
Gabriel Detraz's avatar
Gabriel Detraz committed
403
    """ Ajoute un range d'ip. Intelligence dans le models, fonction views minimaliste"""
404

405 406
    iptype = IpTypeForm(request.POST or None)
    if iptype.is_valid():
407
        iptype.save()
408
        messages.success(request, "Ce type d'ip a été ajouté")
409
        return redirect(reverse('machines:index-iptype'))
410
    return form({'iptypeform': iptype, 'action_name' : 'Créer'}, 'machines/machine.html', request)
411 412

@login_required
413 414
@can_edit(IpType)
def edit_iptype(request, iptype_instance, iptypeid):
Gabriel Detraz's avatar
Gabriel Detraz committed
415
    """ Edition d'un range. Ne permet pas de le redimensionner pour éviter l'incohérence"""
416

417
    iptype = EditIpTypeForm(request.POST or None, instance=iptype_instance)
418
    if iptype.is_valid():
419
        iptype.save()
420
        messages.success(request, "Type d'ip modifié")
421
        return redirect(reverse('machines:index-iptype'))
422
    return form({'iptypeform': iptype, 'action_name' : 'Editer'}, 'machines/machine.html', request)
423 424

@login_required
425 426
@can_delete_set(IpType)
def del_iptype(request, instances):
Gabriel Detraz's avatar
Gabriel Detraz committed
427
    """ Suppression d'un range ip. Supprime les objets ip associés"""
428
    iptype = DelIpTypeForm(request.POST or None, instances=instances)
429 430 431 432
    if iptype.is_valid():
        iptype_dels = iptype.cleaned_data['iptypes']
        for iptype_del in iptype_dels:
            try:
433
                iptype_del.delete()
434 435 436
                messages.success(request, "Le type d'ip a été supprimé")
            except ProtectedError:
                messages.error(request, "Le type d'ip %s est affectée à au moins une machine, vous ne pouvez pas le supprimer" % iptype_del)
437
        return redirect(reverse('machines:index-iptype'))
438
    return form({'iptypeform': iptype, 'action_name' : 'Supprimer'}, 'machines/machine.html', request)
439

chirac's avatar
chirac committed
440
@login_required
441
@can_create(MachineType)
442
def add_machinetype(request):
443

444 445
    machinetype = MachineTypeForm(request.POST or None)
    if machinetype.is_valid():
446
        machinetype.save()
447
        messages.success(request, "Ce type de machine a été ajouté")
448
        return redirect(reverse('machines:index-machinetype'))
449
    return form({'machinetypeform': machinetype, 'action_name' : 'Créer'}, 'machines/machine.html', request)
450

chirac's avatar
chirac committed
451
@login_required
452 453
@can_edit(MachineType)
def edit_machinetype(request, machinetype_instance, machinetypeid):
454

455 456
    machinetype = MachineTypeForm(request.POST or None, instance=machinetype_instance)
    if machinetype.is_valid():
457
        machinetype.save()
458
        messages.success(request, "Type de machine modifié")
459
        return redirect(reverse('machines:index-machinetype'))
460
    return form({'machinetypeform': machinetype, 'action_name' : 'Editer'}, 'machines/machine.html', request)
461

chirac's avatar
chirac committed
462
@login_required
463 464 465
@can_delete_set(MachineType)
def del_machinetype(request, instances):
    machinetype = DelMachineTypeForm(request.POST or None, instances=instances)
466 467 468 469
    if machinetype.is_valid():
        machinetype_dels = machinetype.cleaned_data['machinetypes']
        for machinetype_del in machinetype_dels:
            try:
470
                machinetype_del.delete()
471 472 473
                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)
474
        return redirect(reverse('machines:index-machinetype'))
475
    return form({'machinetypeform': machinetype, 'action_name' : 'Supprimer'}, 'machines/machine.html', request)
476

477
@login_required
478
@can_create(Extension)
479
def add_extension(request):
480

481 482
    extension = ExtensionForm(request.POST or None)
    if extension.is_valid():
483
        extension.save()
484
        messages.success(request, "Cette extension a été ajoutée")
485
        return redirect(reverse('machines:index-extension'))
486
    return form({'extensionform': extension, 'action_name' : 'Créer'}, 'machines/machine.html', request)
487 488

@login_required
489 490
@can_edit(Extension)
def edit_extension(request, extension_instance, extensionid):
491

492 493
    extension = ExtensionForm(request.POST or None, instance=extension_instance)
    if extension.is_valid():
494
        extension.save()
Gabriel Detraz's avatar
Gabriel Detraz committed
495
        messages.success(request, "Extension modifiée")
496
        return redirect(reverse('machines:index-extension'))
497
    return form({'extensionform': extension, 'action_name' : 'Editer'}, 'machines/machine.html', request)
498 499

@login_required
500 501 502
@can_delete_set(Extension)
def del_extension(request, instances):
    extension = DelExtensionForm(request.POST or None, instances=instances)
503 504 505 506
    if extension.is_valid():
        extension_dels = extension.cleaned_data['extensions']
        for extension_del in extension_dels:
            try:
507
                extension_del.delete()
508 509 510
                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)
511
        return redirect(reverse('machines:index-extension'))
512
    return form({'extensionform': extension, 'action_name' : 'Supprimer'}, 'machines/machine.html', request)
513

514
@login_required
515
@can_create(SOA)
516
def add_soa(request):
517

518 519
    soa = SOAForm(request.POST or None)
    if soa.is_valid():
520
        soa.save()
521
        messages.success(request, "Cet enregistrement SOA a été ajouté")
522
        return redirect(reverse('machines:index-extension'))
523
    return form({'soaform': soa, 'action_name' : 'Créer'}, 'machines/machine.html', request)
524 525

@login_required
526 527
@can_edit(SOA)
def edit_soa(request, soa_instance, soaid):
528

529 530
    soa = SOAForm(request.POST or None, instance=soa_instance)
    if soa.is_valid():
531
        soa.save()
532
        messages.success(request, "SOA modifié")
533
        return redirect(reverse('machines:index-extension'))
534
    return form({'soaform': soa, 'action_name' : 'Editer'}, 'machines/machine.html', request)
535 536

@login_required
537 538 539
@can_delete_set(SOA)
def del_soa(request, instances):
    soa = DelSOAForm(request.POST or None, instances=instances)
540 541 542 543
    if soa.is_valid():
        soa_dels = soa.cleaned_data['soa']
        for soa_del in soa_dels:
            try:
544
                soa_del.delete()
545 546 547
                messages.success(request, "Le SOA a été supprimée")
            except ProtectedError:
                messages.error(request, "Erreur le SOA suivant %s ne peut être supprimé" % soa_del)
548
        return redirect(reverse('machines:index-extension'))
549
    return form({'soaform': soa, 'action_name' : 'Supprimer'}, 'machines/machine.html', request)
550

551
@login_required
552
@can_create(Mx)
553
def add_mx(request):
554

555 556
    mx = MxForm(request.POST or None)
    if mx.is_valid():
557
        mx.save()
558
        messages.success(request, "Cet enregistrement mx a été ajouté")
559
        return redirect(reverse('machines:index-extension'))
560
    return form({'mxform': mx, 'action_name' : 'Créer'}, 'machines/machine.html', request)
561 562

@login_required
563 564
@can_edit(Mx)
def edit_mx(request, mx_instance, mxid):
565

566 567
    mx = MxForm(request.POST or None, instance=mx_instance)
    if mx.is_valid():
568
        mx.save()
569
        messages.success(request, "Mx modifié")
570
        return redirect(reverse('machines:index-extension'))
571
    return form({'mxform': mx, 'action_name' : 'Editer'}, 'machines/machine.html', request)
572 573

@login_required
574 575 576
@can_delete_set(Mx)
def del_mx(request, instances):
    mx = DelMxForm(request.POST or None, instances=instances)
577 578 579 580
    if mx.is_valid():
        mx_dels = mx.cleaned_data['mx']
        for mx_del in mx_dels:
            try:
581
                mx_del.delete()
582 583 584
                messages.success(request, "L'mx a été supprimée")
            except ProtectedError:
                messages.error(request, "Erreur le Mx suivant %s ne peut être supprimé" % mx_del)
585
        return redirect(reverse('machines:index-extension'))
586
    return form({'mxform': mx, 'action_name' : 'Supprimer'}, 'machines/machine.html', request)
587

588
@login_required
589
@can_create(Ns)
590
def add_ns(request):
591

592 593
    ns = NsForm(request.POST or None)
    if ns.is_valid():
594
        ns.save()
595
        messages.success(request, "Cet enregistrement ns a été ajouté")
596
        return redirect(reverse('machines:index-extension'))
597
    return form({'nsform': ns, 'action_name' : 'Créer'}, 'machines/machine.html', request)
598 599

@login_required
600 601
@can_edit(Ns)
def edit_ns(request, ns_instance, nsid):
602

603 604
    ns = NsForm(request.POST or None, instance=ns_instance)
    if ns.is_valid():
605
        ns.save()
606
        messages.success(request, "Ns modifié")
607
        return redirect(reverse('machines:index-extension'))
608
    return form({'nsform': ns, 'action_name' : 'Editer'}, 'machines/machine.html', request)
609 610

@login_required
611 612 613
@can_delete_set(Ns)
def del_ns(request, instances):
    ns = DelNsForm(request.POST or None, instances=instances)
614 615 616 617
    if ns.is_valid():
        ns_dels = ns.cleaned_data['ns']
        for ns_del in ns_dels:
            try:
618
                ns_del.delete()
619 620 621
                messages.success(request, "Le ns a été supprimée")
            except ProtectedError:
                messages.error(request, "Erreur le Ns suivant %s ne peut être supprimé" % ns_del)
622
        return redirect(reverse('machines:index-extension'))
623
    return form({'nsform': ns, 'action_name' : 'Supprimer'}, 'machines/machine.html', request)
624

Gabriel Detraz's avatar
Gabriel Detraz committed
625
@login_required
626
@can_create(Txt)
627
def add_txt(request):
628

629 630
    txt = TxtForm(request.POST or None)
    if txt.is_valid():
631
        txt.save()
Gabriel Detraz's avatar
Gabriel Detraz committed
632
        messages.success(request, "Cet enregistrement text a été ajouté")
633
        return redirect(reverse('machines:index-extension'))
634
    return form({'txtform': txt, 'action_name' : 'Créer'}, 'machines/machine.html', request)
Gabriel Detraz's avatar
Gabriel Detraz committed
635 636

@login_required
637 638
@can_edit(Txt)
def edit_txt(request, txt_instance, txtid):
639

640 641
    txt = TxtForm(request.POST or None, instance=txt_instance)
    if txt.is_valid():
642
        txt.save()
643
        messages.success(request, "Txt modifié")
644
        return redirect(reverse('machines:index-extension'))
645
    return form({'txtform': txt, 'action_name' : 'Editer'}, 'machines/machine.html', request)
Gabriel Detraz's avatar
Gabriel Detraz committed
646 647

@login_required
648 649 650
@can_delete_set(Txt)
def del_txt(request, instances):
    txt = DelTxtForm(request.POST or None, instances=instances)
651 652 653
    if txt.is_valid():
        txt_dels = txt.cleaned_data['txt']
        for txt_del in txt_dels:
Gabriel Detraz's avatar
Gabriel Detraz committed
654
            try:
655
                txt_del.delete()
656
                messages.success(request, "Le txt a été supprimé")
Gabriel Detraz's avatar
Gabriel Detraz committed
657
            except ProtectedError:
658
                messages.error(request, "Erreur le Txt suivant %s ne peut être supprimé" % txt_del)
659
        return redirect(reverse('machines:index-extension'))
660
    return form({'txtform': txt, 'action_name' : 'Supprimer'}, 'machines/machine.html', request)
Gabriel Detraz's avatar
Gabriel Detraz committed
661

Gabriel Detraz's avatar
Gabriel Detraz committed
662
@login_required
663
@can_create(Srv)
Gabriel Detraz's avatar
Gabriel Detraz committed
664
def add_srv(request):
665

Gabriel Detraz's avatar
Gabriel Detraz committed
666 667
    srv = SrvForm(request.POST or None)
    if srv.is_valid():
668
        srv.save()
Gabriel Detraz's avatar
Gabriel Detraz committed
669 670
        messages.success(request, "Cet enregistrement srv a été ajouté")
        return redirect(reverse('machines:index-extension'))
671
    return form({'srvform': srv, 'action_name' : 'Créer'}, 'machines/machine.html', request)
Gabriel Detraz's avatar
Gabriel Detraz committed
672 673

@login_required
674 675
@can_edit(Srv)
def edit_srv(request, srv_instance, srvid):
676

Gabriel Detraz's avatar
Gabriel Detraz committed
677 678
    srv = SrvForm(request.POST or None, instance=srv_instance)
    if srv.is_valid():
679
        srv.save()
Gabriel Detraz's avatar
Gabriel Detraz committed
680 681
        messages.success(request, "Srv modifié")
        return redirect(reverse('machines:index-extension'))
682
    return form({'srvform': srv, 'action_name' : 'Editer'}, 'machines/machine.html', request)
Gabriel Detraz's avatar
Gabriel Detraz committed
683 684

@login_required
685 686 687
@can_delete_set(Srv)
def del_srv(request, instances):
    srv = DelSrvForm(request.POST or None, instances=instances)
Gabriel Detraz's avatar
Gabriel Detraz committed
688 689 690 691
    if srv.is_valid():
        srv_dels = srv.cleaned_data['srv']
        for srv_del in srv_dels:
            try:
692
                srv_del.delete()
Gabriel Detraz's avatar
Gabriel Detraz committed
693 694 695 696
                messages.success(request, "L'srv a été supprimée")
            except ProtectedError:
                messages.error(request, "Erreur le Srv suivant %s ne peut être supprimé" % srv_del)
        return redirect(reverse('machines:index-extension'))
697
    return form({'srvform': srv, 'action_name' : 'Supprimer'}, 'machines/machine.html', request)
Gabriel Detraz's avatar
Gabriel Detraz committed
698

699
@login_required
700
@can_create(Domain)
701 702
@can_edit(Interface)
def add_alias(request, interface, interfaceid):
703

704
    alias = AliasForm(request.POST or None, user=request.user)
705 706
    if alias.is_valid():
        alias = alias.save(commit=False)
chirac's avatar
chirac committed
707
        alias.cname = interface.domain
708
        alias.save()
709
        messages.success(request, "Cet alias a été ajouté")
710
        return redirect(reverse(
711
            'machines:index-alias',
712 713
            kwargs={'interfaceid':str(interfaceid)}
            ))
714
    return form({'aliasform': alias, 'action_name' : 'Créer'}, 'machines/machine.html', request)
715 716

@login_required
717 718
@can_edit(Domain)
def edit_alias(request, domain_instance, domainid):
719

720
    alias = AliasForm(request.POST or None, instance=domain_instance, user=request.user)
721
    if alias.is_valid():
722
        domain_instance = alias.save()
723
        messages.success(request, "Alias modifié")
724
        return redirect(reverse(
725
            'machines:index-alias',
726
            kwargs={'interfaceid':str(domain_instance.cname.interface_parent.id)}
727
            ))
728
    return form({'aliasform': alias, 'action_name' : 'Editer'}, 'machines/machine.html', request)
729 730

@login_required
731 732
@can_edit(Interface)
def del_alias(request, interface, interfaceid):
733 734 735 736 737
    alias = DelAliasForm(request.POST or None, interface=interface)
    if alias.is_valid():
        alias_dels = alias.cleaned_data['alias']
        for alias_del in alias_dels:
            try:
738
                alias_del.delete()
739 740 741
                messages.success(request, "L'alias %s a été supprimé" % alias_del)
            except ProtectedError:
                messages.error(request, "Erreur l'alias suivant %s ne peut être supprimé" % alias_del)
742
        return redirect(reverse(
743
            'machines:index-alias',
744 745
            kwargs={'interfaceid':str(interfaceid)}
            ))
746
    return form({'aliasform': alias, 'action_name' : 'Supprimer'}, 'machines/machine.html', request)
747

748 749

@login_required
750
@can_create(Service)
751
def add_service(request):
752

753 754
    service = ServiceForm(request.POST or None)
    if service.is_valid():
755
        service.save()
756
        messages.success(request, "Cet enregistrement service a été ajouté")
757
        return redirect(reverse('machines:index-service'))
758
    return form({'serviceform': service, 'action_name' : 'Créer'}, 'machines/machine.html', request)
759 760

@login_required
761 762
@can_edit(Service)
def edit_service(request, service_instance, serviceid):
763

764 765
    service = ServiceForm(request.POST or None, instance=service_instance)
    if service.is_valid():
766
        service.save()
767
        messages.success(request, "Service modifié")
768
        return redirect(reverse('machines:index-service'))
769
    return form({'serviceform': service, 'action_name' : 'Editer'}, 'machines/machine.html', request)
770 771

@login_required
772 773 774
@can_delete_set(Service)
def del_service(request, instances):
    service = DelServiceForm(request.POST or None, instances=instances)
775 776 777 778
    if service.is_valid():
        service_dels = service.cleaned_data['service']
        for service_del in service_dels:
            try:
779
                service_del.delete()
780 781 782
                messages.success(request, "Le service a été supprimée")
            except ProtectedError:
                messages.error(request, "Erreur le service suivant %s ne peut être supprimé" % service_del)
783
        return redirect(reverse('machines:index-service'))
784
    return form({'serviceform': service, 'action_name' : 'Supprimer'}, 'machines/machine.html', request)
785

786
@login_required
787
@can_create(Vlan)
788
def add_vlan(request):
789

790 791
    vlan = VlanForm(request.POST or None)
    if vlan.is_valid():
792
        vlan.save()
793
        messages.success(request, "Cet enregistrement vlan a été ajouté")
794
        return redirect(reverse('machines:index-vlan'))
795
    return form({'vlanform': vlan, 'action_name' : 'Créer'}, 'machines/machine.html', request)
796 797

@login_required
798 799
@can_edit(Vlan)
def edit_vlan(request, vlan_instance, vlanid):
800

801 802
    vlan = VlanForm(request.POST or None, instance=vlan_instance)
    if vlan.is_valid():
803
        vlan.save()
804
        messages.success(request, "Vlan modifié")
805
        return redirect(reverse('machines:index-vlan'))
806
    return form({'vlanform': vlan, 'action_name' : 'Editer'}, 'machines/machine.html', request)
807 808

@login_required
809 810 811
@can_delete_set(Vlan)
def del_vlan(request, instances):
    vlan = DelVlanForm(request.POST or None, instances=instances)
812 813
    if vlan.is_valid():
        vlan_dels = vlan.cleaned_data['vlan']
814
        for vlan_del in vlan_dels:
815
            try:
816
                vlan_del.delete()
817 818 819
                messages.success(request, "Le vlan a été supprimée")
            except ProtectedError:
                messages.error(request, "Erreur le Vlan suivant %s ne peut être supprimé" % vlan_del)
820
        return redirect(reverse('machines:index-vlan'))
821
    return form({'vlanform': vlan, 'action_name' : 'Supprimer'}, 'machines/machine.html', request)
822

823
@login_required
824
@can_create(Nas)
825
def add_nas(request):
826

827 828
    nas = NasForm(request.POST or None)
    if nas.is_valid():
829
        nas.save()
830
        messages.success(request, "Cet enregistrement nas a été ajouté")
831
        return redirect(reverse('machines:index-nas'))
832
    return form({'nasform': nas, 'action_name' : 'Créer'}, 'machines/machine.html', request)
833 834

@login_required
835 836
@can_edit(Nas)
def edit_nas(request, nas_instance, nasid):
837

838 839
    nas = NasForm(request.POST or None, instance=nas_instance)
    if nas.is_valid():
840
        nas.save()
841
        messages.success(request, "Nas modifié")
842
        return redirect(reverse('machines:index-nas'))
843
    return form({'nasform': nas, 'action_name' : 'Editer'}, 'machines/machine.html', request)
844 845

@login_required
846 847 848
@can_delete_set(Nas)
def del_nas(request, instances):
    nas = DelNasForm(request.POST or None, instances=instances)
849 850 851 852
    if nas.is_valid():
        nas_dels = nas.cleaned_data['nas']
        for nas_del in nas_dels:
            try:
853
                nas_del.delete()
854 855 856
                messages.success(request, "Le nas a été supprimé")
            except ProtectedError:
                messages.error(request, "Erreur le Nas suivant %s ne peut être supprimé" % nas_del)
857
        return redirect(reverse('machines:index-nas'))
858
    return form({'nasform': nas, 'action_name' : 'Supprimer'}, 'machines/machine.html', request)
859

chirac's avatar
chirac committed
860
@login_required
861
@can_view_all(Machine)
862
def index(request):
863
    pagination_large_number = GeneralOption.get_cached_value('pagination_large_number')
864
    machines_list = Machine.objects.select_related('user').prefetch_related('interface_set__domain__extension').prefetch_related('interface_set__ipv4__ip_type').prefetch_related('interface_set__type__ip_type__extension').prefetch_related('interface_set__domain__related_domain__extension').prefetch_related('interface_set__ipv6list')
865 866 867 868 869 870
    machines_list = SortTable.sort(
        machines_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.MACHINES_INDEX
    )
871
    paginator = Paginator(machines_list, pagination_large_number)
872 873 874 875 876 877 878 879 880
    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)
881
    return render(request, 'machines/index.html', {'machines_list': machines_list})
882

883
@login_required
884
@can_view_all(IpType)
885
def index_iptype(request):
886
    iptype_list = IpType.objects.select_related('extension').select_related('vlan').order_by('type')
887 888
    return render(request, 'machines/index_iptype.html', {'iptype_list':iptype_list})

889
@login_required
890
@can_view_all(Vlan)
891
def index_vlan(request):
892
    vlan_list = Vlan.objects.prefetch_related('iptype_set').order_by('vlan_id')
893 894
    return render(request, 'machines/index_vlan.html', {'vlan_list':vlan_list})

chirac's avatar
chirac committed
895
@login_required
896
@can_view_all(MachineType)
897
def index_machinetype(request):
898
    machinetype_list = MachineType.objects.select_related('ip_type').order_by('type')
899
    return render(request, 'machines/index_machinetype.html', {'machinetype_list':machinetype_list})
900

901
@login_required
902
@can_view_all(Nas)
903
def index_nas(request):
904
    nas_list = Nas.objects.select_related('machine_type').select_related('nas_type').order_by('name')
905 906
    return render(request, 'machines/index_nas.html', {'nas_list':nas_list})

907
@login_required
908 909 910 911 912 913
@can_view_all(SOA)
@can_view_all(Mx)
@can_view_all(Ns)
@can_view_all(Txt)
@can_view_all(Srv)
@can_view_all(Extension)
914
def index_extension(request):
915 916
    extension_list = Extension.objects.select_related('origin').select_related('soa').order_by('name')
    soa_list = SOA.objects.order_by('name')
917 918
    mx_list = Mx.objects.order_by('zone').select_related('zone').select_related('name__extension')
    ns_list = Ns.objects.order_by('zone').select_related('zone').select_related('ns__extension')
Gabriel Detraz's avatar
Gabriel Detraz committed
919
    txt_list = Txt.objects.all().select_related('zone')
Gabriel Detraz's avatar
Gabriel Detraz committed
920 921
    srv_list = Srv.objects.all().select_related('extension').select_related('target__extension')
    return render(request, 'machines/index_extension.html', {'extension_list':extension_list, 'soa_list': soa_list, 'mx_list': mx_list, 'ns_list': ns_list, 'txt_list' : txt_list, 'srv_list': srv_list})
Dalahro's avatar
Dalahro committed
922

923
@login_required
924 925
@can_edit(Interface)
def index_alias(request, interface, interfaceid):
chirac's avatar
chirac committed
926
    alias_list = Domain.objects.filter(cname=Domain.objects.filter(interface_parent=interface)).order_by('name')
927 928
    return render(request, 'machines/index_alias.html', {'alias_list':alias_list, 'interface_id': interfaceid})

929 930 931 932 933 934
@login_required
@can_edit(Interface)
def index_ipv6(request, interface, interfaceid):
    ipv6_list = Ipv6List.objects.filter(interface=interface)
    return render(request, 'machines/index_ipv6.html', {'ipv6_list':ipv6_list, 'interface_id': interfaceid})

935
@login_required
936
@can_view_all(Service)
937
def index_service(request):
938 939
    service_list = Service.objects.prefetch_related('service_link_set__server__domain__extension').all()
    servers_list = Service_link.objects.select_related('server__domain__extension').select_related('service').all()
940 941
    return render(request, 'machines/index_service.html', {'service_list':service_list, 'servers_list':servers_list})

942

943
@login_required
944
@can_view_all(OuverturePortList)
945
def index_portlist(request):
946 947 948
    port_list = OuverturePortList.objects.prefetch_related('ouvertureport_set')\
    .prefetch_related('interface_set__domain__extension')\
    .prefetch_related('interface_set__machine__user').order_by('name')
949 950
    return render(request, "machines/index_portlist.html", {'port_list':port_list})

951
@login_required
952 953
@can_edit(OuverturePortList)
def edit_portlist(request, ouvertureportlist_instance, ouvertureportlistid):
954

955
    port_list = EditOuverturePortListForm(request.POST or None, instance=ouvertureportlist_instance)
956
    port_formset = modelformset_factory(
957
            OuverturePort,
958 959
            fields=('begin','end','protocole','io'),
            extra=0,
960 961 962
            can_delete=True,
	    min_num=1,
	    validate_min=True,
963
    )(request.POST or None, queryset=ouvertureportlist_instance.ouvertureport_set.all())
964 965 966 967 968 969 970 971
    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()
972
        messages.success(request, "Liste de ports modifiée")
973
        return redirect(reverse('machines:index-portlist'))
974
    return form({'port_list' : port_list, 'ports' : port_formset}, 'machines/edit_portlist.html', request)
975

976
@login_required
977 978
@can_delete(OuverturePortList)
def del_portlist(request, port_list_instance, ouvertureportlistid):
979 980
    port_list_instance.delete()
    messages.success(request, "La liste de ports a été supprimée")
981
    return redirect(reverse('machines:index-portlist'))
982

983
@login_required
984
@can_create(OuverturePortList)
985
def add_portlist(request):