Merge branch 'author-specific-locking' of https://github.com/jacobtoppm/wagtail into kaedroho-author-specific-locking

This commit is contained in:
Matt Westcott 2020-01-08 15:05:59 +00:00
commit 3f27014a86
9 changed files with 100 additions and 7 deletions

View file

@ -224,6 +224,22 @@ Hooks for building new areas of the admin interface (alongside pages, images, do
As ``construct_main_menu``, but modifies the 'Settings' sub-menu rather than the top-level menu.
.. _register_reports_menu_item:
``register_reports_menu_item``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As ``register_admin_menu_item``, but registers menu items into the 'Reports' sub-menu rather than the top-level menu.
.. _construct_reports_menu:
``construct_reports_menu``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
As ``construct_main_menu``, but modifies the 'Reports' sub-menu rather than the top-level menu.
.. _register_admin_search_area:
``register_admin_search_area``

View file

@ -115,7 +115,7 @@ Database fields
The user who has currently locked the page. Only this user can edit the page.
If this is ``None`` when ``locked`` is ``False``, nobody can edit the page.
If this is ``None`` when ``locked`` is ``True``, nobody can edit the page.
.. attribute:: locked_at

View file

@ -3,7 +3,9 @@
<div class="panel nice-padding">{# TODO try moving these classes onto the section tag #}
<section>
<h2>{% trans "Your locked pages" %}</h2>
<a href="{% url 'wagtailadmin_reports:locked_pages' %}" class="button button-small button-secondary">{% trans "See all locked pages" %}</a>
{% if can_remove_locks %}
<a href="{% url 'wagtailadmin_reports:locked_pages' %}" class="button button-small button-secondary">{% trans "See all locked pages" %}</a>
{% endif %}
<table class="listing listing-page">
<col />
<col width="15%"/>

View file

@ -2,13 +2,32 @@
{% load i18n wagtailadmin_tags %}
{% block page_navigation %}
<td>
{% page_permissions page as perms %}
<p>
Locked
{% if page.locked_by %}by <b>{% if page.locked_by_id == request.user.pk %}you{% else %}{{ page.locked_by }}{% endif %}</b>{% endif %}
{% if page.locked_at %}at <b>{{ page.locked_at|date:"d M Y H:i" }}</b>{% endif %}
{% if page.locked_at %}
{% with page.locked_at|date:"d M Y H:i" as locking_date %}
{% if page.locked_by %}
{% if page.locked_by_id == request.user.pk %}
{% blocktrans %}
Locked by <b>you</b> at <b>{{ locking_date }}</b>
{% endblocktrans %}
{% else %}
{% blocktrans with locked_by=page.locked_by %}
Locked by <b>{{ locked_by }}</b> at <b>{{ locking_date }}</b>
{% endblocktrans %}
{% endif %}
{% else %}
{% blocktrans %}
Locked at <b>{{ locking_date }}</b>
{% endblocktrans %}
{% endif %}
{% endwith %}
{% else %}
{% trans 'Locked' %}
{% endif %}
</p>
{% if perms.can_unlock %}
<form action="{% url 'wagtailadmin_pages:unlock' page.id %}" method="post">

View file

@ -0,0 +1,35 @@
from django.test import TestCase
from django.urls import reverse
from django.utils import timezone
from wagtail.core.models import Page
from wagtail.tests.utils import WagtailTestUtils
class TestLockedPagesView(TestCase, WagtailTestUtils):
def setUp(self):
self.user = self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailadmin_reports:locked_pages'), params)
def test_simple(self):
response = self.get()
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/reports/locked_pages.html')
# Initially there should be no locked pages
self.assertContains(response, "No locked pages found.")
self.page = Page.objects.first()
self.page.locked = True
self.page.locked_by = self.user
self.page.locked_at = timezone.now()
self.page.save()
# Now the listing should contain our locked page
response = self.get()
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/reports/locked_pages.html')
self.assertNotContains(response, "No locked pages found.")
self.assertContains(response, self.page.title)

View file

@ -59,7 +59,8 @@ class LockedPagesPanel:
'locked_pages': Page.objects.filter(
locked=True,
locked_by=self.request.user,
)
),
'can_remove_locks': UserPagePermissionsProxy(self.request.user).can_remove_locks()
}, request=self.request)

View file

@ -2,6 +2,7 @@ from django.utils.translation import ugettext_lazy as _
from django.views.generic.base import TemplateResponseMixin
from django.views.generic.list import BaseListView
from wagtail.admin.auth import permission_denied
from wagtail.core.models import UserPagePermissionsProxy
@ -28,3 +29,8 @@ class LockedPagesView(ReportView):
pages = UserPagePermissionsProxy(self.request.user).editable_pages().filter(locked=True)
self.queryset = pages
return super().get_queryset()
def dispatch(self, request, *args, **kwargs):
if not UserPagePermissionsProxy(request.user).can_remove_locks():
return permission_denied(request)
return super().dispatch(request, *args, **kwargs)

View file

@ -619,9 +619,14 @@ class ReportsMenuItem(SubmenuMenuItem):
template = 'wagtailadmin/shared/menu_submenu_item.html'
class LockedPagesMenuItem(MenuItem):
def is_shown(self, request):
return UserPagePermissionsProxy(request.user).can_remove_locks()
@hooks.register('register_reports_menu_item')
def register_locked_pages_menu_item():
return MenuItem(_('Locked Pages'), reverse('wagtailadmin_reports:locked_pages'), classnames='icon icon-locked', order=700)
return LockedPagesMenuItem(_('Locked Pages'), reverse('wagtailadmin_reports:locked_pages'), classnames='icon icon-locked', order=700)
@hooks.register('register_admin_menu_item')

View file

@ -1838,6 +1838,15 @@ class UserPagePermissionsProxy:
"""Return True if the user has permission to publish any pages"""
return self.publishable_pages().exists()
def can_remove_locks(self):
"""Returns True if the user has permission to unlock pages they have not locked"""
if self.user.is_superuser:
return True
if not self.user.is_active:
return False
else:
return self.permissions.filter(permission_type='unlock').exists()
class PagePermissionTester:
def __init__(self, user_perms, page):