Restrict view_draft to can_publish / can_edit permissions (#3474)

This commit is contained in:
Kees Hink 2017-03-22 12:59:07 +01:00 committed by Matt Westcott
parent 20e8aabdf9
commit 6961f33078
6 changed files with 73 additions and 9 deletions

View file

@ -24,6 +24,7 @@ Changelog
* Tag input fields now accept spaces in tags by default, and can be overridden with the `TAG_SPACES_ALLOWED` setting (Kees Hink, Alex Gleason)
* Page chooser widgets now display the required page type where relevant (Christine Ho)
* Site root pages are now indicated with a globe icon in the explorer listing (Nick Smith, Huub Bouma)
* Draft page view is now restricted to users with edit / publish permission over the page (Kees Hink)
* Fix: Marked 'Date from' / 'Date to' strings in wagtailforms for translation (Vorlif)
* Fix: "File" field label on image edit form is now translated (Stein Strindhaug)
* Fix: Unreliable preview is now reliable by always opening in a new window (Kjartan Sverrisson)

View file

@ -20,13 +20,13 @@ Clicking on a user's name will open their profile details. From here you can the
Click the 'Roles' tab to edit the level of access your users have. By default there are three roles:
+--------------+--------------+-----------------+-----------------+
| Role | Create drafts| Publish content | Access Settings |
+==============+==============+=================+=================+
| Editor | Yes | No | No |
+--------------+--------------+-----------------+-----------------+
| Moderator | Yes | Yes | No |
+--------------+--------------+-----------------+-----------------+
| Administrator| Yes | Yes | Yes |
+--------------+--------------+-----------------+-----------------+
+--------------+--------------------+-----------------+-----------------+
| Role | Create/view drafts | Publish content | Access Settings |
+==============+====================+=================+=================+
| Editor | Yes | No | No |
+--------------+--------------------+-----------------+-----------------+
| Moderator | Yes | Yes | No |
+--------------+--------------------+-----------------+-----------------+
| Administrator| Yes | Yes | Yes |
+--------------+--------------------+-----------------+-----------------+

View file

@ -31,6 +31,7 @@ Other features
* Tag input fields now accept spaces in tags by default, and can be overridden with the ``TAG_SPACES_ALLOWED`` setting (Kees Hink, Alex Gleason)
* Page chooser widgets now display the required page type where relevant (Christine Ho)
* Site root pages are now indicated with a globe icon in the explorer listing (Nick Smith, Huub Bouma)
* Draft page view is now restricted to users with edit / publish permission over the page (Kees Hink)
Bug fixes

View file

@ -31,6 +31,7 @@ The full set of available permission types is as follows:
* **Bulk delete** - allows a user to delete pages that have descendants, in a single operation. Without this permission, a user has to delete the descendant pages individually before deleting the parent. This is a safeguard against accidental deletion. This permission must be used in conjunction with 'add' / 'edit' permission, as it does not provide any deletion rights of its own; it only provides a 'shortcut' for the permissions the user has already. For example, a user with just 'add' and 'bulk delete' permissions will only be able to bulk-delete if all the affected pages are owned by that user, and are unpublished.
* **Lock** - grants the ability to lock or unlock this page (and any pages underneath it) for editing, preventing users from making any further edits to it.
Drafts can be viewed only if the user has either Edit or Publish permission.
Image / document permissions
----------------------------

View file

@ -4080,3 +4080,61 @@ class TestValidationErrorMessages(TestCase, WagtailTestUtils):
self.assertContains(response, """<p class="error-message"><span>This field is required.</span></p>""", count=1, html=True)
# Error on title shown in the header message
self.assertContains(response, "<li>Title: This field is required.</li>", count=1)
class TestDraftAccess(TestCase, WagtailTestUtils):
"""Tests for the draft view access restrictions."""
def setUp(self):
# Find root page
self.root_page = Page.objects.get(id=2)
# Add child page
self.child_page = SimplePage(
title="Hello world!",
slug="hello-world",
content="hello",
)
self.root_page.add_child(instance=self.child_page)
# create user with admin access (but not draft_view access)
user = get_user_model().objects.create_user(username='bob', email='bob@email.com', password='password')
user.user_permissions.add(
Permission.objects.get(content_type__app_label='wagtailadmin', codename='access_admin')
)
def test_draft_access_admin(self):
"""Test that admin can view draft."""
# Login as admin
self.user = self.login()
# Try getting page draft
response = self.client.get(reverse('wagtailadmin_pages:view_draft', args=(self.child_page.id, )))
# User can view
self.assertEqual(response.status_code, 200)
def test_draft_access_unauthorized(self):
"""Test that user without edit/publish permission can't view draft."""
self.assertTrue(self.client.login(username='bob', password='password'))
# Try getting page draft
response = self.client.get(reverse('wagtailadmin_pages:view_draft', args=(self.child_page.id, )))
# User gets Unauthorized response
self.assertEqual(response.status_code, 403)
def test_draft_access_authorized(self):
"""Test that user with edit permission can view draft."""
# give user the permission to edit page
user = get_user_model().objects.get(username='bob')
user.groups.add(Group.objects.get(name='Moderators'))
user.save()
self.assertTrue(self.client.login(username='bob', password='password'))
# Get add subpage page
response = self.client.get(reverse('wagtailadmin_pages:view_draft', args=(self.child_page.id, )))
# User can view
self.assertEqual(response.status_code, 200)

View file

@ -543,6 +543,9 @@ def delete(request, page_id):
def view_draft(request, page_id):
page = get_object_or_404(Page, id=page_id).get_latest_revision_as_page()
perms = page.permissions_for_user(request.user)
if not (perms.can_publish() or perms.can_edit()):
raise PermissionDenied
return page.serve_preview(page.dummy_request(request), page.default_preview_mode)