From a2239e9f4a378240e12a7f7d55d7de0a85ad11a2 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Tue, 22 Sep 2015 11:37:23 +0100 Subject: [PATCH] Prevent root node from being edited/deleted --- .../tests/test_collections_views.py | 30 ++++++++++++++++--- wagtail/wagtailadmin/views/collections.py | 12 ++++++++ wagtail/wagtailadmin/views/generic.py | 14 ++++++--- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/wagtail/wagtailadmin/tests/test_collections_views.py b/wagtail/wagtailadmin/tests/test_collections_views.py index ae4fba868e..22522dbc88 100644 --- a/wagtail/wagtailadmin/tests/test_collections_views.py +++ b/wagtail/wagtailadmin/tests/test_collections_views.py @@ -18,6 +18,20 @@ class TestCollectionsIndexView(TestCase, WagtailTestUtils): self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/collections/index.html') + # Initially there should be no collections listed + # (Root should not be shown) + self.assertContains(response, "No collections have been created.") + + root_collection = Collection.get_first_root_node() + self.collection = root_collection.add_child(name="Holiday snaps") + + # Now the listing should contain our collection + response = self.get() + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, 'wagtailadmin/collections/index.html') + self.assertNotContains(response, "No collections have been created.") + self.assertContains(response, "Holiday snaps") + class TestAddCollection(TestCase, WagtailTestUtils): def setUp(self): @@ -54,8 +68,8 @@ class TestAddCollection(TestCase, WagtailTestUtils): class TestEditCollection(TestCase, WagtailTestUtils): def setUp(self): self.login() - root_collection = Collection.get_first_root_node() - self.collection = root_collection.add_child(name="Holiday snaps") + self.root_collection = Collection.get_first_root_node() + self.collection = self.root_collection.add_child(name="Holiday snaps") def get(self, params={}, collection_id=None): return self.client.get( @@ -73,6 +87,10 @@ class TestEditCollection(TestCase, WagtailTestUtils): response = self.get() self.assertEqual(response.status_code, 200) + def test_cannot_edit_root_collection(self): + response = self.get(collection_id=self.root_collection.id) + self.assertEqual(response.status_code, 404) + def test_get_nonexistent_collection(self): response = self.get(collection_id=100000) self.assertEqual(response.status_code, 404) @@ -95,8 +113,8 @@ class TestEditCollection(TestCase, WagtailTestUtils): class TestDeleteCollection(TestCase, WagtailTestUtils): def setUp(self): self.login() - root_collection = Collection.get_first_root_node() - self.collection = root_collection.add_child(name="Holiday snaps") + self.root_collection = Collection.get_first_root_node() + self.collection = self.root_collection.add_child(name="Holiday snaps") def get(self, params={}, collection_id=None): return self.client.get( @@ -114,6 +132,10 @@ class TestDeleteCollection(TestCase, WagtailTestUtils): response = self.get() self.assertEqual(response.status_code, 200) + def test_cannot_delete_root_collection(self): + response = self.get(collection_id=self.root_collection.id) + self.assertEqual(response.status_code, 404) + def test_get_nonexistent_collection(self): response = self.get(collection_id=100000) self.assertEqual(response.status_code, 404) diff --git a/wagtail/wagtailadmin/views/collections.py b/wagtail/wagtailadmin/views/collections.py index b0d96b75b5..66a91ef147 100644 --- a/wagtail/wagtailadmin/views/collections.py +++ b/wagtail/wagtailadmin/views/collections.py @@ -16,6 +16,10 @@ class Index(IndexView): add_item_label = __("Add a collection") header_icon = 'folder-open-1' + def get_queryset(self): + # Only return children of the root node, so that the root is not editable + return Collection.get_first_root_node().get_children() + class Create(CreateView): permission_policy = collection_permission_policy @@ -48,6 +52,10 @@ class Edit(EditView): context_object_name = 'collection' header_icon = 'folder-open-1' + def get_queryset(self): + # Only return children of the root node, so that the root is not editable + return Collection.get_first_root_node().get_children() + class Delete(DeleteView): permission_policy = collection_permission_policy @@ -58,3 +66,7 @@ class Delete(DeleteView): page_title = __("Delete collection") confirmation_message = __("Are you sure you want to delete this collection?") header_icon = 'folder-open-1' + + def get_queryset(self): + # Only return children of the root node, so that the root is not editable + return Collection.get_first_root_node().get_children() diff --git a/wagtail/wagtailadmin/views/generic.py b/wagtail/wagtailadmin/views/generic.py index 509b8a0693..848026943b 100644 --- a/wagtail/wagtailadmin/views/generic.py +++ b/wagtail/wagtailadmin/views/generic.py @@ -126,6 +126,9 @@ class EditView(PermissionCheckedMixin, View): template_name = 'wagtailadmin/generic/edit.html' permission_required = 'change' + def get_queryset(self): + return self.model.objects.all() + def get_page_subtitle(self): return str(self.instance) @@ -143,12 +146,12 @@ class EditView(PermissionCheckedMixin, View): return self.form.save() def get(self, request, instance_id): - self.instance = get_object_or_404(self.model, id=instance_id) + self.instance = get_object_or_404(self.get_queryset(), id=instance_id) self.form = self.form_class(instance=self.instance) return self.render_to_response() def post(self, request, instance_id): - self.instance = get_object_or_404(self.model, id=instance_id) + self.instance = get_object_or_404(self.get_queryset(), id=instance_id) self.form = self.form_class(request.POST, instance=self.instance) if self.form.is_valid(): self.save_instance() @@ -186,6 +189,9 @@ class DeleteView(PermissionCheckedMixin, View): context_object_name = None permission_required = 'delete' + def get_queryset(self): + return self.model.objects.all() + def get_page_subtitle(self): return str(self.instance) @@ -193,7 +199,7 @@ class DeleteView(PermissionCheckedMixin, View): return reverse(self.delete_url_name, args=(self.instance.id,)) def get(self, request, instance_id): - self.instance = get_object_or_404(self.model, id=instance_id) + self.instance = get_object_or_404(self.get_queryset(), id=instance_id) context = { 'view': self, @@ -205,7 +211,7 @@ class DeleteView(PermissionCheckedMixin, View): return render(request, self.template_name, context) def post(self, request, instance_id): - self.instance = get_object_or_404(self.model, id=instance_id) + self.instance = get_object_or_404(self.get_queryset(), id=instance_id) self.instance.delete() messages.success(request, self.success_message.format(self.instance)) return redirect(self.index_url_name)