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 52.5 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
"""machines.views
The views for the Machines app
"""
31 32 33

from __future__ import unicode_literals

34
from django.urls import reverse
Dalahro's avatar
Dalahro committed
35
from django.http import HttpResponse
36 37
from django.shortcuts import render, redirect
from django.contrib import messages
38
from django.contrib.auth.decorators import login_required, permission_required
39
from django.db.models import ProtectedError, F
40
from django.forms import modelformset_factory
Dalahro's avatar
Dalahro committed
41
from django.views.decorators.csrf import csrf_exempt
42

Dalahro's avatar
Dalahro committed
43
from rest_framework.renderers import JSONRenderer
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

from users.models import User
from preferences.models import GeneralOption
from re2o.utils import (
    all_active_assigned_interfaces,
    filter_active_interfaces,
    SortTable,
    re2o_paginator,
)
from re2o.acl import (
    can_create,
    can_edit,
    can_delete,
    can_view_all,
    can_delete_set,
)
from re2o.views import form

from .serializers import (
63
    FullInterfaceSerializer,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
64 65 66
    InterfaceSerializer,
    TypeSerializer,
    DomainSerializer,
Gabriel Detraz's avatar
Gabriel Detraz committed
67
    TxtSerializer,
Gabriel Detraz's avatar
Gabriel Detraz committed
68
    SrvSerializer,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
69 70 71 72 73
    MxSerializer,
    ExtensionSerializer,
    ServiceServersSerializer,
    NsSerializer,
)
Dalahro's avatar
Dalahro committed
74

Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
from .forms import (
    NewMachineForm,
    EditMachineForm,
    EditInterfaceForm,
    AddInterfaceForm,
    MachineTypeForm,
    DelMachineTypeForm,
    ExtensionForm,
    DelExtensionForm,
    EditIpTypeForm,
    IpTypeForm,
    DelIpTypeForm,
    DomainForm,
    AliasForm,
    DelAliasForm,
90 91
    SOAForm,
    DelSOAForm,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
92 93
    NsForm,
    DelNsForm,
94 95
    TxtForm,
    DelTxtForm,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
96 97 98 99 100 101 102
    MxForm,
    DelMxForm,
    VlanForm,
    DelVlanForm,
    ServiceForm,
    DelServiceForm,
    NasForm,
Gabriel Detraz's avatar
Gabriel Detraz committed
103 104 105
    DelNasForm,
    SrvForm,
    DelSrvForm,
106
    Ipv6ListForm,
107 108
    EditOuverturePortListForm,
    EditOuverturePortConfigForm
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
109 110 111 112 113 114 115
)
from .models import (
    IpType,
    Machine,
    Interface,
    MachineType,
    Extension,
116
    SOA,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
117 118 119 120 121 122 123
    Mx,
    Ns,
    Domain,
    Service,
    Service_link,
    Vlan,
    Nas,
Gabriel Detraz's avatar
Gabriel Detraz committed
124
    Txt,
Gabriel Detraz's avatar
Gabriel Detraz committed
125
    Srv,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
126
    OuverturePortList,
Gabriel Detraz's avatar
Gabriel Detraz committed
127
    OuverturePort,
128
    Ipv6List,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
129
)
130

131 132

def f_type_id(is_type_tt):
133 134 135
    """ 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
    """
136
    return 'id_Interface-type_hidden' if is_type_tt else 'id_Interface-type'
137

138

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

147 148 149 150
    for ip in (f_ipv4.queryset
               .annotate(mtype_id=F('ip_type__machinetype__id'))
               .order_by('mtype_id', 'id')):
        if mtype_id != ip.mtype_id:
151 152
            mtype_id = ip.mtype_id
            used_mtype_id.append(mtype_id)
153
            choices += '],"{t}":[{{key:"",value:"{v}"}},'.format(
154 155
                t=mtype_id,
                v=f_ipv4.empty_label or '""'
156 157
            )
        choices += '{{key:{k},value:"{v}"}},'.format(
158 159
            k=ip.id,
            v=ip.ipv4
160
        )
161

162
    for t in form_obj.fields['type'].queryset.exclude(id__in=used_mtype_id):
163 164 165 166 167
        choices += '], "'+str(t.id)+'": ['
        choices += '{key: "", value: "' + str(f_ipv4.empty_label) + '"},'
    choices += ']}'
    return choices

168 169

def generate_ipv4_engine(is_type_tt):
170
    """ Generate the parameter engine for the massive_bootstrap_form tag
171
    """
172 173 174 175 176 177 178 179
    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(
180
            type_id=f_type_id(is_type_tt)
181
        )
182

183 184

def generate_ipv4_match_func(is_type_tt):
185
    """ Generate the parameter match_func for the massive_bootstrap_form tag
186
    """
