diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py index 5f092f0ae8..a9faef3517 100644 --- a/django/contrib/auth/models.py +++ b/django/contrib/auth/models.py @@ -8,6 +8,7 @@ from django.core.mail import send_mail from django.db import models from django.db.models.manager import EmptyManager from django.utils import timezone +from django.utils.itercompat import is_iterable from django.utils.translation import gettext_lazy as _ from .validators import UnicodeUsernameValidator @@ -304,6 +305,8 @@ class PermissionsMixin(models.Model): 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. """ + 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) def has_module_perms(self, app_label): @@ -452,6 +455,8 @@ class AnonymousUser: return _user_has_perm(self, perm, obj=obj) 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) def has_module_perms(self, module): diff --git a/tests/auth_tests/test_auth_backends.py b/tests/auth_tests/test_auth_backends.py index d01d0b6526..d1471466d7 100644 --- a/tests/auth_tests/test_auth_backends.py +++ b/tests/auth_tests/test_auth_backends.py @@ -53,6 +53,13 @@ class BaseBackendTest(TestCase): self.assertIs(self.user.has_perm('group_perm'), True) 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): """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', '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): self.assertIs(self.user1.has_module_perms("app1"), True) self.assertIs(self.user1.has_module_perms("app2"), False)