mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-28 18:24:38 -05:00
Dont perform permissions queries by default
This commit is contained in:
@@ -14,6 +14,7 @@ from django.contrib.auth.models import Group
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.text import slugify
|
||||
from django.utils.translation import gettext as _
|
||||
from guardian.core import ObjectPermissionChecker
|
||||
from guardian.shortcuts import get_users_with_perms
|
||||
from rest_framework import serializers
|
||||
from rest_framework.fields import SerializerMethodField
|
||||
@@ -149,11 +150,21 @@ class SetPermissionsMixin:
|
||||
class OwnedObjectSerializer(serializers.ModelSerializer, SetPermissionsMixin):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.user = kwargs.pop("user", None)
|
||||
full_perms = kwargs.pop("full_perms", False)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
try:
|
||||
if full_perms:
|
||||
self.fields.pop("user_can_change")
|
||||
else:
|
||||
self.fields.pop("permissions")
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def get_permissions(self, obj):
|
||||
view_codename = f"view_{obj.__class__.__name__.lower()}"
|
||||
change_codename = f"change_{obj.__class__.__name__.lower()}"
|
||||
|
||||
return {
|
||||
"view": {
|
||||
"users": get_users_with_perms(
|
||||
@@ -179,7 +190,19 @@ class OwnedObjectSerializer(serializers.ModelSerializer, SetPermissionsMixin):
|
||||
},
|
||||
}
|
||||
|
||||
def get_user_can_change(self, obj):
|
||||
checker = ObjectPermissionChecker(self.user) if self.user is not None else None
|
||||
return (
|
||||
obj.owner is None
|
||||
or obj.owner == self.user
|
||||
or (
|
||||
self.user is not None
|
||||
and checker.has_perm(f"change_{obj.__class__.__name__.lower()}", obj)
|
||||
)
|
||||
)
|
||||
|
||||
permissions = SerializerMethodField(read_only=True)
|
||||
user_can_change = SerializerMethodField(read_only=True)
|
||||
|
||||
set_permissions = serializers.DictField(
|
||||
label="Set permissions",
|
||||
@@ -235,6 +258,7 @@ class CorrespondentSerializer(MatchingModelSerializer, OwnedObjectSerializer):
|
||||
"last_correspondence",
|
||||
"owner",
|
||||
"permissions",
|
||||
"user_can_change",
|
||||
"set_permissions",
|
||||
)
|
||||
|
||||
@@ -252,6 +276,7 @@ class DocumentTypeSerializer(MatchingModelSerializer, OwnedObjectSerializer):
|
||||
"document_count",
|
||||
"owner",
|
||||
"permissions",
|
||||
"user_can_change",
|
||||
"set_permissions",
|
||||
)
|
||||
|
||||
@@ -303,6 +328,7 @@ class TagSerializerVersion1(MatchingModelSerializer, OwnedObjectSerializer):
|
||||
"document_count",
|
||||
"owner",
|
||||
"permissions",
|
||||
"user_can_change",
|
||||
"set_permissions",
|
||||
)
|
||||
|
||||
@@ -338,6 +364,7 @@ class TagSerializer(MatchingModelSerializer, OwnedObjectSerializer):
|
||||
"document_count",
|
||||
"owner",
|
||||
"permissions",
|
||||
"user_can_change",
|
||||
"set_permissions",
|
||||
)
|
||||
|
||||
@@ -437,6 +464,7 @@ class DocumentSerializer(OwnedObjectSerializer, DynamicFieldsModelSerializer):
|
||||
"archived_file_name",
|
||||
"owner",
|
||||
"permissions",
|
||||
"user_can_change",
|
||||
"set_permissions",
|
||||
"notes",
|
||||
)
|
||||
@@ -464,6 +492,7 @@ class SavedViewSerializer(OwnedObjectSerializer):
|
||||
"filter_rules",
|
||||
"owner",
|
||||
"permissions",
|
||||
"user_can_change",
|
||||
"set_permissions",
|
||||
]
|
||||
|
||||
@@ -783,6 +812,7 @@ class StoragePathSerializer(MatchingModelSerializer, OwnedObjectSerializer):
|
||||
"document_count",
|
||||
"owner",
|
||||
"permissions",
|
||||
"user_can_change",
|
||||
"set_permissions",
|
||||
)
|
||||
|
||||
|
@@ -3396,6 +3396,36 @@ class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
status.HTTP_404_NOT_FOUND,
|
||||
)
|
||||
|
||||
def test_dynamic_permissions_fields(self):
|
||||
Document.objects.create(title="Test", content="content 1", checksum="1")
|
||||
|
||||
user1 = User.objects.create_superuser(username="test1")
|
||||
self.client.force_authenticate(user1)
|
||||
|
||||
response = self.client.get(
|
||||
"/api/documents/",
|
||||
format="json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
resp_data = response.json()
|
||||
|
||||
self.assertNotIn("permissions", resp_data["results"][0])
|
||||
self.assertIn("user_can_change", resp_data["results"][0])
|
||||
|
||||
response = self.client.get(
|
||||
"/api/documents/?full_perms=true",
|
||||
format="json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
resp_data = response.json()
|
||||
|
||||
self.assertIn("permissions", resp_data["results"][0])
|
||||
self.assertNotIn("user_can_change", resp_data["results"][0])
|
||||
|
||||
|
||||
class TestApiRemoteVersion(DirectoriesMixin, APITestCase):
|
||||
ENDPOINT = "/api/remote_version/"
|
||||
|
@@ -157,6 +157,10 @@ class PassUserMixin(CreateModelMixin):
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
kwargs.setdefault("user", self.request.user)
|
||||
kwargs.setdefault(
|
||||
"full_perms",
|
||||
self.request.query_params.get("full_perms", False),
|
||||
)
|
||||
return super().get_serializer(*args, **kwargs)
|
||||
|
||||
|
||||
@@ -274,6 +278,10 @@ class DocumentViewSet(
|
||||
kwargs.setdefault("context", self.get_serializer_context())
|
||||
kwargs.setdefault("fields", fields)
|
||||
kwargs.setdefault("truncate_content", truncate_content.lower() in ["true", "1"])
|
||||
kwargs.setdefault(
|
||||
"full_perms",
|
||||
self.request.query_params.get("full_perms", False),
|
||||
)
|
||||
return serializer_class(*args, **kwargs)
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
|
Reference in New Issue
Block a user