Ticket #11010: object_permissions_r11712_#11010.diff

File object_permissions_r11712_#11010.diff, 12.8 KB (added by apollo13, 6 years ago)
  • django/contrib/auth/__init__.py

    diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py
    index b89aee1..c17f65e 100644
    a b  
    11import datetime
     2
     3from warnings import warn as warn_
     4
    25from django.core.exceptions import ImproperlyConfigured
    36from django.utils.importlib import import_module
    47
    def load_backend(path): 
    1922        cls = getattr(mod, attr)
    2023    except AttributeError:
    2124        raise ImproperlyConfigured, 'Module "%s" does not define a "%s" authentication backend' % (module, attr)
     25   
     26    try:
     27        getattr(cls, 'supports_object_perms')
     28    except AttributeError:
     29        warn_("%s should define `supports_object_perms`." % cls,
     30          PendingDeprecationWarning, stacklevel=3)
     31        cls.supports_object_perms = False
     32
    2233    return cls()
    2334
    2435def get_backends():
  • django/contrib/auth/backends.py

    diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py
    index 05f9835..df73a29 100644
    a b class ModelBackend(object): 
    1111    """
    1212    Authenticates against django.contrib.auth.models.User.
    1313    """
     14    supports_object_perms = False
     15
    1416    # TODO: Model, login attribute name and password attribute name should be
    1517    # configurable.
    1618    def authenticate(self, username=None, password=None):
  • django/contrib/auth/models.py

    diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py
    index e337bec..29c32a0 100644
    a b class User(models.Model): 
    194194    def has_usable_password(self):
    195195        return self.password != UNUSABLE_PASSWORD
    196196
    197     def get_group_permissions(self):
     197    def get_group_permissions(self, obj=None):
    198198        """
    199199        Returns a list of permission strings that this user has through
    200200        his/her groups. This method queries all available auth backends.
     201        If an object is passed in, only permissions matching this object
     202        are returned.
    201203        """
    202204        permissions = set()
    203205        for backend in auth.get_backends():
    204206            if hasattr(backend, "get_group_permissions"):
    205                 permissions.update(backend.get_group_permissions(self))
     207                if obj:
     208                    if backend.supports_object_perms:
     209                        permissions.update(backend.get_group_permissions(self, obj))
     210                else:
     211                    permissions.update(backend.get_group_permissions(self))
    206212        return permissions
    207213
    208     def get_all_permissions(self):
     214    def get_all_permissions(self, obj=None):
    209215        permissions = set()
    210216        for backend in auth.get_backends():
    211217            if hasattr(backend, "get_all_permissions"):
    212                 permissions.update(backend.get_all_permissions(self))
     218                if obj:
     219                    if backend.supports_object_perms:
     220                        permissions.update(backend.get_all_permissions(self, obj))
     221                else:
     222                    permissions.update(backend.get_all_permissions(self))
    213223        return permissions
    214224
    215     def has_perm(self, perm):
     225    def has_perm(self, perm, obj=None):
    216226        """
    217227        Returns True if the user has the specified permission. This method
    218228        queries all available auth backends, but returns immediately if any
    219229        backend returns True. Thus, a user who has permission from a single
    220         auth backend is assumed to have permission in general.
     230        auth backend is assumed to have permission in general. If an object
     231        is provided, permissions for this specific object are checked.
    221232        """
    222233        # Inactive users have no permissions.
    223234        if not self.is_active:
    class User(models.Model): 
    230241        # Otherwise we need to check the backends.
    231242        for backend in auth.get_backends():
    232243            if hasattr(backend, "has_perm"):
    233                 if backend.has_perm(self, perm):
    234                     return True
     244                if obj:
     245                    if backend.supports_object_perms:
     246                        if backend.has_perm(self, perm, obj):
     247                            return True
     248                else:
     249                    if backend.has_perm(self, perm):
     250                        return True
    235251        return False
    236252
    237     def has_perms(self, perm_list):
    238         """Returns True if the user has each of the specified permissions."""
     253    def has_perms(self, perm_list, obj=None):
     254        """Returns True if the user has each of the specified permissions.
     255        If object is passed, it checks if the user has all required perms
     256        for this object.
     257        """
    239258        for perm in perm_list:
    240             if not self.has_perm(perm):
     259            if not self.has_perm(perm, obj):
    241260                return False
    242261        return True
    243262
  • django/contrib/auth/tests/__init__.py

    diff --git a/django/contrib/auth/tests/__init__.py b/django/contrib/auth/tests/__init__.py
    index 14428d0..9a078cf 100644
    a b from django.contrib.auth.tests.views \ 
    44from django.contrib.auth.tests.forms import FORM_TESTS
    55from django.contrib.auth.tests.remote_user \
    66        import RemoteUserTest, RemoteUserNoCreateTest, RemoteUserCustomTest
     7from django.contrib.auth.tests.auth_backends import BackendTest, RowlevelBackendTest
    78from django.contrib.auth.tests.tokens import TOKEN_GENERATOR_TESTS
    89
    910# The password for the fixture data users is 'password'
  • docs/internals/deprecation.txt

    diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt
    index 480b527..b10a575 100644
    a b their deprecation, as per the :ref:`Django deprecation policy 
    1313          hooking up admin URLs.  This has been deprecated since the 1.1
    1414          release.
    1515
     16        * Authentication backends need to define ``supports_object_perms``. The
     17          old backend style got is deprecated since the 1.2 release.
     18
    1619    * 1.4
    1720        * ``CsrfResponseMiddleware``.  This has been deprecated since the 1.2
    1821          release, in favour of the template tag method for inserting the CSRF
    their deprecation, as per the :ref:`Django deprecation policy 
    2831        * The many to many SQL generation functions on the database backends
    2932          will be removed.  These have been deprecated since the 1.2 release.
    3033
     34        * Authentication backends need to support the ``obj`` parameter for
     35          permission checking. The ``supports_object_perms`` variable is not
     36          checked anylonger and can be removed.
     37
    3138    * 2.0
    3239        * ``django.views.defaults.shortcut()``. This function has been moved
    3340          to ``django.contrib.contenttypes.views.shortcut()`` as part of the
  • docs/topics/auth.txt

    diff --git a/docs/topics/auth.txt b/docs/topics/auth.txt
    index 33461a0..9baa732 100644
    a b Methods 
    199199        :meth:`~django.contrib.auth.models.User.set_unusable_password()` has
    200200        been called for this user.
    201201
    202     .. method:: models.User.get_group_permissions()
     202    .. method:: models.User.get_group_permissions(obj=None)
    203203
    204204        Returns a list of permission strings that the user has, through his/her
    205         groups.
     205        groups. If ``obj`` is passed in, only returns the group permissions for
     206        this specific object.
    206207
    207     .. method:: models.User.get_all_permissions()
     208    .. method:: models.User.get_all_permissions(obj=None)
    208209
    209210        Returns a list of permission strings that the user has, both through
    210         group and user permissions.
     211        group and user permissions. If ``obj`` is passed in, only returns the
     212        permissions for this specific object.
    211213
    212     .. method:: models.User.has_perm(perm)
     214
     215    .. method:: models.User.has_perm(perm, obj=None)
    213216
    214217        Returns ``True`` if the user has the specified permission, where perm is
    215218        in the format ``"<app label>.<permission codename>"``.
    216         If the user is inactive, this method will always return ``False``.
     219        If the user is inactive, this method will always return ``False``. If
     220        ``obj`` is passed in this method won't check the permissions for the model,
     221        but the object.
    217222
    218     .. method:: models.User.has_perms(perm_list)
     223    .. method:: models.User.has_perms(perm_list, obj=None)
    219224
    220225        Returns ``True`` if the user has each of the specified permissions,
    221226        where each perm is in the format
    222227        ``"<app label>.<permission codename>"``. If the user is inactive,
    223         this method will always return ``False``.
     228        this method will always return ``False``. If ``obj`` is passed in
     229        this method won't check the permissions for the model, but the object.
    224230
    225231    .. method:: models.User.has_module_perms(package_name)
    226232
    A full authorization implementation can be found in 
    15101516the ``auth_permission`` table most of the time.
    15111517
    15121518.. _django/contrib/auth/backends.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/backends.py
     1519
     1520Handling object permissions
     1521---------------------------
     1522
     1523Django's permission framework has a foundation for object permissions, though
     1524there is no implementation for it in the core. This means, that checking for
     1525object permissions will always return ``False`` or an empty list (depending on
     1526the check performed). To enable object permissions you will have to write your
     1527own Backend which does support them, the only change you have to do is to add
     1528an ``obj`` parameter to the permission functions and set ``supports_objects_perms``
     1529to ``True``. In Django 1.2 a non existing ``supports_objects_perms`` will raise a
     1530``PendingDeprecationWarning``. In 1.3 a non existant ``support_object_perms``
     1531attribute will raise an error and setting it to ``False`` will raise a
     1532``DeprecationWarning``. In 1.4 it's assumed that every backend supports object
     1533permissions and no checking is performed, which means not supporting ``obj`` as
     1534parameter will raise a ``TypeError``.
  • deleted file tests/regressiontests/auth_backends/tests.py

    diff --git a/tests/regressiontests/auth_backends/__init__.py b/tests/regressiontests/auth_backends/__init__.py
    deleted file mode 100644
    index e69de29..0000000
    diff --git a/tests/regressiontests/auth_backends/models.py b/tests/regressiontests/auth_backends/models.py
    deleted file mode 100644
    index e69de29..0000000
    diff --git a/tests/regressiontests/auth_backends/tests.py b/tests/regressiontests/auth_backends/tests.py
    deleted file mode 100644
    index d22f0bf..0000000
    + -  
    1 try:
    2     set
    3 except NameError:
    4     from sets import Set as set     # Python 2.3 fallback
    5 
    6 __test__ = {'API_TESTS': """
    7 >>> from django.contrib.auth.models import User, Group, Permission, AnonymousUser
    8 >>> from django.contrib.contenttypes.models import ContentType
    9 
    10 # No Permissions assigned yet, should return False except for superuser
    11 
    12 >>> user = User.objects.create_user('test', 'test@example.com', 'test')
    13 >>> user.has_perm("auth.test")
    14 False
    15 >>> user.is_staff=True
    16 >>> user.save()
    17 >>> user.has_perm("auth.test")
    18 False
    19 >>> user.is_superuser=True
    20 >>> user.save()
    21 >>> user.has_perm("auth.test")
    22 True
    23 >>> user.is_staff = False
    24 >>> user.is_superuser = False
    25 >>> user.save()
    26 >>> user.has_perm("auth.test")
    27 False
    28 >>> content_type=ContentType.objects.get_for_model(Group)
    29 >>> perm = Permission.objects.create(name="test", content_type=content_type, codename="test")
    30 >>> user.user_permissions.add(perm)
    31 >>> user.save()
    32 
    33 # reloading user to purge the _perm_cache
    34 
    35 >>> user = User.objects.get(username="test")
    36 >>> user.get_all_permissions() == set([u'auth.test'])
    37 True
    38 >>> user.get_group_permissions() == set([])
    39 True
    40 >>> user.has_module_perms("Group")
    41 False
    42 >>> user.has_module_perms("auth")
    43 True
    44 >>> perm = Permission.objects.create(name="test2", content_type=content_type, codename="test2")
    45 >>> user.user_permissions.add(perm)
    46 >>> user.save()
    47 >>> perm = Permission.objects.create(name="test3", content_type=content_type, codename="test3")
    48 >>> user.user_permissions.add(perm)
    49 >>> user.save()
    50 >>> user = User.objects.get(username="test")
    51 >>> user.get_all_permissions() == set([u'auth.test2', u'auth.test', u'auth.test3'])
    52 True
    53 >>> user.has_perm('test')
    54 False
    55 >>> user.has_perm('auth.test')
    56 True
    57 >>> user.has_perms(['auth.test2', 'auth.test3'])
    58 True
    59 >>> perm = Permission.objects.create(name="test_group", content_type=content_type, codename="test_group")
    60 >>> group = Group.objects.create(name='test_group')
    61 >>> group.permissions.add(perm)
    62 >>> group.save()
    63 >>> user.groups.add(group)
    64 >>> user = User.objects.get(username="test")
    65 >>> exp = set([u'auth.test2', u'auth.test', u'auth.test3', u'auth.test_group'])
    66 >>> user.get_all_permissions() == exp
    67 True
    68 >>> user.get_group_permissions() == set([u'auth.test_group'])
    69 True
    70 >>> user.has_perms(['auth.test3', 'auth.test_group'])
    71 True
    72 
    73 >>> user = AnonymousUser()
    74 >>> user.has_perm('test')
    75 False
    76 >>> user.has_perms(['auth.test2', 'auth.test3'])
    77 False
    78 """}
Back to Top