187 188 189 190 191 192 193 194 195 196 197
    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(
198
            type_id=f_type_id(is_type_tt)
199
        )
200

201

202
def generate_ipv4_mbf_param(form_obj, is_type_tt):
203
    """ Generate all the parameters to use with the massive_bootstrap_form
204
    tag """
205
    i_choices = {'ipv4': generate_ipv4_choices(form_obj)}
206 207 208 209
    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)]}
    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

219

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

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

264

chirac's avatar
chirac committed
265
@login_required
266
@can_edit(Interface)
267
def edit_interface(request, interface_instance, **_kwargs):
268 269 270
    """ 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"""
271

272 273 274 275 276
    machine_form = EditMachineForm(
        request.POST or None,
        instance=interface_instance.machine,
        user=request.user
    )
277 278 279 280 281 282 283 284 285 286 287 288
    interface_form = EditInterfaceForm(
        request.POST or None,
        instance=interface_instance,
        user=request.user
    )
    domain_form = DomainForm(
        request.POST or None,
        instance=interface_instance.domain
    )
    if (machine_form.is_valid() and
            interface_form.is_valid() and
            domain_form.is_valid()):
289 290 291
        new_machine_obj = machine_form.save(commit=False)
        new_interface_obj = interface_form.save(commit=False)
        new_domain_obj = domain_form.save(commit=False)
292
        if machine_form.changed_data:
293
            new_machine_obj.save()
294
        if interface_form.changed_data:
295
            new_interface_obj.save()
296
        if domain_form.changed_data:
297
            new_domain_obj.save()
298
        messages.success(request, "La machine a été modifiée")
299 300
        return redirect(reverse(
            'users:profil',
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
            kwargs={'userid': str(interface_instance.machine.user.id)}
        ))
    i_mbf_param = generate_ipv4_mbf_param(interface_form, False)
    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
    )

316

317
@login_required
318
@can_delete(Machine)
319
def del_machine(request, machine, **_kwargs):
Gabriel Detraz's avatar
Gabriel Detraz committed
320
    """ Supprime une machine, interfaces en mode cascade"""
321
    if request.method == "POST":
322
        machine.delete()
323
        messages.success(request, "La machine a été détruite")
324 325
        return redirect(reverse(
            'users:profil',
326 327 328 329 330 331 332 333
            kwargs={'userid': str(machine.user.id)}
        ))
    return form(
        {'objet': machine, 'objet_name': 'machine'},
        'machines/delete.html',
        request
    )

334

chirac's avatar
chirac committed
335
@login_required
336
@can_create(Interface)
337
@can_edit(Machine)
338
def new_interface(request, machine, **_kwargs):
Gabriel Detraz's avatar
Gabriel Detraz committed
339
    """ Ajoute une interface et son domain associé à une machine existante"""
340

341
    interface_form = AddInterfaceForm(request.POST or None, user=request.user)
342
    domain_form = DomainForm(request.POST or None)
343
    if interface_form.is_valid():
344 345 346
        new_interface_obj = interface_form.save(commit=False)
        domain_form.instance.interface_parent = new_interface_obj
        new_interface_obj.machine = machine
347
        if domain_form.is_valid():
348 349 350 351
            new_domain_obj = domain_form.save(commit=False)
            new_interface_obj.save()
            new_domain_obj.interface_parent = new_interface_obj
            new_domain_obj.save()
352
            messages.success(request, "L'interface a été ajoutée")
353 354
            return redirect(reverse(
                'users:profil',
355 356 357 358 359 360 361 362 363 364 365 366 367 368
                kwargs={'userid': str(machine.user.id)}
            ))
    i_mbf_param = generate_ipv4_mbf_param(interface_form, False)
    return form(
        {
            'interfaceform': interface_form,
            'domainform': domain_form,
            'i_mbf_param': i_mbf_param,
            'action_name': 'Créer une interface'
        },
        'machines/machine.html',
        request
    )

369

370
@login_required
371
@can_delete(Interface)
372
def del_interface(request, interface, **_kwargs):
Gabriel Detraz's avatar
Gabriel Detraz committed
373
    """ Supprime une interface. Domain objet en mode cascade"""
374
    if request.method == "POST":
375
        machine = interface.machine
376 377 378
        interface.delete()
        if not machine.interface_set.all():
            machine.delete()
379
        messages.success(request, "L'interface a été détruite")
380 381
        return redirect(reverse(
            'users:profil',
382 383 384 385 386 387 388 389
            kwargs={'userid': str(request.user.id)}
        ))
    return form(
        {'objet': interface, 'objet_name': 'interface'},
        'machines/delete.html',
        request
    )

390

