-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* 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 <jstretch@netboxlabs.com>
- Loading branch information
1 parent
48b2ab3
commit 148278a
Showing
16 changed files
with
567 additions
and
252 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,129 +1,2 @@ | ||
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 | ||
# TODO: Removing this import triggers an import loop due to how form mixins are currently organized | ||
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,5 +4,4 @@ | |
from .bulk_import import * | ||
from .misc import * | ||
from .mixins import * | ||
from .config import * | ||
from .scripts import * |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.