summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorersran9 <sreenidimn@gmail.com>2013-08-07 21:33:31 +0530
committerTim Graham <timograham@gmail.com>2013-08-10 10:10:18 -0400
commit00d23a13ebaf6057d1428e798bfb6cf47bb5ef7c (patch)
tree518db88f66ff84905cdccf899adbeb4e6adf0fc3
parent5737c57d95cc8c17b1aa2da4809f70ad4c212716 (diff)
Fixed #20828 -- Allowed @permission_required to take a list of permissions
Thanks Giggaflop for the suggestion.
-rw-r--r--django/contrib/auth/decorators.py6
-rw-r--r--django/contrib/auth/tests/test_decorators.py58
-rw-r--r--docs/releases/1.7.txt3
-rw-r--r--docs/topics/auth/default.txt5
4 files changed, 70 insertions, 2 deletions
diff --git a/django/contrib/auth/decorators.py b/django/contrib/auth/decorators.py
index 11518193e7..24e31144b1 100644
--- a/django/contrib/auth/decorators.py
+++ b/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:
diff --git a/django/contrib/auth/tests/test_decorators.py b/django/contrib/auth/tests/test_decorators.py
index 6d6d335354..22ad933644 100644
--- a/django/contrib/auth/tests/test_decorators.py
+++ b/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 @@ class LoginRequiredTestCase(AuthViewsTestCase):
"""
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)
diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt
index 6c28d6e1d0..ec37b382d4 100644
--- a/docs/releases/1.7.txt
+++ b/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
=====================================
diff --git a/docs/topics/auth/default.txt b/docs/topics/auth/default.txt
index 7dff9cdca7..78bf820e89 100644
--- a/docs/topics/auth/default.txt
+++ b/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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~