391 392 393
@login_required
@can_create(Ipv6List)
@can_edit(Interface)
394
def new_ipv6list(request, interface, **_kwargs):
395
    """Nouvelle ipv6"""
396
    ipv6list_instance = Ipv6List(interface=interface)
397 398 399 400 401
    ipv6 = Ipv6ListForm(
        request.POST or None,
        instance=ipv6list_instance,
        user=request.user
    )
402
    if ipv6.is_valid():
403
        ipv6.save()
404 405 406
        messages.success(request, "Ipv6 ajoutée")
        return redirect(reverse(
            'machines:index-ipv6',
407 408 409 410 411 412 413 414
            kwargs={'interfaceid': str(interface.id)}
        ))
    return form(
        {'ipv6form': ipv6, 'action_name': 'Créer'},
        'machines/machine.html',
        request
    )

415 416 417

@login_required
@can_edit(Ipv6List)
418
def edit_ipv6list(request, ipv6list_instance, **_kwargs):
419
    """Edition d'une ipv6"""
420 421 422 423 424
    ipv6 = Ipv6ListForm(
        request.POST or None,
        instance=ipv6list_instance,
        user=request.user
    )
425
    if ipv6.is_valid():
426 427 428
        if ipv6.changed_data:
            ipv6.save()
            messages.success(request, "Ipv6 modifiée")
429 430
        return redirect(reverse(
            'machines:index-ipv6',
431 432 433 434 435 436 437 438
            kwargs={'interfaceid': str(ipv6list_instance.interface.id)}
        ))
    return form(
        {'ipv6form': ipv6, 'action_name': 'Editer'},
        'machines/machine.html',
        request
    )

439 440 441

@login_required
@can_delete(Ipv6List)
442
def del_ipv6list(request, ipv6list, **_kwargs):
443 444 445
    """ Supprime une ipv6"""
    if request.method == "POST":
        interfaceid = ipv6list.interface.id
446
        ipv6list.delete()
447 448 449
        messages.success(request, "L'ipv6 a été détruite")
        return redirect(reverse(
            'machines:index-ipv6',
450 451 452 453 454 455 456 457
            kwargs={'interfaceid': str(interfaceid)}
        ))
    return form(
        {'objet': ipv6list, 'objet_name': 'ipv6'},
        'machines/delete.html',
        request
    )

458

459
@login_required
460
@can_create(IpType)
461
def add_iptype(request):
462 463
    """ Ajoute un range d'ip. Intelligence dans le models, fonction views
    minimaliste"""
464

465 466
    iptype = IpTypeForm(request.POST or None)
    if iptype.is_valid():
467
        iptype.save()
468
        messages.success(request, "Ce type d'ip a été ajouté")
469
        return redirect(reverse('machines:index-iptype'))
470 471 472 473 474 475
    return form(
        {'iptypeform': iptype, 'action_name': 'Créer'},
        'machines/machine.html',
        request
    )

476 477

@login_required
478
@can_edit(IpType)
479
def edit_iptype(request, iptype_instance, **_kwargs):
480 481
    """ Edition d'un range. Ne permet pas de le redimensionner pour éviter
    l'incohérence"""
482

483
    iptype = EditIpTypeForm(request.POST or None, instance=iptype_instance)
484
    if iptype.is_valid():
485 486 487
        if iptype.changed_data:
            iptype.save()
            messages.success(request, "Type d'ip modifié")
488
        return redirect(reverse('machines:index-iptype'))
489 490 491 492 493 494
    return form(
        {'iptypeform': iptype, 'action_name': 'Editer'},
        'machines/machine.html',
        request
    )

495 496

@login_required
497 498
@can_delete_set(IpType)
def del_iptype(request, instances):
Gabriel Detraz's avatar
Gabriel Detraz committed
499
    """ Suppression d'un range ip. Supprime les objets ip associés"""
500
    iptype = DelIpTypeForm(request.POST or None, instances=instances)
501 502 503 504
    if iptype.is_valid():
        iptype_dels = iptype.cleaned_data['iptypes']
        for iptype_del in iptype_dels:
            try:
505
                iptype_del.delete()
506 507
                messages.success(request, "Le type d'ip a été supprimé")
            except ProtectedError:
508 509 510 511 512
                messages.error(
                    request,
                    ("Le type d'ip %s est affectée à au moins une machine, "
                     "vous ne pouvez pas le supprimer" % iptype_del)
                )
513
        return redirect(reverse('machines:index-iptype'))
514 515 516 517 518 519
    return form(
        {'iptypeform': iptype, 'action_name': 'Supprimer'},
        'machines/machine.html',
        request
    )

520

chirac's avatar
chirac committed
521
@login_required
522
@can_create(MachineType)
523
def add_machinetype(request):
524
    """ View used to add a Machinetype object """
