]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Fix: add extra error handling to _consume for file checks (#10897)
authorshamoon <4887959+shamoon@users.noreply.github.com>
Sun, 21 Sep 2025 20:21:40 +0000 (13:21 -0700)
committerGitHub <noreply@github.com>
Sun, 21 Sep 2025 20:21:40 +0000 (13:21 -0700)
src/documents/management/commands/document_consumer.py
src/documents/tests/test_management_consumer.py

index 35d79288e61d61e6ed82d7dca13d5da02f0f14bc..97027e02dbaefd1e84e8c6f313b212925747c796 100644 (file)
@@ -82,6 +82,13 @@ def _is_ignored(filepath: Path) -> bool:
 
 
 def _consume(filepath: Path) -> None:
+    # Check permissions early
+    try:
+        filepath.stat()
+    except (PermissionError, OSError):
+        logger.warning(f"Not consuming file {filepath}: Permission denied.")
+        return
+
     if filepath.is_dir() or _is_ignored(filepath):
         return
 
@@ -323,7 +330,12 @@ class Command(BaseCommand):
 
                         # Also make sure the file exists still, some scanners might write a
                         # temporary file first
-                        file_still_exists = filepath.exists() and filepath.is_file()
+                        try:
+                            file_still_exists = filepath.exists() and filepath.is_file()
+                        except (PermissionError, OSError):  # pragma: no cover
+                            # If we can't check, let it fail in the _consume function
+                            file_still_exists = True
+                            continue
 
                         if waited_long_enough and file_still_exists:
                             _consume(filepath)
index 821fd82e0e6f25c56da6e6e8ef20cc85e78308d8..38b9eadda1c07b8c6c0446239712bbd5aff2d4dd 100644 (file)
@@ -209,6 +209,26 @@ class TestConsumer(DirectoriesMixin, ConsumerThreadMixin, TransactionTestCase):
         # assert that we have an error logged with this invalid file.
         error_logger.assert_called_once()
 
+    @mock.patch("documents.management.commands.document_consumer.logger.warning")
+    def test_permission_error_on_prechecks(self, warning_logger):
+        filepath = Path(self.dirs.consumption_dir) / "selinux.txt"
+        filepath.touch()
+
+        original_stat = Path.stat
+
+        def raising_stat(self, *args, **kwargs):
+            if self == filepath:
+                raise PermissionError("Permission denied")
+            return original_stat(self, *args, **kwargs)
+
+        with mock.patch("pathlib.Path.stat", new=raising_stat):
+            document_consumer._consume(filepath)
+
+        warning_logger.assert_called_once()
+        (args, _) = warning_logger.call_args
+        self.assertIn("Permission denied", args[0])
+        self.consume_file_mock.assert_not_called()
+
     @override_settings(CONSUMPTION_DIR="does_not_exist")
     def test_consumption_directory_invalid(self):
         self.assertRaises(CommandError, call_command, "document_consumer", "--oneshot")