Ticket #5457: full_diff.2.diff

File full_diff.2.diff, 11.8 KB (added by Florian Apolloner, 17 years ago)

full diff including docs and tests (I hope everything works, as I am really tired now XD) [last one missed the tests...]

  • django/contrib/auth/backends.py

     
     1from django.db import connection, models
    12from django.contrib.auth.models import User
    23
    34class ModelBackend:
     
    1415        except User.DoesNotExist:
    1516            return None
    1617
     18    def get_group_permissions(self, user_obj):
     19        "Returns a list of permission strings that this user has through his/her groups."
     20        if not hasattr(user_obj, '_group_perm_cache'):
     21            cursor = connection.cursor()
     22            # The SQL below works out to the following, after DB quoting:
     23            # cursor.execute("""
     24            #     SELECT ct."app_label", p."codename"
     25            #     FROM "auth_permission" p, "auth_group_permissions" gp, "auth_user_groups" ug, "django_content_type" ct
     26            #     WHERE p."id" = gp."permission_id"
     27            #         AND gp."group_id" = ug."group_id"
     28            #         AND ct."id" = p."content_type_id"
     29            #         AND ug."user_id" = %s, [self.id])
     30            qn = connection.ops.quote_name
     31            sql = """
     32                SELECT ct.%s, p.%s
     33                FROM %s p, %s gp, %s ug, %s ct
     34                WHERE p.%s = gp.%s
     35                    AND gp.%s = ug.%s
     36                    AND ct.%s = p.%s
     37                    AND ug.%s = %%s""" % (
     38                qn('app_label'), qn('codename'),
     39                qn('auth_permission'), qn('auth_group_permissions'),
     40                qn('auth_user_groups'), qn('django_content_type'),
     41                qn('id'), qn('permission_id'),
     42                qn('group_id'), qn('group_id'),
     43                qn('id'), qn('content_type_id'),
     44                qn('user_id'),)
     45            cursor.execute(sql, [user_obj.id])
     46            user_obj._group_perm_cache = set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()])
     47        return user_obj._group_perm_cache
     48   
     49    def get_all_permissions(self, user_obj):
     50        if not hasattr(user_obj, '_perm_cache'):
     51            user_obj._perm_cache = set([u"%s.%s" % (p.content_type.app_label, p.codename) for p in user_obj.user_permissions.select_related()])
     52            user_obj._perm_cache.update(self.get_group_permissions(user_obj))
     53        return user_obj._perm_cache
     54
     55    def has_perm(self, user_obj, perm):
     56        return perm in self.get_all_permissions(user_obj)
     57
     58    def has_module_perms(self, user_obj, app_label):
     59        return bool(len([p for p in self.get_all_permissions(user_obj) if p[:p.index('.')] == app_label]))
     60
     61
     62
    1763    def get_user(self, user_id):
    1864        try:
    1965            return User.objects.get(pk=user_id)
  • django/contrib/auth/models.py

     
     1from django.contrib.auth import get_backends
    12from django.core import validators
    23from django.core.exceptions import ImproperlyConfigured
    34from django.db import connection, models
     
    177178        return self.password != UNUSABLE_PASSWORD
    178179
    179180    def get_group_permissions(self):
    180         "Returns a list of permission strings that this user has through his/her groups."
    181         if not hasattr(self, '_group_perm_cache'):
    182             cursor = connection.cursor()
    183             # The SQL below works out to the following, after DB quoting:
    184             # cursor.execute("""
    185             #     SELECT ct."app_label", p."codename"
    186             #     FROM "auth_permission" p, "auth_group_permissions" gp, "auth_user_groups" ug, "django_content_type" ct
    187             #     WHERE p."id" = gp."permission_id"
    188             #         AND gp."group_id" = ug."group_id"
    189             #         AND ct."id" = p."content_type_id"
    190             #         AND ug."user_id" = %s, [self.id])
    191             qn = connection.ops.quote_name
    192             sql = """
    193                 SELECT ct.%s, p.%s
    194                 FROM %s p, %s gp, %s ug, %s ct
    195                 WHERE p.%s = gp.%s
    196                     AND gp.%s = ug.%s
    197                     AND ct.%s = p.%s
    198                     AND ug.%s = %%s""" % (
    199                 qn('app_label'), qn('codename'),
    200                 qn('auth_permission'), qn('auth_group_permissions'),
    201                 qn('auth_user_groups'), qn('django_content_type'),
    202                 qn('id'), qn('permission_id'),
    203                 qn('group_id'), qn('group_id'),
    204                 qn('id'), qn('content_type_id'),
    205                 qn('user_id'),)
    206             cursor.execute(sql, [self.id])
    207             self._group_perm_cache = set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()])
    208         return self._group_perm_cache
     181        """
     182        Returns a list of permission strings that this user has through his/her groups.
     183        This method queries the available backends.
     184        """
     185        group_permissions = set([])
     186        for backend in get_backends():
     187            # Backend does not support this method, so skip it
     188            if not hasattr(backend, "get_group_permissions"): continue
     189            group_permissions.update(backend.get_group_permissions(self))
     190        return group_permissions
    209191
    210192    def get_all_permissions(self):
    211         if not hasattr(self, '_perm_cache'):
    212             self._perm_cache = set([u"%s.%s" % (p.content_type.app_label, p.codename) for p in self.user_permissions.select_related()])
    213             self._perm_cache.update(self.get_group_permissions())
    214         return self._perm_cache
     193        permissions = set([])
     194        for backend in get_backends():
     195            # Backend does not support this method, so skip it
     196            if not hasattr(backend, "get_all_permissions"): continue
     197            permissions.update(backend.get_all_permissions(self))
     198        return permissions
    215199
    216200    def has_perm(self, perm):
    217         "Returns True if the user has the specified permission."
     201        """
     202        Returns True if the user has the specified permission.
     203        This method queries the available backends and stops on
     204        the first "True".
     205        """
    218206        if not self.is_active:
    219207            return False
    220208        if self.is_superuser:
    221209            return True
    222         return perm in self.get_all_permissions()
     210        for backend in get_backends():
     211            # Backend does not support this method, so skip it
     212            if not hasattr(backend, "has_perm"): continue
     213            if backend.has_perm(self, perm):
     214                return True
     215        return False
    223216
    224217    def has_perms(self, perm_list):
    225218        "Returns True if the user has each of the specified permissions."
     
    229222        return True
    230223
    231224    def has_module_perms(self, app_label):
    232         "Returns True if the user has any permissions in the given app label."
     225        """
     226        Returns True if the user has any permissions in the given app label.
     227        This method queries the available backends and stops on
     228        the first "True".
     229        """
    233230        if not self.is_active:
    234231            return False
    235232        if self.is_superuser:
    236233            return True
    237         return bool(len([p for p in self.get_all_permissions() if p[:p.index('.')] == app_label]))
     234        for backend in get_backends():
     235            # Backend does not support this method, so skip it
     236            if not hasattr(backend, "has_module_perms"): continue
     237            if backend.has_module_perms(self, app_label):
     238                return True
     239        return False
    238240
    239241    def get_and_delete_messages(self):
    240242        messages = []
  • tests/regressiontests/auth_permission_backend/tests.py

     
     1# -*- coding: utf-8 -*-
     2
     3from django.contrib.auth.models import User, Group, Permission
     4from django.contrib.contenttypes.models import ContentType
     5
     6auth_tests = r"""
     7# No Permissions assigned yet, should return False except for superuser
     8
     9>>> user = User.objects.create_user('test', 'test@example.com', 'test')
     10>>> user.has_perm("auth.test")
     11False
     12>>> user.is_staff=True
     13>>> user.save()
     14>>> user.has_perm("auth.test")
     15False
     16>>> user.is_superuser=True
     17>>> user.save()
     18>>> user.has_perm("auth.test")
     19True
     20>>> user.is_staff = False
     21>>> user.is_superuser = False
     22>>> user.save()
     23>>> user.has_perm("auth.test")
     24False
     25>>> content_type=ContentType.objects.get_for_model(Group)
     26>>> perm = Permission.objects.create(name="test", content_type=content_type, codename="test")
     27>>> user.user_permissions.add(perm)
     28>>> user.save()
     29
     30# reloading user to purge the _perm_cache
     31
     32>>> user = User.objects.get(username="test")
     33>>> user.get_all_permissions()
     34set([u'auth.test'])
     35>>> user.get_group_permissions()
     36set([])
     37>>> user.has_module_perms("Group")
     38False
     39>>> user.has_module_perms("auth")
     40True
     41>>> perm = Permission.objects.create(name="test2", content_type=content_type, codename="test2")
     42>>> user.user_permissions.add(perm)
     43>>> user.save()
     44>>> perm = Permission.objects.create(name="test3", content_type=content_type, codename="test3")
     45>>> user.user_permissions.add(perm)
     46>>> user.save()
     47>>> user = User.objects.get(username="test")
     48>>> user.get_all_permissions()
     49set([u'auth.test2', u'auth.test', u'auth.test3'])
     50>>> user.has_perm('test')
     51False
     52>>> user.has_perm('auth.test')
     53True
     54>>> user.has_perms(['auth.test2', 'auth.test3'])
     55True
     56>>> perm = Permission.objects.create(name="test_group", content_type=content_type, codename="test_group")
     57>>> group = Group.objects.create(name='test_group')
     58>>> group.permissions.add(perm)
     59>>> group.save()
     60>>> user.groups.add(group)
     61>>> user = User.objects.get(username="test")
     62>>> user.get_all_permissions()
     63set([u'auth.test2', u'auth.test', u'auth.test3', u'auth.test_group'])
     64>>> user.get_group_permissions()
     65set([u'auth.test_group'])
     66>>> user.has_perms(['auth.test3', 'auth.test_group'])
     67True
     68"""
     69
     70__test__ = {
     71    'auth_permission_test': auth_tests,
     72}
     73
     74if __name__ == "__main__":
     75    import doctest
     76    doctest.testmod()
  • docs/authentication.txt

     
    10411041                return User.objects.get(pk=user_id)
    10421042            except User.DoesNotExist:
    10431043                return None
     1044
     1045Optionally the Backend allows you to specify any of the permission methods of
     1046the ``User`` object (except from ``has_perms`` which calls ``has_perm`` for each
     1047perm in the list, and ``has_perm`` can be specified in the backend).
     1048This will allow your backend to handle the permissions, if one backend return
     1049``True`` in a permission check, the user will have the permission.
     1050
     1051Here is an sample implementation for ``has_perm`` extending the above exmaple::
     1052       
     1053        # The permission functions all take the user_obj as first (besides the self of
     1054        # the backend, of course) argument and the rest
     1055        # is as you would call it with ``User.*``
     1056        def has_perm(self, user_obj, perm):
     1057            # we give the user admin the right to do everything.
     1058            if user_obj.username == "admin":
     1059                return True
     1060            else:
     1061                return False
     1062
     1063A full implementation can be found in ``django/contrib/auth/backends.py`` _, which is the
     1064default backend and queries the ``auth_permission``-table most of the time.
     1065
     1066.. _django/contrib/auth/backends.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/backends.py
Back to Top