Browse Source

[api] Refactor /create/file API with better validation checks (#4003)

Harsh Gupta 9 months ago
parent
commit
6cc393f640

+ 13 - 2
apps/filebrowser/src/filebrowser/api.py

@@ -603,10 +603,21 @@ def touch(request):
   path = request.POST.get('path')
   path = request.POST.get('path')
   name = request.POST.get('name')
   name = request.POST.get('name')
 
 
+  # Check if path and name are provided
+  if not path or not name:
+    return HttpResponse("Missing parameters: path and name are required.", status=400)
+
+  # Validate the 'name' parameter for invalid characters
   if name and (posixpath.sep in name):
   if name and (posixpath.sep in name):
-    return HttpResponse(f"Error creating {name} file: Slashes are not allowed in filename.", status=400)
+    return HttpResponse(f"Slashes are not allowed in filename. Please choose a different name.", status=400)
+
+  file_path = request.fs.join(path, name)
+
+  # Check if the file already exists
+  if request.fs.isfile(file_path):
+    return HttpResponse(f"Error creating {name} file: File already exists.", status=409)
 
 
-  request.fs.create(request.fs.join(path, name))
+  request.fs.create(file_path)
   return HttpResponse(status=201)
   return HttpResponse(status=201)
 
 
 
 

+ 65 - 1
apps/filebrowser/src/filebrowser/api_test.py

@@ -21,7 +21,7 @@ from unittest.mock import MagicMock, Mock, patch
 from django.core.files.uploadedfile import SimpleUploadedFile
 from django.core.files.uploadedfile import SimpleUploadedFile
 
 
 from aws.s3.s3fs import S3ListAllBucketsException
 from aws.s3.s3fs import S3ListAllBucketsException
-from filebrowser.api import copy, get_all_filesystems, listdir_paged, mkdir, move, rename, upload_file
+from filebrowser.api import copy, get_all_filesystems, listdir_paged, mkdir, move, rename, touch, upload_file
 from filebrowser.conf import (
 from filebrowser.conf import (
   MAX_FILE_SIZE_UPLOAD_LIMIT,
   MAX_FILE_SIZE_UPLOAD_LIMIT,
   RESTRICT_FILE_EXTENSIONS,
   RESTRICT_FILE_EXTENSIONS,
@@ -331,6 +331,70 @@ class TestSimpleFileUploadAPI:
           reset()
           reset()
 
 
 
 
+class TestTouchAPI:
+  def test_touch_success(self):
+    request = Mock(
+      method='POST',
+      POST={'path': 's3a://test-bucket/test-user/', 'name': 'test_file.txt'},
+      fs=Mock(
+        isfile=Mock(return_value=False),
+        join=Mock(return_value='s3a://test-bucket/test-user/test_file.txt'),
+        create=Mock(),
+      ),
+    )
+    response = touch(request)
+
+    assert response.status_code == 201
+    request.fs.create.assert_called_once_with('s3a://test-bucket/test-user/test_file.txt')
+
+  def test_touch_file_exists(self):
+    request = Mock(
+      method='POST',
+      POST={'path': 's3a://test-bucket/test-user/', 'name': 'test_file.txt'},
+      fs=Mock(
+        isfile=Mock(return_value=True),
+        join=Mock(return_value='s3a://test-bucket/test-user/test_file.txt'),
+      ),
+    )
+    response = touch(request)
+
+    assert response.status_code == 409
+    assert response.content.decode('utf-8') == 'Error creating test_file.txt file: File already exists.'
+
+  def test_touch_invalid_name(self):
+    request = Mock(
+      method='POST',
+      POST={'path': 's3a://test-bucket/test-user/', 'name': 'test/file.txt'},
+      fs=Mock(),
+    )
+    response = touch(request)
+
+    assert response.status_code == 400
+    assert response.content.decode('utf-8') == 'Slashes are not allowed in filename. Please choose a different name.'
+
+  def test_touch_no_path(self):
+    request = Mock(
+      method='POST',
+      POST={'name': 'test_file.txt'},
+      fs=Mock(),
+    )
+    response = touch(request)
+
+    assert response.status_code == 400
+    assert response.content.decode('utf-8') == 'Missing parameters: path and name are required.'
+
+  def test_touch_no_name(self):
+    request = Mock(
+      method='POST',
+      POST={'path': 's3a://test-bucket/test-user/'},
+      fs=Mock(),
+    )
+    response = touch(request)
+
+    assert response.status_code == 400
+    assert response.content.decode('utf-8') == 'Missing parameters: path and name are required.'
+
+
 class TestMkdirAPI:
 class TestMkdirAPI:
   def test_mkdir_success(self):
   def test_mkdir_success(self):
     request = Mock(
     request = Mock(