525 526
    machinetype = MachineTypeForm(request.POST or None)
    if machinetype.is_valid():
527
        machinetype.save()
528
        messages.success(request, "Ce type de machine a été ajouté")
529
        return redirect(reverse('machines:index-machinetype'))
530 531 532 533 534 535
    return form(
        {'machinetypeform': machinetype, 'action_name': 'Créer'},
        'machines/machine.html',
        request
    )

536

chirac's avatar
chirac committed
537
@login_required
538
@can_edit(MachineType)
539
def edit_machinetype(request, machinetype_instance, **_kwargs):
540
    """ View used to edit a MachineType object """
541 542 543 544
    machinetype = MachineTypeForm(
        request.POST or None,
        instance=machinetype_instance
    )
545
    if machinetype.is_valid():
546 547 548
        if machinetype.changed_data:
            machinetype.save()
            messages.success(request, "Type de machine modifié")
549
        return redirect(reverse('machines:index-machinetype'))
550 551 552 553 554 555
    return form(
        {'machinetypeform': machinetype, 'action_name': 'Editer'},
        'machines/machine.html',
        request
    )

556

chirac's avatar
chirac committed
557
@login_required
558 559
@can_delete_set(MachineType)
def del_machinetype(request, instances):
560
    """ View used to delete a MachineType object """
561
    machinetype = DelMachineTypeForm(request.POST or None, instances=instances)
562 563 564 565
    if machinetype.is_valid():
        machinetype_dels = machinetype.cleaned_data['machinetypes']
        for machinetype_del in machinetype_dels:
            try:
566
                machinetype_del.delete()
567 568
                messages.success(request, "Le type de machine a été supprimé")
            except ProtectedError:
569 570 571 572 573 574
                messages.error(
                    request,
                    ("Le type de machine %s est affectée à au moins une "
                     "machine, vous ne pouvez pas le supprimer"
                     % machinetype_del)
                )
575
        return redirect(reverse('machines:index-machinetype'))
576 577 578 579 580 581
    return form(
        {'machinetypeform': machinetype, 'action_name': 'Supprimer'},
        'machines/machine.html',
        request
    )

582

583
@login_required
584
@can_create(Extension)
585
def add_extension(request):
586
    """ View used to add an Extension object """
587 588
    extension = ExtensionForm(request.POST or None)
    if extension.is_valid():
589
        extension.save()
590
        messages.success(request, "Cette extension a été ajoutée")
591
        return redirect(reverse('machines:index-extension'))
592 593 594 595 596 597
    return form(
        {'extensionform': extension, 'action_name': 'Créer'},
        'machines/machine.html',
        request
    )

598 599

@login_required
600
@can_edit(Extension)
601
def edit_extension(request, extension_instance, **_kwargs):
602
    """ View used to edit an Extension object """
603 604 605 606
    extension = ExtensionForm(
        request.POST or None,
        instance=extension_instance
    )
607
    if extension.is_valid():
608 609 610
        if extension.changed_data:
            extension.save()
            messages.success(request, "Extension modifiée")
611
        return redirect(reverse('machines:index-extension'))
612 613 614 615 616 617
    return form(
        {'extensionform': extension, 'action_name': 'Editer'},
        'machines/machine.html',
        request
    )

618 619

@login_required
620 621
@can_delete_set(Extension)
def del_extension(request, instances):
622
    """ View used to delete an Extension object """
623
    extension = DelExtensionForm(request.POST or None, instances=instances)
624 625 626 627
    if extension.is_valid():
        extension_dels = extension.cleaned_data['extensions']
        for extension_del in extension_dels:
            try:
628
                extension_del.delete()
629 630
                messages.success(request, "L'extension a été supprimée")
            except ProtectedError:
631 632 633 634 635 636
                messages.error(
                    request,
                    ("L'extension %s est affectée à au moins un type de "
                     "machine, vous ne pouvez pas la supprimer"
                     % extension_del)
                )
637
        return redirect(reverse('machines:index-extension'))
638 639 640 641 642 643
    return form(
        {'extensionform': extension, 'action_name': 'Supprimer'},
        'machines/machine.html',
        request
    )

644

645
@login_required
646
@can_create(SOA)
647
def add_soa(request):
648
    """ View used to add a SOA object """
649 650
    soa = SOAForm(request.POST or None)
    if soa.is_valid():
651
        soa.save()
652
        messages.success(request, "Cet enregistrement SOA a été ajouté")
653
        return redirect(reverse('machines:index-extension'))
654 655 656 657 658 659
    return form(
        {'soaform': soa, 'action_name': 'Créer'},
        'machines/machine.html',
        request
    )

660 661

@login_required
662
@can_edit(SOA)
663
def edit_soa(request, soa_instance, **_kwargs):
664
    """ View used to edit a SOA object """
