| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- from django.contrib import admin
- from django.shortcuts import get_object_or_404, redirect
- from django.template.response import TemplateResponse
- from django.urls import path, reverse
- from django.utils.html import format_html
- from netbox.config import get_config, PARAMS
- from .forms import ConfigRevisionForm
- from .models import ConfigRevision
- @admin.register(ConfigRevision)
- class ConfigRevisionAdmin(admin.ModelAdmin):
- fieldsets = [
- ('Rack Elevations', {
- 'fields': ('RACK_ELEVATION_DEFAULT_UNIT_HEIGHT', 'RACK_ELEVATION_DEFAULT_UNIT_WIDTH'),
- }),
- ('Power', {
- 'fields': ('POWERFEED_DEFAULT_VOLTAGE', 'POWERFEED_DEFAULT_AMPERAGE', 'POWERFEED_DEFAULT_MAX_UTILIZATION')
- }),
- ('IPAM', {
- 'fields': ('ENFORCE_GLOBAL_UNIQUE', 'PREFER_IPV4'),
- }),
- ('Security', {
- 'fields': ('ALLOWED_URL_SCHEMES',),
- }),
- ('Banners', {
- 'fields': ('BANNER_LOGIN', 'BANNER_MAINTENANCE', 'BANNER_TOP', 'BANNER_BOTTOM'),
- 'classes': ('monospace',),
- }),
- ('Pagination', {
- 'fields': ('PAGINATE_COUNT', 'MAX_PAGE_SIZE'),
- }),
- ('Validation', {
- 'fields': ('CUSTOM_VALIDATORS',),
- 'classes': ('monospace',),
- }),
- ('User Preferences', {
- 'fields': ('DEFAULT_USER_PREFERENCES',),
- }),
- ('Miscellaneous', {
- 'fields': ('MAINTENANCE_MODE', 'GRAPHQL_ENABLED', 'CHANGELOG_RETENTION', 'JOB_RETENTION', 'MAPS_URL'),
- }),
- ('Config Revision', {
- 'fields': ('comment',),
- })
- ]
- form = ConfigRevisionForm
- list_display = ('id', 'is_active', 'created', 'comment', 'restore_link')
- ordering = ('-id',)
- readonly_fields = ('data',)
- def get_changeform_initial_data(self, request):
- """
- Populate initial form data from the most recent ConfigRevision.
- """
- latest_revision = ConfigRevision.objects.last()
- initial = latest_revision.data if latest_revision else {}
- initial.update(super().get_changeform_initial_data(request))
- return initial
- # Permissions
- def has_add_permission(self, request):
- # Only superusers may modify the configuration.
- return request.user.is_superuser
- def has_change_permission(self, request, obj=None):
- # ConfigRevisions cannot be modified once created.
- return False
- def has_delete_permission(self, request, obj=None):
- # Only inactive ConfigRevisions may be deleted (must be superuser).
- return request.user.is_superuser and (
- obj is None or not obj.is_active()
- )
- # List display methods
- def restore_link(self, obj):
- if obj.is_active():
- return ''
- return format_html(
- '<a href="{url}" class="button">Restore</a>',
- url=reverse('admin:extras_configrevision_restore', args=(obj.pk,))
- )
- restore_link.short_description = "Actions"
- # URLs
- def get_urls(self):
- urls = [
- path('<int:pk>/restore/', self.admin_site.admin_view(self.restore), name='extras_configrevision_restore'),
- ]
- return urls + super().get_urls()
- # Views
- def restore(self, request, pk):
- # Get the ConfigRevision being restored
- candidate_config = get_object_or_404(ConfigRevision, pk=pk)
- if request.method == 'POST':
- candidate_config.activate()
- self.message_user(request, f"Restored configuration revision #{pk}")
- return redirect(reverse('admin:extras_configrevision_changelist'))
- # 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)
- ))
- context = self.admin_site.each_context(request)
- context.update({
- 'object': candidate_config,
- 'params': params,
- })
- return TemplateResponse(request, 'admin/extras/configrevision/restore.html', context)
|