From 71d4b5c5df03bdc4479207670f763686e597cb3d Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 22 May 2020 09:45:29 -0400 Subject: [PATCH] Enforce object-level permissions for circuit termination swap view --- netbox/circuits/urls.py | 3 +- netbox/circuits/views.py | 71 +++++++++++++++++++++++++--------------- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/netbox/circuits/urls.py b/netbox/circuits/urls.py index 1a7fa283b..1c0f0715b 100644 --- a/netbox/circuits/urls.py +++ b/netbox/circuits/urls.py @@ -37,10 +37,9 @@ urlpatterns = [ path('circuits//edit/', views.CircuitEditView.as_view(), name='circuit_edit'), path('circuits//delete/', views.CircuitDeleteView.as_view(), name='circuit_delete'), path('circuits//changelog/', ObjectChangeLogView.as_view(), name='circuit_changelog', kwargs={'model': Circuit}), - path('circuits//terminations/swap/', views.circuit_terminations_swap, name='circuit_terminations_swap'), + path('circuits//terminations/swap/', views.CircuitSwapTerminations.as_view(), name='circuit_terminations_swap'), # Circuit terminations - path('circuits//terminations/add/', views.CircuitTerminationEditView.as_view(), name='circuittermination_add'), path('circuit-terminations//edit/', views.CircuitTerminationEditView.as_view(), name='circuittermination_edit'), path('circuit-terminations//delete/', views.CircuitTerminationDeleteView.as_view(), name='circuittermination_delete'), diff --git a/netbox/circuits/views.py b/netbox/circuits/views.py index 1f5f05230..bb4d787c8 100644 --- a/netbox/circuits/views.py +++ b/netbox/circuits/views.py @@ -1,6 +1,5 @@ from django.conf import settings from django.contrib import messages -from django.contrib.auth.decorators import permission_required from django.db import transaction from django.db.models import Count, OuterRef from django.shortcuts import get_object_or_404, redirect, render @@ -191,25 +190,47 @@ class CircuitBulkDeleteView(BulkDeleteView): default_return_url = 'circuits:circuit_list' -@permission_required('circuits.change_circuittermination') -def circuit_terminations_swap(request, pk): +class CircuitSwapTerminations(ObjectEditView): + """ + Swap the A and Z terminations of a circuit. + """ + queryset = Circuit.objects.all() - circuit = get_object_or_404(Circuit, pk=pk) - termination_a = CircuitTermination.objects.filter( - circuit=circuit, term_side=CircuitTerminationSideChoices.SIDE_A - ).first() - termination_z = CircuitTermination.objects.filter( - circuit=circuit, term_side=CircuitTerminationSideChoices.SIDE_Z - ).first() - if not termination_a and not termination_z: - messages.error(request, "No terminations have been defined for circuit {}.".format(circuit)) - return redirect('circuits:circuit', pk=circuit.pk) + def get(self, request, pk): + circuit = get_object_or_404(self.queryset, pk=pk) + form = ConfirmationForm() - if request.method == 'POST': + # Circuit must have at least one termination to swap + if not circuit.termination_a and not circuit.termination_z: + messages.error(request, "No terminations have been defined for circuit {}.".format(circuit)) + return redirect('circuits:circuit', pk=circuit.pk) + + return render(request, 'circuits/circuit_terminations_swap.html', { + 'circuit': circuit, + 'termination_a': circuit.termination_a, + 'termination_z': circuit.termination_z, + 'form': form, + 'panel_class': 'default', + 'button_class': 'primary', + 'return_url': circuit.get_absolute_url(), + }) + + def post(self, request, pk): + circuit = get_object_or_404(self.queryset, pk=pk) form = ConfirmationForm(request.POST) + if form.is_valid(): + + termination_a = CircuitTermination.objects.filter( + circuit=circuit, term_side=CircuitTerminationSideChoices.SIDE_A + ).first() + termination_z = CircuitTermination.objects.filter( + circuit=circuit, term_side=CircuitTerminationSideChoices.SIDE_Z + ).first() + if termination_a and termination_z: # Use a placeholder to avoid an IntegrityError on the (circuit, term_side) unique constraint + print('swapping') with transaction.atomic(): termination_a.term_side = '_' termination_a.save() @@ -223,21 +244,19 @@ def circuit_terminations_swap(request, pk): else: termination_z.term_side = 'A' termination_z.save() + messages.success(request, "Swapped terminations for circuit {}.".format(circuit)) return redirect('circuits:circuit', pk=circuit.pk) - else: - form = ConfirmationForm() - - return render(request, 'circuits/circuit_terminations_swap.html', { - 'circuit': circuit, - 'termination_a': termination_a, - 'termination_z': termination_z, - 'form': form, - 'panel_class': 'default', - 'button_class': 'primary', - 'return_url': circuit.get_absolute_url(), - }) + return render(request, 'circuits/circuit_terminations_swap.html', { + 'circuit': circuit, + 'termination_a': circuit.termination_a, + 'termination_z': circuit.termination_z, + 'form': form, + 'panel_class': 'default', + 'button_class': 'primary', + 'return_url': circuit.get_absolute_url(), + }) #