Просмотр исходного кода

Closes #16580: Remove `AUTH_EXEMPT_PATHS` (#16662)

* Closes #16580: Remove AUTH_EXEMPT_PATHS

* Misc cleanup
Jeremy Stretch 1 год назад
Родитель
Сommit
c22463f4aa

+ 1 - 1
netbox/extras/views.py

@@ -1200,7 +1200,7 @@ class ScriptResultView(TableMixin, generic.ObjectView):
 # Markdown
 #
 
-class RenderMarkdownView(View):
+class RenderMarkdownView(LoginRequiredMixin, View):
 
     def post(self, request):
         form = forms.RenderMarkdownForm(request.POST)

+ 0 - 11
netbox/netbox/middleware.py

@@ -1,6 +1,5 @@
 import logging
 import uuid
-from urllib import parse
 
 from django.conf import settings
 from django.contrib import auth, messages
@@ -33,16 +32,6 @@ class CoreMiddleware:
         # Assign a random unique ID to the request. This will be used for change logging.
         request.id = uuid.uuid4()
 
-        # Enforce the LOGIN_REQUIRED config parameter. If true, redirect all non-exempt unauthenticated requests
-        # to the login page.
-        if (
-            settings.LOGIN_REQUIRED and
-            not request.user.is_authenticated and
-            not request.path_info.startswith(settings.AUTH_EXEMPT_PATHS)
-        ):
-            login_url = f'{settings.LOGIN_URL}?next={parse.quote(request.get_full_path_info())}'
-            return HttpResponseRedirect(login_url)
-
         # Enable the event_tracking context manager and process the request.
         with event_tracking(request):
             response = self.get_response(request)

+ 0 - 9
netbox/netbox/settings.py

@@ -502,15 +502,6 @@ EXEMPT_EXCLUDE_MODELS = (
     ('users', 'user'),
 )
 
-# All URLs starting with a string listed here are exempt from login enforcement
-AUTH_EXEMPT_PATHS = (
-    f'/{BASE_PATH}api/',
-    f'/{BASE_PATH}graphql/',
-    f'/{BASE_PATH}login/',
-    f'/{BASE_PATH}oauth/',
-    f'/{BASE_PATH}metrics',
-)
-
 # All URLs starting with a string listed here are exempt from maintenance mode enforcement
 MAINTENANCE_EXEMPT_PATHS = (
     f'/{BASE_PATH}admin/',

+ 6 - 5
netbox/netbox/views/generic/feature_views.py

@@ -1,3 +1,4 @@
+from django.contrib.auth.mixins import LoginRequiredMixin
 from django.contrib.contenttypes.models import ContentType
 from django.contrib import messages
 from django.db import transaction
@@ -12,7 +13,7 @@ from extras.forms import JournalEntryForm
 from extras.models import JournalEntry
 from extras.tables import JournalEntryTable
 from utilities.permissions import get_permission_for_model
-from utilities.views import GetReturnURLMixin, ViewTab
+from utilities.views import ConditionalLoginRequiredMixin, GetReturnURLMixin, ViewTab
 from .base import BaseMultiObjectView
 
 __all__ = (
@@ -24,7 +25,7 @@ __all__ = (
 )
 
 
-class ObjectChangeLogView(View):
+class ObjectChangeLogView(ConditionalLoginRequiredMixin, View):
     """
     Present a history of changes made to a particular object. The model class must be passed as a keyword argument
     when referencing this view in a URL path. For example:
@@ -77,7 +78,7 @@ class ObjectChangeLogView(View):
         })
 
 
-class ObjectJournalView(View):
+class ObjectJournalView(ConditionalLoginRequiredMixin, View):
     """
     Show all journal entries for an object. The model class must be passed as a keyword argument when referencing this
     view in a URL path. For example:
@@ -138,7 +139,7 @@ class ObjectJournalView(View):
         })
 
 
