Add hook and authenticate_with_password view for document view restrictions

This commit is contained in:
Matt Westcott 2017-06-08 00:13:07 +01:00
parent 48d6b2d93e
commit 18864102ee
5 changed files with 76 additions and 2 deletions

View file

@ -6,7 +6,9 @@
</head>
<body>
<h1>{% trans "Password required" %}</h1>
<p>{% trans "You need a password to access this page." %}</p>
{% block password_required_message %}
<p>{% trans "You need a password to access this page." %}</p>
{% endblock %}
<form action="{{ action_url }}" method="POST">
{% csrf_token %}
{{ form.as_p }}

View file

@ -0,0 +1,6 @@
{% extends "wagtailcore/password_required.html" %}
{% load i18n %}
{% block password_required_message %}
<p>{% trans "You need a password to access this document." %}</p>
{% endblock %}

View file

@ -6,4 +6,6 @@ from wagtail.wagtaildocs.views import serve
urlpatterns = [
url(r'^(\d+)/(.*)$', serve.serve, name='wagtaildocs_serve'),
url(r'^authenticate_with_password/(\d+)/$', serve.authenticate_with_password,
name='wagtaildocs_authenticate_with_password'),
]

View file

@ -3,13 +3,17 @@ from __future__ import absolute_import, unicode_literals
from wsgiref.util import FileWrapper
from django.conf import settings
from django.core.urlresolvers import reverse
from django.http import BadHeaderError, Http404, HttpResponse, StreamingHttpResponse
from django.shortcuts import get_object_or_404
from django.shortcuts import get_object_or_404, redirect
from django.template.response import TemplateResponse
from unidecode import unidecode
from wagtail.utils import sendfile_streaming_backend
from wagtail.utils.sendfile import sendfile
from wagtail.wagtailcore import hooks
from wagtail.wagtailcore.forms import PasswordViewRestrictionForm
from wagtail.wagtailcore.models import CollectionViewRestriction
from wagtail.wagtaildocs.models import document_served, get_document_model
@ -74,3 +78,30 @@ def serve(request, document_id, document_filename):
response['Content-Length'] = doc.file.size
return response
def authenticate_with_password(request, restriction_id):
"""
Handle a submission of PasswordViewRestrictionForm to grant view access over a
subtree that is protected by a PageViewRestriction
"""
restriction = get_object_or_404(CollectionViewRestriction, id=restriction_id)
if request.method == 'POST':
form = PasswordViewRestrictionForm(request.POST, instance=restriction)
if form.is_valid():
restriction.mark_as_passed(request)
return redirect(form.cleaned_data['return_url'])
else:
form = PasswordViewRestrictionForm(instance=restriction)
action_url = reverse('wagtaildocs_authenticate_with_password', args=[restriction.id])
password_required_template = getattr(settings, 'DOCUMENT_PASSWORD_REQUIRED_TEMPLATE', 'wagtaildocs/password_required.html')
context = {
'form': form,
'action_url': action_url
}
return TemplateResponse(request, password_required_template, context)

View file

@ -1,8 +1,10 @@
from __future__ import absolute_import, unicode_literals
from django.conf import settings
from django.conf.urls import include, url
from django.contrib.staticfiles.templatetags.staticfiles import static
from django.core import urlresolvers
from django.template.response import TemplateResponse
from django.utils.html import format_html, format_html_join
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext
@ -11,6 +13,8 @@ from wagtail.wagtailadmin.menu import MenuItem
from wagtail.wagtailadmin.search import SearchArea
from wagtail.wagtailadmin.site_summary import SummaryItem
from wagtail.wagtailcore import hooks
from wagtail.wagtailcore.models import BaseViewRestriction
from wagtail.wagtailcore.wagtail_hooks import require_wagtail_login
from wagtail.wagtaildocs import admin_urls
from wagtail.wagtaildocs.api.admin.endpoints import DocumentsAdminAPIEndpoint
from wagtail.wagtaildocs.forms import GroupDocumentPermissionFormSet
@ -130,3 +134,32 @@ def describe_collection_docs(collection):
) % {'count': docs_count},
'url': url,
}
@hooks.register('before_serve_document')
def check_view_restrictions(document, request):
"""
Check whether there are any view restrictions on this document which are
not fulfilled by the given request object. If there are, return an
HttpResponse that will notify the user of that restriction (and possibly
include a password / login form that will allow them to proceed). If
there are no such restrictions, return None
"""
for restriction in document.collection.get_view_restrictions():
if not restriction.accept_request(request):
if restriction.restriction_type == BaseViewRestriction.PASSWORD:
from wagtail.wagtailcore.forms import PasswordViewRestrictionForm
form = PasswordViewRestrictionForm(instance=restriction,
initial={'return_url': request.get_full_path()})
action_url = urlresolvers.reverse('wagtaildocs_authenticate_with_password', args=[restriction.id])
password_required_template = getattr(settings, 'DOCUMENT_PASSWORD_REQUIRED_TEMPLATE', 'wagtaildocs/password_required.html')
context = {
'form': form,
'action_url': action_url
}
return TemplateResponse(request, password_required_template, context)
elif restriction.restriction_type in [BaseViewRestriction.LOGIN, BaseViewRestriction.GROUPS]:
return require_wagtail_login(next=request.get_full_path())