Repository: django-cms/django-cms

Issue:
Incorrect admin URL can cause a Python error
Try to reach a non-existent admin page, say http://localhost:8000/en/admin/cms/page/23/edit-plugin/408/ - you'll get a 404, as expected.

Try (say) http://localhost:8000/en/admin/cms/page/23/edit-plugin/408/edit-plugin/407/, and you'll get:

```
ValueError at /en/admin/cms/page/23/edit-plugin/408/edit-plugin/407/
invalid literal for int() with base 10: '408/edit-plugin/407'
```

I think that this should also return a 404.



Discussion:

Resolving patch:
diff --git a/cms/admin/placeholderadmin.py b/cms/admin/placeholderadmin.py
--- a/cms/admin/placeholderadmin.py
+++ b/cms/admin/placeholderadmin.py
@@ -15,7 +15,7 @@
 from cms.utils.compat.dj import force_unicode
 from cms.utils.plugins import requires_reload, has_reached_plugin_limit
 from django.contrib.admin import ModelAdmin
-from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
+from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound
 from django.shortcuts import render_to_response, get_object_or_404
 from django.template import RequestContext
 from django.template.defaultfilters import force_escape, escapejs
@@ -355,7 +355,10 @@ def copy_plugins(self, request):
 
     @xframe_options_sameorigin
     def edit_plugin(self, request, plugin_id):
-        plugin_id = int(plugin_id)
+        try:
+            plugin_id = int(plugin_id)
+        except ValueError:
+            return HttpResponseNotFound(force_unicode(_("Plugin not found")))
         cms_plugin = get_object_or_404(CMSPlugin.objects.select_related('placeholder'), pk=plugin_id)
 
         instance, plugin_admin = cms_plugin.get_plugin_instance(self.admin_site)


Test patch:
diff --git a/cms/tests/admin.py b/cms/tests/admin.py
--- a/cms/tests/admin.py
+++ b/cms/tests/admin.py
@@ -12,7 +12,8 @@
 from django.contrib.auth.models import Permission, AnonymousUser
 from django.contrib.sites.models import Site
 from django.core.urlresolvers import reverse
-from django.http import (Http404, HttpResponseBadRequest, HttpResponseForbidden, HttpResponse, QueryDict)
+from django.http import (Http404, HttpResponseBadRequest, HttpResponseForbidden, HttpResponse,
+                         QueryDict, HttpResponseNotFound)
 from django.utils.datastructures import MultiValueDictKeyError
 from django.utils.encoding import smart_str
 from django.utils import timezone
@@ -1033,6 +1034,22 @@ def test_plugin_edit_requires_permissions(self):
         response = self.client.post(url, dict())
         self.assertEqual(response.status_code, HttpResponse.status_code)
 
+    def test_plugin_edit_wrong_url(self):
+        """User tries to edit a plugin using a random url. 404 response returned"""
+        plugin = self._create_plugin()
+        _, normal_guy = self._get_guys()
+
+        if get_user_model().USERNAME_FIELD == 'email':
+            self.client.login(username='test@test.com', password='test@test.com')
+        else:
+            self.client.login(username='test', password='test')
+
+        self._give_permission(normal_guy, Text, 'change')
+        url = '%s/edit-plugin/%s/' % (admin_reverse('cms_page_edit_plugin', args=[plugin.id]), plugin.id)
+        response = self.client.post(url, dict())
+        self.assertEqual(response.status_code, HttpResponseNotFound.status_code)
+        self.assertTrue("Plugin not found" in force_unicode(response.content))
+
     def test_plugin_remove_requires_permissions(self):
         """User tries to remove a plugin but has no permissions. He can remove the plugin after he got the permissions"""
         plugin = self._create_plugin()