Fix permission check, perform_create delegation, and test mock setup

- destroy() now checks extras.delete_script (queryset is Script.objects.all())
- create() delegates to self.perform_create() instead of calling serializer.save() directly
- Add comment explaining why update/partial_update intentionally return 405
- Fix test_upload_script_module: set mock_storage.save.return_value so file_path
  receives a real string after the _save_upload return-value fix; add DB existence check

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Arthur
2026-03-30 14:55:52 -07:00
parent 40f31205f2
commit c4077bf0eb
2 changed files with 8 additions and 3 deletions

View File

@@ -306,10 +306,13 @@ class ScriptViewSet(ModelViewSet):
context={'request': request},
)
serializer.is_valid(raise_exception=True)
serializer.save()
self.perform_create(serializer)
return Response(serializer.data, status=status.HTTP_201_CREATED)
# PUT and PATCH are intentionally unsupported: ScriptSerializer has no writable fields
# and there is no implementation for replacing the underlying module file via these methods.
# They remain registered by ModelViewSet and return 405 rather than 404.
def update(self, request, *args, **kwargs):
raise MethodNotAllowed(request.method)
@@ -317,8 +320,8 @@ class ScriptViewSet(ModelViewSet):
raise MethodNotAllowed(request.method)
def destroy(self, request, *args, **kwargs):
if not request.user.has_perm('extras.delete_scriptmodule'):
raise PermissionDenied(_("This user does not have permission to delete script modules."))
if not request.user.has_perm('extras.delete_script'):
raise PermissionDenied(_("This user does not have permission to delete scripts."))
return super().destroy(request, *args, **kwargs)
def _get_script(self, pk):

View File

@@ -1411,6 +1411,7 @@ class ScriptUploadTest(APITestCase):
script_content = b"from extras.scripts import Script\nclass TestScript(Script):\n pass\n"
upload_file = SimpleUploadedFile('test_upload.py', script_content, content_type='text/plain')
mock_storage = MagicMock()
mock_storage.save.return_value = 'test_upload.py'
with patch('extras.api.serializers_.scripts.storages') as mock_storages:
mock_storages.create_storage.return_value = mock_storage
mock_storages.backends = {'scripts': {}}
@@ -1423,6 +1424,7 @@ class ScriptUploadTest(APITestCase):
self.assertHttpStatus(response, status.HTTP_201_CREATED)
self.assertEqual(response.data['file_path'], 'test_upload.py')
mock_storage.save.assert_called_once()
self.assertTrue(ScriptModule.objects.filter(file_path='test_upload.py').exists())
def test_upload_script_module_without_file_fails(self):
self.add_permissions('extras.add_scriptmodule', 'core.add_managedfile')