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

Fixes #17972: Force evaluation of LOGIN_REQUIRED when requesting static media (#17990)

Jeremy Stretch 1 год назад
Родитель
Сommit
954e29aec3
3 измененных файлов с 31 добавлено и 4 удалено
  1. 19 1
      netbox/netbox/tests/test_views.py
  2. 2 3
      netbox/netbox/urls.py
  3. 10 0
      netbox/netbox/views/misc.py

+ 19 - 1
netbox/netbox/tests/test_views.py

@@ -1,7 +1,7 @@
 import urllib.parse
 import urllib.parse
 
 
 from django.urls import reverse
 from django.urls import reverse
-from django.test import override_settings
+from django.test import Client, override_settings
 
 
 from dcim.models import Site
 from dcim.models import Site
 from netbox.constants import EMPTY_TABLE_TEXT
 from netbox.constants import EMPTY_TABLE_TEXT
@@ -74,3 +74,21 @@ class SearchViewTestCase(TestCase):
         self.assertHttpStatus(response, 200)
         self.assertHttpStatus(response, 200)
         content = str(response.content)
         content = str(response.content)
         self.assertIn(EMPTY_TABLE_TEXT, content)
         self.assertIn(EMPTY_TABLE_TEXT, content)
+
+
+class MediaViewTestCase(TestCase):
+
+    def test_media_login_required(self):
+        url = reverse('media', kwargs={'path': 'foo.txt'})
+        response = Client().get(url)
+
+        # Unauthenticated request should redirect to login page
+        self.assertHttpStatus(response, 302)
+
+    @override_settings(LOGIN_REQUIRED=False)
+    def test_media_login_not_required(self):
+        url = reverse('media', kwargs={'path': 'foo.txt'})
+        response = Client().get(url)
+
+        # Unauthenticated request should return a 404 (not found)
+        self.assertHttpStatus(response, 404)

+ 2 - 3
netbox/netbox/urls.py

@@ -2,7 +2,6 @@ from django.conf import settings
 from django.conf.urls import include
 from django.conf.urls import include
 from django.urls import path
 from django.urls import path
 from django.views.decorators.cache import cache_page
 from django.views.decorators.cache import cache_page
-from django.views.static import serve
 from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
 from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
 
 
 from account.views import LoginView, LogoutView
 from account.views import LoginView, LogoutView
@@ -10,7 +9,7 @@ from netbox.api.views import APIRootView, StatusView
 from netbox.graphql.schema import schema
 from netbox.graphql.schema import schema
 from netbox.graphql.views import NetBoxGraphQLView
 from netbox.graphql.views import NetBoxGraphQLView
 from netbox.plugins.urls import plugin_patterns, plugin_api_patterns
 from netbox.plugins.urls import plugin_patterns, plugin_api_patterns
-from netbox.views import HomeView, StaticMediaFailureView, SearchView, htmx
+from netbox.views import HomeView, MediaView, StaticMediaFailureView, SearchView, htmx
 
 
 _patterns = [
 _patterns = [
 
 
@@ -69,7 +68,7 @@ _patterns = [
     path('graphql/', NetBoxGraphQLView.as_view(schema=schema), name='graphql'),
     path('graphql/', NetBoxGraphQLView.as_view(schema=schema), name='graphql'),
 
 
     # Serving static media in Django to pipe it through LoginRequiredMiddleware
     # Serving static media in Django to pipe it through LoginRequiredMiddleware
-    path('media/<path:path>', serve, {'document_root': settings.MEDIA_ROOT}),
+    path('media/<path:path>', MediaView.as_view(), name='media'),
     path('media-failure/', StaticMediaFailureView.as_view(), name='media_failure'),
     path('media-failure/', StaticMediaFailureView.as_view(), name='media_failure'),
 
 
     # Plugins
     # Plugins

+ 10 - 0
netbox/netbox/views/misc.py

@@ -8,6 +8,7 @@ from django.core.cache import cache
 from django.shortcuts import redirect, render
 from django.shortcuts import redirect, render
 from django.utils.translation import gettext_lazy as _
 from django.utils.translation import gettext_lazy as _
 from django.views.generic import View
 from django.views.generic import View
+from django.views.static import serve
 from django_tables2 import RequestConfig
 from django_tables2 import RequestConfig
 from packaging import version
 from packaging import version
 
 
@@ -23,6 +24,7 @@ from utilities.views import ConditionalLoginRequiredMixin
 
 
 __all__ = (
 __all__ = (
     'HomeView',
     'HomeView',
+    'MediaView',
     'SearchView',
     'SearchView',
 )
 )
 
 
@@ -115,3 +117,11 @@ class SearchView(ConditionalLoginRequiredMixin, View):
             'form': form,
             'form': form,
             'table': table,
             'table': table,
         })
         })
+
+
+class MediaView(ConditionalLoginRequiredMixin, View):
+    """
+    Wrap Django's serve() view to enforce LOGIN_REQUIRED for static media.
+    """
+    def get(self, request, path):
+        return serve(request, path, document_root=settings.MEDIA_ROOT)