Commit e130dc32 authored by Alex Gaynor's avatar Alex Gaynor
Browse files

Removed the deprecated-since-1.2 "supports_object_permissions" and...

Removed the deprecated-since-1.2 "supports_object_permissions" and "supports_anonymous_user" flags on authentication backends.  If you have an authenication backend it now *must* suport these.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16789 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 0609255d
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -5,8 +5,6 @@ class ModelBackend(object):
    """
    Authenticates against django.contrib.auth.models.User.
    """
    supports_object_permissions = False
    supports_anonymous_user = True
    supports_inactive_user = True

    # TODO: Model, login attribute name and password attribute name should be
@@ -19,11 +17,13 @@ class ModelBackend(object):
        except User.DoesNotExist:
            return None

    def get_group_permissions(self, user_obj):
    def get_group_permissions(self, user_obj, obj=None):
        """
        Returns a set of permission strings that this user has through his/her
        groups.
        """
        if user_obj.is_anonymous() or obj is not None:
            return set()
        if not hasattr(user_obj, '_group_perm_cache'):
            if user_obj.is_superuser:
                perms = Permission.objects.all()
@@ -33,18 +33,18 @@ class ModelBackend(object):
            user_obj._group_perm_cache = set(["%s.%s" % (ct, name) for ct, name in perms])
        return user_obj._group_perm_cache

    def get_all_permissions(self, user_obj):
        if user_obj.is_anonymous():
    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([u"%s.%s" % (p.content_type.app_label, p.codename) for p in user_obj.user_permissions.select_related()])
            user_obj._perm_cache.update(self.get_group_permissions(user_obj))
        return user_obj._perm_cache

    def has_perm(self, user_obj, perm):
    def has_perm(self, user_obj, perm, obj=None):
        if not user_obj.is_active:
            return False
        return perm in self.get_all_permissions(user_obj)
        return perm in self.get_all_permissions(user_obj, obj)

    def has_module_perms(self, user_obj, app_label):
        """
+15 −31
Original line number Diff line number Diff line
@@ -132,30 +132,20 @@ class UserManager(models.Manager):
# A few helper functions for common logic between User and AnonymousUser.
def _user_get_all_permissions(user, obj):
    permissions = set()
    anon = user.is_anonymous()
    for backend in auth.get_backends():
        if not anon or backend.supports_anonymous_user:
        if hasattr(backend, "get_all_permissions"):
            if obj is not None:
                    if backend.supports_object_permissions:
                        permissions.update(
                            backend.get_all_permissions(user, obj)
                        )
                permissions.update(backend.get_all_permissions(user, obj))
            else:
                permissions.update(backend.get_all_permissions(user))
    return permissions


def _user_has_perm(user, perm, obj):
    anon = user.is_anonymous()
    active = user.is_active
    for backend in auth.get_backends():
        if (not active and not anon and backend.supports_inactive_user) or \
                    (not anon or backend.supports_anonymous_user):
        if hasattr(backend, "has_perm"):
            if obj is not None:
                    if (backend.supports_object_permissions and
                        backend.has_perm(user, perm, obj)):
                if backend.has_perm(user, perm, obj):
                        return True
            else:
                if backend.has_perm(user, perm):
@@ -164,11 +154,8 @@ def _user_has_perm(user, perm, obj):


def _user_has_module_perms(user, app_label):
    anon = user.is_anonymous()
    active = user.is_active
    for backend in auth.get_backends():
        if (not active and not anon and backend.supports_inactive_user) or \
                    (not anon or backend.supports_anonymous_user):
        if hasattr(backend, "has_module_perms"):
            if backend.has_module_perms(user, app_label):
                return True
@@ -264,10 +251,7 @@ class User(models.Model):
        for backend in auth.get_backends():
            if hasattr(backend, "get_group_permissions"):
                if obj is not None:
                    if backend.supports_object_permissions:
                        permissions.update(
                            backend.get_group_permissions(self, obj)
                        )
                    permissions.update(backend.get_group_permissions(self, obj))
                else:
                    permissions.update(backend.get_group_permissions(self))
        return permissions
+2 −2
Original line number Diff line number Diff line
from django.contrib.auth.tests.auth_backends import (BackendTest,
    RowlevelBackendTest, AnonymousUserBackendTest, NoAnonymousUserBackendTest,
    NoBackendsTest, InActiveUserBackendTest, NoInActiveUserBackendTest)
    RowlevelBackendTest, AnonymousUserBackendTest, NoBackendsTest,
    InActiveUserBackendTest, NoInActiveUserBackendTest)
from django.contrib.auth.tests.basic import BasicTestCase, PasswordUtilsTestCase
from django.contrib.auth.tests.context_processors import AuthContextProcessorTests
from django.contrib.auth.tests.decorators import LoginRequiredTestCase
+1 −43
Original line number Diff line number Diff line
@@ -103,14 +103,12 @@ class TestObj(object):


class SimpleRowlevelBackend(object):
    supports_object_permissions = True
    supports_inactive_user = False

    # This class also supports tests for anonymous user permissions, and
    # inactive user permissions via subclasses which just set the
    # 'supports_anonymous_user' or 'supports_inactive_user' attribute.


    def has_perm(self, user, perm, obj=None):
        if not obj:
            return # We only support row level perms
@@ -119,7 +117,6 @@ class SimpleRowlevelBackend(object):
            if user.username == 'test2':
                return True
            elif user.is_anonymous() and perm == 'anon':
                # not reached due to supports_anonymous_user = False
                return True
            elif not user.is_active and perm == 'inactive':
                return True
@@ -199,20 +196,12 @@ class RowlevelBackendTest(TestCase):


class AnonymousUserBackend(SimpleRowlevelBackend):

    supports_anonymous_user = True
    supports_inactive_user = False


class NoAnonymousUserBackend(SimpleRowlevelBackend):

    supports_anonymous_user = False
    supports_inactive_user = False


class AnonymousUserBackendTest(TestCase):
    """
    Tests for AnonymousUser delegating to backend if it has 'supports_anonymous_user' = True
    Tests for AnonymousUser delegating to backend.
    """

    backend = 'django.contrib.auth.tests.auth_backends.AnonymousUserBackend'
@@ -241,33 +230,6 @@ class AnonymousUserBackendTest(TestCase):
        self.assertEqual(self.user1.get_all_permissions(TestObj()), set(['anon']))


class NoAnonymousUserBackendTest(TestCase):
    """
    Tests that AnonymousUser does not delegate to backend if it has 'supports_anonymous_user' = False
    """
    backend = 'django.contrib.auth.tests.auth_backends.NoAnonymousUserBackend'

    def setUp(self):
        self.curr_auth = settings.AUTHENTICATION_BACKENDS
        settings.AUTHENTICATION_BACKENDS = tuple(self.curr_auth) + (self.backend,)
        self.user1 = AnonymousUser()

    def tearDown(self):
        settings.AUTHENTICATION_BACKENDS = self.curr_auth

    def test_has_perm(self):
        self.assertEqual(self.user1.has_perm('perm', TestObj()), False)
        self.assertEqual(self.user1.has_perm('anon', TestObj()), False)

    def test_has_perms(self):
        self.assertEqual(self.user1.has_perms(['anon'], TestObj()), False)

    def test_has_module_perms(self):
        self.assertEqual(self.user1.has_module_perms("app1"), False)
        self.assertEqual(self.user1.has_module_perms("app2"), False)

    def test_get_all_permissions(self):
        self.assertEqual(self.user1.get_all_permissions(TestObj()), set())


class NoBackendsTest(TestCase):
@@ -287,14 +249,10 @@ class NoBackendsTest(TestCase):


class InActiveUserBackend(SimpleRowlevelBackend):

    supports_anonymous_user = False
    supports_inactive_user = True


class NoInActiveUserBackend(SimpleRowlevelBackend):

    supports_anonymous_user = False
    supports_inactive_user = False


+2 −30
Original line number Diff line number Diff line
@@ -1633,8 +1633,6 @@ object the first time a user authenticates::
        ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de'
        """

        supports_object_permissions = False
        supports_anonymous_user = False
        supports_inactive_user = False

        def authenticate(self, username=None, password=None):
