Skip to content

Commit

Permalink
Fixes #17972: Force evaluation of LOGIN_REQUIRED when requesting stat…
Browse files Browse the repository at this point in the history
…ic media (#17990)
  • Loading branch information
jeremystretch authored Nov 12, 2024
1 parent 494d410 commit 954e29a
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 4 deletions.
20 changes: 19 additions & 1 deletion netbox/netbox/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import urllib.parse

from django.urls import reverse
from django.test import override_settings
from django.test import Client, override_settings

from dcim.models import Site
from netbox.constants import EMPTY_TABLE_TEXT
Expand Down Expand Up @@ -74,3 +74,21 @@ def test_search_no_results(self):
self.assertHttpStatus(response, 200)
content = str(response.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)
5 changes: 2 additions & 3 deletions netbox/netbox/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@
from django.conf.urls import include
from django.urls import path
from django.views.decorators.cache import cache_page
from django.views.static import serve
from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView

from account.views import LoginView, LogoutView
from netbox.api.views import APIRootView, StatusView
from netbox.graphql.schema import schema
from netbox.graphql.views import NetBoxGraphQLView
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 = [

Expand Down Expand Up @@ -69,7 +68,7 @@
path('graphql/', NetBoxGraphQLView.as_view(schema=schema), name='graphql'),

# 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'),

# Plugins
Expand Down
10 changes: 10 additions & 0 deletions netbox/netbox/views/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from django.shortcuts import redirect, render
from django.utils.translation import gettext_lazy as _
from django.views.generic import View
from django.views.static import serve
from django_tables2 import RequestConfig
from packaging import version

Expand All @@ -23,6 +24,7 @@

__all__ = (
'HomeView',
'MediaView',
'SearchView',
)

Expand Down Expand Up @@ -115,3 +117,11 @@ def get(self, request):
'form': form,
'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)

0 comments on commit 954e29a

Please sign in to comment.