665 666
    soa = SOAForm(request.POST or None, instance=soa_instance)
    if soa.is_valid():
667 668 669
        if soa.changed_data:
            soa.save()
            messages.success(request, "SOA modifié")
670
        return redirect(reverse('machines:index-extension'))
671 672 673 674 675 676
    return form(
        {'soaform': soa, 'action_name': 'Editer'},
        'machines/machine.html',
        request
    )

677 678

@login_required
679 680
@can_delete_set(SOA)
def del_soa(request, instances):
681
    """ View used to delete a SOA object """
682
    soa = DelSOAForm(request.POST or None, instances=instances)
683 684 685 686
    if soa.is_valid():
        soa_dels = soa.cleaned_data['soa']
        for soa_del in soa_dels:
            try:
687
                soa_del.delete()
688 689
                messages.success(request, "Le SOA a été supprimée")
            except ProtectedError:
690 691 692 693 694
                messages.error(
                    request,
                    ("Erreur le SOA suivant %s ne peut être supprimé"
                     % soa_del)
                )
695
        return redirect(reverse('machines:index-extension'))
696 697 698 699 700 701
    return form(
        {'soaform': soa, 'action_name': 'Supprimer'},
        'machines/machine.html',
        request
    )

702

703
@login_required
704
@can_create(Mx)
705
def add_mx(request):
706
    """ View used to add a MX object """
707 708
    mx = MxForm(request.POST or None)
    if mx.is_valid():
709
        mx.save()
710
        messages.success(request, "Cet enregistrement mx a été ajouté")
711
        return redirect(reverse('machines:index-extension'))
712 713 714 715 716 717
    return form(
        {'mxform': mx, 'action_name': 'Créer'},
        'machines/machine.html',
        request
    )

718 719

@login_required
720
@can_edit(Mx)
721
def edit_mx(request, mx_instance, **_kwargs):
722
    """ View used to edit a MX object """
723 724
    mx = MxForm(request.POST or None, instance=mx_instance)
    if mx.is_valid():
725 726 727
        if mx.changed_data:
            mx.save()
            messages.success(request, "Mx modifié")
728
        return redirect(reverse('machines:index-extension'))
729 730 731 732 733 734
    return form(
        {'mxform': mx, 'action_name': 'Editer'},
        'machines/machine.html',
        request
    )

735 736

@login_required
737 738
@can_delete_set(Mx)
def del_mx(request, instances):
739
    """ View used to delete a MX object """
740
    mx = DelMxForm(request.POST or None, instances=instances)
741 742 743 744
    if mx.is_valid():
        mx_dels = mx.cleaned_data['mx']
        for mx_del in mx_dels:
            try:
745
                mx_del.delete()
746 747
                messages.success(request, "L'mx a été supprimée")
            except ProtectedError:
748 749 750 751 752
                messages.error(
                    request,
                    ("Erreur le Mx suivant %s ne peut être supprimé"
                     % mx_del)
                )
753
        return redirect(reverse('machines:index-extension'))
754 755 756 757 758 759
    return form(
        {'mxform': mx, 'action_name': 'Supprimer'},
        'machines/machine.html',
        request
    )

760

761
@login_required
762
@can_create(Ns)
763
def add_ns(request):
764
    """ View used to add a NS object """
765 766
    ns = NsForm(request.POST or None)
    if ns.is_valid():
767
        ns.save()
768
        messages.success(request, "Cet enregistrement ns a été ajouté")
769
        return redirect(reverse('machines:index-extension'))
770 771 772 773 774 775
    return form(
        {'nsform': ns, 'action_name': 'Créer'},
        'machines/machine.html',
        request
    )

776 777

@login_required
778
@can_edit(Ns)
779
def edit_ns(request, ns_instance, **_kwargs):
780
    """ View used to edit a NS object """
781 782
    ns = NsForm(request.POST or None, instance=ns_instance)
    if ns.is_valid():
783 784 785
        if ns.changed_data:
            ns.save()
            messages.success(request, "Ns modifié")
786
        return redirect(reverse('machines:index-extension'))
787 788 789 790 791 792
    return form(
        {'nsform': ns, 'action_name': 'Editer'},
        'machines/machine.html',
        request
    )

793 794

@login_required
795 796
@can_delete_set(Ns)
def del_ns(request, instances):
797
    """ View used to delete a NS object """
798
    ns = DelNsForm(request.POST or None, instances=instances)
799 800 801 802
    if ns.is_valid():
        ns_dels = ns.cleaned_data['ns']
        for ns_del in ns_dels:
            try:
803
                ns_del.delete()
804 805
                messages.success(request, "Le ns a été supprimée")
            except ProtectedError:
