Fixed #33269 -- Made AnonymousUser/PermissionsMixin.has_perms() raise ValueError on string or non-iterable perm_list.

This commit is contained in:
Lie Ryan 2021-10-11 14:54:50 +11:00 committed by Mariusz Felisiak
parent 4bfe8c0eec
commit 05cde4764d
2 changed files with 19 additions and 0 deletions

View File

@ -8,6 +8,7 @@ from django.core.mail import send_mail
from django.db import models from django.db import models
from django.db.models.manager import EmptyManager from django.db.models.manager import EmptyManager
from django.utils import timezone from django.utils import timezone
from django.utils.itercompat import is_iterable
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from .validators import UnicodeUsernameValidator from .validators import UnicodeUsernameValidator
@ -304,6 +305,8 @@ class PermissionsMixin(models.Model):
Return True if the user has each of the specified permissions. If Return True if the user has each of the specified permissions. If
object is passed, check if the user has all required perms for it. object is passed, check if the user has all required perms for it.
""" """
if not is_iterable(perm_list) or isinstance(perm_list, str):
raise ValueError('perm_list must be an iterable of permissions.')
return all(self.has_perm(perm, obj) for perm in perm_list) return all(self.has_perm(perm, obj) for perm in perm_list)
def has_module_perms(self, app_label): def has_module_perms(self, app_label):
@ -452,6 +455,8 @@ class AnonymousUser:
return _user_has_perm(self, perm, obj=obj) return _user_has_perm(self, perm, obj=obj)
def has_perms(self, perm_list, obj=None): def has_perms(self, perm_list, obj=None):
if not is_iterable(perm_list) or isinstance(perm_list, str):
raise ValueError('perm_list must be an iterable of permissions.')
return all(self.has_perm(perm, obj) for perm in perm_list) return all(self.has_perm(perm, obj) for perm in perm_list)
def has_module_perms(self, module): def has_module_perms(self, module):

View File

@ -53,6 +53,13 @@ class BaseBackendTest(TestCase):
self.assertIs(self.user.has_perm('group_perm'), True) self.assertIs(self.user.has_perm('group_perm'), True)
self.assertIs(self.user.has_perm('other_perm', TestObj()), False) self.assertIs(self.user.has_perm('other_perm', TestObj()), False)
def test_has_perms_perm_list_invalid(self):
msg = 'perm_list must be an iterable of permissions.'
with self.assertRaisesMessage(ValueError, msg):
self.user.has_perms('user_perm')
with self.assertRaisesMessage(ValueError, msg):
self.user.has_perms(object())
class CountingMD5PasswordHasher(MD5PasswordHasher): class CountingMD5PasswordHasher(MD5PasswordHasher):
"""Hasher that counts how many times it computes a hash.""" """Hasher that counts how many times it computes a hash."""
@ -476,6 +483,13 @@ class AnonymousUserBackendTest(SimpleTestCase):
self.assertIs(self.user1.has_perms(['anon'], TestObj()), True) self.assertIs(self.user1.has_perms(['anon'], TestObj()), True)
self.assertIs(self.user1.has_perms(['anon', 'perm'], TestObj()), False) self.assertIs(self.user1.has_perms(['anon', 'perm'], TestObj()), False)
def test_has_perms_perm_list_invalid(self):
msg = 'perm_list must be an iterable of permissions.'
with self.assertRaisesMessage(ValueError, msg):
self.user1.has_perms('perm')
with self.assertRaisesMessage(ValueError, msg):
self.user1.has_perms(object())
def test_has_module_perms(self): def test_has_module_perms(self):
self.assertIs(self.user1.has_module_perms("app1"), True) self.assertIs(self.user1.has_module_perms("app1"), True)
self.assertIs(self.user1.has_module_perms("app2"), False) self.assertIs(self.user1.has_module_perms("app2"), False)