Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #18991 -- Allowed permission lookup by "if in"

When looking permissions from PermWrapper it is now possible to use
{% if "someapp.someperm" in perms %} instead of
{% if perms.someapp.someperm %}.
  • Loading branch information...
commit d5a4f209c3889a76a23a19f3212ab2d7b5c62e1c 1 parent c253282
@akaariai akaariai authored
View
11 django/contrib/auth/context_processors.py
@@ -32,6 +32,17 @@ def __iter__(self):
# I am large, I contain multitudes.
raise TypeError("PermWrapper is not iterable.")
+ def __contains__(self, perm_name):
+ """
+ Lookup by "someapp" or "someapp.someperm" in perms.
+ """
+ if '.' not in perm_name:
+ # The name refers to module.
+ return bool(self[perm_name])
+ module_name, perm_name = perm_name.split('.', 1)
+ return self[module_name][perm_name]
+
+
def auth(request):
"""
Returns context variables required by apps that use Django's authentication
View
41 django/contrib/auth/tests/context_processors.py
@@ -3,6 +3,8 @@
from django.conf import global_settings
from django.contrib.auth import authenticate
from django.contrib.auth.tests.utils import skipIfCustomUser
+from django.contrib.auth.models import User, Permission
+from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.context_processors import PermWrapper, PermLookupDict
from django.db.models import Q
from django.test import TestCase
@@ -10,13 +12,13 @@
class MockUser(object):
- def has_module_perm(self, perm):
- if perm == 'mockapp.someapp':
+ def has_module_perms(self, perm):
+ if perm == 'mockapp':
return True
return False
def has_perm(self, perm):
- if perm == 'someperm':
+ if perm == 'mockapp.someperm':
return True
return False
@@ -40,13 +42,19 @@ def __eq__(self, other):
def test_permwrapper_in(self):
"""
- Test that 'something' in PermWrapper doesn't end up in endless loop.
+ Test that 'something' in PermWrapper works as expected.
"""
perms = PermWrapper(MockUser())
- with self.assertRaises(TypeError):
- self.EQLimiterObject() in perms
+ # Works for modules and full permissions.
+ self.assertTrue('mockapp' in perms)
+ self.assertFalse('nonexisting' in perms)
+ self.assertTrue('mockapp.someperm' in perms)
+ self.assertFalse('mockapp.nonexisting' in perms)
def test_permlookupdict_in(self):
+ """
+ No endless loops if accessed with 'in' - refs #18979.
+ """
pldict = PermLookupDict(MockUser(), 'mockapp')
with self.assertRaises(TypeError):
self.EQLimiterObject() in pldict
@@ -92,9 +100,28 @@ def test_session_is_accessed(self):
self.assertContains(response, "Session accessed")
def test_perms_attrs(self):
- self.client.login(username='super', password='secret')
+ u = User.objects.create_user(username='normal', password='secret')
+ u.user_permissions.add(
+ Permission.objects.get(
+ content_type=ContentType.objects.get_for_model(Permission),
+ codename='add_permission'))
+ self.client.login(username='normal', password='secret')
response = self.client.get('/auth_processor_perms/')
self.assertContains(response, "Has auth permissions")
+ self.assertContains(response, "Has auth.add_permission permissions")
+ self.assertNotContains(response, "nonexisting")
+
+ def test_perm_in_perms_attrs(self):
+ u = User.objects.create_user(username='normal', password='secret')
+ u.user_permissions.add(
+ Permission.objects.get(
+ content_type=ContentType.objects.get_for_model(Permission),
+ codename='add_permission'))
+ self.client.login(username='normal', password='secret')
+ response = self.client.get('/auth_processor_perm_in_perms/')
+ self.assertContains(response, "Has auth permissions")
+ self.assertContains(response, "Has auth.add_permission permissions")
+ self.assertNotContains(response, "nonexisting")
def test_message_attrs(self):
self.client.login(username='super', password='secret')
View
4 django/contrib/auth/tests/templates/context_processors/auth_attrs_perm_in_perms.html
@@ -0,0 +1,4 @@
+{% if 'auth' in perms %}Has auth permissions{% endif %}
+{% if 'auth.add_permission' in perms %}Has auth.add_permission permissions{% endif %}
+{% if 'nonexisting' in perms %}nonexisting perm found{% endif %}
+{% if 'auth.nonexisting' in perms %}auth.nonexisting perm found{% endif %}
View
3  django/contrib/auth/tests/templates/context_processors/auth_attrs_perms.html
@@ -1 +1,4 @@
{% if perms.auth %}Has auth permissions{% endif %}
+{% if perms.auth.add_permission %}Has auth.add_permission permissions{% endif %}
+{% if perms.nonexisting %}nonexisting perm found{% endif %}
+{% if perms.auth.nonexisting in perms %}auth.nonexisting perm found{% endif %}
View
5 django/contrib/auth/tests/urls.py
@@ -37,6 +37,10 @@ def auth_processor_perms(request):
return render_to_response('context_processors/auth_attrs_perms.html',
RequestContext(request, {}, processors=[context_processors.auth]))
+def auth_processor_perm_in_perms(request):
+ return render_to_response('context_processors/auth_attrs_perm_in_perms.html',
+ RequestContext(request, {}, processors=[context_processors.auth]))
+
def auth_processor_messages(request):
info(request, "Message 1")
return render_to_response('context_processors/auth_attrs_messages.html',
@@ -58,6 +62,7 @@ def userpage(request):
(r'^auth_processor_attr_access/$', auth_processor_attr_access),
(r'^auth_processor_user/$', auth_processor_user),
(r'^auth_processor_perms/$', auth_processor_perms),
+ (r'^auth_processor_perm_in_perms/$', auth_processor_perm_in_perms),
(r'^auth_processor_messages/$', auth_processor_messages),
url(r'^userpage/(.+)/$', userpage, name="userpage"),
)
View
4 docs/releases/1.5.txt
@@ -180,6 +180,10 @@ Django 1.5 also includes several smaller improvements worth noting:
and inversion, expanding the types of expressions that can be passed to the
database.
+* When using :class:`~django.template.RequestContext`, it is now possible to
+ look up permissions by using ``{% if 'someapp.someperm' in perms %}``
+ in templates.
+
Backwards incompatible changes in 1.5
=====================================
View
14 docs/topics/auth.txt
@@ -1710,6 +1710,20 @@ Thus, you can check permissions in template ``{% if %}`` statements:
<p>You don't have permission to do anything in the foo app.</p>
{% endif %}
+.. versionadded:: 1.5
+ Permission lookup by "if in".
+
+It is possible to also look permissions up by ``{% if in %}`` statements.
+For example:
+
+.. code-block:: html+django
+
+ {% if 'foo' in perms %}
+ {% if 'foo.can_vote' in perms %}
+ <p>In lookup works, too.</p>
+ {% endif %}
+ {% endif %}
+
Groups
======
Please sign in to comment.
Something went wrong with that request. Please try again.