-class ObjectJobsView(View):
+class ObjectJobsView(ConditionalLoginRequiredMixin, View):
     """
     Render a list of all Job assigned to an object. For example:
 
@@ -191,7 +192,7 @@ class ObjectJobsView(View):
         })
 
 
-class ObjectSyncDataView(View):
+class ObjectSyncDataView(LoginRequiredMixin, View):
 
     def post(self, request, model, **kwargs):
         """

+ 2 - 1
netbox/netbox/views/htmx.py

@@ -1,3 +1,4 @@
+from django.contrib.auth.mixins import LoginRequiredMixin
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ObjectDoesNotExist
 from django.http import Http404
@@ -6,7 +7,7 @@ from django.utils.module_loading import import_string
 from django.views.generic import View
 
 
-class ObjectSelectorView(View):
+class ObjectSelectorView(LoginRequiredMixin, View):
     template_name = 'htmx/object_selector.html'
 
     def get(self, request):

+ 3 - 2
netbox/netbox/views/misc.py

@@ -19,6 +19,7 @@ from netbox.search.backends import search_backend
 from netbox.tables import SearchTable
 from utilities.htmx import htmx_partial
 from utilities.paginator import EnhancedPaginator, get_paginate_count
+from utilities.views import ConditionalLoginRequiredMixin
 
 __all__ = (
     'HomeView',
@@ -28,7 +29,7 @@ __all__ = (
 Link = namedtuple('Link', ('label', 'viewname', 'permission', 'count'))
 
 
-class HomeView(View):
+class HomeView(ConditionalLoginRequiredMixin, View):
     template_name = 'home.html'
 
     def get(self, request):
@@ -62,7 +63,7 @@ class HomeView(View):
         })
 
 
-class SearchView(View):
+class SearchView(ConditionalLoginRequiredMixin, View):
 
     def get(self, request):
         results = []

+ 15 - 3
netbox/utilities/views.py

@@ -1,5 +1,6 @@
 from typing import Iterable
 
+from django.conf import settings
 from django.contrib.auth.mixins import AccessMixin
 from django.core.exceptions import ImproperlyConfigured
 from django.urls import reverse
@@ -13,6 +14,7 @@ from utilities.relations import get_related_models
 from .permissions import resolve_permission
 
 __all__ = (
+    'ConditionalLoginRequiredMixin',
     'ContentTypePermissionRequiredMixin',
     'GetRelatedModelsMixin',
     'GetReturnURLMixin',
@@ -27,10 +29,20 @@ __all__ = (
 # View Mixins
 #
 
-class ContentTypePermissionRequiredMixin(AccessMixin):
+class ConditionalLoginRequiredMixin(AccessMixin):
+    """
+    Similar to Django's LoginRequiredMixin, but enforces authentication only if LOGIN_REQUIRED is True.
+    """
+    def dispatch(self, request, *args, **kwargs):
+        if settings.LOGIN_REQUIRED and not request.user.is_authenticated:
+            return self.handle_no_permission()
+        return super().dispatch(request, *args, **kwargs)
+
+
+class ContentTypePermissionRequiredMixin(ConditionalLoginRequiredMixin):
     """
     Similar to Django's built-in PermissionRequiredMixin, but extended to check model-level permission assignments.
-    This is related to ObjectPermissionRequiredMixin, except that is does not enforce object-level permissions,
+    This is related to ObjectPermissionRequiredMixin, except that it does not enforce object-level permissions,
     and fits within NetBox's custom permission enforcement system.
 
     additional_permissions: An optional iterable of statically declared permissions to evaluate in addition to those
@@ -63,7 +75,7 @@ class ContentTypePermissionRequiredMixin(AccessMixin):
         return super().dispatch(request, *args, **kwargs)
 
 
-class ObjectPermissionRequiredMixin(AccessMixin):
+class ObjectPermissionRequiredMixin(ConditionalLoginRequiredMixin):
     """
     Similar to Django's built-in PermissionRequiredMixin, but extended to check for both model-level and object-level
     permission assignments. If the user has only object-level permissions assigned, the view's queryset is filtered