浏览代码

Check user has "change" permission when viewing object usage

Karl Hobley 2 年之前
父节点
当前提交
d0fed42492

+ 52 - 0
wagtail/documents/tests/test_admin_views.py

@@ -1801,6 +1801,58 @@ class TestGetUsage(TestCase, WagtailTestUtils):
         # There's no usage so there should be no table rows
         self.assertRegex(response.content.decode("utf-8"), r"<tbody>(\s|\n)*</tbody>")
 
+    def test_usage_page_with_only_change_permission(self):
+        # Create a user with change_document permission but not add_document
+        user = self.create_user(
+            username="changeonly", email="changeonly@example.com", password="password"
+        )
+        change_permission = Permission.objects.get(
+            content_type__app_label="wagtaildocs", codename="change_document"
+        )
+        admin_permission = Permission.objects.get(
+            content_type__app_label="wagtailadmin", codename="access_admin"
+        )
+        self.changers_group = Group.objects.create(name="Document changers")
+        GroupCollectionPermission.objects.create(
+            group=self.changers_group,
+            collection=Collection.get_first_root_node(),
+            permission=change_permission,
+        )
+        user.groups.add(self.changers_group)
+
+        user.user_permissions.add(admin_permission)
+        self.login(username="changeonly", password="password")
+
+        response = self.client.get(reverse("wagtaildocs:document_usage", args=[1]))
+
+        self.assertEqual(response.status_code, 200)
+
+    def test_usage_page_without_change_permission(self):
+        # Create a user with add_document permission but not change_document
+        user = self.create_user(
+            username="addonly", email="addonly@example.com", password="password"
+        )
+        add_permission = Permission.objects.get(
+            content_type__app_label="wagtaildocs", codename="add_document"
+        )
+        admin_permission = Permission.objects.get(
+            content_type__app_label="wagtailadmin", codename="access_admin"
+        )
+        self.adders_group = Group.objects.create(name="Document adders")
+        GroupCollectionPermission.objects.create(
+            group=self.adders_group,
+            collection=Collection.get_first_root_node(),
+            permission=add_permission,
+        )
+        user.groups.add(self.adders_group)
+
+        user.user_permissions.add(admin_permission)
+        self.login(username="addonly", password="password")
+
+        response = self.client.get(reverse("wagtaildocs:document_usage", args=[1]))
+
+        self.assertEqual(response.status_code, 302)
+
 
 class TestEditOnlyPermissions(TestCase, WagtailTestUtils):
     def setUp(self):

+ 6 - 0
wagtail/documents/views/documents.py

@@ -260,10 +260,16 @@ def delete(request, document_id):
     )
 
 
+@permission_checker.require("change")
 def usage(request, document_id):
     Document = get_document_model()
     doc = get_object_or_404(Document, id=document_id)
 
+    if not permission_policy.user_has_permission_for_instance(
+        request.user, "change", doc
+    ):
+        raise PermissionDenied
+
     paginator = Paginator(doc.get_usage(), per_page=20)
     used_by = paginator.get_page(request.GET.get("p"))
 

+ 101 - 2
wagtail/images/tests/test_admin_views.py

@@ -1,3 +1,4 @@
+import datetime
 import json
 import urllib
 
@@ -16,8 +17,13 @@ from wagtail.admin.admin_url_finder import AdminURLFinder
 from wagtail.images import get_image_model
 from wagtail.images.models import UploadedImage
 from wagtail.images.utils import generate_signature
-from wagtail.models import Collection, GroupCollectionPermission, get_root_collection_id
-from wagtail.test.testapp.models import CustomImage, CustomImageWithAuthor
+from wagtail.models import (
+    Collection,
+    GroupCollectionPermission,
+    Page,
+    get_root_collection_id,
+)
+from wagtail.test.testapp.models import CustomImage, CustomImageWithAuthor, EventPage
 from wagtail.test.utils import WagtailTestUtils
 
 from .utils import Image, get_test_image_file
@@ -1126,6 +1132,99 @@ class TestImageDeleteView(TestCase, WagtailTestUtils):
         self.assertEqual(response.status_code, 302)
 
 