@@ -1683,7 +1681,7 @@ fairly simply::

        # ...

        def has_perm(self, user_obj, perm):
        def has_perm(self, user_obj, perm, obj=None):
            if user_obj.username == settings.ADMIN_LOGIN:
                return True
            else:
@@ -1720,19 +1718,6 @@ for the authors of re-usable apps, who can delegate all questions of authorizati
to the auth backend, rather than needing settings, for example, to control
anonymous access.

To enable this in your own backend, you must set the class attribute
``supports_anonymous_user`` to ``True``. (This precaution is to maintain
compatibility with backends that assume that all user objects are actual
instances of the :class:`django.contrib.auth.models.User` class). With this
in place, :class:`django.contrib.auth.models.AnonymousUser` will delegate all
the relevant permission methods to the authentication backends.

A nonexistent ``supports_anonymous_user`` attribute will raise a hidden
``PendingDeprecationWarning`` if used in Django 1.2. In Django 1.3, this
warning will be upgraded to a ``DeprecationWarning``, which will be displayed
loudly. Additionally ``supports_anonymous_user`` will be set to ``False``.
Django 1.4 will assume that every backend supports anonymous users being
passed to the authorization methods.

Authorization for inactive users
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1766,16 +1751,3 @@ Django's permission framework has a foundation for object permissions, though
there is no implementation for it in the core. That means that checking for
object permissions will always return ``False`` or an empty list (depending on
the check performed).
 No newline at end of file

To enable object permissions in your own
:doc:`authentication backend </ref/authbackends>` you'll just have
to allow passing an ``obj`` parameter to the permission methods and set the
``supports_object_permissions`` class attribute to ``True``.

A nonexistent ``supports_object_permissions`` will raise a hidden
``PendingDeprecationWarning`` if used in Django 1.2. In Django 1.3, this
warning will be upgraded to a ``DeprecationWarning``, which will be displayed
loudly. Additionally ``supports_object_permissions`` will be set to ``False``.
Django 1.4 will assume that every backend supports object permissions and
won't check for the existence of ``supports_object_permissions``, which
means not supporting ``obj`` as a parameter will raise a ``TypeError``.