From a9ada4457bfdddc37f812c4447e08986b4f90646 Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Fri, 15 Aug 2025 15:22:03 -0500 Subject: [PATCH] Fixes: #19669 & #18396 - Allow Token Authentication against Media view (#20046) --- netbox/netbox/views/misc.py | 4 ++-- netbox/utilities/views.py | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/netbox/netbox/views/misc.py b/netbox/netbox/views/misc.py index f28b0f7b1..ab995db66 100644 --- a/netbox/netbox/views/misc.py +++ b/netbox/netbox/views/misc.py @@ -20,7 +20,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 +from utilities.views import ConditionalLoginRequiredMixin, TokenConditionalLoginRequiredMixin __all__ = ( 'HomeView', @@ -119,7 +119,7 @@ class SearchView(ConditionalLoginRequiredMixin, View): }) -class MediaView(ConditionalLoginRequiredMixin, View): +class MediaView(TokenConditionalLoginRequiredMixin, View): """ Wrap Django's serve() view to enforce LOGIN_REQUIRED for static media. """ diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index 1263874c4..5c6c7977d 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -7,6 +7,7 @@ from django.urls import reverse from django.urls.exceptions import NoReverseMatch from django.utils.translation import gettext_lazy as _ +from netbox.api.authentication import TokenAuthentication from netbox.plugins import PluginConfig from netbox.registry import registry from utilities.relations import get_related_models @@ -19,6 +20,7 @@ __all__ = ( 'GetRelatedModelsMixin', 'GetReturnURLMixin', 'ObjectPermissionRequiredMixin', + 'TokenConditionalLoginRequiredMixin', 'ViewTab', 'get_viewname', 'register_model_view', @@ -39,6 +41,19 @@ class ConditionalLoginRequiredMixin(AccessMixin): return super().dispatch(request, *args, **kwargs) +class TokenConditionalLoginRequiredMixin(ConditionalLoginRequiredMixin): + def dispatch(self, request, *args, **kwargs): + # Attempt to authenticate the user using a DRF token, if provided + if settings.LOGIN_REQUIRED and not request.user.is_authenticated: + authenticator = TokenAuthentication() + auth_info = authenticator.authenticate(request) + if auth_info is not None: + request.user = auth_info[0] # User object + request.auth = auth_info[1] + + return super().dispatch(request, *args, **kwargs) + + class ContentTypePermissionRequiredMixin(ConditionalLoginRequiredMixin): """ Similar to Django's built-in PermissionRequiredMixin, but extended to check model-level permission assignments.