diff --git a/netbox/extras/urls.py b/netbox/extras/urls.py index c4fc3d938..811576b3c 100644 --- a/netbox/extras/urls.py +++ b/netbox/extras/urls.py @@ -114,5 +114,9 @@ urlpatterns = [ path('scripts///jobs/', views.ScriptJobsView.as_view(), name='script_jobs'), # Markdown - path('render/markdown/', views.RenderMarkdownView.as_view(), name="render_markdown") + path('render/markdown/', views.RenderMarkdownView.as_view(), name="render_markdown"), + + # Config Revision + path('config-revision/', views.ConfigRevisionView.as_view(), name='config_revision'), + ] diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 6cbadf09d..81bea84f1 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -1189,3 +1189,20 @@ class RenderMarkdownView(View): rendered = render_markdown(form.cleaned_data['text']) return HttpResponse(rendered) + + +# +# Config Revision +# + +class ConfigRevisionView(generic.ObjectView): + queryset = ConfigRevision.objects.all() + + def get(self, request, **kwargs): + instance = ConfigRevision.objects.last() + + return render(request, self.get_template_name(), { + 'object': instance, + 'tab': self.tab, + **self.get_extra_context(request, instance), + }) diff --git a/netbox/netbox/navigation/menu.py b/netbox/netbox/navigation/menu.py index 6e5bcfc23..21fdb74cf 100644 --- a/netbox/netbox/navigation/menu.py +++ b/netbox/netbox/navigation/menu.py @@ -344,6 +344,22 @@ OPERATIONS_MENU = Menu( ), ) +ADMIN_MENU = Menu( + label=_('Admin'), + icon_class='mdi mdi-account-multiple', + groups=( + MenuGroup( + label=_('Configuration'), + items=( + MenuItem( + link='extras:config_revision', + link_text=_('Config Revision'), + permissions=['extras.config_revision'] + ), + ), + ), + ), +) MENUS = [ ORGANIZATION_MENU, @@ -358,6 +374,7 @@ MENUS = [ PROVISIONING_MENU, CUSTOMIZATION_MENU, OPERATIONS_MENU, + ADMIN_MENU, ] # diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index 43ca9a589..a45e149c7 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -5,6 +5,7 @@ from django.urls.exceptions import NoReverseMatch from netbox.registry import registry from .permissions import resolve_permission +from .querysets import RestrictedQuerySet __all__ = ( 'ContentTypePermissionRequiredMixin', @@ -93,7 +94,7 @@ class ObjectPermissionRequiredMixin(AccessMixin): 'a base queryset'.format(self.__class__.__name__) ) - if not self.has_permission(): + if isinstance(self.queryset, RestrictedQuerySet) and not self.has_permission(): return self.handle_no_permission() return super().dispatch(request, *args, **kwargs)