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 %}.
This commit is contained in:
parent
c2532825db
commit
d5a4f209c3
|
@ -32,6 +32,17 @@ class PermWrapper(object):
|
||||||
# I am large, I contain multitudes.
|
# I am large, I contain multitudes.
|
||||||
raise TypeError("PermWrapper is not iterable.")
|
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):
|
def auth(request):
|
||||||
"""
|
"""
|
||||||
Returns context variables required by apps that use Django's authentication
|
Returns context variables required by apps that use Django's authentication
|
||||||
|
|
|
@ -3,6 +3,8 @@ import os
|
||||||
from django.conf import global_settings
|
from django.conf import global_settings
|
||||||
from django.contrib.auth import authenticate
|
from django.contrib.auth import authenticate
|
||||||
from django.contrib.auth.tests.utils import skipIfCustomUser
|
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.contrib.auth.context_processors import PermWrapper, PermLookupDict
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
@ -10,13 +12,13 @@ from django.test.utils import override_settings
|
||||||
|
|
||||||
|
|
||||||
class MockUser(object):
|
class MockUser(object):
|
||||||
def has_module_perm(self, perm):
|
def has_module_perms(self, perm):
|
||||||
if perm == 'mockapp.someapp':
|
if perm == 'mockapp':
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def has_perm(self, perm):
|
def has_perm(self, perm):
|
||||||
if perm == 'someperm':
|
if perm == 'mockapp.someperm':
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -40,13 +42,19 @@ class PermWrapperTests(TestCase):
|
||||||
|
|
||||||
def test_permwrapper_in(self):
|
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())
|
perms = PermWrapper(MockUser())
|
||||||
with self.assertRaises(TypeError):
|
# Works for modules and full permissions.
|
||||||
self.EQLimiterObject() in perms
|
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):
|
def test_permlookupdict_in(self):
|
||||||
|
"""
|
||||||
|
No endless loops if accessed with 'in' - refs #18979.
|
||||||
|
"""
|
||||||
pldict = PermLookupDict(MockUser(), 'mockapp')
|
pldict = PermLookupDict(MockUser(), 'mockapp')
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
self.EQLimiterObject() in pldict
|
self.EQLimiterObject() in pldict
|
||||||
|
@ -92,9 +100,28 @@ class AuthContextProcessorTests(TestCase):
|
||||||
self.assertContains(response, "Session accessed")
|
self.assertContains(response, "Session accessed")
|
||||||
|
|
||||||
def test_perms_attrs(self):
|
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/')
|
response = self.client.get('/auth_processor_perms/')
|
||||||
self.assertContains(response, "Has auth permissions")
|
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):
|
def test_message_attrs(self):
|
||||||
self.client.login(username='super', password='secret')
|
self.client.login(username='super', password='secret')
|
||||||
|
|
|
@ -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 %}
|
|
@ -1 +1,4 @@
|
||||||
{% if perms.auth %}Has auth permissions{% endif %}
|
{% 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 %}
|
||||||
|
|
|
@ -37,6 +37,10 @@ def auth_processor_perms(request):
|
||||||
return render_to_response('context_processors/auth_attrs_perms.html',
|
return render_to_response('context_processors/auth_attrs_perms.html',
|
||||||
RequestContext(request, {}, processors=[context_processors.auth]))
|
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):
|
def auth_processor_messages(request):
|
||||||
info(request, "Message 1")
|
info(request, "Message 1")
|
||||||
return render_to_response('context_processors/auth_attrs_messages.html',
|
return render_to_response('context_processors/auth_attrs_messages.html',
|
||||||
|
@ -58,6 +62,7 @@ urlpatterns = urlpatterns + patterns('',
|
||||||
(r'^auth_processor_attr_access/$', auth_processor_attr_access),
|
(r'^auth_processor_attr_access/$', auth_processor_attr_access),
|
||||||
(r'^auth_processor_user/$', auth_processor_user),
|
(r'^auth_processor_user/$', auth_processor_user),
|
||||||
(r'^auth_processor_perms/$', auth_processor_perms),
|
(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),
|
(r'^auth_processor_messages/$', auth_processor_messages),
|
||||||
url(r'^userpage/(.+)/$', userpage, name="userpage"),
|
url(r'^userpage/(.+)/$', userpage, name="userpage"),
|
||||||
)
|
)
|
||||||
|
|
|
@ -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
|
and inversion, expanding the types of expressions that can be passed to the
|
||||||
database.
|
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
|
Backwards incompatible changes in 1.5
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
|
|
|
@ -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>
|
<p>You don't have permission to do anything in the foo app.</p>
|
||||||
{% endif %}
|
{% 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
|
Groups
|
||||||
======
|
======
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue