mirror of
https://github.com/Hopiu/wagtail.git
synced 2026-04-11 10:30:58 +00:00
Add admin interface for setting collection view restrictions
This commit is contained in:
parent
58d7112e5f
commit
83c8db1ab5
12 changed files with 206 additions and 8 deletions
|
|
@ -21,7 +21,9 @@ from taggit.managers import TaggableManager
|
|||
|
||||
from wagtail.wagtailadmin import widgets
|
||||
from wagtail.wagtailcore.models import (
|
||||
Collection, GroupCollectionPermission, Page, PageViewRestriction
|
||||
BaseViewRestriction,
|
||||
Collection, CollectionViewRestriction, GroupCollectionPermission,
|
||||
Page, PageViewRestriction
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -192,29 +194,43 @@ class CopyForm(forms.Form):
|
|||
return cleaned_data
|
||||
|
||||
|
||||
class PageViewRestrictionForm(forms.ModelForm):
|
||||
class BaseViewRestrictionForm(forms.ModelForm):
|
||||
restriction_type = forms.ChoiceField(
|
||||
label=ugettext_lazy("Visibility"), choices=PageViewRestriction.RESTRICTION_CHOICES,
|
||||
label=ugettext_lazy("Visibility"), choices=BaseViewRestriction.RESTRICTION_CHOICES,
|
||||
widget=forms.RadioSelect)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PageViewRestrictionForm, self).__init__(*args, **kwargs)
|
||||
super(BaseViewRestrictionForm, self).__init__(*args, **kwargs)
|
||||
|
||||
self.fields['groups'].widget = forms.CheckboxSelectMultiple()
|
||||
self.fields['groups'].queryset = Group.objects.all()
|
||||
|
||||
def clean_password(self):
|
||||
password = self.cleaned_data.get('password')
|
||||
if self.cleaned_data.get('restriction_type') == PageViewRestriction.PASSWORD and not password:
|
||||
if self.cleaned_data.get('restriction_type') == BaseViewRestriction.PASSWORD and not password:
|
||||
raise forms.ValidationError(_("This field is required."), code='invalid')
|
||||
return password
|
||||
|
||||
def clean_groups(self):
|
||||
groups = self.cleaned_data.get('groups')
|
||||
if self.cleaned_data.get('restriction_type') == PageViewRestriction.GROUPS and not groups:
|
||||
if self.cleaned_data.get('restriction_type') == BaseViewRestriction.GROUPS and not groups:
|
||||
raise forms.ValidationError(_("Please select at least one group."), code='invalid')
|
||||
return groups
|
||||
|
||||
class Meta:
|
||||
model = BaseViewRestriction
|
||||
fields = ('restriction_type', 'password', 'groups')
|
||||
|
||||
|
||||
class CollectionViewRestrictionForm(BaseViewRestrictionForm):
|
||||
|
||||
class Meta:
|
||||
model = CollectionViewRestriction
|
||||
fields = ('restriction_type', 'password', 'groups')
|
||||
|
||||
|
||||
class PageViewRestrictionForm(BaseViewRestrictionForm):
|
||||
|
||||
class Meta:
|
||||
model = PageViewRestriction
|
||||
fields = ('restriction_type', 'password', 'groups')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
{% load i18n %}
|
||||
{% trans "Collection privacy" as title_str %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=title_str icon="no-view" %}
|
||||
|
||||
<div class="nice-padding">
|
||||
<p>{% trans "This collection has been made private by a parent collection." %}</p>
|
||||
<p>{% trans "You can edit the privacy settings on:" %} <a href="{% url 'wagtailadmin_collections:edit' collection_with_restriction.id %}">{{ collection_with_restriction.name }}</a>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
{% load i18n %}
|
||||
{% trans "Collection privacy" as title_str %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=title_str icon="no-view" %}
|
||||
|
||||
<div class="nice-padding">
|
||||
<p class="help-block help-info">{% trans "Privacy settings determine who is able to view documents in this collection." %}</p>
|
||||
<form action="{% url 'wagtailadmin_collections:set_privacy' collection.id %}" method="POST" novalidate>
|
||||
{% csrf_token %}
|
||||
<ul class="fields">
|
||||
{% include "wagtailadmin/shared/field_as_li.html" with field=form.restriction_type %}
|
||||
{% include "wagtailadmin/shared/field_as_li.html" with field=form.password li_classes="password-field" %}
|
||||
</ul>
|
||||
<ul class="fields" id="groups-fields">
|
||||
{% include "wagtailadmin/shared/field_as_li.html" with field=form.groups %}
|
||||
</ul>
|
||||
<input type="submit" value="{% trans "Save" %}" class="button" />
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
function(modal) {
|
||||
$('form', modal.body).submit(function() {
|
||||
modal.postForm(this.action, $(this).serialize());
|
||||
return false;
|
||||
});
|
||||
|
||||
var restrictionTypePasswordField = $("input[name='restriction_type'][value='password']", modal.body);
|
||||
var restrictionTypeGroupsField = $("input[name='restriction_type'][value='groups']", modal.body);
|
||||
var passwordField = $(".password-field", modal.body);
|
||||
var groupsFields = $('#groups-fields', modal.body);
|
||||
|
||||
function refreshFormFields() {
|
||||
if (restrictionTypePasswordField.is(':checked')) {
|
||||
passwordField.show();
|
||||
groupsFields.hide();
|
||||
} else if (restrictionTypeGroupsField.is(':checked')){
|
||||
passwordField.hide();
|
||||
groupsFields.show();
|
||||
} else {
|
||||
passwordField.hide();
|
||||
groupsFields.hide();
|
||||
}
|
||||
}
|
||||
refreshFormFields();
|
||||
|
||||
$("input[name='restriction_type']", modal.body).change(refreshFormFields);
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
function(modal) {
|
||||
modal.respond('setPermission', {% if is_public %}true{% else %}false{% endif %});
|
||||
modal.close();
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{% load i18n wagtailadmin_tags %}
|
||||
|
||||
{% test_collection_is_public collection as is_public %}
|
||||
|
||||
{% if not collection.is_root %}
|
||||
<div class="privacy-indicator {% if is_public %}public{% else %}private{% endif %}">
|
||||
{% trans "Privacy" %}
|
||||
<a href="{% url 'wagtailadmin_collections:set_privacy' collection.id %}" class="status-tag primary action-set-privacy">
|
||||
{# labels are shown/hidden in CSS according to the 'private' / 'public' class on view-permission-indicator #}
|
||||
<span class="label-public icon icon-view">{% trans 'Public' %}</span>
|
||||
<span class="label-private icon icon-no-view">{% trans 'Private' %}</span>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{% extends "wagtailadmin/generic/edit.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block before_form %}
|
||||
{% include "wagtailadmin/collections/_privacy_switch.html" with collection=object collection_perms=collection_perms only %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
{{ block.super }}
|
||||
<script src="{% static 'wagtailadmin/js/modal-workflow.js' %}"></script>
|
||||
<script src="{% static 'wagtailadmin/js/privacy-switch.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
{% include "wagtailadmin/shared/header.html" with title=view.page_title subtitle=view.get_page_subtitle icon=view.header_icon %}
|
||||
|
||||
<div class="nice-padding">
|
||||
{% block before_form %}{% endblock %}
|
||||
<form action="{{ view.get_edit_url }}" method="POST" novalidate{% if form.is_multipart %} enctype="multipart/form-data"{% endif %}>
|
||||
{% csrf_token %}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,11 @@ from wagtail.wagtailadmin.menu import admin_menu
|
|||
from wagtail.wagtailadmin.navigation import get_explorable_root_page
|
||||
from wagtail.wagtailadmin.search import admin_search_areas
|
||||
from wagtail.wagtailcore import hooks
|
||||
from wagtail.wagtailcore.models import Page, PageViewRestriction, UserPagePermissionsProxy
|
||||
from wagtail.wagtailcore.models import (
|
||||
CollectionViewRestriction,
|
||||
Page, PageViewRestriction,
|
||||
UserPagePermissionsProxy
|
||||
)
|
||||
from wagtail.wagtailcore.utils import cautious_slugify as _cautious_slugify
|
||||
from wagtail.wagtailcore.utils import camelcase_to_underscore, escape_script
|
||||
|
||||
|
|
@ -133,6 +137,25 @@ def page_permissions(context, page):
|
|||
return context['user_page_permissions'].for_page(page)
|
||||
|
||||
|
||||
@assignment_tag(takes_context=True)
|
||||
def test_collection_is_public(context, collection):
|
||||
"""
|
||||
Usage: {% test_collection_is_public collection as is_public %}
|
||||
Sets 'is_public' to True iff there are no collection view restrictions in place
|
||||
on this collection.
|
||||
Caches the list of collection view restrictions in the context, to avoid repeated
|
||||
DB queries on repeated calls.
|
||||
"""
|
||||
if 'all_collection_view_restrictions' not in context:
|
||||
context['all_collection_view_restrictions'] = CollectionViewRestriction.objects.select_related('collection').values_list(
|
||||
'collection__name', flat=True
|
||||
)
|
||||
|
||||
is_private = collection.name in context['all_collection_view_restrictions']
|
||||
|
||||
return not is_private
|
||||
|
||||
|
||||
@assignment_tag(takes_context=True)
|
||||
def test_page_is_public(context, page):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@ from __future__ import absolute_import, unicode_literals
|
|||
|
||||
from django.conf.urls import url
|
||||
|
||||
from wagtail.wagtailadmin.views import collections
|
||||
from wagtail.wagtailadmin.views import collection_privacy, collections
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', collections.Index.as_view(), name='index'),
|
||||
url(r'^add/$', collections.Create.as_view(), name='add'),
|
||||
url(r'^(\d+)/$', collections.Edit.as_view(), name='edit'),
|
||||
url(r'^(\d+)/delete/$', collections.Delete.as_view(), name='delete'),
|
||||
url(r'^(\d+)/privacy/$', collection_privacy.set_privacy, name='set_privacy'),
|
||||
]
|
||||
|
|
|
|||
72
wagtail/wagtailadmin/views/collection_privacy.py
Normal file
72
wagtail/wagtailadmin/views/collection_privacy.py
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from wagtail.wagtailadmin.forms import CollectionViewRestrictionForm
|
||||
from wagtail.wagtailadmin.modal_workflow import render_modal_workflow
|
||||
from wagtail.wagtailcore.models import Collection, CollectionViewRestriction
|
||||
from wagtail.wagtailcore.permissions import collection_permission_policy
|
||||
|
||||
|
||||
def set_privacy(request, collection_id):
|
||||
collection = get_object_or_404(Collection, id=collection_id)
|
||||
if not collection_permission_policy.user_has_permission(request.user, 'change'):
|
||||
raise PermissionDenied
|
||||
|
||||
# fetch restriction records in depth order so that ancestors appear first
|
||||
restrictions = collection.get_view_restrictions().order_by('collection__depth')
|
||||
if restrictions:
|
||||
restriction = restrictions[0]
|
||||
restriction_exists_on_ancestor = (restriction.collection != collection)
|
||||
else:
|
||||
restriction = None
|
||||
restriction_exists_on_ancestor = False
|
||||
|
||||
if request.method == 'POST':
|
||||
form = CollectionViewRestrictionForm(request.POST, instance=restriction)
|
||||
if form.is_valid() and not restriction_exists_on_ancestor:
|
||||
if form.cleaned_data['restriction_type'] == CollectionViewRestriction.NONE:
|
||||
# remove any existing restriction
|
||||
if restriction:
|
||||
restriction.delete()
|
||||
else:
|
||||
restriction = form.save(commit=False)
|
||||
restriction.collection = collection
|
||||
form.save()
|
||||
|
||||
return render_modal_workflow(
|
||||
request, None, 'wagtailadmin/collection_privacy/set_privacy_done.js', {
|
||||
'is_public': (form.cleaned_data['restriction_type'] == 'none')
|
||||
}
|
||||
)
|
||||
|
||||
else: # request is a GET
|
||||
if not restriction_exists_on_ancestor:
|
||||
if restriction:
|
||||
form = CollectionViewRestrictionForm(instance=restriction)
|
||||
else:
|
||||
# no current view restrictions on this collection
|
||||
form = CollectionViewRestrictionForm(initial={
|
||||
'restriction_type': 'none'
|
||||
})
|
||||
|
||||
if restriction_exists_on_ancestor:
|
||||
# display a message indicating that there is a restriction at ancestor level -
|
||||
# do not provide the form for setting up new restrictions
|
||||
return render_modal_workflow(
|
||||
request, 'wagtailadmin/collection_privacy/ancestor_privacy.html', None,
|
||||
{
|
||||
'collection_with_restriction': restriction.collection,
|
||||
}
|
||||
)
|
||||
else:
|
||||
# no restriction set at ancestor level - can set restrictions here
|
||||
return render_modal_workflow(
|
||||
request,
|
||||
'wagtailadmin/collection_privacy/set_privacy.html',
|
||||
'wagtailadmin/collection_privacy/set_privacy.js', {
|
||||
'collection': collection,
|
||||
'form': form,
|
||||
}
|
||||
)
|
||||
|
|
@ -49,6 +49,7 @@ class Edit(EditView):
|
|||
permission_policy = collection_permission_policy
|
||||
model = Collection
|
||||
form_class = CollectionForm
|
||||
template_name = 'wagtailadmin/collections/edit.html'
|
||||
success_message = ugettext_lazy("Collection '{0}' updated.")
|
||||
error_message = ugettext_lazy("The collection could not be saved due to errors.")
|
||||
delete_item_label = ugettext_lazy("Delete collection")
|
||||
|
|
|
|||
Loading…
Reference in a new issue