806 807 808 809 810
                messages.error(
                    request,
                    ("Erreur le Ns suivant %s ne peut être supprimé"
                     % ns_del)
                )
811
        return redirect(reverse('machines:index-extension'))
812 813 814 815 816 817
    return form(
        {'nsform': ns, 'action_name': 'Supprimer'},
        'machines/machine.html',
        request
    )

818

Gabriel Detraz's avatar
Gabriel Detraz committed
819
@login_required
820
@can_create(Txt)
821
def add_txt(request):
822
    """ View used to add a TXT object """
823 824
    txt = TxtForm(request.POST or None)
    if txt.is_valid():
825
        txt.save()
Gabriel Detraz's avatar
Gabriel Detraz committed
826
        messages.success(request, "Cet enregistrement text a été ajouté")
827
        return redirect(reverse('machines:index-extension'))
828 829 830 831 832 833
    return form(
        {'txtform': txt, 'action_name': 'Créer'},
        'machines/machine.html',
        request
    )

Gabriel Detraz's avatar
Gabriel Detraz committed
834 835

@login_required
836
@can_edit(Txt)
837
def edit_txt(request, txt_instance, **_kwargs):
838
    """ View used to edit a TXT object """
839 840
    txt = TxtForm(request.POST or None, instance=txt_instance)
    if txt.is_valid():
841 842 843
        if txt.changed_data:
            txt.save()
            messages.success(request, "Txt modifié")
844
        return redirect(reverse('machines:index-extension'))
845 846 847 848 849 850
    return form(
        {'txtform': txt, 'action_name': 'Editer'},
        'machines/machine.html',
        request
    )

Gabriel Detraz's avatar
Gabriel Detraz committed
851 852

@login_required
853 854
@can_delete_set(Txt)
def del_txt(request, instances):
855
    """ View used to delete a TXT object """
856
    txt = DelTxtForm(request.POST or None, instances=instances)
857 858 859
    if txt.is_valid():
        txt_dels = txt.cleaned_data['txt']
        for txt_del in txt_dels:
Gabriel Detraz's avatar
Gabriel Detraz committed
860
            try:
861
                txt_del.delete()
862
                messages.success(request, "Le txt a été supprimé")
Gabriel Detraz's avatar
Gabriel Detraz committed
863
            except ProtectedError:
864 865 866 867 868
                messages.error(
                    request,
                    ("Erreur le Txt suivant %s ne peut être supprimé"
                     % txt_del)
                )
869
        return redirect(reverse('machines:index-extension'))
870 871 872 873 874 875
    return form(
        {'txtform': txt, 'action_name': 'Supprimer'},
        'machines/machine.html',
        request
    )

Gabriel Detraz's avatar
Gabriel Detraz committed
876

Gabriel Detraz's avatar
Gabriel Detraz committed
877
@login_required
878
@can_create(Srv)
Gabriel Detraz's avatar
Gabriel Detraz committed
879
def add_srv(request):
880
    """ View used to add a SRV object """
Gabriel Detraz's avatar
Gabriel Detraz committed
881 882
    srv = SrvForm(request.POST or None)
    if srv.is_valid():
883
        srv.save()
Gabriel Detraz's avatar
Gabriel Detraz committed
884 885
        messages.success(request, "Cet enregistrement srv a été ajouté")
        return redirect(reverse('machines:index-extension'))
886 887 888 889 890 891
    return form(
        {'srvform': srv, 'action_name': 'Créer'},
        'machines/machine.html',
        request
    )

Gabriel Detraz's avatar
Gabriel Detraz committed
892 893

@login_required
894
@can_edit(Srv)
895
def edit_srv(request, srv_instance, **_kwargs):
896
    """ View used to edit a SRV object """
Gabriel Detraz's avatar
Gabriel Detraz committed
897 898
    srv = SrvForm(request.POST or None, instance=srv_instance)
    if srv.is_valid():
899 900 901
        if srv.changed_data:
            srv.save()
            messages.success(request, "Srv modifié")
Gabriel Detraz's avatar
Gabriel Detraz committed
902
        return redirect(reverse('machines:index-extension'))
903 904 905 906 907 908
    return form(
        {'srvform': srv, 'action_name': 'Editer'},
        'machines/machine.html',
        request
    )

Gabriel Detraz's avatar
Gabriel Detraz committed
909 910

@login_required
911 912
@can_delete_set(Srv)
def del_srv(request, instances):
913
    """ View used to delete a SRV object """
914
    srv = DelSrvForm(request.POST or None, instances=instances)
Gabriel Detraz's avatar
Gabriel Detraz committed
915 916 917 918
    if srv.is_valid():
        srv_dels = srv.cleaned_data['srv']
        for srv_del in srv_dels:
            try:
