|
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 |
8 | 2 | 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) |
0 commit comments