From 68341c55b31462a7fededa8494665a57841be7dc Mon Sep 17 00:00:00 2001 From: Arthur Date: Fri, 16 Jun 2023 11:32:54 -0700 Subject: [PATCH] 12591 restore view --- netbox/extras/tables/tables.py | 9 +++ netbox/extras/urls.py | 1 + netbox/extras/views.py | 37 +++++++++ .../extras/configrevision_restore.html | 75 +++++++++++++++++++ 4 files changed, 122 insertions(+) create mode 100644 netbox/templates/extras/configrevision_restore.html diff --git a/netbox/extras/tables/tables.py b/netbox/extras/tables/tables.py index f5de07f33..3ec9e298a 100644 --- a/netbox/extras/tables/tables.py +++ b/netbox/extras/tables/tables.py @@ -31,11 +31,20 @@ IMAGEATTACHMENT_IMAGE = ''' {% endif %} ''' +REVISION_BUTTONS = """ +{% if not record.is_active %} + + + +{% endif %} +""" + class ConfigRevisionTable(NetBoxTable): is_active = columns.BooleanColumn() actions = columns.ActionsColumn( actions=('edit', 'delete'), + extra_buttons=REVISION_BUTTONS ) class Meta(NetBoxTable.Meta): diff --git a/netbox/extras/urls.py b/netbox/extras/urls.py index 5144fa004..55d1d9e06 100644 --- a/netbox/extras/urls.py +++ b/netbox/extras/urls.py @@ -120,5 +120,6 @@ urlpatterns = [ path('config-revision/', views.ConfigRevisionListView.as_view(), name='configrevision'), path('config-revision/add/', views.ConfigRevisionEditView.as_view(), name='configrevision_add'), path('config-revision/delete/', views.ConfigRevisionBulkDeleteView.as_view(), name='configrevision_bulk_delete'), + path('config-revision//restore', views.ConfigRevisionRestoreView.as_view(), name='configrevision_restore'), path('config-revision//', include(get_model_urls('extras', 'configrevision'))), ] diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 9db31adea..dfc5427aa 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -14,6 +14,7 @@ from core.models import Job from core.tables import JobTable from extras.dashboard.forms import DashboardWidgetAddForm, DashboardWidgetForm from extras.dashboard.utils import get_widget_class +from netbox.config import get_config, PARAMS from netbox.views import generic from utilities.forms import ConfirmationForm, get_field_value from utilities.htmx import is_htmx @@ -1223,3 +1224,39 @@ class ConfigRevisionBulkDeleteView(generic.BulkDeleteView): queryset = ConfigRevision.objects.all() filterset = filtersets.ConfigRevisionFilterSet table = tables.ConfigRevisionTable + + +class ConfigRevisionRestoreView(ContentTypePermissionRequiredMixin, View): + + def get_required_permission(self): + return 'extras.configrevision_edit' + + def get(self, request, pk): + candidate_config = get_object_or_404(ConfigRevision, pk=pk) + + # Get the current ConfigRevision + config_version = get_config().version + current_config = ConfigRevision.objects.filter(pk=config_version).first() + + params = [] + for param in PARAMS: + params.append(( + param.name, + current_config.data.get(param.name, None), + candidate_config.data.get(param.name, None) + )) + + return render(request, 'extras/configrevision_restore.html', { + 'object': candidate_config, + 'params': params, + }) + + def post(self, request, pk): + if not request.user.has_perm('extras.configrevision_edit'): + return HttpResponseForbidden() + + candidate_config = get_object_or_404(ConfigRevision, pk=pk) + candidate_config.activate() + self.message_user(request, f"Restored configuration revision #{pk}") + + return redirect(reverse('admin:extras_configrevision_changelist')) diff --git a/netbox/templates/extras/configrevision_restore.html b/netbox/templates/extras/configrevision_restore.html new file mode 100644 index 000000000..5f287e859 --- /dev/null +++ b/netbox/templates/extras/configrevision_restore.html @@ -0,0 +1,75 @@ +{% extends 'base/layout.html' %} +{% load helpers %} +{% load buttons %} +{% load perms %} +{% load static %} + +{% block title %}{{ script }}{% endblock %} + +{% block subtitle %} + {{ script.Meta.description|markdown }} +{% endblock %} + +{% block header %} +
+
+ +
+
+ {{ block.super }} +{% endblock header %} + +{% block controls %} +
+
+ {% if request.user|can_delete:job %} + {% delete_button job %} + {% endif %} +
+
+{% endblock controls %} + +{% block content %} + +
+
+
+ +

Restore configuration #{{ object.pk }} from {{ object.created }}?

+ + + + + + + + + + + + {% for param, current, new in params %} + + + + + + + {% endfor %} + +
ParameterCurrent ValueNew Value
{{ param }}{{ current }}{{ new }}{% if current != new %}*{% endif %}
+ +
+
+
+{% endblock content %} + +{% block modals %} +{% endblock modals %}