diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/pages/_lock_indicator.html b/wagtail/wagtailadmin/templates/wagtailadmin/pages/_lock_indicator.html
new file mode 100644
index 000000000..78084cc9b
--- /dev/null
+++ b/wagtail/wagtailadmin/templates/wagtailadmin/pages/_lock_indicator.html
@@ -0,0 +1,29 @@
+{% load i18n wagtailadmin_tags %}
+
+{% if not page_perms %}
+ {% page_permissions page as page_perms %}
+{% endif %}
+
+
+ {% if page.locked %}
+ {% trans "Locked" %}
+
+ {% if page_perms.can_lock %}
+
+ {% endif %}
+ {% else %}
+ {% trans "Unlocked" %}
+
+ {% if page_perms.can_lock %}
+
+ {% endif %}
+ {% endif %}
+
diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/pages/edit.html b/wagtail/wagtailadmin/templates/wagtailadmin/pages/edit.html
index d7ccf4c5e..f5874a703 100644
--- a/wagtail/wagtailadmin/templates/wagtailadmin/pages/edit.html
+++ b/wagtail/wagtailadmin/templates/wagtailadmin/pages/edit.html
@@ -23,6 +23,7 @@
{% endif %}
{% include "wagtailadmin/pages/_privacy_indicator.html" with page=page page_perms=page_perms only %}
+ {% include "wagtailadmin/pages/_lock_indicator.html" %}
diff --git a/wagtail/wagtailadmin/urls.py b/wagtail/wagtailadmin/urls.py
index 72833130e..9f60b110a 100644
--- a/wagtail/wagtailadmin/urls.py
+++ b/wagtail/wagtailadmin/urls.py
@@ -73,6 +73,9 @@ urlpatterns += [
url(r'^pages/(\d+)/privacy/$', page_privacy.set_privacy, name='wagtailadmin_pages_set_privacy'),
+ url(r'^pages/(\d+)/lock/$', pages.lock, name='wagtailadmin_pages_lock'),
+ url(r'^pages/(\d+)/unlock/$', pages.unlock, name='wagtailadmin_pages_unlock'),
+
url(r'^choose-page/$', chooser.browse, name='wagtailadmin_choose_page'),
url(r'^choose-page/(\d+)/$', chooser.browse, name='wagtailadmin_choose_page_child'),
url(r'^choose-external-link/$', chooser.external_link, name='wagtailadmin_choose_page_external_link'),
diff --git a/wagtail/wagtailadmin/views/pages.py b/wagtail/wagtailadmin/views/pages.py
index a7212cc3e..bb737315e 100644
--- a/wagtail/wagtailadmin/views/pages.py
+++ b/wagtail/wagtailadmin/views/pages.py
@@ -9,7 +9,8 @@ from django.contrib.auth.decorators import permission_required
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.utils import timezone
from django.utils.translation import ugettext as _
-from django.views.decorators.http import require_GET
+from django.utils.http import is_safe_url
+from django.views.decorators.http import require_GET, require_POST
from django.views.decorators.vary import vary_on_headers
from wagtail.wagtailadmin.edit_handlers import TabbedInterface, ObjectList
@@ -806,3 +807,49 @@ def preview_for_moderation(request, revision_id):
# pass in the real user request rather than page.dummy_request(), so that request.user
# and request.revision_id will be picked up by the wagtail user bar
return page.serve_preview(request, page.default_preview_mode)
+
+
+@permission_required('wagtailadmin.access_admin')
+@require_POST
+def lock(request, page_id):
+ # Get the page
+ page = Page.objects.get(id=page_id)
+
+ # Check permissions
+ if not page.permissions_for_user(request.user).can_lock():
+ raise PermissionDenied
+
+ # Lock the page
+ if not page.locked:
+ page.locked = True
+ page.save()
+
+ # Redirect
+ redirect_to = request.POST.get('next', None)
+ if redirect_to and is_safe_url(url=redirect_to, host=request.get_host()):
+ return redirect(redirect_to)
+ else:
+ return redirect('wagtail_explore', args=(page.get_parent().id, ))
+
+
+@permission_required('wagtailadmin.access_admin')
+@require_POST
+def unlock(request, page_id):
+ # Get the page
+ page = Page.objects.get(id=page_id)
+
+ # Check permissions
+ if not page.permissions_for_user(request.user).can_lock():
+ raise PermissionDenied
+
+ # Unlock the page
+ if page.locked:
+ page.locked = False
+ page.save()
+
+ # Redirect
+ redirect_to = request.POST.get('next', None)
+ if redirect_to and is_safe_url(url=redirect_to, host=request.get_host()):
+ return redirect(redirect_to)
+ else:
+ return redirect('wagtail_explore', args=(page.get_parent().id, ))
diff --git a/wagtail/wagtailcore/models.py b/wagtail/wagtailcore/models.py
index f48f034e9..de839a664 100644
--- a/wagtail/wagtailcore/models.py
+++ b/wagtail/wagtailcore/models.py
@@ -883,6 +883,7 @@ class PageRevision(models.Model):
obj.live = self.page.live
obj.has_unpublished_changes = self.page.has_unpublished_changes
obj.owner = self.page.owner
+ obj.locked = self.page.locked
return obj
@@ -1078,6 +1079,9 @@ class PagePermissionTester(object):
def can_set_view_restrictions(self):
return self.can_publish()
+ def can_lock(self):
+ return self.user.is_superuser
+
def can_publish_subpage(self):
"""
Niggly special case for creating and publishing a page in one go.