919
                srv_del.delete()
Gabriel Detraz's avatar
Gabriel Detraz committed
920 921
                messages.success(request, "L'srv a été supprimée")
            except ProtectedError:
922 923 924 925 926
                messages.error(
                    request,
                    ("Erreur le Srv suivant %s ne peut être supprimé"
                     % srv_del)
                )
Gabriel Detraz's avatar
Gabriel Detraz committed
927
        return redirect(reverse('machines:index-extension'))
928 929 930 931 932 933
    return form(
        {'srvform': srv, 'action_name': 'Supprimer'},
        'machines/machine.html',
        request
    )

Gabriel Detraz's avatar
Gabriel Detraz committed
934

935
@login_required
936
@can_create(Domain)
937 938
@can_edit(Interface)
def add_alias(request, interface, interfaceid):
939
    """ View used to add an Alias object """
940
    alias = AliasForm(request.POST or None, user=request.user)
941 942
    if alias.is_valid():
        alias = alias.save(commit=False)
chirac's avatar
chirac committed
943
        alias.cname = interface.domain
944
        alias.save()
945
        messages.success(request, "Cet alias a été ajouté")
946
        return redirect(reverse(
947
            'machines:index-alias',
948 949 950 951 952 953 954 955
            kwargs={'interfaceid': str(interfaceid)}
        ))
    return form(
        {'aliasform': alias, 'action_name': 'Créer'},
        'machines/machine.html',
        request
    )

956 957

@login_required
958
@can_edit(Domain)
959
def edit_alias(request, domain_instance, **_kwargs):
960
    """ View used to edit an Alias object """
961 962 963 964 965
    alias = AliasForm(
        request.POST or None,
        instance=domain_instance,
        user=request.user
    )
966
    if alias.is_valid():
967 968 969
        if alias.changed_data:
            domain_instance = alias.save()
            messages.success(request, "Alias modifié")
970
        return redirect(reverse(
971
            'machines:index-alias',
972 973 974 975 976 977 978 979 980 981
            kwargs={
                'interfaceid': str(domain_instance.cname.interface_parent.id)
            }
        ))
    return form(
        {'aliasform': alias, 'action_name': 'Editer'},
        'machines/machine.html',
        request
    )

982 983

@login_required
984 985
@can_edit(Interface)
def del_alias(request, interface, interfaceid):
986
    """ View used to delete an Alias object """
987 988 989 990 991
    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:
992
                alias_del.delete()
993 994 995 996
                messages.success(
                    request,
                    "L'alias %s a été supprimé" % alias_del
                )
997
            except ProtectedError:
998 999 1000 1001 1002
                messages.error(
                    request,
                    ("Erreur l'alias suivant %s ne peut être supprimé"
                     % alias_del)
                )
1003
        return redirect(reverse(
1004
            'machines:index-alias',
1005 1006 1007 1008 1009 1010 1011
            kwargs={'interfaceid': str(interfaceid)}
        ))
    return form(
        {'aliasform': alias, 'action_name': 'Supprimer'},
        'machines/machine.html',
        request
    )
1012

1013 1014

@login_required
1015
@can_create(Service)
1016
def add_service(request):
1017
    """ View used to add a Service object """
1018 1019
    service = ServiceForm(request.POST or None)
    if service.is_valid():
1020
        service.save()
1021
        messages.success(request, "Cet enregistrement service a été ajouté")
1022
        return redirect(reverse('machines:index-service'))
1023 1024 1025 1026 1027 1028
    return form(
        {'serviceform': service, 'action_name': 'Créer'},
        'machines/machine.html',
        request
    )

1029 1030

@login_required
1031
@can_edit(Service)
1032
def edit_service(request, service_instance, **_kwargs):
1033
    """ View used to edit a Service object """
1034 1035
    service = ServiceForm(request.POST or None, instance=service_instance)
    if service.is_valid():
1036 1037 1038
        if service.changed_data:
            service.save()
            messages.success(request, "Service modifié")
1039
        return redirect(reverse('machines:index-service'))
1040 1041 1042 1043 1044 1045
    return form(
        {'serviceform': service, 'action_name': 'Editer'},
        'machines/machine.html',
        request
    )

1046 1047

@login_required
1048 1049
@can_delete_set(Service)
def del_service(request, instances):
1050
    """ View used to delete a Service object """
1051
    service = DelServiceForm(request.POST or None, instances=instances)
1052 1053 1054 1055
    if service.is_valid():
        service_dels = service.cleaned_data['service']
        for service_del in service_dels:
            try:
1056
                service_del.delete()
1057 1058
                messages.success(request, "Le service a été supprimée")
            except ProtectedError:
