Skip to content

Commit 148278a

Browse files
12591 config params admin (#12904)
* 12591 initial commit * 12591 detail view * 12591 add/edit view * 12591 edit button * 12591 base views and forms * 12591 form cleanup * 12591 form cleanup * 12591 form cleanup * 12591 review changes * 12591 move check for restrictedqueryset * 12591 restore view * 12591 restore page styling * 12591 remove admin * Remove edit view for ConfigRevision instances * Order ConfigRevisions by creation time * Correct permission name * Use RestrictedQuerySet for ConfigRevision * Fix redirect URL --------- Co-authored-by: Jeremy Stretch <[email protected]>
1 parent 48b2ab3 commit 148278a

File tree

16 files changed

+567
-252
lines changed

16 files changed

+567
-252
lines changed

netbox/extras/admin.py

+1-128
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,2 @@
1-
from django.contrib import admin
2-
from django.shortcuts import get_object_or_404, redirect
3-
from django.template.response import TemplateResponse
4-
from django.urls import path, reverse
5-
from django.utils.html import format_html
6-
7-
from netbox.config import get_config, PARAMS
1+
# TODO: Removing this import triggers an import loop due to how form mixins are currently organized
82
from .forms import ConfigRevisionForm
9-
from .models import ConfigRevision
10-
11-
12-
@admin.register(ConfigRevision)
13-
class ConfigRevisionAdmin(admin.ModelAdmin):
14-
fieldsets = [
15-
('Rack Elevations', {
16-
'fields': ('RACK_ELEVATION_DEFAULT_UNIT_HEIGHT', 'RACK_ELEVATION_DEFAULT_UNIT_WIDTH'),
17-
}),
18-
('Power', {
19-
'fields': ('POWERFEED_DEFAULT_VOLTAGE', 'POWERFEED_DEFAULT_AMPERAGE', 'POWERFEED_DEFAULT_MAX_UTILIZATION')
20-
}),
21-
('IPAM', {
22-
'fields': ('ENFORCE_GLOBAL_UNIQUE', 'PREFER_IPV4'),
23-
}),
24-
('Security', {
25-
'fields': ('ALLOWED_URL_SCHEMES',),
26-
}),
27-
('Banners', {
28-
'fields': ('BANNER_LOGIN', 'BANNER_MAINTENANCE', 'BANNER_TOP', 'BANNER_BOTTOM'),
29-
'classes': ('monospace',),
30-
}),
31-
('Pagination', {
32-
'fields': ('PAGINATE_COUNT', 'MAX_PAGE_SIZE'),
33-
}),
34-
('Validation', {
35-
'fields': ('CUSTOM_VALIDATORS',),
36-
'classes': ('monospace',),
37-
}),
38-
('User Preferences', {
39-
'fields': ('DEFAULT_USER_PREFERENCES',),
40-
}),
41-
('Miscellaneous', {
42-
'fields': ('MAINTENANCE_MODE', 'GRAPHQL_ENABLED', 'CHANGELOG_RETENTION', 'JOB_RETENTION', 'MAPS_URL'),
43-
}),
44-
('Config Revision', {
45-
'fields': ('comment',),
46-
})
47-
]
48-
form = ConfigRevisionForm
49-
list_display = ('id', 'is_active', 'created', 'comment', 'restore_link')
50-
ordering = ('-id',)
51-
readonly_fields = ('data',)
52-
53-
def get_changeform_initial_data(self, request):
54-
"""
55-
Populate initial form data from the most recent ConfigRevision.
56-
"""
57-
latest_revision = ConfigRevision.objects.last()
58-
initial = latest_revision.data if latest_revision else {}
59-
initial.update(super().get_changeform_initial_data(request))
60-
61-
return initial
62-
63-
# Permissions
64-
65-
def has_add_permission(self, request):
66-
# Only superusers may modify the configuration.
67-
return request.user.is_superuser
68-
69-
def has_change_permission(self, request, obj=None):
70-
# ConfigRevisions cannot be modified once created.
71-
return False
72-
73-
def has_delete_permission(self, request, obj=None):
74-
# Only inactive ConfigRevisions may be deleted (must be superuser).
75-
return request.user.is_superuser and (
76-
obj is None or not obj.is_active()
77-
)
78-
79-
# List display methods
80-
81-
def restore_link(self, obj):
82-
if obj.is_active():
83-
return ''
84-
return format_html(
85-
'<a href="{url}" class="button">Restore</a>',
86-
url=reverse('admin:extras_configrevision_restore', args=(obj.pk,))
87-
)
88-
restore_link.short_description = "Actions"
89-
90-
# URLs
91-
92-
def get_urls(self):
93-
urls = [
94-
path('<int:pk>/restore/', self.admin_site.admin_view(self.restore), name='extras_configrevision_restore'),
95-
]
96-
97-
return urls + super().get_urls()
98-
99-
# Views
100-
101-
def restore(self, request, pk):
102-
# Get the ConfigRevision being restored
103-
candidate_config = get_object_or_404(ConfigRevision, pk=pk)
104-
105-
if request.method == 'POST':
106-
candidate_config.activate()
107-
self.message_user(request, f"Restored configuration revision #{pk}")
108-
109-
return redirect(reverse('admin:extras_configrevision_changelist'))
110-
111-
# Get the current ConfigRevision
112-
config_version = get_config().version
113-
current_config = ConfigRevision.objects.filter(pk=config_version).first()
114-
115-
params = []
116-
for param in PARAMS:
117-
params.append((
118-
param.name,
119-
current_config.data.get(param.name, None),
120-
candidate_config.data.get(param.name, None)
121-
))
122-
123-
context = self.admin_site.each_context(request)
124-
context.update({
125-
'object': candidate_config,
126-
'params': params,
127-
})
128-
129-
return TemplateResponse(request, 'admin/extras/configrevision/restore.html', context)

netbox/extras/filtersets.py

+25
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
__all__ = (
1818
'ConfigContextFilterSet',
19+
'ConfigRevisionFilterSet',
1920
'ConfigTemplateFilterSet',
2021
'ContentTypeFilterSet',
2122
'CustomFieldFilterSet',
@@ -557,3 +558,27 @@ def search(self, queryset, name, value):
557558
Q(app_label__icontains=value) |
558559
Q(model__icontains=value)
559560
)
561+
562+
563+
#
564+
# ConfigRevisions
565+
#
566+
567+
class ConfigRevisionFilterSet(BaseFilterSet):
568+
q = django_filters.CharFilter(
569+
method='search',
570+
label=_('Search'),
571+
)
572+
573+
class Meta:
574+
model = ConfigRevision
575+
fields = [
576+
'id',
577+
]
578+
579+
def search(self, queryset, name, value):
580+
if not value.strip():
581+
return queryset
582+
return queryset.filter(
583+
Q(comment__icontains=value)
584+
)

netbox/extras/forms/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@
44
from .bulk_import import *
55
from .misc import *
66
from .mixins import *
7-
from .config import *
87
from .scripts import *

netbox/extras/forms/config.py

-82
This file was deleted.

netbox/extras/forms/filtersets.py

+7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
__all__ = (
2020
'ConfigContextFilterForm',
21+
'ConfigRevisionFilterForm',
2122
'ConfigTemplateFilterForm',
2223
'CustomFieldFilterForm',
2324
'CustomLinkFilterForm',
@@ -444,3 +445,9 @@ class ObjectChangeFilterForm(SavedFiltersMixin, FilterForm):
444445
api_url='/api/extras/content-types/',
445446
)
446447
)
448+
449+
450+
class ConfigRevisionFilterForm(SavedFiltersMixin, FilterForm):
451+
fieldsets = (
452+
(None, ('q', 'filter_id')),
453+
)

0 commit comments

Comments
 (0)