190 lines
7.2 KiB
Python
190 lines
7.2 KiB
Python
from django.http import HttpResponseForbidden
|
|
from django.shortcuts import get_object_or_404, redirect
|
|
from django.utils.translation import gettext_lazy
|
|
|
|
from wagtail import hooks
|
|
from wagtail.admin import messages
|
|
from wagtail.admin.forms.collections import CollectionForm
|
|
from wagtail.admin.ui.tables import TitleColumn
|
|
from wagtail.admin.views.generic import CreateView, DeleteView, EditView, IndexView
|
|
from wagtail.models import Collection
|
|
from wagtail.permissions import collection_permission_policy
|
|
|
|
|
|
class Index(IndexView):
|
|
permission_policy = collection_permission_policy
|
|
model = Collection
|
|
context_object_name = "collections"
|
|
results_template_name = "wagtailadmin/collections/index_results.html"
|
|
add_url_name = "wagtailadmin_collections:add"
|
|
index_url_name = "wagtailadmin_collections:index"
|
|
page_title = gettext_lazy("Collections")
|
|
add_item_label = gettext_lazy("Add a collection")
|
|
header_icon = "folder-open-1"
|
|
columns = [
|
|
TitleColumn(
|
|
"name",
|
|
label=gettext_lazy("Name"),
|
|
url_name="wagtailadmin_collections:edit",
|
|
id_accessor="0",
|
|
accessor="1",
|
|
)
|
|
]
|
|
|
|
def get_queryset(self):
|
|
return self.permission_policy.instances_user_has_any_permission_for(
|
|
self.request.user, ["add", "change", "delete"]
|
|
).exclude(depth=1)
|
|
|
|
def get_table(self, object_list):
|
|
return super().get_table(object_list.get_indented_choices())
|
|
|
|
|
|
class Create(CreateView):
|
|
permission_policy = collection_permission_policy
|
|
model = Collection
|
|
form_class = CollectionForm
|
|
page_title = gettext_lazy("Add collection")
|
|
success_message = gettext_lazy("Collection '%(object)s' created.")
|
|
add_url_name = "wagtailadmin_collections:add"
|
|
edit_url_name = "wagtailadmin_collections:edit"
|
|
index_url_name = "wagtailadmin_collections:index"
|
|
header_icon = "folder-open-1"
|
|
|
|
def get_form(self, form_class=None):
|
|
form = super().get_form(form_class)
|
|
# Now filter collections offered in parent field by current user's add permissions
|
|
collections = self.permission_policy.instances_user_has_permission_for(
|
|
self.request.user, "add"
|
|
)
|
|
form.fields["parent"].queryset = collections
|
|
return form
|
|
|
|
def save_instance(self):
|
|
instance = self.form.save(commit=False)
|
|
parent = self.form.cleaned_data["parent"]
|
|
parent.add_child(instance=instance)
|
|
return instance
|
|
|
|
|
|
class Edit(EditView):
|
|
permission_policy = collection_permission_policy
|
|
model = Collection
|
|
form_class = CollectionForm
|
|
template_name = "wagtailadmin/collections/edit.html"
|
|
success_message = gettext_lazy("Collection '%(object)s' updated.")
|
|
error_message = gettext_lazy("The collection could not be saved due to errors.")
|
|
edit_url_name = "wagtailadmin_collections:edit"
|
|
index_url_name = "wagtailadmin_collections:index"
|
|
delete_url_name = "wagtailadmin_collections:delete"
|
|
context_object_name = "collection"
|
|
header_icon = "folder-open-1"
|
|
|
|
def _user_may_move_collection(self, user, instance):
|
|
"""
|
|
Is this instance used for assigning GroupCollectionPermissions to the user?
|
|
If so, this user is not allowed do move the collection to a new part of the tree
|
|
"""
|
|
if user.is_active and user.is_superuser:
|
|
return True
|
|
else:
|
|
permissions = (
|
|
self.permission_policy._get_user_permission_objects_for_actions(
|
|
user, {"add", "change", "delete"}
|
|
)
|
|
)
|
|
return not {
|
|
permission
|
|
for permission in permissions
|
|
if permission.collection_id == instance.pk
|
|
}
|
|
|
|
def get_queryset(self):
|
|
return self.permission_policy.instances_user_has_permission_for(
|
|
self.request.user, "change"
|
|
).exclude(depth=1)
|
|
|
|
def get_form(self, form_class=None):
|
|
form = super().get_form(form_class)
|
|
user = self.request.user
|
|
# if user does not have add permission anywhere, they can't move a collection
|
|
if not self.permission_policy.user_has_permission(user, "add"):
|
|
form.fields.pop("parent")
|
|
# If this instance is a collection used to assign permissions for this user,
|
|
# do not let the user move this collection.
|
|
elif not self._user_may_move_collection(user, form.instance):
|
|
form.fields.pop("parent")
|
|
else:
|
|
# Filter collections offered in parent field by current user's add permissions
|
|
collections = self.permission_policy.instances_user_has_permission_for(
|
|
user, "add"
|
|
)
|
|
form.fields["parent"].queryset = collections
|
|
# Disable unavailable options in CollectionChoiceField select widget
|
|
form.fields["parent"].disabled_queryset = form.instance.get_descendants(
|
|
inclusive=True
|
|
)
|
|
|
|
form.initial["parent"] = form.instance.get_parent().pk
|
|
return form
|
|
|
|
def save_instance(self):
|
|
instance = self.form.save()
|
|
if "parent" in self.form.changed_data:
|
|
instance.move(self.form.cleaned_data["parent"], "sorted-child")
|
|
return instance
|
|
|
|
|
|
class Delete(DeleteView):
|
|
permission_policy = collection_permission_policy
|
|
model = Collection
|
|
success_message = gettext_lazy("Collection '%(object)s' deleted.")
|
|
index_url_name = "wagtailadmin_collections:index"
|
|
edit_url_name = "wagtailadmin_collections:edit"
|
|
delete_url_name = "wagtailadmin_collections:delete"
|
|
page_title = gettext_lazy("Delete collection")
|
|
confirmation_message = gettext_lazy(
|
|
"Are you sure you want to delete this collection?"
|
|
)
|
|
header_icon = "folder-open-1"
|
|
|
|
def get_queryset(self):
|
|
return self.permission_policy.instances_user_has_permission_for(
|
|
self.request.user, "delete"
|
|
).exclude(depth=1)
|
|
|
|
def get_collection_contents(self):
|
|
collection_contents = [
|
|
hook(self.object)
|
|
for hook in hooks.get_hooks("describe_collection_contents")
|
|
]
|
|
|
|
# filter out any hook responses that report that the collection is empty
|
|
# (by returning None, or a dict with 'count': 0)
|
|
def is_nonempty(item_type):
|
|
return item_type and item_type["count"] > 0
|
|
|
|
return list(filter(is_nonempty, collection_contents))
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
collection_contents = self.get_collection_contents()
|
|
|
|
if collection_contents:
|
|
# collection is non-empty; render the 'not allowed to delete' response
|
|
self.template_name = "wagtailadmin/collections/delete_not_empty.html"
|
|
context["collection_contents"] = collection_contents
|
|
|
|
return context
|
|
|
|
def post(self, request, pk):
|
|
self.object = get_object_or_404(self.get_queryset(), id=pk)
|
|
collection_contents = self.get_collection_contents()
|
|
|
|
if collection_contents:
|
|
# collection is non-empty; refuse to delete it
|
|
return HttpResponseForbidden()
|
|
|
|
messages.success(request, self.get_success_message())
|
|
self.object.delete()
|
|
return redirect(self.index_url_name)
|