Skip to content

Commit aa450b3

Browse files
authored
fix: History URL button broken link on the Snippets change form (#84)
1 parent 98ddf0c commit aa450b3

File tree

2 files changed

+81
-21
lines changed

2 files changed

+81
-21
lines changed

djangocms_snippet/admin.py

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from django.db import models
55
from django.forms import Textarea
66

7+
from cms.utils.permissions import get_model_permission_codename
8+
79
from .cms_config import SnippetCMSAppConfig
810
from .forms import SnippetForm
911
from .models import Snippet
@@ -47,32 +49,24 @@ class Meta:
4749
def get_urls(self):
4850
info = self.model._meta.app_label, self.model._meta.model_name
4951
return [
50-
url(
51-
r"^$",
52-
self.admin_site.admin_view(self.changelist_view),
53-
name="{}_{}_changelist".format(*info),
54-
),
55-
url(
56-
r"^(?P<snippet_id>\d+)/$",
57-
self.admin_site.admin_view(self.changelist_view),
58-
name="{}_{}_list".format(*info),
59-
),
60-
url(
61-
r"^add/$",
62-
self.admin_site.admin_view(self.add_view),
63-
name="{}_{}_add".format(*info),
64-
),
65-
url(
66-
r"^(?P<object_id>\d+)/change/$",
67-
self.admin_site.admin_view(self.change_view),
68-
name="{}_{}_change".format(*info),
69-
),
7052
url(
7153
r"^(?P<snippet_id>\d+)/preview/$",
7254
self.admin_site.admin_view(SnippetPreviewView.as_view()),
7355
name="{}_{}_preview".format(*info),
7456
),
75-
]
57+
] + super().get_urls()
58+
59+
def has_delete_permission(self, request, obj=None):
60+
"""
61+
When versioning is enabled, delete option is not available.
62+
If versioning is disabled, it may be possible to delete, as long as a user also has add permissions, and they
63+
are not in use.
64+
"""
65+
if obj and not djangocms_versioning_enabled:
66+
return request.user.has_perm(
67+
get_model_permission_codename(self.model, 'add'),
68+
)
69+
return False
7670

7771

7872
admin.site.register(Snippet, SnippetAdmin)

tests/test_admin.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@
1616

1717
class SnippetAdminTestCase(CMSTestCase):
1818
def setUp(self):
19+
self.superuser = self.get_superuser()
1920
self.snippet = Snippet.objects.create(
2021
name="Test Snippet",
2122
slug="test-snippet",
2223
html="<h1>This is a test</h1>",
2324
snippet_grouper=SnippetGrouper.objects.create(),
2425
)
26+
self.snippet_version = Version.objects.create(content=self.snippet, created_by=self.superuser)
2527
self.snippet_admin = snippet_admin.SnippetAdmin(Snippet, admin)
2628
self.snippet_admin_request = RequestFactory().get("/admin/djangocms_snippet")
29+
self.edit_url = reverse("admin:djangocms_snippet_snippet_change", args=(self.snippet.id,),)
30+
self.delete_url = reverse("admin:djangocms_snippet_snippet_delete", args=(self.snippet.id,),)
2731

2832
@override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=False)
2933
def test_admin_list_display_without_versioning(self):
@@ -67,6 +71,68 @@ def test_admin_uses_form(self):
6771
"""
6872
self.assertEqual(self.snippet_admin.form, SnippetForm)
6973

74+
@override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True)
75+
def test_admin_delete_button_disabled_versioning_enabled(self):
76+
"""
77+
If versioning is enabled, the delete button should not be rendered on the change form
78+
"""
79+
admin.site.unregister(Snippet)
80+
reload(cms_config)
81+
reload(snippet_admin)
82+
83+
with self.login_user_context(self.superuser):
84+
response = self.client.get(self.edit_url)
85+
86+
self.assertNotContains(
87+
response, '<a href="/en/admin/djangocms_snippet/snippet/1/delete/" class="deletelink">Delete</a>'
88+
)
89+
90+
@override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=False)
91+
def test_admin_delete_button_available_versioning_disabled(self):
92+
"""
93+
If versioning is disabled, the delete button should be rendered on the change form
94+
"""
95+
admin.site.unregister(Snippet)
96+
reload(cms_config)
97+
reload(snippet_admin)
98+
99+
with self.login_user_context(self.superuser):
100+
response = self.client.get(self.edit_url)
101+
102+
self.assertContains(
103+
response, '<a href="/en/admin/djangocms_snippet/snippet/1/delete/" class="deletelink">Delete</a>'
104+
)
105+
106+
@override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True)
107+
def test_admin_delete_endpoint_inaccessible_versioning_enabled(self):
108+
"""
109+
If versioning is enabled, the delete endpoint should not be accessible.
110+
"""
111+
admin.site.unregister(Snippet)
112+
reload(cms_config)
113+
reload(snippet_admin)
114+
115+
with self.login_user_context(self.superuser):
116+
response = self.client.post(self.delete_url)
117+
118+
# The delete endpoint should return a 403 forbidden if we try to access it with versioning enabled
119+
self.assertEqual(response.status_code, 403)
120+
121+
@override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=False)
122+
def test_admin_delete_endpoint_accessible_versioning_disabled(self):
123+
"""
124+
If versioning is disabled, the delete endpoint should be accessible.
125+
"""
126+
admin.site.unregister(Snippet)
127+
reload(cms_config)
128+
reload(snippet_admin)
129+
130+
with self.login_user_context(self.superuser):
131+
response = self.client.post(self.delete_url)
132+
133+
# The delete endpoint should return a 200 success if we try to access it with versioning disabled
134+
self.assertEqual(response.status_code, 200)
135+
70136

71137
class SnippetAdminFormTestCase(CMSTestCase):
72138
def setUp(self):

0 commit comments

Comments
 (0)