mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-02-18 00:29:35 -06:00
Merge branch 'dev' into feature-document-versions-1218
This commit is contained in:
@@ -435,7 +435,6 @@ src/documents/permissions.py:0: error: Function is missing a type annotation [n
|
|||||||
src/documents/permissions.py:0: error: Function is missing a type annotation [no-untyped-def]
|
src/documents/permissions.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||||
src/documents/permissions.py:0: error: Function is missing a type annotation [no-untyped-def]
|
src/documents/permissions.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||||
src/documents/permissions.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def]
|
src/documents/permissions.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def]
|
||||||
src/documents/permissions.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def]
|
|
||||||
src/documents/permissions.py:0: error: Item "list[str]" of "Any | list[str] | QuerySet[User, User]" has no attribute "exclude" [union-attr]
|
src/documents/permissions.py:0: error: Item "list[str]" of "Any | list[str] | QuerySet[User, User]" has no attribute "exclude" [union-attr]
|
||||||
src/documents/permissions.py:0: error: Item "list[str]" of "Any | list[str] | QuerySet[User, User]" has no attribute "exists" [union-attr]
|
src/documents/permissions.py:0: error: Item "list[str]" of "Any | list[str] | QuerySet[User, User]" has no attribute "exists" [union-attr]
|
||||||
src/documents/permissions.py:0: error: Item "list[str]" of "Any | list[str] | QuerySet[User, User]" has no attribute "exists" [union-attr]
|
src/documents/permissions.py:0: error: Item "list[str]" of "Any | list[str] | QuerySet[User, User]" has no attribute "exists" [union-attr]
|
||||||
@@ -589,7 +588,6 @@ src/documents/serialisers.py:0: error: Function is missing a type annotation for
|
|||||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def]
|
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def]
|
||||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def]
|
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def]
|
||||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def]
|
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def]
|
||||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def]
|
|
||||||
src/documents/serialisers.py:0: error: Incompatible type for lookup 'pk': (got "str | None", expected "str | int") [misc]
|
src/documents/serialisers.py:0: error: Incompatible type for lookup 'pk': (got "str | None", expected "str | int") [misc]
|
||||||
src/documents/serialisers.py:0: error: Incompatible types in assignment (expression has type "PrimaryKeyRelatedField[Tag]", base class "Field" defined the type as "BaseSerializer[Any]") [assignment]
|
src/documents/serialisers.py:0: error: Incompatible types in assignment (expression has type "PrimaryKeyRelatedField[Tag]", base class "Field" defined the type as "BaseSerializer[Any]") [assignment]
|
||||||
src/documents/serialisers.py:0: error: Incompatible types in assignment (expression has type "Sequence[str] | tuple[Lower]", variable has type "Sequence[str] | None") [assignment]
|
src/documents/serialisers.py:0: error: Incompatible types in assignment (expression has type "Sequence[str] | tuple[Lower]", variable has type "Sequence[str] | None") [assignment]
|
||||||
@@ -1559,7 +1557,6 @@ src/documents/views.py:0: error: Function is missing a return type annotation [
|
|||||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
|
||||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
@@ -199,12 +201,12 @@ def get_document_count_filter_for_user(user):
|
|||||||
|
|
||||||
|
|
||||||
def annotate_document_count_for_related_queryset(
|
def annotate_document_count_for_related_queryset(
|
||||||
queryset,
|
queryset: QuerySet[Any],
|
||||||
through_model,
|
through_model: Any,
|
||||||
related_object_field: str,
|
related_object_field: str,
|
||||||
target_field: str = "document_id",
|
target_field: str = "document_id",
|
||||||
user=None,
|
user: User | None = None,
|
||||||
):
|
) -> QuerySet[Any]:
|
||||||
"""
|
"""
|
||||||
Annotate a queryset with permissions-aware document counts using a subquery
|
Annotate a queryset with permissions-aware document counts using a subquery
|
||||||
against a relation table.
|
against a relation table.
|
||||||
@@ -234,11 +236,11 @@ def annotate_document_count_for_related_queryset(
|
|||||||
|
|
||||||
|
|
||||||
def get_objects_for_user_owner_aware(
|
def get_objects_for_user_owner_aware(
|
||||||
user,
|
user: User | None,
|
||||||
perms,
|
perms: str | list[str],
|
||||||
Model,
|
Model: Any,
|
||||||
*,
|
*,
|
||||||
include_deleted=False,
|
include_deleted: bool = False,
|
||||||
) -> QuerySet:
|
) -> QuerySet:
|
||||||
"""
|
"""
|
||||||
Returns objects the user owns, are unowned, or has explicit perms.
|
Returns objects the user owns, are unowned, or has explicit perms.
|
||||||
@@ -314,7 +316,7 @@ class AcknowledgeTasksPermissions(BasePermission):
|
|||||||
"POST": ["documents.change_paperlesstask"],
|
"POST": ["documents.change_paperlesstask"],
|
||||||
}
|
}
|
||||||
|
|
||||||
def has_permission(self, request, view):
|
def has_permission(self, request: Any, view: Any) -> bool:
|
||||||
if not request.user or not request.user.is_authenticated: # pragma: no cover
|
if not request.user or not request.user.is_authenticated: # pragma: no cover
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -185,6 +185,7 @@ from documents.serialisers import PostDocumentSerializer
|
|||||||
from documents.serialisers import RunTaskViewSerializer
|
from documents.serialisers import RunTaskViewSerializer
|
||||||
from documents.serialisers import SavedViewSerializer
|
from documents.serialisers import SavedViewSerializer
|
||||||
from documents.serialisers import SearchResultSerializer
|
from documents.serialisers import SearchResultSerializer
|
||||||
|
from documents.serialisers import SerializerWithPerms
|
||||||
from documents.serialisers import ShareLinkBundleSerializer
|
from documents.serialisers import ShareLinkBundleSerializer
|
||||||
from documents.serialisers import ShareLinkSerializer
|
from documents.serialisers import ShareLinkSerializer
|
||||||
from documents.serialisers import StoragePathSerializer
|
from documents.serialisers import StoragePathSerializer
|
||||||
@@ -287,17 +288,22 @@ class PassUserMixin(GenericAPIView):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def get_serializer(self, *args, **kwargs):
|
def get_serializer(self, *args, **kwargs):
|
||||||
kwargs.setdefault("user", self.request.user)
|
serializer_class = self.get_serializer_class()
|
||||||
try:
|
if isinstance(serializer_class, type) and issubclass(
|
||||||
full_perms = get_boolean(
|
serializer_class,
|
||||||
str(self.request.query_params.get("full_perms", "false")),
|
SerializerWithPerms,
|
||||||
|
):
|
||||||
|
kwargs.setdefault("user", self.request.user)
|
||||||
|
try:
|
||||||
|
full_perms = get_boolean(
|
||||||
|
str(self.request.query_params.get("full_perms", "false")),
|
||||||
|
)
|
||||||
|
except ValueError:
|
||||||
|
full_perms = False
|
||||||
|
kwargs.setdefault(
|
||||||
|
"full_perms",
|
||||||
|
full_perms,
|
||||||
)
|
)
|
||||||
except ValueError:
|
|
||||||
full_perms = False
|
|
||||||
kwargs.setdefault(
|
|
||||||
"full_perms",
|
|
||||||
full_perms,
|
|
||||||
)
|
|
||||||
return super().get_serializer(*args, **kwargs)
|
return super().get_serializer(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@@ -404,8 +410,17 @@ class PermissionsAwareDocumentCountMixin(BulkPermissionMixin, PassUserMixin):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Default is simple relation path, override for through-table/count specialization.
|
# Default is simple relation path, override for through-table/count specialization.
|
||||||
document_count_through = None
|
document_count_through: type[Model] | None = None
|
||||||
document_count_source_field = None
|
document_count_source_field: str | None = None
|
||||||
|
|
||||||
|
def _get_document_count_source_field(self) -> str:
|
||||||
|
if self.document_count_source_field is None:
|
||||||
|
msg = (
|
||||||
|
"document_count_source_field must be set when "
|
||||||
|
"document_count_through is configured"
|
||||||
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
|
return self.document_count_source_field
|
||||||
|
|
||||||
def get_document_count_filter(self):
|
def get_document_count_filter(self):
|
||||||
request = getattr(self, "request", None)
|
request = getattr(self, "request", None)
|
||||||
@@ -421,7 +436,7 @@ class PermissionsAwareDocumentCountMixin(BulkPermissionMixin, PassUserMixin):
|
|||||||
return annotate_document_count_for_related_queryset(
|
return annotate_document_count_for_related_queryset(
|
||||||
base_qs,
|
base_qs,
|
||||||
through_model=self.document_count_through,
|
through_model=self.document_count_through,
|
||||||
related_object_field=self.document_count_source_field,
|
related_object_field=self._get_document_count_source_field(),
|
||||||
user=user,
|
user=user,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -523,7 +538,7 @@ class TagViewSet(PermissionsAwareDocumentCountMixin, ModelViewSet):
|
|||||||
.select_related("owner")
|
.select_related("owner")
|
||||||
.order_by(*ordering),
|
.order_by(*ordering),
|
||||||
through_model=self.document_count_through,
|
through_model=self.document_count_through,
|
||||||
related_object_field=self.document_count_source_field,
|
related_object_field=self._get_document_count_source_field(),
|
||||||
user=user,
|
user=user,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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-02-16 17:04+0000\n"
|
"POT-Creation-Date: 2026-02-16 17:32+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"
|
||||||
@@ -1323,7 +1323,7 @@ msgstr ""
|
|||||||
msgid "Duplicate document identifiers are not allowed."
|
msgid "Duplicate document identifiers are not allowed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/serialisers.py:2331 documents/views.py:2864
|
#: documents/serialisers.py:2331 documents/views.py:2879
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Documents not found: %(ids)s"
|
msgid "Documents not found: %(ids)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -1587,20 +1587,20 @@ msgstr ""
|
|||||||
msgid "Unable to parse URI {value}"
|
msgid "Unable to parse URI {value}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/views.py:2876
|
#: documents/views.py:2891
|
||||||
#, 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:2919
|
#: documents/views.py:2934
|
||||||
msgid "Bundle is already being processed."
|
msgid "Bundle is already being processed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: documents/views.py:2976
|
#: documents/views.py:2991
|
||||||
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:2986
|
#: documents/views.py:3001
|
||||||
msgid "The share link bundle is unavailable."
|
msgid "The share link bundle is unavailable."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user