Commit d5a4f209 authored by Anssi Kääriäinen's avatar Anssi Kääriäinen
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 %}.
parent c2532825
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -32,6 +32,17 @@ class PermWrapper(object):
        # 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
+34 −7
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@ import os
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 @@ from django.test.utils import override_settings


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 @@ class PermWrapperTests(TestCase):

    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 @@ class AuthContextProcessorTests(TestCase):
        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')
+4 −0
Original line number Diff line number Diff line
{% 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 %}
+3 −0
Original line number Diff line number Diff line
{% 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 %}
+5 −0
Original line number Diff line number Diff line
@@ -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 @@ urlpatterns = urlpatterns + patterns('',
    (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"),
)
Loading