mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-22 20:12:00 -06:00
Fixes #5470: Fix exception when making OPTIONS request for a REST API list endpoint
This commit is contained in:
parent
e2d17b1999
commit
c835ec5102
@ -12,6 +12,7 @@
|
||||
* [#5463](https://github.com/netbox-community/netbox/issues/5463) - Back-to-back Circuit Termination throws AttributeError exception
|
||||
* [#5465](https://github.com/netbox-community/netbox/issues/5465) - Correct return URL when disconnecting a cable from a device
|
||||
* [#5466](https://github.com/netbox-community/netbox/issues/5466) - Fix validation for required custom fields
|
||||
* [#5470](https://github.com/netbox-community/netbox/issues/5470) - Fix exception when making `OPTIONS` request for a REST API list endpoint
|
||||
|
||||
---
|
||||
|
||||
|
@ -1,10 +1,45 @@
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import Http404
|
||||
from django.utils.encoding import force_str
|
||||
from rest_framework import exceptions
|
||||
from rest_framework.metadata import SimpleMetadata
|
||||
from rest_framework.request import clone_request
|
||||
|
||||
from netbox.api import ContentTypeField
|
||||
|
||||
|
||||
class ContentTypeMetadata(SimpleMetadata):
|
||||
class BulkOperationMetadata(SimpleMetadata):
|
||||
|
||||
def determine_actions(self, request, view):
|
||||
"""
|
||||
Replace the stock determine_actions() method to assess object permissions only
|
||||
when viewing a specific object. This is necessary to support OPTIONS requests
|
||||
with bulk update in place (see #5470).
|
||||
"""
|
||||
actions = {}
|
||||
for method in {'PUT', 'POST'} & set(view.allowed_methods):
|
||||
view.request = clone_request(request, method)
|
||||
try:
|
||||
# Test global permissions
|
||||
if hasattr(view, 'check_permissions'):
|
||||
view.check_permissions(view.request)
|
||||
# Test object permissions (if viewing a specific object)
|
||||
if method == 'PUT' and view.lookup_url_kwarg and hasattr(view, 'get_object'):
|
||||
view.get_object()
|
||||
except (exceptions.APIException, PermissionDenied, Http404):
|
||||
pass
|
||||
else:
|
||||
# If user has appropriate permissions for the view, include
|
||||
# appropriate metadata about the fields that should be supplied.
|
||||
serializer = view.get_serializer()
|
||||
actions[method] = self.get_serializer_info(serializer)
|
||||
finally:
|
||||
view.request = request
|
||||
|
||||
return actions
|
||||
|
||||
|
||||
class ContentTypeMetadata(BulkOperationMetadata):
|
||||
|
||||
def get_field_info(self, field):
|
||||
field_info = super().get_field_info(field)
|
||||
|
@ -467,6 +467,7 @@ REST_FRAMEWORK = {
|
||||
'DEFAULT_FILTER_BACKENDS': (
|
||||
'django_filters.rest_framework.DjangoFilterBackend',
|
||||
),
|
||||
'DEFAULT_METADATA_CLASS': 'netbox.api.metadata.BulkOperationMetadata',
|
||||
'DEFAULT_PAGINATION_CLASS': 'netbox.api.pagination.OptionalLimitOffsetPagination',
|
||||
'DEFAULT_PERMISSION_CLASSES': (
|
||||
'netbox.api.authentication.TokenPermissions',
|
||||
|
@ -109,6 +109,15 @@ class APIViewTestCases:
|
||||
url = self._get_detail_url(instance2)
|
||||
self.assertHttpStatus(self.client.get(url, **self.header), status.HTTP_404_NOT_FOUND)
|
||||
|
||||
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
|
||||
def test_options_object(self):
|
||||
"""
|
||||
Make an OPTIONS request for a single object.
|
||||
"""
|
||||
url = self._get_detail_url(self._get_queryset().first())
|
||||
response = self.client.options(url, **self.header)
|
||||
self.assertHttpStatus(response, status.HTTP_200_OK)
|
||||
|
||||
class ListObjectsViewTestCase(APITestCase):
|
||||
brief_fields = []
|
||||
|
||||
@ -174,6 +183,14 @@ class APIViewTestCases:
|
||||
self.assertHttpStatus(response, status.HTTP_200_OK)
|
||||
self.assertEqual(len(response.data['results']), 2)
|
||||
|
||||
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
|
||||
def test_options_objects(self):
|
||||
"""
|
||||
Make an OPTIONS request for a list endpoint.
|
||||
"""
|
||||
response = self.client.options(self._get_list_url(), **self.header)
|
||||
self.assertHttpStatus(response, status.HTTP_200_OK)
|
||||
|
||||
class CreateObjectViewTestCase(APITestCase):
|
||||
create_data = []
|
||||
validation_excluded_fields = []
|
||||
|
Loading…
Reference in New Issue
Block a user