Compare commits

...

3 Commits

Author SHA1 Message Date
Andreas Schneider
85e0d1842a Tests: add regression test for redis URL with empty username (#12460)
* Tests: add regression test for redis URL with empty username and password

Covers the unix://:SECRET@/path.sock format (empty username, password only),
which was missing from the existing test cases for PR #12239.

* Update src/paperless/tests/settings/test_custom_parsers.py

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2026-03-29 06:31:18 -07:00
GitHub Actions
62f79c088e Auto translate strings 2026-03-28 21:00:05 +00:00
shamoon
129da3ade7 Tweakhancement: show file extension in StoragePath test (#12452) 2026-03-28 13:58:33 -07:00
4 changed files with 55 additions and 20 deletions

View File

@@ -360,7 +360,7 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
content_type="application/json", content_type="application/json",
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, "path/Something") self.assertEqual(response.data, "path/Something.pdf")
def test_test_storage_path_respects_none_placeholder_setting(self) -> None: def test_test_storage_path_respects_none_placeholder_setting(self) -> None:
""" """
@@ -390,7 +390,7 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
content_type="application/json", content_type="application/json",
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, "folder/none/Something") self.assertEqual(response.data, "folder/none/Something.pdf")
with override_settings(FILENAME_FORMAT_REMOVE_NONE=True): with override_settings(FILENAME_FORMAT_REMOVE_NONE=True):
response = self.client.post( response = self.client.post(
@@ -399,7 +399,7 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
content_type="application/json", content_type="application/json",
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, "folder/Something") self.assertEqual(response.data, "folder/Something.pdf")
def test_test_storage_path_requires_document_view_permission(self) -> None: def test_test_storage_path_requires_document_view_permission(self) -> None:
owner = User.objects.create_user(username="owner") owner = User.objects.create_user(username="owner")
@@ -447,7 +447,27 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
content_type="application/json", content_type="application/json",
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, "path/Shared") self.assertEqual(response.data, "path/Shared.pdf")
def test_test_storage_path_prefers_existing_filename_extension(self) -> None:
document = Document.objects.create(
mime_type="image/jpeg",
filename="existing/Document.jpeg",
title="Something",
checksum="123",
)
response = self.client.post(
f"{self.ENDPOINT}test/",
json.dumps(
{
"document": document.id,
"path": "path/{{ title }}",
},
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, "path/Something.jpeg")
def test_test_storage_path_exposes_basic_document_context_but_not_sensitive_owner_data( def test_test_storage_path_exposes_basic_document_context_but_not_sensitive_owner_data(
self, self,
@@ -478,12 +498,12 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
content_type="application/json", content_type="application/json",
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, "owner") self.assertEqual(response.data, "owner.pdf")
for expression, expected in ( for expression, expected in (
("{{ document.content }}", "Top secret content"), ("{{ document.content }}", "Top secret content.pdf"),
("{{ document.id }}", str(document.id)), ("{{ document.id }}", f"{document.id}.pdf"),
("{{ document.page_count }}", "2"), ("{{ document.page_count }}", "2.pdf"),
): ):
response = self.client.post( response = self.client.post(
f"{self.ENDPOINT}test/", f"{self.ENDPOINT}test/",
@@ -545,7 +565,7 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
content_type="application/json", content_type="application/json",
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, "Private Correspondent") self.assertEqual(response.data, "Private Correspondent.pdf")
response = self.client.post( response = self.client.post(
f"{self.ENDPOINT}test/", f"{self.ENDPOINT}test/",
@@ -560,7 +580,7 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
content_type="application/json", content_type="application/json",
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, "Private Correspondent") self.assertEqual(response.data, "Private Correspondent.pdf")
def test_test_storage_path_superuser_can_view_private_related_objects(self) -> None: def test_test_storage_path_superuser_can_view_private_related_objects(self) -> None:
owner = User.objects.create_user(username="owner") owner = User.objects.create_user(username="owner")
@@ -589,7 +609,7 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
content_type="application/json", content_type="application/json",
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, "Private Correspondent") self.assertEqual(response.data, "Private Correspondent.pdf")
def test_test_storage_path_includes_doc_type_storage_path_and_tags( def test_test_storage_path_includes_doc_type_storage_path_and_tags(
self, self,
@@ -636,7 +656,7 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
content_type="application/json", content_type="application/json",
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, "Private Type/private/path/Private Tag") self.assertEqual(response.data, "Private Type/private/path/Private Tag.pdf")
response = self.client.post( response = self.client.post(
f"{self.ENDPOINT}test/", f"{self.ENDPOINT}test/",
@@ -649,7 +669,7 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
content_type="application/json", content_type="application/json",
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, "Private Type/Private Tag") self.assertEqual(response.data, "Private Type/Private Tag.pdf")
def test_test_storage_path_includes_custom_fields_for_visible_document( def test_test_storage_path_includes_custom_fields_for_visible_document(
self, self,
@@ -685,7 +705,7 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
content_type="application/json", content_type="application/json",
) )
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, "42") self.assertEqual(response.data, "42.pdf")
class TestBulkEditObjects(APITestCase): class TestBulkEditObjects(APITestCase):

View File

@@ -3290,6 +3290,12 @@ class StoragePathViewSet(PermissionsAwareDocumentCountMixin, ModelViewSet):
path = serializer.validated_data.get("path") path = serializer.validated_data.get("path")
result = format_filename(document, path) result = format_filename(document, path)
if result:
extension = (
Path(str(document.filename)).suffix if document.filename else ""
) or document.file_type
result_path = Path(result)
result = str(result_path.with_name(f"{result_path.name}{extension}"))
return Response(result) return Response(result)

View File

@@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: paperless-ngx\n" "Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-26 14:37+0000\n" "POT-Creation-Date: 2026-03-28 20:59+0000\n"
"PO-Revision-Date: 2022-02-17 04:17\n" "PO-Revision-Date: 2022-02-17 04:17\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: English\n" "Language-Team: English\n"
@@ -1341,7 +1341,7 @@ msgstr ""
msgid "Duplicate document identifiers are not allowed." msgid "Duplicate document identifiers are not allowed."
msgstr "" msgstr ""
#: documents/serialisers.py:2587 documents/views.py:3599 #: documents/serialisers.py:2587 documents/views.py:3605
#, python-format #, python-format
msgid "Documents not found: %(ids)s" msgid "Documents not found: %(ids)s"
msgstr "" msgstr ""
@@ -1613,20 +1613,20 @@ msgstr ""
msgid "Invalid more_like_id" msgid "Invalid more_like_id"
msgstr "" msgstr ""
#: documents/views.py:3611 #: documents/views.py:3617
#, python-format #, python-format
msgid "Insufficient permissions to share document %(id)s." msgid "Insufficient permissions to share document %(id)s."
msgstr "" msgstr ""
#: documents/views.py:3654 #: documents/views.py:3660
msgid "Bundle is already being processed." msgid "Bundle is already being processed."
msgstr "" msgstr ""
#: documents/views.py:3711 #: documents/views.py:3717
msgid "The share link bundle is still being prepared. Please try again later." msgid "The share link bundle is still being prepared. Please try again later."
msgstr "" msgstr ""
#: documents/views.py:3721 #: documents/views.py:3727
msgid "The share link bundle is unavailable." msgid "The share link bundle is unavailable."
msgstr "" msgstr ""

View File

@@ -79,6 +79,15 @@ class TestRedisSocketConversion:
), ),
id="celery_style_socket_with_credentials", id="celery_style_socket_with_credentials",
), ),
# Empty username, password only: unix://:SECRET@/path.sock
pytest.param(
"unix://:SECRET@/run/redis/paperless.sock",
(
"redis+socket://:SECRET@/run/redis/paperless.sock",
"unix://:SECRET@/run/redis/paperless.sock",
),
id="redis_py_style_socket_with_password_only",
),
], ],
) )
def test_redis_socket_parsing( def test_redis_socket_parsing(