diff --git a/django/contrib/auth/context_processors.py b/django/contrib/auth/context_processors.py index 3ffab01e94..ea9f95c4f0 100644 --- a/django/contrib/auth/context_processors.py +++ b/django/contrib/auth/context_processors.py @@ -11,6 +11,11 @@ class PermLookupDict(object): def __getitem__(self, perm_name): return self.user.has_perm("%s.%s" % (self.module_name, perm_name)) + def __iter__(self): + # To fix 'item in perms.someapp' and __getitem__ iteraction we need to + # define __iter__. See #18979 for details. + raise TypeError("PermLookupDict is not iterable.") + def __nonzero__(self): return self.user.has_module_perms(self.module_name) diff --git a/django/contrib/auth/tests/context_processors.py b/django/contrib/auth/tests/context_processors.py index dcd50fc6cc..55cbdd413e 100644 --- a/django/contrib/auth/tests/context_processors.py +++ b/django/contrib/auth/tests/context_processors.py @@ -2,12 +2,56 @@ import os from django.conf import global_settings from django.contrib.auth import authenticate +from django.contrib.auth.context_processors import PermWrapper, PermLookupDict from django.db.models import Q from django.template import context from django.test import TestCase from django.test.utils import override_settings +class MockUser(object): + def has_module_perm(self, perm): + if perm == 'mockapp.someapp': + return True + return False + + def has_perm(self, perm): + if perm == 'someperm': + return True + return False + + +class PermWrapperTests(TestCase): + """ + Test some details of the PermWrapper implementation. + """ + class EQLimiterObject(object): + """ + This object makes sure __eq__ will not be called endlessly. + """ + def __init__(self): + self.eq_calls = 0 + + def __eq__(self, other): + if self.eq_calls > 0: + return True + self.eq_calls += 1 + return False + + def test_permwrapper_in(self): + """ + Test that 'something' in PermWrapper doesn't end up in endless loop. + """ + perms = PermWrapper(MockUser()) + with self.assertRaises(TypeError): + self.EQLimiterObject() in perms + + def test_permlookupdict_in(self): + pldict = PermLookupDict(MockUser(), 'mockapp') + with self.assertRaises(TypeError): + self.EQLimiterObject() in pldict + + class AuthContextProcessorTests(TestCase): """ Tests for the ``django.contrib.auth.context_processors.auth`` processor