mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-09-21 17:08:33 +00:00
Chore: Add shared helpers for granting test permissions and use them
This commit is contained in:
@@ -5,7 +5,6 @@ import pytest
|
||||
from django.contrib.auth.models import Group
|
||||
from django.db import connection
|
||||
from django.test.utils import CaptureQueriesContext
|
||||
from guardian.shortcuts import assign_perm
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from documents.models import CustomField
|
||||
@@ -23,6 +22,7 @@ from paperless_testing.factories import DocumentFactory
|
||||
from paperless_testing.factories import DocumentTypeFactory
|
||||
from paperless_testing.factories import TagFactory
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
pytestmark = [pytest.mark.search, pytest.mark.django_db]
|
||||
|
||||
@@ -188,7 +188,7 @@ class TestAddOrUpdateIds:
|
||||
pk=1,
|
||||
owner=owner,
|
||||
)
|
||||
assign_perm("view_document", user, doc)
|
||||
grant_object(user, doc, "view_document")
|
||||
|
||||
with backend.batch_update() as batch:
|
||||
batch.add_or_update_ids([doc.pk])
|
||||
@@ -208,7 +208,7 @@ class TestAddOrUpdateIds:
|
||||
pk=1,
|
||||
owner=owner,
|
||||
)
|
||||
assign_perm("view_document", group, doc)
|
||||
grant_object(group, doc, "view_document")
|
||||
|
||||
with backend.batch_update() as batch:
|
||||
batch.add_or_update_ids([doc.pk])
|
||||
@@ -842,7 +842,7 @@ class TestRebuild:
|
||||
content="group secret keyword",
|
||||
owner=owner,
|
||||
)
|
||||
assign_perm("view_document", group, doc)
|
||||
grant_object(group, doc, "view_document")
|
||||
|
||||
backend.rebuild(Document.objects.all())
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ from typing import TYPE_CHECKING
|
||||
import pytest
|
||||
from django.contrib.auth.models import Group
|
||||
from django.contrib.auth.models import User
|
||||
from guardian.shortcuts import assign_perm
|
||||
|
||||
from documents.models import Correspondent
|
||||
from documents.models import Document
|
||||
@@ -26,6 +25,7 @@ from documents.models import DocumentType
|
||||
from documents.models import StoragePath
|
||||
from documents.models import Tag
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from documents.search._backend import TantivyBackend
|
||||
@@ -128,7 +128,7 @@ class TestPermissionFilteringOnIndexedDocuments:
|
||||
checksum="perm-shared-user",
|
||||
owner=owner,
|
||||
)
|
||||
assign_perm("view_document", viewer, doc)
|
||||
grant_object(viewer, doc, "view_document")
|
||||
backend.add_or_update(doc)
|
||||
|
||||
assert backend.search_ids("invoice", user=viewer) == [doc.pk]
|
||||
@@ -158,7 +158,7 @@ class TestPermissionFilteringOnIndexedDocuments:
|
||||
checksum="perm-shared-group",
|
||||
owner=owner,
|
||||
)
|
||||
assign_perm("view_document", group_member.groups.first(), doc)
|
||||
grant_object(group_member.groups.first(), doc, "view_document")
|
||||
backend.add_or_update(doc)
|
||||
|
||||
assert backend.search_ids("invoice", user=group_member) == [doc.pk]
|
||||
|
||||
@@ -4,7 +4,6 @@ import json
|
||||
import shutil
|
||||
import zipfile
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.test import override_settings
|
||||
from django.utils import timezone
|
||||
from rest_framework import status
|
||||
@@ -17,6 +16,7 @@ from documents.tests.utils import SampleDirMixin
|
||||
from documents.tests.utils import read_streaming_response
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
|
||||
|
||||
class TestBulkDownload(DirectoriesMixin, SampleDirMixin, APITestCase):
|
||||
@@ -327,9 +327,7 @@ class TestBulkDownload(DirectoriesMixin, SampleDirMixin, APITestCase):
|
||||
|
||||
def test_download_insufficient_permissions(self) -> None:
|
||||
user = UserFactory(username="temp_user")
|
||||
user.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(user, "view_document")
|
||||
self.client.force_authenticate(user=user)
|
||||
|
||||
self.doc2.owner = self.user
|
||||
|
||||
@@ -2,10 +2,8 @@ import json
|
||||
from unittest import mock
|
||||
|
||||
from auditlog.models import LogEntry
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.auth.models import User
|
||||
from django.test import override_settings
|
||||
from guardian.shortcuts import assign_perm
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
@@ -17,6 +15,9 @@ from documents.models import StoragePath
|
||||
from documents.models import Tag
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_all_global
|
||||
from paperless_testing.permissions import grant_global
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
|
||||
class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
@@ -286,7 +287,7 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
) -> None:
|
||||
self.setup_mock(m, "modify_custom_fields")
|
||||
user = UserFactory(username="doc-owner")
|
||||
user.user_permissions.add(Permission.objects.get(codename="change_document"))
|
||||
grant_global(user, "change_document")
|
||||
other_user = UserFactory(username="other-user")
|
||||
source_doc = Document.objects.create(
|
||||
checksum="source",
|
||||
@@ -789,9 +790,7 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
def test_api_bulk_edit_with_all_true_resolves_owned_duplicates(self, m) -> None:
|
||||
self.setup_mock(m, "set_storage_path")
|
||||
user = UserFactory(username="duplicate-owner")
|
||||
user.user_permissions.add(
|
||||
Permission.objects.get(codename="change_document"),
|
||||
)
|
||||
grant_global(user, "change_document")
|
||||
first_duplicate = Document.objects.create(
|
||||
checksum="owned-duplicate",
|
||||
title="First duplicate",
|
||||
@@ -1179,7 +1178,7 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
user1 = User.objects.create(username="user1")
|
||||
self.client.force_authenticate(user=user1)
|
||||
|
||||
assign_perm("view_document", user1, self.doc2)
|
||||
grant_object(user1, self.doc2, "view_document")
|
||||
|
||||
response = self.client.post(
|
||||
"/api/documents/selection_data/",
|
||||
@@ -1189,9 +1188,7 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
user1.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(user1, "view_document")
|
||||
user1 = User.objects.get(pk=user1.pk)
|
||||
self.client.force_authenticate(user=user1)
|
||||
response = self.client.post(
|
||||
@@ -1534,7 +1531,7 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
self.doc1.owner = User.objects.get(username="temp_admin")
|
||||
self.doc1.save()
|
||||
user1 = User.objects.create(username="user1")
|
||||
user1.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(user1)
|
||||
user1.save()
|
||||
self.client.force_authenticate(user=user1)
|
||||
|
||||
@@ -1588,8 +1585,8 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
self.doc1.owner = User.objects.get(username="temp_admin")
|
||||
self.doc1.save()
|
||||
user1 = User.objects.create(username="user1")
|
||||
assign_perm("view_document", user1, self.doc1)
|
||||
user1.user_permissions.add(*Permission.objects.all())
|
||||
grant_object(user1, self.doc1, "view_document")
|
||||
grant_all_global(user1)
|
||||
user1.save()
|
||||
self.client.force_authenticate(user=user1)
|
||||
|
||||
@@ -1610,7 +1607,7 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
m.assert_not_called()
|
||||
self.assertEqual(response.content, b"Insufficient permissions")
|
||||
|
||||
assign_perm("change_document", user1, self.doc1)
|
||||
grant_object(user1, self.doc1, "change_document")
|
||||
|
||||
response = self.client.post(
|
||||
"/api/documents/bulk_edit/",
|
||||
@@ -1820,7 +1817,7 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
self.doc1.owner = User.objects.get(username="temp_admin")
|
||||
self.doc1.save()
|
||||
user1 = User.objects.create(username="user1")
|
||||
user1.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(user1)
|
||||
user1.save()
|
||||
self.client.force_authenticate(user=user1)
|
||||
|
||||
@@ -1881,7 +1878,7 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
self.doc1.owner = User.objects.get(username="temp_admin")
|
||||
self.doc1.save()
|
||||
user1 = User.objects.create(username="user1")
|
||||
user1.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(user1)
|
||||
user1.save()
|
||||
self.client.force_authenticate(user=user1)
|
||||
|
||||
@@ -1921,10 +1918,7 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
def test_merge_and_delete_requires_change_permission(self, m) -> None:
|
||||
self.setup_mock(m, "merge")
|
||||
user = UserFactory(username="no-change")
|
||||
user.user_permissions.add(
|
||||
Permission.objects.get(codename="add_document"),
|
||||
Permission.objects.get(codename="delete_document"),
|
||||
)
|
||||
grant_global(user, "add_document", "delete_document")
|
||||
self.client.force_authenticate(user=user)
|
||||
|
||||
response = self.client.post(
|
||||
@@ -2311,7 +2305,7 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
self.doc1.owner = User.objects.get(username="temp_admin")
|
||||
self.doc1.save()
|
||||
user1 = User.objects.create(username="user1")
|
||||
user1.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(user1)
|
||||
user1.save()
|
||||
self.client.force_authenticate(user=user1)
|
||||
|
||||
@@ -2374,10 +2368,7 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
self.setup_mock(edit_pdf_mock, "edit_pdf")
|
||||
self.setup_mock(remove_password_mock, "remove_password")
|
||||
user = UserFactory(username="no-delete")
|
||||
user.user_permissions.add(
|
||||
Permission.objects.get(codename="add_document"),
|
||||
Permission.objects.get(codename="change_document"),
|
||||
)
|
||||
grant_global(user, "add_document", "change_document")
|
||||
self.client.force_authenticate(user=user)
|
||||
|
||||
cases = [
|
||||
@@ -2464,7 +2455,7 @@ class TestBulkEditAPI(DirectoriesMixin, APITestCase):
|
||||
self.doc1.owner = User.objects.get(username="temp_admin")
|
||||
self.doc1.save()
|
||||
user1 = User.objects.create(username="user1")
|
||||
user1.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(user1)
|
||||
user1.save()
|
||||
self.client.force_authenticate(user=user1)
|
||||
|
||||
|
||||
@@ -4,15 +4,15 @@ from typing import TYPE_CHECKING
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.auth.models import User
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from django.contrib.auth.models import User
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
|
||||
@@ -115,9 +115,7 @@ class TestChatStreamingViewUnrestrictedFlag:
|
||||
needs to reach the view at all. Model-level only: says nothing
|
||||
about which documents (if any) this user can actually see.
|
||||
"""
|
||||
regular_user.user_permissions.add(
|
||||
*Permission.objects.filter(codename="view_document"),
|
||||
)
|
||||
grant_global(regular_user, "view_document")
|
||||
return user_client
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -5,7 +5,6 @@ from unittest.mock import ANY
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.test import override_settings
|
||||
from guardian.shortcuts import assign_perm
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
@@ -14,6 +13,8 @@ from documents.models import CustomFieldInstance
|
||||
from documents.models import Document
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
|
||||
class TestCustomFieldsAPI(DirectoriesMixin, APITestCase):
|
||||
@@ -1175,9 +1176,7 @@ class TestCustomFieldsAPI(DirectoriesMixin, APITestCase):
|
||||
self,
|
||||
) -> None:
|
||||
source_owner = UserFactory(username="source-owner")
|
||||
source_owner.user_permissions.add(
|
||||
Permission.objects.get(codename="change_document"),
|
||||
)
|
||||
grant_global(source_owner, "change_document")
|
||||
other_user = UserFactory(username="other-user")
|
||||
|
||||
source_doc = Document.objects.create(
|
||||
@@ -1222,9 +1221,7 @@ class TestCustomFieldsAPI(DirectoriesMixin, APITestCase):
|
||||
self,
|
||||
) -> None:
|
||||
source_owner = UserFactory(username="source-owner")
|
||||
source_owner.user_permissions.add(
|
||||
Permission.objects.get(codename="change_document"),
|
||||
)
|
||||
grant_global(source_owner, "change_document")
|
||||
other_user = UserFactory(username="other-user")
|
||||
|
||||
source_doc = Document.objects.create(
|
||||
@@ -1244,7 +1241,7 @@ class TestCustomFieldsAPI(DirectoriesMixin, APITestCase):
|
||||
data_type=CustomField.FieldDataType.DOCUMENTLINK,
|
||||
)
|
||||
|
||||
assign_perm("change_document", source_owner, target_doc)
|
||||
grant_object(source_owner, target_doc, "change_document")
|
||||
self.client.force_authenticate(user=source_owner)
|
||||
|
||||
resp = self.client.patch(
|
||||
|
||||
@@ -5,7 +5,6 @@ from typing import TYPE_CHECKING
|
||||
from unittest import mock
|
||||
|
||||
from auditlog.models import LogEntry # type: ignore[import-untyped]
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.test import TestCase as DjangoTestCase
|
||||
@@ -22,6 +21,7 @@ from documents.versioning import annotate_effective_content
|
||||
from documents.views import DocumentSelectionMixin
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
@@ -91,9 +91,7 @@ class TestDocumentVersioningApi(DirectoriesMixin, APITestCase):
|
||||
def test_root_endpoint_returns_403_when_user_lacks_permission(self) -> None:
|
||||
owner = UserFactory(username="owner")
|
||||
viewer = UserFactory(username="viewer")
|
||||
viewer.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(viewer, "view_document")
|
||||
root = Document.objects.create(
|
||||
title="root",
|
||||
checksum="root",
|
||||
@@ -285,9 +283,7 @@ class TestDocumentVersioningApi(DirectoriesMixin, APITestCase):
|
||||
def test_delete_version_returns_403_without_permission(self) -> None:
|
||||
owner = UserFactory(username="owner")
|
||||
other = UserFactory(username="other")
|
||||
other.user_permissions.add(
|
||||
Permission.objects.get(codename="delete_document"),
|
||||
)
|
||||
grant_global(other, "delete_document")
|
||||
root = Document.objects.create(
|
||||
title="root",
|
||||
checksum="root",
|
||||
@@ -373,9 +369,7 @@ class TestDocumentVersioningApi(DirectoriesMixin, APITestCase):
|
||||
def test_update_version_label_returns_403_without_permission(self) -> None:
|
||||
owner = UserFactory(username="owner")
|
||||
other = UserFactory(username="other")
|
||||
other.user_permissions.add(
|
||||
Permission.objects.get(codename="change_document"),
|
||||
)
|
||||
grant_global(other, "change_document")
|
||||
root = Document.objects.create(
|
||||
title="root",
|
||||
checksum="root",
|
||||
@@ -555,9 +549,7 @@ class TestDocumentVersioningApi(DirectoriesMixin, APITestCase):
|
||||
def test_metadata_returns_403_when_user_lacks_permission(self) -> None:
|
||||
owner = UserFactory(username="owner")
|
||||
other = UserFactory(username="other")
|
||||
other.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(other, "view_document")
|
||||
doc = Document.objects.create(
|
||||
title="root",
|
||||
checksum="root",
|
||||
@@ -673,7 +665,7 @@ class TestDocumentVersioningApi(DirectoriesMixin, APITestCase):
|
||||
|
||||
def test_update_version_requires_global_change_permission(self) -> None:
|
||||
user = UserFactory(username="add-only")
|
||||
user.user_permissions.add(Permission.objects.get(codename="add_document"))
|
||||
grant_global(user, "add_document")
|
||||
root = Document.objects.create(
|
||||
title="root",
|
||||
checksum="root",
|
||||
|
||||
@@ -23,7 +23,6 @@ from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.db import DataError
|
||||
from django.test import override_settings
|
||||
from django.utils import timezone
|
||||
from guardian.shortcuts import assign_perm
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
@@ -54,6 +53,9 @@ from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import DocumentFactory
|
||||
from paperless_testing.factories import TagFactory
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_all_global
|
||||
from paperless_testing.permissions import grant_global
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
|
||||
class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
@@ -360,8 +362,8 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
|
||||
user1 = UserFactory(username="test1")
|
||||
user2 = UserFactory(username="test2")
|
||||
user1.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
user2.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
grant_global(user1, "view_document")
|
||||
grant_global(user2, "view_document")
|
||||
|
||||
self.client.force_authenticate(user2)
|
||||
|
||||
@@ -384,7 +386,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
response = self.client.get(f"/api/documents/{doc.pk}/thumb/")
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
assign_perm("view_document", user2, doc)
|
||||
grant_object(user2, doc, "view_document")
|
||||
|
||||
response = self.client.get(f"/api/documents/{doc.pk}/download/")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
@@ -762,7 +764,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
"""
|
||||
# No auditlog permissions
|
||||
user = UserFactory(username="test")
|
||||
user.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
grant_global(user, "view_document")
|
||||
self.client.force_authenticate(user=user)
|
||||
doc = Document.objects.create(
|
||||
title="First title",
|
||||
@@ -1076,9 +1078,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
def test_has_duplicates_filter_respects_document_permissions(self) -> None:
|
||||
owner = UserFactory(username="duplicate-owner")
|
||||
requester = UserFactory(username="duplicate-requester")
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(requester, "view_document")
|
||||
visible_document = Document.objects.create(
|
||||
title="visible document",
|
||||
checksum="permission-match",
|
||||
@@ -1097,7 +1097,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
[document["id"] for document in response.data["results"]],
|
||||
)
|
||||
|
||||
assign_perm("view_document", requester, hidden_duplicate)
|
||||
grant_object(requester, hidden_duplicate, "view_document")
|
||||
response = self.client.get("/api/documents/?has_duplicates=true")
|
||||
self.assertIn(
|
||||
visible_document.id,
|
||||
@@ -1320,8 +1320,8 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
"""
|
||||
u1 = UserFactory(username="user1")
|
||||
u2 = UserFactory(username="user2")
|
||||
u1.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
u2.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
grant_global(u1, "view_document")
|
||||
grant_global(u2, "view_document")
|
||||
|
||||
u1_doc1 = Document.objects.create(
|
||||
title="none1",
|
||||
@@ -1354,7 +1354,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
)
|
||||
|
||||
self.client.force_authenticate(user=u1)
|
||||
assign_perm("view_document", u1, u2_doc2)
|
||||
grant_object(u1, u2_doc2, "view_document")
|
||||
|
||||
# Will not show any u1 docs or u2_doc1 which isn't shared
|
||||
response = self.client.get(f"/api/documents/?owner__id__none={u1.id}")
|
||||
@@ -1401,7 +1401,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
[u1_doc1.id, u1_doc2.id, u2_doc2.id],
|
||||
)
|
||||
|
||||
assign_perm("view_document", u2, u1_doc1)
|
||||
grant_object(u2, u1_doc1, "view_document")
|
||||
|
||||
# Will show only documents shared by user
|
||||
response = self.client.get(f"/api/documents/?shared_by__id={u1.id}")
|
||||
@@ -1426,7 +1426,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
(regression test for https://github.com/paperless-ngx/paperless-ngx/issues/13331)
|
||||
"""
|
||||
user = UserFactory(username="user1")
|
||||
user.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
grant_global(user, "view_document")
|
||||
group = Group.objects.create(name="group1")
|
||||
user.groups.add(group)
|
||||
|
||||
@@ -1434,7 +1434,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
tag2 = TagFactory()
|
||||
doc = DocumentFactory(title="shared", owner=user)
|
||||
doc.tags.add(tag1, tag2)
|
||||
assign_perm("view_document", group, doc)
|
||||
grant_object(group, doc, "view_document")
|
||||
|
||||
self.client.force_authenticate(user=user)
|
||||
response = self.client.get(
|
||||
@@ -1455,9 +1455,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
"""
|
||||
owner = UserFactory(username="owner1")
|
||||
stranger = UserFactory(username="stranger1")
|
||||
stranger.user_permissions.add(
|
||||
*Permission.objects.filter(codename="view_document"),
|
||||
)
|
||||
grant_global(stranger, "view_document")
|
||||
|
||||
DocumentFactory(title="private", owner=owner)
|
||||
|
||||
@@ -1479,13 +1477,13 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
member = UserFactory(username="member1")
|
||||
non_member = UserFactory(username="nonmember1")
|
||||
for u in (member, non_member):
|
||||
u.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
grant_global(u, "view_document")
|
||||
|
||||
group = Group.objects.create(name="group2")
|
||||
member.groups.add(group)
|
||||
|
||||
doc = DocumentFactory(title="shared2", owner=owner)
|
||||
assign_perm("view_document", group, doc)
|
||||
grant_object(group, doc, "view_document")
|
||||
|
||||
self.client.force_authenticate(user=member)
|
||||
response = self.client.get("/api/documents/")
|
||||
@@ -1819,9 +1817,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
def test_statistics_with_statistics_permission(self) -> None:
|
||||
owner = UserFactory(username="owner")
|
||||
stats_user = UserFactory(username="stats-user")
|
||||
stats_user.user_permissions.add(
|
||||
Permission.objects.get(codename="view_global_statistics"),
|
||||
)
|
||||
grant_global(stats_user, "view_global_statistics")
|
||||
|
||||
inbox_tag = Tag.objects.create(
|
||||
name="stats_inbox",
|
||||
@@ -2808,9 +2804,9 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
sort_field="",
|
||||
)
|
||||
|
||||
assign_perm("view_savedview", u1, v2)
|
||||
assign_perm("change_savedview", u1, v2)
|
||||
assign_perm("view_savedview", u1, v3)
|
||||
grant_object(u1, v2, "view_savedview")
|
||||
grant_object(u1, v2, "change_savedview")
|
||||
grant_object(u1, v3, "view_savedview")
|
||||
|
||||
self.client.force_authenticate(user=u1)
|
||||
|
||||
@@ -3570,7 +3566,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
- Notes are neither created nor deleted
|
||||
"""
|
||||
user1 = UserFactory(username="test1")
|
||||
user1.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(user1)
|
||||
user1.save()
|
||||
|
||||
user2 = UserFactory(username="test2")
|
||||
@@ -3593,7 +3589,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
self.assertEqual(resp.content, b"Insufficient permissions to view notes")
|
||||
self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
assign_perm("view_document", user1, doc)
|
||||
grant_object(user1, doc, "view_document")
|
||||
|
||||
resp = self.client.post(
|
||||
f"/api/documents/{doc.pk}/notes/",
|
||||
@@ -3618,11 +3614,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
|
||||
def test_notes_require_global_document_permissions(self) -> None:
|
||||
user = UserFactory(username="note_editor")
|
||||
user.user_permissions.add(
|
||||
*Permission.objects.filter(
|
||||
codename__in=["view_note", "add_note", "delete_note"],
|
||||
),
|
||||
)
|
||||
grant_global(user, "view_note", "add_note", "delete_note")
|
||||
doc = Document.objects.create(
|
||||
title="test",
|
||||
mime_type="application/pdf",
|
||||
@@ -3635,9 +3627,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
response = self.client.get(f"/api/documents/{doc.pk}/notes/")
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
user.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(user, "view_document")
|
||||
user = User.objects.get(pk=user.pk)
|
||||
self.client.force_authenticate(user)
|
||||
response = self.client.get(f"/api/documents/{doc.pk}/notes/")
|
||||
@@ -3649,9 +3639,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
user.user_permissions.add(
|
||||
Permission.objects.get(codename="change_document"),
|
||||
)
|
||||
grant_global(user, "change_document")
|
||||
user = User.objects.get(pk=user.pk)
|
||||
self.client.force_authenticate(user)
|
||||
response = self.client.post(
|
||||
@@ -3799,11 +3787,11 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
- Non-unique items are not allowed
|
||||
"""
|
||||
user1 = UserFactory(username="test1")
|
||||
user1.user_permissions.add(*Permission.objects.filter(codename="add_tag"))
|
||||
grant_global(user1, "add_tag")
|
||||
user1.save()
|
||||
|
||||
user2 = UserFactory(username="test2")
|
||||
user2.user_permissions.add(*Permission.objects.filter(codename="add_tag"))
|
||||
grant_global(user2, "add_tag")
|
||||
user2.save()
|
||||
|
||||
# User 1 creates tag 1 owned by user 1 by default
|
||||
@@ -3859,11 +3847,11 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
- Non-unique items are not allowed on update
|
||||
"""
|
||||
user1 = UserFactory(username="test1")
|
||||
user1.user_permissions.add(*Permission.objects.filter(codename="change_tag"))
|
||||
grant_global(user1, "change_tag")
|
||||
user1.save()
|
||||
|
||||
user2 = UserFactory(username="test2")
|
||||
user2.user_permissions.add(*Permission.objects.filter(codename="change_tag"))
|
||||
grant_global(user2, "change_tag")
|
||||
user2.save()
|
||||
|
||||
# Create name tag 1 owned by user 1
|
||||
@@ -3995,7 +3983,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
- Links only shown if user has permissions
|
||||
"""
|
||||
user1 = UserFactory(username="test1")
|
||||
user1.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(user1)
|
||||
user1.save()
|
||||
|
||||
user2 = UserFactory(username="test2")
|
||||
@@ -4018,7 +4006,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
self.assertEqual(resp.content, b"Insufficient permissions to add share link")
|
||||
self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
assign_perm("change_document", user1, doc)
|
||||
grant_object(user1, doc, "change_document")
|
||||
|
||||
resp = self.client.get(
|
||||
f"/api/documents/{doc.pk}/share_links/",
|
||||
@@ -4036,7 +4024,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
- Share link creation is denied until view permission is granted
|
||||
"""
|
||||
user1 = UserFactory(username="test1")
|
||||
user1.user_permissions.add(*Permission.objects.filter(codename="add_sharelink"))
|
||||
grant_global(user1, "add_sharelink")
|
||||
user1.save()
|
||||
|
||||
user2 = UserFactory(username="test2")
|
||||
@@ -4061,7 +4049,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
)
|
||||
self.assertEqual(create_resp.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
assign_perm("view_document", user1, doc)
|
||||
grant_object(user1, doc, "view_document")
|
||||
|
||||
create_resp = self.client.post(
|
||||
"/api/share_links/",
|
||||
@@ -4073,9 +4061,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
)
|
||||
self.assertEqual(create_resp.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
user1.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(user1, "view_document")
|
||||
user1 = User.objects.get(pk=user1.pk)
|
||||
self.client.force_authenticate(user1)
|
||||
create_resp = self.client.post(
|
||||
@@ -4099,7 +4085,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
- ASN +1 from user2's doc is returned for user1
|
||||
"""
|
||||
user1 = UserFactory(username="test1")
|
||||
user1.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(user1)
|
||||
user1.save()
|
||||
|
||||
user2 = UserFactory(username="test2")
|
||||
@@ -4143,7 +4129,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
- ASN 1 is returned
|
||||
"""
|
||||
user1 = UserFactory(username="test1")
|
||||
user1.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(user1)
|
||||
user1.save()
|
||||
|
||||
doc1 = Document.objects.create(
|
||||
@@ -4350,7 +4336,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
- Error response is returned
|
||||
"""
|
||||
user1 = UserFactory(username="test1")
|
||||
user1.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(user1)
|
||||
user1.save()
|
||||
|
||||
doc = Document.objects.create(
|
||||
|
||||
@@ -2,7 +2,6 @@ import json
|
||||
import shutil
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.core import mail
|
||||
from django.test import override_settings
|
||||
from rest_framework import status
|
||||
@@ -12,6 +11,7 @@ from documents.models import Document
|
||||
from documents.tests.utils import SampleDirMixin
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
|
||||
|
||||
class TestEmail(DirectoriesMixin, SampleDirMixin, APITestCase):
|
||||
@@ -304,7 +304,7 @@ class TestEmail(DirectoriesMixin, SampleDirMixin, APITestCase):
|
||||
- Forbidden response is returned
|
||||
"""
|
||||
user1 = UserFactory(username="test1")
|
||||
user1.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
grant_global(user1, "view_document")
|
||||
|
||||
doc_owned = Document.objects.create(
|
||||
title="owned_doc",
|
||||
@@ -339,7 +339,7 @@ class TestEmail(DirectoriesMixin, SampleDirMixin, APITestCase):
|
||||
- Request succeeds
|
||||
"""
|
||||
user1 = UserFactory(username="test1")
|
||||
user1.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
grant_global(user1, "view_document")
|
||||
|
||||
self.client.force_authenticate(user1)
|
||||
|
||||
|
||||
@@ -3,12 +3,10 @@ import json
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import Group
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import connection
|
||||
from django.test import override_settings
|
||||
from django.test.utils import CaptureQueriesContext
|
||||
from guardian.shortcuts import assign_perm
|
||||
from guardian.shortcuts import get_groups_with_perms
|
||||
from guardian.shortcuts import get_users_with_perms
|
||||
from rest_framework import status
|
||||
@@ -23,6 +21,8 @@ from documents.models import StoragePath
|
||||
from documents.models import Tag
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
|
||||
class TestApiObjects(DirectoriesMixin, APITestCase):
|
||||
@@ -164,9 +164,7 @@ class TestApiObjects(DirectoriesMixin, APITestCase):
|
||||
)
|
||||
|
||||
user = UserFactory(username="regular")
|
||||
user.user_permissions.add(
|
||||
Permission.objects.get(codename="view_correspondent"),
|
||||
)
|
||||
grant_global(user, "view_correspondent")
|
||||
self.client.force_authenticate(user=user)
|
||||
|
||||
response = self.client.get("/api/correspondents/?last_correspondence=true")
|
||||
@@ -458,9 +456,7 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
|
||||
def test_test_storage_path_requires_document_view_permission(self) -> None:
|
||||
owner = UserFactory(username="owner")
|
||||
unprivileged = UserFactory(username="unprivileged")
|
||||
unprivileged.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(unprivileged, "view_document")
|
||||
document = Document.objects.create(
|
||||
mime_type="application/pdf",
|
||||
owner=owner,
|
||||
@@ -490,7 +486,7 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
|
||||
title="Shared",
|
||||
checksum="123",
|
||||
)
|
||||
assign_perm("view_document", viewer, document)
|
||||
grant_object(viewer, document, "view_document")
|
||||
|
||||
self.client.force_authenticate(user=viewer)
|
||||
response = self.client.post(
|
||||
@@ -505,9 +501,7 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
viewer.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(viewer, "view_document")
|
||||
viewer = User.objects.get(pk=viewer.pk)
|
||||
self.client.force_authenticate(user=viewer)
|
||||
response = self.client.post(
|
||||
@@ -551,9 +545,7 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
|
||||
password="password",
|
||||
email="owner@example.com",
|
||||
)
|
||||
owner.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(owner, "view_document")
|
||||
document = Document.objects.create(
|
||||
mime_type="application/pdf",
|
||||
owner=owner,
|
||||
@@ -628,10 +620,8 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
|
||||
title="Document",
|
||||
checksum="123",
|
||||
)
|
||||
assign_perm("view_document", viewer, document)
|
||||
viewer.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_object(viewer, document, "view_document")
|
||||
grant_global(viewer, "view_document")
|
||||
|
||||
self.client.force_authenticate(user=viewer)
|
||||
response = self.client.post(
|
||||
@@ -718,10 +708,8 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
|
||||
checksum="123",
|
||||
)
|
||||
document.tags.add(private_tag)
|
||||
assign_perm("view_document", viewer, document)
|
||||
viewer.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_object(viewer, document, "view_document")
|
||||
grant_global(viewer, "view_document")
|
||||
|
||||
self.client.force_authenticate(user=viewer)
|
||||
response = self.client.post(
|
||||
@@ -774,10 +762,8 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
|
||||
field=custom_field,
|
||||
value_int=42,
|
||||
)
|
||||
assign_perm("view_document", viewer, document)
|
||||
viewer.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_object(viewer, document, "view_document")
|
||||
grant_global(viewer, "view_document")
|
||||
|
||||
self.client.force_authenticate(user=viewer)
|
||||
response = self.client.post(
|
||||
@@ -1031,9 +1017,7 @@ class TestBulkEditObjects(APITestCase):
|
||||
THEN:
|
||||
- User is able to delete objects
|
||||
"""
|
||||
self.user1.user_permissions.add(
|
||||
*Permission.objects.filter(codename="delete_tag"),
|
||||
)
|
||||
grant_global(self.user1, "delete_tag")
|
||||
self.user1.save()
|
||||
self.client.force_authenticate(user=self.user1)
|
||||
|
||||
@@ -1063,9 +1047,7 @@ class TestBulkEditObjects(APITestCase):
|
||||
self.t2.owner = User.objects.get(username="temp_admin")
|
||||
self.t2.save()
|
||||
|
||||
self.user1.user_permissions.add(
|
||||
*Permission.objects.filter(codename="delete_tag"),
|
||||
)
|
||||
grant_global(self.user1, "delete_tag")
|
||||
self.user1.save()
|
||||
self.client.force_authenticate(user=self.user1)
|
||||
|
||||
@@ -1098,9 +1080,7 @@ class TestBulkEditObjects(APITestCase):
|
||||
self.t2.owner = User.objects.get(username="temp_admin")
|
||||
self.t2.save()
|
||||
|
||||
self.user1.user_permissions.add(
|
||||
*Permission.objects.filter(codename="delete_tag"),
|
||||
)
|
||||
grant_global(self.user1, "delete_tag")
|
||||
self.user1.save()
|
||||
self.client.force_authenticate(user=self.user1)
|
||||
|
||||
|
||||
@@ -5,9 +5,7 @@ from unittest import mock
|
||||
from allauth.mfa.models import Authenticator
|
||||
from allauth.mfa.totp.internal import auth as totp_auth
|
||||
from django.contrib.auth.models import Group
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.auth.models import User
|
||||
from guardian.shortcuts import assign_perm
|
||||
from guardian.shortcuts import get_perms
|
||||
from guardian.shortcuts import get_users_with_perms
|
||||
from rest_framework import status
|
||||
@@ -21,6 +19,9 @@ from documents.models import StoragePath
|
||||
from documents.models import Tag
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_all_global
|
||||
from paperless_testing.permissions import grant_global
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
|
||||
class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
@@ -139,7 +140,7 @@ class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
|
||||
def test_api_sufficient_permissions(self) -> None:
|
||||
user = UserFactory(username="test")
|
||||
user.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(user)
|
||||
user.is_staff = True
|
||||
self.client.force_authenticate(user)
|
||||
|
||||
@@ -169,7 +170,7 @@ class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
def test_api_get_object_permissions(self) -> None:
|
||||
user1 = UserFactory(username="test1")
|
||||
user2 = UserFactory(username="test2")
|
||||
user1.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
grant_global(user1, "view_document")
|
||||
self.client.force_authenticate(user1)
|
||||
|
||||
self.assertEqual(
|
||||
@@ -420,10 +421,10 @@ class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
doc.owner = user1
|
||||
doc.save()
|
||||
|
||||
assign_perm("view_document", user2, doc)
|
||||
assign_perm("change_document", user2, doc)
|
||||
assign_perm("view_document", group1, doc)
|
||||
assign_perm("change_document", group1, doc)
|
||||
grant_object(user2, doc, "view_document")
|
||||
grant_object(user2, doc, "change_document")
|
||||
grant_object(group1, doc, "view_document")
|
||||
grant_object(group1, doc, "change_document")
|
||||
|
||||
self.client.force_authenticate(user1)
|
||||
|
||||
@@ -449,9 +450,7 @@ class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
def test_document_permissions_change_requires_owner(self) -> None:
|
||||
owner = UserFactory(username="owner")
|
||||
editor = UserFactory(username="editor")
|
||||
editor.user_permissions.add(
|
||||
*Permission.objects.all(),
|
||||
)
|
||||
grant_all_global(editor)
|
||||
|
||||
doc = Document.objects.create(
|
||||
title="Ownered doc",
|
||||
@@ -461,8 +460,8 @@ class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
owner=owner,
|
||||
)
|
||||
|
||||
assign_perm("view_document", editor, doc)
|
||||
assign_perm("change_document", editor, doc)
|
||||
grant_object(editor, doc, "view_document")
|
||||
grant_object(editor, doc, "change_document")
|
||||
|
||||
self.client.force_authenticate(editor)
|
||||
response = self.client.patch(
|
||||
@@ -501,7 +500,7 @@ class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
|
||||
def test_dynamic_permissions_fields(self) -> None:
|
||||
user1 = UserFactory(username="user1")
|
||||
user1.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
grant_global(user1, "view_document")
|
||||
user2 = UserFactory(username="user2")
|
||||
|
||||
Document.objects.create(title="Test", content="content 1", checksum="1")
|
||||
@@ -524,10 +523,10 @@ class TestApiAuth(DirectoriesMixin, APITestCase):
|
||||
owner=user1,
|
||||
)
|
||||
|
||||
assign_perm("view_document", user1, doc2)
|
||||
assign_perm("view_document", user1, doc3)
|
||||
assign_perm("change_document", user1, doc3)
|
||||
assign_perm("view_document", user2, doc4)
|
||||
grant_object(user1, doc2, "view_document")
|
||||
grant_object(user1, doc3, "view_document")
|
||||
grant_object(user1, doc3, "change_document")
|
||||
grant_object(user2, doc4, "view_document")
|
||||
|
||||
self.client.force_authenticate(user1)
|
||||
|
||||
@@ -860,9 +859,7 @@ class TestApiUser(DirectoriesMixin, APITestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
|
||||
regular_user = UserFactory(username="regular_user")
|
||||
regular_user.user_permissions.add(
|
||||
*Permission.objects.all(),
|
||||
)
|
||||
grant_all_global(regular_user)
|
||||
self.client.force_authenticate(regular_user)
|
||||
Authenticator.objects.create(
|
||||
user=user1,
|
||||
@@ -887,7 +884,7 @@ class TestApiUser(DirectoriesMixin, APITestCase):
|
||||
"""
|
||||
|
||||
user1 = UserFactory(username="user1")
|
||||
user1.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(user1)
|
||||
user2 = UserFactory(username="user2", superuser=True)
|
||||
|
||||
self.client.force_authenticate(user1)
|
||||
@@ -974,7 +971,7 @@ class TestApiUser(DirectoriesMixin, APITestCase):
|
||||
"""
|
||||
|
||||
user1 = UserFactory(username="user1")
|
||||
user1.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(user1)
|
||||
user2 = UserFactory(username="user2", superuser=True)
|
||||
|
||||
self.client.force_authenticate(user1)
|
||||
@@ -1277,7 +1274,7 @@ class TestBulkEditObjectPermissions(APITestCase):
|
||||
},
|
||||
}
|
||||
|
||||
assign_perm("view_tag", self.user3, self.t1)
|
||||
grant_object(self.user3, self.t1, "view_tag")
|
||||
self.t1.owner = self.user3
|
||||
self.t1.save()
|
||||
|
||||
@@ -1374,13 +1371,9 @@ class TestBulkEditObjectPermissions(APITestCase):
|
||||
"""
|
||||
self.t1.owner = self.user2
|
||||
self.t1.save()
|
||||
assign_perm("view_tag", self.user1, self.t1)
|
||||
assign_perm("change_tag", self.user1, self.t1)
|
||||
self.user1.user_permissions.add(
|
||||
*Permission.objects.filter(
|
||||
codename__in=["view_tag", "change_tag"],
|
||||
),
|
||||
)
|
||||
grant_object(self.user1, self.t1, "view_tag")
|
||||
grant_object(self.user1, self.t1, "change_tag")
|
||||
grant_global(self.user1, "view_tag", "change_tag")
|
||||
user1 = User.objects.get(pk=self.user1.pk)
|
||||
self.client.force_authenticate(user=user1)
|
||||
|
||||
@@ -1427,13 +1420,9 @@ class TestBulkEditObjectPermissions(APITestCase):
|
||||
"""
|
||||
owned = Tag.objects.create(name="owned", owner=self.user1)
|
||||
shared = Tag.objects.create(name="shared", owner=self.user2)
|
||||
assign_perm("view_tag", self.user1, shared)
|
||||
assign_perm("change_tag", self.user1, shared)
|
||||
self.user1.user_permissions.add(
|
||||
*Permission.objects.filter(
|
||||
codename__in=["view_tag", "change_tag"],
|
||||
),
|
||||
)
|
||||
grant_object(self.user1, shared, "view_tag")
|
||||
grant_object(self.user1, shared, "change_tag")
|
||||
grant_global(self.user1, "view_tag", "change_tag")
|
||||
user1 = User.objects.get(pk=self.user1.pk)
|
||||
self.client.force_authenticate(user=user1)
|
||||
|
||||
@@ -1474,14 +1463,10 @@ class TestBulkEditObjectPermissions(APITestCase):
|
||||
"""
|
||||
self.t1.owner = self.user2
|
||||
self.t1.save()
|
||||
assign_perm("view_tag", self.user1, self.t1)
|
||||
assign_perm("change_tag", self.user1, self.t1)
|
||||
assign_perm("delete_tag", self.user1, self.t1)
|
||||
self.user1.user_permissions.add(
|
||||
*Permission.objects.filter(
|
||||
codename__in=["view_tag", "change_tag", "delete_tag"],
|
||||
),
|
||||
)
|
||||
grant_object(self.user1, self.t1, "view_tag")
|
||||
grant_object(self.user1, self.t1, "change_tag")
|
||||
grant_object(self.user1, self.t1, "delete_tag")
|
||||
grant_global(self.user1, "view_tag", "change_tag", "delete_tag")
|
||||
user1 = User.objects.get(pk=self.user1.pk)
|
||||
self.client.force_authenticate(user=user1)
|
||||
|
||||
@@ -1586,7 +1571,7 @@ class TestBulkEditObjectPermissions(APITestCase):
|
||||
- Request succeeds and null is treated as an empty user list,
|
||||
so the existing view permission is removed
|
||||
"""
|
||||
assign_perm("view_tag", self.user1, self.t1)
|
||||
grant_object(self.user1, self.t1, "view_tag")
|
||||
|
||||
response = self.client.post(
|
||||
"/api/bulk_edit_objects/",
|
||||
|
||||
@@ -9,7 +9,6 @@ from django.contrib.auth.models import Group
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.test import override_settings
|
||||
from django.utils import timezone
|
||||
from guardian.shortcuts import assign_perm
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
@@ -31,6 +30,8 @@ from paperless_mail.models import MailRule
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import DocumentFactory
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
pytestmark = pytest.mark.search
|
||||
|
||||
@@ -951,7 +952,7 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
"""
|
||||
u1 = UserFactory(username="user1")
|
||||
u2 = UserFactory(username="user2")
|
||||
u1.user_permissions.add(Permission.objects.get(codename="view_document"))
|
||||
grant_global(u1, "view_document")
|
||||
|
||||
self.client.force_authenticate(user=u1)
|
||||
|
||||
@@ -991,7 +992,7 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data, ["applebaum", "apples"])
|
||||
|
||||
assign_perm("view_document", u1, d3)
|
||||
grant_object(u1, d3, "view_document")
|
||||
backend.add_or_update(d3)
|
||||
|
||||
response = self.client.get("/api/search/autocomplete/?term=app")
|
||||
@@ -1002,7 +1003,7 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
user = UserFactory(username="group-user")
|
||||
owner = UserFactory(username="document-owner")
|
||||
group = Group.objects.create(name="temporary-viewers")
|
||||
user.user_permissions.add(Permission.objects.get(codename="view_document"))
|
||||
grant_global(user, "view_document")
|
||||
user.groups.add(group)
|
||||
|
||||
document = Document.objects.create(
|
||||
@@ -1011,7 +1012,7 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
checksum="group-revocation",
|
||||
owner=owner,
|
||||
)
|
||||
assign_perm("view_document", group, document)
|
||||
grant_object(group, document, "view_document")
|
||||
get_backend().add_or_update(document)
|
||||
self.client.force_authenticate(user=user)
|
||||
|
||||
@@ -1093,9 +1094,7 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
def test_search_spelling_suggestion_suppressed_for_private_terms(self) -> None:
|
||||
owner = UserFactory(username="owner")
|
||||
attacker = UserFactory(username="attacker")
|
||||
attacker.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(attacker, "view_document")
|
||||
|
||||
backend = get_backend()
|
||||
for i in range(5):
|
||||
@@ -1224,9 +1223,7 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
"""
|
||||
owner = UserFactory(username="owner")
|
||||
attacker = UserFactory(username="attacker")
|
||||
attacker.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(attacker, "view_document")
|
||||
|
||||
private_seed = Document.objects.create(
|
||||
title="private bank statement",
|
||||
@@ -1537,8 +1534,8 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
superuser = UserFactory(username="superuser", superuser=True)
|
||||
u1 = UserFactory(username="user1")
|
||||
u2 = UserFactory(username="user2")
|
||||
u1.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
u2.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
grant_global(u1, "view_document")
|
||||
grant_global(u2, "view_document")
|
||||
|
||||
Document.objects.create(checksum="1", content="test 1", owner=u1)
|
||||
Document.objects.create(checksum="2", content="test 2", owner=u2)
|
||||
@@ -1590,8 +1587,8 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
"""
|
||||
u1 = UserFactory(username="user1")
|
||||
u2 = UserFactory(username="user2")
|
||||
u1.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
u2.user_permissions.add(*Permission.objects.filter(codename="view_document"))
|
||||
grant_global(u1, "view_document")
|
||||
grant_global(u2, "view_document")
|
||||
|
||||
d1 = Document.objects.create(checksum="1", content="test 1", owner=u1)
|
||||
d2 = Document.objects.create(checksum="2", content="test 2", owner=u2)
|
||||
@@ -1616,9 +1613,9 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
r = self.client.get("/api/documents/?query=test&owner__isnull=true")
|
||||
self.assertEqual(r.data["count"], 1)
|
||||
|
||||
assign_perm("view_document", u1, d2)
|
||||
assign_perm("view_document", u1, d3)
|
||||
assign_perm("view_document", u2, d1)
|
||||
grant_object(u1, d2, "view_document")
|
||||
grant_object(u1, d3, "view_document")
|
||||
grant_object(u2, d1, "view_document")
|
||||
|
||||
backend.add_or_update(d1)
|
||||
backend.add_or_update(d2)
|
||||
@@ -1925,7 +1922,7 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
sort_field="",
|
||||
owner=user2,
|
||||
)
|
||||
assign_perm("view_savedview", user1, shared_view)
|
||||
grant_object(user1, shared_view, "view_savedview")
|
||||
mail_account1 = MailAccount.objects.create(name="bank mail account 1")
|
||||
mail_account2 = MailAccount.objects.create(name="mail account 2")
|
||||
mail_rule1 = MailRule.objects.create(
|
||||
@@ -2020,10 +2017,7 @@ class TestDocumentSearchApi(DirectoriesMixin, APITestCase):
|
||||
def test_global_search_filters_owned_mail_objects(self) -> None:
|
||||
user1 = UserFactory(username="mail-search-user")
|
||||
user2 = UserFactory(username="other-mail-search-user")
|
||||
user1.user_permissions.add(
|
||||
Permission.objects.get(codename="view_mailaccount"),
|
||||
Permission.objects.get(codename="view_mailrule"),
|
||||
)
|
||||
grant_global(user1, "view_mailaccount", "view_mailrule")
|
||||
|
||||
own_account = MailAccount.objects.create(
|
||||
name="bank owned account",
|
||||
|
||||
@@ -5,7 +5,6 @@ from datetime import timedelta
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.test import override_settings
|
||||
from django.utils import timezone
|
||||
from rest_framework import status
|
||||
@@ -16,6 +15,7 @@ from documents.permissions import has_system_status_permission
|
||||
from paperless import version
|
||||
from paperless_testing.factories import PaperlessTaskFactory
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
|
||||
|
||||
class TestSystemStatus(APITestCase):
|
||||
@@ -106,9 +106,7 @@ class TestSystemStatus(APITestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
user = UserFactory(username="status_user")
|
||||
user.user_permissions.add(
|
||||
Permission.objects.get(codename="view_system_monitoring"),
|
||||
)
|
||||
grant_global(user, "view_system_monitoring")
|
||||
|
||||
self.client.force_login(user)
|
||||
response = self.client.get(self.ENDPOINT)
|
||||
|
||||
@@ -11,10 +11,8 @@ from datetime import timedelta
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils import timezone
|
||||
from guardian.shortcuts import assign_perm
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
@@ -22,6 +20,8 @@ from documents.filters import PaperlessTaskFilterSet
|
||||
from documents.models import PaperlessTask
|
||||
from paperless_testing.factories import DocumentFactory
|
||||
from paperless_testing.factories import PaperlessTaskFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
pytestmark = pytest.mark.api
|
||||
|
||||
@@ -348,9 +348,7 @@ class TestGetTasksV10:
|
||||
user_client: APIClient,
|
||||
) -> None:
|
||||
"""Regular users see their own tasks and unowned (system) tasks; other users' tasks are hidden."""
|
||||
regular_user.user_permissions.add(
|
||||
Permission.objects.get(codename="view_paperlesstask"),
|
||||
)
|
||||
grant_global(regular_user, "view_paperlesstask")
|
||||
|
||||
PaperlessTaskFactory(owner=admin_user) # other user — not visible
|
||||
unowned_task = PaperlessTaskFactory() # unowned (system task) — visible
|
||||
@@ -586,9 +584,7 @@ class TestGetTasksV9:
|
||||
regular_user: User,
|
||||
) -> None:
|
||||
"""Non-staff users see their own tasks plus unowned tasks via v9 API."""
|
||||
regular_user.user_permissions.add(
|
||||
Permission.objects.get(codename="view_paperlesstask"),
|
||||
)
|
||||
grant_global(regular_user, "view_paperlesstask")
|
||||
|
||||
client = APIClient()
|
||||
client.force_authenticate(user=regular_user)
|
||||
@@ -734,9 +730,7 @@ class TestAcknowledge:
|
||||
user_client: APIClient,
|
||||
) -> None:
|
||||
"""Users granted change_paperlesstask permission can acknowledge tasks."""
|
||||
regular_user.user_permissions.add(
|
||||
Permission.objects.get(codename="change_paperlesstask"),
|
||||
)
|
||||
grant_global(regular_user, "change_paperlesstask")
|
||||
regular_user.save()
|
||||
|
||||
task = PaperlessTaskFactory()
|
||||
@@ -803,9 +797,7 @@ class TestSummaryPermissions:
|
||||
regular_user,
|
||||
) -> None:
|
||||
"""A user with view_system_monitoring but no document permissions can access summary/."""
|
||||
regular_user.user_permissions.add(
|
||||
Permission.objects.get(codename="view_system_monitoring"),
|
||||
)
|
||||
grant_global(regular_user, "view_system_monitoring")
|
||||
|
||||
response = user_client.get(ENDPOINT + "summary/")
|
||||
|
||||
@@ -818,9 +810,7 @@ class TestSummaryPermissions:
|
||||
admin_user,
|
||||
) -> None:
|
||||
"""Monitoring user sees aggregate data for all tasks, not just unowned ones."""
|
||||
regular_user.user_permissions.add(
|
||||
Permission.objects.get(codename="view_system_monitoring"),
|
||||
)
|
||||
grant_global(regular_user, "view_system_monitoring")
|
||||
PaperlessTaskFactory(
|
||||
owner=admin_user,
|
||||
task_type=PaperlessTask.TaskType.CONSUME_FILE,
|
||||
@@ -841,9 +831,7 @@ class TestSummaryPermissions:
|
||||
) -> None:
|
||||
"""A regular user with view_paperlesstask but not view_system_monitoring sees only
|
||||
their own tasks and unowned tasks in the summary, not other users' tasks."""
|
||||
regular_user.user_permissions.add(
|
||||
Permission.objects.get(codename="view_paperlesstask"),
|
||||
)
|
||||
grant_global(regular_user, "view_paperlesstask")
|
||||
|
||||
PaperlessTaskFactory(
|
||||
owner=regular_user,
|
||||
@@ -1008,9 +996,7 @@ class TestDuplicateDocumentsPermissions:
|
||||
|
||||
@pytest.fixture()
|
||||
def user_v9_client(self, regular_user: User) -> APIClient:
|
||||
regular_user.user_permissions.add(
|
||||
Permission.objects.get(codename="view_paperlesstask"),
|
||||
)
|
||||
grant_global(regular_user, "view_paperlesstask")
|
||||
client = APIClient()
|
||||
client.force_authenticate(user=regular_user)
|
||||
client.credentials(HTTP_ACCEPT=ACCEPT_V9)
|
||||
@@ -1081,7 +1067,7 @@ class TestDuplicateDocumentsPermissions:
|
||||
) -> None:
|
||||
"""A user with explicit guardian view_document permission sees the duplicate_of document."""
|
||||
doc = DocumentFactory(owner=admin_user, title="Granted Doc")
|
||||
assign_perm("view_document", regular_user, doc)
|
||||
grant_object(regular_user, doc, "view_document")
|
||||
PaperlessTaskFactory(
|
||||
owner=regular_user,
|
||||
status=PaperlessTask.Status.SUCCESS,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from datetime import date
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.core.cache import cache
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
@@ -8,6 +7,7 @@ from rest_framework.test import APITestCase
|
||||
from documents.models import Document
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_all_global
|
||||
|
||||
|
||||
class TestTrashAPI(DirectoriesMixin, APITestCase):
|
||||
@@ -15,7 +15,7 @@ class TestTrashAPI(DirectoriesMixin, APITestCase):
|
||||
super().setUp()
|
||||
|
||||
self.user = UserFactory(username="temp_admin")
|
||||
self.user.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(self.user)
|
||||
self.client.force_authenticate(user=self.user)
|
||||
cache.clear()
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ from django.contrib.auth.models import User
|
||||
from django.db import connection
|
||||
from django.test import TestCase
|
||||
from django.test.utils import CaptureQueriesContext
|
||||
from guardian.shortcuts import assign_perm
|
||||
from guardian.shortcuts import get_groups_with_perms
|
||||
from guardian.shortcuts import get_users_with_perms
|
||||
|
||||
@@ -24,6 +23,7 @@ from documents.models import StoragePath
|
||||
from documents.models import Tag
|
||||
from documents.permissions import set_permissions_for_objects
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
|
||||
class TestBulkEdit(DirectoriesMixin, TestCase):
|
||||
@@ -440,7 +440,7 @@ class TestBulkEdit(DirectoriesMixin, TestCase):
|
||||
def test_set_permissions(self, m) -> None:
|
||||
doc_ids = [self.doc1.id, self.doc2.id, self.doc3.id]
|
||||
|
||||
assign_perm("view_document", self.group1, self.doc1)
|
||||
grant_object(self.group1, self.doc1, "view_document")
|
||||
|
||||
permissions = {
|
||||
"view": {
|
||||
@@ -482,8 +482,8 @@ class TestBulkEdit(DirectoriesMixin, TestCase):
|
||||
self.doc1.owner = self.user1
|
||||
self.doc1.save()
|
||||
|
||||
assign_perm("view_document", self.user1, self.doc1)
|
||||
assign_perm("view_document", self.group1, self.doc1)
|
||||
grant_object(self.user1, self.doc1, "view_document")
|
||||
grant_object(self.group1, self.doc1, "view_document")
|
||||
|
||||
permissions = {
|
||||
"view": {
|
||||
@@ -609,7 +609,7 @@ class TestBulkEdit(DirectoriesMixin, TestCase):
|
||||
self.doc1.owner = self.user1
|
||||
self.doc1.save()
|
||||
self.user1.groups.add(self.group1)
|
||||
assign_perm("view_document", self.group1, self.doc1)
|
||||
grant_object(self.group1, self.doc1, "view_document")
|
||||
|
||||
bulk_edit.set_permissions(
|
||||
[self.doc1.id],
|
||||
|
||||
@@ -26,7 +26,6 @@ from django.test import override_settings
|
||||
from django.utils import timezone
|
||||
from guardian.models import GroupObjectPermission
|
||||
from guardian.models import UserObjectPermission
|
||||
from guardian.shortcuts import assign_perm
|
||||
|
||||
from documents.management.commands import document_exporter
|
||||
from documents.models import Correspondent
|
||||
@@ -51,6 +50,7 @@ from documents.tests.utils import SampleDirMixin
|
||||
from paperless_mail.models import MailAccount
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.dirs import paperless_environment
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
|
||||
@pytest.mark.management
|
||||
@@ -105,8 +105,8 @@ class TestExportImport(
|
||||
user=self.user,
|
||||
)
|
||||
|
||||
assign_perm("view_document", self.user2, self.d2)
|
||||
assign_perm("view_document", self.group1, self.d3)
|
||||
grant_object(self.user2, self.d2, "view_document")
|
||||
grant_object(self.group1, self.d3, "view_document")
|
||||
|
||||
self.t1 = Tag.objects.create(name="t")
|
||||
self.dt1 = DocumentType.objects.create(name="dt")
|
||||
|
||||
@@ -2,7 +2,6 @@ import json
|
||||
from unittest import mock
|
||||
|
||||
from auditlog.models import LogEntry
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase
|
||||
from rest_framework import status
|
||||
@@ -12,6 +11,7 @@ from documents.bulk_edit import merge_as_versions
|
||||
from documents.models import Document
|
||||
from documents.serialisers import MergeDocumentsAsVersionsSerializer
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
|
||||
|
||||
class TestMergeDocumentsAsVersionsSerializer(TestCase):
|
||||
@@ -336,11 +336,7 @@ class TestMergeDocumentsAsVersions(TestCase):
|
||||
class TestMergeDocumentsAsVersionsAPI(APITestCase):
|
||||
def setUp(self) -> None:
|
||||
self.user = UserFactory(username="user")
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(codename="change_document"),
|
||||
Permission.objects.get(codename="view_document"),
|
||||
Permission.objects.get(codename="delete_document"),
|
||||
)
|
||||
grant_global(self.user, "change_document", "view_document", "delete_document")
|
||||
self.doc1 = Document.objects.create(
|
||||
checksum="A",
|
||||
title="A",
|
||||
@@ -406,10 +402,7 @@ class TestMergeDocumentsAsVersionsAPI(APITestCase):
|
||||
merge_mock.__name__ = "merge_as_versions"
|
||||
# Owns them and may change them, but may not make them stop being documents
|
||||
user = UserFactory(username="no-delete")
|
||||
user.user_permissions.add(
|
||||
Permission.objects.get(codename="change_document"),
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(user, "change_document", "view_document")
|
||||
for doc in (self.doc1, self.doc2):
|
||||
doc.owner = user
|
||||
doc.save()
|
||||
|
||||
@@ -7,9 +7,7 @@ from unittest.mock import patch
|
||||
import pytest
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.contrib.auth.models import Group
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.test import override_settings
|
||||
from guardian.shortcuts import assign_perm
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
from documents.matching import match_correspondents
|
||||
@@ -30,6 +28,8 @@ from paperless_testing.factories import DocumentTypeFactory
|
||||
from paperless_testing.factories import StoragePathFactory
|
||||
from paperless_testing.factories import TagFactory
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from paperless_testing.dirs import PaperlessDirs
|
||||
@@ -80,7 +80,7 @@ class TestPermittedDocumentIdsSecurity:
|
||||
owner = UserFactory(username="owner")
|
||||
shared = DocumentFactory(owner=owner)
|
||||
not_shared = DocumentFactory(owner=owner)
|
||||
assign_perm("view_document", grantee, shared)
|
||||
grant_object(grantee, shared, "view_document")
|
||||
|
||||
assert_visible_document_ids(
|
||||
permitted_document_ids(grantee),
|
||||
@@ -100,7 +100,7 @@ class TestPermittedDocumentIdsSecurity:
|
||||
group = Group.objects.create(name="finance")
|
||||
member.groups.add(group)
|
||||
shared = DocumentFactory(owner=owner)
|
||||
assign_perm("view_document", group, shared)
|
||||
grant_object(group, shared, "view_document")
|
||||
|
||||
assert_visible_document_ids(
|
||||
permitted_document_ids(member),
|
||||
@@ -197,12 +197,10 @@ class TestAiChatAllDocumentsPermissionBoundary:
|
||||
|
||||
owner = UserFactory(username="owner")
|
||||
asker = UserFactory(username="asker")
|
||||
asker.user_permissions.add(
|
||||
*Permission.objects.filter(codename="view_document"),
|
||||
)
|
||||
grant_global(asker, "view_document")
|
||||
shared = DocumentFactory(owner=owner)
|
||||
not_shared = DocumentFactory(owner=owner)
|
||||
assign_perm("view_document", asker, shared)
|
||||
grant_object(asker, shared, "view_document")
|
||||
|
||||
client = APIClient()
|
||||
client.force_authenticate(user=asker)
|
||||
@@ -229,7 +227,7 @@ class TestDuplicateDocumentsPermissionBoundary:
|
||||
dup_visible = DocumentFactory(owner=owner, checksum="dupe-checksum")
|
||||
dup_hidden = DocumentFactory(owner=owner, checksum="dupe-checksum")
|
||||
dup_hidden.delete() # soft delete, should still be found (include_deleted=True)
|
||||
assign_perm("view_document", stranger, dup_visible)
|
||||
grant_object(stranger, dup_visible, "view_document")
|
||||
|
||||
result_owner = _get_viewable_duplicates(original, owner)
|
||||
assert {d.pk for d in result_owner} == {dup_visible.pk, dup_hidden.pk}
|
||||
@@ -245,9 +243,9 @@ class TestPermittedDocumentIdsArbitraryPermission:
|
||||
viewer_only = UserFactory(username="viewer")
|
||||
editor = UserFactory(username="editor")
|
||||
doc = DocumentFactory(owner=owner)
|
||||
assign_perm("view_document", viewer_only, doc)
|
||||
assign_perm("change_document", editor, doc)
|
||||
assign_perm("view_document", editor, doc)
|
||||
grant_object(viewer_only, doc, "view_document")
|
||||
grant_object(editor, doc, "change_document")
|
||||
grant_object(editor, doc, "view_document")
|
||||
|
||||
assert_visible_document_ids(
|
||||
permitted_document_ids(editor, perm="change_document"),
|
||||
@@ -264,7 +262,7 @@ class TestPermittedDocumentIdsArbitraryPermission:
|
||||
owner = UserFactory(username="owner")
|
||||
editor = UserFactory(username="editor")
|
||||
doc = DocumentFactory(owner=owner)
|
||||
assign_perm("change_document", editor, doc)
|
||||
grant_object(editor, doc, "change_document")
|
||||
|
||||
assert_visible_document_ids(
|
||||
permitted_document_ids(editor, perm="documents.change_document"),
|
||||
@@ -277,7 +275,7 @@ class TestPermittedDocumentIdsArbitraryPermission:
|
||||
stranger = UserFactory(username="mallory")
|
||||
view_only = UserFactory(username="viewer")
|
||||
doc = DocumentFactory(owner=owner)
|
||||
assign_perm("view_document", view_only, doc)
|
||||
grant_object(view_only, doc, "view_document")
|
||||
doc.delete()
|
||||
|
||||
assert_visible_document_ids(
|
||||
@@ -313,9 +311,7 @@ class TestEmailDocumentPermissionBoundary:
|
||||
):
|
||||
owner = UserFactory(username="owner")
|
||||
requester = UserFactory(username="requester")
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(requester, "view_document")
|
||||
rest_api_client.force_authenticate(user=requester)
|
||||
hidden = DocumentFactory(owner=owner)
|
||||
|
||||
@@ -347,15 +343,13 @@ class TestBulkEditChangePermissionBoundary:
|
||||
requester = UserFactory(username="requester")
|
||||
# grant the global change_document permission so the object-level
|
||||
# check (not the global has_perm check) is what's under test
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="change_document"),
|
||||
)
|
||||
grant_global(requester, "change_document")
|
||||
rest_api_client.force_authenticate(user=requester)
|
||||
changeable = DocumentFactory(owner=owner)
|
||||
assign_perm("view_document", requester, changeable)
|
||||
assign_perm("change_document", requester, changeable) # fully permitted
|
||||
grant_object(requester, changeable, "view_document")
|
||||
grant_object(requester, changeable, "change_document") # fully permitted
|
||||
target = DocumentFactory(owner=owner)
|
||||
assign_perm("view_document", requester, target) # view only, NOT change
|
||||
grant_object(requester, target, "view_document") # view only, NOT change
|
||||
|
||||
response = rest_api_client.post(
|
||||
"/api/documents/bulk_edit/",
|
||||
@@ -380,7 +374,7 @@ class TestBulkDownloadPermissionChecksRootDocument:
|
||||
requester = UserFactory(username="requester")
|
||||
root = DocumentFactory(owner=owner)
|
||||
root.source_path.write_bytes(b"%PDF-1.4 test")
|
||||
assign_perm("view_document", requester, root)
|
||||
grant_object(requester, root, "view_document")
|
||||
rest_api_client.force_authenticate(user=requester)
|
||||
|
||||
response = rest_api_client.post(
|
||||
@@ -398,15 +392,13 @@ class TestBulkDownloadPermissionChecksRootDocument:
|
||||
) -> None:
|
||||
owner = UserFactory(username="owner")
|
||||
requester = UserFactory(username="requester")
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(requester, "view_document")
|
||||
rest_api_client.force_authenticate(user=requester)
|
||||
root = DocumentFactory(owner=owner)
|
||||
# a version of root that the requester has NOT been individually granted
|
||||
version = DocumentFactory(owner=owner, root_document=root, version_index=1)
|
||||
version.source_path.write_bytes(b"%PDF-1.4 test")
|
||||
assign_perm("view_document", requester, root) # granted on ROOT only
|
||||
grant_object(requester, root, "view_document") # granted on ROOT only
|
||||
|
||||
response = rest_api_client.post(
|
||||
"/api/documents/bulk_download/",
|
||||
@@ -425,10 +417,8 @@ class TestBulkDownloadPermissionChecksRootDocument:
|
||||
# `stranger` case) can't tell the two apart, since they're denied
|
||||
# either way.
|
||||
version_only_grantee = UserFactory(username="version_only_grantee")
|
||||
version_only_grantee.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
assign_perm("view_document", version_only_grantee, version)
|
||||
grant_global(version_only_grantee, "view_document")
|
||||
grant_object(version_only_grantee, version, "view_document")
|
||||
rest_api_client.force_authenticate(user=version_only_grantee)
|
||||
response = rest_api_client.post(
|
||||
"/api/documents/bulk_download/",
|
||||
@@ -449,12 +439,10 @@ class TestTrashRestorePermissionBoundary:
|
||||
):
|
||||
owner = UserFactory(username="owner")
|
||||
requester = UserFactory(username="requester")
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="delete_document"),
|
||||
)
|
||||
grant_global(requester, "delete_document")
|
||||
rest_api_client.force_authenticate(user=requester)
|
||||
doc = DocumentFactory(owner=owner)
|
||||
assign_perm("view_document", requester, doc) # view only, NOT delete
|
||||
grant_object(requester, doc, "view_document") # view only, NOT delete
|
||||
doc.delete()
|
||||
|
||||
response = rest_api_client.post(
|
||||
@@ -470,12 +458,10 @@ class TestTrashRestorePermissionBoundary:
|
||||
):
|
||||
owner = UserFactory(username="owner")
|
||||
requester = UserFactory(username="requester")
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="delete_document"),
|
||||
)
|
||||
grant_global(requester, "delete_document")
|
||||
rest_api_client.force_authenticate(user=requester)
|
||||
doc = DocumentFactory(owner=owner)
|
||||
assign_perm("delete_document", requester, doc)
|
||||
grant_object(requester, doc, "delete_document")
|
||||
doc.delete()
|
||||
|
||||
response = rest_api_client.post(
|
||||
@@ -490,7 +476,7 @@ class TestTrashRestorePermissionBoundary:
|
||||
requester = UserFactory(username="requester")
|
||||
rest_api_client.force_authenticate(user=requester)
|
||||
doc = DocumentFactory(owner=owner)
|
||||
assign_perm("delete_document", requester, doc)
|
||||
grant_object(requester, doc, "delete_document")
|
||||
doc.delete()
|
||||
|
||||
response = rest_api_client.post(
|
||||
@@ -517,12 +503,10 @@ class TestTrashViewExcludesExplicitlyGrantedDocuments:
|
||||
def test_explicit_grant_does_not_leak_trashed_document(self, rest_api_client):
|
||||
owner = UserFactory(username="trash_owner")
|
||||
grantee = UserFactory(username="trash_grantee")
|
||||
grantee.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(grantee, "view_document")
|
||||
doc = DocumentFactory(owner=owner)
|
||||
doc.delete() # soft delete
|
||||
assign_perm("view_document", grantee, doc)
|
||||
grant_object(grantee, doc, "view_document")
|
||||
|
||||
rest_api_client.force_authenticate(user=grantee)
|
||||
response = rest_api_client.get("/api/trash/")
|
||||
@@ -565,7 +549,7 @@ class TestPermittedObjectIdsGenericModels:
|
||||
)
|
||||
other = UserFactory(username=f"other_{suffix}")
|
||||
granted = factory(owner=other)
|
||||
assign_perm(perm, user, granted)
|
||||
grant_object(user, granted, perm)
|
||||
|
||||
assert_visible_document_ids(
|
||||
permitted_object_ids(user, model, perm),
|
||||
@@ -593,7 +577,7 @@ class TestPermittedObjectIdsGenericModels:
|
||||
stranger = UserFactory(username=f"stranger2_{model.__name__}")
|
||||
shared = factory(owner=owner)
|
||||
not_shared = factory(owner=owner)
|
||||
assign_perm(perm, grantee, shared)
|
||||
grant_object(grantee, shared, perm)
|
||||
|
||||
assert_visible_document_ids(
|
||||
permitted_object_ids(grantee, model, perm),
|
||||
@@ -618,7 +602,7 @@ class TestPermittedObjectIdsGenericModels:
|
||||
group = Group.objects.create(name=f"group_{model.__name__}")
|
||||
member.groups.add(group)
|
||||
shared = factory(owner=owner)
|
||||
assign_perm(perm, group, shared)
|
||||
grant_object(group, shared, perm)
|
||||
|
||||
assert_visible_document_ids(
|
||||
permitted_object_ids(member, model, perm),
|
||||
@@ -658,7 +642,7 @@ class TestMatchingRespectsObjectPermissions:
|
||||
match="invoice",
|
||||
matching_algorithm=Tag.MATCH_LITERAL,
|
||||
)
|
||||
assign_perm("view_tag", classifying_user, visible_tag)
|
||||
grant_object(classifying_user, visible_tag, "view_tag")
|
||||
doc = DocumentFactory(owner=classifying_user, content="an invoice document")
|
||||
|
||||
matched = match_tags(doc, classifier=None, user=classifying_user)
|
||||
@@ -679,7 +663,7 @@ class TestMatchingRespectsObjectPermissions:
|
||||
match="invoice",
|
||||
matching_algorithm=Correspondent.MATCH_LITERAL,
|
||||
)
|
||||
assign_perm("view_correspondent", classifying_user, visible_correspondent)
|
||||
grant_object(classifying_user, visible_correspondent, "view_correspondent")
|
||||
doc = DocumentFactory(owner=classifying_user, content="an invoice document")
|
||||
|
||||
matched = match_correspondents(doc, classifier=None, user=classifying_user)
|
||||
@@ -700,7 +684,7 @@ class TestMatchingRespectsObjectPermissions:
|
||||
match="invoice",
|
||||
matching_algorithm=DocumentType.MATCH_LITERAL,
|
||||
)
|
||||
assign_perm("view_documenttype", classifying_user, visible_document_type)
|
||||
grant_object(classifying_user, visible_document_type, "view_documenttype")
|
||||
doc = DocumentFactory(owner=classifying_user, content="an invoice document")
|
||||
|
||||
matched = match_document_types(doc, classifier=None, user=classifying_user)
|
||||
@@ -721,7 +705,7 @@ class TestMatchingRespectsObjectPermissions:
|
||||
match="invoice",
|
||||
matching_algorithm=StoragePath.MATCH_LITERAL,
|
||||
)
|
||||
assign_perm("view_storagepath", classifying_user, visible_storage_path)
|
||||
grant_object(classifying_user, visible_storage_path, "view_storagepath")
|
||||
doc = DocumentFactory(owner=classifying_user, content="an invoice document")
|
||||
|
||||
matched = match_storage_paths(doc, classifier=None, user=classifying_user)
|
||||
@@ -738,9 +722,7 @@ class TestBulkEditObjectsApplyToAllPermissionBoundary:
|
||||
new_owner = UserFactory(username="tags_new_owner")
|
||||
# grant the global change_tag permission so the object-level
|
||||
# filtering (not the global has_perm check) is what's under test
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="change_tag"),
|
||||
)
|
||||
grant_global(requester, "change_tag")
|
||||
rest_api_client.force_authenticate(user=requester)
|
||||
visible = TagFactory(owner=requester)
|
||||
hidden = TagFactory(owner=owner)
|
||||
@@ -775,14 +757,12 @@ class TestBulkEditObjectsApplyToAllPermissionBoundary:
|
||||
"""
|
||||
owner = UserFactory(username="shared_tags_owner")
|
||||
requester = UserFactory(username="shared_tags_requester")
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="change_tag"),
|
||||
)
|
||||
grant_global(requester, "change_tag")
|
||||
rest_api_client.force_authenticate(user=requester)
|
||||
owned = TagFactory(owner=requester)
|
||||
shared = TagFactory(owner=owner)
|
||||
assign_perm("view_tag", requester, shared)
|
||||
assign_perm("change_tag", requester, shared)
|
||||
grant_object(requester, shared, "view_tag")
|
||||
grant_object(requester, shared, "change_tag")
|
||||
|
||||
response = rest_api_client.post(
|
||||
"/api/bulk_edit_objects/",
|
||||
@@ -838,9 +818,7 @@ class TestBulkEditObjectsTagDescendantPartialPermission:
|
||||
new_owner = UserFactory(username="tag_hierarchy_new_owner")
|
||||
# global change_tag permission so the has_perm() gate passes and the
|
||||
# object-level permitted_object_ids filtering is what's under test
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="change_tag"),
|
||||
)
|
||||
grant_global(requester, "change_tag")
|
||||
rest_api_client.force_authenticate(user=requester)
|
||||
|
||||
parent = TagFactory(owner=requester, name="parent-tag")
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import pytest
|
||||
from guardian.shortcuts import assign_perm
|
||||
from rest_framework.test import APIRequestFactory
|
||||
|
||||
from documents.filters import PermittedObjectsFilter
|
||||
from documents.models import Tag
|
||||
from paperless_testing.factories import TagFactory
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
|
||||
class _DummyView:
|
||||
@@ -35,7 +35,7 @@ class TestPermittedObjectsFilter:
|
||||
unowned = TagFactory(owner=None)
|
||||
granted = TagFactory(owner=owner)
|
||||
hidden = TagFactory(owner=owner)
|
||||
assign_perm("view_tag", grantee, granted)
|
||||
grant_object(grantee, granted, "view_tag")
|
||||
request = APIRequestFactory().get("/")
|
||||
request.user = grantee
|
||||
|
||||
@@ -53,7 +53,7 @@ class TestPermittedObjectsFilter:
|
||||
grantee = UserFactory(username="grantee2")
|
||||
owned = TagFactory(owner=grantee)
|
||||
granted = TagFactory(owner=owner)
|
||||
assign_perm("view_tag", grantee, granted)
|
||||
grant_object(grantee, granted, "view_tag")
|
||||
request = APIRequestFactory().get("/")
|
||||
request.user = grantee
|
||||
|
||||
@@ -82,7 +82,7 @@ class TestPermittedObjectsFilter:
|
||||
TagFactory(owner=None)
|
||||
TagFactory(owner=user)
|
||||
granted = TagFactory(owner=UserFactory(username=f"o_{username}"))
|
||||
assign_perm("view_tag", user, granted)
|
||||
grant_object(user, granted, "view_tag")
|
||||
request = APIRequestFactory().get("/")
|
||||
request.user = user
|
||||
|
||||
|
||||
@@ -6,10 +6,8 @@ from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils import timezone
|
||||
from guardian.shortcuts import assign_perm
|
||||
from rest_framework import serializers
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
@@ -23,6 +21,8 @@ from documents.tasks import cleanup_expired_share_link_bundles
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import DocumentFactory
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
|
||||
class ShareLinkBundleAPITests(DirectoriesMixin, APITestCase):
|
||||
@@ -58,11 +58,9 @@ class ShareLinkBundleAPITests(DirectoriesMixin, APITestCase):
|
||||
) -> None:
|
||||
owner = UserFactory(username="document_owner")
|
||||
requester = UserFactory(username="bundle_creator")
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="add_sharelinkbundle"),
|
||||
)
|
||||
grant_global(requester, "add_sharelinkbundle")
|
||||
document = DocumentFactory.create(owner=owner)
|
||||
assign_perm("view_document", requester, document)
|
||||
grant_object(requester, document, "view_document")
|
||||
self.client.force_authenticate(requester)
|
||||
payload = {
|
||||
"document_ids": [document.pk],
|
||||
@@ -73,9 +71,7 @@ class ShareLinkBundleAPITests(DirectoriesMixin, APITestCase):
|
||||
response = self.client.post(self.ENDPOINT, payload, format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(requester, "view_document")
|
||||
requester = User.objects.get(pk=requester.pk)
|
||||
self.client.force_authenticate(requester)
|
||||
response = self.client.post(self.ENDPOINT, payload, format="json")
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
@@ -14,15 +13,14 @@ from documents.serialisers import TagSerializer
|
||||
from documents.signals.handlers import run_workflows
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
|
||||
|
||||
class TestTagHierarchyPermissions(APITestCase):
|
||||
def test_children_only_include_visible_tags(self) -> None:
|
||||
owner = UserFactory(username="owner")
|
||||
requester = UserFactory(username="requester")
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="view_tag"),
|
||||
)
|
||||
grant_global(requester, "view_tag")
|
||||
parent = Tag.objects.create(name="Visible parent", owner=requester)
|
||||
hidden_child = Tag.objects.create(
|
||||
name="Hidden child",
|
||||
|
||||
@@ -15,7 +15,6 @@ from django.test import TestCase
|
||||
from django.test import override_settings
|
||||
from django.test.utils import CaptureQueriesContext
|
||||
from django.utils import timezone
|
||||
from guardian.shortcuts import assign_perm
|
||||
from rest_framework import status
|
||||
|
||||
from documents.caching import get_llm_suggestion_cache
|
||||
@@ -35,6 +34,8 @@ from paperless_ai.exceptions import LLMProviderError
|
||||
from paperless_ai.exceptions import LLMTimeoutError
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
|
||||
class TestViews(DirectoriesMixin, TestCase):
|
||||
@@ -142,9 +143,7 @@ class TestViews(DirectoriesMixin, TestCase):
|
||||
codename__contains="sharelink",
|
||||
)
|
||||
self.user.user_permissions.add(*sharelink_permissions)
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(self.user, "view_document")
|
||||
self.user.save()
|
||||
|
||||
self.client.force_login(self.user)
|
||||
@@ -206,9 +205,7 @@ class TestViews(DirectoriesMixin, TestCase):
|
||||
codename__contains="sharelink",
|
||||
)
|
||||
self.user.user_permissions.add(*sharelink_permissions)
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(codename="view_document"),
|
||||
)
|
||||
grant_global(self.user, "view_document")
|
||||
self.client.force_login(self.user)
|
||||
|
||||
create_response = self.client.post(
|
||||
@@ -241,16 +238,16 @@ class TestViews(DirectoriesMixin, TestCase):
|
||||
group2 = Group.objects.create(name="group2")
|
||||
group3 = Group.objects.create(name="group3")
|
||||
t1 = Tag.objects.create(name="invoice", pk=1)
|
||||
assign_perm("view_tag", self.user, t1)
|
||||
assign_perm("view_tag", user2, t1)
|
||||
assign_perm("view_tag", user3, t1)
|
||||
assign_perm("view_tag", group1, t1)
|
||||
assign_perm("view_tag", group2, t1)
|
||||
assign_perm("view_tag", group3, t1)
|
||||
assign_perm("change_tag", self.user, t1)
|
||||
assign_perm("change_tag", user2, t1)
|
||||
assign_perm("change_tag", group1, t1)
|
||||
assign_perm("change_tag", group2, t1)
|
||||
grant_object(self.user, t1, "view_tag")
|
||||
grant_object(user2, t1, "view_tag")
|
||||
grant_object(user3, t1, "view_tag")
|
||||
grant_object(group1, t1, "view_tag")
|
||||
grant_object(group2, t1, "view_tag")
|
||||
grant_object(group3, t1, "view_tag")
|
||||
grant_object(self.user, t1, "change_tag")
|
||||
grant_object(user2, t1, "change_tag")
|
||||
grant_object(group1, t1, "change_tag")
|
||||
grant_object(group2, t1, "change_tag")
|
||||
|
||||
Tag.objects.create(name="bank statement", pk=2)
|
||||
d1 = Document.objects.create(
|
||||
@@ -429,11 +426,7 @@ class TestAISuggestions(DirectoriesMixin, TestCase):
|
||||
tag_owner = UserFactory(username="cache_tag_owner")
|
||||
invisible_tag = Tag.objects.create(name="cache_restricted", owner=tag_owner)
|
||||
requester = UserFactory(username="cache_requester")
|
||||
requester.user_permissions.add(
|
||||
*Permission.objects.filter(
|
||||
codename__in=["view_document", "change_document", "view_tag"],
|
||||
),
|
||||
)
|
||||
grant_global(requester, "view_document", "change_document", "view_tag")
|
||||
mock_get_cache.return_value = MagicMock(
|
||||
suggestions={
|
||||
"title": "Untitled",
|
||||
@@ -879,11 +872,7 @@ class TestAISuggestions(DirectoriesMixin, TestCase):
|
||||
tag_owner = UserFactory(username="tagowner")
|
||||
invisible_tag = Tag.objects.create(name="restricted", owner=tag_owner)
|
||||
requester = UserFactory(username="requester")
|
||||
requester.user_permissions.add(
|
||||
*Permission.objects.filter(
|
||||
codename__in=["view_document", "change_document", "view_tag"],
|
||||
),
|
||||
)
|
||||
grant_global(requester, "view_document", "change_document", "view_tag")
|
||||
|
||||
mock_get_ai_classification.return_value = {
|
||||
"title": "Untitled",
|
||||
@@ -967,9 +956,7 @@ class TestAIChatStreamingView(DirectoriesMixin, TestCase):
|
||||
super().setUp()
|
||||
|
||||
def grant_view_document_permission(self) -> None:
|
||||
self.user.user_permissions.add(
|
||||
*Permission.objects.filter(codename="view_document"),
|
||||
)
|
||||
grant_global(self.user, "view_document")
|
||||
|
||||
@override_settings(AI_ENABLED=False)
|
||||
def test_post_ai_disabled(self) -> None:
|
||||
|
||||
@@ -17,7 +17,6 @@ from django.contrib.auth.models import User
|
||||
from django.core import mail
|
||||
from django.test import override_settings
|
||||
from django.utils import timezone
|
||||
from guardian.shortcuts import assign_perm
|
||||
from guardian.shortcuts import get_groups_with_perms
|
||||
from guardian.shortcuts import get_users_with_perms
|
||||
from httpx import ConnectError
|
||||
@@ -72,6 +71,7 @@ from paperless_mail.models import MailAccount
|
||||
from paperless_mail.models import MailRule
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
|
||||
class TestWorkflows(
|
||||
@@ -2130,10 +2130,10 @@ class TestWorkflows(
|
||||
original_filename="sample.pdf",
|
||||
)
|
||||
|
||||
assign_perm("documents.view_document", self.user2, doc)
|
||||
assign_perm("documents.change_document", self.user2, doc)
|
||||
assign_perm("documents.view_document", self.group1, doc)
|
||||
assign_perm("documents.change_document", self.group1, doc)
|
||||
grant_object(self.user2, doc, "documents.view_document")
|
||||
grant_object(self.user2, doc, "documents.change_document")
|
||||
grant_object(self.group1, doc, "documents.view_document")
|
||||
grant_object(self.group1, doc, "documents.change_document")
|
||||
|
||||
superuser = UserFactory(username="superuser", superuser=True)
|
||||
self.client.force_authenticate(user=superuser)
|
||||
@@ -2901,10 +2901,10 @@ class TestWorkflows(
|
||||
doc.tags.set([self.t1, self.t2])
|
||||
CustomFieldInstance.objects.create(document=doc, field=self.cf1)
|
||||
doc.save()
|
||||
assign_perm("documents.view_document", self.user3, doc)
|
||||
assign_perm("documents.change_document", self.user3, doc)
|
||||
assign_perm("documents.view_document", self.group1, doc)
|
||||
assign_perm("documents.change_document", self.group1, doc)
|
||||
grant_object(self.user3, doc, "documents.view_document")
|
||||
grant_object(self.user3, doc, "documents.change_document")
|
||||
grant_object(self.group1, doc, "documents.view_document")
|
||||
grant_object(self.group1, doc, "documents.change_document")
|
||||
|
||||
superuser = UserFactory(username="superuser", superuser=True)
|
||||
self.client.force_authenticate(user=superuser)
|
||||
@@ -3098,10 +3098,10 @@ class TestWorkflows(
|
||||
doc.tags.set([self.t1, self.t2])
|
||||
CustomFieldInstance.objects.create(document=doc, field=self.cf1)
|
||||
doc.save()
|
||||
assign_perm("documents.view_document", self.user3, doc)
|
||||
assign_perm("documents.change_document", self.user3, doc)
|
||||
assign_perm("documents.view_document", self.group1, doc)
|
||||
assign_perm("documents.change_document", self.group1, doc)
|
||||
grant_object(self.user3, doc, "documents.view_document")
|
||||
grant_object(self.user3, doc, "documents.change_document")
|
||||
grant_object(self.group1, doc, "documents.view_document")
|
||||
grant_object(self.group1, doc, "documents.change_document")
|
||||
|
||||
superuser = UserFactory(username="superuser", superuser=True)
|
||||
self.client.force_authenticate(user=superuser)
|
||||
|
||||
@@ -7,7 +7,6 @@ from unittest.mock import patch
|
||||
import pytest
|
||||
import pytest_mock
|
||||
from django.test import override_settings
|
||||
from guardian.shortcuts import assign_perm
|
||||
from guardian.shortcuts import remove_perm
|
||||
|
||||
from documents.models import Document
|
||||
@@ -27,6 +26,7 @@ from paperless_ai.taxonomy import TaxonomyCandidates
|
||||
from paperless_testing.factories import DocumentFactory
|
||||
from paperless_testing.factories import TagFactory
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -815,8 +815,8 @@ class TestFulltextSimilarDocuments:
|
||||
content="shared content phrase",
|
||||
owner=owner,
|
||||
)
|
||||
assign_perm("view_document", viewer, permitted)
|
||||
assign_perm("view_document", viewer, now_private)
|
||||
grant_object(viewer, permitted, "view_document")
|
||||
grant_object(viewer, now_private, "view_document")
|
||||
fulltext_backend.add_or_update(source)
|
||||
fulltext_backend.add_or_update(permitted)
|
||||
fulltext_backend.add_or_update(now_private)
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import json
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.auth.models import User
|
||||
from guardian.shortcuts import assign_perm
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
@@ -19,6 +17,9 @@ from paperless_testing.factories import CorrespondentFactory
|
||||
from paperless_testing.factories import DocumentTypeFactory
|
||||
from paperless_testing.factories import TagFactory
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_all_global
|
||||
from paperless_testing.permissions import grant_global
|
||||
from paperless_testing.permissions import grant_object
|
||||
|
||||
|
||||
class TestAPIMailAccounts(DirectoriesMixin, APITestCase):
|
||||
@@ -35,7 +36,7 @@ class TestAPIMailAccounts(DirectoriesMixin, APITestCase):
|
||||
super().setUp()
|
||||
|
||||
self.user = UserFactory(username="temp_admin")
|
||||
self.user.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(self.user)
|
||||
self.user.save()
|
||||
self.client.force_authenticate(user=self.user)
|
||||
|
||||
@@ -331,7 +332,7 @@ class TestAPIMailAccounts(DirectoriesMixin, APITestCase):
|
||||
owner=owner,
|
||||
)
|
||||
user = UserFactory(username="object_perms_only")
|
||||
assign_perm("change_mailaccount", user, account)
|
||||
grant_object(user, account, "change_mailaccount")
|
||||
self.client.force_authenticate(user=user)
|
||||
|
||||
response = self.client.post(
|
||||
@@ -384,7 +385,7 @@ class TestAPIMailAccounts(DirectoriesMixin, APITestCase):
|
||||
account2 = MailAccountFactory(name="Email2", owner=self.user)
|
||||
_account3 = MailAccountFactory(name="Email3", owner=user2)
|
||||
account4 = MailAccountFactory(name="Email4", owner=user2)
|
||||
assign_perm("view_mailaccount", self.user, account4)
|
||||
grant_object(self.user, account4, "view_mailaccount")
|
||||
|
||||
response = self.client.get(self.ENDPOINT)
|
||||
|
||||
@@ -402,7 +403,7 @@ class TestAPIMailRules(DirectoriesMixin, APITestCase):
|
||||
super().setUp()
|
||||
|
||||
self.user = UserFactory(username="temp_admin")
|
||||
self.user.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(self.user)
|
||||
self.user.save()
|
||||
self.client.force_authenticate(user=self.user)
|
||||
|
||||
@@ -636,7 +637,7 @@ class TestAPIMailRules(DirectoriesMixin, APITestCase):
|
||||
) -> None:
|
||||
other_user = UserFactory(username="mail-owner")
|
||||
foreign_account = MailAccountFactory(name="ForeignEmail", owner=other_user)
|
||||
assign_perm("change_mailaccount", self.user, foreign_account)
|
||||
grant_object(self.user, foreign_account, "change_mailaccount")
|
||||
|
||||
response = self.client.post(
|
||||
self.ENDPOINT,
|
||||
@@ -688,7 +689,7 @@ class TestAPIMailRules(DirectoriesMixin, APITestCase):
|
||||
rule2 = MailRuleFactory(account=account1, order=1, owner=self.user)
|
||||
MailRuleFactory(account=account1, order=2, owner=user2)
|
||||
rule4 = MailRuleFactory(account=account1, order=3, owner=user2)
|
||||
assign_perm("view_mailrule", self.user, rule4)
|
||||
grant_object(self.user, rule4, "view_mailrule")
|
||||
|
||||
response = self.client.get(self.ENDPOINT)
|
||||
|
||||
@@ -739,7 +740,7 @@ class TestAPIProcessedMails(DirectoriesMixin, APITestCase):
|
||||
super().setUp()
|
||||
|
||||
self.user = UserFactory(username="temp_admin")
|
||||
self.user.user_permissions.add(*Permission.objects.all())
|
||||
grant_all_global(self.user)
|
||||
self.user.save()
|
||||
self.client.force_authenticate(user=self.user)
|
||||
|
||||
@@ -763,7 +764,7 @@ class TestAPIProcessedMails(DirectoriesMixin, APITestCase):
|
||||
)
|
||||
ProcessedMailFactory(rule=rule, owner=user2)
|
||||
pm4 = ProcessedMailFactory(rule=rule, owner=user2)
|
||||
assign_perm("view_processedmail", self.user, pm4)
|
||||
grant_object(self.user, pm4, "view_processedmail")
|
||||
|
||||
response = self.client.get(self.ENDPOINT)
|
||||
|
||||
@@ -814,7 +815,7 @@ class TestAPIProcessedMails(DirectoriesMixin, APITestCase):
|
||||
owner=self.user,
|
||||
)
|
||||
pm_granted = ProcessedMailFactory(rule=rule, owner=user2)
|
||||
assign_perm("delete_processedmail", self.user, pm_granted)
|
||||
grant_object(self.user, pm_granted, "delete_processedmail")
|
||||
pm_forbidden = ProcessedMailFactory(rule=rule, owner=user2)
|
||||
|
||||
# Success for allowed items
|
||||
@@ -858,11 +859,9 @@ class TestAPIProcessedMails(DirectoriesMixin, APITestCase):
|
||||
def test_bulk_delete_requires_global_delete_permission(self) -> None:
|
||||
owner = UserFactory(username="mail_owner")
|
||||
requester = UserFactory(username="mail_deleter")
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="add_processedmail"),
|
||||
)
|
||||
grant_global(requester, "add_processedmail")
|
||||
mail = ProcessedMailFactory(owner=owner)
|
||||
assign_perm("delete_processedmail", requester, mail)
|
||||
grant_object(requester, mail, "delete_processedmail")
|
||||
self.client.force_authenticate(requester)
|
||||
|
||||
response = self.client.post(
|
||||
@@ -872,9 +871,7 @@ class TestAPIProcessedMails(DirectoriesMixin, APITestCase):
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
requester.user_permissions.add(
|
||||
Permission.objects.get(codename="delete_processedmail"),
|
||||
)
|
||||
grant_global(requester, "delete_processedmail")
|
||||
requester = User.objects.get(pk=requester.pk)
|
||||
self.client.force_authenticate(requester)
|
||||
response = self.client.post(
|
||||
|
||||
@@ -43,6 +43,7 @@ from paperless_mail.tests.factories import MailRuleFactory
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import CorrespondentFactory
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
@@ -2264,11 +2265,7 @@ class TestMailAccountTestView(APITestCase):
|
||||
self.mailMocker.setUp()
|
||||
self.addCleanup(self.mailMocker.doCleanups)
|
||||
self.user = UserFactory(username="testuser", password="testpassword")
|
||||
self.user.user_permissions.add(
|
||||
*Permission.objects.filter(
|
||||
codename__in=["add_mailaccount", "change_mailaccount"],
|
||||
),
|
||||
)
|
||||
grant_global(self.user, "add_mailaccount", "change_mailaccount")
|
||||
self.user.save()
|
||||
self.client.force_authenticate(user=self.user)
|
||||
self.url = "/api/mail_accounts/test/"
|
||||
|
||||
@@ -14,6 +14,7 @@ from paperless_mail.models import MailAccount
|
||||
from paperless_mail.oauth import PaperlessMailOAuth2Manager
|
||||
from paperless_mail.tests.factories import MailAccountFactory
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
|
||||
|
||||
@override_settings(
|
||||
@@ -28,13 +29,7 @@ class TestMailOAuth(
|
||||
):
|
||||
def setUp(self) -> None:
|
||||
self.user = UserFactory(username="testuser")
|
||||
self.user.user_permissions.add(
|
||||
*Permission.objects.filter(
|
||||
codename__in=[
|
||||
"add_mailaccount",
|
||||
],
|
||||
),
|
||||
)
|
||||
grant_global(self.user, "add_mailaccount")
|
||||
self.user.save()
|
||||
self.client.force_login(self.user)
|
||||
self.mail_account_handler = MailAccountHandler()
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
"""Helpers that grant permissions to users and groups in tests.
|
||||
|
||||
Two mechanisms, two names. A global permission is a Django model permission held
|
||||
by a user. An object permission is a guardian permission held on one object by a
|
||||
user or a group. They are not interchangeable.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from guardian.shortcuts import assign_perm
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from django.contrib.auth.models import Group
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models import Model
|
||||
|
||||
|
||||
def grant_global(user: User, *perms: str) -> None:
|
||||
"""Grant model-level permissions.
|
||||
|
||||
Each of perms is a codename or "app_label.codename". An unknown name raises
|
||||
Permission.DoesNotExist.
|
||||
"""
|
||||
for perm in perms:
|
||||
app_label, _, codename = perm.rpartition(".")
|
||||
lookup = {"codename": codename}
|
||||
if app_label:
|
||||
lookup["content_type__app_label"] = app_label
|
||||
user.user_permissions.add(Permission.objects.get(**lookup))
|
||||
|
||||
|
||||
def grant_all_global(user: User) -> None:
|
||||
"""Grant every existing model-level permission without making a superuser."""
|
||||
user.user_permissions.add(*Permission.objects.all())
|
||||
|
||||
|
||||
def grant_object(target: User | Group, obj: Model, *perms: str) -> None:
|
||||
"""Grant object-level permissions on obj to a user or a group."""
|
||||
for perm in perms:
|
||||
assign_perm(perm, target, obj)
|
||||
Reference in New Issue
Block a user