Pārlūkot izejas kodu

Fixed #7599 -- Added get_user_permissions to ModelBackend.

Thanks to @gdub for the report and intial patch and
@charettes and @timgraham for the review.
Jorge C. Leitão 11 gadi atpakaļ
vecāks
revīzija
cc35bd461d
2 mainītis faili ar 81 papildinājumiem un 10 dzēšanām
  1. 33 10
      django/contrib/auth/backends.py
  2. 48 0
      docs/ref/contrib/auth.txt

+ 33 - 10
django/contrib/auth/backends.py

@@ -21,29 +21,52 @@ class ModelBackend(object):
             # difference between an existing and a non-existing user (#20760).
             UserModel().set_password(password)
 
-    def get_group_permissions(self, user_obj, obj=None):
+    def _get_user_permissions(self, user_obj):
+        return user_obj.user_permissions.all()
+
+    def _get_group_permissions(self, user_obj):
+        user_groups_field = get_user_model()._meta.get_field('groups')
+        user_groups_query = 'group__%s' % user_groups_field.related_query_name()
+        return Permission.objects.filter(**{user_groups_query: user_obj})
+
+    def _get_permissions(self, user_obj, obj, from_name):
         """
-        Returns a set of permission strings that this user has through his/her
-        groups.
+        Returns the permissions of `user_obj` from `from_name`. `from_name` can
+        be either "group" or "user" to return permissions from
+        `_get_group_permissions` or `_get_user_permissions` respectively.
         """
         if user_obj.is_anonymous() or obj is not None:
             return set()
-        if not hasattr(user_obj, '_group_perm_cache'):
+
+        perm_cache_name = '_%s_perm_cache' % from_name
+        if not hasattr(user_obj, perm_cache_name):
             if user_obj.is_superuser:
                 perms = Permission.objects.all()
             else:
-                user_groups_field = get_user_model()._meta.get_field('groups')
-                user_groups_query = 'group__%s' % user_groups_field.related_query_name()
-                perms = Permission.objects.filter(**{user_groups_query: user_obj})
+                perms = getattr(self, '_get_%s_permissions' % from_name)(user_obj)
             perms = perms.values_list('content_type__app_label', 'codename').order_by()
-            user_obj._group_perm_cache = set("%s.%s" % (ct, name) for ct, name in perms)
-        return user_obj._group_perm_cache
+            setattr(user_obj, perm_cache_name, set("%s.%s" % (ct, name) for ct, name in perms))
+        return getattr(user_obj, perm_cache_name)
+
+    def get_user_permissions(self, user_obj, obj=None):
+        """
+        Returns a set of permission strings the user `user_obj` has from their
+        `user_permissions`.
+        """
+        return self._get_permissions(user_obj, obj, 'user')
+
+    def get_group_permissions(self, user_obj, obj=None):
+        """
+        Returns a set of permission strings the user `user_obj` has from the
+        groups they belong.
+        """
+        return self._get_permissions(user_obj, obj, 'group')
 
     def get_all_permissions(self, user_obj, obj=None):
         if user_obj.is_anonymous() or obj is not None:
             return set()
         if not hasattr(user_obj, '_perm_cache'):
-            user_obj._perm_cache = set("%s.%s" % (p.content_type.app_label, p.codename) for p in user_obj.user_permissions.select_related())
+            user_obj._perm_cache = self.get_user_permissions(user_obj)
             user_obj._perm_cache.update(self.get_group_permissions(user_obj))
         return user_obj._perm_cache
 

+ 48 - 0
docs/ref/contrib/auth.txt

@@ -425,6 +425,54 @@ The following backends are available in :mod:`django.contrib.auth.backends`:
     :class:`~django.contrib.auth.models.User` and
     :class:`~django.contrib.auth.models.PermissionsMixin`.
 
+    :meth:`has_perm`, :meth:`get_all_permissions`, :meth:`get_user_permissions`,
+    and :meth:`get_group_permissions` allow an object to be passed as a
+    parameter for object-specific permissions, but this backend does not
+    implement them other than returning an empty set of permissions if
+    ``obj is not None``.
+
+    .. method:: authenticate(username=None, password=None, **kwargs)
+
+        Tries to authenticate ``username`` with ``password`` by calling
+        :meth:`User.check_password
+        <django.contrib.auth.models.User.check_password>`. If no ``username``
+        is provided, it tries to fetch a username from ``kwargs`` using the
+        key :attr:`CustomUser.USERNAME_FIELD
+        <django.contrib.auth.models.CustomUser.USERNAME_FIELD>`. Returns an
+        authenticated user or ``None``.
+
+    .. method:: get_user_permissions(user_obj, obj=None)
+
+        .. versionadded:: 1.8
+
+        Returns the set of permission strings the ``user_obj`` has from their
+        own user permissions. Returns an empty set if the user
+        :meth:`~django.contrib.auth.models.AbstractBaseUser.is_anonymous`.
+
+    .. method:: get_group_permissions(user_obj, obj=None)
+
+        Returns the set of permission strings the ``user_obj`` has from the
+        permissions of the groups they belong. Returns an empty set if the user
+        :meth:`~django.contrib.auth.models.AbstractBaseUser.is_anonymous`.
+
+    .. method:: get_all_permissions(user_obj, obj=None)
+
+        Returns the set of permission strings the ``user_obj`` has, including
+        both user permissions and groups permissions. Returns an empty set if
+        the user
+        :meth:`~django.contrib.auth.models.AbstractBaseUser.is_anonymous`.
+
+    .. method:: has_perm(user_obj, perm, obj=None)
+
+        Uses :meth:`get_all_permissions` to check if ``user_obj`` has the
+        permission string ``perm``. Returns ``False`` if the user is not
+        :meth:`~django.contrib.auth.models.CustomUser.is_active`.
+
+    .. method:: has_module_perms(self, user_obj, app_label)
+
+        Returns whether the ``user_obj`` has any permissions on the app
+        ``app_label``.
+
 .. class:: RemoteUserBackend
 
     Use this backend to take advantage of external-to-Django-handled