Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #20828 -- Allowed @permission_required to take a list of permis…

…sions

Thanks Giggaflop for the suggestion.
  • Loading branch information...
commit 00d23a13ebaf6057d1428e798bfb6cf47bb5ef7c 1 parent 5737c57
ersran9 authored timgraham committed
View
6 django/contrib/auth/decorators.py
@@ -64,8 +64,12 @@ def permission_required(perm, login_url=None, raise_exception=False):
is raised.
"""
def check_perms(user):
+ if not isinstance(perm, (list, tuple)):
+ perms = (perm, )
+ else:
+ perms = perm
# First check if the user has the permission (even anon users)
- if user.has_perm(perm):
+ if user.has_perms(perms):
return True
# In case the 403 handler should be called raise the exception
if raise_exception:
View
58 django/contrib/auth/tests/test_decorators.py
@@ -1,7 +1,12 @@
from django.conf import settings
-from django.contrib.auth.decorators import login_required
+from django.contrib.auth import models
+from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.tests.test_views import AuthViewsTestCase
from django.contrib.auth.tests.utils import skipIfCustomUser
+from django.core.exceptions import PermissionDenied
+from django.http import HttpResponse
+from django.test import TestCase
+from django.test.client import RequestFactory
@skipIfCustomUser
@@ -49,3 +54,54 @@ def testLoginRequiredNextUrl(self):
"""
self.testLoginRequired(view_url='/login_required_login_url/',
login_url='/somewhere/')
+
+
+class PermissionsRequiredDecoratorTest(TestCase):
+ """
+ Tests for the permission_required decorator
+ """
+ def setUp(self):
+ self.user = models.User.objects.create(username='joe', password='qwerty')
+ self.factory = RequestFactory()
+ # Add permissions auth.add_customuser and auth.change_customuser
+ perms = models.Permission.objects.filter(codename__in=('add_customuser', 'change_customuser'))
+ self.user.user_permissions.add(*perms)
+
+ def test_many_permissions_pass(self):
+
+ @permission_required(['auth.add_customuser', 'auth.change_customuser'])
+ def a_view(request):
+ return HttpResponse()
+ request = self.factory.get('/rand')
+ request.user = self.user
+ resp = a_view(request)
+ self.assertEqual(resp.status_code, 200)
+
+ def test_single_permission_pass(self):
+
+ @permission_required('auth.add_customuser')
+ def a_view(request):
+ return HttpResponse()
+ request = self.factory.get('/rand')
+ request.user = self.user
+ resp = a_view(request)
+ self.assertEqual(resp.status_code, 200)
+
+ def test_permissioned_denied_redirect(self):
+
+ @permission_required(['auth.add_customuser', 'auth.change_customuser', 'non-existant-permission'])
+ def a_view(request):
+ return HttpResponse()
+ request = self.factory.get('/rand')
+ request.user = self.user
+ resp = a_view(request)
+ self.assertEqual(resp.status_code, 302)
+
+ def test_permissioned_denied_exception_raised(self):
+
+ @permission_required(['auth.add_customuser', 'auth.change_customuser', 'non-existant-permission'], raise_exception=True)
+ def a_view(request):
+ return HttpResponse()
+ request = self.factory.get('/rand')
+ request.user = self.user
+ self.assertRaises(PermissionDenied, a_view, request)
View
3  docs/releases/1.7.txt
@@ -135,6 +135,9 @@ Minor features
``Meta`` option allows you to customize (or disable) creation of the default
add, change, and delete permissions.
+* The :func:`~django.contrib.auth.decorators.permission_required` decorator can
+ take a list of permissions as well as a single permission.
+
Backwards incompatible changes in 1.7
=====================================
View
5 docs/topics/auth/default.txt
@@ -528,6 +528,11 @@ The permission_required decorator
(HTTP Forbidden) view<http_forbidden_view>` instead of redirecting to the
login page.
+ .. versionchanged:: 1.7
+
+ The :func:`~django.contrib.auth.decorators.permission_required`
+ decorator can take a list of permissions as well as a single permission.
+
Applying permissions to generic views
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Please sign in to comment.
Something went wrong with that request. Please try again.