1059 1060 1061 1062 1063
                messages.error(
                    request,
                    ("Erreur le service suivant %s ne peut être supprimé"
                     % service_del)
                )
1064
        return redirect(reverse('machines:index-service'))
1065 1066 1067 1068 1069 1070
    return form(
        {'serviceform': service, 'action_name': 'Supprimer'},
        'machines/machine.html',
        request
    )

1071

1072
@login_required
1073
@can_create(Vlan)
1074
def add_vlan(request):
1075
    """ View used to add a VLAN object """
1076 1077
    vlan = VlanForm(request.POST or None)
    if vlan.is_valid():
1078
        vlan.save()
1079
        messages.success(request, "Cet enregistrement vlan a été ajouté")
1080
        return redirect(reverse('machines:index-vlan'))
1081 1082 1083 1084 1085 1086
    return form(
        {'vlanform': vlan, 'action_name': 'Créer'},
        'machines/machine.html',
        request
    )

1087 1088

@login_required
1089
@can_edit(Vlan)
1090
def edit_vlan(request, vlan_instance, **_kwargs):
1091
    """ View used to edit a VLAN object """
1092 1093
    vlan = VlanForm(request.POST or None, instance=vlan_instance)
    if vlan.is_valid():
1094 1095 1096
        if vlan.changed_data:
            vlan.save()
            messages.success(request, "Vlan modifié")
1097
        return redirect(reverse('machines:index-vlan'))
1098 1099 1100 1101 1102 1103
    return form(
        {'vlanform': vlan, 'action_name': 'Editer'},
        'machines/machine.html',
        request
    )

1104 1105

@login_required
1106 1107
@can_delete_set(Vlan)
def del_vlan(request, instances):
1108
    """ View used to delete a VLAN object """
1109
    vlan = DelVlanForm(request.POST or None, instances=instances)
1110 1111
    if vlan.is_valid():
        vlan_dels = vlan.cleaned_data['vlan']
1112
        for vlan_del in vlan_dels:
1113
            try:
1114
                vlan_del.delete()
1115 1116
                messages.success(request, "Le vlan a été supprimée")
            except ProtectedError:
1117 1118 1119 1120 1121
                messages.error(
                    request,
                    ("Erreur le Vlan suivant %s ne peut être supprimé"
                     % vlan_del)
                )
1122
        return redirect(reverse('machines:index-vlan'))
1123 1124 1125 1126 1127 1128
    return form(
        {'vlanform': vlan, 'action_name': 'Supprimer'},
        'machines/machine.html',
        request
    )

1129

1130
@login_required
1131
@can_create(Nas)
1132
def add_nas(request):
1133
    """ View used to add a NAS object """
1134 1135
    nas = NasForm(request.POST or None)
    if nas.is_valid():
1136
        nas.save()
1137
        messages.success(request, "Cet enregistrement nas a été ajouté")
1138
        return redirect(reverse('machines:index-nas'))
1139 1140 1141 1142 1143 1144
    return form(
        {'nasform': nas, 'action_name': 'Créer'},
        'machines/machine.html',
        request
    )

1145 1146

@login_required
1147
@can_edit(Nas)
1148
def edit_nas(request, nas_instance, **_kwargs):
1149
    """ View used to edit a NAS object """
1150 1151
    nas = NasForm(request.POST or None, instance=nas_instance)
    if nas.is_valid():
1152 1153 1154
        if nas.changed_data:
            nas.save()
            messages.success(request, "Nas modifié")
1155
        return redirect(reverse('machines:index-nas'))
1156 1157 1158 1159 1160 1161
    return form(
        {'nasform': nas, 'action_name': 'Editer'},
        'machines/machine.html',
        request
    )

1162 1163

@login_required
1164 1165
@can_delete_set(Nas)
def del_nas(request, instances):
1166
    """ View used to delete a NAS object """
1167
    nas = DelNasForm(request.POST or None, instances=instances)
1168 1169 1170 1171
    if nas.is_valid():
        nas_dels = nas.cleaned_data['nas']
        for nas_del in nas_dels:
            try:
1172
                nas_del.delete()
1173 1174
                messages.success(request, "Le nas a été supprimé")
            except ProtectedError:
1175 1176 1177 1178 1179
                messages.error(
                    request,
                    ("Erreur le Nas suivant %s ne peut être supprimé"
                     % nas_del)
                )
1180
        return redirect(reverse('machines:index-nas'))
1181 1182 1183 1184 1185 1186
    return form(
        {'nasform': nas, 'action_name': 'Supprimer'},
        'machines/machine.html',
        request
    )

1187

chirac's avatar
chirac committed
1188
@login_required
1189
@can_view_all(Machine)
1190
def index(request):
1191 1192
    """ The home view for this app. Displays the list of registered
    machines in Re2o """
1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203