Fixed #24929 -- Allowed permission_required decorator to take any iterable
This commit is contained in:
parent
8b1f39a727
commit
39937de7e6
|
@ -4,6 +4,7 @@ from django.conf import settings
|
||||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.shortcuts import resolve_url
|
from django.shortcuts import resolve_url
|
||||||
|
from django.utils import six
|
||||||
from django.utils.decorators import available_attrs
|
from django.utils.decorators import available_attrs
|
||||||
from django.utils.six.moves.urllib.parse import urlparse
|
from django.utils.six.moves.urllib.parse import urlparse
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ def permission_required(perm, login_url=None, raise_exception=False):
|
||||||
is raised.
|
is raised.
|
||||||
"""
|
"""
|
||||||
def check_perms(user):
|
def check_perms(user):
|
||||||
if not isinstance(perm, (list, tuple)):
|
if isinstance(perm, six.string_types):
|
||||||
perms = (perm, )
|
perms = (perm, )
|
||||||
else:
|
else:
|
||||||
perms = perm
|
perms = perm
|
||||||
|
|
|
@ -114,6 +114,10 @@ Minor features
|
||||||
a deprecation warning in older versions and is no longer supported in
|
a deprecation warning in older versions and is no longer supported in
|
||||||
Django 1.9).
|
Django 1.9).
|
||||||
|
|
||||||
|
* The permission argument of
|
||||||
|
:func:`~django.contrib.auth.decorators.permission_required()` accepts all
|
||||||
|
kinds of iterables, not only list and tuples.
|
||||||
|
|
||||||
:mod:`django.contrib.gis`
|
:mod:`django.contrib.gis`
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -580,7 +580,7 @@ The permission_required decorator
|
||||||
(i.e. ``polls.can_vote`` for a permission on a model in the ``polls``
|
(i.e. ``polls.can_vote`` for a permission on a model in the ``polls``
|
||||||
application).
|
application).
|
||||||
|
|
||||||
The decorator may also take a list of permissions.
|
The decorator may also take an iterable of permissions.
|
||||||
|
|
||||||
Note that :func:`~django.contrib.auth.decorators.permission_required()`
|
Note that :func:`~django.contrib.auth.decorators.permission_required()`
|
||||||
also takes an optional ``login_url`` parameter. Example::
|
also takes an optional ``login_url`` parameter. Example::
|
||||||
|
@ -599,6 +599,11 @@ The permission_required decorator
|
||||||
(HTTP Forbidden) view<http_forbidden_view>` instead of redirecting to the
|
(HTTP Forbidden) view<http_forbidden_view>` instead of redirecting to the
|
||||||
login page.
|
login page.
|
||||||
|
|
||||||
|
.. versionchanged:: 1.9
|
||||||
|
|
||||||
|
In older versions, the ``permission`` parameter only worked with
|
||||||
|
strings, lists, and tuples instead of strings and any iterable.
|
||||||
|
|
||||||
.. _applying-permissions-to-generic-views:
|
.. _applying-permissions-to-generic-views:
|
||||||
|
|
||||||
Applying permissions to generic views
|
Applying permissions to generic views
|
||||||
|
|
|
@ -76,6 +76,16 @@ class PermissionsRequiredDecoratorTest(TestCase):
|
||||||
resp = a_view(request)
|
resp = a_view(request)
|
||||||
self.assertEqual(resp.status_code, 200)
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
|
def test_many_permissions_in_set_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):
|
def test_single_permission_pass(self):
|
||||||
|
|
||||||
@permission_required('auth.add_customuser')
|
@permission_required('auth.add_customuser')
|
||||||
|
|
Loading…
Reference in New Issue