diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index ba5c9f2f..fc7b6e0b 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -4,6 +4,8 @@ from django.db import models from django.forms import Textarea +from cms.utils.permissions import get_model_permission_codename + from .cms_config import SnippetCMSAppConfig from .forms import SnippetForm from .models import Snippet @@ -47,32 +49,24 @@ class Meta: def get_urls(self): info = self.model._meta.app_label, self.model._meta.model_name return [ - url( - r"^$", - self.admin_site.admin_view(self.changelist_view), - name="{}_{}_changelist".format(*info), - ), - url( - r"^(?P\d+)/$", - self.admin_site.admin_view(self.changelist_view), - name="{}_{}_list".format(*info), - ), - url( - r"^add/$", - self.admin_site.admin_view(self.add_view), - name="{}_{}_add".format(*info), - ), - url( - r"^(?P\d+)/change/$", - self.admin_site.admin_view(self.change_view), - name="{}_{}_change".format(*info), - ), url( r"^(?P\d+)/preview/$", self.admin_site.admin_view(SnippetPreviewView.as_view()), name="{}_{}_preview".format(*info), ), - ] + ] + super().get_urls() + + def has_delete_permission(self, request, obj=None): + """ + When versioning is enabled, delete option is not available. + If versioning is disabled, it may be possible to delete, as long as a user also has add permissions, and they + are not in use. + """ + if obj and not djangocms_versioning_enabled: + return request.user.has_perm( + get_model_permission_codename(self.model, 'add'), + ) + return False admin.site.register(Snippet, SnippetAdmin) diff --git a/tests/test_admin.py b/tests/test_admin.py index 54d37120..f29b29c7 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -16,14 +16,18 @@ class SnippetAdminTestCase(CMSTestCase): def setUp(self): + self.superuser = self.get_superuser() self.snippet = Snippet.objects.create( name="Test Snippet", slug="test-snippet", html="

This is a test

", snippet_grouper=SnippetGrouper.objects.create(), ) + self.snippet_version = Version.objects.create(content=self.snippet, created_by=self.superuser) self.snippet_admin = snippet_admin.SnippetAdmin(Snippet, admin) self.snippet_admin_request = RequestFactory().get("/admin/djangocms_snippet") + self.edit_url = reverse("admin:djangocms_snippet_snippet_change", args=(self.snippet.id,),) + self.delete_url = reverse("admin:djangocms_snippet_snippet_delete", args=(self.snippet.id,),) @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=False) def test_admin_list_display_without_versioning(self): @@ -67,6 +71,68 @@ def test_admin_uses_form(self): """ self.assertEqual(self.snippet_admin.form, SnippetForm) + @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) + def test_admin_delete_button_disabled_versioning_enabled(self): + """ + If versioning is enabled, the delete button should not be rendered on the change form + """ + admin.site.unregister(Snippet) + reload(cms_config) + reload(snippet_admin) + + with self.login_user_context(self.superuser): + response = self.client.get(self.edit_url) + + self.assertNotContains( + response, 'Delete' + ) + + @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=False) + def test_admin_delete_button_available_versioning_disabled(self): + """ + If versioning is disabled, the delete button should be rendered on the change form + """ + admin.site.unregister(Snippet) + reload(cms_config) + reload(snippet_admin) + + with self.login_user_context(self.superuser): + response = self.client.get(self.edit_url) + + self.assertContains( + response, 'Delete' + ) + + @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) + def test_admin_delete_endpoint_inaccessible_versioning_enabled(self): + """ + If versioning is enabled, the delete endpoint should not be accessible. + """ + admin.site.unregister(Snippet) + reload(cms_config) + reload(snippet_admin) + + with self.login_user_context(self.superuser): + response = self.client.post(self.delete_url) + + # The delete endpoint should return a 403 forbidden if we try to access it with versioning enabled + self.assertEqual(response.status_code, 403) + + @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=False) + def test_admin_delete_endpoint_accessible_versioning_disabled(self): + """ + If versioning is disabled, the delete endpoint should be accessible. + """ + admin.site.unregister(Snippet) + reload(cms_config) + reload(snippet_admin) + + with self.login_user_context(self.superuser): + response = self.client.post(self.delete_url) + + # The delete endpoint should return a 200 success if we try to access it with versioning disabled + self.assertEqual(response.status_code, 200) + class SnippetAdminFormTestCase(CMSTestCase): def setUp(self):