+class TestUsage(TestCase, WagtailTestUtils):
+    def setUp(self):
+        self.login()
+
+        # Create an image to edit
+        self.image = Image.objects.create(
+            title="Test image",
+            file=get_test_image_file(),
+        )
+
+    def test_usage_page(self):
+        home_page = Page.objects.get(id=2)
+        home_page.add_child(
+            instance=EventPage(
+                title="Christmas",
+                slug="christmas",
+                feed_image=self.image,
+                date_from=datetime.date.today(),
+                audience="private",
+                location="Test",
+                cost="Test",
+            )
+        ).save_revision().publish()
+
+        response = self.client.get(
+            reverse("wagtailimages:image_usage", args=[self.image.id])
+        )
+        self.assertContains(response, "Christmas")
+
+    def test_usage_page_no_usage(self):
+        response = self.client.get(
+            reverse("wagtailimages:image_usage", args=[self.image.id])
+        )
+        # There's no usage so there should be no table rows
+        self.assertRegex(response.content.decode("utf-8"), r"<tbody>(\s|\n)*</tbody>")
+
+    def test_usage_page_with_only_change_permission(self):
+        # Create a user with change_image permission but not add_image
+        user = self.create_user(
+            username="changeonly", email="changeonly@example.com", password="password"
+        )
+        change_permission = Permission.objects.get(
+            content_type__app_label="wagtailimages", codename="change_image"
+        )
+        admin_permission = Permission.objects.get(
+            content_type__app_label="wagtailadmin", codename="access_admin"
+        )
+        self.changers_group = Group.objects.create(name="Image changers")
+        GroupCollectionPermission.objects.create(
+            group=self.changers_group,
+            collection=Collection.get_first_root_node(),
+            permission=change_permission,
+        )
+        user.groups.add(self.changers_group)
+
+        user.user_permissions.add(admin_permission)
+        self.login(username="changeonly", password="password")
+
+        response = self.client.get(
+            reverse("wagtailimages:image_usage", args=[self.image.id])
+        )
+
+        self.assertEqual(response.status_code, 200)
+
+    def test_usage_page_without_change_permission(self):
+        # Create a user with add_image permission but not change_image
+        user = self.create_user(
+            username="addonly", email="addonly@example.com", password="password"
+        )
+        add_permission = Permission.objects.get(
+            content_type__app_label="wagtailimages", codename="add_image"
+        )
+        admin_permission = Permission.objects.get(
+            content_type__app_label="wagtailadmin", codename="access_admin"
+        )
+        self.adders_group = Group.objects.create(name="Image adders")
+        GroupCollectionPermission.objects.create(
+            group=self.adders_group,
+            collection=Collection.get_first_root_node(),
+            permission=add_permission,
+        )
+        user.groups.add(self.adders_group)
+
+        user.user_permissions.add(admin_permission)
+        self.login(username="addonly", password="password")
+
+        response = self.client.get(
+            reverse("wagtailimages:image_usage", args=[self.image.id])
+        )
+
+        self.assertEqual(response.status_code, 302)
+
+
 class TestImageChooserView(TestCase, WagtailTestUtils):
     def setUp(self):
         self.user = self.login()

+ 6 - 0
wagtail/images/views/images.py

@@ -397,9 +397,15 @@ def add(request):
     )
 
 
+@permission_checker.require("change")
 def usage(request, image_id):
     image = get_object_or_404(get_image_model(), id=image_id)
 
+    if not permission_policy.user_has_permission_for_instance(
+        request.user, "change", image
+    ):
+        raise PermissionDenied
+
     paginator = Paginator(image.get_usage(), per_page=USAGE_PAGE_SIZE)
     used_by = paginator.get_page(request.GET.get("p"))
 

+ 1 - 0
wagtail/snippets/views/snippets.py

@@ -547,6 +547,7 @@ class UsageView(generic.IndexView):
     paginate_by = 20
     page_kwarg = "p"
     is_searchable = False
+    permission_required = "change"
 
     def setup(self, request, *args, pk, **kwargs):
         super().setup(request, *args, **kwargs)